diff --git a/modules/externalinflow/src/ExternalInflow_Registry.txt b/modules/externalinflow/src/ExternalInflow_Registry.txt index e5659ed467..8f32087734 100644 --- a/modules/externalinflow/src/ExternalInflow_Registry.txt +++ b/modules/externalinflow/src/ExternalInflow_Registry.txt @@ -54,9 +54,6 @@ typedef ExternalInflow/ExtInfw ParameterType IntKi NodeClusterType - typedef ^ InputType ReKi pxVel {:} - - "x position of velocity interface (Aerodyn) nodes" "m" typedef ^ InputType ReKi pyVel {:} - - "y position of velocity interface (Aerodyn) nodes" "m" typedef ^ InputType ReKi pzVel {:} - - "z position of velocity interface (Aerodyn) nodes" "m" -typedef ^ InputType ReKi pxdotVel {:} - - "x of velocity interface (Aerodyn) nodes" "m" -typedef ^ InputType ReKi pydotVel {:} - - "y position of velocity interface (Aerodyn) nodes" "m" -typedef ^ InputType ReKi pzdotVel {:} - - "z position of velocity interface (Aerodyn) nodes" "m" typedef ^ InputType ReKi pxForce {:} - - "x position of actuator force nodes" "m" typedef ^ InputType ReKi pyForce {:} - - "y position of actuator force nodes" "m" typedef ^ InputType ReKi pzForce {:} - - "z position of actuator force nodes" "m" diff --git a/modules/openfast-library/src/FAST_Library.f90 b/modules/openfast-library/src/FAST_Library.f90 index 247137d84d..5de7b339f8 100644 --- a/modules/openfast-library/src/FAST_Library.f90 +++ b/modules/openfast-library/src/FAST_Library.f90 @@ -1,53 +1,53 @@ -! FAST_Library.f90 +! FAST_Library.f90 ! ! FUNCTIONS/SUBROUTINES exported from FAST_Library.dll: -! FAST_Start - subroutine -! FAST_Update - subroutine -! FAST_End - subroutine -! +! FAST_Start - subroutine +! FAST_Update - subroutine +! FAST_End - subroutine +! ! DO NOT REMOVE or MODIFY LINES starting with "!DEC$" or "!GCC$" ! !DEC$ specifies attributes for IVF and !GCC$ specifies attributes for gfortran ! -!================================================================================================================================== +!================================================================================================================================== MODULE FAST_Data USE, INTRINSIC :: ISO_C_Binding USE FAST_Subs ! all of the ModuleName and ModuleName_types modules are inherited from FAST_Subs - + IMPLICIT NONE SAVE - + ! Local parameters: REAL(DbKi), PARAMETER :: t_initial = 0.0_DbKi ! Initial time - INTEGER(IntKi) :: NumTurbines + INTEGER(IntKi) :: NumTurbines INTEGER, PARAMETER :: IntfStrLen = 1025 ! length of strings through the C interface INTEGER(IntKi), PARAMETER :: MAXOUTPUTS = 4000 ! Maximum number of outputs INTEGER(IntKi), PARAMETER :: MAXInitINPUTS = 53 ! Maximum number of initialization values from Simulink INTEGER(IntKi), PARAMETER :: NumFixedInputs = 51 - - + + ! Global (static) data: TYPE(FAST_TurbineType), ALLOCATABLE :: Turbine(:) ! Data for each turbine INTEGER(IntKi) :: n_t_global ! simulation time step, loop counter for global (FAST) simulation INTEGER(IntKi) :: ErrStat ! Error status CHARACTER(IntfStrLen-1) :: ErrMsg ! Error message (this needs to be static so that it will print in Matlab's mex library) - + contains -!================================================================================================================================== +!================================================================================================================================== subroutine FAST_AllocateTurbines(nTurbines, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_AllocateTurbines') - IMPLICIT NONE + IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_AllocateTurbines !GCC$ ATTRIBUTES DLLEXPORT :: FAST_AllocateTurbines #endif INTEGER(C_INT), INTENT(IN ) :: nTurbines INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + if (nTurbines > 0) then NumTurbines = nTurbines end if - + if (nTurbines > 10) then call wrscr1('Number of turbines is > 10! Are you sure you have enough memory?') call wrscr1('Proceeding anyway.') @@ -63,7 +63,7 @@ subroutine FAST_AllocateTurbines(nTurbines, ErrStat_c, ErrMsg_c) BIND (C, NAME=' ErrMsg = " "//C_NULL_CHAR end if ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - + end subroutine FAST_AllocateTurbines !================================================================================================================================== subroutine FAST_DeallocateTurbines(ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_DeallocateTurbines') @@ -84,35 +84,35 @@ subroutine FAST_DeallocateTurbines(ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Deal end subroutine !================================================================================================================================== subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt_out_c, tmax_c, ErrStat_c, ErrMsg_c, ChannelNames_c, TMax, InitInpAry) BIND (C, NAME='FAST_Sizes') - IMPLICIT NONE + IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Sizes !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Sizes #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) - INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c - INTEGER(C_INT), INTENT( OUT) :: NumOuts_c - REAL(C_DOUBLE), INTENT( OUT) :: dt_c - REAL(C_DOUBLE), INTENT( OUT) :: dt_out_c + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c + INTEGER(C_INT), INTENT( OUT) :: NumOuts_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_out_c REAL(C_DOUBLE), INTENT( OUT) :: tmax_c - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ChannelNames_c(ChanLen*MAXOUTPUTS+1) - REAL(C_DOUBLE),OPTIONAL,INTENT(IN ) :: TMax - REAL(C_DOUBLE),OPTIONAL,INTENT(IN ) :: InitInpAry(MAXInitINPUTS) - + REAL(C_DOUBLE),OPTIONAL,INTENT(IN ) :: TMax + REAL(C_DOUBLE),OPTIONAL,INTENT(IN ) :: InitInpAry(MAXInitINPUTS) + ! local - CHARACTER(IntfStrLen) :: InputFileName + CHARACTER(IntfStrLen) :: InputFileName INTEGER :: i, j, k TYPE(FAST_ExternInitType) :: ExternInitData - - ! transfer the character array from C to a Fortran string: + + ! transfer the character array from C to a Fortran string: InputFileName = TRANSFER( InputFileName_c, InputFileName ) I = INDEX(InputFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... IF ( I > 0 ) InputFileName = InputFileName(1:I) ! remove it - - ! initialize variables: + + ! initialize variables: n_t_global = 0 IF (PRESENT(TMax) .AND. .NOT. PRESENT(InitInpAry)) THEN @@ -130,18 +130,18 @@ subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt ExternInitData%TurbinePos = 0.0_ReKi ! turbine position is at the origin ExternInitData%NumCtrl2SC = 0 ExternInitData%NumSC2Ctrl = 0 - ExternInitData%SensorType = NINT(InitInpAry(1)) + ExternInitData%SensorType = NINT(InitInpAry(1)) ! -- MATLAB Integration -- ! Make sure fast farm integration is false ExternInitData%FarmIntegration = .false. ExternInitData%WaveFieldMod = 0 - + IF ( NINT(InitInpAry(2)) == 1 ) THEN ExternInitData%LidRadialVel = .true. ELSE ExternInitData%LidRadialVel = .false. END IF - + CALL FAST_InitializeAll_T( t_initial, iTurb, Turbine(iTurb), ErrStat, ErrMsg, InputFileName, ExternInitData) ELSE @@ -149,8 +149,8 @@ subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt CALL FAST_InitializeAll_T( t_initial, iTurb, Turbine(iTurb), ErrStat, ErrMsg, InputFileName) END IF - - AbortErrLev_c = AbortErrLev + + AbortErrLev_c = AbortErrLev NumOuts_c = min(MAXOUTPUTS, SUM( Turbine(iTurb)%y_FAST%numOuts )) dt_c = Turbine(iTurb)%p_FAST%dt dt_out_c = Turbine(iTurb)%p_FAST%DT_Out @@ -159,11 +159,11 @@ subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - -#ifdef CONSOLE_FILE + +#ifdef CONSOLE_FILE if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) -#endif - +#endif + ! return the names of the output channels IF ( ALLOCATED( Turbine(iTurb)%y_FAST%ChannelNames ) ) then k = 1; @@ -177,71 +177,71 @@ subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt ELSE ChannelNames_c = C_NULL_CHAR END IF - + end subroutine FAST_Sizes !================================================================================================================================== subroutine FAST_Start(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Start') - IMPLICIT NONE + IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Start !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Start #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - INTEGER(C_INT), INTENT(IN ) :: NumInputs_c - INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: NumInputs_c + INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) REAL(C_DOUBLE), INTENT( OUT) :: OutputAry(NumOutputs_c) - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + - ! local - CHARACTER(IntfStrLen) :: InputFileName + CHARACTER(IntfStrLen) :: InputFileName INTEGER :: i REAL(ReKi) :: Outputs(NumOutputs_c-1) - + INTEGER(IntKi) :: ErrStat2 ! Error status CHARACTER(IntfStrLen-1) :: ErrMsg2 ! Error message (this needs to be static so that it will print in Matlab's mex library) - - ! initialize variables: + + ! initialize variables: n_t_global = 0 !............................................................................................................................... ! Initialization of solver: (calculate outputs based on states at t=t_initial as well as guesses of inputs and constraint states) - !............................................................................................................................... - CALL FAST_Solution0_T(Turbine(iTurb), ErrStat, ErrMsg ) - + !............................................................................................................................... + CALL FAST_Solution0_T(Turbine(iTurb), ErrStat, ErrMsg ) + if (ErrStat <= AbortErrLev) then ! return outputs here, too IF(NumOutputs_c /= SIZE(Turbine(iTurb)%y_FAST%ChannelNames) ) THEN ErrStat = ErrID_Fatal ErrMsg = trim(ErrMsg)//NewLine//"FAST_Start:size of NumOutputs is invalid." ELSE - - CALL FillOutputAry_T(Turbine(iTurb), Outputs) - OutputAry(1) = Turbine(iTurb)%m_FAST%t_global - OutputAry(2:NumOutputs_c) = Outputs + + CALL FillOutputAry_T(Turbine(iTurb), Outputs) + OutputAry(1) = Turbine(iTurb)%m_FAST%t_global + OutputAry(2:NumOutputs_c) = Outputs CALL FAST_Linearize_T(t_initial, 0, Turbine(iTurb), ErrStat2, ErrMsg2) if (ErrStat2 /= ErrID_None) then ErrStat = max(ErrStat,ErrStat2) ErrMsg = TRIM(ErrMsg)//NewLine//TRIM(ErrMsg2) end if - - + + END IF end if - - + + ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - -#ifdef CONSOLE_FILE + +#ifdef CONSOLE_FILE if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) -#endif - +#endif + end subroutine FAST_Start !================================================================================================================================== subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, EndSimulationEarly, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Update') @@ -250,25 +250,25 @@ subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, En !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Update !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Update #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - INTEGER(C_INT), INTENT(IN ) :: NumInputs_c - INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: NumInputs_c + INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) REAL(C_DOUBLE), INTENT( OUT) :: OutputAry(NumOutputs_c) LOGICAL(C_BOOL), INTENT( OUT) :: EndSimulationEarly - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + ! local variables REAL(ReKi) :: Outputs(NumOutputs_c-1) INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 ! Error status CHARACTER(IntfStrLen-1) :: ErrMsg2 ! Error message (this needs to be static so that it will print in Matlab's mex library) - + EndSimulationEarly = .FALSE. - IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish - + IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish + ! we can't continue because we might over-step some arrays that are allocated to the size of the simulation IF (n_t_global == Turbine(iTurb)%p_FAST%n_TMax_m1 + 1) THEN ! we call update an extra time in Simulink, which we can ignore until the time shift with outputs is solved @@ -276,12 +276,12 @@ subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, En ErrStat_c = ErrID_None ErrMsg = C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - ELSE + ELSE ErrStat_c = ErrID_Info ErrMsg = "Simulation completed."//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) END IF - + ELSEIF(NumOutputs_c /= SIZE(Turbine(iTurb)%y_FAST%ChannelNames) ) THEN ErrStat_c = ErrID_Fatal ErrMsg = "FAST_Update:size of OutputAry is invalid or FAST has too many outputs."//C_NULL_CHAR @@ -296,7 +296,7 @@ subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, En CALL FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, Turbine(iTurb)%m_FAST) - CALL FAST_Solution_T( t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) + CALL FAST_Solution_T( t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) n_t_global = n_t_global + 1 CALL FAST_Linearize_T( t_initial, n_t_global, Turbine(iTurb), ErrStat2, ErrMsg2) @@ -304,26 +304,26 @@ subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, En ErrStat = max(ErrStat,ErrStat2) ErrMsg = TRIM(ErrMsg)//NewLine//TRIM(ErrMsg2) end if - + IF ( Turbine(iTurb)%m_FAST%Lin%FoundSteady) THEN EndSimulationEarly = .TRUE. END IF - + ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) END IF ! set the outputs for external code here - CALL FillOutputAry_T(Turbine(iTurb), Outputs) - OutputAry(1) = Turbine(iTurb)%m_FAST%t_global - OutputAry(2:NumOutputs_c) = Outputs + CALL FillOutputAry_T(Turbine(iTurb), Outputs) + OutputAry(1) = Turbine(iTurb)%m_FAST%t_global + OutputAry(2:NumOutputs_c) = Outputs -#ifdef CONSOLE_FILE +#ifdef CONSOLE_FILE if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) -#endif - -end subroutine FAST_Update +#endif + +end subroutine FAST_Update !================================================================================================================================== ! Get the hub's absolute position, rotation velocity, and orientation DCM for the current time step subroutine FAST_HubPosition(iTurb, AbsPosition_c, RotationalVel_c, Orientation_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_HubPosition') @@ -369,14 +369,14 @@ subroutine FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, m_FAST) USE, INTRINSIC :: ISO_C_Binding USE FAST_Types ! USE FAST_Data, only: NumFixedInputs - + IMPLICIT NONE - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - INTEGER(C_INT), INTENT(IN ) :: NumInputs_c + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: NumInputs_c REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) ! Inputs from Simulink TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST ! Miscellaneous variables - + ! set the inputs from external code here... ! transfer inputs from Simulink to FAST IF ( NumInputs_c < NumFixedInputs ) RETURN ! This is an error @@ -391,12 +391,12 @@ subroutine FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, m_FAST) m_FAST%ExternInput%BlAirfoilCom = InputAry(9:11) m_FAST%ExternInput%CableDeltaL = InputAry(12:31) m_FAST%ExternInput%CableDeltaLdot = InputAry(32:51) - + IF ( NumInputs_c > NumFixedInputs ) THEN ! NumFixedInputs is the fixed number of inputs IF ( NumInputs_c == NumFixedInputs + 3 ) & m_FAST%ExternInput%LidarFocus = InputAry(52:54) - END IF - + END IF + end subroutine FAST_SetExternalInputs !================================================================================================================================== subroutine FAST_End(iTurb, StopTheProgram) BIND (C, NAME='FAST_End') @@ -405,11 +405,11 @@ subroutine FAST_End(iTurb, StopTheProgram) BIND (C, NAME='FAST_End') !DEC$ ATTRIBUTES DLLEXPORT :: FAST_End !GCC$ ATTRIBUTES DLLEXPORT :: FAST_End #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number LOGICAL(C_BOOL), INTENT(IN) :: StopTheProgram ! flag indicating if the program should end (false if there are more turbines to end) CALL ExitThisProgram_T( Turbine(iTurb), ErrID_None, LOGICAL(StopTheProgram)) - + end subroutine FAST_End !================================================================================================================================== subroutine FAST_CreateCheckpoint(iTurb, CheckpointRootName_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CreateCheckpoint') @@ -418,41 +418,41 @@ subroutine FAST_CreateCheckpoint(iTurb, CheckpointRootName_c, ErrStat_c, ErrMsg_ !DEC$ ATTRIBUTES DLLEXPORT :: FAST_CreateCheckpoint !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CreateCheckpoint #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + ! local - CHARACTER(IntfStrLen) :: CheckpointRootName + CHARACTER(IntfStrLen) :: CheckpointRootName INTEGER(IntKi) :: I INTEGER(IntKi) :: Unit - - - ! transfer the character array from C to a Fortran string: + + + ! transfer the character array from C to a Fortran string: CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) I = INDEX(CheckpointRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... IF ( I > 0 ) CheckpointRootName = CheckpointRootName(1:I) ! remove it - + if ( LEN_TRIM(CheckpointRootName) == 0 ) then CheckpointRootName = TRIM(Turbine(iTurb)%p_FAST%OutFileRoot)//'.'//trim( Num2LStr(n_t_global) ) end if - - + + Unit = -1 CALL FAST_CreateCheckpoint_T(t_initial, n_t_global, 1, Turbine(iTurb), CheckpointRootName, ErrStat, ErrMsg, Unit ) - ! transfer Fortran variables to C: + ! transfer Fortran variables to C: ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) -#ifdef CONSOLE_FILE +#ifdef CONSOLE_FILE if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) -#endif - -end subroutine FAST_CreateCheckpoint +#endif + +end subroutine FAST_CreateCheckpoint !================================================================================================================================== subroutine FAST_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, NumOuts_c, dt_c, n_t_global_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Restart') IMPLICIT NONE @@ -460,52 +460,52 @@ subroutine FAST_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, NumOuts_c, d !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Restart !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Restart #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) - INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c - INTEGER(C_INT), INTENT( OUT) :: NumOuts_c - REAL(C_DOUBLE), INTENT( OUT) :: dt_c - INTEGER(C_INT), INTENT( OUT) :: n_t_global_c - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c + INTEGER(C_INT), INTENT( OUT) :: NumOuts_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_c + INTEGER(C_INT), INTENT( OUT) :: n_t_global_c + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + ! local - CHARACTER(IntfStrLen) :: CheckpointRootName + CHARACTER(IntfStrLen) :: CheckpointRootName INTEGER(IntKi) :: I INTEGER(IntKi) :: Unit REAL(DbKi) :: t_initial_out INTEGER(IntKi) :: NumTurbines_out - CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' - - - ! transfer the character array from C to a Fortran string: + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' + + + ! transfer the character array from C to a Fortran string: CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) I = INDEX(CheckpointRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... IF ( I > 0 ) CheckpointRootName = CheckpointRootName(1:I) ! remove it - + Unit = -1 CALL FAST_RestoreFromCheckpoint_T(t_initial_out, n_t_global, NumTurbines_out, Turbine(iTurb), CheckpointRootName, ErrStat, ErrMsg, Unit ) - + ! check that these are valid: IF (t_initial_out /= t_initial) CALL SetErrStat(ErrID_Fatal, "invalid value of t_initial.", ErrStat, ErrMsg, RoutineName ) IF (NumTurbines_out /= 1) CALL SetErrStat(ErrID_Fatal, "invalid value of NumTurbines.", ErrStat, ErrMsg, RoutineName ) - - - ! transfer Fortran variables to C: + + + ! transfer Fortran variables to C: n_t_global_c = n_t_global - AbortErrLev_c = AbortErrLev + AbortErrLev_c = AbortErrLev NumOuts_c = min(MAXOUTPUTS, SUM( Turbine(iTurb)%y_FAST%numOuts )) ! includes time - dt_c = Turbine(iTurb)%p_FAST%dt - + dt_c = Turbine(iTurb)%p_FAST%dt + ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) -#ifdef CONSOLE_FILE +#ifdef CONSOLE_FILE if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) -#endif - -end subroutine FAST_Restart +#endif + +end subroutine FAST_Restart !================================================================================================================================== subroutine FAST_ExtLoads_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c, TurbPosn, AbortErrLev_c, dtDriver_c, dt_c, NumBl_c, & @@ -613,12 +613,12 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c !DEC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Init !GCC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Init #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - REAL(C_DOUBLE), INTENT(IN ) :: TMax - CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + REAL(C_DOUBLE), INTENT(IN ) :: TMax + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) INTEGER(C_INT), INTENT(IN ) :: TurbID ! Need not be same as iTurb CHARACTER(KIND=C_CHAR), INTENT( OUT) :: OutFileRoot_c(IntfStrLen) ! Root of output and restart file name - INTEGER(C_INT), INTENT(IN ) :: NumSC2CtrlGlob ! Supercontroller global outputs = controller global inputs + INTEGER(C_INT), INTENT(IN ) :: NumSC2CtrlGlob ! Supercontroller global outputs = controller global inputs INTEGER(C_INT), INTENT(IN ) :: NumSC2Ctrl ! Supercontroller outputs = controller inputs INTEGER(C_INT), INTENT(IN ) :: NumCtrl2SC ! controller outputs = Supercontroller inputs REAL(C_FLOAT), INTENT(IN ) :: InitScOutputsGlob (*) ! Initial Supercontroller global outputs = controller inputs @@ -626,46 +626,48 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c INTEGER(C_INT), INTENT(IN ) :: NumActForcePtsBlade ! number of actuator line force points in blade INTEGER(C_INT), INTENT(IN ) :: NumActForcePtsTower ! number of actuator line force points in tower INTEGER(C_INT), INTENT(IN ):: NodeClusterType_c - REAL(C_FLOAT), INTENT(IN ) :: TurbPosn(3) + REAL(C_FLOAT), INTENT(IN ) :: TurbPosn(3) INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c REAL(C_DOUBLE), INTENT(IN ) :: dtDriver_c REAL(C_DOUBLE), INTENT( OUT) :: dt_c INTEGER(C_INT), INTENT( OUT) :: InflowType ! inflow type - 1 = From Inflow module, 2 = External - INTEGER(C_INT), INTENT( OUT) :: NumBl_c - INTEGER(C_INT), INTENT( OUT) :: NumBlElem_c - INTEGER(C_INT), INTENT( OUT) :: NumTwrElem_c + INTEGER(C_INT), INTENT( OUT) :: NumBl_c + INTEGER(C_INT), INTENT( OUT) :: NumBlElem_c + INTEGER(C_INT), INTENT( OUT) :: NumTwrElem_c TYPE(ExtInfw_InputType_C), INTENT(INOUT) :: ExtInfw_Input_from_FAST !INTENT(INOUT) instead of INTENT(OUT) to avoid gcc compiler warnings about variable tracking sizes TYPE(ExtInfw_OutputType_C),INTENT(INOUT) :: ExtInfw_Output_to_FAST !INTENT(INOUT) instead of INTENT(OUT) to avoid gcc compiler warnings about variable tracking sizes TYPE(SC_DX_InputType_C), INTENT(INOUT) :: SC_DX_Input_from_FAST TYPE(SC_DX_OutputType_C), INTENT(INOUT) :: SC_DX_Output_to_FAST - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + ! local - CHARACTER(IntfStrLen) :: InputFileName - INTEGER(C_INT) :: i + CHARACTER(IntfStrLen) :: InputFileName + INTEGER(C_INT) :: i TYPE(FAST_ExternInitType) :: ExternInitData - - ! transfer the character array from C to a Fortran string: + + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_ExtInfw_Init' + + ! transfer the character array from C to a Fortran string: InputFileName = TRANSFER( InputFileName_c, InputFileName ) I = INDEX(InputFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... IF ( I > 0 ) InputFileName = InputFileName(1:I) ! remove it - - ! initialize variables: - n_t_global = 0 + + ! initialize variables: + n_t_global = 0 ErrStat = ErrID_None ErrMsg = "" - + NumBl_c = 0 ! initialize here in case of error NumBlElem_c = 0 ! initialize here in case of error - + ExternInitData%TMax = TMax ExternInitData%TurbineID = TurbID ExternInitData%TurbinePos = TurbPosn ExternInitData%SensorType = SensorType_None ExternInitData%NumCtrl2SC = NumCtrl2SC ExternInitData%NumSC2CtrlGlob = NumSC2CtrlGlob - + if ( NumSC2CtrlGlob > 0 ) then CALL AllocAry( ExternInitData%fromSCGlob, NumSC2CtrlGlob, 'ExternInitData%fromSCGlob', ErrStat, ErrMsg) IF (FAILED()) RETURN @@ -674,7 +676,7 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c ExternInitData%fromSCGlob(i) = InitScOutputsGlob(i) end do end if - + ExternInitData%NumSC2Ctrl = NumSC2Ctrl if ( NumSC2Ctrl > 0 ) then CALL AllocAry( ExternInitData%fromSC, NumSC2Ctrl, 'ExternInitData%fromSC', ErrStat, ErrMsg) @@ -684,7 +686,7 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c ExternInitData%fromSC(i) = InitScOutputsTurbine(i) end do end if - + ExternInitData%NumActForcePtsBlade = NumActForcePtsBlade ExternInitData%NumActForcePtsTower = NumActForcePtsTower ExternInitData%DTdriver = dtDriver_c @@ -693,22 +695,36 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c CALL FAST_InitializeAll_T( t_initial, iTurb, Turbine(iTurb), ErrStat, ErrMsg, InputFileName, ExternInitData ) ! set values for return to ExternalInflow - AbortErrLev_c = AbortErrLev + AbortErrLev_c = AbortErrLev dt_c = Turbine(iTurb)%p_FAST%dt ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - + + InflowType = Turbine(iTurb)%p_FAST%CompInflow + IF ( ErrStat >= AbortErrLev ) THEN CALL WrScr( "Error in FAST_ExtInfw_Init:FAST_InitializeAll_T" // TRIM(ErrMsg) ) RETURN END IF - + + if ( (InflowType == 3) .and. (NumActForcePtsBlade .eq. 0) .and. (NumActForcePtsTower .eq. 0) ) then + CALL SetErrStat(ErrID_Warn, "Number of actuator points is zero when inflow type is 2. Mapping of loads may not work. ", ErrStat, ErrMsg, RoutineName ) + end if + + if ( (InflowType .ne. 3) .and. ((NumActForcePtsBlade .ne. 0) .or. (NumActForcePtsTower .ne. 0)) ) then + !!FAST reassigns CompInflow after reading it to a module number based on an internal list in the FAST_Registry. So 2 in input file becomes 3 inside the code. + CALL SetErrStat(ErrID_Fatal, "Number of requested actuator points is non-zero when inflow type is not 2. Please set number of actuator points to zero when induction is turned on.", ErrStat, ErrMsg, RoutineName ) + ErrStat_c = ErrStat + ErrMsg_c = TRANSFER( trim(ErrMsg)//C_NULL_CHAR, ErrMsg_c ) + return + end if + call SetExternalInflow_pointers(iTurb, ExtInfw_Input_from_FAST, ExtInfw_Output_to_FAST, SC_DX_Input_from_FAST, SC_DX_Output_to_FAST) - - ! 7-Sep-2015: Sang wants these integers for the ExternalInflow mapping, which is tied to the AeroDyn nodes. FAST doesn't restrict the number of nodes on each + + ! 7-Sep-2015: Sang wants these integers for the ExternalInflow mapping, which is tied to the AeroDyn nodes. FAST doesn't restrict the number of nodes on each ! blade mesh to be the same, so if this DOES ever change, we'll need to make ExternalInflow less tied to the AeroDyn mapping. - IF (Turbine(iTurb)%p_FAST%CompAero == MODULE_AD14) THEN + IF (Turbine(iTurb)%p_FAST%CompAero == MODULE_AD14) THEN NumBl_c = SIZE(Turbine(iTurb)%AD14%Input(1)%InputMarkers) NumBlElem_c = Turbine(iTurb)%AD14%Input(1)%InputMarkers(1)%Nnodes ELSEIF (Turbine(iTurb)%p_FAST%CompAero == MODULE_AD) THEN @@ -720,33 +736,41 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c IF (NumBl_c > 0) THEN NumBlElem_c = Turbine(iTurb)%AD%Input(1)%rotors(1)%BladeMotion(1)%Nnodes END IF + NumTwrElem_c = Turbine(iTurb)%AD%y%rotors(1)%TowerLoad%Nnodes + ELSE + NumBl_c = 0 + NumBlElem_c = 0 + NumTwrElem_c = 0 END IF + ErrStat_c = ErrStat + ErrMsg_c = TRANSFER( trim(ErrMsg)//C_NULL_CHAR, ErrMsg_c ) + OutFileRoot_c = TRANSFER( trim(Turbine(iTurb)%p_FAST%OutFileRoot)//C_NULL_CHAR, OutFileRoot_c ) - + contains LOGICAL FUNCTION FAILED() - + FAILED = ErrStat >= AbortErrLev - + IF (ErrStat > 0) THEN CALL WrScr( "Error in FAST_ExtInfw_Init:FAST_InitializeAll_T" // TRIM(ErrMsg) ) - + IF ( FAILED ) THEN - + AbortErrLev_c = AbortErrLev ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - + !IF (ALLOCATED(Turbine)) DEALLOCATE(Turbine) ! bjj: if there is an error, the driver should call FAST_DeallocateTurbines() instead of putting this deallocate statement here END IF END IF - - + + END FUNCTION FAILED -end subroutine +end subroutine !================================================================================================================================== subroutine FAST_CFD_Solution0(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Solution0') @@ -800,46 +824,46 @@ subroutine FAST_ExtInfw_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, dt_c !DEC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Restart !GCC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Restart #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) - INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c + INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) + INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c INTEGER(C_INT), INTENT( OUT) :: numblades_c INTEGER(C_INT), INTENT( OUT) :: numElementsPerBlade_c INTEGER(C_INT), INTENT( OUT) :: numElementsTower_c - REAL(C_DOUBLE), INTENT( OUT) :: dt_c - INTEGER(C_INT), INTENT( OUT) :: n_t_global_c + REAL(C_DOUBLE), INTENT( OUT) :: dt_c + INTEGER(C_INT), INTENT( OUT) :: n_t_global_c TYPE(ExtInfw_InputType_C), INTENT(INOUT) :: ExtInfw_Input_from_FAST !INTENT(INOUT) instead of INTENT(OUT) to avoid gcc compiler warnings about variable tracking sizes TYPE(ExtInfw_OutputType_C),INTENT(INOUT) :: ExtInfw_Output_to_FAST !INTENT(INOUT) instead of INTENT(OUT) to avoid gcc compiler warnings about variable tracking sizes TYPE(SC_DX_InputType_C), INTENT(INOUT) :: SC_DX_Input_from_FAST TYPE(SC_DX_OutputType_C), INTENT(INOUT) :: SC_DX_Output_to_FAST - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + ! local variables - INTEGER(C_INT) :: NumOuts_c - CHARACTER(IntfStrLen) :: CheckpointRootName + INTEGER(C_INT) :: NumOuts_c + CHARACTER(IntfStrLen) :: CheckpointRootName INTEGER(IntKi) :: I INTEGER(IntKi) :: Unit REAL(DbKi) :: t_initial_out INTEGER(IntKi) :: NumTurbines_out - CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' - + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' + CALL NWTC_Init() - ! transfer the character array from C to a Fortran string: + ! transfer the character array from C to a Fortran string: CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) I = INDEX(CheckpointRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... IF ( I > 0 ) CheckpointRootName = CheckpointRootName(1:I) ! remove it - + Unit = -1 CALL FAST_RestoreFromCheckpoint_T(t_initial_out, n_t_global, NumTurbines_out, Turbine(iTurb), CheckpointRootName, ErrStat, ErrMsg, Unit ) - + ! check that these are valid: IF (t_initial_out /= t_initial) CALL SetErrStat(ErrID_Fatal, "invalid value of t_initial.", ErrStat, ErrMsg, RoutineName ) IF (NumTurbines_out /= 1) CALL SetErrStat(ErrID_Fatal, "invalid value of NumTurbines.", ErrStat, ErrMsg, RoutineName ) - - ! transfer Fortran variables to C: + + ! transfer Fortran variables to C: n_t_global_c = n_t_global - AbortErrLev_c = AbortErrLev + AbortErrLev_c = AbortErrLev NumOuts_c = min(MAXOUTPUTS, SUM( Turbine(iTurb)%y_FAST%numOuts )) ! includes time if (allocated(Turbine(iTurb)%ad%p%rotors)) then ! this might not be allocated if we had an error earlier numBlades_c = Turbine(iTurb)%ad%p%rotors(1)%numblades @@ -850,19 +874,19 @@ subroutine FAST_ExtInfw_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, dt_c end if numElementsTower_c = Turbine(iTurb)%ad%p%rotors(1)%numtwrnds - - dt_c = Turbine(iTurb)%p_FAST%dt - + + dt_c = Turbine(iTurb)%p_FAST%dt + ErrStat_c = ErrStat ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) -#ifdef CONSOLE_FILE +#ifdef CONSOLE_FILE if (ErrStat /= ErrID_None) call wrscr1(trim(ErrMsg)) -#endif +#endif if (ErrStat >= AbortErrLev) return - + call SetExternalInflow_pointers(iTurb, ExtInfw_Input_from_FAST, ExtInfw_Output_to_FAST, SC_DX_Input_from_FAST, SC_DX_Output_to_FAST) end subroutine FAST_ExtInfw_Restart