diff --git a/MARBL_tools/run_test_suite.sh b/MARBL_tools/run_test_suite.sh index e1e1b051..102fad61 100755 --- a/MARBL_tools/run_test_suite.sh +++ b/MARBL_tools/run_test_suite.sh @@ -356,6 +356,12 @@ if [ "${STATUS}" == "PASS" ]; then STATUS=$(check_return $?) print_status "requested_tracers.py" >> ${RESULTS_CACHE} + # Print all output_for_GCM variables + cd ${MARBL_ROOT}/tests/regression_tests/available_output + (set -x ; ./available_output.py) + STATUS=$(check_return $?) + print_status "available_output.py" >> ${RESULTS_CACHE} + # Initialize MARBL (with MPI) cd ${MARBL_ROOT}/tests/regression_tests/init (set -x ; ./init.py --mpitasks 2) diff --git a/docs/src/dev-guide/marbl-interface.rst b/docs/src/dev-guide/marbl-interface.rst index 48b5f1aa..2e14e7a0 100644 --- a/docs/src/dev-guide/marbl-interface.rst +++ b/docs/src/dev-guide/marbl-interface.rst @@ -32,6 +32,7 @@ The class definition is shown below: type(marbl_forcing_fields_type), allocatable , public :: interior_tendency_forcings(:) ! input real (r8), allocatable , public :: interior_tendencies(:,:) ! output type(marbl_interior_tendency_forcing_indexing_type), public :: interior_tendency_forcing_ind ! FIXME #311: should be private + type(marbl_output_for_GCM_type) , public :: interior_tendency_output ! output type(marbl_diagnostics_type) , public :: interior_tendency_diags ! output ! public data related to computing surface fluxes @@ -43,20 +44,20 @@ The class definition is shown below: type(marbl_diagnostics_type) , public :: surface_flux_diags ! output ! public data - global averages - real (r8) , public, allocatable :: glo_avg_fields_interior_tendency(:) ! output (nfields) - real (r8) , public, allocatable :: glo_avg_averages_interior_tendency(:) ! input (nfields) - real (r8) , public, allocatable :: glo_avg_fields_surface_flux(:,:) ! output (num_elements,nfields) - real (r8) , public, allocatable :: glo_avg_averages_surface_flux(:) ! input (nfields) + real (r8), public, allocatable :: glo_avg_fields_interior_tendency(:) ! output (nfields) + real (r8), public, allocatable :: glo_avg_averages_interior_tendency(:) ! input (nfields) + real (r8), public, allocatable :: glo_avg_fields_surface_flux(:,:) ! output (num_elements,nfields) + real (r8), public, allocatable :: glo_avg_averages_surface_flux(:) ! input (nfields) ! FIXME #77: for now, running means are being computed in the driver ! they will eventually be moved from the interface to inside MARBL - real (r8) , public, allocatable :: glo_scalar_interior_tendency(:) - real (r8) , public, allocatable :: glo_scalar_surface_flux(:) + real (r8), public, allocatable :: glo_scalar_interior_tendency(:) + real (r8), public, allocatable :: glo_scalar_surface_flux(:) - type(marbl_running_mean_0d_type) , public, allocatable :: glo_avg_rmean_interior_tendency(:) - type(marbl_running_mean_0d_type) , public, allocatable :: glo_avg_rmean_surface_flux(:) - type(marbl_running_mean_0d_type) , public, allocatable :: glo_scalar_rmean_interior_tendency(:) - type(marbl_running_mean_0d_type) , public, allocatable :: glo_scalar_rmean_surface_flux(:) + type(marbl_running_mean_0d_type), public, allocatable :: glo_avg_rmean_interior_tendency(:) + type(marbl_running_mean_0d_type), public, allocatable :: glo_avg_rmean_surface_flux(:) + type(marbl_running_mean_0d_type), public, allocatable :: glo_scalar_rmean_interior_tendency(:) + type(marbl_running_mean_0d_type), public, allocatable :: glo_scalar_rmean_surface_flux(:) ! private data type(unit_system_type), private :: unit_system @@ -80,6 +81,7 @@ The class definition is shown below: type(marbl_internal_timers_type), private :: timers type(marbl_timer_indexing_type), private :: timer_ids type(marbl_settings_type), private :: settings + type(marbl_output_for_GCM_registry_type), private :: output_for_gcm_registry contains @@ -106,7 +108,6 @@ The class definition is shown below: get_string procedure, public :: get_settings_var_cnt procedure, public :: add_output_for_GCM - procedure, public :: get_output_for_GCM procedure, private :: inquire_settings_metadata_by_name procedure, private :: inquire_settings_metadata_by_id procedure, private :: put_real diff --git a/src/marbl_interface.F90 b/src/marbl_interface.F90 index ba024133..afc691ad 100644 --- a/src/marbl_interface.F90 +++ b/src/marbl_interface.F90 @@ -90,18 +90,16 @@ module marbl_interface type(marbl_forcing_fields_type), allocatable , public :: interior_tendency_forcings(:) ! input real (r8), allocatable , public :: interior_tendencies(:,:) ! output type(marbl_interior_tendency_forcing_indexing_type), public :: interior_tendency_forcing_ind ! FIXME #311: should be private - type(marbl_diagnostics_type) , public :: interior_tendency_diags ! output type(marbl_output_for_GCM_type) , public :: interior_tendency_output ! output + type(marbl_diagnostics_type) , public :: interior_tendency_diags ! output ! public data related to computing surface fluxes - real (r8) , public, allocatable :: tracers_at_surface(:,:) ! input - type(marbl_forcing_fields_type) , public, allocatable :: surface_flux_forcings(:) ! input - type(marbl_surface_flux_forcing_indexing_type) , public :: surface_flux_forcing_ind ! FIXME #311: should be private - real (r8) , public, allocatable :: surface_fluxes(:,:) ! output - type(marbl_diagnostics_type) , public :: surface_flux_diags ! output - type(marbl_output_for_GCM_type) , public :: surface_flux_output ! output - - ! public data that the GCM needs to explicitly request + real (r8) , public, allocatable :: tracers_at_surface(:,:) ! input + type(marbl_forcing_fields_type) , public, allocatable :: surface_flux_forcings(:) ! input + type(marbl_surface_flux_forcing_indexing_type) , public :: surface_flux_forcing_ind ! FIXME #311: should be private + real (r8) , public, allocatable :: surface_fluxes(:,:) ! output + type(marbl_output_for_GCM_type) , public :: surface_flux_output ! output + type(marbl_diagnostics_type) , public :: surface_flux_diags ! output ! public data - global averages real (r8), public, allocatable :: glo_avg_fields_interior_tendency(:) ! output (nfields) @@ -114,6 +112,10 @@ module marbl_interface real (r8), public, allocatable :: glo_scalar_interior_tendency(:) real (r8), public, allocatable :: glo_scalar_surface_flux(:) + ! Registry of available output for the GCM + ! (Public so we can provide available_output test in the standalone driver) + type(marbl_output_for_GCM_registry_type), public :: output_for_gcm_registry + type(marbl_running_mean_0d_type), public, allocatable :: glo_avg_rmean_interior_tendency(:) type(marbl_running_mean_0d_type), public, allocatable :: glo_avg_rmean_surface_flux(:) type(marbl_running_mean_0d_type), public, allocatable :: glo_scalar_rmean_interior_tendency(:) @@ -141,7 +143,6 @@ module marbl_interface type(marbl_internal_timers_type), private :: timers type(marbl_timer_indexing_type), private :: timer_ids type(marbl_settings_type), private :: settings - type(marbl_output_for_GCM_registry_type), private :: output_for_gcm_registry contains diff --git a/tests/driver_src/marbl.F90 b/tests/driver_src/marbl.F90 index f61f3000..4e4dcdfe 100644 --- a/tests/driver_src/marbl.F90 +++ b/tests/driver_src/marbl.F90 @@ -42,6 +42,7 @@ Program marbl ! Use from libmarbl.a use marbl_interface, only : marbl_interface_class + use marbl_interface_public_types, only : marbl_output_for_GCM_linked_list_type use marbl_logging, only : marbl_log_type use marbl_kinds_mod, only : char_len @@ -74,9 +75,10 @@ Program marbl character(len=char_len) :: namelist_file, settings_file character(len=3) :: unit_system_opt integer :: argcnt - logical :: labort_after_argparse, lshow_usage, lfound_file + logical :: labort_after_argparse, lshow_usage, lfound_file, lunavailable_output type(marbl_interface_class), dimension(:), allocatable :: marbl_instances + type(marbl_output_for_GCM_linked_list_type), pointer :: registered_output type(marbl_log_type) :: driver_status_log integer :: n, cnt character(len=char_len) :: settings_file_line, varname, log_message @@ -437,6 +439,57 @@ Program marbl call marbl_instances(1)%shutdown() end if + ! -- available_output test -- ! + case ('available_output') + call verify_single_instance(num_inst, trim(testname)) + lprint_marbl_log = .false. + call marbl_init_test(marbl_instances(1), unit_system_opt, lshutdown = .false.) + if (.not. marbl_instances(1)%StatusLog%labort_marbl) then + ! Log available output for GCM and note if any output is unavailable + call driver_status_log%log_header('Available output for GCM', subname) + lunavailable_output = .false. + cnt = 0 + registered_output => marbl_instances(1)%output_for_gcm_registry%registered_outputs + do while (associated(registered_output)) + if (len_trim(registered_output%err_message) == 0) then + cnt = cnt+1 + write(log_message, "(I0, 2A)") cnt, '. ', trim(registered_output%long_name) + call driver_status_log%log_noerror(log_message, subname) + write(log_message, "(2A)") ' short name: ', trim(registered_output%short_name) + call driver_status_log%log_noerror(log_message, subname) + write(log_message, "(2A)") ' units: ', trim(registered_output%units) + call driver_status_log%log_noerror(log_message, subname) + write(log_message, "(2A)") ' field_source: ', trim(registered_output%field_source) + call driver_status_log%log_noerror(log_message, subname) + else + lunavailable_output = .true. + end if + registered_output => registered_output%next + end do + + if (cnt.eq.0) then + call driver_status_log%log_noerror('No available output for the GCM in this configuration!', subname) + end if + + if (lunavailable_output) then + call driver_status_log%log_header('Unavailable output for GCM', subname) + cnt = 0 + registered_output => marbl_instances(1)%output_for_gcm_registry%registered_outputs + do while (associated(registered_output)) + if (len_trim(registered_output%err_message) > 0) then + cnt = cnt+1 + write(log_message, "(I0, 2A)") cnt, '. ', trim(registered_output%long_name) + call driver_status_log%log_noerror(log_message, subname) + write(log_message, "(2A)") ' * ', trim(registered_output%err_message) + call driver_status_log%log_noerror(log_message, subname) + end if + registered_output => registered_output%next + end do + end if + call marbl_instances(1)%shutdown() + end if + + ! -- call_compute_subroutines test -- ! case ('call_compute_subroutines') lprint_marbl_log = .false. call marbl_call_compute_subroutines_test(marbl_instances, hist_file, unit_system_opt, driver_status_log) diff --git a/tests/regression_tests/available_output/available_output.py b/tests/regression_tests/available_output/available_output.py new file mode 100755 index 00000000..3acea76c --- /dev/null +++ b/tests/regression_tests/available_output/available_output.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +from sys import path +import os + +path.insert(0, os.path.join('..', '..', 'python_for_tests')) +from marbl_testing_class import MARBL_testcase + +mt = MARBL_testcase() + +mt.parse_args(desc='Run MARBL init and print list of available output for GCM') + +mt.build_exe() + +mt.run_exe() \ No newline at end of file diff --git a/tests/regression_tests/available_output/test.nml b/tests/regression_tests/available_output/test.nml new file mode 100644 index 00000000..07a50fc9 --- /dev/null +++ b/tests/regression_tests/available_output/test.nml @@ -0,0 +1,3 @@ +&marbl_driver_nml +testname="available_output" +/