diff --git a/CMakeLists.txt b/CMakeLists.txt index 02619930d7ca28caef51a281c6a3b728256f1f44..dc1cd0e1d66bcea5099ce51e4aa7cd723dea7551 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,10 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.19) option(INCLUDE_CUDA "GPU build in mode" OFF) option(INCLUDE_CXX "CXX build in mode" OFF) option(BUILD_DOC "Build documentation" OFF) option(SFX_CHECK_NAN "Build documentation" OFF) +option(USE_CONFIG_PARSER "Build config parser" OFF) project(INMCM_sfx) enable_language(Fortran) @@ -26,15 +27,23 @@ if (SFX_CHECK_NAN) add_definitions(-DSFX_CHECK_NAN) endif () +set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/modules) + +if(USE_CONFIG_PARSER) + add_subdirectory(parser/) + list(APPEND RUN_MACRO -DUSE_CONFIG_PARSER) + set(INCLUDE_CXX ON) +endif(USE_CONFIG_PARSER) + if(INCLUDE_CXX) - set(RUN_MACRO -DINCLUDE_CXX) + list(APPEND RUN_MACRO -DINCLUDE_CXX) endif(INCLUDE_CXX) if(INCLUDE_CUDA) enable_language(CUDA) find_package(CUDA REQUIRED) include_directories(${CUDA_INCLUDE_DIRS}) - set(RUN_MACRO -DINCLUDE_CUDA) + list(APPEND RUN_MACRO -DINCLUDE_CUDA) set(INCLUDE_CXX ON) endif(INCLUDE_CUDA) @@ -60,6 +69,7 @@ set(SOURCES_F srcF/sfx_sheba.f90 srcF/sfx_sheba_param.f90 srcF/sfx_fc_wrapper.F90 + srcF/parser_subfunctions.f90 ) set(HEADERS_F @@ -123,7 +133,6 @@ endif(INCLUDE_CXX OR INCLUDE_CUDA) set(SOURCES ${MEMPROC_HEADERS_CU} ${MEMPROC_SOURCES_CU} ${MEMPROC_HEADERS_CXX} ${MEMPROC_SOURCES_CXX} ${HEADERS_CU} ${SOURCES_CU} ${HEADERS_CXX} ${SOURCES_CXX} ${SOURCES_C} ${HEADERS_F} ${SOURCES_F}) -# set(CMAKE_Fortran_FLAGS " -cpp ") set(CMAKE_Fortran_FLAGS " -g -fbacktrace -ffpe-trap=zero,overflow,underflow -cpp ") if(INCLUDE_CXX OR INCLUDE_CUDA) set(CMAKE_CXX_FLAGS " -g -Wunused-variable ") @@ -132,13 +141,14 @@ if(INCLUDE_CXX OR INCLUDE_CUDA) set(CMAKE_CUDA_FLAGS " -g ") endif(INCLUDE_CXX OR INCLUDE_CUDA) -add_subdirectory(parser/) - add_executable(drag ${SOURCES}) add_definitions(${RUN_MACRO}) set_property(TARGET drag PROPERTY LINKER_LANGUAGE Fortran) target_include_directories(drag PUBLIC ${CMAKE_BINARY_DIR}/modules/) -target_link_libraries(drag parser_F parser_CXX) + +if(USE_CONFIG_PARSER) + target_link_libraries(drag parser_F parser_CXX) +endif(USE_CONFIG_PARSER) #copy data on post build diff --git a/config.txt b/config.txt new file mode 100644 index 0000000000000000000000000000000000000000..54d31e4eb9b5afaf81f78b115eeb92257d1da74d --- /dev/null +++ b/config.txt @@ -0,0 +1,13 @@ + +input_files +{ + filename_in_common = "../data/IRGASON_zh.txt"; + filename_in = "../data/Irgason1.txt"; + filename_out = "../out_IRGASON1.txt"; +} + +surface +{ + surface_type = "ocean"; + z0_m = 0.1; # aerodynamic roughness [m] +} diff --git a/parser/CMakeLists.txt b/parser/CMakeLists.txt index da342d4fd030cd8d195acf9bb19789b233bd3304..c2aa35d9621979495542c170e9de3c7091720c98 100644 --- a/parser/CMakeLists.txt +++ b/parser/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.19) # option(INCLUDE_CXX "CXX build in mode" OFF) diff --git a/parser/call_parser.F90 b/parser/call_parser.F90 index a6620506acbf1f8d679eb3ddb44f9643f58594ad..df56d48062814e610098927be6e7f80c65347938 100644 --- a/parser/call_parser.F90 +++ b/parser/call_parser.F90 @@ -1,16 +1,4 @@ -! module C_FUNC_SUB -! contains - -! INTEGER function get_char_len(name) BIND(C) -! USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR -! IMPLICIT NONE -! CHARACTER (KIND=C_CHAR), intent(in) :: name(*) -! end function get_char_len - -! end module C_FUNC_SUB - -module PARSER_C_FUNC - +module PARSER INTERFACE SUBROUTINE run(filename) BIND(C) USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR @@ -47,41 +35,37 @@ module PARSER_C_FUNC INTEGER (KIND=C_INT), intent(out) :: len END SUBROUTINE get_char_len - SUBROUTINE get_charc(name, value) BIND(C) + SUBROUTINE get_char_c(name, value) BIND(C) USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR IMPLICIT NONE CHARACTER (KIND=C_CHAR), intent(in) :: name(*) CHARACTER (KIND=C_CHAR), intent(out) :: value(*) - END SUBROUTINE get_charc + END SUBROUTINE get_char_c END INTERFACE -end module PARSER_C_FUNC -! TODO: - -SUBROUTINE get_char_lenf(name, len) - USE PARSER_C_FUNC - - IMPLICIT NONE - CHARACTER, intent(in) :: name(*) - INTEGER, intent(out) :: len + contains + + SUBROUTINE get_char_lenf(name, len) + IMPLICIT NONE + CHARACTER, intent(in) :: name(*) + INTEGER, intent(out) :: len - call get_char_len(name, len) -END SUBROUTINE get_char_lenf + call get_char_len(name, len) + END SUBROUTINE get_char_lenf -SUBROUTINE get_charf(name, char_value) - USE PARSER_C_FUNC + SUBROUTINE get_charf(name, char_value) + IMPLICIT NONE + CHARACTER, allocatable, intent(OUT) :: char_value(:) + CHARACTER, intent(in) :: name(*) + INTEGER :: len - IMPLICIT NONE - CHARACTER, allocatable, intent(OUT) :: char_value(:) + call get_char_lenf(name, len) - CHARACTER, intent(in) :: name(*) - INTEGER :: len + IF(allocated(char_value)) deallocate(char_value) + allocate(char_value(len)) - call get_char_lenf(name, len) - - write(*, *) 'len = ', len + call get_char_c(name, char_value) + END SUBROUTINE get_charf - ! IF(ALLOCATED(char_value)) DEALLOCATE(char_value) - ! allocate(char_value(4)) -END SUBROUTINE get_charf \ No newline at end of file +end module PARSER \ No newline at end of file diff --git a/parser/call_parser.c b/parser/call_parser.c index 109668d0d87c61fd9e29c70b77a4c7ec4d5b26a7..9b5294bc5eb65248a12c64a5c29dea5f4a4b7b3c 100644 --- a/parser/call_parser.c +++ b/parser/call_parser.c @@ -22,7 +22,7 @@ int get_double(const char* name, double* value) return get_doubleCXX(name, value); } -int get_charc(const char* name, char* value) +int get_char_c(const char* name, char* value) { return get_charCXX(name, value); } diff --git a/parser/call_parser.cpp b/parser/call_parser.cpp index d08a0b95da52dd0df3bc8b385a0ee308f8aa933f..6e323111ae413446f55bb24f641f1c7de3b9f245 100644 --- a/parser/call_parser.cpp +++ b/parser/call_parser.cpp @@ -53,8 +53,6 @@ extern "C" { std::string target_res; bool res = Parser.get_value(name, target_res); - printf("target_res = %s, len = %d\n", target_res.c_str(), target_res.size()); - const int n = target_res.size(); for (int i = 0; i < n; i++) diff --git a/parser/config-parser.cpp b/parser/config-parser.cpp index 00e1dbec087a4f109fab36802c245040a00cd957..e25c57186be616abace9861e167c7fe535abba29 100644 --- a/parser/config-parser.cpp +++ b/parser/config-parser.cpp @@ -1248,7 +1248,7 @@ bool scm::ConfigParser::set_command( if (dyn_expr.size() != rpn_key.get_value(rpn_size - 1)) { - printf(" CONFIG:> incorrect number (%i) of command '%s' arguments (line, %i)\n", + printf(" CONFIG:> incorrect number (%li) of command '%s' arguments (line, %i)\n", dyn_expr.size(), lexeme_list.get_token(rpn.get_value(rpn_size - 1)), lexeme_list.get_tag(rpn.get_value(rpn_size - 1))); diff --git a/srcF/parser_subfunctions.f90 b/srcF/parser_subfunctions.f90 new file mode 100644 index 0000000000000000000000000000000000000000..9d722a4ed0c8d6101ab756ff95e2292d02e11a61 --- /dev/null +++ b/srcF/parser_subfunctions.f90 @@ -0,0 +1,43 @@ +module PARSER_SUB_F + contains + + FUNCTION compare_char_arrays(arr1, arr2, N) RESULT(isEqual) + IMPLICIT NONE + CHARACTER, intent(in) :: arr1(N) + CHARACTER, intent(in) :: arr2(N) + INTEGER, intent(in) :: N + LOGICAL :: isEqual + INTEGER :: i + + isEqual = .TRUE. + + DO i = 1, N + IF (arr1(i) .NE. arr2(i)) THEN + isEqual = .FALSE. ! Найдено неравенство + EXIT + END IF + END DO + END FUNCTION compare_char_arrays + + FUNCTION get_sfx_type(config_var_name) RESULT(type) + USE PARSER + USE sfx_surface + IMPLICIT NONE + CHARACTER, intent(in) :: config_var_name(*) + CHARACTER, allocatable :: sfx_type(:) + INTEGER :: type + + call get_charf(config_var_name, sfx_type) + + if ( compare_char_arrays(sfx_type, "ocean", SIZE(sfx_type)) ) then + type = surface_ocean + else if ( compare_char_arrays(sfx_type, "lake", SIZE(sfx_type)) ) then + type = surface_lake + else if ( compare_char_arrays(sfx_type, "land", SIZE(sfx_type)) ) then + type = surface_land + end if + + deallocate(sfx_type) + END FUNCTION get_sfx_type + +end module PARSER_SUB_F \ No newline at end of file diff --git a/srcF/sfx_main.f90 b/srcF/sfx_main.f90 index 374a396a2c2ff20e4420f6204e8ce5e0f6da82b9..08dbd680a2defd5f08ebf13996678a9ee7ac7f3a 100644 --- a/srcF/sfx_main.f90 +++ b/srcF/sfx_main.f90 @@ -2,6 +2,13 @@ program sfx_main ! modules used ! -------------------------------------------------------------------------------- +#ifdef USE_CONFIG_PARSER + USE PARSER_SUB_F + USE PARSER + USE sfx_surface + use iso_c_binding, only: C_NULL_CHAR +#endif + use sfx_phys_const use sfx_common use sfx_io @@ -100,6 +107,12 @@ program sfx_main integer :: status ! -------------------------------------------------------------------------------- +#ifdef USE_CONFIG_PARSER + character, allocatable :: fn_in_common(:), fn_in(:), fn_out(:) + integer :: sfx_type + real :: z0_m +#endif + !< @brief define model & dataset model_id = model_esm !< default = ESM @@ -218,6 +231,27 @@ program sfx_main stop end if +#ifdef USE_CONFIG_PARSER + call run("config.txt"//C_NULL_CHAR) + call get_charf("input_files.filename_in_common"//C_NULL_CHAR, fn_in_common) + call get_charf("input_files.filename_in"//C_NULL_CHAR, fn_in) + if (is_output_set == 0) call get_charf("input_files.filename_out"//C_NULL_CHAR, fn_out) + + sfx_type = get_sfx_type("surface.surface_type"//C_NULL_CHAR) + + if ( (sfx_type == surface_ocean) .or. (sfx_type == surface_lake) ) then + call get_float("surface.z0_m"//C_NULL_CHAR, z0_m) + end if + + write(*, *) "fn_in_common: ", fn_in_common + write(*, *) "fn_in: ", fn_in + if (is_output_set == 0) write(*, *) "fn_out: ", fn_out + write(*, *) "sfx_type: ", sfx_type + if ( (sfx_type == surface_ocean) .or. (sfx_type == surface_lake) ) then + write(*, *) "z0_m: ", z0_m + end if +#endif + !< @brief set name & filenames for specific dataset if (dataset_id == dataset_MOSAiC) then dataset_name = 'MOSAiC' @@ -345,6 +379,12 @@ program sfx_main call deallocate_meteo_vec(meteo) call deallocate_sfx_vec(sfx) +#ifdef USE_CONFIG_PARSER + deallocate( fn_in_common ) + deallocate( fn_in ) + if (is_output_set == 0) deallocate( fn_out ) +#endif + ! *: remove formats: not needed 10 format (f8.4,2x,f8.4)