From db5632f03ec6d5ae80e4493c9f3ec7ffd67d0d4d Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 25 Sep 2023 14:36:52 -0600 Subject: [PATCH] ADI: fix UpdateStates getting incorrect previous time inputs Previous timestep inputs for update states were getting set identical to the new inputs. This resulted in incorrect loads and wake propagation. --- .../python-lib/aerodyn_inflow_library.py | 10 +++---- .../aerodyn/src/AeroDyn_Inflow_C_Binding.f90 | 27 ++++++++++++++----- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/modules/aerodyn/python-lib/aerodyn_inflow_library.py b/modules/aerodyn/python-lib/aerodyn_inflow_library.py index edf7abdec8..a1084baf39 100644 --- a/modules/aerodyn/python-lib/aerodyn_inflow_library.py +++ b/modules/aerodyn/python-lib/aerodyn_inflow_library.py @@ -135,7 +135,7 @@ def __init__(self, library_path): # Number of turbines self.numTurbines = 1 -#FIXME: make sure this still works and doesn't need to be expanded to multiple turbines +#FIXME: some assumptions about a single turbine here. # Initial position of hub and blades # used for setup of AD, not used after init. self.initHubPos = np.zeros(shape=(3),dtype=c_float) @@ -312,7 +312,6 @@ def adi_setuprotor(self,iturb,turbRefPos): self._initNumBlades = self.numBlades _turbRefPos = (c_float * len(turbRefPos))(*turbRefPos) -#FIXME: this is setup for one rotor only right now # check hub and root points for initialization self.check_init_hubroot() @@ -350,7 +349,6 @@ def adi_setuprotor(self,iturb,turbRefPos): self.check_error() -#FIXME: split this into ADI_C_SetupRotor def adi_init(self, AD_input_string_array, IfW_input_string_array): # some bookkeeping initialization self._numChannels_c = c_int(0) @@ -416,8 +414,8 @@ def adi_init(self, AD_input_string_array, IfW_input_string_array): ## adi_reinit ------------------------------------------------------------------------------------------------------------ + #FIXME: this routine is not setup #def adi_reinit(self): - # #FIXME: need to pass something in here I think. Not sure what. # # # call ADI_C_ReInit # self.ADI_C_ReInit( @@ -428,7 +426,6 @@ def adi_init(self, AD_input_string_array, IfW_input_string_array): # ) # # self.check_error() - # #FIXME: anything coming out that needs handling/passing? # adi_setrotormotion ------------------------------------------------------------------------------------------------------------ @@ -851,7 +848,8 @@ def output_channel_units(self): # correctly, this will be identical to the corresponding values in the # AeroDyn/InflowWind output channels. -#FIXME: this is incorrect +#FIXME: this may not output everything in the interface (updates have been made +# since writing this, but this routine was not updated accordingly class DriverDbg(): """ This is only for debugging purposes only. The input motions and resulting diff --git a/modules/aerodyn/src/AeroDyn_Inflow_C_Binding.f90 b/modules/aerodyn/src/AeroDyn_Inflow_C_Binding.f90 index 5d9af2681b..186d650fce 100644 --- a/modules/aerodyn/src/AeroDyn_Inflow_C_Binding.f90 +++ b/modules/aerodyn/src/AeroDyn_Inflow_C_Binding.f90 @@ -94,6 +94,7 @@ MODULE AeroDyn_Inflow_C_BINDING type(ADI_Data) :: ADI type(ADI_InitInputType) :: InitInp !< Initialization data type(ADI_InitOutputType) :: InitOutData !< Initial output data -- Names, units, and version info. + type(ADI_InputType) :: ADI_u !< ADI inputs -- set by AD_SetInputMotion. Copied as needed (necessary for correction steps) !------------------------------ ! Simulation data type(Dvr_SimData) :: Sim !< data about the simulation @@ -626,6 +627,13 @@ SUBROUTINE ADI_C_Init( ADinputFilePassed, ADinputFileString_C, ADinputFileString enddo InputTimePrev = ADI%InputTimes(1) - Sim%dT ! Initialize for UpdateStates + !------------------------------------------------------------- + ! copy of ADI inputs. AD_SetInputMotion will set this mesh. When CalcOutput is called, + ! this data is used. When UpdateStates is called, this data is copied over to the ADI%u + !------------------------------------------------------------- + call ADI_CopyInput (ADI%u(1), ADI_u, MESH_NEWCOPY, Errstat2, ErrMsg2) + if (Failed()) return + !------------------------------------------------------------- ! Initial setup of other pieces of x,xd,z,OtherState @@ -858,7 +866,7 @@ subroutine SetupMotionLoadsInterfaceMeshes() Force = .TRUE. ,& Moment = .TRUE. ) if(Failed()) return - BldPtLoadMesh(iWT)%RemapFlag = .TRUE. + BldPtLoadMesh(iWT)%RemapFlag = .FALSE. ! Temp mesh for load transfer CALL MeshCopy( SrcMesh = BldPtLoadMesh(iWT) ,& @@ -870,7 +878,7 @@ subroutine SetupMotionLoadsInterfaceMeshes() Force = .TRUE. ,& Moment = .TRUE. ) if(Failed()) return - BldPtLoadMesh_tmp(iWT)%RemapFlag = .TRUE. + BldPtLoadMesh_tmp(iWT)%RemapFlag = .FALSE. ! For checking the mesh @@ -889,7 +897,7 @@ subroutine SetupMotionLoadsInterfaceMeshes() ! Force = .TRUE. ,& ! Moment = .TRUE. ) ! if(Failed()) return -! NacLoadMesh(iWT)%RemapFlag = .TRUE. +! NacLoadMesh(iWT)%RemapFlag = .FALSE. ! ! ! For checking the mesh, uncomment this. ! ! note: CU is is output unit (platform dependent). @@ -1009,6 +1017,8 @@ SUBROUTINE ADI_C_CalcOutput(Time_C, & Time = REAL(Time_C,DbKi) ! Call the main subroutine ADI_CalcOutput to get the resulting forces and moments at time T + call ADI_CopyInput (ADI_u, ADI%u(1), MESH_UPDATECOPY, Errstat2, ErrMsg2) ! copy new inputs over + if (Failed()) return CALL ADI_CalcOutput( Time, ADI%u(1), ADI%p, ADI%x(STATE_CURR), ADI%xd(STATE_CURR), ADI%z(STATE_CURR), ADI%OtherState(STATE_CURR), ADI%y, ADI%m, ErrStat2, ErrMsg2 ) if (Failed()) return @@ -1133,6 +1143,11 @@ SUBROUTINE ADI_C_UpdateStates( Time_C, TimeNext_C, & CALL ADI_CopyOtherState (ADI%OtherState(STATE_CURR), ADI%OtherState(STATE_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2); if (Failed()) return + ! Copy newinputs for time u(INPUT_PRED) + call ADI_CopyInput (ADI_u, ADI%u(INPUT_PRED), MESH_UPDATECOPY, Errstat2, ErrMsg2) + if (Failed()) return + + ! Call the main subroutine ADI_UpdateStates to get the velocities CALL ADI_UpdateStates( ADI%InputTimes(INPUT_CURR), n_Global, ADI%u, ADI%InputTimes, ADI%p, ADI%x(STATE_PRED), ADI%xd(STATE_PRED), ADI%z(STATE_PRED), ADI%OtherState(STATE_PRED), ADI%m, ErrStat2, ErrMsg2 ) if (Failed()) return @@ -1479,7 +1494,7 @@ subroutine SetupMotionMesh() enddo call MeshCommit ( BldPtMotionMesh(iWT), ErrStat2, ErrMsg2 ); if(Failed()) return - BldPtMotionMesh(iWT)%RemapFlag = .TRUE. + BldPtMotionMesh(iWT)%RemapFlag = .FALSE. ! For checking the mesh, uncomment this. ! note: CU is is output unit (platform dependent). @@ -1511,7 +1526,7 @@ subroutine SetupMotionMesh() ! call MeshConstructElement ( NacMotionMesh(iWT), ELEMENT_POINT, ErrStat2, ErrMsg2, p1=1 ); if(Failed()) return ! ! call MeshCommit ( NacMotionMesh(iWT), ErrStat2, ErrMsg2 ); if(Failed()) return -! NacMotionMesh(iWT)%RemapFlag = .TRUE. +! NacMotionMesh(iWT)%RemapFlag = .FALSE. ! ! ! For checking the mesh, uncomment this. ! ! note: CU is is output unit (platform dependent). @@ -1600,7 +1615,7 @@ subroutine ADI_C_SetRotorMotion( iWT_c, & ! Transfer motions to input meshes do iWT=1,Sim%NumTurbines call Set_MotionMesh(iWT, ErrStat2, ErrMsg2); if (Failed()) return - call AD_SetInputMotion( iWT, ADI%u(1), & + call AD_SetInputMotion( iWT, ADI_u, & HubPos_C, HubOri_C, HubVel_C, HubAcc_C, & NacPos_C, NacOri_C, NacVel_C, NacAcc_C, & BldRootPos_C, BldRootOri_C, BldRootVel_C, BldRootAcc_C, &