diff --git a/applications/io_demo/example/configuration.nml b/applications/io_demo/example/configuration.nml index d06bb4fe2..d0718497a 100644 --- a/applications/io_demo/example/configuration.nml +++ b/applications/io_demo/example/configuration.nml @@ -49,6 +49,10 @@ coord_system='native' file_convention = 'UGRID' / +&files + checkpoint_stem_name = 'restart-io_demo-' +/ + &io_demo multifile_io = .false. io_benchmark = .false. diff --git a/applications/io_demo/rose-meta/lfric-io_demo/HEAD/rose-meta.conf b/applications/io_demo/rose-meta/lfric-io_demo/HEAD/rose-meta.conf index 2b8c3d9ae..0b58b269f 100644 --- a/applications/io_demo/rose-meta/lfric-io_demo/HEAD/rose-meta.conf +++ b/applications/io_demo/rose-meta/lfric-io_demo/HEAD/rose-meta.conf @@ -1,5 +1,22 @@ import=lfric-driver/HEAD +[namelist:files] +compulsory=true +description=Configuration options for file reading and writing +help=Configuration options for file reading and writing +ns=namelist/Job/IO +sort-key=Section-A03 +title=Files + +[namelist:files=checkpoint_stem_name] +compulsory=true +description=Filename stem for checkpoint files +help=Where this app writes and reads checkpoint files. +ns=namelist/Job/IO/Checkpointing & Restart +sort-key=A-007 +!string_length=filename +type=character + [namelist:io_demo] compulsory=true description=Provides options for configuring the runtime behaviour of the IO_Demo app diff --git a/applications/io_demo/source/driver/init_io_demo_mod.F90 b/applications/io_demo/source/driver/init_io_demo_mod.F90 index 0be601260..1fcd50def 100644 --- a/applications/io_demo/source/driver/init_io_demo_mod.F90 +++ b/applications/io_demo/source/driver/init_io_demo_mod.F90 @@ -16,7 +16,7 @@ module init_io_demo_mod use driver_modeldb_mod, only : modeldb_type use field_collection_mod, only : field_collection_type use field_mod, only : field_type - use field_parent_mod, only : write_interface + use field_parent_mod, only : write_interface, read_interface use function_space_collection_mod, only : function_space_collection use function_space_mod, only : function_space_type use fs_continuity_mod, only : Wtheta @@ -25,6 +25,7 @@ module init_io_demo_mod LOG_LEVEL_TRACE, & LOG_LEVEL_ERROR use mesh_mod, only : mesh_type + use lfric_xios_read_mod, only : read_field_generic use lfric_xios_write_mod, only : write_field_generic use io_demo_constants_mod, only : create_io_demo_constants use random_number_generator_mod, only : random_number_generator_type @@ -53,7 +54,8 @@ subroutine init_io_demo(modeldb, mesh, chi, panel_id) type(random_number_generator_type), pointer :: rng type(field_type) :: diffusion_field type(field_collection_type), pointer :: depository - procedure(write_interface), pointer :: tmp_ptr + procedure(read_interface), pointer :: tmp_read_ptr + procedure(write_interface), pointer :: tmp_write_ptr real(kind=r_def), parameter :: min_val = 280.0_r_def real(kind=r_def), parameter :: max_val = 330.0_r_def @@ -89,11 +91,10 @@ subroutine init_io_demo(modeldb, mesh, chi, panel_id) fs => function_space_collection%get_fs(mesh, order_h, order_v, Wtheta) call diffusion_field%initialise(fs, name="diffusion_field") - ! Set up field with an IO behaviour (XIOS only at present) - if (write_diag .and. use_xios_io) then - tmp_ptr => write_field_generic - call diffusion_field%set_write_behaviour(tmp_ptr) - end if + tmp_read_ptr => read_field_generic + tmp_write_ptr => write_field_generic + call diffusion_field%set_read_behaviour(tmp_read_ptr) + call diffusion_field%set_write_behaviour(tmp_write_ptr) ! Add field to modeldb depository => modeldb%fields%get_field_collection("depository") diff --git a/applications/io_demo/source/driver/io_demo_checkpoint_mod.f90 b/applications/io_demo/source/driver/io_demo_checkpoint_mod.f90 new file mode 100644 index 000000000..4d9ef9c5b --- /dev/null +++ b/applications/io_demo/source/driver/io_demo_checkpoint_mod.f90 @@ -0,0 +1,109 @@ +!----------------------------------------------------------------------------- +! (c) Crown copyright Met Office. All rights reserved. +! The file LICENCE, distributed with this code, contains details of the terms +! under which the code may be used. +!----------------------------------------------------------------------------- +!> @brief Sets up checkpointing for the IO_demo app +!> @details Creates an IO context for checkpointing and adds the appropriate +!! files and fields to it +module io_demo_checkpoint_mod + + use constants_mod, only: i_def, str_max_filename + use driver_modeldb_mod, only: modeldb_type + use event_mod, only: event_action + use event_actor_mod, only: event_actor_type + use field_mod, only: field_type + use field_collection_mod, only: field_collection_type + use file_mod, only: FILE_MODE_WRITE, FILE_MODE_READ + use io_context_mod, only: io_context_type, callback_clock_arg + use linked_list_mod, only: linked_list_type + use lfric_xios_action_mod, only: advance + use lfric_xios_context_mod, only: lfric_xios_context_type + use lfric_xios_file_mod, only: lfric_xios_file_type, OPERATION_ONCE + use log_mod, only: log_event, LOG_LEVEL_DEBUG + + implicit none + + private + public :: setup_checkpoint_io + +contains + + !> @details Sets up checkpointing for the IO_demo app + !> @param[in,out] modeldb The model database + !> @param[in] chi The co-ordinate field + !> @param[in] panel_id The panel id field + subroutine setup_checkpoint_io(modeldb, chi, panel_id) + + type(modeldb_type), intent(inout) :: modeldb + type(field_type), intent(in) :: chi(:) + type(field_type), intent(in) :: panel_id + + type(lfric_xios_context_type) :: tmp_io_context + type(lfric_xios_context_type), pointer :: cp_context, io_context + type(linked_list_type), pointer :: file_list + type(field_collection_type), pointer :: checkpoint_fields + + class(event_actor_type), pointer :: event_actor_ptr + procedure(event_action), pointer :: context_advance + procedure(callback_clock_arg), pointer :: before_close + + character(len=str_max_filename) :: checkpoint_write_filename, checkpoint_read_filename + integer(i_def) :: ts_start, ts_end + + call log_event( 'io_demo: Setting up checkpoint I/O', LOG_LEVEL_DEBUG ) + + ts_start = modeldb%calendar%parse_instance(modeldb%config%time%timestep_start()) + ts_end = modeldb%calendar%parse_instance(modeldb%config%time%timestep_end()) + checkpoint_fields => modeldb%fields%get_field_collection("depository") + + call tmp_io_context%initialise( "checkpoint_context", start=ts_start, stop=ts_end ) + call modeldb%io_contexts%add_context(tmp_io_context) + + ! Get pointer to persistent context + call modeldb%io_contexts%get_io_context("checkpoint_context", cp_context) + file_list => cp_context%get_filelist() + + if (modeldb%config%io%checkpoint_write()) then + write(checkpoint_write_filename, '(A,I0)') & + trim(modeldb%config%files%checkpoint_stem_name()), ts_end + call file_list%insert_item( lfric_xios_file_type( checkpoint_write_filename, & + xios_id = "checkpoint_io_demo", & + io_mode = FILE_MODE_WRITE, & + freq = ts_end - ts_start + 1, & + operation = OPERATION_ONCE, & + fields_in_file = checkpoint_fields ) ) + end if + if (modeldb%config%io%checkpoint_read()) then + write(checkpoint_read_filename, '(A,I0)') & + trim(modeldb%config%files%checkpoint_stem_name()), ts_start - 1 + call file_list%insert_item( lfric_xios_file_type( checkpoint_read_filename, & + xios_id = "restart_io_demo", & + io_mode = FILE_MODE_READ, & + freq = 1, & + operation = OPERATION_ONCE, & + fields_in_file = checkpoint_fields ) ) + end if + + event_actor_ptr => cp_context + context_advance => advance + + before_close => null() + call cp_context%initialise_xios_context( modeldb%mpi%get_comm(), chi, panel_id, & + modeldb%clock, modeldb%calendar, before_close ) + + call modeldb%clock%add_event(context_advance, event_actor_ptr) + call cp_context%set_active(.true.) + + ! Set current context back to main + call modeldb%io_contexts%get_io_context("io_demo", io_context) + call io_context%set_current() + + nullify(cp_context) + nullify(file_list) + nullify(checkpoint_fields) + nullify(io_context) + + end subroutine setup_checkpoint_io + +end module io_demo_checkpoint_mod \ No newline at end of file diff --git a/applications/io_demo/source/driver/io_demo_driver_mod.f90 b/applications/io_demo/source/driver/io_demo_driver_mod.f90 index b3474a73a..312170eef 100644 --- a/applications/io_demo/source/driver/io_demo_driver_mod.f90 +++ b/applications/io_demo/source/driver/io_demo_driver_mod.f90 @@ -38,6 +38,7 @@ module io_demo_driver_mod use multifile_io_mod, only : init_multifile_io, step_multifile_io use io_benchmark_setup_mod, only : create_io_benchmark_fields, setup_io_benchmark_files use io_benchmark_step_mod, only : step_io_benchmark + use io_demo_checkpoint_mod, only : setup_checkpoint_io use io_demo_alg_mod, only : io_demo_alg use sci_field_minmax_alg_mod, only : log_field_minmax @@ -92,6 +93,8 @@ subroutine initialise(program_name, modeldb) logical :: check_partitions logical :: multifile_io logical :: io_benchmark + logical :: checkpoint_write + logical :: checkpoint_read integer(i_def), parameter :: one_layer = 1_i_def integer(i_def) :: i @@ -111,6 +114,10 @@ subroutine initialise(program_name, modeldb) scaled_radius = modeldb%config%planet%scaled_radius() multifile_io = modeldb%config%io_demo%multifile_io() io_benchmark = modeldb%config%io_demo%io_benchmark() + checkpoint_write = modeldb%config%io%checkpoint_write() + checkpoint_read = modeldb%config%io%checkpoint_read() + + ! Log the configuration !======================================================================= ! Mesh @@ -214,6 +221,13 @@ subroutine initialise(program_name, modeldb) call panel_id_inventory%get_field(mesh, panel_id) call init_io_demo(modeldb, mesh, chi, panel_id) + !======================================================================= + ! Set up checkpointing + !======================================================================= + if (checkpoint_write .or. checkpoint_read) then + call setup_checkpoint_io(modeldb, chi, panel_id) + end if + nullify(mesh, chi, panel_id) deallocate(base_mesh_names) diff --git a/components/lfric-xios/source/lfric_xios_context_mod.f90 b/components/lfric-xios/source/lfric_xios_context_mod.f90 index 9f951767d..f56c5f84e 100644 --- a/components/lfric-xios/source/lfric_xios_context_mod.f90 +++ b/components/lfric-xios/source/lfric_xios_context_mod.f90 @@ -185,8 +185,12 @@ subroutine finalise_xios_context( this ) type(lfric_xios_file_type), pointer :: file => null() integer(tik) :: timing_idlx, timing_idxc - if ( LPROF ) call start_timing(timing_idlx, 'lfric_xios.finalise_context') + if (this%xios_context_initialised) then + if ( LPROF ) call start_timing(timing_idlx, 'lfric_xios.finalise_context') + call log_event( 'Finalising XIOS context: ' // this%get_context_name(), LOG_LEVEL_DEBUG ) + call this%set_current() + ! Perform final write if (this%filelist%get_length() > 0) then loop => this%filelist%get_head() @@ -225,10 +229,10 @@ subroutine finalise_xios_context( this ) end do end if this%xios_context_initialised = .false. + if ( LPROF ) call stop_timing(timing_idlx, 'lfric_xios.finalise_context') end if nullify(loop) nullify(file) - if ( LPROF ) call stop_timing(timing_idlx, 'lfric_xios.finalise_context') end subroutine finalise_xios_context diff --git a/rose-stem/app/io_demo/rose-app.conf b/rose-stem/app/io_demo/rose-app.conf index 941e03c95..869faffae 100644 --- a/rose-stem/app/io_demo/rose-app.conf +++ b/rose-stem/app/io_demo/rose-app.conf @@ -18,6 +18,7 @@ mode=mkdir mode=auto source=namelist:base_mesh = namelist:extrusion + = namelist:files = namelist:finite_element = namelist:io = namelist:io_demo @@ -46,6 +47,9 @@ method='uniform' number_of_layers=10 planet_radius=6371229.0 +[namelist:files] +checkpoint_stem_name='$CYLC_SUITE_SHARE_DIR/data/restart-io_demo-$ROSE_TASK_NAME' + [namelist:finite_element] cellshape='quadrilateral' coord_order=1 diff --git a/rose-stem/site/common/io_demo/tasks_io_demo.cylc b/rose-stem/site/common/io_demo/tasks_io_demo.cylc index 56f78cbba..85fffef6a 100644 --- a/rose-stem/site/common/io_demo/tasks_io_demo.cylc +++ b/rose-stem/site/common/io_demo/tasks_io_demo.cylc @@ -13,6 +13,17 @@ "tsteps": 10, }) %} +{% elif task_ns.conf_name == "default-C24-CP" %} + + {% do task_dict.update({ + "opt_confs": ["default"], + "resolution": "C24", + "tsteps": 90, + "crun": 2, + "kgo_checks": [], + }) %} + + {% elif task_ns.conf_name == "multifile-C24" %} {% do task_dict.update({ diff --git a/rose-stem/site/meto/groups/group_io_demo.cylc b/rose-stem/site/meto/groups/group_io_demo.cylc index 39c59a254..df5150787 100644 --- a/rose-stem/site/meto/groups/group_io_demo.cylc +++ b/rose-stem/site/meto/groups/group_io_demo.cylc @@ -11,6 +11,8 @@ "io_demo_azspice_canned", "io_demo_default-C24_azspice_gnu_fast-debug-32bit", "io_demo_default-C24_azspice_gnu_full-debug-64bit", + "io_demo_default-C24-CP_azspice_gnu_fast-debug-32bit", + "io_demo_default-C24-CP_azspice_gnu_fast-debug-64bit", "io_demo_multifile-C24_azspice_gnu_fast-debug-64bit", "io_demo_multifile-C24_azspice_gnu_fast-debug-32bit", "io_demo_benchmark-C24_azspice_gnu_fast-debug-64bit", @@ -39,6 +41,8 @@ "io_demo_ex1a_canned", "io_demo_default-C24_ex1a_cce_fast-debug-32bit", "io_demo_default-C24_ex1a_cce_full-debug-64bit", + "io_demo_default-C24-CP_ex1a_cce_fast-debug-32bit", + "io_demo_default-C24-CP_ex1a_cce_fast-debug-64bit", "io_demo_multifile-C24_ex1a_cce_fast-debug-64bit", "io_demo_multifile-C24_ex1a_cce_fast-debug-32bit", "io_demo_multifile-C24_ex1a_gnu_fast-debug-64bit", diff --git a/rose-stem/templates/graph/populate_crun_graph.cylc b/rose-stem/templates/graph/populate_crun_graph.cylc index c77a415b6..738efe23d 100644 --- a/rose-stem/templates/graph/populate_crun_graph.cylc +++ b/rose-stem/templates/graph/populate_crun_graph.cylc @@ -60,7 +60,7 @@ application_build_task, crun_task]) %} {% do graph_sections.append([ - mesh_run_task, + mesh_run_tasks[0], crun_task]) %} {% else %} {# All other runs depend on the run previously #}