From 9fee431aa3571ae0340e67949be3218fd410b63a Mon Sep 17 00:00:00 2001 From: "Marc T. Henry de Frahan" Date: Thu, 16 Jan 2025 14:32:29 -0700 Subject: [PATCH] Enable optional coupling to openfast 4.0 (#1441) --- CMakeLists.txt | 14 +++ .../actuator/turbine/fast/FastIface.H | 4 + .../actuator/turbine/fast/FastIface.cpp | 28 ++++- .../actuator/turbine/fast/fast_types.H | 8 +- .../actuator/turbine/fast/fast_wrapper.H | 100 ++++++++++++++++-- docs/sphinx/user/build.rst | 8 ++ test/CMakeLists.txt | 2 +- 7 files changed, 147 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b62d7cb15..1594ddd4db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,6 +173,20 @@ if(AMR_WIND_ENABLE_OPENFAST) target_compile_definitions(${amr_wind_lib_name} PUBLIC AMR_WIND_USE_OPENFAST) target_include_directories(${amr_wind_lib_name} PUBLIC ${OpenFAST_INCLUDE_DIRS}) target_link_libraries(${amr_wind_lib_name} PUBLIC ${OpenFAST_LIBRARIES}) + + set(AMR_WIND_OPENFAST_VERSION "3" CACHE STRING "OpenFAST major version") + if((AMR_WIND_OPENFAST_VERSION STREQUAL "master") OR (AMR_WIND_OPENFAST_VERSION STREQUAL "main") OR (AMR_WIND_OPENFAST_VERSION STREQUAL "develop")) + set(AMR_WIND_OPENFAST_VERSION "4.0") + endif() + if(NOT AMR_WIND_OPENFAST_VERSION VERSION_LESS "5") + message(FATAL_ERROR "AMR_WIND_OPENFAST_VERSION must be less than 5.") + endif() + string(REPLACE "." ";" OPENFAST_VERSION_LIST ${AMR_WIND_OPENFAST_VERSION}) + list(LENGTH OPENFAST_VERSION_LIST OPENFAST_VERSION_LIST_LENGTH) + if(OPENFAST_VERSION_LIST_LENGTH GREATER_EQUAL 1) + list(GET OPENFAST_VERSION_LIST 0 OPENFAST_VERSION_MAJOR) + endif() + target_compile_definitions(${amr_wind_lib_name} PUBLIC OPENFAST_VERSION_MAJOR=${OPENFAST_VERSION_MAJOR}) endif() if(AMR_WIND_ENABLE_ASCENT) diff --git a/amr-wind/wind_energy/actuator/turbine/fast/FastIface.H b/amr-wind/wind_energy/actuator/turbine/fast/FastIface.H index 4a2048350e..1ae0d521a9 100644 --- a/amr-wind/wind_energy/actuator/turbine/fast/FastIface.H +++ b/amr-wind/wind_energy/actuator/turbine/fast/FastIface.H @@ -81,6 +81,10 @@ protected: int m_num_sc_inputs{0}; int m_num_sc_outputs{0}; +#if OPENFAST_VERSION_MAJOR == 4 + int m_inflow_type{2}; +#endif + int m_num_sc_inputs_glob{0}; float m_init_sc_inputs_glob{0.0}; float m_init_sc_inputs_turbine{0.0}; diff --git a/amr-wind/wind_energy/actuator/turbine/fast/FastIface.cpp b/amr-wind/wind_energy/actuator/turbine/fast/FastIface.cpp index 60995dbac1..b59dd27703 100644 --- a/amr-wind/wind_energy/actuator/turbine/fast/FastIface.cpp +++ b/amr-wind/wind_energy/actuator/turbine/fast/FastIface.cpp @@ -130,7 +130,7 @@ void FastIface::init_solution(const int local_id) AMREX_ALWAYS_ASSERT(m_is_initialized); auto& fi = *m_turbine_data[local_id]; - fast_func(FAST_OpFM_Solution0, &fi.tid_local); + fast_func(FAST_Solution0, &fi.tid_local); fi.is_solution0 = false; } @@ -168,7 +168,7 @@ void FastIface::advance_turbine(const int local_id) write_velocity_data(fi); for (int i = 0; i < fi.num_substeps; ++i, ++fi.time_index) { - fast_func(FAST_OpFM_Step, &fi.tid_local); + fast_func(FAST_Step, &fi.tid_local); } if (fi.chkpt_interval > 0 && @@ -220,6 +220,17 @@ void FastIface::fast_init_turbine(FastTurbine& fi) amrex::Array inp_file; copy_filename(fi.input_file, inp_file.begin()); +#if OPENFAST_VERSION_MAJOR == 4 + char out_file[fast_strlen()]; + fast_func( + FAST_ExtInfw_Init, &fi.tid_local, &fi.stop_time, inp_file.begin(), + &fi.tid_global, out_file, &m_num_sc_inputs_glob, &m_num_sc_inputs, + &m_num_sc_outputs, &m_init_sc_inputs_glob, &m_init_sc_inputs_turbine, + &fi.num_pts_blade, &fi.num_pts_tower, fi.base_pos.begin(), &abort_lev, + &fi.dt_cfd, &fi.dt_fast, &m_inflow_type, &fi.num_blades, + &fi.num_blade_elem, &fi.num_tower_elem, &fi.chord_cluster_type, + &fi.to_cfd, &fi.from_cfd, &fi.to_sc, &fi.from_sc); +#else fast_func( FAST_OpFM_Init, &fi.tid_local, &fi.stop_time, inp_file.begin(), &fi.tid_global, &m_num_sc_inputs_glob, &m_num_sc_inputs, @@ -227,6 +238,7 @@ void FastIface::fast_init_turbine(FastTurbine& fi) &fi.num_pts_blade, &fi.num_pts_tower, fi.base_pos.begin(), &abort_lev, &fi.dt_fast, &fi.num_blades, &fi.num_blade_elem, &fi.chord_cluster_type, &fi.to_cfd, &fi.from_cfd, &fi.to_sc, &fi.from_sc); +#endif { #ifdef AMR_WIND_USE_OPENFAST @@ -289,13 +301,13 @@ void FastIface::fast_replay_turbine(FastTurbine& fi) // restart fi.time_index = 0; read_velocity_data(fi, ncf, 0); - fast_func(FAST_OpFM_Solution0, &fi.tid_local); + fast_func(FAST_Solution0, &fi.tid_local); fi.is_solution0 = false; for (int ic = 0; ic < num_cfd_steps; ++ic) { read_velocity_data(fi, ncf, ic); for (int i = 0; i < fi.num_substeps; ++i, ++fi.time_index) { - fast_func(FAST_OpFM_Step, &fi.tid_local); + fast_func(FAST_Step, &fi.tid_local); } } AMREX_ALWAYS_ASSERT(fi.time_index == num_steps); @@ -321,10 +333,18 @@ void FastIface::fast_restart_turbine(FastTurbine& fi) amrex::Array chkpt_file; copy_filename(fi.checkpoint_file, chkpt_file.begin()); +#if OPENFAST_VERSION_MAJOR == 4 + fast_func( + FAST_ExtInfw_Restart, &fi.tid_local, chkpt_file.begin(), &abort_lev, + &fi.dt_fast, &m_inflow_type, &fi.num_blades, &fi.num_blade_elem, + &fi.num_tower_elem, &fi.time_index, &fi.to_cfd, &fi.from_cfd, &fi.to_sc, + &fi.from_sc); +#else fast_func( FAST_OpFM_Restart, &fi.tid_local, chkpt_file.begin(), &abort_lev, &fi.dt_fast, &fi.num_blades, &fi.num_blade_elem, &fi.time_index, &fi.to_cfd, &fi.from_cfd, &fi.to_sc, &fi.from_sc); +#endif { #ifdef AMR_WIND_USE_OPENFAST diff --git a/amr-wind/wind_energy/actuator/turbine/fast/fast_types.H b/amr-wind/wind_energy/actuator/turbine/fast/fast_types.H index ddd271ff30..ec08d0dc07 100644 --- a/amr-wind/wind_energy/actuator/turbine/fast/fast_types.H +++ b/amr-wind/wind_energy/actuator/turbine/fast/fast_types.H @@ -57,6 +57,10 @@ struct FastTurbine //! Total number of elements along the blade int num_blade_elem; +#if OPENFAST_VERSION_MAJOR == 4 + //! Total number of elements along the tower + int num_tower_elem; +#endif //! Node cluster type for the chord int chord_cluster_type{0}; @@ -87,8 +91,8 @@ struct FastTurbine // Data structures that are used to exchange between fast/cfd - exw_fast::OpFM_InputType to_cfd; - exw_fast::OpFM_OutputType from_cfd; + exw_fast::OfInputType to_cfd; + exw_fast::OfOutputType from_cfd; exw_fast::SC_DX_InputType to_sc; exw_fast::SC_DX_OutputType from_sc; diff --git a/amr-wind/wind_energy/actuator/turbine/fast/fast_wrapper.H b/amr-wind/wind_energy/actuator/turbine/fast/fast_wrapper.H index ccff5d36eb..12733d5990 100644 --- a/amr-wind/wind_energy/actuator/turbine/fast/fast_wrapper.H +++ b/amr-wind/wind_energy/actuator/turbine/fast/fast_wrapper.H @@ -2,6 +2,7 @@ #define FAST_WRAPPER_H namespace exw_fast { + #ifdef AMR_WIND_USE_OPENFAST extern "C" { #include "FAST_Library.h" @@ -19,11 +20,6 @@ inline constexpr int fast_strlen() { return INTERFACE_STRING_LENGTH; } #define ErrID_Severe 3 #define ErrID_Fatal 4 -struct OpFM_InputType -{}; -struct OpFM_OutputType -{}; - struct SC_DX_InputType {}; struct SC_DX_OutputType @@ -37,11 +33,7 @@ inline void FAST_AllocateTurbines(int* /*unused*/, int* /*unused*/, char* /*unused*/) {} inline void FAST_DeallocateTurbines(int* /*unused*/, char* /*unused*/) {} -inline void -FAST_OpFM_Solution0(int* /*unused*/, int* /*unused*/, char* /*unused*/) -{} -inline void FAST_OpFM_Step(int* /*unused*/, int* /*unused*/, char* /*unused*/) -{} + inline void FAST_CreateCheckpoint( int* /*unused*/, char* /*unused*/, int* /*unused*/, char* /*unused*/) {} @@ -55,6 +47,79 @@ inline void FAST_HubPosition( char* /*unused*/) {} +#if OPENFAST_VERSION_MAJOR == 4 +struct ExtInfw_InputType_t +{}; + +struct ExtInfw_OutputType_t +{}; + +inline void +FAST_CFD_Solution0(int* /*unused*/, int* /*unused*/, char* /*unused*/) +{} + +inline void FAST_CFD_Step(int* /*unused*/, int* /*unused*/, char* /*unused*/) {} + +inline void FAST_ExtInfw_Init( + int* /*unused*/, + double* /*unused*/, + const char* /*unused*/, + int* /*unused*/, + const char* /*unused*/, + int* /*unused*/, + int* /*unused*/, + int* /*unused*/, + float* /*unused*/, + float* /*unused*/, + int* /*unused*/, + int* /*unused*/, + float* /*unused*/, + int* /*unused*/, + double* /*unused*/, + int* /*unused*/, + int* /*unused*/, + int* /*unused*/, + int* /*unused*/, + int* /*unused*/, + OpFM_InputType* /*unused*/, + OpFM_OutputType* /*unused*/, + SC_DX_InputType* /*unused*/, + SC_DX_OutputType* /*unused*/, + int* /*unused*/, + char* /*unused*/) +{} + +inline void FAST_ExtInfw_Restart( + int* /*unused*/, + char* /*unused*/, + int* /*unused*/, + double* /*unused*/, + int* /*unused*/, + int* /*unused*/, + int* /*unused*/, + int* /*unused*/, + OpFM_InputType* /*unused*/, + OpFM_OutputType* /*unused*/, + SC_DX_InputType* /*unused*/, + SC_DX_OutputType* /*unused*/, + int* /*unused*/, + char* /*unused*/) +{} + +#else +struct OpFM_InputType +{}; + +struct OpFM_OutputType +{}; + +inline void +FAST_OpFM_Solution0(int* /*unused*/, int* /*unused*/, char* /*unused*/) +{} + +inline void FAST_OpFM_Step(int* /*unused*/, int* /*unused*/, char* /*unused*/) +{} + inline void FAST_OpFM_Init( int* /*unused*/, double* /*unused*/, @@ -97,6 +162,21 @@ inline void FAST_OpFM_Restart( char* /*unused*/) {} #endif + +#endif + +#if OPENFAST_VERSION_MAJOR == 4 +static constexpr auto& FAST_Solution0 = FAST_CFD_Solution0; +static constexpr auto& FAST_Step = FAST_CFD_Step; +using OfInputType = ExtInfw_InputType_t; +using OfOutputType = ExtInfw_OutputType_t; +#else +static constexpr auto& FAST_Solution0 = FAST_OpFM_Solution0; +static constexpr auto& FAST_Step = FAST_OpFM_Step; +using OfInputType = OpFM_InputType; +using OfOutputType = OpFM_OutputType; +#endif + } // namespace exw_fast #endif /* FAST_WRAPPER_H */ diff --git a/docs/sphinx/user/build.rst b/docs/sphinx/user/build.rst index 7b4f270adc..4cdc052fbb 100644 --- a/docs/sphinx/user/build.rst +++ b/docs/sphinx/user/build.rst @@ -103,6 +103,14 @@ Dependencies Enable NetCDF outputs. Default: OFF +.. cmakeval:: AMR_WIND_ENABLE_OPENFAST + + Enable OpenFAST coupling. Default: OFF + +.. cmakeval:: AMR_WIND_OPENFAST_VERSION + + OpenFAST version. Default: 3 + Other AMR-Wind specific options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c36d15eec2..e3cb8d7795 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -323,7 +323,7 @@ if(AMR_WIND_ENABLE_W2A) add_test_re(abl_multiphase_w2a) endif() -if(AMR_WIND_ENABLE_OPENFAST) +if(AMR_WIND_ENABLE_OPENFAST AND AMR_WIND_OPENFAST_VERSION VERSION_LESS "4") set(ACT_UNIFORM_ALM_TEST_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test_files/act_uniform_alm) set(ACT_UNIFORM_ALM_TEST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/test_files/act_uniform_alm) set(RTEST_ACT_UNIFORM_ALM_TEST_BINARY_DIR ${ACT_UNIFORM_ALM_TEST_BINARY_DIR}/r-test)