!> @brief main run sfx on dataset subroutine ! ---------------------------------------------------------------------------- subroutine run_dataset(filename_out, dataset, model) use sfx_phys_const use sfx_common use sfx_config use sfx_io use sfx_data use sfx_esm, only: & get_surface_fluxes_vec_esm => get_surface_fluxes_vec, & numericsType_esm => numericsType use sfx_log, only: & get_surface_fluxes_vec_log => get_surface_fluxes_vec, & numericsType_log => numericsType use sfx_most, only: & get_surface_fluxes_vec_most => get_surface_fluxes_vec, & numericsType_most => numericsType use sfx_sheba, only: & get_surface_fluxes_vec_sheba => get_surface_fluxes_vec, & numericsType_sheba => numericsType ! -------------------------------------------------------------------------------- ! directives list ! -------------------------------------------------------------------------------- implicit none ! -------------------------------------------------------------------------------- character(len=*), intent(in) :: filename_out type(sfxDatasetType), intent(in) :: dataset integer, intent(in) :: model ! input/output model data ! -------------------------------------------------------------------------------- type(meteoDataVecType) :: meteo !< meteorological data (input) type(meteoDataType) :: meteo_cell type(sfxDataVecType) :: sfx !< surface fluxes (output) type(numericsType_esm) :: numerics_esm !< surface flux module (ESM) numerics parameters type(numericsType_log) :: numerics_log !< surface flux module (LOG) numerics parameters type(numericsType_most) :: numerics_most !< surface flux module (MOST) numerics parameters type(numericsType_sheba) :: numerics_sheba !< surface flux module (SHEBA) numerics parameters integer :: num !< number of 'cells' in input ! -------------------------------------------------------------------------------- ! local variables ! -------------------------------------------------------------------------------- integer :: i integer :: io, status ! -------------------------------------------------------------------------------- write(*, *) ' Running SFX:' write(*, '(a,a)') ' model = ', trim(get_model_tag(model)) write(*, '(a,a)') ' dataset = ', trim(get_dataset_tag(dataset%id)) write(*, '(a,a)') ' filename[IN] = ', trim(dataset%filename) write(*, '(a,a)') ' filename[OUT] = ', trim(filename_out) write(*, '(a, g0)') ' surface type = ', dataset%surface_type write(*, '(a, g0)') ' h = ', dataset%h write(*, '(a, g0)') ' z0(m) = ', dataset%z0_m write(*, '(a, g0)') ' z0(h) = ', dataset%z0_h !< @brief define number of cells open(newunit = io, file = dataset%filename, iostat = status, status ='old') if (status /= 0) then write(*, *) ' FAILURE! > unable to open file: ', trim(dataset%filename) return end if num = 0 status = 0 do while (status.eq.0) read (io, *, iostat = status) meteo_cell%U, meteo_cell%dT, meteo_cell%Tsemi, meteo_cell%dQ num = num + 1 enddo num = num - 1 close(io) ! --- print number of elements in dataset write(*, '(a, g0)') ' size = ', num if (dataset%nmax > 0) then write(*, '(a, g0)') ' nmax = ', dataset%nmax num = min(num, dataset%nmax) end if !< @brief allocate input & output data call allocate_meteo_vec(meteo, num) call allocate_sfx_vec(sfx, num) !< @brief setting height & roughness meteo_cell%h = dataset%h meteo_cell%z0_m = dataset%z0_m !< @brief read input data open(newunit = io, file = dataset%filename, iostat = status, status = 'old') if (status /= 0) then write(*, *) ' FAILURE! > unable to open file: ', trim(dataset%filename) return end if do i = 1, num read(io, *) meteo_cell%U, meteo_cell%dT, meteo_cell%Tsemi, meteo_cell%dQ meteo%h(i) = meteo_cell%h meteo%U(i) = meteo_cell%U meteo%dT(i) = meteo_cell%dT meteo%Tsemi(i) = meteo_cell%Tsemi meteo%dQ(i) = meteo_cell%dQ meteo%z0_m(i) = meteo_cell%z0_m enddo close(io) !< @brief calling flux module if (model == model_esm) then call get_surface_fluxes_vec_esm(sfx, meteo, numerics_esm, num) else if (model == model_log) then call get_surface_fluxes_vec_log(sfx, meteo, numerics_log, num) else if (model == model_most) then call get_surface_fluxes_vec_most(sfx, meteo, numerics_most, num) else if (model == model_sheba) then call get_surface_fluxes_vec_sheba(sfx, meteo, numerics_sheba, num) end if !< @brief write output data call write_ascii_vec11(filename_out, & sfx%zeta, sfx%Rib, & sfx%Re, sfx%B, sfx%z0_m, sfx%z0_t, & sfx%Rib_conv_lim, & sfx%Cm,sfx%Ct, sfx%Km, sfx%Pr_t_inv, num, '(11(f10.4,3x))', status) !< @brief deallocate input & output data call deallocate_meteo_vec(meteo) call deallocate_sfx_vec(sfx) end subroutine 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_common use sfx_config ! -------------------------------------------------------------------------------- ! directives list ! -------------------------------------------------------------------------------- implicit none ! -------------------------------------------------------------------------------- type(sfxDatasetType) :: dataset integer :: model character(len = 256) :: filename_out ! command line arguments ! -------------------------------------------------------------------------------- integer :: num_args character(len = 128) :: arg character(len = 128), parameter :: arg_key_model = '--model' character(len = 128), parameter :: arg_key_dataset = '--dataset' character(len = 128), parameter :: arg_key_output = '--output' character(len = 128), parameter :: arg_key_nmax = '--nmax' character(len = 128), parameter :: arg_key_help = '--help' character(len = 128), parameter :: arg_key_config = "--config" integer :: is_output_set ! -------------------------------------------------------------------------------- ! local variables ! -------------------------------------------------------------------------------- integer :: i integer :: status integer :: id, nmax ! -------------------------------------------------------------------------------- #ifdef USE_CONFIG_PARSER character, allocatable :: config_field(:) #endif !< @brief define default model & dataset model = model_esm !< default = ESM call set_dataset(dataset, dataset_mosaic) !< default = MOSAiC is_output_set = 0 !< default = auto define output filename !< @brief command line arguments processing num_args = command_argument_count() do i = 1, num_args call get_command_argument(i, arg) if (trim(arg) == trim(arg_key_help)) then write(*, *) ' sfx model, usage:' write(*, *) ' --help' write(*, *) ' print usage options' write(*, *) ' --model [key]' write(*, *) ' key = esm (default) || log || most || sheba' write(*, *) ' --dataset [key]' write(*, *) ' key = mosaic (default) || irgason || sheba' write(*, *) ' = lake || papa || toga || user [filename] [param]' write(*, *) ' param = [h] [z0(m)] [z0(h)]' write(*, *) ' --output [filename]' write(*, *) ' set output filename' write(*, *) ' --config [filename]' write(*, *) ' use configuration file' write(*, *) ' --nmax [value]' write(*, *) ' max number of data points > 0' stop end if if (trim(arg) == trim(arg_key_model)) then if (i == num_args) then write(*, *) ' FAILURE! > missing model [key] argument' stop end if call get_command_argument(i + 1, arg) model = get_model_id(arg) if (model == -1) then write(*, *) ' FAILURE! > unknown model [key]: ', trim(arg) stop end if else if (trim(arg) == trim(arg_key_dataset)) then if (i == num_args) then write(*, *) ' FAILURE! > missing dataset [key] argument' stop end if call get_command_argument(i + 1, arg) id = get_dataset_id(arg) if (id == -1) then write(*, *) ' FAILURE! > unknown dataset [key]: ', trim(arg) stop end if !< save nmax if previously set nmax = dataset%nmax call set_dataset(dataset, id) dataset%nmax = nmax if (dataset%id == dataset_user) then !< @brief user-defined dataset if (i + 5 > num_args) then write(*, *) ' FAILURE! > incorrect arguments for [user] dataset' stop end if !< filename call get_command_argument(i + 2, dataset%filename) !< reading 'h' call get_command_argument(i + 3, arg) call str2real(dataset%h, arg, status) if (status /= 0) then write(*, *) ' FAILURE! > expecting real h [value]' stop end if if (dataset%h <= 0) then write(*, *) ' FAILURE! > h [value] should be positive' stop end if !< reading 'z0(m)' call get_command_argument(i + 4, arg) call str2real(dataset%z0_m, arg, status) if (status /= 0) then write(*, *) ' FAILURE! > expecting real z0(m) [value]' stop end if !< reading 'z0(h)' call get_command_argument(i + 5, arg) call str2real(dataset%z0_h, arg, status) if (status /= 0) then write(*, *) ' FAILURE! > expecting real z0(h) [value]' stop end if end if else if (trim(arg) == trim(arg_key_output)) then if (i == num_args) then write(*, *) ' FAILURE! > missing output [key] argument' stop end if call get_command_argument(i + 1, filename_out) is_output_set = 1 else if (trim(arg) == trim(arg_key_nmax)) then if (i == num_args) then write(*, *) ' FAILURE! > missing nmax [key] argument' stop end if call get_command_argument(i + 1, arg) call str2int(dataset%nmax, arg, status) if (status /= 0) then write(*, *) ' FAILURE! > expecting int nmax [value]' stop end if if (dataset%nmax <= 0) then write(*, *) ' FAILURE! > nmax [value] should be positive' stop end if else if (trim(arg) == trim(arg_key_config)) then if (i == num_args) then write(*, *) ' FAILURE! > missing configuration file [key] argument' stop end if call get_command_argument(i + 1, arg) #ifdef USE_CONFIG_PARSER call run(trim(arg)//C_NULL_CHAR) call is_varname("model.id"//C_NULL_CHAR, status) if (status /= 0) then call get_charf("model.id"//C_NULL_CHAR, config_field) model = get_model_id(char_array2str(config_field)) if (model == -1) then write(*, *) ' FAILURE! > unknown model [key]: ', trim(char_array2str(config_field)) stop end if end if call is_varname("dataset.id"//C_NULL_CHAR, status) if (status /= 0) then call get_charf("dataset.id"//C_NULL_CHAR, config_field) id = get_dataset_id(char_array2str(config_field)) if (id == -1) then write(*, *) ' FAILURE! > unknown dataset [key]: ', trim(char_array2str(config_field)) stop end if !< save nmax if previously set nmax = dataset%nmax call set_dataset(dataset, id) dataset%nmax = nmax call is_varname("dataset.filename"//C_NULL_CHAR, status) if ((status /= 0).or.(dataset%id == dataset_user)) then !< mandatory in user dataset call get_charf("dataset.filename"//C_NULL_CHAR, config_field) dataset%filename = char_array2str(config_field) end if call is_varname("dataset.h"//C_NULL_CHAR, status) if ((status /= 0).or.(dataset%id == dataset_user)) then !< mandatory in user dataset call get_float("dataset.h"//C_NULL_CHAR, dataset%h) end if call is_varname("dataset.z0_m"//C_NULL_CHAR, status) if ((status /= 0).or.(dataset%id == dataset_user)) then !< mandatory in user dataset call get_float("dataset.z0_m"//C_NULL_CHAR, dataset%z0_m) end if call is_varname("dataset.z0_h"//C_NULL_CHAR, status) if ((status /= 0).or.(dataset%id == dataset_user)) then !< mandatory in user dataset call get_float("dataset.z0_h"//C_NULL_CHAR, dataset%z0_h) end if end if call is_varname("dataset.nmax"//C_NULL_CHAR, status) if (status /= 0) then call get_int("dataset.nmax"//C_NULL_CHAR, dataset%nmax) end if call is_varname("output.filename"//C_NULL_CHAR, status) if (status /= 0) then call get_charf("output.filename"//C_NULL_CHAR, config_field) filename_out = char_array2str(config_field) is_output_set = 1 end if if (allocated(config_field)) deallocate(config_field) #endif end if end do !< @bried set auto-defined output filename if (is_output_set == 0) then filename_out = 'output-' // trim(get_dataset_tag(dataset%id)) // '.txt' end if !< @brief running main driver call run_dataset(filename_out, dataset, model) stop end program