From 6f67d3394b6e4fccd0392da446db79dc8f82d992 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 26 Jun 2026 11:50:00 +0100 Subject: [PATCH 01/53] add additional extrusion --- .../lfric-lfric2lfric/HEAD/rose-meta.conf | 14 ++ .../lfric2lfric_infrastructure_mod.X90 | 156 +++++++++++++----- 2 files changed, 129 insertions(+), 41 deletions(-) diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf index dbe84fe41f..fbf7104840 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf @@ -290,3 +290,17 @@ help=The mesh can be used to perform a LFRic forecast (Dynamics), ns=namelist/lfric2lfric/configuration value-titles=Dynamics, Source, Destination values='dynamics', 'source', 'destination' + +[namelist:extrusion] +duplicate=true +!instance_key_member=mesh_type + +[namelist:extrusion=mesh_type] +compulsory=true +description=The purpose of the mesh +!enumeration=true +help=Is this vertical extrusion associated with the source or + =destination grids? +ns=namelist/lfric2lfric/configuration +value-titles=Source, Destination +values='source', 'destination' diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 83f7f6c1f8..2a5c73acf4 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -114,6 +114,9 @@ module lfric2lfric_infrastructure_mod character(len=*), public, parameter :: source_collection_name = "source_fields" character(len=*), public, parameter :: target_collection_name = "target_fields" + integer(kind=i_def), public, parameter :: dst = 1 ! destination mesh, destination extrusion + integer(kind=i_def), public, parameter :: src = 2 ! source mesh, source extrusion + contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -155,18 +158,21 @@ contains type(mesh_type), pointer :: orography_twod_mesh type(mesh_type), pointer :: orography_mesh - class(extrusion_type), allocatable :: extrusion + class(extrusion_type), allocatable :: extrusion_src + class(extrusion_type), allocatable :: extrusion_dst type(uniform_extrusion_type), allocatable :: extrusion_2d ! Pointers for namelists type(namelist_type), pointer :: planet_nml - type(namelist_type), pointer :: extrusion_nml + type(namelist_type), pointer :: src_extrusion_nml + type(namelist_type), pointer :: dst_extrusion_nml type(namelist_type), pointer :: lfric2lfric_nml type(namelist_type), pointer :: files_nml type(namelist_type), pointer :: finite_element_nml ! Namelist parameters character(len=str_def) :: mesh_names(2) + character(len=str_def), allocatable :: mesh_names_dst_ext(2) character(len=str_def), allocatable :: twod_names(:) character(len=str_def) :: start_dump_filename character(len=str_def) :: source_file_lbc @@ -181,16 +187,16 @@ contains integer(kind=i_def) :: element_order_h integer(kind=i_def) :: element_order_v - integer(kind=i_def) :: extrusion_method - integer(kind=i_def) :: number_of_layers - real(kind=r_def) :: domain_height + integer(kind=i_def) :: src_extrusion_method + integer(kind=i_def) :: dst_extrusion_method + integer(kind=i_def) :: src_number_of_layers + integer(kind=i_def) :: dst_number_of_layers + real(kind=r_def) :: src_domain_height + real(kind=r_def) :: dst_domain_height integer(kind=i_def) :: i integer(kind=i_def), parameter :: one_layer = 1_i_def - integer(kind=i_def), parameter :: dst = 1 - integer(kind=i_def), parameter :: src = 2 - type(coupling_type), pointer :: coupling_ptr type(field_collection_type), pointer :: cpl_snd_2d type(field_collection_type), pointer :: cpl_rcv_2d @@ -217,15 +223,21 @@ contains ! Extract namelist variables ! ------------------------------- planet_nml => modeldb%configuration%get_namelist('planet') - extrusion_nml => modeldb%configuration%get_namelist('extrusion') + src_extrusion_nml => modeldb%configuration%get_namelist('extrusion', & + 'source') + dst_extrusion_nml => modeldb%configuration%get_namelist('extrusion', & + 'destination') lfric2lfric_nml => modeldb%configuration%get_namelist('lfric2lfric') files_nml => modeldb%configuration%get_namelist('files') finite_element_nml => modeldb%configuration%get_namelist('finite_element') call planet_nml%get_value( 'scaled_radius', scaled_radius ) - call extrusion_nml%get_value( 'method', extrusion_method ) - call extrusion_nml%get_value( 'number_of_layers', number_of_layers ) - call extrusion_nml%get_value( 'domain_height', domain_height ) + call src_extrusion_nml%get_value( 'method', src_extrusion_method ) + call src_extrusion_nml%get_value( 'number_of_layers', src_number_of_layers ) + call src_extrusion_nml%get_value( 'domain_height', src_domain_height ) + call dst_extrusion_nml%get_value( 'method', dst_extrusion_method ) + call dst_extrusion_nml%get_value( 'number_of_layers', dst_number_of_layers ) + call dst_extrusion_nml%get_value( 'domain_height', dst_domain_height ) ! Check lfric2lfric configuration settings are allowed call lfric2lfric_check_configuration( lfric2lfric_nml ) @@ -259,57 +271,109 @@ contains log_level_error) end select - select case (extrusion_method) + select case (src_extrusion_method) case (method_uniform, method_quadratic, method_geometric) - allocate( extrusion, source=create_extrusion( & - extrusion_method, domain_height, & - domain_bottom, number_of_layers, & - prime_extrusion ) ) + allocate( src_extrusion, source=create_extrusion( & + src_extrusion_method, src_domain_height, & + domain_bottom, src_number_of_layers, & + prime_extrusion ) ) case (method_dcmip) - allocate( extrusion, source=dcmip_extrusion_type( & - domain_bottom, domain_height, & - number_of_layers, prime_extrusion ) ) + allocate( src_extrusion, source=dcmip_extrusion_type( & + domain_bottom, src_domain_height, & + src_number_of_layers, prime_extrusion ) ) case (method_um_L38_29t_9s_40km) - allocate( extrusion, source=um_l38_29t_9s_40km_extrusion_type( & - domain_bottom, domain_height, & - number_of_layers, prime_extrusion ) ) + allocate( src_extrusion, source=um_l38_29t_9s_40km_extrusion_type( & + domain_bottom, src_domain_height, & + src_number_of_layers, prime_extrusion ) ) case (method_um_L85_50t_35s_85km) - allocate( extrusion, source=um_l85_50t_35s_85km_extrusion_type( & - domain_bottom, domain_height, & - number_of_layers, prime_extrusion ) ) + allocate( src_extrusion, source=um_l85_50t_35s_85km_extrusion_type( & + domain_bottom, src_domain_height, & + src_number_of_layers, prime_extrusion ) ) case (method_um_L70_50t_20s_80km) - allocate( extrusion, source=um_l70_50t_20s_80km_extrusion_type( & - domain_bottom, domain_height, & - number_of_layers, prime_extrusion ) ) + allocate( src_extrusion, source=um_l70_50t_20s_80km_extrusion_type( & + domain_bottom, src_domain_height, & + src_number_of_layers, prime_extrusion ) ) case (method_um_L70_61t_9s_40km) - allocate( extrusion, source=um_l70_61t_9s_40km_extrusion_type( & - domain_bottom, domain_height, & - number_of_layers, prime_extrusion ) ) + allocate( src_extrusion, source=um_l70_61t_9s_40km_extrusion_type( & + domain_bottom, src_domain_height, & + src_number_of_layers, prime_extrusion ) ) case (method_um_L120_99t_21s_40km) - allocate( extrusion, source=um_L120_99t_21s_40km_extrusion_type( & - domain_bottom, domain_height, & - number_of_layers, prime_extrusion ) ) + allocate( src_extrusion, source=um_L120_99t_21s_40km_extrusion_type( & + domain_bottom, src_domain_height, & + src_number_of_layers, prime_extrusion ) ) case (method_um_L140_122t_18s_40km) - allocate( extrusion, source=um_L140_122t_18s_40km_extrusion_type(& - domain_bottom, domain_height, & - number_of_layers, prime_extrusion ) ) + allocate( src_extrusion, source=um_L140_122t_18s_40km_extrusion_type( & + domain_bottom, src_domain_height, & + src_number_of_layers, prime_extrusion ) ) case default write( log_scratch_space, '(A)' ) & "lfric2lfric_infrastructure_mod" // & - ': Unrecognised extrusion method: ' // & - trim(key_from_method( extrusion_method )) + ': Unrecognised source extrusion method: ' // & + trim(key_from_method( src_extrusion_method )) call log_event( log_scratch_space, log_level_error ) end select + select case (dst_extrusion_method) + case (method_uniform, method_quadratic, method_geometric) + allocate( dst_extrusion, source=create_extrusion( & + dst_extrusion_method, dst_domain_height, & + domain_bottom, dst_number_of_layers, & + prime_extrusion ) ) + + case (method_dcmip) + allocate( dst_extrusion, source=dcmip_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L38_29t_9s_40km) + allocate( dst_extrusion, source=um_l38_29t_9s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L85_50t_35s_85km) + allocate( dst_extrusion, source=um_l85_50t_35s_85km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L70_50t_20s_80km) + allocate( dst_extrusion, source=um_l70_50t_20s_80km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L70_61t_9s_40km) + allocate( dst_extrusion, source=um_l70_61t_9s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L120_99t_21s_40km) + allocate( dst_extrusion, source=um_L120_99t_21s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L140_122t_18s_40km) + allocate( dst_extrusion, source=um_L140_122t_18s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case default + write( log_scratch_space, '(A)' ) & + "lfric2lfric_infrastructure_mod" // & + ': Unrecognised destination extrusion method: ' // & + trim(key_from_method( dst_extrusion_method )) + call log_event( log_scratch_space, log_level_error ) + + end select + + extrusion_2d = uniform_extrusion_type( domain_bottom, & domain_bottom, & one_layer, twod ) @@ -321,8 +385,18 @@ contains call init_mesh( modeldb%configuration, & modeldb%mpi%get_comm_rank(), & modeldb%mpi%get_comm_size(), & - mesh_names, extrusion, & + mesh_names, & + src_extrusion, & stencil_depth, regrid_method ) + + ! If dst extrusion is different to src extrusion + allocate( mesh_names_dst_ext, source=mesh_names ) + do i=1, size(mesh_names) + mesh_names_dst_ext(i) = trim(mesh_names(i))//'_dst_ext' + end do + call create_mesh( mesh_names, & + dst_extrusion, & + alt_name=mesh_names_dst_ext ) allocate( twod_names, source=mesh_names ) do i=1, size(twod_names) From 9b047e309cfe4ec342dc50cbdbf80d96677455fa Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:17:02 +0100 Subject: [PATCH 02/53] change_of_extrusion logical --- .../lfric2lfric_infrastructure_mod.X90 | 131 ++++++++++-------- 1 file changed, 71 insertions(+), 60 deletions(-) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 2a5c73acf4..ee2260bf65 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -158,8 +158,8 @@ contains type(mesh_type), pointer :: orography_twod_mesh type(mesh_type), pointer :: orography_mesh - class(extrusion_type), allocatable :: extrusion_src - class(extrusion_type), allocatable :: extrusion_dst + class(extrusion_type), allocatable :: src_extrusion + class(extrusion_type), allocatable :: dst_extrusion type(uniform_extrusion_type), allocatable :: extrusion_2d ! Pointers for namelists @@ -204,6 +204,7 @@ contains type(coupler_exchange_2d_type) :: coupler_exchange_2d integer(kind=i_def) :: ierror logical(kind=l_def) :: is_running + logical(kind=l_def) :: extrusion_change !------------------------ ! XIOS contexts @@ -239,6 +240,11 @@ contains call dst_extrusion_nml%get_value( 'number_of_layers', dst_number_of_layers ) call dst_extrusion_nml%get_value( 'domain_height', dst_domain_height ) + extrusion_change=.false. + if ( src_extrusion_method \= dst_extrusion_method ) then extrusion_change=.true. + if ( src_number_of_layers \= dst_number_of_layers ) then extrusion_change=.true. + if ( src_domain_height \= dst_domain_height ) then extrusion_change=.true. + ! Check lfric2lfric configuration settings are allowed call lfric2lfric_check_configuration( lfric2lfric_nml ) @@ -322,57 +328,60 @@ contains end select - select case (dst_extrusion_method) - case (method_uniform, method_quadratic, method_geometric) - allocate( dst_extrusion, source=create_extrusion( & - dst_extrusion_method, dst_domain_height, & - domain_bottom, dst_number_of_layers, & - prime_extrusion ) ) - - case (method_dcmip) - allocate( dst_extrusion, source=dcmip_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L38_29t_9s_40km) - allocate( dst_extrusion, source=um_l38_29t_9s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L85_50t_35s_85km) - allocate( dst_extrusion, source=um_l85_50t_35s_85km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L70_50t_20s_80km) - allocate( dst_extrusion, source=um_l70_50t_20s_80km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L70_61t_9s_40km) - allocate( dst_extrusion, source=um_l70_61t_9s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L120_99t_21s_40km) - allocate( dst_extrusion, source=um_L120_99t_21s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L140_122t_18s_40km) - allocate( dst_extrusion, source=um_L140_122t_18s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case default - write( log_scratch_space, '(A)' ) & - "lfric2lfric_infrastructure_mod" // & - ': Unrecognised destination extrusion method: ' // & - trim(key_from_method( dst_extrusion_method )) - call log_event( log_scratch_space, log_level_error ) - - end select + if (extrusion_change) then + + select case (dst_extrusion_method) + case (method_uniform, method_quadratic, method_geometric) + allocate( dst_extrusion, source=create_extrusion( & + dst_extrusion_method, dst_domain_height, & + domain_bottom, dst_number_of_layers, & + prime_extrusion ) ) + + case (method_dcmip) + allocate( dst_extrusion, source=dcmip_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L38_29t_9s_40km) + allocate( dst_extrusion, source=um_l38_29t_9s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L85_50t_35s_85km) + allocate( dst_extrusion, source=um_l85_50t_35s_85km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L70_50t_20s_80km) + allocate( dst_extrusion, source=um_l70_50t_20s_80km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L70_61t_9s_40km) + allocate( dst_extrusion, source=um_l70_61t_9s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L120_99t_21s_40km) + allocate( dst_extrusion, source=um_L120_99t_21s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case (method_um_L140_122t_18s_40km) + allocate( dst_extrusion, source=um_L140_122t_18s_40km_extrusion_type( & + domain_bottom, dst_domain_height, & + dst_number_of_layers, prime_extrusion ) ) + + case default + write( log_scratch_space, '(A)' ) & + "lfric2lfric_infrastructure_mod" // & + ': Unrecognised destination extrusion method: ' // & + trim(key_from_method( dst_extrusion_method )) + call log_event( log_scratch_space, log_level_error ) + + end select + end if extrusion_2d = uniform_extrusion_type( domain_bottom, & domain_bottom, & @@ -390,14 +399,16 @@ contains stencil_depth, regrid_method ) ! If dst extrusion is different to src extrusion - allocate( mesh_names_dst_ext, source=mesh_names ) - do i=1, size(mesh_names) - mesh_names_dst_ext(i) = trim(mesh_names(i))//'_dst_ext' - end do - call create_mesh( mesh_names, & - dst_extrusion, & - alt_name=mesh_names_dst_ext ) - + if (extrusion_change) then + allocate( mesh_names_dst_ext, source=mesh_names ) + do i=1, size(mesh_names) + mesh_names_dst_ext(i) = trim(mesh_names(i))//'_dst_ext' + end do + call create_mesh( mesh_names, & + dst_extrusion, & + alt_name=mesh_names_dst_ext ) + end if + allocate( twod_names, source=mesh_names ) do i=1, size(twod_names) twod_names(i) = trim(twod_names(i))//'_2d' From 479df9341cc1cb25d9e8c02b9fecdf462d87b811 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 29 Jun 2026 09:02:25 +0100 Subject: [PATCH 03/53] logicals --- .../lfric2lfric_infrastructure_mod.X90 | 58 +++++++++++++------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index ee2260bf65..dd07d8d36d 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -204,8 +204,9 @@ contains type(coupler_exchange_2d_type) :: coupler_exchange_2d integer(kind=i_def) :: ierror logical(kind=l_def) :: is_running - logical(kind=l_def) :: extrusion_change - + logical(kind=l_def) :: vertical_change + logical(kind=l_def) :: horizontal_change + !------------------------ ! XIOS contexts !------------------------ @@ -240,11 +241,6 @@ contains call dst_extrusion_nml%get_value( 'number_of_layers', dst_number_of_layers ) call dst_extrusion_nml%get_value( 'domain_height', dst_domain_height ) - extrusion_change=.false. - if ( src_extrusion_method \= dst_extrusion_method ) then extrusion_change=.true. - if ( src_number_of_layers \= dst_number_of_layers ) then extrusion_change=.true. - if ( src_domain_height \= dst_domain_height ) then extrusion_change=.true. - ! Check lfric2lfric configuration settings are allowed call lfric2lfric_check_configuration( lfric2lfric_nml ) @@ -259,6 +255,14 @@ contains call finite_element_nml%get_value( 'element_order_h', element_order_h) call finite_element_nml%get_value( 'element_order_v', element_order_v) + vertical_change = .false. + if ( src_extrusion_method \= dst_extrusion_method ) then vertical_change = .true. + if ( src_number_of_layers \= dst_number_of_layers ) then vertical_change = .true. + if ( src_domain_height \= dst_domain_height ) then vertical_change = .true. + + horizontal_change = .false. + if ( mesh_names(dst) \= mesh_names(src) ) then horizontal_change = .true. + !======================================================================= ! Mesh !======================================================================= @@ -328,7 +332,7 @@ contains end select - if (extrusion_change) then + if (vertical_change) then select case (dst_extrusion_method) case (method_uniform, method_quadratic, method_geometric) @@ -398,8 +402,7 @@ contains src_extrusion, & stencil_depth, regrid_method ) - ! If dst extrusion is different to src extrusion - if (extrusion_change) then + if (vertical_change) then allocate( mesh_names_dst_ext, source=mesh_names ) do i=1, size(mesh_names) mesh_names_dst_ext(i) = trim(mesh_names(i))//'_dst_ext' @@ -432,9 +435,19 @@ contains !----------------------------------------------------------------------- mesh_src => mesh_collection%get_mesh(trim(mesh_names(src))) twod_mesh_src => mesh_collection%get_mesh(trim(twod_names(src))) - mesh_dst => mesh_collection%get_mesh(trim(mesh_names(dst))) - twod_mesh_dst => mesh_collection%get_mesh(trim(twod_names(dst))) + if (vertical_change) then + mesh_dst => mesh_collection%get_mesh(trim(mesh_names_dst_ext(dst))) + twod_mesh_dst => mesh_collection%get_mesh(trim(twod_names(dst))) + else + mesh_dst => mesh_collection%get_mesh(trim(mesh_names(dst))) + twod_mesh_dst => mesh_collection%get_mesh(trim(twod_names(dst))) + end if + + if (vertical_change and horizontal_change) then + mesh_inter => mesh_collection%get_mesh(trim(mesh_names_dst(dst))) + end if + ! Log this change call log_event('Source mesh set to: ' // mesh_names(src), & log_level_debug) @@ -456,12 +469,21 @@ contains files_init_ptr => init_lfric2lfric_dst_files ! Initialise the IO context with all the required info - call init_io( context_dst, & - mesh_names(dst), & - modeldb, & - chi_inventory, & - panel_id_inventory, & - populate_filelist=files_init_ptr ) + if (vertical_change) then + call init_io( context_dst, & + mesh_names_dst_ext(dst), & + modeldb, & + chi_inventory, & + panel_id_inventory, & + populate_filelist=files_init_ptr ) + else + call init_io( context_dst, & + mesh_names(dst), & + modeldb, & + chi_inventory, & + panel_id_inventory, & + populate_filelist=files_init_ptr ) + end if call modeldb%io_contexts%get_io_context(context_dst, io_context_dst) From f81bfc90c1e3d77286f4c97e6f76fb635d07a217 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:12:27 +0100 Subject: [PATCH 04/53] More mesh extrusions and regridding infrastructure --- .../source/algorithm/lfric2lfric_vert_mod.x90 | 55 ++++++++ .../source/driver/lfric2lfric_driver_mod.F90 | 68 +++++++++- .../source/driver/lfric2lfric_init_mod.f90 | 53 ++++++-- .../lfric2lfric_infrastructure_mod.X90 | 120 ++++++++++-------- 4 files changed, 231 insertions(+), 65 deletions(-) create mode 100644 applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 new file mode 100644 index 0000000000..c06d0c5c6f --- /dev/null +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -0,0 +1,55 @@ +module lfric2lfric_vert_mod + + use field_parent_mod, only: field_parent_type + use field_mod, only: field_type + use field_collection_mod, only: field_collection_type + use field_collection_iterator_mod, only: & + field_collection_iterator_type + use log_mod, only: log_event, & + log_level_info, & + log_scratch_space + + implicit none + + private + public :: lfric2lfric_vert + +contains + + subroutine lfric2lfric_vert( source_fields, target_fields ) + + implicit none + + type(field_collection_type), intent(inout) :: source_fields + type(field_collection_type), intent(inout) :: target_fields + + type(field_collection_iterator_type) :: iter + + class(field_parent_type), pointer :: field => null() + type(field_type), pointer :: field_src => null() + type(field_type), pointer :: field_dst => null() + + character(len=str_def) :: field_name + + ! Main loop over fields to be processed + call iter%initialise(source_fields) + do + ! Locate the field to be processed in the field collections + if ( .not.iter%has_next() ) exit + field => iter%next() + field_name = field%get_name() + + call source_fields%get_field(field_name, field_src) + call target_fields%get_field(field_name, field_dst) + + write(log_scratch_space, '(A,A)') "Processing lfric field ", & + trim(field_name) + call log_event(log_scratch_space, log_level_info) + ! Dummy initialisation - to be replaced with actual + ! vertical regridding + call setval_X(field_dst, 1.0_r_def) + enddo + + end subroutine lfric2lfric_vert + +end module lfric2lfric_vert_mod diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index e02dd55801..b33b0297d5 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -34,8 +34,10 @@ module lfric2lfric_driver_mod use lfric2lfric_infrastructure_mod, only: initialise_infrastructure, & context_dst, context_src, & source_collection_name, & - target_collection_name + target_collection_name, & + interm_collection_name use lfric2lfric_regrid_mod, only: lfric2lfric_regrid + use lfric2lfric_vert_mod, only: lfric2lfric_vert implicit none @@ -92,6 +94,8 @@ subroutine run( modeldb, oasis_clock ) ! Local parameters type(namelist_type), pointer :: files_nml type(namelist_type), pointer :: lfric2lfric_nml + type(namelist_type), pointer :: src_extrusion_nml + type(namelist_type), pointer :: dst_extrusion_nml integer(kind=i_def) :: step, time_steps logical(kind=l_def) :: is_running @@ -101,32 +105,79 @@ subroutine run( modeldb, oasis_clock ) type(field_collection_type), pointer :: source_fields type(field_collection_type), pointer :: target_fields + type(field_collection_type), pointer :: interm_fields type(lfric_xios_context_type), pointer :: io_context + character(len=str_def) :: mesh_names(2) + integer(kind=i_def) :: src_extrusion_method + integer(kind=i_def) :: dst_extrusion_method + integer(kind=i_def) :: src_number_of_layers + integer(kind=i_def) :: dst_number_of_layers + real(kind=r_def) :: src_domain_height + real(kind=r_def) :: dst_domain_height + ! Namelist pointers files_nml => modeldb%configuration%get_namelist('files') lfric2lfric_nml => modeldb%configuration%get_namelist('lfric2lfric') + src_extrusion_nml => modeldb%configuration%get_namelist('extrusion', & + 'source') + dst_extrusion_nml => modeldb%configuration%get_namelist('extrusion', & + 'destination') ! Extract configuration variables call files_nml%get_value( 'start_dump_filename', start_dump_filename ) call files_nml%get_value( 'checkpoint_stem_name', checkpoint_stem_name ) call lfric2lfric_nml%get_value( 'mode', mode ) call lfric2lfric_nml%get_value( 'regrid_method', regrid_method ) + + call lfric2lfric_nml%get_value( 'destination_mesh_name', & + mesh_names(dst) ) + call lfric2lfric_nml%get_value( 'source_mesh_name', & + mesh_names(src) ) + call src_extrusion_nml%get_value( 'method', src_extrusion_method ) + call src_extrusion_nml%get_value( 'number_of_layers', src_number_of_layers ) + call src_extrusion_nml%get_value( 'domain_height', src_domain_height ) + call dst_extrusion_nml%get_value( 'method', dst_extrusion_method ) + call dst_extrusion_nml%get_value( 'number_of_layers', dst_number_of_layers ) + call dst_extrusion_nml%get_value( 'domain_height', dst_domain_height ) + + vertical_change = .false. + if ( src_extrusion_method \= dst_extrusion_method ) then vertical_change = .true. + if ( src_number_of_layers \= dst_number_of_layers ) then vertical_change = .true. + if ( src_domain_height \= dst_domain_height ) then vertical_change = .true. + + horizontal_change = .false. + if ( mesh_names(dst) \= mesh_names(src) ) then horizontal_change = .true. ! Point to source and target field collections source_fields => modeldb%fields%get_field_collection(source_collection_name) target_fields => modeldb%fields%get_field_collection(target_collection_name) + if (horizontal_change .and. vertical_change) then + interm_fields => modeldb%fields%get_field_collection(intermediate_collection_name) + + else if (horizontal_change .and. .not. vertical_change) then + interm_fields => modeldb%fields%get_field_collection(target_collection_name) + + else if (vertical_change .and. .not. horizontal_change) then + interm_fields => modeldb%fields%get_field_collection(source_collection_name) + end if + ! Read fields and perform the regridding if (mode == mode_ics) then call read_checkpoint(source_fields, & start_timestep, & start_dump_filename ) - call lfric2lfric_regrid(modeldb, oasis_clock, source_fields, & - target_fields, regrid_method) - + if (horizontal_change) then + call lfric2lfric_regrid(modeldb, oasis_clock, source_fields, & + interm_fields, regrid_method) + end if + if (vertical_change) then + call lfric2lfric_vert(interm_fields, target_fields) + end if + ! Write output call modeldb%io_contexts%get_io_context(context_dst, io_context) call io_context%set_current() @@ -148,8 +199,13 @@ subroutine run( modeldb, oasis_clock ) call read_state(source_fields) - call lfric2lfric_regrid(modeldb, oasis_clock, source_fields, & - target_fields, regrid_method) + if (horizontal_change) then + call lfric2lfric_regrid(modeldb, oasis_clock, source_fields, & + interm_fields, regrid_method) + end if + if (vertical_change) then + call lfric2lfric_vert(interm_fields, target_fields) + end if is_running = modeldb%clock%tick() diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index ab2a73b094..43a0c05c7a 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -40,17 +40,25 @@ module lfric2lfric_init_mod !! will hold the file to be written !> @param [in] start_dump_filename File to get field names from !> @param [in] mode Process ics or lbcs + !> @param [in] horizontal_change Logical for horizontal regridding + !> @param [in] vertical_change Logical for vertical regridding !> @param [in] origin_collection_name Holds the origin fields !> @param [in] origin_mesh Mesh to initialise 3D fields !> @param [in] origin_twod_mesh Mesh to initialise 2D fields + !> @param [in] interm_collection_name Holds the intermediate fields + !> @param [in] interm_mesh Mesh for intermediate 3D fields + !> @param [in] interm_twod_mesh Mesh for intermediate 2D fields !> @param [in] target_collection_name Holds target fields !> @param [in] target_mesh Mesh for target 3D fields !> @param [in] target_twod_mesh Mesh for target 2D fields - subroutine init_lfric2lfric( modeldb, context_src, context_dst, & - start_dump_filename, mode, & - origin_collection_name, & - origin_mesh, origin_twod_mesh, & - target_collection_name, & + subroutine init_lfric2lfric( modeldb, context_src, context_dst, & + start_dump_filename, mode, & + horizontal_change, vertical_change, & + origin_collection_name, & + origin_mesh, origin_twod_mesh, & + interm_collection_name, & + interm_mesh, interm_twod_mesh, & + target_collection_name, & target_mesh, target_twod_mesh ) implicit none @@ -60,10 +68,14 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & character(len=*), intent(in) :: context_dst character(len=*), intent(in) :: start_dump_filename integer(i_def), intent(in) :: mode + logical(l_def), intent(in) :: horizontal_change + logical(l_def), intent(in) :: vertical_change character(len=*), intent(in) :: origin_collection_name type(mesh_type), intent(in), pointer :: origin_mesh type(mesh_type), intent(in), pointer :: origin_twod_mesh - ! Optionals + character(len=*), intent(in) :: interm_collection_name + type(mesh_type), intent(in), pointer :: interm_mesh + type(mesh_type), intent(in), pointer :: interm_twod_mesh character(len=*), intent(in) :: target_collection_name type(mesh_type), intent(in), pointer :: target_mesh type(mesh_type), intent(in), pointer :: target_twod_mesh @@ -116,9 +128,6 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & field_collection => & modeldb%fields%get_field_collection(target_collection_name) - call modeldb%io_contexts%get_io_context(context_dst, io_context) - call io_context%set_current() - if (mode == mode_ics) then prefix = 'checkpoint_' else if (mode == mode_lbc) then @@ -133,9 +142,35 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & prefix ) end do + !-------------------------------------------------------------------------- + ! Initialise Intermediate Fields + !-------------------------------------------------------------------------- + if (horizontal_change .and. vertical_change) then + call modeldb%fields%add_empty_field_collection(interm_collection_name) + field_collection => & + modeldb%fields%get_field_collection(interm_collection_name) + + if (mode == mode_ics) then + prefix = 'checkpoint_' + else if (mode == mode_lbc) then + prefix = 'lbc_' + end if + + do i = 1, num_fields + call field_maker( field_collection, & + config_list(i), & + interm_mesh, & + interm_twod_mesh, & + prefix ) + end do + end if + call modeldb%io_contexts%get_io_context(context_src, io_context) call io_context%set_current() + call modeldb%io_contexts%get_io_context(context_dst, io_context) + call io_context%set_current() + ! Now finished with config_list, deallocate deallocate(config_list) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index dd07d8d36d..a0b449c716 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -113,6 +113,7 @@ module lfric2lfric_infrastructure_mod ! Source and destination field collection names character(len=*), public, parameter :: source_collection_name = "source_fields" character(len=*), public, parameter :: target_collection_name = "target_fields" + character(len=*), public, parameter :: interm_collection_name = "intermediate_fields" integer(kind=i_def), public, parameter :: dst = 1 ! destination mesh, destination extrusion integer(kind=i_def), public, parameter :: src = 2 ! source mesh, source extrusion @@ -155,8 +156,11 @@ contains type(mesh_type), pointer :: twod_mesh_src type(mesh_type), pointer :: mesh_dst type(mesh_type), pointer :: twod_mesh_dst - type(mesh_type), pointer :: orography_twod_mesh - type(mesh_type), pointer :: orography_mesh + type(mesh_type), pointer :: mesh_interm + type(mesh_type), pointer :: orography_twod_mesh_src + type(mesh_type), pointer :: orography_mesh_src + type(mesh_type), pointer :: orography_twod_mesh_dst + type(mesh_type), pointer :: orography_mesh_dst class(extrusion_type), allocatable :: src_extrusion class(extrusion_type), allocatable :: dst_extrusion @@ -402,14 +406,20 @@ contains src_extrusion, & stencil_depth, regrid_method ) + + allocate( mesh_names_dst_ext, source=mesh_names ) + if (vertical_change) then - allocate( mesh_names_dst_ext, source=mesh_names ) do i=1, size(mesh_names) mesh_names_dst_ext(i) = trim(mesh_names(i))//'_dst_ext' end do call create_mesh( mesh_names, & dst_extrusion, & alt_name=mesh_names_dst_ext ) + else + do i=1, size(mesh_names) + mesh_names_dst_ext(i) = trim(mesh_names(i)) + end do end if allocate( twod_names, source=mesh_names ) @@ -433,30 +443,36 @@ contains !----------------------------------------------------------------------- ! Assign pointers to the correct meshes !----------------------------------------------------------------------- + ! If the source extrusion is the same as the destination extrusion, + ! mesh_dst = mesh_interm and only horizontal interpolation is applied. + ! + ! If the source mesh is the same as the destination mesh, + ! mesh_src = mesh_interm and only vertical interpolation is applied. + ! + ! The source meshes mesh_src => mesh_collection%get_mesh(trim(mesh_names(src))) twod_mesh_src => mesh_collection%get_mesh(trim(twod_names(src))) - if (vertical_change) then - mesh_dst => mesh_collection%get_mesh(trim(mesh_names_dst_ext(dst))) - twod_mesh_dst => mesh_collection%get_mesh(trim(twod_names(dst))) - else - mesh_dst => mesh_collection%get_mesh(trim(mesh_names(dst))) - twod_mesh_dst => mesh_collection%get_mesh(trim(twod_names(dst))) - end if + ! The interim mesh (horizontal interpolation of mesh_names(src) + ! to mesh_names(dst)) + mesh_interm => mesh_collection%get_mesh(trim(mesh_names(dst))) - if (vertical_change and horizontal_change) then - mesh_inter => mesh_collection%get_mesh(trim(mesh_names_dst(dst))) - end if - + ! The destination mesh (vertical interpolation of mesh_names(dst) to + ! mesh_names_dst_ext(dst) + mesh_dst => mesh_collection%get_mesh(trim(mesh_names_dst_ext(dst))) + twod_mesh_dst => mesh_collection%get_mesh(trim(twod_names(dst))) + ! Log this change call log_event('Source mesh set to: ' // mesh_names(src), & log_level_debug) call log_event('Source 2D mesh set to: ' // twod_names(src), & log_level_debug) - call log_event('Destination mesh set to: ' // mesh_names(dst), & + call log_event('Destination mesh set to: ' // mesh_names_dst_ext(dst), & log_level_debug) call log_event('Destination 2D mesh set to: ' // twod_names(dst), & log_level_debug) + call log_event('Intermediate mesh set to: ' // mesh_names(dst), & + log_level_debug) !======================================================================= ! Setup I/O system @@ -469,21 +485,13 @@ contains files_init_ptr => init_lfric2lfric_dst_files ! Initialise the IO context with all the required info - if (vertical_change) then - call init_io( context_dst, & - mesh_names_dst_ext(dst), & - modeldb, & - chi_inventory, & - panel_id_inventory, & - populate_filelist=files_init_ptr ) - else - call init_io( context_dst, & - mesh_names(dst), & - modeldb, & - chi_inventory, & - panel_id_inventory, & - populate_filelist=files_init_ptr ) - end if + call init_io( context_dst, & + mesh_names_dst_ext(dst), & + modeldb, & + chi_inventory, & + panel_id_inventory, & + populate_filelist=files_init_ptr ) + call modeldb%io_contexts%get_io_context(context_dst, io_context_dst) @@ -511,11 +519,11 @@ contains halo_depth = twod_mesh_dst%get_halo_depth()) ! Get pointers to the destination mesh: - orography_mesh => mesh_collection%get_mesh(mesh_names(dst)) - orography_twod_mesh => mesh_collection%get_mesh(orography_mesh, TWOD) + orography_mesh_dst => mesh_collection%get_mesh(mesh_names(dst)) + orography_twod_mesh_dst => mesh_collection%get_mesh(orography_mesh, TWOD) ! Set up surface altitude field - this will be used to generate orography - call init_altitude( orography_twod_mesh, surface_altitude_dst ) + call init_altitude( orography_twod_mesh_dst, surface_altitude_dst ) end if !----------------------------------------------------------------------- @@ -554,35 +562,39 @@ contains orog_init_option == orog_init_option_start_dump ) then ! Get pointers to the source mesh: - orography_mesh => mesh_collection%get_mesh(mesh_names(src)) - orography_twod_mesh => mesh_collection%get_mesh(orography_mesh, TWOD) + orography_mesh_src => mesh_collection%get_mesh(mesh_names(src)) + orography_twod_mesh_src => mesh_collection%get_mesh(orography_mesh, TWOD) call surface_altitude_src%initialise(vector_space, & name='surface_altitude_src', & halo_depth = twod_mesh_src%get_halo_depth()) ! Set up surface altitude field - this will be used to generate orography - call init_altitude( orography_twod_mesh, surface_altitude_src ) + call init_altitude( orography_twod_mesh_src, surface_altitude_src ) end if !======================================================================= ! Create and initialise prognostic fields !======================================================================= if (mode == mode_ics) then - call init_lfric2lfric( modeldb, context_src, context_dst, & - start_dump_filename, mode, & - source_collection_name, mesh_src, twod_mesh_src, & - target_collection_name, mesh_dst, twod_mesh_dst ) + call init_lfric2lfric( modeldb, context_src, context_dst, & + start_dump_filename, mode, & + horizontal_change, vertical_change, & + source_collection_name, mesh_src, twod_mesh_src, & + interm_collection_name, mesh_interm, twod_mesh_dst, & + target_collection_name, mesh_dst, twod_mesh_dst ) else if (mode == mode_lbc) then call lfric2lfric_nml%get_value( 'source_file_lbc', source_file_lbc ) - call init_lfric2lfric( modeldb, context_src, context_dst, & - source_file_lbc, mode, & - source_collection_name, mesh_src, twod_mesh_src, & - target_collection_name, mesh_dst, twod_mesh_dst ) + call init_lfric2lfric( modeldb, context_src, context_dst, & + source_file_lbc, mode, & + horizontal_change, vertical_change, & + source_collection_name, mesh_src, twod_mesh_src, & + interm_collection_name, mesh_interm, twod_mesh_dst, & + target_collection_name, mesh_dst, twod_mesh_dst ) end if !======================================================================= - ! Initialize variables for each regrid method + ! Initialize variables for each horizontal regrid method !======================================================================= select case (regrid_method) case (regrid_method_map) @@ -613,7 +625,7 @@ contains call log_event( log_scratch_space, log_level_error ) #endif end select - + !======================================================================= ! The lateral boundary conditions of limited-area models (LAMs) are ! implemented by updating the data values at the boundaries with values @@ -671,10 +683,18 @@ contains call blend_orography(surface_altitude_dst, surface_altitude_src_on_dst, & mesh_names(dst)) - call setup_orography_alg( mesh_names(dst:dst), & - orography_mesh%get_mesh_name(), & - chi_inventory, & - panel_id_inventory, & + ! Adjust the chi fields to account for the orography + ! -------------------------------------------------------- + call setup_orography_alg( mesh_names(src), & + orography_mesh_src%get_mesh_name(), & + chi_inventory, & + panel_id_inventory, & + surface_altitude_src ) + + call setup_orography_alg( mesh_names_dst_ext(dst), & + orography_mesh_dst%get_mesh_name(), & + chi_inventory, & + panel_id_inventory, & surface_altitude_dst ) end if From a2d157ada4632ec56614f2429fa409704bdf0bbc Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 1 Jul 2026 14:54:10 +0100 Subject: [PATCH 05/53] local build completes --- .../source/algorithm/lfric2lfric_vert_mod.x90 | 3 +- .../source/driver/lfric2lfric_driver_mod.F90 | 26 +++++++++++----- .../source/driver/lfric2lfric_init_mod.f90 | 2 +- .../lfric2lfric_infrastructure_mod.X90 | 30 +++++++++++-------- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 index c06d0c5c6f..cc46af3010 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -1,5 +1,6 @@ module lfric2lfric_vert_mod + use constants_mod, only: str_def use field_parent_mod, only: field_parent_type use field_mod, only: field_type use field_collection_mod, only: field_collection_type @@ -47,7 +48,7 @@ contains call log_event(log_scratch_space, log_level_info) ! Dummy initialisation - to be replaced with actual ! vertical regridding - call setval_X(field_dst, 1.0_r_def) + call invoke(setval_C(field_dst, 1.0_r_def)) enddo end subroutine lfric2lfric_vert diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index b33b0297d5..0005050a65 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -7,7 +7,7 @@ !> module lfric2lfric_driver_mod - use constants_mod, only: str_def, i_def, l_def, r_second + use constants_mod, only: str_def, i_def, l_def, r_def, r_second use driver_fem_mod, only: final_fem use driver_io_mod, only: final_io use driver_modeldb_mod, only: modeldb_type @@ -35,7 +35,8 @@ module lfric2lfric_driver_mod context_dst, context_src, & source_collection_name, & target_collection_name, & - interm_collection_name + interm_collection_name, & + src, dst use lfric2lfric_regrid_mod, only: lfric2lfric_regrid use lfric2lfric_vert_mod, only: lfric2lfric_vert @@ -117,6 +118,8 @@ subroutine run( modeldb, oasis_clock ) real(kind=r_def) :: src_domain_height real(kind=r_def) :: dst_domain_height + logical(l_def) :: horizontal_change, vertical_change + ! Namelist pointers files_nml => modeldb%configuration%get_namelist('files') lfric2lfric_nml => modeldb%configuration%get_namelist('lfric2lfric') @@ -143,19 +146,26 @@ subroutine run( modeldb, oasis_clock ) call dst_extrusion_nml%get_value( 'domain_height', dst_domain_height ) vertical_change = .false. - if ( src_extrusion_method \= dst_extrusion_method ) then vertical_change = .true. - if ( src_number_of_layers \= dst_number_of_layers ) then vertical_change = .true. - if ( src_domain_height \= dst_domain_height ) then vertical_change = .true. - + if ( src_extrusion_method /= dst_extrusion_method ) then + vertical_change = .true. + end if + if ( src_number_of_layers /= dst_number_of_layers ) then + vertical_change = .true. + end if + if ( src_domain_height /= dst_domain_height ) then + vertical_change = .true. + end if horizontal_change = .false. - if ( mesh_names(dst) \= mesh_names(src) ) then horizontal_change = .true. + if ( mesh_names(dst) /= mesh_names(src) ) then + horizontal_change = .true. + end if ! Point to source and target field collections source_fields => modeldb%fields%get_field_collection(source_collection_name) target_fields => modeldb%fields%get_field_collection(target_collection_name) if (horizontal_change .and. vertical_change) then - interm_fields => modeldb%fields%get_field_collection(intermediate_collection_name) + interm_fields => modeldb%fields%get_field_collection(interm_collection_name) else if (horizontal_change .and. .not. vertical_change) then interm_fields => modeldb%fields%get_field_collection(target_collection_name) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index 43a0c05c7a..2506439513 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -11,7 +11,7 @@ module lfric2lfric_init_mod - use constants_mod, only: i_def, r_def, str_def + use constants_mod, only: i_def, r_def, str_def, l_def use driver_modeldb_mod, only: modeldb_type use field_collection_mod, only: field_collection_type use lfric_xios_context_mod, only: lfric_xios_context_type diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index a0b449c716..adf7601246 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -176,7 +176,7 @@ contains ! Namelist parameters character(len=str_def) :: mesh_names(2) - character(len=str_def), allocatable :: mesh_names_dst_ext(2) + character(len=str_def), allocatable :: mesh_names_dst_ext(:) character(len=str_def), allocatable :: twod_names(:) character(len=str_def) :: start_dump_filename character(len=str_def) :: source_file_lbc @@ -260,13 +260,19 @@ contains call finite_element_nml%get_value( 'element_order_v', element_order_v) vertical_change = .false. - if ( src_extrusion_method \= dst_extrusion_method ) then vertical_change = .true. - if ( src_number_of_layers \= dst_number_of_layers ) then vertical_change = .true. - if ( src_domain_height \= dst_domain_height ) then vertical_change = .true. - + if ( src_extrusion_method /= dst_extrusion_method ) then + vertical_change = .true. + end if + if ( src_number_of_layers /= dst_number_of_layers ) then + vertical_change = .true. + end if + if ( src_domain_height /= dst_domain_height ) then + vertical_change = .true. + end if horizontal_change = .false. - if ( mesh_names(dst) \= mesh_names(src) ) then horizontal_change = .true. - + if ( mesh_names(dst) /= mesh_names(src) ) then + horizontal_change = .true. + end if !======================================================================= ! Mesh !======================================================================= @@ -520,7 +526,7 @@ contains ! Get pointers to the destination mesh: orography_mesh_dst => mesh_collection%get_mesh(mesh_names(dst)) - orography_twod_mesh_dst => mesh_collection%get_mesh(orography_mesh, TWOD) + orography_twod_mesh_dst => mesh_collection%get_mesh(orography_mesh_dst, TWOD) ! Set up surface altitude field - this will be used to generate orography call init_altitude( orography_twod_mesh_dst, surface_altitude_dst ) @@ -563,7 +569,7 @@ contains ! Get pointers to the source mesh: orography_mesh_src => mesh_collection%get_mesh(mesh_names(src)) - orography_twod_mesh_src => mesh_collection%get_mesh(orography_mesh, TWOD) + orography_twod_mesh_src => mesh_collection%get_mesh(orography_mesh_src, TWOD) call surface_altitude_src%initialise(vector_space, & name='surface_altitude_src', & @@ -685,13 +691,13 @@ contains ! Adjust the chi fields to account for the orography ! -------------------------------------------------------- - call setup_orography_alg( mesh_names(src), & + call setup_orography_alg( mesh_names(src:src), & orography_mesh_src%get_mesh_name(), & chi_inventory, & panel_id_inventory, & surface_altitude_src ) - call setup_orography_alg( mesh_names_dst_ext(dst), & + call setup_orography_alg( mesh_names_dst_ext(dst:dst), & orography_mesh_dst%get_mesh_name(), & chi_inventory, & panel_id_inventory, & @@ -699,7 +705,7 @@ contains end if deallocate(twod_names) - deallocate(extrusion) + deallocate(src_extrusion, dst_extrusion) end subroutine initialise_infrastructure From bafc1ff80c919de6ceac41a03880bde44c872e9a Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 1 Jul 2026 17:59:52 +0100 Subject: [PATCH 06/53] rose --- .../app/lfric2lfric/opt/rose-app-clim_gal9.conf | 9 ++++++++- .../opt/rose-app-clim_gal9_ral_seuk.conf | 9 ++++++++- rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf | 9 ++++++++- .../app/lfric2lfric/opt/rose-app-ral_seuk.conf | 9 ++++++++- rose-stem/app/lfric2lfric/rose-app.conf | 14 ++++++++++++-- 5 files changed, 44 insertions(+), 6 deletions(-) diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf index 723f79bc39..97859764ba 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf @@ -1,7 +1,14 @@ [file:lfric2lfric_clim_gal9_C12_MG.nc] source="$BIG_DATA_DIR/start_dumps/proto-ral/AppsTicket110/lfric_atm_clim_gal9_C12_dt-1800p0_intel_64-bit_fast-debug_000072.nc" -[namelist:extrusion] +[namelist:extrusion(source)] +domain_height=80000.0 +method='um_L70_50t_20s_80km' +number_of_layers=70 +stretching_height=17507.0 +stretching_method='smooth' + +[namelist:extrusion(destination)] domain_height=80000.0 method='um_L70_50t_20s_80km' number_of_layers=70 diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf index c9a2536321..0e17efbd7d 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf @@ -1,7 +1,14 @@ [file:lfric2lfric_clim_gal9_C12_MG.nc] source="$BIG_DATA_DIR/start_dumps/proto-ral/AppsTicket110/lfric_atm_clim_gal9_C12_dt-1800p0_intel_64-bit_fast-debug_000072.nc" -[namelist:extrusion] +[namelist:extrusion(source)] +domain_height=80000.0 +method='um_L70_50t_20s_80km' +number_of_layers=70 +stretching_height=17507.0 +stretching_method='smooth' + +[namelist:extrusion(destination)] domain_height=80000.0 method='um_L70_50t_20s_80km' number_of_layers=70 diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf b/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf index 566f047fd3..5fab9e117a 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf @@ -4,7 +4,14 @@ source=$ROSE_SUITE_DIR/app/lfric2lfric/file/iodef_ral3.xml [file:lfric2lfric_ral3_seuk.nc] source="$BIG_DATA_DIR/start_dumps/proto-ral/Ticket3510/seuk/checkpoint_um2lfric_000001.nc" -[namelist:extrusion] +[namelist:extrusion(source)] +domain_height=40000.0 +method='um_L70_61t_9s_40km' +number_of_layers=70 +stretching_height=16641.984 +stretching_method='smooth' + +[namelist:extrusion(destination)] domain_height=40000.0 method='um_L70_61t_9s_40km' number_of_layers=70 diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf b/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf index 441c46314d..538a836596 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf @@ -4,7 +4,14 @@ source=$ROSE_SUITE_DIR/app/lfric2lfric/file/iodef_ral.xml [file:lfric2lfric_ral_seuk_MG.nc] source="$BIG_DATA_DIR/start_dumps/proto-ral/AppsTicket110/lfric_atm_proto_ral_seuk_seuk_MG_dt-50p0_intel_64-bit_fast-debug_000072.nc" -[namelist:extrusion] +[namelist:extrusion(source)] +domain_height=40000.0 +method='um_L70_61t_9s_40km' +number_of_layers=70 +stretching_height=16641.984 +stretching_method='smooth' + +[namelist:extrusion(destination)] domain_height=40000.0 method='um_L70_61t_9s_40km' number_of_layers=70 diff --git a/rose-stem/app/lfric2lfric/rose-app.conf b/rose-stem/app/lfric2lfric/rose-app.conf index 3da09230b2..1a0f54d012 100644 --- a/rose-stem/app/lfric2lfric/rose-app.conf +++ b/rose-stem/app/lfric2lfric/rose-app.conf @@ -16,7 +16,7 @@ mode=mkdir [file:configuration.nml] mode=auto -source=namelist:extrusion +source=namelist:extrusion(:) = namelist:finite_element = namelist:io = (namelist:jules_hydrology) @@ -239,9 +239,19 @@ vapour_forcing='none' vertadvect_forcing=.false. wind_forcing='none' -[namelist:extrusion] +[namelist:extrusion(destination)] domain_height=39254.833575999997 !!eta_values='' +mesh_type='destination' +method='um_L38_29t_9s_40km' +number_of_layers=38 +planet_radius=6371229.0 +stretching_method='linear' + +[namelist:extrusion(source)] +domain_height=39254.833575999997 +!!eta_values='' +mesh_type='source' method='um_L38_29t_9s_40km' number_of_layers=38 planet_radius=6371229.0 From a2e7291207b12262937c6cf8d73e84c96847a645 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 2 Jul 2026 12:47:22 +0100 Subject: [PATCH 07/53] corrections --- applications/lfric2lfric/example/configuration.nml | 11 +++++++++++ .../source/driver/lfric2lfric_init_mod.f90 | 7 ++++--- .../initialisation/lfric2lfric_infrastructure_mod.X90 | 3 ++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/applications/lfric2lfric/example/configuration.nml b/applications/lfric2lfric/example/configuration.nml index ea19ff5851..a401ca85a1 100644 --- a/applications/lfric2lfric/example/configuration.nml +++ b/applications/lfric2lfric/example/configuration.nml @@ -19,6 +19,17 @@ target_domain = 'global', &extrusion domain_height = 80000.0, +mesh_type = 'source', +method = 'um_L70_50t_20s_80km', +number_of_layers = 70, +planet_radius = 6371229.0, +stretching_height = 17507.0, +stretching_method = 'smooth', +/ + +&extrusion +domain_height = 80000.0, +mesh_type = 'destination', method = 'um_L70_50t_20s_80km', number_of_layers = 70, planet_radius = 6371229.0, diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index 2506439513..ab634f2457 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -128,6 +128,9 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & field_collection => & modeldb%fields%get_field_collection(target_collection_name) + call modeldb%io_contexts%get_io_context(context_dst, io_context) + call io_context%set_current() + if (mode == mode_ics) then prefix = 'checkpoint_' else if (mode == mode_lbc) then @@ -168,9 +171,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call modeldb%io_contexts%get_io_context(context_src, io_context) call io_context%set_current() - call modeldb%io_contexts%get_io_context(context_dst, io_context) - call io_context%set_current() - + ! Now finished with config_list, deallocate deallocate(config_list) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index adf7601246..55bcb36cd3 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -705,7 +705,8 @@ contains end if deallocate(twod_names) - deallocate(src_extrusion, dst_extrusion) + deallocate(src_extrusion) + if (allocated(dst_extrusion)) deallocate(dst_extrusion) end subroutine initialise_infrastructure From 8a08049abca23046ebfa6c81c5da8c4ee5d8219e Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:20:30 +0100 Subject: [PATCH 08/53] new task with vertical regridding --- .../app/lfric2lfric/opt/rose-app-dst_L38_40km.conf | 7 +++++++ .../app/lfric2lfric/opt/rose-app-src_L70_80km.conf | 7 +++++++ .../site/common/lfric2lfric/tasks_lfric2lfric.cylc | 13 +++++++++++++ rose-stem/site/meto/groups/groups_lfric2lfric.cylc | 1 + 4 files changed, 28 insertions(+) create mode 100644 rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf create mode 100644 rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf b/rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf new file mode 100644 index 0000000000..030f3f8a39 --- /dev/null +++ b/rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf @@ -0,0 +1,7 @@ +[namelist:extrusion(destination)] +domain_height=39254.833575999997 +mesh_type='destination' +method='um_L38_29t_9s_40km' +number_of_layers=38 +planet_radius=6371229.0 +stretching_method='linear' \ No newline at end of file diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf b/rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf new file mode 100644 index 0000000000..8c7962d5fc --- /dev/null +++ b/rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf @@ -0,0 +1,7 @@ +[namelist:extrusion(source)] +domain_height=80000.0 +mesh_type='source' +method='um_L70_50t_20s_80km' +number_of_layers=70 +stretching_height=17507.0 +stretching_method='smooth' \ No newline at end of file diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index b68dc1efcd..fed9d13d23 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -96,6 +96,19 @@ "src_type": "global", }) %} +{% elif task_ns.conf_name == "oasis_C12L70_to_seukL38" %} + + {% do task_dict.update({ + "opt_confs": ["clim_gal9_ral_seuk","oasis","src_L70_80km","dst_L38_40km"], + "resolution": "C12_C16_lam", + "dst_mesh": "seuk_MG", + "dst_name": "dynamics", + "dst_type": "regional", + "src_mesh": "C24_C12", + "src_name": "C12", + "src_type": "global", + }) %} + {% elif task_ns.conf_name == "oasis_clim_gal9_C12-ral_seuk_C16_lam" %} {% do task_dict.update({ diff --git a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc index eca0b1d27d..33e7e6befa 100644 --- a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc +++ b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc @@ -15,6 +15,7 @@ "lfric2lfric_oasis_clim_gal9-C24_C12_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam-lbc_azspice_gnu_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_seukL38_azspice_gnu_fast-debug-64bit", "lfric2lfric_azspice_canned", ], "lfric2lfric_azspice_extra": [ From ddd9ac9cde06a53a68b7fe9b4acaa50e38603514 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 3 Jul 2026 10:20:11 +0100 Subject: [PATCH 09/53] C12 to C12 extrusions --- rose-stem/app/lfric2lfric/opt/rose-app-C12_C12.conf | 5 +++++ .../site/common/lfric2lfric/tasks_lfric2lfric.cylc | 13 +++++++++++++ rose-stem/site/meto/groups/groups_lfric2lfric.cylc | 1 + 3 files changed, 19 insertions(+) create mode 100644 rose-stem/app/lfric2lfric/opt/rose-app-C12_C12.conf diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-C12_C12.conf b/rose-stem/app/lfric2lfric/opt/rose-app-C12_C12.conf new file mode 100644 index 0000000000..a6d7d25af7 --- /dev/null +++ b/rose-stem/app/lfric2lfric/opt/rose-app-C12_C12.conf @@ -0,0 +1,5 @@ +[namelist:lfric2lfric] +destination_mesh_name='C12' +destination_meshfile_prefix='${MESH_DIR}/C24_C12/mesh_C24_C12' +source_mesh_name='C12' +source_meshfile_prefix='${MESH_DIR}/C24_C12/mesh_C24_C12' diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index fed9d13d23..956485023e 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -109,6 +109,19 @@ "src_type": "global", }) %} +{% elif task_ns.conf_name == "oasis_C12L70_to_C12L38" %} + + {% do task_dict.update({ + "opt_confs": ["clim_gal9","oasis","src_L70_80km","dst_L38_40km"], + "resolution": "C12_C12", + "dst_mesh": "C24_C12", + "dst_name": "C12", + "dst_type": "global", + "src_mesh": "C24_C12", + "src_name": "C12", + "src_type": "global", + }) %} + {% elif task_ns.conf_name == "oasis_clim_gal9_C12-ral_seuk_C16_lam" %} {% do task_dict.update({ diff --git a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc index 33e7e6befa..39eee63405 100644 --- a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc +++ b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc @@ -16,6 +16,7 @@ "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam-lbc_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_C12L70_to_seukL38_azspice_gnu_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_C12L38_azspice_gnu_fast-debug-64bit", "lfric2lfric_azspice_canned", ], "lfric2lfric_azspice_extra": [ From 6ee71864c0999c95f6a1a173ced483bc2ad04507 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:45:04 +0100 Subject: [PATCH 10/53] lfric2lfric test suite completes on azspice --- .../initialisation/lfric2lfric_infrastructure_mod.X90 | 1 + .../opt/{rose-app-C12_C12.conf => rose-app-C12.conf} | 0 .../site/common/lfric2lfric/tasks_lfric2lfric.cylc | 2 +- rose-stem/site/meto/groups/groups_lfric2lfric.cylc | 11 ++--------- 4 files changed, 4 insertions(+), 10 deletions(-) rename rose-stem/app/lfric2lfric/opt/{rose-app-C12_C12.conf => rose-app-C12.conf} (100%) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 4c21f4123d..c159a1f23e 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -445,6 +445,7 @@ contains end do call create_mesh( mesh_names, & dst_extrusion, & + inner_halo_tiles, tile_size, & alt_name=mesh_names_dst_ext ) else do i=1, size(mesh_names) diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-C12_C12.conf b/rose-stem/app/lfric2lfric/opt/rose-app-C12.conf similarity index 100% rename from rose-stem/app/lfric2lfric/opt/rose-app-C12_C12.conf rename to rose-stem/app/lfric2lfric/opt/rose-app-C12.conf diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index 25fe629c29..f55505b95b 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -154,7 +154,7 @@ {% do task_dict.update({ "opt_confs": ["clim_gal9","oasis","src_L70_80km","dst_L38_40km"], - "resolution": "C12_C12", + "resolution": "C12", "dst_mesh": "C24_C12", "dst_name": "C12", "dst_type": "global", diff --git a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc index d8c3830900..f8a76189b0 100644 --- a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc +++ b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc @@ -11,19 +11,12 @@ "lfric2lfric_ral_seuk-C32_lam_MG_1cpu_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_ral_seuk-C32_lam_MG_1cpu_azspice_gnu_fast-debug-64bit", "lfric2lfric_ral3-seuk_azspice_gnu_fast-debug-64bit", -<<<<<<< HEAD - "lfric2lfric_clim_gal9-C24_C12_azspice_gnu_fast-debug-64bit", - "lfric2lfric_oasis_clim_gal9-C24_C12_azspice_gnu_fast-debug-64bit", - "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam_azspice_gnu_fast-debug-64bit", - "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam-lbc_azspice_gnu_fast-debug-64bit", - "lfric2lfric_oasis_C12L70_to_seukL38_azspice_gnu_fast-debug-64bit", - "lfric2lfric_oasis_C12L70_to_C12L38_azspice_gnu_fast-debug-64bit", -======= "lfric2lfric_clim_gal9-C24_C12_1cpu_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9-C24_C12_1cpu_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam_1cpu_azspice_gnu_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam-lbc_1cpu_azspice_gnu_fast-debug-64bit", ->>>>>>> upstream/main + "lfric2lfric_oasis_C12L70_to_seukL38_azspice_gnu_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_C12L38_azspice_gnu_fast-debug-64bit", "lfric2lfric_azspice_canned", ], "lfric2lfric_azspice_extra": [ From 599cf128646d90a73171171cc73e2c5ca7090f20 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 3 Jul 2026 17:23:43 +0100 Subject: [PATCH 11/53] Pass stretching height through argument list (AI Claude) --- .../lfric2lfric_infrastructure_mod.X90 | 10 ++++++-- .../gungho/source/driver/gungho_model_mod.F90 | 4 +++- .../orography/assign_orography_field_mod.F90 | 24 ++++++++++++++++--- .../orography/setup_orography_alg_mod.x90 | 22 +++++++++++------ 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index c159a1f23e..3fc3ea7f1a 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -194,6 +194,8 @@ contains integer(kind=i_def) :: dst_number_of_layers real(kind=r_def) :: src_domain_height real(kind=r_def) :: dst_domain_height + real(kind=r_def) :: src_stretching_height + real(kind=r_def) :: dst_stretching_height integer(i_def) :: tile_size_x integer(i_def) :: tile_size_y @@ -242,9 +244,11 @@ contains src_extrusion_method = modeldb%config%extrusion%method() src_number_of_layers = modeldb%config%extrusion%number_of_layers() src_domain_height = modeldb%config%extrusion%domain_height() + src_stretching_height = modeldb%config%extrusion%stretching_height() dst_extrusion_method = modeldb%config%extrusion_dst%method() dst_number_of_layers = modeldb%config%extrusion_dst%number_of_layers() dst_domain_height = modeldb%config%extrusion_dst%domain_height() + dst_stretching_height = modeldb%config%extrusion_dst%stretching_height() mode = modeldb%config%lfric2lfric%mode() regrid_method = modeldb%config%lfric2lfric%regrid_method() @@ -728,13 +732,15 @@ contains orography_mesh_src%get_mesh_name(), & chi_inventory, & panel_id_inventory, & - surface_altitude_src ) + surface_altitude_src, & + src_stretching_height ) call setup_orography_alg( mesh_names_dst_ext(dst:dst), & orography_mesh_dst%get_mesh_name(), & chi_inventory, & panel_id_inventory, & - surface_altitude_dst ) + surface_altitude_dst, & + dst_stretching_height ) end if deallocate(twod_names) diff --git a/science/gungho/source/driver/gungho_model_mod.F90 b/science/gungho/source/driver/gungho_model_mod.F90 index b89f3f2ab1..ca7a376917 100644 --- a/science/gungho/source/driver/gungho_model_mod.F90 +++ b/science/gungho/source/driver/gungho_model_mod.F90 @@ -37,6 +37,7 @@ module gungho_model_mod shifted_extrusion_type, & double_level_extrusion_type, & TWOD, SHIFTED, DOUBLE_LEVEL + use extrusion_config_mod, only : stretching_height use multigrid_mod, only : get_multigrid_tile_size, & init_multigrid_fs_chain use field_array_mod, only : field_array_type @@ -1046,7 +1047,8 @@ subroutine initialise_infrastructure( io_context_name, modeldb ) orography_mesh%get_mesh_name(), & chi_inventory, & panel_id_inventory, & - surface_altitude ) + surface_altitude, & + stretching_height ) !======================================================================= diff --git a/science/gungho/source/orography/assign_orography_field_mod.F90 b/science/gungho/source/orography/assign_orography_field_mod.F90 index 9b9e4299e5..4d131bd74e 100644 --- a/science/gungho/source/orography/assign_orography_field_mod.F90 +++ b/science/gungho/source/orography/assign_orography_field_mod.F90 @@ -67,6 +67,7 @@ subroutine analytic_orography_interface(nlayers, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & domain_surface, domain_height, & + stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, panel_id) @@ -78,6 +79,7 @@ subroutine analytic_orography_interface(nlayers, & integer(kind=i_def), intent(in) :: ndf_chi, ndf_pid integer(kind=i_def), intent(in) :: map_chi(ndf_chi), map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi) real(kind=r_def), intent(in) :: chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) @@ -98,6 +100,7 @@ subroutine ancil_orography_interface(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & ndf, undf, map, basis) @@ -112,6 +115,7 @@ subroutine ancil_orography_interface(nlayers, & integer(kind=i_def), intent(in) :: map(ndf) real(kind=r_def), intent(in) :: basis(ndf,ndf_chi) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: chi_1_in(undf_chi) real(kind=r_def), intent(in) :: chi_2_in(undf_chi) @@ -144,9 +148,10 @@ end subroutine ancil_orography_interface !! fields, itemised by mesh !> @param[in] mesh Mesh to apply orography to !> @param[in] surface_altitude Field containing the surface altitude + !> @param[in] stretching_height Vertical stretching height parameter !============================================================================= subroutine assign_orography_field(chi_inventory, panel_id_inventory, & - mesh, surface_altitude) + mesh, surface_altitude, stretching_height) use inventory_by_mesh_mod, only : inventory_by_mesh_type use field_mod, only : field_type, field_proxy_type @@ -168,6 +173,7 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & ! We keep the surface_altitude as an optional argument since it is ! not needed for miniapps that only want analytic orography type(field_type), optional, intent(in) :: surface_altitude + real(kind=r_def), intent(in) :: stretching_height ! Local variables type(field_type), pointer :: chi(:) @@ -260,7 +266,7 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & call analytic_orography( & nlayers, ndf_chi, undf_chi, map_chi(:,cell), & ndf_pid, undf_pid, map_pid(:,cell), & - domain_surface, domain_height, & + domain_surface, domain_height, stretching_height, & chi_in_proxy(1)%data, chi_in_proxy(2)%data, & chi_in_proxy(3)%data, & chi_proxy(1)%data, chi_proxy(2)%data, chi_proxy(3)%data, & @@ -336,7 +342,7 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & nlayers, chi_proxy(1)%data, chi_proxy(2)%data, chi_proxy(3)%data, & chi_in_proxy(1)%data, chi_in_proxy(2)%data, chi_in_proxy(3)%data, & panel_id_proxy%data, sfc_alt_proxy%data, & - domain_surface, domain_height, & + domain_surface, domain_height, stretching_height, & ndf_chi, undf_chi, map_chi(:,cell), & ndf_pid, undf_pid, map_pid(:,cell), & ndf_sf, undf_sf, map_sf(:,cell), basis_sf_on_chi & @@ -382,6 +388,7 @@ subroutine analytic_orography_spherical_xyz(nlayers, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & domain_surface, domain_height, & + stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, panel_id) @@ -393,6 +400,7 @@ subroutine analytic_orography_spherical_xyz(nlayers, & integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi), chi_2(undf_chi) @@ -478,6 +486,7 @@ subroutine analytic_orography_spherical_native(nlayers, & ndf_pid, undf_pid, map_pid, & domain_surface, & domain_height, & + stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, & panel_id) @@ -490,6 +499,7 @@ subroutine analytic_orography_spherical_native(nlayers, & integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi), chi_2(undf_chi) @@ -570,6 +580,7 @@ subroutine analytic_orography_cartesian(nlayers, & ndf_pid, undf_pid, map_pid, & domain_surface, & domain_height, & + stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, & panel_id) @@ -582,6 +593,7 @@ subroutine analytic_orography_cartesian(nlayers, & integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi), chi_2(undf_chi) @@ -656,6 +668,7 @@ subroutine ancil_orography_spherical_xyz(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -682,6 +695,7 @@ subroutine ancil_orography_spherical_xyz(nlayers, & real(kind=r_def), intent(in) :: panel_id(undf_pid) real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height ! Internal variables integer(kind=i_def) :: k, df, dfchi, dfk @@ -769,6 +783,7 @@ subroutine ancil_orography_spherical_sph(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -795,6 +810,7 @@ subroutine ancil_orography_spherical_sph(nlayers, & real(kind=r_def), intent(in) :: panel_id(undf_pid) real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height ! Internal variables integer(kind=i_def) :: k, df, dfchi, dfk @@ -867,6 +883,7 @@ subroutine ancil_orography_cartesian(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -893,6 +910,7 @@ subroutine ancil_orography_cartesian(nlayers, & real(kind=r_def), intent(in) :: panel_id(undf_pid) real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: domain_surface, domain_height + real(kind=r_def), intent(in) :: stretching_height ! Internal variables integer(kind=i_def) :: k, df, dfchi, dfk diff --git a/science/gungho/source/orography/setup_orography_alg_mod.x90 b/science/gungho/source/orography/setup_orography_alg_mod.x90 index 94ebcca3c5..1476d13aa4 100644 --- a/science/gungho/source/orography/setup_orography_alg_mod.x90 +++ b/science/gungho/source/orography/setup_orography_alg_mod.x90 @@ -57,11 +57,13 @@ contains !> @param[in] panel_id_inventory Contains the model's panel ID fields !! paired with their mesh. !> @param[in] surf_alt_w3 Surface altitude on the orography mesh + !> @param[in] stretching_height Vertical stretching height parameter subroutine setup_orography_alg( all_mesh_names, & orography_mesh_name, & chi_inventory, & panel_id_inventory, & - surf_alt_w3 ) + surf_alt_w3, & + stretching_height ) use assign_orography_field_mod, only: assign_orography_field use surface_altitude_alg_mod, only: surface_altitude_alg @@ -77,6 +79,7 @@ contains type(inventory_by_mesh_type), intent(inout) :: chi_inventory type(inventory_by_mesh_type), intent(in) :: panel_id_inventory type(field_type), intent(in) :: surf_alt_w3 + real(kind=r_def), intent(in) :: stretching_height ! local variables integer(kind=i_def) :: i, fs_id @@ -185,21 +188,24 @@ contains ! Assignment of orography from surface_altitude on orography mesh call assign_orography_field( & - chi_inventory, panel_id_inventory, source_mesh, surf_alt_w0 & + chi_inventory, panel_id_inventory, source_mesh, surf_alt_w0, & + stretching_height & ) ! Assign for shifted and double level meshes if they exist if (mesh_collection%check_for(source_mesh, SHIFTED)) then shifted_mesh => mesh_collection%get_mesh(source_mesh, SHIFTED) call assign_orography_field( & - chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0 & + chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0, & + stretching_height & ) end if if (mesh_collection%check_for(source_mesh, DOUBLE_LEVEL)) then double_level_mesh => mesh_collection%get_mesh(source_mesh, DOUBLE_LEVEL) call assign_orography_field( & - chi_inventory, panel_id_inventory, double_level_mesh, surf_alt_w0 & + chi_inventory, panel_id_inventory, double_level_mesh, surf_alt_w0, & + stretching_height & ) end if @@ -301,14 +307,16 @@ contains ! Adjust coordinates ! ---------------------------------------------------------------------- ! call assign_orography_field( & - chi_inventory, panel_id_inventory, target_mesh, surf_alt_w0_ptr & + chi_inventory, panel_id_inventory, target_mesh, surf_alt_w0_ptr, & + stretching_height & ) ! Assign for shifted and double level meshes if they exist if (mesh_collection%check_for(target_mesh, SHIFTED)) then shifted_mesh => mesh_collection%get_mesh(target_mesh, SHIFTED) call assign_orography_field( & - chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0_ptr & + chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0_ptr, & + stretching_height & ) end if @@ -316,7 +324,7 @@ contains double_level_mesh => mesh_collection%get_mesh(target_mesh, DOUBLE_LEVEL) call assign_orography_field( & chi_inventory, panel_id_inventory, double_level_mesh, & - surf_alt_w0_ptr & + surf_alt_w0_ptr, stretching_height & ) end if end do From b978cf6d2886f911a5d9032f8f7a859e4051b3fd Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:51:17 +0100 Subject: [PATCH 12/53] Revert "Pass stretching height through argument list (AI Claude)" This reverts commit 599cf128646d90a73171171cc73e2c5ca7090f20. --- .../lfric2lfric_infrastructure_mod.X90 | 10 ++------ .../gungho/source/driver/gungho_model_mod.F90 | 4 +--- .../orography/assign_orography_field_mod.F90 | 24 +++---------------- .../orography/setup_orography_alg_mod.x90 | 22 ++++++----------- 4 files changed, 13 insertions(+), 47 deletions(-) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 3fc3ea7f1a..c159a1f23e 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -194,8 +194,6 @@ contains integer(kind=i_def) :: dst_number_of_layers real(kind=r_def) :: src_domain_height real(kind=r_def) :: dst_domain_height - real(kind=r_def) :: src_stretching_height - real(kind=r_def) :: dst_stretching_height integer(i_def) :: tile_size_x integer(i_def) :: tile_size_y @@ -244,11 +242,9 @@ contains src_extrusion_method = modeldb%config%extrusion%method() src_number_of_layers = modeldb%config%extrusion%number_of_layers() src_domain_height = modeldb%config%extrusion%domain_height() - src_stretching_height = modeldb%config%extrusion%stretching_height() dst_extrusion_method = modeldb%config%extrusion_dst%method() dst_number_of_layers = modeldb%config%extrusion_dst%number_of_layers() dst_domain_height = modeldb%config%extrusion_dst%domain_height() - dst_stretching_height = modeldb%config%extrusion_dst%stretching_height() mode = modeldb%config%lfric2lfric%mode() regrid_method = modeldb%config%lfric2lfric%regrid_method() @@ -732,15 +728,13 @@ contains orography_mesh_src%get_mesh_name(), & chi_inventory, & panel_id_inventory, & - surface_altitude_src, & - src_stretching_height ) + surface_altitude_src ) call setup_orography_alg( mesh_names_dst_ext(dst:dst), & orography_mesh_dst%get_mesh_name(), & chi_inventory, & panel_id_inventory, & - surface_altitude_dst, & - dst_stretching_height ) + surface_altitude_dst ) end if deallocate(twod_names) diff --git a/science/gungho/source/driver/gungho_model_mod.F90 b/science/gungho/source/driver/gungho_model_mod.F90 index ca7a376917..b89f3f2ab1 100644 --- a/science/gungho/source/driver/gungho_model_mod.F90 +++ b/science/gungho/source/driver/gungho_model_mod.F90 @@ -37,7 +37,6 @@ module gungho_model_mod shifted_extrusion_type, & double_level_extrusion_type, & TWOD, SHIFTED, DOUBLE_LEVEL - use extrusion_config_mod, only : stretching_height use multigrid_mod, only : get_multigrid_tile_size, & init_multigrid_fs_chain use field_array_mod, only : field_array_type @@ -1047,8 +1046,7 @@ subroutine initialise_infrastructure( io_context_name, modeldb ) orography_mesh%get_mesh_name(), & chi_inventory, & panel_id_inventory, & - surface_altitude, & - stretching_height ) + surface_altitude ) !======================================================================= diff --git a/science/gungho/source/orography/assign_orography_field_mod.F90 b/science/gungho/source/orography/assign_orography_field_mod.F90 index 4d131bd74e..9b9e4299e5 100644 --- a/science/gungho/source/orography/assign_orography_field_mod.F90 +++ b/science/gungho/source/orography/assign_orography_field_mod.F90 @@ -67,7 +67,6 @@ subroutine analytic_orography_interface(nlayers, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & domain_surface, domain_height, & - stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, panel_id) @@ -79,7 +78,6 @@ subroutine analytic_orography_interface(nlayers, & integer(kind=i_def), intent(in) :: ndf_chi, ndf_pid integer(kind=i_def), intent(in) :: map_chi(ndf_chi), map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi) real(kind=r_def), intent(in) :: chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) @@ -100,7 +98,6 @@ subroutine ancil_orography_interface(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & - stretching_height, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & ndf, undf, map, basis) @@ -115,7 +112,6 @@ subroutine ancil_orography_interface(nlayers, & integer(kind=i_def), intent(in) :: map(ndf) real(kind=r_def), intent(in) :: basis(ndf,ndf_chi) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: chi_1_in(undf_chi) real(kind=r_def), intent(in) :: chi_2_in(undf_chi) @@ -148,10 +144,9 @@ end subroutine ancil_orography_interface !! fields, itemised by mesh !> @param[in] mesh Mesh to apply orography to !> @param[in] surface_altitude Field containing the surface altitude - !> @param[in] stretching_height Vertical stretching height parameter !============================================================================= subroutine assign_orography_field(chi_inventory, panel_id_inventory, & - mesh, surface_altitude, stretching_height) + mesh, surface_altitude) use inventory_by_mesh_mod, only : inventory_by_mesh_type use field_mod, only : field_type, field_proxy_type @@ -173,7 +168,6 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & ! We keep the surface_altitude as an optional argument since it is ! not needed for miniapps that only want analytic orography type(field_type), optional, intent(in) :: surface_altitude - real(kind=r_def), intent(in) :: stretching_height ! Local variables type(field_type), pointer :: chi(:) @@ -266,7 +260,7 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & call analytic_orography( & nlayers, ndf_chi, undf_chi, map_chi(:,cell), & ndf_pid, undf_pid, map_pid(:,cell), & - domain_surface, domain_height, stretching_height, & + domain_surface, domain_height, & chi_in_proxy(1)%data, chi_in_proxy(2)%data, & chi_in_proxy(3)%data, & chi_proxy(1)%data, chi_proxy(2)%data, chi_proxy(3)%data, & @@ -342,7 +336,7 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & nlayers, chi_proxy(1)%data, chi_proxy(2)%data, chi_proxy(3)%data, & chi_in_proxy(1)%data, chi_in_proxy(2)%data, chi_in_proxy(3)%data, & panel_id_proxy%data, sfc_alt_proxy%data, & - domain_surface, domain_height, stretching_height, & + domain_surface, domain_height, & ndf_chi, undf_chi, map_chi(:,cell), & ndf_pid, undf_pid, map_pid(:,cell), & ndf_sf, undf_sf, map_sf(:,cell), basis_sf_on_chi & @@ -388,7 +382,6 @@ subroutine analytic_orography_spherical_xyz(nlayers, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & domain_surface, domain_height, & - stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, panel_id) @@ -400,7 +393,6 @@ subroutine analytic_orography_spherical_xyz(nlayers, & integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi), chi_2(undf_chi) @@ -486,7 +478,6 @@ subroutine analytic_orography_spherical_native(nlayers, & ndf_pid, undf_pid, map_pid, & domain_surface, & domain_height, & - stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, & panel_id) @@ -499,7 +490,6 @@ subroutine analytic_orography_spherical_native(nlayers, & integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi), chi_2(undf_chi) @@ -580,7 +570,6 @@ subroutine analytic_orography_cartesian(nlayers, & ndf_pid, undf_pid, map_pid, & domain_surface, & domain_height, & - stretching_height, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, & panel_id) @@ -593,7 +582,6 @@ subroutine analytic_orography_cartesian(nlayers, & integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi), chi_2(undf_chi) @@ -668,7 +656,6 @@ subroutine ancil_orography_spherical_xyz(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & - stretching_height, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -695,7 +682,6 @@ subroutine ancil_orography_spherical_xyz(nlayers, & real(kind=r_def), intent(in) :: panel_id(undf_pid) real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height ! Internal variables integer(kind=i_def) :: k, df, dfchi, dfk @@ -783,7 +769,6 @@ subroutine ancil_orography_spherical_sph(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & - stretching_height, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -810,7 +795,6 @@ subroutine ancil_orography_spherical_sph(nlayers, & real(kind=r_def), intent(in) :: panel_id(undf_pid) real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height ! Internal variables integer(kind=i_def) :: k, df, dfchi, dfk @@ -883,7 +867,6 @@ subroutine ancil_orography_cartesian(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & - stretching_height, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -910,7 +893,6 @@ subroutine ancil_orography_cartesian(nlayers, & real(kind=r_def), intent(in) :: panel_id(undf_pid) real(kind=r_def), intent(in) :: surface_altitude(undf) real(kind=r_def), intent(in) :: domain_surface, domain_height - real(kind=r_def), intent(in) :: stretching_height ! Internal variables integer(kind=i_def) :: k, df, dfchi, dfk diff --git a/science/gungho/source/orography/setup_orography_alg_mod.x90 b/science/gungho/source/orography/setup_orography_alg_mod.x90 index 1476d13aa4..94ebcca3c5 100644 --- a/science/gungho/source/orography/setup_orography_alg_mod.x90 +++ b/science/gungho/source/orography/setup_orography_alg_mod.x90 @@ -57,13 +57,11 @@ contains !> @param[in] panel_id_inventory Contains the model's panel ID fields !! paired with their mesh. !> @param[in] surf_alt_w3 Surface altitude on the orography mesh - !> @param[in] stretching_height Vertical stretching height parameter subroutine setup_orography_alg( all_mesh_names, & orography_mesh_name, & chi_inventory, & panel_id_inventory, & - surf_alt_w3, & - stretching_height ) + surf_alt_w3 ) use assign_orography_field_mod, only: assign_orography_field use surface_altitude_alg_mod, only: surface_altitude_alg @@ -79,7 +77,6 @@ contains type(inventory_by_mesh_type), intent(inout) :: chi_inventory type(inventory_by_mesh_type), intent(in) :: panel_id_inventory type(field_type), intent(in) :: surf_alt_w3 - real(kind=r_def), intent(in) :: stretching_height ! local variables integer(kind=i_def) :: i, fs_id @@ -188,24 +185,21 @@ contains ! Assignment of orography from surface_altitude on orography mesh call assign_orography_field( & - chi_inventory, panel_id_inventory, source_mesh, surf_alt_w0, & - stretching_height & + chi_inventory, panel_id_inventory, source_mesh, surf_alt_w0 & ) ! Assign for shifted and double level meshes if they exist if (mesh_collection%check_for(source_mesh, SHIFTED)) then shifted_mesh => mesh_collection%get_mesh(source_mesh, SHIFTED) call assign_orography_field( & - chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0, & - stretching_height & + chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0 & ) end if if (mesh_collection%check_for(source_mesh, DOUBLE_LEVEL)) then double_level_mesh => mesh_collection%get_mesh(source_mesh, DOUBLE_LEVEL) call assign_orography_field( & - chi_inventory, panel_id_inventory, double_level_mesh, surf_alt_w0, & - stretching_height & + chi_inventory, panel_id_inventory, double_level_mesh, surf_alt_w0 & ) end if @@ -307,16 +301,14 @@ contains ! Adjust coordinates ! ---------------------------------------------------------------------- ! call assign_orography_field( & - chi_inventory, panel_id_inventory, target_mesh, surf_alt_w0_ptr, & - stretching_height & + chi_inventory, panel_id_inventory, target_mesh, surf_alt_w0_ptr & ) ! Assign for shifted and double level meshes if they exist if (mesh_collection%check_for(target_mesh, SHIFTED)) then shifted_mesh => mesh_collection%get_mesh(target_mesh, SHIFTED) call assign_orography_field( & - chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0_ptr, & - stretching_height & + chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0_ptr & ) end if @@ -324,7 +316,7 @@ contains double_level_mesh => mesh_collection%get_mesh(target_mesh, DOUBLE_LEVEL) call assign_orography_field( & chi_inventory, panel_id_inventory, double_level_mesh, & - surf_alt_w0_ptr, stretching_height & + surf_alt_w0_ptr & ) end if end do From 1a022fe8962a04801b2c606c474ef3829f7a7002 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:18:39 +0100 Subject: [PATCH 13/53] correction --- .../site/common/lfric2lfric/tasks_lfric2lfric.cylc | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index f55505b95b..a2e035a9d1 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -174,19 +174,7 @@ "src_mesh": "C24_C12", "src_name": "C12", "src_type": "global", - }) %} - -{% elif task_ns.conf_name == "oasis_clim_gal9_C12-ral_seuk_C16_lam" %} - {% do task_dict.update({ - "opt_confs": ["clim_gal9_ral_seuk","oasis"], - "resolution": "C12_C16_lam", - "dst_mesh": "seuk_MG", - "dst_name": "dynamics", - "dst_type": "regional", - "src_mesh": "C24_C12", - "src_name": "C12", - "src_type": "global", - "mpi_parts": 6, + "mpi_parts": 6, }) %} {% elif task_ns.conf_name == "oasis_clim_gal9_C12-ral_seuk_C16_lam_1cpu" %} From 5f97a961050b477785c6f1b8c922bdb5bd48e949 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:08:56 +0100 Subject: [PATCH 14/53] Add stretching_height as a subroutine parameter --- .../source/driver/lfric2lfric_driver_mod.F90 | 14 ++++ .../lfric2lfric_infrastructure_mod.X90 | 24 ++++++- .../gungho/source/driver/gungho_model_mod.F90 | 22 ++++--- .../orography/assign_orography_field_mod.F90 | 66 +++++++++++++++++-- .../orography/setup_orography_alg_mod.x90 | 24 +++++-- 5 files changed, 129 insertions(+), 21 deletions(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 0e8eb42adc..681b4a49bc 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -110,17 +110,25 @@ subroutine run( modeldb, oasis_clock ) integer(kind=i_def) :: dst_extrusion_method integer(kind=i_def) :: src_number_of_layers integer(kind=i_def) :: dst_number_of_layers + integer(kind=i_def) :: src_stretching_method + integer(kind=i_def) :: dst_stretching_method real(kind=r_def) :: src_domain_height real(kind=r_def) :: dst_domain_height + real(kind=r_def) :: src_stretching_height + real(kind=r_def) :: dst_stretching_height logical(l_def) :: horizontal_change, vertical_change src_extrusion_method = modeldb%config%extrusion%method() src_number_of_layers = modeldb%config%extrusion%number_of_layers() src_domain_height = modeldb%config%extrusion%domain_height() + src_stretching_height = modeldb%config%extrusion%stretching_height() + src_stretching_method = modeldb%config%extrusion%stretching_method() dst_extrusion_method = modeldb%config%extrusion_dst%method() dst_number_of_layers = modeldb%config%extrusion_dst%number_of_layers() dst_domain_height = modeldb%config%extrusion_dst%domain_height() + dst_stretching_height = modeldb%config%extrusion_dst%stretching_height() + dst_stretching_method = modeldb%config%extrusion_dst%stretching_method() mesh_names(dst) = modeldb%config%lfric2lfric%destination_mesh_name() mesh_names(src) = modeldb%config%lfric2lfric%source_mesh_name() @@ -135,6 +143,12 @@ subroutine run( modeldb, oasis_clock ) if ( src_domain_height /= dst_domain_height ) then vertical_change = .true. end if + if ( src_stretching_height /= dst_stretching_height ) then + vertical_change = .true. + end if + if ( src_stretching_method /= dst_stretching_method ) then + vertical_change = .true. + end if horizontal_change = .false. if ( mesh_names(dst) /= mesh_names(src) ) then horizontal_change = .true. diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index c159a1f23e..8ad7d6cec0 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -192,8 +192,15 @@ contains integer(kind=i_def) :: dst_extrusion_method integer(kind=i_def) :: src_number_of_layers integer(kind=i_def) :: dst_number_of_layers + integer(kind=i_def) :: src_stretching_method + integer(kind=i_def) :: dst_stretching_method real(kind=r_def) :: src_domain_height real(kind=r_def) :: dst_domain_height + real(kind=r_def) :: src_stretching_height + real(kind=r_def) :: dst_stretching_height + + logical(kind=l_def) :: vertical_change + logical(kind=l_def) :: horizontal_change integer(i_def) :: tile_size_x integer(i_def) :: tile_size_y @@ -210,8 +217,6 @@ contains type(coupler_exchange_2d_type) :: coupler_exchange_2d integer(kind=i_def) :: ierror logical(kind=l_def) :: is_running - logical(kind=l_def) :: vertical_change - logical(kind=l_def) :: horizontal_change !------------------------ ! XIOS contexts @@ -242,9 +247,13 @@ contains src_extrusion_method = modeldb%config%extrusion%method() src_number_of_layers = modeldb%config%extrusion%number_of_layers() src_domain_height = modeldb%config%extrusion%domain_height() + src_stretching_height = modeldb%config%extrusion%stretching_height() + src_stretching_method = modeldb%config%extrusion%stretching_method() dst_extrusion_method = modeldb%config%extrusion_dst%method() dst_number_of_layers = modeldb%config%extrusion_dst%number_of_layers() dst_domain_height = modeldb%config%extrusion_dst%domain_height() + dst_stretching_height = modeldb%config%extrusion_dst%stretching_height() + dst_stretching_method = modeldb%config%extrusion_dst%stretching_method() mode = modeldb%config%lfric2lfric%mode() regrid_method = modeldb%config%lfric2lfric%regrid_method() @@ -273,10 +282,17 @@ contains if ( src_domain_height /= dst_domain_height ) then vertical_change = .true. end if + if ( src_stretching_height /= dst_stretching_height ) then + vertical_change = .true. + end if + if ( src_stretching_method /= dst_stretching_method ) then + vertical_change = .true. + end if horizontal_change = .false. if ( mesh_names(dst) /= mesh_names(src) ) then horizontal_change = .true. end if + !======================================================================= ! Mesh !======================================================================= @@ -728,12 +744,16 @@ contains orography_mesh_src%get_mesh_name(), & chi_inventory, & panel_id_inventory, & + src_stretching_height, & + src_stretching_method, & surface_altitude_src ) call setup_orography_alg( mesh_names_dst_ext(dst:dst), & orography_mesh_dst%get_mesh_name(), & chi_inventory, & panel_id_inventory, & + dst_stretching_height, & + dst_stretching_method, & surface_altitude_dst ) end if diff --git a/science/gungho/source/driver/gungho_model_mod.F90 b/science/gungho/source/driver/gungho_model_mod.F90 index b89f3f2ab1..f488c7df4b 100644 --- a/science/gungho/source/driver/gungho_model_mod.F90 +++ b/science/gungho/source/driver/gungho_model_mod.F90 @@ -563,6 +563,8 @@ subroutine initialise_infrastructure( io_context_name, modeldb ) character(str_def), allocatable :: twod_names(:) character(str_def), allocatable :: shifted_names(:) character(str_def), allocatable :: double_names(:) + integer(i_def) :: stretching_method + real(r_def) :: stretching_height character(str_def), allocatable :: meshes_to_check(:) @@ -620,14 +622,16 @@ subroutine initialise_infrastructure( io_context_name, modeldb ) chain_mesh_tags = modeldb%config%multigrid%chain_mesh_tags() end if - prime_mesh_name = modeldb%config%base_mesh%prime_mesh_name() - geometry = modeldb%config%base_mesh%geometry() - topology = modeldb%config%base_mesh%topology() - prepartitioned = modeldb%config%base_mesh%prepartitioned() - domain_height = modeldb%config%extrusion%domain_height() - extrusion_method = modeldb%config%extrusion%method() - number_of_layers = modeldb%config%extrusion%number_of_layers() - scaled_radius = modeldb%config%planet%scaled_radius() + prime_mesh_name = modeldb%config%base_mesh%prime_mesh_name() + geometry = modeldb%config%base_mesh%geometry() + topology = modeldb%config%base_mesh%topology() + prepartitioned = modeldb%config%base_mesh%prepartitioned() + domain_height = modeldb%config%extrusion%domain_height() + extrusion_method = modeldb%config%extrusion%method() + stretching_method = modeldb%config%extrusion%stretching_method() + stretching_height = modeldb%config%extrusion%stretching_height() + number_of_layers = modeldb%config%extrusion%number_of_layers() + scaled_radius = modeldb%config%planet%scaled_radius() if (prepartitioned) then tile_size_x = 1 @@ -1046,6 +1050,8 @@ subroutine initialise_infrastructure( io_context_name, modeldb ) orography_mesh%get_mesh_name(), & chi_inventory, & panel_id_inventory, & + stretching_height, & + stretching_method, & surface_altitude ) diff --git a/science/gungho/source/orography/assign_orography_field_mod.F90 b/science/gungho/source/orography/assign_orography_field_mod.F90 index 9b9e4299e5..06c2e31018 100644 --- a/science/gungho/source/orography/assign_orography_field_mod.F90 +++ b/science/gungho/source/orography/assign_orography_field_mod.F90 @@ -29,9 +29,7 @@ module assign_orography_field_mod eta2z_linear, & eta2z_smooth use analytic_orography_mod, only : orography_profile - use extrusion_config_mod, only : stretching_height, & - stretching_method, & - stretching_method_linear + use extrusion_config_mod, only : stretching_method_linear use log_mod, only : log_event, & LOG_LEVEL_INFO, & LOG_LEVEL_ERROR @@ -67,6 +65,8 @@ subroutine analytic_orography_interface(nlayers, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & domain_surface, domain_height, & + stretching_height, & + stretching_method, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, panel_id) @@ -77,6 +77,8 @@ subroutine analytic_orography_interface(nlayers, & integer(kind=i_def), intent(in) :: nlayers, undf_chi, undf_pid integer(kind=i_def), intent(in) :: ndf_chi, ndf_pid integer(kind=i_def), intent(in) :: map_chi(ndf_chi), map_pid(ndf_pid) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: domain_surface, domain_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi) real(kind=r_def), intent(in) :: chi_2_in(undf_chi) @@ -98,6 +100,8 @@ subroutine ancil_orography_interface(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & + stretching_method, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & ndf, undf, map, basis) @@ -110,6 +114,8 @@ subroutine ancil_orography_interface(nlayers, & integer(kind=i_def), intent(in) :: ndf_chi, ndf_pid, ndf integer(kind=i_def), intent(in) :: map_chi(ndf_chi), map_pid(ndf_pid) integer(kind=i_def), intent(in) :: map(ndf) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: basis(ndf,ndf_chi) real(kind=r_def), intent(in) :: domain_surface, domain_height real(kind=r_def), intent(in) :: surface_altitude(undf) @@ -143,10 +149,14 @@ end subroutine ancil_orography_interface !> @param[in] panel_id_inventory Contains all of the model's panel ID !! fields, itemised by mesh !> @param[in] mesh Mesh to apply orography to + !> @param[in] stretching_height Physical height above which surface altitude + !! does not influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] surface_altitude Field containing the surface altitude !============================================================================= - subroutine assign_orography_field(chi_inventory, panel_id_inventory, & - mesh, surface_altitude) + subroutine assign_orography_field(chi_inventory, panel_id_inventory, & + mesh, stretching_height, & + stretching_method, surface_altitude) use inventory_by_mesh_mod, only : inventory_by_mesh_type use field_mod, only : field_type, field_proxy_type @@ -164,6 +174,8 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & type(inventory_by_mesh_type), intent(inout) :: chi_inventory type(inventory_by_mesh_type), intent(in) :: panel_id_inventory type(mesh_type), pointer, intent(in) :: mesh + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height ! We keep the surface_altitude as an optional argument since it is ! not needed for miniapps that only want analytic orography @@ -261,6 +273,7 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & nlayers, ndf_chi, undf_chi, map_chi(:,cell), & ndf_pid, undf_pid, map_pid(:,cell), & domain_surface, domain_height, & + stretching_height, stretching_method, & chi_in_proxy(1)%data, chi_in_proxy(2)%data, & chi_in_proxy(3)%data, & chi_proxy(1)%data, chi_proxy(2)%data, chi_proxy(3)%data, & @@ -337,6 +350,7 @@ subroutine assign_orography_field(chi_inventory, panel_id_inventory, & chi_in_proxy(1)%data, chi_in_proxy(2)%data, chi_in_proxy(3)%data, & panel_id_proxy%data, sfc_alt_proxy%data, & domain_surface, domain_height, & + stretching_height, stretching_method, & ndf_chi, undf_chi, map_chi(:,cell), & ndf_pid, undf_pid, map_pid(:,cell), & ndf_sf, undf_sf, map_sf(:,cell), basis_sf_on_chi & @@ -370,6 +384,9 @@ end subroutine assign_orography_field !> @param[in] map_pid Indirection map for panel_id !> @param[in] domain_surface Physical height of flat domain surface (m) !> @param[in] domain_height Physical height of domain top (m) + !> @param[in] stretching_height Physical height above which surface altitude does not + !! influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] chi_1_in 1st coordinate field in Wchi (input) !> @param[in] chi_2_in 2nd coordinate field in Wchi (input) !> @param[in] chi_3_in 3rd coordinate field in Wchi (input) @@ -382,6 +399,8 @@ subroutine analytic_orography_spherical_xyz(nlayers, & ndf_chi, undf_chi, map_chi, & ndf_pid, undf_pid, map_pid, & domain_surface, domain_height, & + stretching_height, & + stretching_method, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, panel_id) @@ -392,6 +411,8 @@ subroutine analytic_orography_spherical_xyz(nlayers, & integer(kind=i_def), intent(in) :: ndf_chi, ndf_pid integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: domain_surface, domain_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) @@ -465,6 +486,9 @@ end subroutine analytic_orography_spherical_xyz !> @param[in] map_pid Indirection map for panel_id !> @param[in] domain_surface Physical height of flat domain surface (m) !> @param[in] domain_height Physical height of domain top (m) + !> @param[in] stretching_height Physical height above which surface altitude does not + !! influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] chi_1_in 1st coordinate field in Wchi (input) !> @param[in] chi_2_in 2nd coordinate field in Wchi (input) !> @param[in] chi_3_in 3rd coordinate field in Wchi (input) @@ -478,6 +502,8 @@ subroutine analytic_orography_spherical_native(nlayers, & ndf_pid, undf_pid, map_pid, & domain_surface, & domain_height, & + stretching_height, & + stretching_method, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, & panel_id) @@ -489,6 +515,8 @@ subroutine analytic_orography_spherical_native(nlayers, & integer(kind=i_def), intent(in) :: ndf_chi, ndf_pid integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: domain_surface, domain_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) @@ -557,6 +585,9 @@ end subroutine analytic_orography_spherical_native !> @param[in] map_pid Indirection map for panel_id !> @param[in] domain_surface Physical height of flat domain surface (m) !> @param[in] domain_height Physical height of domain top (m) + !> @param[in] stretching_height Physical height above which surface altitude does not + !! influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] chi_1_in 1st coordinate field in Wchi (input) !> @param[in] chi_2_in 2nd coordinate field in Wchi (input) !> @param[in] chi_3_in 3rd coordinate field in Wchi (input) @@ -570,6 +601,8 @@ subroutine analytic_orography_cartesian(nlayers, & ndf_pid, undf_pid, map_pid, & domain_surface, & domain_height, & + stretching_height, & + stretching_method, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, & panel_id) @@ -581,6 +614,8 @@ subroutine analytic_orography_cartesian(nlayers, & integer(kind=i_def), intent(in) :: ndf_chi, ndf_pid integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: domain_surface, domain_height real(kind=r_def), intent(in) :: chi_1_in(undf_chi), chi_2_in(undf_chi) real(kind=r_def), intent(in) :: chi_3_in(undf_chi) @@ -639,6 +674,9 @@ end subroutine analytic_orography_cartesian !> @param[in] surface_altitude Surface altitude field data !> @param[in] domain_surface Physical height of flat domain surface (m) !> @param[in] domain_height Physical height of domain top (m) + !> @param[in] stretching_height Physical height above which surface altitude does not + !! influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] ndf_chi Num DoFs per cell for map_chi !> @param[in] undf_chi Column coords' num DoFs this partition !> @param[in] map_chi Indirection map for coordinate field @@ -656,6 +694,8 @@ subroutine ancil_orography_spherical_xyz(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & + stretching_method, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -672,6 +712,8 @@ subroutine ancil_orography_spherical_xyz(nlayers, & integer(kind=i_def), intent(in) :: map(ndf) integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: basis(ndf, ndf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi) real(kind=r_def), intent(inout) :: chi_2(undf_chi) @@ -752,6 +794,9 @@ end subroutine ancil_orography_spherical_xyz !> @param[in] surface_altitude Surface altitude field data !> @param[in] domain_surface Physical height of flat domain surface (m) !> @param[in] domain_height Physical height of domain top (m) + !> @param[in] stretching_height Physical height above which surface altitude does not + !! influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] ndf_chi Num DoFs per cell for map_chi !> @param[in] undf_chi Column coords' num DoFs this partition !> @param[in] map_chi Indirection map for coordinate field @@ -769,6 +814,8 @@ subroutine ancil_orography_spherical_sph(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & + stretching_method, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -785,6 +832,8 @@ subroutine ancil_orography_spherical_sph(nlayers, & integer(kind=i_def), intent(in) :: map(ndf) integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: basis(ndf, ndf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi) real(kind=r_def), intent(inout) :: chi_2(undf_chi) @@ -850,6 +899,9 @@ end subroutine ancil_orography_spherical_sph !> @param[in] surface_altitude Surface altitude field data !> @param[in] domain_surface Physical height of flat domain surface (m) !> @param[in] domain_height Physical height of domain top (m) + !> @param[in] stretching_height Physical height above which surface altitude does not + !! influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] ndf_chi Num DoFs per cell for map_chi !> @param[in] undf_chi Column coords' num DoFs this partition !> @param[in] map_chi Indirection map for coordinate field @@ -867,6 +919,8 @@ subroutine ancil_orography_cartesian(nlayers, & panel_id, & surface_altitude, & domain_surface, domain_height, & + stretching_height, & + stretching_method, & ndf_chi, undf_chi, & map_chi, & ndf_pid, undf_pid, & @@ -883,6 +937,8 @@ subroutine ancil_orography_cartesian(nlayers, & integer(kind=i_def), intent(in) :: map(ndf) integer(kind=i_def), intent(in) :: map_chi(ndf_chi) integer(kind=i_def), intent(in) :: map_pid(ndf_pid) + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height real(kind=r_def), intent(in) :: basis(ndf, ndf_chi) real(kind=r_def), intent(inout) :: chi_1(undf_chi) real(kind=r_def), intent(inout) :: chi_2(undf_chi) diff --git a/science/gungho/source/orography/setup_orography_alg_mod.x90 b/science/gungho/source/orography/setup_orography_alg_mod.x90 index 94ebcca3c5..fe68dd423f 100644 --- a/science/gungho/source/orography/setup_orography_alg_mod.x90 +++ b/science/gungho/source/orography/setup_orography_alg_mod.x90 @@ -56,11 +56,16 @@ contains !! paired with their mesh. !> @param[in] panel_id_inventory Contains the model's panel ID fields !! paired with their mesh. + !> @param[in] stretching_height Physical height above which surface altitude + !! does not influence layer height (m) + !> @param[in] stretching_method Method of generating stretching !> @param[in] surf_alt_w3 Surface altitude on the orography mesh subroutine setup_orography_alg( all_mesh_names, & orography_mesh_name, & chi_inventory, & panel_id_inventory, & + stretching_height, & + stretching_method, & surf_alt_w3 ) use assign_orography_field_mod, only: assign_orography_field @@ -77,6 +82,8 @@ contains type(inventory_by_mesh_type), intent(inout) :: chi_inventory type(inventory_by_mesh_type), intent(in) :: panel_id_inventory type(field_type), intent(in) :: surf_alt_w3 + integer(kind=i_def), intent(in) :: stretching_method + real(kind=r_def), intent(in) :: stretching_height ! local variables integer(kind=i_def) :: i, fs_id @@ -185,21 +192,24 @@ contains ! Assignment of orography from surface_altitude on orography mesh call assign_orography_field( & - chi_inventory, panel_id_inventory, source_mesh, surf_alt_w0 & + chi_inventory, panel_id_inventory, source_mesh, & + stretching_height, stretching_method, surf_alt_w0 & ) ! Assign for shifted and double level meshes if they exist if (mesh_collection%check_for(source_mesh, SHIFTED)) then shifted_mesh => mesh_collection%get_mesh(source_mesh, SHIFTED) call assign_orography_field( & - chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0 & + chi_inventory, panel_id_inventory, shifted_mesh, & + stretching_height, stretching_method, surf_alt_w0 & ) end if if (mesh_collection%check_for(source_mesh, DOUBLE_LEVEL)) then double_level_mesh => mesh_collection%get_mesh(source_mesh, DOUBLE_LEVEL) call assign_orography_field( & - chi_inventory, panel_id_inventory, double_level_mesh, surf_alt_w0 & + chi_inventory, panel_id_inventory, double_level_mesh, & + stretching_height, stretching_method, surf_alt_w0 & ) end if @@ -301,14 +311,16 @@ contains ! Adjust coordinates ! ---------------------------------------------------------------------- ! call assign_orography_field( & - chi_inventory, panel_id_inventory, target_mesh, surf_alt_w0_ptr & + chi_inventory, panel_id_inventory, target_mesh, & + stretching_height, stretching_method, surf_alt_w0_ptr & ) ! Assign for shifted and double level meshes if they exist if (mesh_collection%check_for(target_mesh, SHIFTED)) then shifted_mesh => mesh_collection%get_mesh(target_mesh, SHIFTED) call assign_orography_field( & - chi_inventory, panel_id_inventory, shifted_mesh, surf_alt_w0_ptr & + chi_inventory, panel_id_inventory, shifted_mesh, & + stretching_height, stretching_method, surf_alt_w0_ptr & ) end if @@ -316,7 +328,7 @@ contains double_level_mesh => mesh_collection%get_mesh(target_mesh, DOUBLE_LEVEL) call assign_orography_field( & chi_inventory, panel_id_inventory, double_level_mesh, & - surf_alt_w0_ptr & + stretching_height, stretching_method, surf_alt_w0_ptr & ) end if end do From 6d899ce80c1d89800a79704952573114c5a54057 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 9 Jul 2026 15:15:51 +0100 Subject: [PATCH 15/53] Add get_height to vertical regridding --- .../source/algorithm/lfric2lfric_vert_mod.x90 | 60 ++++++++++++++----- .../source/driver/lfric2lfric_driver_mod.F90 | 4 +- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 index cc46af3010..f54d199d65 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -1,11 +1,15 @@ module lfric2lfric_vert_mod - use constants_mod, only: str_def + use constants_mod, only: str_def, i_def + use driver_modeldb_mod, only: modeldb_type use field_parent_mod, only: field_parent_type use field_mod, only: field_type use field_collection_mod, only: field_collection_type - use field_collection_iterator_mod, only: & - field_collection_iterator_type + use field_collection_iterator_mod, & + only: field_collection_iterator_type + use sci_geometric_constants_mod, & + only: get_height_fv + use mesh_mod, only: mesh_type use log_mod, only: log_event, & log_level_info, & log_scratch_space @@ -17,21 +21,34 @@ module lfric2lfric_vert_mod contains - subroutine lfric2lfric_vert( source_fields, target_fields ) + !> @brief Apply vertical regridding + !> @details Loop over the fields in the source_fields collection, + !! and apply the vertical regridding to obtain the regridded + !! field in the target_fields collection. + !> @param modeldb Model state object + !> @param source_fields The collection of fields to be regridded + !> @param target_fields The collection of regridded fields + subroutine lfric2lfric_vert( modeldb, source_fields, target_fields ) implicit none + type(modeldb_type), intent(inout) :: modeldb type(field_collection_type), intent(inout) :: source_fields type(field_collection_type), intent(inout) :: target_fields type(field_collection_iterator_type) :: iter - class(field_parent_type), pointer :: field => null() - type(field_type), pointer :: field_src => null() - type(field_type), pointer :: field_dst => null() - - character(len=str_def) :: field_name - + class(field_parent_type), pointer :: field + type(field_type), pointer :: field_src + type(field_type), pointer :: field_dst + type(field_type), pointer :: height_src + type(field_type), pointer :: height_dst + type(mesh_type), pointer :: mesh_src + type(mesh_type), pointer :: mesh_dst + + character(len=str_def) :: field_name + integer(kind=i_def) :: fs_src, fs_dst + ! Main loop over fields to be processed call iter%initialise(source_fields) do @@ -42,13 +59,26 @@ contains call source_fields%get_field(field_name, field_src) call target_fields%get_field(field_name, field_dst) - + write(log_scratch_space, '(A,A)') "Processing lfric field ", & - trim(field_name) + trim(field_name) call log_event(log_scratch_space, log_level_info) - ! Dummy initialisation - to be replaced with actual - ! vertical regridding - call invoke(setval_C(field_dst, 1.0_r_def)) + + mesh_src => field_src%get_mesh() + mesh_dst => field_dst%get_mesh() + fs_src = field_src%which_function_space() + fs_dst = field_dst%which_function_space() + + ! Get the associated heights, ready for vertical interpolation kernels + height_src => get_height_fv(modeldb%config, mesh_src, fs_src) + height_dst => get_height_fv(modeldb%config, mesh_dst, fs_dst) + + ! Dummy initialisation. This will be replaced with actual + ! vertical regridding from #253. + ! call invoke( lfric2lfric_vert_lin_interp_lin_extrap_code_r_single( & + ! field_dst, field_src, height_dst, height_src)) + ! At the moment just writing out the heights. + call invoke(setval_X(field_dst, height_dst)) enddo end subroutine lfric2lfric_vert diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 681b4a49bc..071af9bb00 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -184,7 +184,7 @@ subroutine run( modeldb, oasis_clock ) interm_fields, regrid_method) end if if (vertical_change) then - call lfric2lfric_vert(interm_fields, target_fields) + call lfric2lfric_vert(modeldb, interm_fields, target_fields) end if ! Write output @@ -212,7 +212,7 @@ subroutine run( modeldb, oasis_clock ) interm_fields, regrid_method) end if if (vertical_change) then - call lfric2lfric_vert(interm_fields, target_fields) + call lfric2lfric_vert(modeldb, interm_fields, target_fields) end if is_running = modeldb%clock%tick() From ea75009f35686d20999756a4c65cfd1c72b48ebc Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 13 Jul 2026 10:34:38 +0100 Subject: [PATCH 16/53] Blended orography corrections --- .../lfric2lfric_infrastructure_mod.X90 | 11 ++++++ rose-stem/app/lfric2lfric/rose-app.conf | 34 ++++++------------- .../limited_area_masks_alg_mod.x90 | 5 +++ .../orography/blend_orography_alg_mod.x90 | 8 +++++ 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 8ad7d6cec0..d97bc13728 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -740,6 +740,7 @@ contains ! Adjust the chi fields to account for the orography ! -------------------------------------------------------- + ! source mesh, source extrusion, source orography call setup_orography_alg( mesh_names(src:src), & orography_mesh_src%get_mesh_name(), & chi_inventory, & @@ -748,6 +749,16 @@ contains src_stretching_method, & surface_altitude_src ) + ! destination mesh, source extrusion, source orog on destination mesh + call setup_orography_alg( mesh_names(dst:dst), & + orography_mesh_dst%get_mesh_name(), & + chi_inventory, & + panel_id_inventory, & + src_stretching_height, & + src_stretching_method, & + surface_altitude_src_on_dst ) + + ! destination mesh, destination extrusion, destination orog call setup_orography_alg( mesh_names_dst_ext(dst:dst), & orography_mesh_dst%get_mesh_name(), & chi_inventory, & diff --git a/rose-stem/app/lfric2lfric/rose-app.conf b/rose-stem/app/lfric2lfric/rose-app.conf index e9468e1913..35d5a0c808 100644 --- a/rose-stem/app/lfric2lfric/rose-app.conf +++ b/rose-stem/app/lfric2lfric/rose-app.conf @@ -19,6 +19,7 @@ mode=mkdir mode=auto source=namelist:extrusion =namelist:extrusion_dst + =namelist:boundaries = namelist:finite_element = namelist:io = (namelist:jules_hydrology) @@ -104,29 +105,16 @@ sg_orog_mixing='none' !!zhloc_depth_fac=0 [namelist:boundaries] -!!blend_frequency='inner' -!!blending_weights=0 -!!blending_weights_w2v=0 -!!boundary_e=0 -!!boundary_n=0 -!!boundary_s=0 -!!boundary_w=0 -!!edge_cells_ew=0 -!!edge_cells_ns=0 -!!inner_width_ew=0 -!!inner_width_ns=0 -!!lbc_eos_height=0 -!!lbc_method='onion_layer' -limited_area=.false. -!!normal_only=.false. -!!outer_width_ew=0 -!!outer_width_ns=0 -!!output_lbcs=.false. -!!rim_width_ew=0 -!!rim_width_ns=0 -!!solver_boundary_depth=0 -!!transport_boundary_depth=0 -transport_overwrite_freq='final' +blend_frequency='inner' +blending_weights=1.0,1.0,1.0,1.0,0.9,0.7,0.5,0.3,0.1 +blending_weights_w2v=1.0,1.0,1.0,1.0,0.9,0.7,0.5,0.3,0.1 +lbc_eos_height=10 +lbc_method='onion_layer' +limited_area=.true. +normal_only=.true. +output_lbcs=.true. +solver_boundary_depth=4 +transport_boundary_depth=4 [namelist:checks] limit_cfl=.false. diff --git a/science/gungho/source/algorithm/limited_area/limited_area_masks_alg_mod.x90 b/science/gungho/source/algorithm/limited_area/limited_area_masks_alg_mod.x90 index a5cbfb514c..4a0be42d87 100644 --- a/science/gungho/source/algorithm/limited_area/limited_area_masks_alg_mod.x90 +++ b/science/gungho/source/algorithm/limited_area/limited_area_masks_alg_mod.x90 @@ -21,6 +21,7 @@ module limited_area_masks_alg_mod log_scratch_space, & LOG_LEVEL_ERROR, & LOG_LEVEL_INFO, & + LOG_LEVEL_DEBUG, & LOG_LEVEL_WARNING use function_space_mod, only: function_space_type use function_space_collection_mod, only: function_space_collection @@ -532,6 +533,8 @@ contains if ( lbc_method == lbc_method_onion_layer )then + call log_event('Creating blend mask using onion layers', LOG_LEVEL_DEBUG) + fs_enum = mask%which_function_space() select case(fs_enum) @@ -555,6 +558,8 @@ contains else + call log_event('Creating blend mask using coordinates', LOG_LEVEL_DEBUG) + ! |<-------------rim_width------------>| ! | | | | ! |<--outer--> |<--inner-->| | diff --git a/science/gungho/source/orography/blend_orography_alg_mod.x90 b/science/gungho/source/orography/blend_orography_alg_mod.x90 index c5e498de38..8038bf9b03 100644 --- a/science/gungho/source/orography/blend_orography_alg_mod.x90 +++ b/science/gungho/source/orography/blend_orography_alg_mod.x90 @@ -15,6 +15,11 @@ module blend_orography_alg_mod use limited_area_constants_mod, only: get_blend_mask, & get_lbc_mask_fv use mesh_mod, only: mesh_type + use log_mod, only: log_event, & + LOG_LEVEL_INFO, & + LOG_LEVEL_DEBUG, & + LOG_LEVEL_ERROR + implicit none public :: blend_orography @@ -43,6 +48,9 @@ contains integer(kind=i_def) :: fs_enum type(mesh_type), pointer :: mesh + call log_event( "Creating the blended orography (for LAMs)", & + LOG_LEVEL_DEBUG ) + ! Define the function space required for masks. fs_enum = lam_orog%which_function_space() mesh => lam_orog%get_mesh() From c8d9b6a35e256d94b38b40974e805e87cf61ab54 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Tue, 14 Jul 2026 11:25:54 +0100 Subject: [PATCH 17/53] Add orography to the output files --- .../source/driver/lfric2lfric_init_mod.f90 | 11 +++++++++++ .../initialisation/lfric2lfric_field_init_mod.f90 | 6 +++++- .../lfric2lfric_infrastructure_mod.X90 | 12 ++++++++++++ rose-stem/app/lfric2lfric/file/iodef_orography.xml | 2 ++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index ab634f2457..b2f5dcf828 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -19,6 +19,10 @@ module lfric2lfric_init_mod log_level_info use mesh_mod, only: mesh_type use netcdf, only: nf90_max_name + use orography_config_mod, only: orog_init_option, & + orog_init_option_analytic, & + orog_init_option_ancil, & + orog_init_option_start_dump ! lfric2lfric mods use lfric2lfric_config_mod, only: mode_ics, mode_lbc @@ -145,6 +149,13 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & prefix ) end do + if ( orog_init_option == orog_init_option_analytic .or. & + orog_init_option == orog_init_option_ancil .or. & + orog_init_option == orog_init_option_start_dump ) then + call field_maker(field_collection, trim('surface_altitude'), & + target_mesh, target_twod_mesh, prefix) + end if + !-------------------------------------------------------------------------- ! Initialise Intermediate Fields !-------------------------------------------------------------------------- diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 index 1b41ed2aa0..fe2be646bd 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 @@ -160,10 +160,14 @@ subroutine field_maker(field_collection, field_name, mesh, twod_mesh, prefix) cp_write_behaviour => checkpoint_write_xios if ( .NOT. field_collection%field_exists(field_name) ) then - ! Get function space from metadata + ! Get function space from metadata + call log_event("Before", & + LOG_LEVEL_INFO) vector_space => space_from_metadata(trim(prefix)//trim(field_name), & mesh_3d=mesh, & mesh_2d=twod_mesh ) + call log_event("After", & + LOG_LEVEL_INFO) ! Initialise the field call field%initialise(vector_space=vector_space, & diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index d97bc13728..8231ad2a9d 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -71,6 +71,8 @@ module lfric2lfric_infrastructure_mod use lfric2lfric_init_coupler_mod,only: lfric2lfric_init_coupler_src, & lfric2lfric_init_coupler_dst, & lfric2lfric_end_coupler_init + use lfric2lfric_field_init_mod, only: field_maker + use netcdf, only: nf90_max_name #ifdef MCT use coupling_mod, only: coupling_type, & get_coupling_from_collection @@ -217,6 +219,9 @@ contains type(coupler_exchange_2d_type) :: coupler_exchange_2d integer(kind=i_def) :: ierror logical(kind=l_def) :: is_running + + type(field_collection_type), pointer :: target_collection + type(field_type), pointer :: field !------------------------ ! XIOS contexts @@ -738,6 +743,13 @@ contains call blend_orography(surface_altitude_dst, surface_altitude_src_on_dst, & mesh_names(dst)) + ! Copy the destination (possibly blended) orography to the output fields + ! -------------------------------------------------------- + + target_collection => modeldb%fields%get_field_collection(target_collection_name) + call target_collection%get_field("surface_altitude", field) + call invoke(setval_X(field,surface_altitude_dst)) + ! Adjust the chi fields to account for the orography ! -------------------------------------------------------- ! source mesh, source extrusion, source orography diff --git a/rose-stem/app/lfric2lfric/file/iodef_orography.xml b/rose-stem/app/lfric2lfric/file/iodef_orography.xml index 787a8bb186..8cc65056a8 100644 --- a/rose-stem/app/lfric2lfric/file/iodef_orography.xml +++ b/rose-stem/app/lfric2lfric/file/iodef_orography.xml @@ -63,6 +63,8 @@ + + From ac9165b15712020c910216150633fe7a3bef9570 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Tue, 14 Jul 2026 12:12:34 +0100 Subject: [PATCH 18/53] vertical_change horizontal_change logic --- .../source/driver/lfric2lfric_driver_mod.F90 | 38 ++++++------------ .../lfric2lfric_infrastructure_mod.X90 | 39 +++++++++++-------- .../lfric2lfric/source/lfric2lfric.F90 | 9 +++-- 3 files changed, 40 insertions(+), 46 deletions(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 071af9bb00..70026d240b 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -24,6 +24,9 @@ module lfric2lfric_driver_mod use sci_checksum_alg_mod, only: checksum_alg use xios, only: xios_date, xios_get_current_date, & xios_date_convert_to_string + use orography_config_mod, only: orog_init_option_analytic, & + orog_init_option_ancil, & + orog_init_option_start_dump !------------------------------------ ! lfric2lfric modules @@ -53,15 +56,17 @@ module lfric2lfric_driver_mod !! and fields. !> @param [in,out] modeldb The structure holding model state !> @param [in,out] oasis_clock Clock for OASIS exchanges - subroutine initialise( modeldb, oasis_clock ) + subroutine initialise( modeldb, oasis_clock, vertical_change, horizontal_change ) implicit none type(modeldb_type), intent(inout) :: modeldb type(model_clock_type), allocatable, & intent(inout) :: oasis_clock + logical(kind=l_def), intent(inout) :: vertical_change + logical(kind=l_def), intent(inout) :: horizontal_change - call initialise_infrastructure( modeldb, oasis_clock ) + call initialise_infrastructure( modeldb, oasis_clock, vertical_change, horizontal_change ) end subroutine initialise @@ -73,13 +78,15 @@ end subroutine initialise !! XIOS context and writes to an output file. !> @param [in,out] modeldb The structure that holds model state !> @param [in,out] oasis_clock Clock for OASIS exchanges - subroutine run( modeldb, oasis_clock ) + subroutine run( modeldb, oasis_clock, vertical_change, horizontal_change ) implicit none type(modeldb_type), intent(inout) :: modeldb type(model_clock_type), allocatable, & intent(inout) :: oasis_clock + logical(kind=l_def), intent(in) :: vertical_change + logical(kind=l_def), intent(in) :: horizontal_change ! LFRic-XIOS constants integer(kind=i_def), parameter :: start_timestep = 1_i_def @@ -112,13 +119,12 @@ subroutine run( modeldb, oasis_clock ) integer(kind=i_def) :: dst_number_of_layers integer(kind=i_def) :: src_stretching_method integer(kind=i_def) :: dst_stretching_method + integer(kind=i_def) :: orog_init_option real(kind=r_def) :: src_domain_height real(kind=r_def) :: dst_domain_height real(kind=r_def) :: src_stretching_height real(kind=r_def) :: dst_stretching_height - logical(l_def) :: horizontal_change, vertical_change - src_extrusion_method = modeldb%config%extrusion%method() src_number_of_layers = modeldb%config%extrusion%number_of_layers() src_domain_height = modeldb%config%extrusion%domain_height() @@ -129,30 +135,10 @@ subroutine run( modeldb, oasis_clock ) dst_domain_height = modeldb%config%extrusion_dst%domain_height() dst_stretching_height = modeldb%config%extrusion_dst%stretching_height() dst_stretching_method = modeldb%config%extrusion_dst%stretching_method() + orog_init_option = modeldb%config%orography%orog_init_option() mesh_names(dst) = modeldb%config%lfric2lfric%destination_mesh_name() mesh_names(src) = modeldb%config%lfric2lfric%source_mesh_name() - - vertical_change = .false. - if ( src_extrusion_method /= dst_extrusion_method ) then - vertical_change = .true. - end if - if ( src_number_of_layers /= dst_number_of_layers ) then - vertical_change = .true. - end if - if ( src_domain_height /= dst_domain_height ) then - vertical_change = .true. - end if - if ( src_stretching_height /= dst_stretching_height ) then - vertical_change = .true. - end if - if ( src_stretching_method /= dst_stretching_method ) then - vertical_change = .true. - end if - horizontal_change = .false. - if ( mesh_names(dst) /= mesh_names(src) ) then - horizontal_change = .true. - end if ! Extract configuration variables start_dump_filename = modeldb%config%files%start_dump_filename() diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 8231ad2a9d..f8046e4b11 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -105,6 +105,9 @@ module lfric2lfric_infrastructure_mod source_topology_non_periodic, & source_geometry_planar, & source_geometry_spherical + use orography_config_mod, only: orog_init_option_analytic, & + orog_init_option_ancil, & + orog_init_option_start_dump implicit none @@ -134,14 +137,16 @@ contains !! fields. !> @param [in,out] modeldb The structure holding model state !> @param [in,out] oasis_clock Clock for OASIS exchanges - subroutine initialise_infrastructure( modeldb, oasis_clock ) + subroutine initialise_infrastructure( modeldb, oasis_clock, vertical_change, horizontal_change ) implicit none type(modeldb_type), intent(inout) :: modeldb type(model_clock_type), allocatable, & intent(inout) :: oasis_clock - + logical(kind=l_def), intent(inout) :: vertical_change + logical(kind=l_def), intent(inout) :: horizontal_change + ! Coordinate field type(field_type), pointer :: chi(:) type(field_type), pointer :: panel_id @@ -172,7 +177,6 @@ contains class(extrusion_type), allocatable :: dst_extrusion type(uniform_extrusion_type), allocatable :: extrusion_2d - ! Namelist parameters character(len=str_def) :: mesh_names(2) character(len=str_def), allocatable :: mesh_names_dst_ext(:) @@ -196,14 +200,12 @@ contains integer(kind=i_def) :: dst_number_of_layers integer(kind=i_def) :: src_stretching_method integer(kind=i_def) :: dst_stretching_method + integer(kind=i_def) :: orog_init_option real(kind=r_def) :: src_domain_height real(kind=r_def) :: dst_domain_height real(kind=r_def) :: src_stretching_height real(kind=r_def) :: dst_stretching_height - logical(kind=l_def) :: vertical_change - logical(kind=l_def) :: horizontal_change - integer(i_def) :: tile_size_x integer(i_def) :: tile_size_y logical(l_def) :: inner_halo_tiles @@ -259,6 +261,7 @@ contains dst_domain_height = modeldb%config%extrusion_dst%domain_height() dst_stretching_height = modeldb%config%extrusion_dst%stretching_height() dst_stretching_method = modeldb%config%extrusion_dst%stretching_method() + orog_init_option = modeldb%config%orography%orog_init_option() mode = modeldb%config%lfric2lfric%mode() regrid_method = modeldb%config%lfric2lfric%regrid_method() @@ -277,22 +280,24 @@ contains tile_size_y = 1 inner_halo_tiles = .false. + ! Vertical interpolation is required if there is a change in the vertical + ! extrusion, or a change in the orography vertical_change = .false. - if ( src_extrusion_method /= dst_extrusion_method ) then + if ( src_extrusion_method /= dst_extrusion_method .or. & + src_number_of_layers /= dst_number_of_layers .or. & + src_domain_height /= dst_domain_height .or. & + src_stretching_height /= dst_stretching_height .or. & + src_stretching_method /= dst_stretching_method ) then vertical_change = .true. end if - if ( src_number_of_layers /= dst_number_of_layers ) then - vertical_change = .true. - end if - if ( src_domain_height /= dst_domain_height ) then - vertical_change = .true. - end if - if ( src_stretching_height /= dst_stretching_height ) then - vertical_change = .true. - end if - if ( src_stretching_method /= dst_stretching_method ) then + if ( orog_init_option == orog_init_option_analytic .or. & + orog_init_option == orog_init_option_ancil .or. & + orog_init_option == orog_init_option_start_dump ) then vertical_change = .true. end if + + ! Horizontal interpolation is required if there is a change + ! in the mesh (horizontal grid) horizontal_change = .false. if ( mesh_names(dst) /= mesh_names(src) ) then horizontal_change = .true. diff --git a/applications/lfric2lfric/source/lfric2lfric.F90 b/applications/lfric2lfric/source/lfric2lfric.F90 index 6a260e03ca..2e1f1e9067 100644 --- a/applications/lfric2lfric/source/lfric2lfric.F90 +++ b/applications/lfric2lfric/source/lfric2lfric.F90 @@ -15,7 +15,7 @@ program lfric2lfric use cli_mod, only: parse_command_line - use constants_mod, only: precision_real + use constants_mod, only: precision_real, l_def use driver_collections_mod, only: init_collections, final_collections use driver_config_mod, only: init_config, final_config use driver_comm_mod, only: init_comm, final_comm @@ -48,6 +48,9 @@ program lfric2lfric ! Clock for OASIS exchanges type(model_clock_type), allocatable :: oasis_clock + logical(kind=l_def) :: vertical_change + logical(kind=l_def) :: horizontal_change + call parse_command_line( filename ) call modeldb%config%initialise( program_name ) @@ -86,9 +89,9 @@ program lfric2lfric call modeldb%io_contexts%initialise(program_name, 100) call log_event( 'Initialising ' // program_name // ' ...', log_level_trace ) - call initialise( modeldb, oasis_clock ) + call initialise( modeldb, oasis_clock, vertical_change, horizontal_change ) - call run( modeldb, oasis_clock ) + call run( modeldb, oasis_clock, vertical_change, horizontal_change ) call log_event( 'Finalising ' // program_name // ' ...', log_level_trace ) call finalise( program_name, modeldb ) From 6beaf6d83b7c54b184bed6aba8a510df69d37e1d Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:43:54 +0100 Subject: [PATCH 19/53] corrections --- applications/lfric2lfric/example/configuration.nml | 4 ++++ .../source/driver/lfric2lfric_init_mod.f90 | 8 ++++++-- .../lfric2lfric_infrastructure_mod.X90 | 12 +++++++----- .../app/lfric2lfric/opt/rose-app-C12_C16_lam.conf | 2 -- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/applications/lfric2lfric/example/configuration.nml b/applications/lfric2lfric/example/configuration.nml index fe12fd4a2b..1a4edc1deb 100644 --- a/applications/lfric2lfric/example/configuration.nml +++ b/applications/lfric2lfric/example/configuration.nml @@ -106,3 +106,7 @@ coord_space = 'Wchi', &planet scaling_factor = 125.0, / + +&orography + orog_init_option = 'none' +/ \ No newline at end of file diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index b2f5dcf828..c2518ea437 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -152,8 +152,12 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & if ( orog_init_option == orog_init_option_analytic .or. & orog_init_option == orog_init_option_ancil .or. & orog_init_option == orog_init_option_start_dump ) then - call field_maker(field_collection, trim('surface_altitude'), & - target_mesh, target_twod_mesh, prefix) + if ( mode == mode_ics ) then + + call field_maker(field_collection, trim('surface_altitude'), & + target_mesh, target_twod_mesh, prefix) + + end if end if !-------------------------------------------------------------------------- diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index f8046e4b11..bc5f267010 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -750,11 +750,13 @@ contains ! Copy the destination (possibly blended) orography to the output fields ! -------------------------------------------------------- - - target_collection => modeldb%fields%get_field_collection(target_collection_name) - call target_collection%get_field("surface_altitude", field) - call invoke(setval_X(field,surface_altitude_dst)) - + + if (mode == mode_ics) then + target_collection => modeldb%fields%get_field_collection(target_collection_name) + call target_collection%get_field("surface_altitude", field) + call invoke(setval_X(field,surface_altitude_dst)) + end if + ! Adjust the chi fields to account for the orography ! -------------------------------------------------------- ! source mesh, source extrusion, source orography diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf b/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf index 330c8f6e26..950011de21 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf @@ -15,5 +15,3 @@ source_meshfile_prefix='${MESH_DIR}/C24_C12/mesh_C24_C12' src_ancil_directory='$BIG_DATA_DIR/ancils/basic-gagl/Puku/C12/n96e' src_orography_mean_ancil_path='orography/globe30/qrparm.orog.ugrid' -[namelist:orography] -orog_init_option='ancil' From 64f858402092d53e303676511fbc7b17acdcae2c Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 08:44:40 +0100 Subject: [PATCH 20/53] correction --- applications/lfric2lfric/example/configuration.nml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/lfric2lfric/example/configuration.nml b/applications/lfric2lfric/example/configuration.nml index 1a4edc1deb..d25b8274cf 100644 --- a/applications/lfric2lfric/example/configuration.nml +++ b/applications/lfric2lfric/example/configuration.nml @@ -109,4 +109,4 @@ coord_space = 'Wchi', &orography orog_init_option = 'none' -/ \ No newline at end of file +/ From 2325001d3de7ec719a4ff0be515113debb82afaa Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 09:50:34 +0100 Subject: [PATCH 21/53] use modeldb for logicals horizontal_change and vertical_change --- .../source/driver/lfric2lfric_driver_mod.F90 | 23 ++++++++++--------- .../source/driver/lfric2lfric_init_mod.f90 | 11 +++++---- .../lfric2lfric_infrastructure_mod.X90 | 12 ++++++---- .../lfric2lfric/source/lfric2lfric.F90 | 7 ++---- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 70026d240b..983e0d2800 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -56,17 +56,15 @@ module lfric2lfric_driver_mod !! and fields. !> @param [in,out] modeldb The structure holding model state !> @param [in,out] oasis_clock Clock for OASIS exchanges - subroutine initialise( modeldb, oasis_clock, vertical_change, horizontal_change ) + subroutine initialise( modeldb, oasis_clock ) implicit none type(modeldb_type), intent(inout) :: modeldb type(model_clock_type), allocatable, & intent(inout) :: oasis_clock - logical(kind=l_def), intent(inout) :: vertical_change - logical(kind=l_def), intent(inout) :: horizontal_change - call initialise_infrastructure( modeldb, oasis_clock, vertical_change, horizontal_change ) + call initialise_infrastructure( modeldb, oasis_clock ) end subroutine initialise @@ -78,15 +76,13 @@ end subroutine initialise !! XIOS context and writes to an output file. !> @param [in,out] modeldb The structure that holds model state !> @param [in,out] oasis_clock Clock for OASIS exchanges - subroutine run( modeldb, oasis_clock, vertical_change, horizontal_change ) + subroutine run( modeldb, oasis_clock ) implicit none type(modeldb_type), intent(inout) :: modeldb type(model_clock_type), allocatable, & intent(inout) :: oasis_clock - logical(kind=l_def), intent(in) :: vertical_change - logical(kind=l_def), intent(in) :: horizontal_change ! LFRic-XIOS constants integer(kind=i_def), parameter :: start_timestep = 1_i_def @@ -125,6 +121,10 @@ subroutine run( modeldb, oasis_clock, vertical_change, horizontal_change ) real(kind=r_def) :: src_stretching_height real(kind=r_def) :: dst_stretching_height + logical(kind=l_def), pointer :: vertical_change + logical(kind=l_def), pointer :: horizontal_change + + ! Extract configuration variables src_extrusion_method = modeldb%config%extrusion%method() src_number_of_layers = modeldb%config%extrusion%number_of_layers() src_domain_height = modeldb%config%extrusion%domain_height() @@ -137,10 +137,8 @@ subroutine run( modeldb, oasis_clock, vertical_change, horizontal_change ) dst_stretching_method = modeldb%config%extrusion_dst%stretching_method() orog_init_option = modeldb%config%orography%orog_init_option() - mesh_names(dst) = modeldb%config%lfric2lfric%destination_mesh_name() - mesh_names(src) = modeldb%config%lfric2lfric%source_mesh_name() - - ! Extract configuration variables + mesh_names(dst) = modeldb%config%lfric2lfric%destination_mesh_name() + mesh_names(src) = modeldb%config%lfric2lfric%source_mesh_name() start_dump_filename = modeldb%config%files%start_dump_filename() checkpoint_stem_name = modeldb%config%files%checkpoint_stem_name() @@ -151,6 +149,9 @@ subroutine run( modeldb, oasis_clock, vertical_change, horizontal_change ) source_fields => modeldb%fields%get_field_collection(source_collection_name) target_fields => modeldb%fields%get_field_collection(target_collection_name) + call modeldb%values%get_value("vertical_change", vertical_change) + call modeldb%values%get_value("horizontal_change", horizontal_change) + if (horizontal_change .and. vertical_change) then interm_fields => modeldb%fields%get_field_collection(interm_collection_name) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index c2518ea437..7ca5bf329a 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -44,8 +44,6 @@ module lfric2lfric_init_mod !! will hold the file to be written !> @param [in] start_dump_filename File to get field names from !> @param [in] mode Process ics or lbcs - !> @param [in] horizontal_change Logical for horizontal regridding - !> @param [in] vertical_change Logical for vertical regridding !> @param [in] origin_collection_name Holds the origin fields !> @param [in] origin_mesh Mesh to initialise 3D fields !> @param [in] origin_twod_mesh Mesh to initialise 2D fields @@ -57,7 +55,6 @@ module lfric2lfric_init_mod !> @param [in] target_twod_mesh Mesh for target 2D fields subroutine init_lfric2lfric( modeldb, context_src, context_dst, & start_dump_filename, mode, & - horizontal_change, vertical_change, & origin_collection_name, & origin_mesh, origin_twod_mesh, & interm_collection_name, & @@ -72,8 +69,6 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & character(len=*), intent(in) :: context_dst character(len=*), intent(in) :: start_dump_filename integer(i_def), intent(in) :: mode - logical(l_def), intent(in) :: horizontal_change - logical(l_def), intent(in) :: vertical_change character(len=*), intent(in) :: origin_collection_name type(mesh_type), intent(in), pointer :: origin_mesh type(mesh_type), intent(in), pointer :: origin_twod_mesh @@ -84,6 +79,9 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & type(mesh_type), intent(in), pointer :: target_mesh type(mesh_type), intent(in), pointer :: target_twod_mesh + logical(l_def), pointer :: horizontal_change + logical(l_def), pointer :: vertical_change + ! For field creation and storage type(field_collection_type), pointer :: field_collection @@ -100,6 +98,9 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call log_event( 'lfric2lfric: Initialising miniapp ...', log_level_info ) + call modeldb%values%get_value("vertical_change", vertical_change) + call modeldb%values%get_value("horizontal_change", horizontal_change) + if (mode == mode_ics) then prefix = 'restart_' else if (mode == mode_lbc) then diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index bc5f267010..4bf0e10bb2 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -137,15 +137,13 @@ contains !! fields. !> @param [in,out] modeldb The structure holding model state !> @param [in,out] oasis_clock Clock for OASIS exchanges - subroutine initialise_infrastructure( modeldb, oasis_clock, vertical_change, horizontal_change ) + subroutine initialise_infrastructure( modeldb, oasis_clock ) implicit none type(modeldb_type), intent(inout) :: modeldb type(model_clock_type), allocatable, & intent(inout) :: oasis_clock - logical(kind=l_def), intent(inout) :: vertical_change - logical(kind=l_def), intent(inout) :: horizontal_change ! Coordinate field type(field_type), pointer :: chi(:) @@ -206,6 +204,9 @@ contains real(kind=r_def) :: src_stretching_height real(kind=r_def) :: dst_stretching_height + logical(kind=l_def) :: vertical_change + logical(kind=l_def) :: horizontal_change + integer(i_def) :: tile_size_x integer(i_def) :: tile_size_y logical(l_def) :: inner_halo_tiles @@ -303,6 +304,9 @@ contains horizontal_change = .true. end if + call modeldb%values%add_key_value('vertical_change', vertical_change) + call modeldb%values%add_key_value('horizontal_change', horizontal_change) + !======================================================================= ! Mesh !======================================================================= @@ -645,14 +649,12 @@ contains if (mode == mode_ics) then call init_lfric2lfric( modeldb, context_src, context_dst, & start_dump_filename, mode, & - horizontal_change, vertical_change, & source_collection_name, mesh_src, twod_mesh_src, & interm_collection_name, mesh_interm, twod_mesh_dst, & target_collection_name, mesh_dst, twod_mesh_dst ) else if (mode == mode_lbc) then call init_lfric2lfric( modeldb, context_src, context_dst, & source_file_lbc, mode, & - horizontal_change, vertical_change, & source_collection_name, mesh_src, twod_mesh_src, & interm_collection_name, mesh_interm, twod_mesh_dst, & target_collection_name, mesh_dst, twod_mesh_dst ) diff --git a/applications/lfric2lfric/source/lfric2lfric.F90 b/applications/lfric2lfric/source/lfric2lfric.F90 index 2e1f1e9067..dccb133db8 100644 --- a/applications/lfric2lfric/source/lfric2lfric.F90 +++ b/applications/lfric2lfric/source/lfric2lfric.F90 @@ -47,9 +47,6 @@ program lfric2lfric #endif ! Clock for OASIS exchanges type(model_clock_type), allocatable :: oasis_clock - - logical(kind=l_def) :: vertical_change - logical(kind=l_def) :: horizontal_change call parse_command_line( filename ) @@ -89,9 +86,9 @@ program lfric2lfric call modeldb%io_contexts%initialise(program_name, 100) call log_event( 'Initialising ' // program_name // ' ...', log_level_trace ) - call initialise( modeldb, oasis_clock, vertical_change, horizontal_change ) + call initialise( modeldb, oasis_clock ) - call run( modeldb, oasis_clock, vertical_change, horizontal_change ) + call run( modeldb, oasis_clock ) call log_event( 'Finalising ' // program_name // ' ...', log_level_trace ) call finalise( program_name, modeldb ) From f732f3e76f84075687090d6212a465eeca4a1dab Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 10:25:57 +0100 Subject: [PATCH 22/53] log messages --- .../lfric2lfric_field_init_mod.f90 | 4 ---- .../lfric2lfric_infrastructure_mod.X90 | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 index fe2be646bd..867ab70a23 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 @@ -161,13 +161,9 @@ subroutine field_maker(field_collection, field_name, mesh, twod_mesh, prefix) if ( .NOT. field_collection%field_exists(field_name) ) then ! Get function space from metadata - call log_event("Before", & - LOG_LEVEL_INFO) vector_space => space_from_metadata(trim(prefix)//trim(field_name), & mesh_3d=mesh, & mesh_2d=twod_mesh ) - call log_event("After", & - LOG_LEVEL_INFO) ! Initialise the field call field%initialise(vector_space=vector_space, & diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 4bf0e10bb2..75b663bf1d 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -47,6 +47,7 @@ module lfric2lfric_infrastructure_mod use lfric_xios_action_mod, only: advance use log_mod, only: log_event, & log_scratch_space, & + log_level_info, & log_level_error, & log_level_debug use mesh_mod, only: mesh_type @@ -306,7 +307,21 @@ contains call modeldb%values%add_key_value('vertical_change', vertical_change) call modeldb%values%add_key_value('horizontal_change', horizontal_change) - + + if ( horizontal_change == .true. ) then + call log_event("Horizontal interpolation logical set to TRUE", & + log_level_info) + else + call log_event("Horizontal interpolation logical set to FALSE", & + log_level_info) + end if + if ( vertical_change == .true. ) then + call log_event("Vertical interpolation logical set to TRUE", & + log_level_info) + else + call log_event("Vertical interpolation logical set to FALSE", & + log_level_info) + end if !======================================================================= ! Mesh !======================================================================= From d27bb22451f286fdd6a93cbf6a3bb0e85d608aaf Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:04:52 +0100 Subject: [PATCH 23/53] tidy --- applications/lfric2lfric/source/lfric2lfric.F90 | 3 +-- rose-stem/app/lfric2lfric/opt/rose-app-C12.conf | 8 ++++---- .../site/common/lfric2lfric/tasks_lfric2lfric.cylc | 10 +++++----- rose-stem/site/meto/groups/groups_lfric2lfric.cylc | 2 ++ 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/applications/lfric2lfric/source/lfric2lfric.F90 b/applications/lfric2lfric/source/lfric2lfric.F90 index dccb133db8..0a0e1ee539 100644 --- a/applications/lfric2lfric/source/lfric2lfric.F90 +++ b/applications/lfric2lfric/source/lfric2lfric.F90 @@ -15,7 +15,7 @@ program lfric2lfric use cli_mod, only: parse_command_line - use constants_mod, only: precision_real, l_def + use constants_mod, only: precision_real use driver_collections_mod, only: init_collections, final_collections use driver_config_mod, only: init_config, final_config use driver_comm_mod, only: init_comm, final_comm @@ -47,7 +47,6 @@ program lfric2lfric #endif ! Clock for OASIS exchanges type(model_clock_type), allocatable :: oasis_clock - call parse_command_line( filename ) call modeldb%config%initialise( program_name ) diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-C12.conf b/rose-stem/app/lfric2lfric/opt/rose-app-C12.conf index a6d7d25af7..87cbe9951d 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-C12.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-C12.conf @@ -1,5 +1,5 @@ [namelist:lfric2lfric] -destination_mesh_name='C12' -destination_meshfile_prefix='${MESH_DIR}/C24_C12/mesh_C24_C12' -source_mesh_name='C12' -source_meshfile_prefix='${MESH_DIR}/C24_C12/mesh_C24_C12' +destination_mesh_name='dynamics' +destination_meshfile_prefix='${MESH_DIR}/C12/mesh_C12' +source_mesh_name='dynamics' +source_meshfile_prefix='${MESH_DIR}/C12/mesh_C12' diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index a2e035a9d1..07019d9b27 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -155,11 +155,11 @@ {% do task_dict.update({ "opt_confs": ["clim_gal9","oasis","src_L70_80km","dst_L38_40km"], "resolution": "C12", - "dst_mesh": "C24_C12", - "dst_name": "C12", + "dst_mesh": "C12", + "dst_name": "dynamics", "dst_type": "global", - "src_mesh": "C24_C12", - "src_name": "C12", + "src_mesh": "C12", + "src_name": "dynamics", "src_type": "global", }) %} @@ -174,7 +174,7 @@ "src_mesh": "C24_C12", "src_name": "C12", "src_type": "global", - "mpi_parts": 6, + "mpi_parts": 6, }) %} {% elif task_ns.conf_name == "oasis_clim_gal9_C12-ral_seuk_C16_lam_1cpu" %} diff --git a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc index f8a76189b0..23c622d4d2 100644 --- a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc +++ b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc @@ -52,6 +52,8 @@ "lfric2lfric_oasis_clim_gal9-C24_C12_6cpu_ex1a_cce_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam_1cpu_ex1a_cce_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam-lbc_1cpu_ex1a_cce_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_seukL38_ex1a_cce_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_C12L38_ex1a_cce_fast-debug-64bit", "lfric2lfric_ex1a_canned", ], "lfric2lfric_ex1a_extra": [ From 159085e09e6bc0e120660f721e1aa5051b6d56b7 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:21:58 +0100 Subject: [PATCH 24/53] tidy --- .../lfric-lfric2lfric/HEAD/rose-meta.conf | 14 +++++++------- .../source/algorithm/lfric2lfric_vert_mod.x90 | 16 ++++++++++++---- .../lfric2lfric_infrastructure_mod.X90 | 4 ++-- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf index 93b8ca5936..ecb0cdc604 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf @@ -318,12 +318,12 @@ type=real compulsory=true description=Method for generating eta coordinate !enumeration=true -fail-if=this == 'um_L38_29t_9s_40km' and namelist:extrusion=number_of_layers != 38 ; - =this == 'um_L70_50t_20s_80km' and namelist:extrusion=number_of_layers != 70 ; - =this == 'um_L85_50t_35s_85km' and namelist:extrusion=number_of_layers != 85 ; - =this == 'um_L70_61t_9s_40km' and namelist:extrusion=number_of_layers != 70 ; - =this == 'um_L120_99t_21s_40km' and namelist:extrusion=number_of_layers != 120 ; - =this == 'um_L140_122t_18s_40km' and namelist:extrusion=number_of_layers != 140 ; +fail-if=this == 'um_L38_29t_9s_40km' and namelist:extrusion_dst=number_of_layers != 38 ; + =this == 'um_L70_50t_20s_80km' and namelist:extrusion_dst=number_of_layers != 70 ; + =this == 'um_L85_50t_35s_85km' and namelist:extrusion_dst=number_of_layers != 85 ; + =this == 'um_L70_61t_9s_40km' and namelist:extrusion_dst=number_of_layers != 70 ; + =this == 'um_L120_99t_21s_40km' and namelist:extrusion_dst=number_of_layers != 120 ; + =this == 'um_L140_122t_18s_40km' and namelist:extrusion_dst=number_of_layers != 140 ; help=Available extrusion methods are (\f$n$ is number of layers): =1) Uniform eta spacing (\f$\frac{k}{n}\f$); =2) Quadratic eta spacing (\f$\frac{k}{n}^2\f$); @@ -389,7 +389,7 @@ help=Available stretching methods are: =1) Linear (linear multiple of physical depth) =2) Smooth (quadratic below stretching_height, linear above) sort-key=Panel-A01 -trigger=namelist:extrusion=stretching_height: 'smooth' ; +trigger=namelist:extrusion_dst=stretching_height: 'smooth' ; value-titles=Linear, Smooth values='linear', 'smooth' diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 index f54d199d65..d13d88b281 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -1,3 +1,11 @@ +!----------------------------------------------------------------------------- +! (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 Apply vertical regridding using the vertical regridding kernels +!! and height values for the source and target vertically extruded +!! meshes. module lfric2lfric_vert_mod use constants_mod, only: str_def, i_def @@ -23,7 +31,7 @@ contains !> @brief Apply vertical regridding !> @details Loop over the fields in the source_fields collection, - !! and apply the vertical regridding to obtain the regridded + !! and apply the vertical regridding kernels to obtain the regridded !! field in the target_fields collection. !> @param modeldb Model state object !> @param source_fields The collection of fields to be regridded @@ -73,11 +81,11 @@ contains height_src => get_height_fv(modeldb%config, mesh_src, fs_src) height_dst => get_height_fv(modeldb%config, mesh_dst, fs_dst) - ! Dummy initialisation. This will be replaced with actual - ! vertical regridding from #253. + ! Dummy initialisation - just writing out the heights + ! TODO Replaced the dummy initialisation with actual + ! vertical regridding from #253. i.e. ! call invoke( lfric2lfric_vert_lin_interp_lin_extrap_code_r_single( & ! field_dst, field_src, height_dst, height_src)) - ! At the moment just writing out the heights. call invoke(setval_X(field_dst, height_dst)) enddo diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 75b663bf1d..8d0daaf343 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -308,14 +308,14 @@ contains call modeldb%values%add_key_value('vertical_change', vertical_change) call modeldb%values%add_key_value('horizontal_change', horizontal_change) - if ( horizontal_change == .true. ) then + if ( horizontal_change ) then call log_event("Horizontal interpolation logical set to TRUE", & log_level_info) else call log_event("Horizontal interpolation logical set to FALSE", & log_level_info) end if - if ( vertical_change == .true. ) then + if ( vertical_change ) then call log_event("Vertical interpolation logical set to TRUE", & log_level_info) else From 2468580d89731865a8555351c767184c65b59108 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 12:14:43 +0100 Subject: [PATCH 25/53] tidy --- applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 | 1 - .../source/initialisation/lfric2lfric_field_init_mod.f90 | 2 +- applications/lfric2lfric/source/lfric2lfric.F90 | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index 7ca5bf329a..ddf4404bf0 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -187,7 +187,6 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call modeldb%io_contexts%get_io_context(context_src, io_context) call io_context%set_current() - ! Now finished with config_list, deallocate deallocate(config_list) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 index 867ab70a23..1b41ed2aa0 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 @@ -160,7 +160,7 @@ subroutine field_maker(field_collection, field_name, mesh, twod_mesh, prefix) cp_write_behaviour => checkpoint_write_xios if ( .NOT. field_collection%field_exists(field_name) ) then - ! Get function space from metadata + ! Get function space from metadata vector_space => space_from_metadata(trim(prefix)//trim(field_name), & mesh_3d=mesh, & mesh_2d=twod_mesh ) diff --git a/applications/lfric2lfric/source/lfric2lfric.F90 b/applications/lfric2lfric/source/lfric2lfric.F90 index 0a0e1ee539..6a260e03ca 100644 --- a/applications/lfric2lfric/source/lfric2lfric.F90 +++ b/applications/lfric2lfric/source/lfric2lfric.F90 @@ -47,6 +47,7 @@ program lfric2lfric #endif ! Clock for OASIS exchanges type(model_clock_type), allocatable :: oasis_clock + call parse_command_line( filename ) call modeldb%config%initialise( program_name ) From d14bbe0fee9a3e3adbd8abc5036e3e9bf61be954 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 13:35:58 +0100 Subject: [PATCH 26/53] reorganise extrusions, and whitespace --- .../source/algorithm/lfric2lfric_vert_mod.x90 | 10 +- .../source/driver/lfric2lfric_driver_mod.F90 | 8 +- .../source/driver/lfric2lfric_init_mod.f90 | 8 +- .../lfric2lfric_infrastructure_mod.X90 | 125 +++--------------- 4 files changed, 28 insertions(+), 123 deletions(-) diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 index d13d88b281..dbbd966d00 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -23,7 +23,7 @@ module lfric2lfric_vert_mod log_scratch_space implicit none - + private public :: lfric2lfric_vert @@ -53,10 +53,10 @@ contains type(field_type), pointer :: height_dst type(mesh_type), pointer :: mesh_src type(mesh_type), pointer :: mesh_dst - + character(len=str_def) :: field_name integer(kind=i_def) :: fs_src, fs_dst - + ! Main loop over fields to be processed call iter%initialise(source_fields) do @@ -67,7 +67,7 @@ contains call source_fields%get_field(field_name, field_src) call target_fields%get_field(field_name, field_dst) - + write(log_scratch_space, '(A,A)') "Processing lfric field ", & trim(field_name) call log_event(log_scratch_space, log_level_info) @@ -88,7 +88,7 @@ contains ! field_dst, field_src, height_dst, height_src)) call invoke(setval_X(field_dst, height_dst)) enddo - + end subroutine lfric2lfric_vert end module lfric2lfric_vert_mod diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 983e0d2800..0e5f16b007 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -151,13 +151,13 @@ subroutine run( modeldb, oasis_clock ) call modeldb%values%get_value("vertical_change", vertical_change) call modeldb%values%get_value("horizontal_change", horizontal_change) - + if (horizontal_change .and. vertical_change) then interm_fields => modeldb%fields%get_field_collection(interm_collection_name) - + else if (horizontal_change .and. .not. vertical_change) then interm_fields => modeldb%fields%get_field_collection(target_collection_name) - + else if (vertical_change .and. .not. horizontal_change) then interm_fields => modeldb%fields%get_field_collection(source_collection_name) end if @@ -173,7 +173,7 @@ subroutine run( modeldb, oasis_clock ) if (vertical_change) then call lfric2lfric_vert(modeldb, interm_fields, target_fields) end if - + ! Write output call modeldb%io_contexts%get_io_context(context_dst, io_context) call io_context%set_current() diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index ddf4404bf0..c6be9c3651 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -81,7 +81,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & logical(l_def), pointer :: horizontal_change logical(l_def), pointer :: vertical_change - + ! For field creation and storage type(field_collection_type), pointer :: field_collection @@ -100,7 +100,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call modeldb%values%get_value("vertical_change", vertical_change) call modeldb%values%get_value("horizontal_change", horizontal_change) - + if (mode == mode_ics) then prefix = 'restart_' else if (mode == mode_lbc) then @@ -154,7 +154,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & orog_init_option == orog_init_option_ancil .or. & orog_init_option == orog_init_option_start_dump ) then if ( mode == mode_ics ) then - + call field_maker(field_collection, trim('surface_altitude'), & target_mesh, target_twod_mesh, prefix) @@ -183,7 +183,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & prefix ) end do end if - + call modeldb%io_contexts%get_io_context(context_src, io_context) call io_context%set_current() diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 8d0daaf343..4763e6da94 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -16,8 +16,7 @@ module lfric2lfric_infrastructure_mod use blend_orography_alg_mod, only: blend_orography use constants_mod, only: str_def, str_max_filename, & r_def, i_def, l_def, r_second - use create_mesh_mod, only: create_extrusion, & - create_mesh + use create_mesh_mod, only: create_mesh use driver_modeldb_mod, only: modeldb_type use driver_fem_mod, only: init_fem use driver_io_mod, only: init_io, & @@ -31,13 +30,7 @@ module lfric2lfric_infrastructure_mod use fs_continuity_mod, only: W3 use function_space_collection_mod,only: function_space_collection use function_space_mod, only: function_space_type - use gungho_extrusion_mod, only: dcmip_extrusion_type, & - um_L38_29t_9s_40km_extrusion_type, & - um_L85_50t_35s_85km_extrusion_type, & - um_L70_61t_9s_40km_extrusion_type, & - um_L120_99t_21s_40km_extrusion_type, & - um_L140_122t_18s_40km_extrusion_type, & - um_L70_50t_20s_80km_extrusion_type + use gungho_extrusion_mod, only: create_extrusion use sci_geometric_constants_mod, only: get_chi_inventory, & get_panel_id_inventory use init_altitude_mod, only: init_altitude @@ -356,109 +349,21 @@ contains log_level_error) end select - select case (src_extrusion_method) - case (method_uniform, method_quadratic, method_geometric) - allocate( src_extrusion, source=create_extrusion( & - src_extrusion_method, src_domain_height, & - domain_bottom, src_number_of_layers, & - prime_extrusion ) ) - - case (method_dcmip) - allocate( src_extrusion, source=dcmip_extrusion_type( & - domain_bottom, src_domain_height, & - src_number_of_layers, prime_extrusion ) ) - - case (method_um_L38_29t_9s_40km) - allocate( src_extrusion, source=um_l38_29t_9s_40km_extrusion_type( & - domain_bottom, src_domain_height, & - src_number_of_layers, prime_extrusion ) ) - - case (method_um_L85_50t_35s_85km) - allocate( src_extrusion, source=um_l85_50t_35s_85km_extrusion_type( & - domain_bottom, src_domain_height, & - src_number_of_layers, prime_extrusion ) ) - - case (method_um_L70_50t_20s_80km) - allocate( src_extrusion, source=um_l70_50t_20s_80km_extrusion_type( & - domain_bottom, src_domain_height, & - src_number_of_layers, prime_extrusion ) ) - - case (method_um_L70_61t_9s_40km) - allocate( src_extrusion, source=um_l70_61t_9s_40km_extrusion_type( & - domain_bottom, src_domain_height, & - src_number_of_layers, prime_extrusion ) ) - - case (method_um_L120_99t_21s_40km) - allocate( src_extrusion, source=um_L120_99t_21s_40km_extrusion_type( & - domain_bottom, src_domain_height, & - src_number_of_layers, prime_extrusion ) ) - - case (method_um_L140_122t_18s_40km) - allocate( src_extrusion, source=um_L140_122t_18s_40km_extrusion_type( & - domain_bottom, src_domain_height, & - src_number_of_layers, prime_extrusion ) ) - - case default - write( log_scratch_space, '(A)' ) & - "lfric2lfric_infrastructure_mod" // & - ': Unrecognised source extrusion method: ' // & - trim(key_from_method( src_extrusion_method )) - call log_event( log_scratch_space, log_level_error ) - - end select - + allocate( src_extrusion, source = & + create_extrusion( src_extrusion_method, & + source_geometry, & + src_number_of_layers, & + src_domain_height, & + scaled_radius )) + if (vertical_change) then - select case (dst_extrusion_method) - case (method_uniform, method_quadratic, method_geometric) - allocate( dst_extrusion, source=create_extrusion( & - dst_extrusion_method, dst_domain_height, & - domain_bottom, dst_number_of_layers, & - prime_extrusion ) ) - - case (method_dcmip) - allocate( dst_extrusion, source=dcmip_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L38_29t_9s_40km) - allocate( dst_extrusion, source=um_l38_29t_9s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L85_50t_35s_85km) - allocate( dst_extrusion, source=um_l85_50t_35s_85km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L70_50t_20s_80km) - allocate( dst_extrusion, source=um_l70_50t_20s_80km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L70_61t_9s_40km) - allocate( dst_extrusion, source=um_l70_61t_9s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L120_99t_21s_40km) - allocate( dst_extrusion, source=um_L120_99t_21s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case (method_um_L140_122t_18s_40km) - allocate( dst_extrusion, source=um_L140_122t_18s_40km_extrusion_type( & - domain_bottom, dst_domain_height, & - dst_number_of_layers, prime_extrusion ) ) - - case default - write( log_scratch_space, '(A)' ) & - "lfric2lfric_infrastructure_mod" // & - ': Unrecognised destination extrusion method: ' // & - trim(key_from_method( dst_extrusion_method )) - call log_event( log_scratch_space, log_level_error ) - - end select + allocate( dst_extrusion, source = & + create_extrusion( dst_extrusion_method, & + source_geometry, & + dst_number_of_layers, & + dst_domain_height, & + scaled_radius )) end if From 9ecb788f7f91a9862d5fbc04701d76ee4654cbb7 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:10:24 +0100 Subject: [PATCH 27/53] corrections and whitespace --- .../lfric2lfric_infrastructure_mod.X90 | 30 +++++++++---------- .../orography/blend_orography_alg_mod.x90 | 4 +-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 4763e6da94..7d68aedde3 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -138,7 +138,7 @@ contains type(modeldb_type), intent(inout) :: modeldb type(model_clock_type), allocatable, & intent(inout) :: oasis_clock - + ! Coordinate field type(field_type), pointer :: chi(:) type(field_type), pointer :: panel_id @@ -200,7 +200,7 @@ contains logical(kind=l_def) :: vertical_change logical(kind=l_def) :: horizontal_change - + integer(i_def) :: tile_size_x integer(i_def) :: tile_size_y logical(l_def) :: inner_halo_tiles @@ -219,7 +219,7 @@ contains type(field_collection_type), pointer :: target_collection type(field_type), pointer :: field - + !------------------------ ! XIOS contexts !------------------------ @@ -240,7 +240,7 @@ contains ! ------------------------------- ! Extract namelist variables ! ------------------------------- - + ! Check lfric2lfric configuration settings are allowed call lfric2lfric_check_configuration( modeldb%config ) @@ -278,7 +278,7 @@ contains ! Vertical interpolation is required if there is a change in the vertical ! extrusion, or a change in the orography vertical_change = .false. - if ( src_extrusion_method /= dst_extrusion_method .or. & + if ( src_extrusion_method /= dst_extrusion_method .or. & src_number_of_layers /= dst_number_of_layers .or. & src_domain_height /= dst_domain_height .or. & src_stretching_height /= dst_stretching_height .or. & @@ -290,7 +290,7 @@ contains orog_init_option == orog_init_option_start_dump ) then vertical_change = .true. end if - + ! Horizontal interpolation is required if there is a change ! in the mesh (horizontal grid) horizontal_change = .false. @@ -351,16 +351,16 @@ contains allocate( src_extrusion, source = & create_extrusion( src_extrusion_method, & - source_geometry, & + geometry, & src_number_of_layers, & src_domain_height, & scaled_radius )) - + if (vertical_change) then allocate( dst_extrusion, source = & create_extrusion( dst_extrusion_method, & - source_geometry, & + geometry, & dst_number_of_layers, & dst_domain_height, & scaled_radius )) @@ -385,7 +385,7 @@ contains mesh_names, src_extrusion, & inner_halo_tiles, tile_size, & stencil_depth, regrid_method ) - + allocate( mesh_names_dst_ext, source=mesh_names ) @@ -400,9 +400,9 @@ contains else do i=1, size(mesh_names) mesh_names_dst_ext(i) = trim(mesh_names(i)) - end do + end do end if - + allocate( twod_names, source=mesh_names ) do i=1, size(twod_names) twod_names(i) = trim(twod_names(i))//'_2d' @@ -443,7 +443,7 @@ contains ! mesh_names_dst_ext(dst) mesh_dst => mesh_collection%get_mesh(trim(mesh_names_dst_ext(dst))) twod_mesh_dst => mesh_collection%get_mesh(trim(twod_names(dst))) - + ! Log this change call log_event('Source mesh set to: ' // mesh_names(src), & log_level_debug) @@ -474,7 +474,7 @@ contains panel_id_inventory, & geometry, topology, & populate_filelist=files_init_ptr ) - + call modeldb%io_contexts%get_io_context(context_dst, io_context_dst) @@ -612,7 +612,7 @@ contains call log_event( log_scratch_space, log_level_error ) #endif end select - + !======================================================================= ! The lateral boundary conditions of limited-area models (LAMs) are ! implemented by updating the data values at the boundaries with values diff --git a/science/gungho/source/orography/blend_orography_alg_mod.x90 b/science/gungho/source/orography/blend_orography_alg_mod.x90 index 8038bf9b03..58815a7baa 100644 --- a/science/gungho/source/orography/blend_orography_alg_mod.x90 +++ b/science/gungho/source/orography/blend_orography_alg_mod.x90 @@ -19,7 +19,7 @@ module blend_orography_alg_mod LOG_LEVEL_INFO, & LOG_LEVEL_DEBUG, & LOG_LEVEL_ERROR - + implicit none public :: blend_orography @@ -50,7 +50,7 @@ contains call log_event( "Creating the blended orography (for LAMs)", & LOG_LEVEL_DEBUG ) - + ! Define the function space required for masks. fs_enum = lam_orog%which_function_space() mesh => lam_orog%get_mesh() From 6e599629db2b04ba5a05a1503715e4d0c6a98ce7 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:36:13 +0100 Subject: [PATCH 28/53] validate rose corrections --- .../lfric-lfric2lfric/HEAD/rose-meta.conf | 215 ++++++++++-------- .../lfric2lfric/opt/rose-app-C12_C16_lam.conf | 4 - .../opt/rose-app-clim_gal9_ral_seuk.conf | 12 + .../opt/rose-app-dst_L38_40km.conf | 2 +- .../opt/rose-app-src_L70_80km.conf | 2 +- rose-stem/app/lfric2lfric/rose-app.conf | 33 ++- 6 files changed, 152 insertions(+), 116 deletions(-) diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf index ecb0cdc604..2103c06787 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf @@ -7,6 +7,121 @@ compulsory=false compulsory=false !!trigger=namelist:partitioning: .false.; +[namelist:extrusion_dst] +compulsory=true +description=Vertical extrusion settings for the destination mesh. +help= +ns=namelist/Model/Mesh/Extrusion +sort-key=Section-A03 + +[namelist:extrusion_dst=domain_height] +compulsory=true +description=Height of domain above the surface [m] +fail-if=this < 0.0 ; +help=Height of the model domain above the surface. + =Surface is 0m for planar domains and planet_radius for spherical. +!kind=default +range=this > 0.0: +sort-key=Panel-A02 +type=real + +[namelist:extrusion_dst=eta_values] +!bounds=namelist:extrusion=number_of_layers-1 +compulsory=true +description=Eta values, excluding 0 and 1 +help=Non-dimensional height values defining the model vertical levels. + =The length should be smaller by number_of_layers by one. + = + =The values must strictly be between 0 and 1: + =0 < eta_values < 1 + =because 0 and 1 are appended to the list automatically. +!kind=default +length=: +range=0.0:1.0 +sort-key=Panel-A04 +type=real + +[namelist:extrusion_dst=method] +compulsory=true +description=Method for generating eta coordinate +!enumeration=true +fail-if=this == 'um_L38_29t_9s_40km' and namelist:extrusion_dst=number_of_layers != 38 ; + =this == 'um_L70_50t_20s_80km' and namelist:extrusion_dst=number_of_layers != 70 ; + =this == 'um_L85_50t_35s_85km' and namelist:extrusion_dst=number_of_layers != 85 ; + =this == 'um_L70_61t_9s_40km' and namelist:extrusion_dst=number_of_layers != 70 ; + =this == 'um_L120_99t_21s_40km' and namelist:extrusion_dst=number_of_layers != 120 ; + =this == 'um_L140_122t_18s_40km' and namelist:extrusion_dst=number_of_layers != 140 ; +help=Available extrusion methods are (\f$n$ is number of layers): + =0) Specified by user; + =1) Uniform eta spacing (\f$\frac{k}{n}\f$); + =2) Quadratic eta spacing (\f$\frac{k}{n}^2\f$); + =3) Geometric eta spacing (\f$d\eta = \frac{(s - 1)}{(s^{n} - 1)}$) + = with stretching factor prescribed (\f$s=1.03$); + =4) DCMIP eta spacing (Ullrich et al. (2012) DCMIP documentation, Appendix F.2.) + = with flattening parameter prescribed. + =5) L38 40km UM specific eta spacing; + =6) L70 80km UM specific eta spacing; + =7) L85 85km UM specific eta spacing; + =8) L70 40km UM specific eta spacing + =9) L120 40km UM specific eta spacing + =10) L140 40km UM specific eta spacing +sort-key=Panel-A01 +trigger=namelist:extrusion_dst=eta_values: 'specified_values'; +value-titles=Uniform, Quadratic, Geometric, DCMIP, + = um_L38_29t_9s_40km, um_L70_50t_20s_80km, um_L85_50t_35s_85km, um_L70_61t_9s_40km, + = um_L120_99t_21s_40km, um_L140_122t_18s_40km +values='uniform', 'quadratic', 'geometric', 'dcmip', + ='um_L38_29t_9s_40km', 'um_L70_50t_20s_80km', 'um_L85_50t_35s_85km', 'um_L70_61t_9s_40km', + ='um_L120_99t_21s_40km', 'um_L140_122t_18s_40km' + +[namelist:extrusion_dst=number_of_layers] +compulsory=true +description=Number of layers in the vertical +fail-if=this < 1 ; +help=Setting for number of layers of 3D-mesh in vertical. +!kind=default +range=1: +sort-key=Panel-A03 +type=integer + +[namelist:extrusion_dst=planet_radius] +compulsory=true +description=Radius of the planet surface [m] +fail-if=this <= 0.0 ; +help=Radius of domain bottom. Note: Orography not included. +!kind=default +range=this > 0.0: +sort-key=Panel-A02 +type=real + +[namelist:extrusion_dst=stretching_height] +compulsory=false +description=Physical height above which surface altitude does not + = influence layer height +fail-if=this < 0.0 ; +help=Physical height above which surface altitude does not + =influence layer height. + =Note that in order to reproduce the vertical stretching used in + =the UM 'smooth' extrusion, this value should be set to + =the value of eta_rho corresponding to the UM level + =first_constant_r_rho_level and multiplied by domain_height. +!kind=default +range=0: +sort-key=Panel-A02 ;1 +type=real + +[namelist:extrusion_dst=stretching_method] +compulsory=false +description=Method of generating stretching +!enumeration=true +help=Available stretching methods are: + =1) Linear (linear multiple of physical depth) + =2) Smooth (quadratic below stretching_height, linear above) +sort-key=Panel-A01 +trigger=namelist:extrusion_dst=stretching_height: 'smooth' ; +value-titles=Linear, Smooth +values='linear', 'smooth' + [namelist:lfric2lfric] compulsory=true description= @@ -28,7 +143,6 @@ values='planar', 'spherical' [namelist:lfric2lfric=destination_mesh_name] compulsory=true description=Tag-name for destination-mesh -fail-if=this == namelist:lfric2lfric=source_mesh_name ; help=Mesh topologies are held in UGRID conformant NetCDF files which =may contain more than one mesh topology. This tag-name identifies =the mesh topology to use from the mesh file namelist:lfric2lfric=destination_meshfile_prefix. @@ -183,7 +297,6 @@ values='planar', 'spherical' [namelist:lfric2lfric=source_mesh_name] compulsory=true description=Tag-name for source-mesh -fail-if=this == namelist:lfric2lfric=destination_mesh_name ; help=Mesh topologies are held in UGRID conformant NetCDF files which =may contain more than one mesh topology. This tag-name identifies =the mesh topology to use from the mesh file namelist:lfric2lfric=source_meshfile_prefix. @@ -295,101 +408,3 @@ help=The designation of the mesh to which this ns=namelist/lfric2lfric/configuration !string_length=default type=character - -[namelist:extrusion_dst] -compulsory=true -description=Vertical extrusion settings for the destination mesh. -help= -ns=namelist/Model/Mesh/Extrusion -sort-key=Section-A03 - -[namelist:extrusion_dst=domain_height] -compulsory=true -description=Height of domain above the surface [m] -fail-if=this < 0.0 ; -help=Height of the model domain above the surface. - =Surface is 0m for planar domains and planet_radius for spherical. -!kind=default -range=this > 0.0: -sort-key=Panel-A02 -type=real - -[namelist:extrusion_dst=method] -compulsory=true -description=Method for generating eta coordinate -!enumeration=true -fail-if=this == 'um_L38_29t_9s_40km' and namelist:extrusion_dst=number_of_layers != 38 ; - =this == 'um_L70_50t_20s_80km' and namelist:extrusion_dst=number_of_layers != 70 ; - =this == 'um_L85_50t_35s_85km' and namelist:extrusion_dst=number_of_layers != 85 ; - =this == 'um_L70_61t_9s_40km' and namelist:extrusion_dst=number_of_layers != 70 ; - =this == 'um_L120_99t_21s_40km' and namelist:extrusion_dst=number_of_layers != 120 ; - =this == 'um_L140_122t_18s_40km' and namelist:extrusion_dst=number_of_layers != 140 ; -help=Available extrusion methods are (\f$n$ is number of layers): - =1) Uniform eta spacing (\f$\frac{k}{n}\f$); - =2) Quadratic eta spacing (\f$\frac{k}{n}^2\f$); - =3) Geometric eta spacing (\f$d\eta = \frac{(s - 1)}{(s^{n} - 1)}$) - = with stretching factor prescribed (\f$s=1.03$); - =4) DCMIP eta spacing (Ullrich et al. (2012) DCMIP documentation, Appendix F.2.) - = with flattening parameter prescribed. - =5) L38 40km UM specific eta spacing; - =6) L70 80km UM specific eta spacing; - =7) L85 85km UM specific eta spacing; - =8) L70 40km UM specific eta spacing - =9) L120 40km UM specific eta spacing - =10) L140 40km UM specific eta spacing -sort-key=Panel-A01 -value-titles=Uniform, Quadratic, Geometric, DCMIP, - = um_L38_29t_9s_40km, um_L70_50t_20s_80km, um_L85_50t_35s_85km, um_L70_61t_9s_40km, - = um_L120_99t_21s_40km, um_L140_122t_18s_40km -values='uniform', 'quadratic', 'geometric', 'dcmip', - ='um_L38_29t_9s_40km', 'um_L70_50t_20s_80km', 'um_L85_50t_35s_85km', 'um_L70_61t_9s_40km', - ='um_L120_99t_21s_40km', 'um_L140_122t_18s_40km' - -[namelist:extrusion_dst=number_of_layers] -compulsory=true -description=Number of layers in the vertical -fail-if=this < 1 ; -help=Setting for number of layers of 3D-mesh in vertical. -!kind=default -range=1: -sort-key=Panel-A03 -type=integer - -[namelist:extrusion_dst=planet_radius] -compulsory=true -description=Radius of the planet surface [m] -fail-if=this <= 0.0 ; -help=Radius of domain bottom. Note: Orography not included. -!kind=default -range=this > 0.0: -sort-key=Panel-A02 -type=real - -[namelist:extrusion_dst=stretching_height] -compulsory=false -description=Physical height above which surface altitude does not - = influence layer height -fail-if=this < 0.0 ; -help=Physical height above which surface altitude does not - =influence layer height. - =Note that in order to reproduce the vertical stretching used in - =the UM 'smooth' extrusion, this value should be set to - =the value of eta_rho corresponding to the UM level - =first_constant_r_rho_level and multiplied by domain_height. -!kind=default -range=0: -sort-key=Panel-A02 ;1 -type=real - -[namelist:extrusion_dst=stretching_method] -compulsory=false -description=Method of generating stretching -!enumeration=true -help=Available stretching methods are: - =1) Linear (linear multiple of physical depth) - =2) Smooth (quadratic below stretching_height, linear above) -sort-key=Panel-A01 -trigger=namelist:extrusion_dst=stretching_height: 'smooth' ; -value-titles=Linear, Smooth -values='linear', 'smooth' - diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf b/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf index 950011de21..6facf39303 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-C12_C16_lam.conf @@ -1,9 +1,6 @@ [file:iodef.xml] source=$ROSE_SUITE_DIR/app/lfric2lfric/file/iodef_orography.xml -[namelist:files] -orography_mean_ancil_path='' - [namelist:lfric2lfric] destination_mesh_name='dynamics' destination_meshfile_prefix='${MESH_DIR}/seuk_MG/mesh_seuk_MG' @@ -14,4 +11,3 @@ source_mesh_name='C12' source_meshfile_prefix='${MESH_DIR}/C24_C12/mesh_C24_C12' src_ancil_directory='$BIG_DATA_DIR/ancils/basic-gagl/Puku/C12/n96e' src_orography_mean_ancil_path='orography/globe30/qrparm.orog.ugrid' - diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf index 02877f4ad7..16e0206d4e 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf @@ -1,6 +1,18 @@ [file:lfric2lfric_clim_gal9_C12_MG.nc] source="$BIG_DATA_DIR/start_dumps/proto-ral/AppsTicket110/lfric_atm_clim_gal9_C12_dt-1800p0_intel_64-bit_fast-debug_000072.nc" +[namelist:boundaries] +blend_frequency='inner' +blending_weights=1.0,1.0,1.0,1.0,0.9,0.7,0.5,0.3,0.1 +blending_weights_w2v=1.0,1.0,1.0,1.0,0.9,0.7,0.5,0.3,0.1 +lbc_eos_height=10 +lbc_method='onion_layer' +limited_area=.true. +normal_only=.true. +output_lbcs=.true. +solver_boundary_depth=4 +transport_boundary_depth=4 + [namelist:extrusion] domain_height=80000.0 method='um_L70_50t_20s_80km' diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf b/rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf index 33fd5d9900..ae8fce007f 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-dst_L38_40km.conf @@ -3,4 +3,4 @@ domain_height=39254.833575999997 method='um_L38_29t_9s_40km' number_of_layers=38 planet_radius=6371229.0 -stretching_method='linear' \ No newline at end of file +stretching_method='linear' diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf b/rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf index 116aa7c5f2..d97fabaebe 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-src_L70_80km.conf @@ -3,4 +3,4 @@ domain_height=80000.0 method='um_L70_50t_20s_80km' number_of_layers=70 stretching_height=17507.0 -stretching_method='smooth' \ No newline at end of file +stretching_method='smooth' diff --git a/rose-stem/app/lfric2lfric/rose-app.conf b/rose-stem/app/lfric2lfric/rose-app.conf index 6d0cf21677..7fead03c32 100644 --- a/rose-stem/app/lfric2lfric/rose-app.conf +++ b/rose-stem/app/lfric2lfric/rose-app.conf @@ -105,16 +105,29 @@ sg_orog_mixing='none' !!zhloc_depth_fac=0 [namelist:boundaries] -blend_frequency='inner' -blending_weights=1.0,1.0,1.0,1.0,0.9,0.7,0.5,0.3,0.1 -blending_weights_w2v=1.0,1.0,1.0,1.0,0.9,0.7,0.5,0.3,0.1 -lbc_eos_height=10 -lbc_method='onion_layer' -limited_area=.true. -normal_only=.true. -output_lbcs=.true. -solver_boundary_depth=4 -transport_boundary_depth=4 +!!blend_frequency='final' +!!blending_weights=0.0 +!!blending_weights_w2v=0.0 +!!boundary_e=1 +!!boundary_n=1 +!!boundary_s=1 +!!boundary_w=1 +!!edge_cells_ew=1 +!!edge_cells_ns=1 +!!inner_width_ew=1 +!!inner_width_ns=1 +!!lbc_eos_height=100 +!!lbc_method='coordinate_based' +limited_area=.false. +!!normal_only=.true. +!!outer_width_ew=1 +!!outer_width_ns=1 +!!output_lbcs=.false. +!!rim_width_ew=1 +!!rim_width_ns=1 +!!solver_boundary_depth=1 +!!transport_boundary_depth=6 +transport_overwrite_freq='final' [namelist:checks] limit_cfl=.false. From 4a8b6d0431711ff68ffb123b20ff2ccfc5fdd3b4 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:47:49 +0100 Subject: [PATCH 29/53] Remove tabs --- rose-stem/site/meto/groups/groups_lfric2lfric.cylc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc index 23c622d4d2..4fcf2f7d51 100644 --- a/rose-stem/site/meto/groups/groups_lfric2lfric.cylc +++ b/rose-stem/site/meto/groups/groups_lfric2lfric.cylc @@ -52,7 +52,7 @@ "lfric2lfric_oasis_clim_gal9-C24_C12_6cpu_ex1a_cce_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam_1cpu_ex1a_cce_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam-lbc_1cpu_ex1a_cce_fast-debug-64bit", - "lfric2lfric_oasis_C12L70_to_seukL38_ex1a_cce_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_seukL38_ex1a_cce_fast-debug-64bit", "lfric2lfric_oasis_C12L70_to_C12L38_ex1a_cce_fast-debug-64bit", "lfric2lfric_ex1a_canned", ], From ae186821db725f08ddc9fa51d7848685b2b7bf73 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:05:37 +0100 Subject: [PATCH 30/53] rose corrections --- rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf | 1 - rose-stem/app/lfric2lfric/rose-app.conf | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf index 16e0206d4e..4af46b8816 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf @@ -11,7 +11,6 @@ limited_area=.true. normal_only=.true. output_lbcs=.true. solver_boundary_depth=4 -transport_boundary_depth=4 [namelist:extrusion] domain_height=80000.0 diff --git a/rose-stem/app/lfric2lfric/rose-app.conf b/rose-stem/app/lfric2lfric/rose-app.conf index 7fead03c32..468f1fd6e2 100644 --- a/rose-stem/app/lfric2lfric/rose-app.conf +++ b/rose-stem/app/lfric2lfric/rose-app.conf @@ -1,4 +1,4 @@ -meta=lfric-lfric2lfric/vn3.2 +meta=lfric-lfric2lfric/HEAD [command] default=$CORE_ROOT_DIR/bin/tweak_iodef; \ From abdcd78e8b1877c6a99ca65f402cc98e6357fd53 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 15 Jul 2026 16:58:40 +0100 Subject: [PATCH 31/53] correction --- .../lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf index 2103c06787..f392e31b3f 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf @@ -26,7 +26,7 @@ sort-key=Panel-A02 type=real [namelist:extrusion_dst=eta_values] -!bounds=namelist:extrusion=number_of_layers-1 +!bounds=namelist:extrusion_dst=number_of_layers-1 compulsory=true description=Eta values, excluding 0 and 1 help=Non-dimensional height values defining the model vertical levels. From 4882762955dd2beb749c23f4b6b2b4c114599a2b Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:12:10 +0100 Subject: [PATCH 32/53] gungho unit tests --- .../analytic_orography_field_cartesian_mod_test.pf | 7 +++++-- .../analytic_orography_field_spherical_mod_test.pf | 9 ++++++--- .../orography/ancil_orography_cartesian_mod_test.pf | 9 ++++++--- .../orography/ancil_orography_spherical_mod_test.pf | 9 ++++++--- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/science/gungho/unit-test/orography/analytic_orography_field_cartesian_mod_test.pf b/science/gungho/unit-test/orography/analytic_orography_field_cartesian_mod_test.pf index c38cf9bd3e..2e43fae74a 100644 --- a/science/gungho/unit-test/orography/analytic_orography_field_cartesian_mod_test.pf +++ b/science/gungho/unit-test/orography/analytic_orography_field_cartesian_mod_test.pf @@ -12,6 +12,7 @@ module analytic_orography_field_cartesian_mod_test use global_mesh_mod, only : global_mesh_type use analytic_orography_mod, only : orography_profile use ugrid_mesh_data_mod, only : ugrid_mesh_data_type + use extrusion_config_mod, only : method_uniform, stretching_method_linear use funit @@ -40,6 +41,7 @@ module analytic_orography_field_cartesian_mod_test real(r_def), parameter :: domain_bottom = 0.0_r_def real(r_def), parameter :: domain_height = 10000.0_r_def + real(r_def), parameter :: stretching_height = 1.0_r_def real(r_def), parameter :: surface_pressure = 1000.0e2_r_def integer(i_def), parameter :: nlayers = 10_i_def @@ -71,7 +73,6 @@ contains feign_orography_schar_cartesian_config use orography_schar_cartesian_config_mod, & only : direction_x - use extrusion_config_mod, only : method_uniform, stretching_method_linear use initial_pressure_config_mod, only : method_balanced @@ -93,7 +94,7 @@ contains planet_radius=6000.0_r_def, & domain_height=domain_height, & number_of_layers=nlayers, & - stretching_height=1.0_r_def, & + stretching_height=stretching_height, & stretching_method=stretching_method_linear, & eta_values=(/0.5_r_def/) ) @@ -253,6 +254,8 @@ contains ndf, undf, map, & height_flat_surface, & height_domain_top, & + stretching_height, & + stretching_method_linear, & chi_1_in, chi_2_in, chi_3_in, & chi_1, chi_2, chi_3, & panel_id ) diff --git a/science/gungho/unit-test/orography/analytic_orography_field_spherical_mod_test.pf b/science/gungho/unit-test/orography/analytic_orography_field_spherical_mod_test.pf index 9d1571fc7e..8d76cdba76 100644 --- a/science/gungho/unit-test/orography/analytic_orography_field_spherical_mod_test.pf +++ b/science/gungho/unit-test/orography/analytic_orography_field_spherical_mod_test.pf @@ -13,6 +13,8 @@ module analytic_orography_field_spherical_mod_test use global_mesh_mod, only : global_mesh_type use analytic_orography_mod, only : orography_profile use ugrid_mesh_data_mod, only : ugrid_mesh_data_type + use extrusion_config_mod, only : method_uniform, & + stretching_method_linear use funit @@ -40,6 +42,7 @@ module analytic_orography_field_spherical_mod_test real(r_def), parameter :: radius = 6371229.0_r_def real(r_def), parameter :: domain_height = 10000.0_r_def + real(r_def), parameter :: stretching_height = 1.0_r_def integer(i_def), parameter :: nlayers = 10_i_def integer(i_def), parameter :: total_ranks = 1_i_def @@ -60,8 +63,6 @@ contains use agnesi_orography_spherical_mod, only : agnesi_spherical_type use base_mesh_config_mod, only : geometry_spherical, & topology_fully_periodic - use extrusion_config_mod, only : method_uniform, & - stretching_method_linear use finite_element_config_mod, only : cellshape_quadrilateral, & coord_system_xyz, & coord_space_wchi @@ -95,7 +96,7 @@ contains planet_radius=radius, & domain_height=domain_height, & number_of_layers=nlayers, & - stretching_height=1.0_r_def, & + stretching_height=stretching_height, & stretching_method=stretching_method_linear, & eta_values=(/0.5_r_def/) ) @@ -270,6 +271,8 @@ contains ndf, undf, map, & height_flat_surface, & height_domain_top, & + stretching_height, & + stretching_method_linear, & chi_1_in, chi_2_in, chi_3_in, & chi_1_cart, chi_2_cart, chi_3_cart, & panel_id ) diff --git a/science/gungho/unit-test/orography/ancil_orography_cartesian_mod_test.pf b/science/gungho/unit-test/orography/ancil_orography_cartesian_mod_test.pf index 0d8031b075..5b4f51bcfa 100644 --- a/science/gungho/unit-test/orography/ancil_orography_cartesian_mod_test.pf +++ b/science/gungho/unit-test/orography/ancil_orography_cartesian_mod_test.pf @@ -6,6 +6,8 @@ module ancil_orography_cartesian_mod_test use constants_mod, only : i_def, r_def + use extrusion_config_mod, only : method_uniform, & + stretching_method_linear use funit implicit none @@ -17,6 +19,7 @@ module ancil_orography_cartesian_mod_test real(r_def), parameter :: dx = 6000.0_r_def real(r_def), parameter :: dy = 1000.0_r_def real(r_def), parameter :: dz = 2000.0_r_def + real(r_def), parameter :: stretching_height = 1.0_r_def real(r_def), parameter :: domain_height = nlayers*dz real(r_def), parameter :: domain_surface = 0.0_r_def @@ -30,8 +33,6 @@ contains use base_mesh_config_mod, only : geometry_planar, & topology_fully_periodic - use extrusion_config_mod, only : method_uniform, & - stretching_method_linear use finite_element_config_mod, only : cellshape_quadrilateral, & coord_system_xyz, coord_space_wchi use feign_config_mod, only : feign_finite_element_config, & @@ -54,7 +55,7 @@ contains planet_radius = 0.0_r_def, & domain_height = domain_height, & number_of_layers = nlayers, & - stretching_height= 1.0_r_def, & + stretching_height= stretching_height, & stretching_method= stretching_method_linear,& eta_values=(/0.5_r_def/) ) @@ -213,6 +214,8 @@ contains srf_alt_w0, & domain_surface, & domain_height, & + stretching_height, & + stretching_method_linear, & ndf_wchi, & undf_wchi, & map_wchi(:, cell), & diff --git a/science/gungho/unit-test/orography/ancil_orography_spherical_mod_test.pf b/science/gungho/unit-test/orography/ancil_orography_spherical_mod_test.pf index ad8625391e..255e20237c 100644 --- a/science/gungho/unit-test/orography/ancil_orography_spherical_mod_test.pf +++ b/science/gungho/unit-test/orography/ancil_orography_spherical_mod_test.pf @@ -6,6 +6,8 @@ module ancil_orography_spherical_mod_test use constants_mod, only : i_def, r_def + use extrusion_config_mod, only : method_uniform, & + stretching_method_linear use funit implicit none @@ -17,6 +19,7 @@ module ancil_orography_spherical_mod_test real(r_def), parameter :: dlat = 1.0_r_def/180.0_r_def real(r_def), parameter :: dlon = 1.0_r_def/180.0_r_def real(r_def), parameter :: dr = 1000.0_r_def + real(r_def), parameter :: stretching_height = 1.0_r_def real(r_def), parameter :: domain_height = nlayers*dr real(r_def), parameter :: radius = 6371229.0_r_def real(r_def), parameter :: domain_surface = radius @@ -31,8 +34,6 @@ contains use base_mesh_config_mod, only : geometry_spherical, & topology_fully_periodic - use extrusion_config_mod, only : method_uniform, & - stretching_method_linear use finite_element_config_mod, only : cellshape_quadrilateral, & coord_system_xyz, coord_space_wchi use feign_config_mod, only : feign_finite_element_config, & @@ -55,7 +56,7 @@ contains planet_radius = radius, & domain_height = domain_height, & number_of_layers = nlayers, & - stretching_height= 1.0_r_def, & + stretching_height= stretching_height, & stretching_method= stretching_method_linear,& eta_values=(/0.5_r_def/) ) @@ -217,6 +218,8 @@ contains srf_alt_w0, & domain_surface, & domain_height, & + stretching_height, & + stretching_method_linear, & ndf_wchi, & undf_wchi, & map_wchi(:, cell), & From 4ca5114e6be46f8f14619f078af30e216ac6ecf1 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 20 Jul 2026 10:49:01 +0100 Subject: [PATCH 33/53] Added nci --- rose-stem/site/nci/groups/groups_lfric2lfric.cylc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rose-stem/site/nci/groups/groups_lfric2lfric.cylc b/rose-stem/site/nci/groups/groups_lfric2lfric.cylc index 252921b31b..a61ba97663 100644 --- a/rose-stem/site/nci/groups/groups_lfric2lfric.cylc +++ b/rose-stem/site/nci/groups/groups_lfric2lfric.cylc @@ -14,6 +14,8 @@ "lfric2lfric_clim_gal9-C24_C12_6cpu_gadi_intel_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9-C24_C12_6cpu_gadi_intel_fast-debug-64bit", "lfric2lfric_oasis_clim_gal9_C12-ral_seuk_C16_lam_4cpu_gadi_intel_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_seukL38_gadi_intel_fast-debug-64bit", + "lfric2lfric_oasis_C12L70_to_C12L38_gadi_intel_fast-debug-64bit", "lfric2lfric_gadi_canned", ], "lfric2lfric_gadi_extra": [ From 13a4f3fc4bb06b558322faf16264063103447246 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:51:37 +0100 Subject: [PATCH 34/53] source_config_list and target_config_list --- .../source/driver/lfric2lfric_init_mod.f90 | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index ab2a73b094..b9ffb2fad5 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -73,8 +73,10 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & ! For get_field_list returns integer(kind=i_def) :: num_fields - character(len=str_def), allocatable :: config_list(:) - character(len=nf90_max_name) :: prefix + character(len=str_def), allocatable :: source_config_list(:) + character(len=str_def), allocatable :: target_config_list(:) + character(len=nf90_max_name) :: source_prefix + character(len=nf90_max_name) :: target_prefix ! Source context pointer and temporary context for setup type(lfric_xios_context_type), pointer :: io_context @@ -85,14 +87,23 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call log_event( 'lfric2lfric: Initialising miniapp ...', log_level_info ) if (mode == mode_ics) then - prefix = 'restart_' + source_prefix = 'restart_' else if (mode == mode_lbc) then - prefix = '' + source_prefix = '' + end if + if (mode == mode_ics) then + target_prefix = 'checkpoint_' + else if (mode == mode_lbc) then + target_prefix = 'lbc_' end if ! Get field names from filename and validate presence in iodef.xml - call get_field_list( num_fields, config_list, start_dump_filename, prefix ) - + call get_field_list( num_fields, target_config_list, & + start_dump_filename, target_prefix ) + + call get_field_list( num_fields, source_config_list, & + start_dump_filename, source_prefix ) + !-------------------------------------------------------------------------- ! Initialise Source Fields !-------------------------------------------------------------------------- @@ -102,10 +113,10 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & ! Now need to loop over length of config_list make field for each do i = 1, num_fields - call field_maker( field_collection, & - config_list(i), & - origin_mesh, & - origin_twod_mesh, & + call field_maker( field_collection, & + source_config_list(i), & + origin_mesh, & + origin_twod_mesh, & prefix ) end do @@ -119,18 +130,12 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call modeldb%io_contexts%get_io_context(context_dst, io_context) call io_context%set_current() - if (mode == mode_ics) then - prefix = 'checkpoint_' - else if (mode == mode_lbc) then - prefix = 'lbc_' - end if - do i = 1, num_fields - call field_maker( field_collection, & - config_list(i), & - target_mesh, & - target_twod_mesh, & - prefix ) + call field_maker( field_collection, & + target_config_list(i), & + target_mesh, & + target_twod_mesh, & + target_prefix ) end do call modeldb%io_contexts%get_io_context(context_src, io_context) From 19d9ad8ba3d7e4cfc986bf329bc43e142ede510c Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:38:27 +0100 Subject: [PATCH 35/53] Revert "source_config_list and target_config_list" This reverts commit 13a4f3fc4bb06b558322faf16264063103447246. --- .../source/driver/lfric2lfric_init_mod.f90 | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index b9ffb2fad5..ab2a73b094 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -73,10 +73,8 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & ! For get_field_list returns integer(kind=i_def) :: num_fields - character(len=str_def), allocatable :: source_config_list(:) - character(len=str_def), allocatable :: target_config_list(:) - character(len=nf90_max_name) :: source_prefix - character(len=nf90_max_name) :: target_prefix + character(len=str_def), allocatable :: config_list(:) + character(len=nf90_max_name) :: prefix ! Source context pointer and temporary context for setup type(lfric_xios_context_type), pointer :: io_context @@ -87,23 +85,14 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call log_event( 'lfric2lfric: Initialising miniapp ...', log_level_info ) if (mode == mode_ics) then - source_prefix = 'restart_' + prefix = 'restart_' else if (mode == mode_lbc) then - source_prefix = '' - end if - if (mode == mode_ics) then - target_prefix = 'checkpoint_' - else if (mode == mode_lbc) then - target_prefix = 'lbc_' + prefix = '' end if ! Get field names from filename and validate presence in iodef.xml - call get_field_list( num_fields, target_config_list, & - start_dump_filename, target_prefix ) - - call get_field_list( num_fields, source_config_list, & - start_dump_filename, source_prefix ) - + call get_field_list( num_fields, config_list, start_dump_filename, prefix ) + !-------------------------------------------------------------------------- ! Initialise Source Fields !-------------------------------------------------------------------------- @@ -113,10 +102,10 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & ! Now need to loop over length of config_list make field for each do i = 1, num_fields - call field_maker( field_collection, & - source_config_list(i), & - origin_mesh, & - origin_twod_mesh, & + call field_maker( field_collection, & + config_list(i), & + origin_mesh, & + origin_twod_mesh, & prefix ) end do @@ -130,12 +119,18 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & call modeldb%io_contexts%get_io_context(context_dst, io_context) call io_context%set_current() + if (mode == mode_ics) then + prefix = 'checkpoint_' + else if (mode == mode_lbc) then + prefix = 'lbc_' + end if + do i = 1, num_fields - call field_maker( field_collection, & - target_config_list(i), & - target_mesh, & - target_twod_mesh, & - target_prefix ) + call field_maker( field_collection, & + config_list(i), & + target_mesh, & + target_twod_mesh, & + prefix ) end do call modeldb%io_contexts%get_io_context(context_src, io_context) From 78917301cd1517b699735b52eccc2aa379a2b667 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 30 Jul 2026 16:32:26 +0100 Subject: [PATCH 36/53] Check for ndata difference --- .../source/driver/lfric2lfric_regrid_mod.F90 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_regrid_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_regrid_mod.F90 index 4859100c77..5cc9886c00 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_regrid_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_regrid_mod.F90 @@ -89,6 +89,7 @@ subroutine lfric2lfric_regrid( modeldb, oasis_clock, & integer(kind=i_def) :: fs_id type(function_space_type), pointer :: fs_w3_src, fs_w3_dst type(function_space_type), pointer :: fs_wth_src, fs_wth_dst + type(function_space_type), pointer :: fs_type type(mesh_type), pointer :: mesh_dst character(len=str_def) :: mesh_names(2) @@ -101,7 +102,7 @@ subroutine lfric2lfric_regrid( modeldb, oasis_clock, & integer(kind=i_def), parameter :: dst = 1 integer(kind=i_def), parameter :: src = 2 - + integer(kind=i_def) :: ndata_src, ndata_dst ! Obtain namelist parameters mesh_names(dst) = modeldb%config%lfric2lfric%destination_mesh_name() @@ -151,6 +152,16 @@ subroutine lfric2lfric_regrid( modeldb, oasis_clock, & trim(field_name) call log_event(log_scratch_space, log_level_info) + ! Is this a multidata field and is ndata the same? + fs_type => field_src%get_function_space() + ndata_src = fs_type%get_ndata() + fs_type => field_dst%get_function_space() + ndata_dst = fs_type%get_ndata() + if (ndata_dst /= ndata_src) then + write(log_scratch_space, '(A)') "ndata not equal " + call log_event(log_scratch_space, log_level_info) + end if + ! Convert W2 fields to a set of W3 and Wtheta fields fs_id = field_src%which_function_space() if (fs_id == W2) then From 4a6c03f087d9be60ca8d9e4184153678743392ec Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Thu, 30 Jul 2026 16:48:01 +0100 Subject: [PATCH 37/53] example data with tiles and different ndata --- applications/lfric2lfric/example/iodef.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/applications/lfric2lfric/example/iodef.xml b/applications/lfric2lfric/example/iodef.xml index 09a1fa0727..ced820e220 100644 --- a/applications/lfric2lfric/example/iodef.xml +++ b/applications/lfric2lfric/example/iodef.xml @@ -24,6 +24,7 @@ + @@ -63,7 +64,8 @@ - + + From 96da3f420d23b6f6cce63d348db446e4fec88ddb Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:05:46 +0100 Subject: [PATCH 38/53] iodef --- applications/lfric2lfric/example/iodef.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/applications/lfric2lfric/example/iodef.xml b/applications/lfric2lfric/example/iodef.xml index ced820e220..4568a3f594 100644 --- a/applications/lfric2lfric/example/iodef.xml +++ b/applications/lfric2lfric/example/iodef.xml @@ -23,8 +23,9 @@ - - + + + From b2665f60aaa6222ffc388ca5d5bd00e2923a6077 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Tue, 4 Aug 2026 15:03:17 +0100 Subject: [PATCH 39/53] infrastructure for tiles --- .../algorithm/lfric2lfric_tiles_mod.x90 | 76 +++++++++++++++++ .../source/driver/lfric2lfric_driver_mod.F90 | 17 +++- .../source/driver/lfric2lfric_init_mod.f90 | 29 ++++--- .../lfric2lfric_query_multilayer_mod.f90 | 81 +++++++++++++++++++ 4 files changed, 189 insertions(+), 14 deletions(-) create mode 100644 applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 create mode 100644 applications/lfric2lfric/source/initialisation/lfric2lfric_query_multilayer_mod.f90 diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 new file mode 100644 index 0000000000..8ee7c924d2 --- /dev/null +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 @@ -0,0 +1,76 @@ +!----------------------------------------------------------------------------- +! (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 Reconfiguration associated with changes in tiles +module lfric2lfric_tiles_mod + + use constants_mod, only: str_def, i_def + use driver_modeldb_mod, only: modeldb_type + use extrusion_mod, only: TWOD + use field_parent_mod, only: field_parent_type + use field_mod, only: field_type + use field_collection_mod, only: field_collection_type + use field_collection_iterator_mod, & + only: field_collection_iterator_type + use mesh_mod, only: mesh_type + use log_mod, only: log_event, & + log_level_info, & + log_scratch_space + + implicit none + + private + public :: lfric2lfric_tiles + +contains + + !> @brief Apply the changes associated with the change in tiles. + !> @details Loop over the fields in the source_fields collection, + !! and deal with the change in tiles. + !> @param modeldb Model state object + !> @param source_fields The collection of fields to be regridded + !> @param target_fields The collection of regridded fields + subroutine lfric2lfric_tiles( modeldb, source_fields, target_fields ) + + implicit none + + type(modeldb_type), intent(inout) :: modeldb + type(field_collection_type), intent(inout) :: source_fields + type(field_collection_type), intent(inout) :: target_fields + + type(field_collection_iterator_type) :: iter + + class(field_parent_type), pointer :: field + type(field_type), pointer :: field_src + type(field_type), pointer :: field_dst + type(mesh_type), pointer :: mesh + + character(len=str_def) :: field_name + + ! Main loop over fields to be processed + call iter%initialise(source_fields) + do + ! Locate the field to be processed in the field collections + if ( .not.iter%has_next() ) exit + field => iter%next() + field_name = field%get_name() + + call source_fields%get_field(field_name, field_src) + call target_fields%get_field(field_name, field_dst) + + mesh => field_src%get_mesh() + if (mesh%get_extrusion_id() == TWOD) then + + write(log_scratch_space, '(A,A)') "Processing lfric field ", & + trim(field_name) + call log_event(log_scratch_space, log_level_info) + + ! Apply changes associated with tiles + end if + end do + + end subroutine lfric2lfric_tiles + +end module lfric2lfric_tiles_mod diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 0e5f16b007..dfb709241f 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -40,6 +40,8 @@ module lfric2lfric_driver_mod src, dst use lfric2lfric_regrid_mod, only: lfric2lfric_regrid use lfric2lfric_vert_mod, only: lfric2lfric_vert + use lfric2lfric_tiles_mod, only: lfric2lfric_tiles + implicit none @@ -123,6 +125,8 @@ subroutine run( modeldb, oasis_clock ) logical(kind=l_def), pointer :: vertical_change logical(kind=l_def), pointer :: horizontal_change + logical(kind=l_def), pointer :: tile_change + logical(kind=l_def) :: vertical_or_tile_change ! Extract configuration variables src_extrusion_method = modeldb%config%extrusion%method() @@ -151,14 +155,18 @@ subroutine run( modeldb, oasis_clock ) call modeldb%values%get_value("vertical_change", vertical_change) call modeldb%values%get_value("horizontal_change", horizontal_change) + call modeldb%values%get_value("tile_change", tile_change) - if (horizontal_change .and. vertical_change) then + if (vertical_change .or. tile_change) then + vertical_or_tile_change = .true. + end if + if (horizontal_change .and. vertical_or_tile_change) then interm_fields => modeldb%fields%get_field_collection(interm_collection_name) - else if (horizontal_change .and. .not. vertical_change) then + else if (horizontal_change .and. .not. vertical_or_tile_change) then interm_fields => modeldb%fields%get_field_collection(target_collection_name) - else if (vertical_change .and. .not. horizontal_change) then + else if (vertical_or_tile_change .and. .not. horizontal_change) then interm_fields => modeldb%fields%get_field_collection(source_collection_name) end if @@ -173,6 +181,9 @@ subroutine run( modeldb, oasis_clock ) if (vertical_change) then call lfric2lfric_vert(modeldb, interm_fields, target_fields) end if + if (tile_change) then + call lfric2lfric_tiles(modeldb, interm_fields, target_fields) + end if ! Write output call modeldb%io_contexts%get_io_context(context_dst, io_context) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index c6be9c3651..69fc77c0f1 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -27,6 +27,8 @@ module lfric2lfric_init_mod ! lfric2lfric mods use lfric2lfric_config_mod, only: mode_ics, mode_lbc use lfric2lfric_field_init_mod, only: get_field_list, field_maker + use lfric2lfric_query_multilayer_mod, & + only: query_multilayer implicit none private @@ -81,9 +83,12 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & logical(l_def), pointer :: horizontal_change logical(l_def), pointer :: vertical_change + logical(l_def), pointer :: tile_change ! For field creation and storage - type(field_collection_type), pointer :: field_collection + type(field_collection_type), pointer :: target_fields + type(field_collection_type), pointer :: source_fields + type(field_collection_type), pointer :: interm_fields ! For get_field_list returns integer(kind=i_def) :: num_fields @@ -115,11 +120,11 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & !-------------------------------------------------------------------------- ! Initialise our field collection call modeldb%fields%add_empty_field_collection(origin_collection_name) - field_collection => modeldb%fields%get_field_collection(origin_collection_name) + source_fields => modeldb%fields%get_field_collection(origin_collection_name) ! Now need to loop over length of config_list make field for each do i = 1, num_fields - call field_maker( field_collection, & + call field_maker( source_fields, & config_list(i), & origin_mesh, & origin_twod_mesh, & @@ -130,8 +135,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & ! Initialise Target Fields !-------------------------------------------------------------------------- call modeldb%fields%add_empty_field_collection(target_collection_name) - field_collection => & - modeldb%fields%get_field_collection(target_collection_name) + target_fields => modeldb%fields%get_field_collection(target_collection_name) call modeldb%io_contexts%get_io_context(context_dst, io_context) call io_context%set_current() @@ -143,7 +147,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & end if do i = 1, num_fields - call field_maker( field_collection, & + call field_maker( target_fields, & config_list(i), & target_mesh, & target_twod_mesh, & @@ -155,19 +159,22 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & orog_init_option == orog_init_option_start_dump ) then if ( mode == mode_ics ) then - call field_maker(field_collection, trim('surface_altitude'), & + call field_maker(target_fields, trim('surface_altitude'), & target_mesh, target_twod_mesh, prefix) end if end if + call query_multilayer( modeldb, source_fields, target_fields ) + call modeldb%values%get_value("tile_change", tile_change) + !-------------------------------------------------------------------------- ! Initialise Intermediate Fields !-------------------------------------------------------------------------- - if (horizontal_change .and. vertical_change) then + if ( (horizontal_change .and. vertical_change) .or. & + (horizontal_change .and. tile_change)) then call modeldb%fields%add_empty_field_collection(interm_collection_name) - field_collection => & - modeldb%fields%get_field_collection(interm_collection_name) + interm_fields => modeldb%fields%get_field_collection(interm_collection_name) if (mode == mode_ics) then prefix = 'checkpoint_' @@ -176,7 +183,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & end if do i = 1, num_fields - call field_maker( field_collection, & + call field_maker( interm_fields, & config_list(i), & interm_mesh, & interm_twod_mesh, & diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_query_multilayer_mod.f90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_query_multilayer_mod.f90 new file mode 100644 index 0000000000..ecb7d0e0df --- /dev/null +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_query_multilayer_mod.f90 @@ -0,0 +1,81 @@ +!----------------------------------------------------------------------------- +! (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 Query whether extra work is required for the multi-layer fields. +module lfric2lfric_query_multilayer_mod + + use constants_mod, only: str_def, i_def, l_def + use driver_modeldb_mod, only: modeldb_type + use field_mod, only: field_type + use field_collection_mod, only: field_collection_type + use field_parent_mod, only: field_parent_type + use field_collection_iterator_mod, only: & + field_collection_iterator_type + use function_space_mod, only: function_space_type + use log_mod, only: log_event, & + log_scratch_space, & + log_level_info, & + log_level_error + + implicit none + + private + public :: query_multilayer + +contains + + !> @brief Set the tile_change logical to true or false + !> @details tile_change is true if there is a change in the number of tiles + !! for any field between the source_fields and target_fields. + subroutine query_multilayer( modeldb, source_fields, target_fields ) + + implicit none + + type(modeldb_type), intent(inout) :: modeldb + type(field_collection_type), pointer, intent(in) :: source_fields + type(field_collection_type), pointer, intent(in) :: target_fields + + type(field_collection_iterator_type) :: iter + + class(field_parent_type), pointer :: field + type(field_type), pointer :: field_src + type(field_type), pointer :: field_dst + type(function_space_type), pointer :: fs_type + + character(len=str_def) :: field_name + integer(kind=i_def) :: ndata_src, ndata_dst + logical(kind=l_def) :: tile_change + + tile_change = .false. + + ! Main loop over fields to be processed + call iter%initialise(source_fields) + do + ! Locate the field to be processed in the field collections + if ( .not.iter%has_next() ) exit + field => iter%next() + field_name = field%get_name() + + call source_fields%get_field(field_name, field_src) + call target_fields%get_field(field_name, field_dst) + + ! Is this a multidata field and is ndata the same? + fs_type => field_src%get_function_space() + ndata_src = fs_type%get_ndata() + fs_type => field_dst%get_function_space() + ndata_dst = fs_type%get_ndata() + if (ndata_dst /= ndata_src) then + write(log_scratch_space, '(A)') "ndata not equal " + call log_event(log_scratch_space, log_level_info) + + tile_change = .true. + end if + end do + + call modeldb%values%add_key_value('tile_change', tile_change) + + end subroutine query_multilayer + +end module lfric2lfric_query_multilayer_mod From b267540ee55e3594c067b71e38f0ba15a686d6f0 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 7 Aug 2026 16:20:09 +0100 Subject: [PATCH 40/53] tile mapping --- .../lfric2lfric/example/configuration.nml | 6 +- .../lfric-lfric2lfric/HEAD/rose-meta.conf | 17 +++ .../algorithm/lfric2lfric_tiles_mod.x90 | 59 ++++++++- .../source/driver/lfric2lfric_init_mod.f90 | 14 ++- .../lfric2lfric_field_init_mod.f90 | 29 +++-- .../lfric2lfric_multidata_map_kernel_mod.F90 | 117 ++++++++++++++++++ 6 files changed, 221 insertions(+), 21 deletions(-) create mode 100644 applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_kernel_mod.F90 diff --git a/applications/lfric2lfric/example/configuration.nml b/applications/lfric2lfric/example/configuration.nml index d25b8274cf..c51a1dc063 100644 --- a/applications/lfric2lfric/example/configuration.nml +++ b/applications/lfric2lfric/example/configuration.nml @@ -68,7 +68,7 @@ coord_space = 'Wchi', / &logging - run_log_level = 'info', + run_log_level = 'debug', / &time @@ -110,3 +110,7 @@ coord_space = 'Wchi', &orography orog_init_option = 'none' / + +&dst_jules_surface_types + multidata_map = 1,2,11,6,6,6,7,8,9 +/ diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf index f392e31b3f..a2a48c90eb 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf @@ -408,3 +408,20 @@ help=The designation of the mesh to which this ns=namelist/lfric2lfric/configuration !string_length=default type=character + +[namelist:dst_jules_surface_types] +compulsory=true +description= +ns=namelist/dst_jules_surface_types +title=dst_jules_surface_types + +[namelist:dst_jules_surface_types=multidata_map] +compulsory=true +description=Multidata map for surface/land tiles. +help=List multidata levels to map to the + =destination multidata field. +!kind=default +length=: +ns=namelist/lfric2lfric/configuration +range=0: +type=integer \ No newline at end of file diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 index 8ee7c924d2..d3e10c0bec 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 @@ -6,7 +6,7 @@ !> @brief Reconfiguration associated with changes in tiles module lfric2lfric_tiles_mod - use constants_mod, only: str_def, i_def + use constants_mod, only: str_def, i_def, l_def use driver_modeldb_mod, only: modeldb_type use extrusion_mod, only: TWOD use field_parent_mod, only: field_parent_type @@ -14,9 +14,14 @@ module lfric2lfric_tiles_mod use field_collection_mod, only: field_collection_type use field_collection_iterator_mod, & only: field_collection_iterator_type + use function_space_mod, only: function_space_type use mesh_mod, only: mesh_type - use log_mod, only: log_event, & - log_level_info, & + use lfric2lfric_multidata_map_kernel_mod, & + only: lfric2lfric_multidata_map_type + use log_mod, only: log_event, & + log_level_debug, & + log_level_info, & + log_level_error, & log_scratch_space implicit none @@ -46,9 +51,15 @@ contains type(field_type), pointer :: field_src type(field_type), pointer :: field_dst type(mesh_type), pointer :: mesh - + type(function_space_type), pointer :: fs_type + integer(i_def), allocatable :: multidata_map(:) + integer(kind=i_def) :: ndata_dst, ndata_src character(len=str_def) :: field_name + logical(l_def), parameter :: ndata_first = .false. + write(log_scratch_space, '(A)') "Tiles " + call log_event(log_scratch_space, log_level_info) + ! Main loop over fields to be processed call iter%initialise(source_fields) do @@ -60,6 +71,7 @@ contains call source_fields%get_field(field_name, field_src) call target_fields%get_field(field_name, field_dst) + ! Continue if it is a 2D mesh field mesh => field_src%get_mesh() if (mesh%get_extrusion_id() == TWOD) then @@ -67,10 +79,45 @@ contains trim(field_name) call log_event(log_scratch_space, log_level_info) - ! Apply changes associated with tiles + fs_type => field_src%get_function_space() + ndata_src = fs_type%get_ndata() + fs_type => field_dst%get_function_space() + ndata_dst = fs_type%get_ndata() + + write(log_scratch_space, '(A,I5)') "ndata_dst ", ndata_dst + call log_event(log_scratch_space, log_level_debug) + write(log_scratch_space, '(A,I5)') "ndata_src ", ndata_src + call log_event(log_scratch_space, log_level_debug) + + if (ndata_src /= ndata_dst) then + + ! Need to add full list of fields on surface tiles + if ( field_name == 'tile_snow_rgrain' ) then + + multidata_map = modeldb%config%dst_jules_surface_types%multidata_map() + + write(log_scratch_space, '(*(g0,1x))') "multidata ", multidata_map + call log_event(log_scratch_space, log_level_debug) + + if ( size(multidata_map) /= ndata_dst ) then + write(log_scratch_space, '(A,I5,A,I5)') & + "size of multidata map = ", size(multidata_map), & + " not equal to ndata_dst = ", ndata_dst + call log_event(log_scratch_space, log_level_error) + end if + + call invoke( lfric2lfric_multidata_map_type( field_dst, ndata_dst, & + field_src, ndata_src, & + ndata_first )) + end if + ! If field name is a sea-ice field + ! rederive + + end if + end if end do - end subroutine lfric2lfric_tiles + end subroutine lfric2lfric_tiles end module lfric2lfric_tiles_mod diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 index 69fc77c0f1..6da02eeaf1 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_init_mod.f90 @@ -84,6 +84,7 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & logical(l_def), pointer :: horizontal_change logical(l_def), pointer :: vertical_change logical(l_def), pointer :: tile_change + logical(l_def), parameter :: no_xios = .true. ! For field creation and storage type(field_collection_type), pointer :: target_fields @@ -171,15 +172,18 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & !-------------------------------------------------------------------------- ! Initialise Intermediate Fields !-------------------------------------------------------------------------- + call modeldb%io_contexts%get_io_context(context_src, io_context) + call io_context%set_current() + if ( (horizontal_change .and. vertical_change) .or. & (horizontal_change .and. tile_change)) then call modeldb%fields%add_empty_field_collection(interm_collection_name) interm_fields => modeldb%fields%get_field_collection(interm_collection_name) if (mode == mode_ics) then - prefix = 'checkpoint_' + prefix = 'restart_' else if (mode == mode_lbc) then - prefix = 'lbc_' + prefix = '' end if do i = 1, num_fields @@ -187,13 +191,11 @@ subroutine init_lfric2lfric( modeldb, context_src, context_dst, & config_list(i), & interm_mesh, & interm_twod_mesh, & - prefix ) + prefix, & + no_xios ) end do end if - call modeldb%io_contexts%get_io_context(context_src, io_context) - call io_context%set_current() - ! Now finished with config_list, deallocate deallocate(config_list) diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 index 1b41ed2aa0..9c8d7aebf1 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_field_init_mod.f90 @@ -7,7 +7,7 @@ !> routine for field creation. module lfric2lfric_field_init_mod - use constants_mod, only: i_def, str_def + use constants_mod, only: i_def, str_def, l_def use field_collection_mod, only: field_collection_type use field_mod, only: field_type use field_parent_mod, only: read_interface, & @@ -135,14 +135,18 @@ end subroutine get_field_list !! initalised on !> @param [in] twod_mesh The 2D mesh the field could be !! intialised on - subroutine field_maker(field_collection, field_name, mesh, twod_mesh, prefix) + !> @param [in, optional] input_no_xios Don't apply xios associated parts + subroutine field_maker(field_collection, field_name, mesh, twod_mesh, prefix, input_no_xios) type(field_collection_type), pointer, intent(inout) :: field_collection character(len=*), intent(in) :: field_name type(mesh_type), pointer, intent(in) :: mesh type(mesh_type), pointer, intent(in) :: twod_mesh character(len=nf90_max_name), intent(in) :: prefix - + logical(l_def), optional, intent(in) :: input_no_xios + + logical(l_def) :: no_xios + ! Field object to initialise type(field_type) :: field @@ -153,6 +157,13 @@ subroutine field_maker(field_collection, field_name, mesh, twod_mesh, prefix) procedure(checkpoint_write_interface), pointer :: cp_write_behaviour procedure(checkpoint_read_interface), pointer :: cp_read_behaviour + no_xios = .false. + if (present(input_no_xios)) then + if (input_no_xios) then + no_xios = .true. + end if + endif + ! Set write behaviour to generic write_behaviour => write_field_generic read_behaviour => read_field_generic @@ -170,11 +181,13 @@ subroutine field_maker(field_collection, field_name, mesh, twod_mesh, prefix) name=field_name) ! Set the generic write behaviours - call field%set_read_behaviour(read_behaviour) - call field%set_write_behaviour(write_behaviour) - call field%set_checkpoint_read_behaviour(cp_read_behaviour) - call field%set_checkpoint_write_behaviour(cp_write_behaviour) - + if ( .NOT. no_xios ) then + call field%set_read_behaviour(read_behaviour) + call field%set_write_behaviour(write_behaviour) + call field%set_checkpoint_read_behaviour(cp_read_behaviour) + call field%set_checkpoint_write_behaviour(cp_write_behaviour) + end if + call log_event("Adding " // trim(field_name) // & " to field collection " // & field_collection%get_name(), & diff --git a/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_kernel_mod.F90 b/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_kernel_mod.F90 new file mode 100644 index 0000000000..0c97936a97 --- /dev/null +++ b/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_kernel_mod.F90 @@ -0,0 +1,117 @@ +!----------------------------------------------------------------------------- +! (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 Map multidata fields with different ndata numbers. +!> @details This is used for lfric2lfric reconfiguration, most likely +!! for regridding 2D fields on surface tiles. The multidata_map +!! is read from configuration and is an integer array (of size of +!! the destination ndata) containing a list of the array positions +!! from the source data. +module lfric2lfric_multidata_map_kernel_mod + + use argument_mod, only: arg_type, & + GH_FIELD, & + GH_SCALAR, & + GH_REAL, & + GH_INTEGER, & + GH_READ, & + GH_WRITE, & + GH_LOGICAL, & + CELL_COLUMN, & + ANY_SPACE_1, & + ANY_SPACE_2 + use constants_mod, only: i_def, r_def, l_def + use kernel_mod, only: kernel_type + use dst_jules_surface_types_config_mod, & + only: multidata_map + + implicit none + + private + + type, public, extends(kernel_type) :: lfric2lfric_multidata_map_type + private + type(arg_type), dimension(5) :: meta_args = (/ & + arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_SPACE_1), & ! field_dst + arg_type(GH_SCALAR, GH_INTEGER, GH_READ), & ! ndata_dst + arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_SPACE_2), & ! field_src + arg_type(GH_SCALAR, GH_INTEGER, GH_READ), & ! ndata_src + arg_type(GH_SCALAR, GH_LOGICAL, GH_READ) & ! ndata_first + /) + integer :: operates_on = CELL_COLUMN + contains + procedure, nopass :: lfric2lfric_multidata_map_code + end type lfric2lfric_multidata_map_type + + public :: lfric2lfric_multidata_map_code + +contains + +!> @brief Map a multidata field to another multidata field +!! @param[in] nlayers Number of layers +!! @param[in,out] field_dst Output (destination) multidata field +!! @param[in] ndata_dst Number of data points in field_dst +!! @param[in] field_src Input (source) multidata field +!! @param[in] ndata_src Number of data points in field_src +!! @param[in] ndata_first Data layout (data- or layer-first) +!! @param[in] ndf_dst Number of dofs per cell for field_dst +!! @param[in] undf_dst Total number of dofs per cell for field_dst +!! @param[in] map_dst Cell dofmap for field_dst +!! @param[in] ndf_src Number of dofs per cell for field_src +!! @param[in] undf_src Total number of dofs per cell for field_src +!! @param[in] map_src Cell dofmap for field_src +subroutine lfric2lfric_multidata_map_code(nlayers, & + field_dst, & + ndata_dst, & + field_src, & + ndata_src, & + ndata_first, & + ndf_dst, & + undf_dst, & + map_dst, & + ndf_src, & + undf_src, & + map_src) + + integer(kind=i_def), intent(in) :: nlayers + + integer(kind=i_def), intent(in) :: ndata_src + integer(kind=i_def), intent(in) :: ndf_src + integer(kind=i_def), intent(in) :: undf_src + integer(kind=i_def), intent(in) :: map_src(ndf_src) + + integer(kind=i_def), intent(in) :: ndata_dst + integer(kind=i_def), intent(in) :: ndf_dst + integer(kind=i_def), intent(in) :: undf_dst + integer(kind=i_def), intent(in) :: map_dst(ndf_dst) + + logical(kind=l_def), intent(in) :: ndata_first + + real(kind=r_def), intent(in) :: field_src(undf_src) + real(kind=r_def), intent(out) :: field_dst(undf_dst) + + integer(kind=i_def) :: df, i_dst, i_src, k + + if (ndata_first) then + do k = 0, nlayers - 1 + i_dst = map_dst(1) + k * ndata_dst + i_src = map_src(1) + k * ndata_src + do df = 0, ndata_dst -1 + field_dst( i_dst + df ) = field_src( i_src + multidata_map(df+1) -1 ) + end do + end do + else + do df = 0, ndata_dst - 1 + i_dst = map_dst(1) + df * nlayers + i_src = map_src(1) + (multidata_map(df+1) - 1) * nlayers + do k =0, nlayers-1 + field_dst( i_dst + k ) = field_src( i_src + k ) + end do + end do + end if + +end subroutine lfric2lfric_multidata_map_code + +end module lfric2lfric_multidata_map_kernel_mod From 3123afea6ab35a7d813d4d9a90e0fd7a5bcdc506 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:45:03 +0100 Subject: [PATCH 41/53] code review response # This is a combination of 9 commits. upgrade macro code review response correction correction correction correction correction (to allow for opts) metadata default rose meta compulsory false --- .../lfric-lfric2lfric/HEAD/rose-meta.conf | 12 +-- .../rose-meta/lfric-lfric2lfric/versions.py | 73 +++++++++++++++++++ .../source/driver/lfric2lfric_driver_mod.F90 | 36 +-------- .../lfric2lfric_infrastructure_mod.X90 | 8 +- .../lfric2lfric/opt/rose-app-clim_gal9.conf | 7 -- .../opt/rose-app-clim_gal9_ral_seuk.conf | 7 -- .../app/lfric2lfric/opt/rose-app-ral3.conf | 7 -- .../lfric2lfric/opt/rose-app-ral_seuk.conf | 7 -- rose-stem/app/lfric2lfric/rose-app.conf | 48 +++++------- 9 files changed, 107 insertions(+), 98 deletions(-) diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf index f392e31b3f..9eb4cf6863 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf @@ -8,14 +8,14 @@ compulsory=false !!trigger=namelist:partitioning: .false.; [namelist:extrusion_dst] -compulsory=true +compulsory=false description=Vertical extrusion settings for the destination mesh. help= ns=namelist/Model/Mesh/Extrusion sort-key=Section-A03 [namelist:extrusion_dst=domain_height] -compulsory=true +compulsory=false description=Height of domain above the surface [m] fail-if=this < 0.0 ; help=Height of the model domain above the surface. @@ -27,7 +27,7 @@ type=real [namelist:extrusion_dst=eta_values] !bounds=namelist:extrusion_dst=number_of_layers-1 -compulsory=true +compulsory=false description=Eta values, excluding 0 and 1 help=Non-dimensional height values defining the model vertical levels. =The length should be smaller by number_of_layers by one. @@ -42,7 +42,7 @@ sort-key=Panel-A04 type=real [namelist:extrusion_dst=method] -compulsory=true +compulsory=false description=Method for generating eta coordinate !enumeration=true fail-if=this == 'um_L38_29t_9s_40km' and namelist:extrusion_dst=number_of_layers != 38 ; @@ -75,7 +75,7 @@ values='uniform', 'quadratic', 'geometric', 'dcmip', ='um_L120_99t_21s_40km', 'um_L140_122t_18s_40km' [namelist:extrusion_dst=number_of_layers] -compulsory=true +compulsory=false description=Number of layers in the vertical fail-if=this < 1 ; help=Setting for number of layers of 3D-mesh in vertical. @@ -85,7 +85,7 @@ sort-key=Panel-A03 type=integer [namelist:extrusion_dst=planet_radius] -compulsory=true +compulsory=false description=Radius of the planet surface [m] fail-if=this <= 0.0 ; help=Radius of domain bottom. Note: Orography not included. diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/versions.py b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/versions.py index 01e65a2b91..3b09e937d1 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/versions.py +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/versions.py @@ -31,3 +31,76 @@ def upgrade(self, config, meta_config=None): # Add settings return config, self.reports """ + +class vn32_t581(MacroUpgrade): + # Upgrade macro for #581 by Christine Johnson + + BEFORE_TAG = "vn3.2" + AFTER_TAG = "vn3.2_t581" + + def upgrade(self, config, meta_config=None): + # Add settings + + domain_height = self.get_setting_value( + config, ["namelist:extrusion", "domain_height"] + ) + eta_values = self.get_setting_value( + config, ["namelist:extrusion", "eta_values"] + ) + method = self.get_setting_value( + config, ["namelist:extrusion", "method"] + ) + number_of_layers = self.get_setting_value( + config, ["namelist:extrusion", "number_of_layers"] + ) + planet_radius = self.get_setting_value( + config, ["namelist:extrusion", "planet_radius"] + ) + stretching_method = self.get_setting_value( + config, ["namelist:extrusion", "stretching_method"] + ) + stretching_height = self.get_setting_value( + config, ["namelist:extrusion", "stretching_height"] + ) + start_dump_filename = self.get_setting_value( + config, ["namelist:files", "start_dump_filename"] + ) + + if start_dump_filename != "'lfric2lfric_dump'" : + self.add_setting( + config, + ["namelist:extrusion_dst", "domain_height"], + domain_height, + ) + self.add_setting( + config, + ["namelist:extrusion_dst", "eta_values"], + eta_values, + ) + self.add_setting( + config, + ["namelist:extrusion_dst", "method"], + method, + ) + self.add_setting( + config, + ["namelist:extrusion_dst", "number_of_layers"], + number_of_layers, + ) + self.add_setting( + config, + ["namelist:extrusion_dst", "planet_radius"], + planet_radius, + ) + self.add_setting( + config, + ["namelist:extrusion_dst", "stretching_method"], + stretching_method, + ) + self.add_setting( + config, + ["namelist:extrusion_dst", "stretching_height"], + stretching_height, + ) + + return config, self.reports diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 0e5f16b007..6e78690249 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -24,9 +24,6 @@ module lfric2lfric_driver_mod use sci_checksum_alg_mod, only: checksum_alg use xios, only: xios_date, xios_get_current_date, & xios_date_convert_to_string - use orography_config_mod, only: orog_init_option_analytic, & - orog_init_option_ancil, & - orog_init_option_start_dump !------------------------------------ ! lfric2lfric modules @@ -36,8 +33,7 @@ module lfric2lfric_driver_mod context_dst, context_src, & source_collection_name, & target_collection_name, & - interm_collection_name, & - src, dst + interm_collection_name use lfric2lfric_regrid_mod, only: lfric2lfric_regrid use lfric2lfric_vert_mod, only: lfric2lfric_vert @@ -108,37 +104,10 @@ subroutine run( modeldb, oasis_clock ) type(lfric_xios_context_type), pointer :: io_context - character(len=str_def) :: mesh_names(2) - integer(kind=i_def) :: src_extrusion_method - integer(kind=i_def) :: dst_extrusion_method - integer(kind=i_def) :: src_number_of_layers - integer(kind=i_def) :: dst_number_of_layers - integer(kind=i_def) :: src_stretching_method - integer(kind=i_def) :: dst_stretching_method - integer(kind=i_def) :: orog_init_option - real(kind=r_def) :: src_domain_height - real(kind=r_def) :: dst_domain_height - real(kind=r_def) :: src_stretching_height - real(kind=r_def) :: dst_stretching_height - logical(kind=l_def), pointer :: vertical_change logical(kind=l_def), pointer :: horizontal_change ! Extract configuration variables - src_extrusion_method = modeldb%config%extrusion%method() - src_number_of_layers = modeldb%config%extrusion%number_of_layers() - src_domain_height = modeldb%config%extrusion%domain_height() - src_stretching_height = modeldb%config%extrusion%stretching_height() - src_stretching_method = modeldb%config%extrusion%stretching_method() - dst_extrusion_method = modeldb%config%extrusion_dst%method() - dst_number_of_layers = modeldb%config%extrusion_dst%number_of_layers() - dst_domain_height = modeldb%config%extrusion_dst%domain_height() - dst_stretching_height = modeldb%config%extrusion_dst%stretching_height() - dst_stretching_method = modeldb%config%extrusion_dst%stretching_method() - orog_init_option = modeldb%config%orography%orog_init_option() - - mesh_names(dst) = modeldb%config%lfric2lfric%destination_mesh_name() - mesh_names(src) = modeldb%config%lfric2lfric%source_mesh_name() start_dump_filename = modeldb%config%files%start_dump_filename() checkpoint_stem_name = modeldb%config%files%checkpoint_stem_name() @@ -160,6 +129,9 @@ subroutine run( modeldb, oasis_clock ) else if (vertical_change .and. .not. horizontal_change) then interm_fields => modeldb%fields%get_field_collection(source_collection_name) + + else + interm_fields => null() end if ! Read fields and perform the regridding diff --git a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 index 7d68aedde3..76152a2d0e 100644 --- a/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 +++ b/applications/lfric2lfric/source/initialisation/lfric2lfric_infrastructure_mod.X90 @@ -303,17 +303,17 @@ contains if ( horizontal_change ) then call log_event("Horizontal interpolation logical set to TRUE", & - log_level_info) + log_level_debug) else call log_event("Horizontal interpolation logical set to FALSE", & - log_level_info) + log_level_debug) end if if ( vertical_change ) then call log_event("Vertical interpolation logical set to TRUE", & - log_level_info) + log_level_debug) else call log_event("Vertical interpolation logical set to FALSE", & - log_level_info) + log_level_debug) end if !======================================================================= ! Mesh diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf index 4cb9093333..723f79bc39 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9.conf @@ -8,13 +8,6 @@ number_of_layers=70 stretching_height=17507.0 stretching_method='smooth' -[namelist:extrusion_dst] -domain_height=80000.0 -method='um_L70_50t_20s_80km' -number_of_layers=70 -stretching_height=17507.0 -stretching_method='smooth' - [namelist:files] checkpoint_stem_name='restart_lfric2lfric_clim_gal9_C12_MG' start_dump_filename='lfric2lfric_clim_gal9_C12_MG' diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf index 4af46b8816..2da98c9872 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-clim_gal9_ral_seuk.conf @@ -19,13 +19,6 @@ number_of_layers=70 stretching_height=17507.0 stretching_method='smooth' -[namelist:extrusion_dst] -domain_height=80000.0 -method='um_L70_50t_20s_80km' -number_of_layers=70 -stretching_height=17507.0 -stretching_method='smooth' - [namelist:files] checkpoint_stem_name='restart_lfric2lfric_ral_seuk_MG' start_dump_filename='lfric2lfric_clim_gal9_C12_MG' diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf b/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf index 5d9d3e097f..4235bafd08 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-ral3.conf @@ -11,13 +11,6 @@ number_of_layers=70 stretching_height=16641.984 stretching_method='smooth' -[namelist:extrusion_dst] -domain_height=40000.0 -method='um_L70_61t_9s_40km' -number_of_layers=70 -stretching_height=16641.984 -stretching_method='smooth' - [namelist:files] checkpoint_stem_name='restart_lfric2lfric_ral3_seuk' !!lbc_directory='$BIG_DATA_DIR/lbcs/proto-ral/Ticket3510/seuk' diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf b/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf index 1def0d95c3..558c0e5789 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-ral_seuk.conf @@ -11,13 +11,6 @@ number_of_layers=70 stretching_height=16641.984 stretching_method='smooth' -[namelist:extrusion_dst] -domain_height=40000.0 -method='um_L70_61t_9s_40km' -number_of_layers=70 -stretching_height=16641.984 -stretching_method='smooth' - [namelist:files] checkpoint_stem_name='restart_lfric2lfric_ral_seuk_MG' start_dump_filename='lfric2lfric_ral_seuk_MG' diff --git a/rose-stem/app/lfric2lfric/rose-app.conf b/rose-stem/app/lfric2lfric/rose-app.conf index 468f1fd6e2..58e0688dcc 100644 --- a/rose-stem/app/lfric2lfric/rose-app.conf +++ b/rose-stem/app/lfric2lfric/rose-app.conf @@ -1,4 +1,4 @@ -meta=lfric-lfric2lfric/HEAD +meta=lfric-lfric2lfric/vn3.2 [command] default=$CORE_ROOT_DIR/bin/tweak_iodef; \ @@ -105,28 +105,28 @@ sg_orog_mixing='none' !!zhloc_depth_fac=0 [namelist:boundaries] -!!blend_frequency='final' -!!blending_weights=0.0 -!!blending_weights_w2v=0.0 -!!boundary_e=1 -!!boundary_n=1 -!!boundary_s=1 -!!boundary_w=1 -!!edge_cells_ew=1 -!!edge_cells_ns=1 -!!inner_width_ew=1 -!!inner_width_ns=1 -!!lbc_eos_height=100 +!!blend_frequency='inner' +!!blending_weights=0 +!!blending_weights_w2v=0 +!!boundary_e=0 +!!boundary_n=0 +!!boundary_s=0 +!!boundary_w=0 +!!edge_cells_ew=0 +!!edge_cells_ns=0 +!!inner_width_ew=0 +!!inner_width_ns=0 +!!lbc_eos_height=0 !!lbc_method='coordinate_based' limited_area=.false. -!!normal_only=.true. -!!outer_width_ew=1 -!!outer_width_ns=1 +!!normal_only=.false. +!!outer_width_ew=0 +!!outer_width_ns=0 !!output_lbcs=.false. -!!rim_width_ew=1 -!!rim_width_ns=1 -!!solver_boundary_depth=1 -!!transport_boundary_depth=6 +!!rim_width_ew=0 +!!rim_width_ns=0 +!!solver_boundary_depth=0 +!!transport_boundary_depth=0 transport_overwrite_freq='final' [namelist:checks] @@ -271,14 +271,6 @@ number_of_layers=38 planet_radius=6371229.0 stretching_method='linear' -[namelist:extrusion_dst] -domain_height=39254.833575999997 -!!eta_values='' -method='um_L38_29t_9s_40km' -number_of_layers=38 -planet_radius=6371229.0 -stretching_method='linear' - [namelist:files] !!aerosols_ancil_path='' !!albedo_nir_ancil_path='' From 887abdffc19ee647e5f998e10e29395d5c1ec368 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 2 Sep 2026 15:06:34 +0100 Subject: [PATCH 42/53] Additional --- rose-stem/app/lfric2lfric/rose-app.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rose-stem/app/lfric2lfric/rose-app.conf b/rose-stem/app/lfric2lfric/rose-app.conf index 58e0688dcc..bb21c8afb5 100644 --- a/rose-stem/app/lfric2lfric/rose-app.conf +++ b/rose-stem/app/lfric2lfric/rose-app.conf @@ -117,7 +117,7 @@ sg_orog_mixing='none' !!inner_width_ew=0 !!inner_width_ns=0 !!lbc_eos_height=0 -!!lbc_method='coordinate_based' +!!lbc_method='onion_layer' limited_area=.false. !!normal_only=.false. !!outer_width_ew=0 From c58c7d3d1492aa88b9ba01268b6f1dc4dddac70a Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Wed, 2 Sep 2026 15:09:05 +0100 Subject: [PATCH 43/53] additional2 --- .../lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 6e78690249..bd88bde9b2 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -8,7 +8,7 @@ module lfric2lfric_driver_mod use constants_mod, only: str_def, str_max_filename, & - i_def, r_def, l_def, r_second + i_def, l_def, r_second use driver_fem_mod, only: final_fem use driver_io_mod, only: final_io use driver_modeldb_mod, only: modeldb_type From 54ac29ad4f34355b212ae203725ed1e44a4bdd51 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 4 Sep 2026 16:25:04 +0100 Subject: [PATCH 44/53] correction after merge --- rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index ace55daf93..e5faee9aa9 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -148,7 +148,7 @@ {% do task_dict.update({ "opt_confs": ["clim_gal9_ral_seuk","oasis","src_L70_80km","dst_L38_40km"], - "resolution": "C12_C16_lam", + "resolution": ["C24_C12", "seuk_MG"], "dst_mesh": "seuk_MG", "dst_name": "dynamics", "dst_type": "regional", From 6e4036b3d052524be903744b214f8b88ddd9db9e Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 4 Sep 2026 17:11:30 +0100 Subject: [PATCH 45/53] additional changes since merge --- rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index e5faee9aa9..5a1f503ef7 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -147,7 +147,7 @@ {% elif task_ns.conf_name == "oasis_C12L70_to_seukL38" %} {% do task_dict.update({ - "opt_confs": ["clim_gal9_ral_seuk","oasis","src_L70_80km","dst_L38_40km"], + "opt_confs": ["oasis","src_L70_80km","dst_L38_40km"], "resolution": ["C24_C12", "seuk_MG"], "dst_mesh": "seuk_MG", "dst_name": "dynamics", @@ -160,7 +160,7 @@ {% elif task_ns.conf_name == "oasis_C12L70_to_C12L38" %} {% do task_dict.update({ - "opt_confs": ["clim_gal9","oasis","src_L70_80km","dst_L38_40km"], + "opt_confs": ["oasis","src_L70_80km","dst_L38_40km"], "resolution": "C12", "dst_mesh": "C12", "dst_name": "dynamics", From a3b363cbb45ee8965c22efac73285eb7b320af8d Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Fri, 4 Sep 2026 17:57:47 +0100 Subject: [PATCH 46/53] correction after merge --- .../site/common/lfric2lfric/tasks_lfric2lfric.cylc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index 5a1f503ef7..24dede6112 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -147,7 +147,7 @@ {% elif task_ns.conf_name == "oasis_C12L70_to_seukL38" %} {% do task_dict.update({ - "opt_confs": ["oasis","src_L70_80km","dst_L38_40km"], + "opt_confs": ["oasis","src_C12_L70","src_L70_80km","dst_L38_40km"], "resolution": ["C24_C12", "seuk_MG"], "dst_mesh": "seuk_MG", "dst_name": "dynamics", @@ -160,13 +160,13 @@ {% elif task_ns.conf_name == "oasis_C12L70_to_C12L38" %} {% do task_dict.update({ - "opt_confs": ["oasis","src_L70_80km","dst_L38_40km"], - "resolution": "C12", - "dst_mesh": "C12", - "dst_name": "dynamics", + "opt_confs": ["oasis","src_C12_L70","src_L70_80km","dst_L38_40km"], + "resolution": "C24_C12", + "dst_mesh": "C24_C12", + "dst_name": "C12", "dst_type": "global", - "src_mesh": "C12", - "src_name": "dynamics", + "src_mesh": "C24_C12", + "src_name": "C12", "src_type": "global", }) %} From c3602a99385c0d31c70c2077d9d867eb8dda8362 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:38:08 +0100 Subject: [PATCH 47/53] separate src_c12 and dst_c12 --- .../{rose-app-C12.conf => rose-app-dst_C12.conf} | 2 -- .../app/lfric2lfric/opt/rose-app-src_C12.conf | 8 ++++++++ .../site/common/lfric2lfric/tasks_lfric2lfric.cylc | 14 +++++++------- 3 files changed, 15 insertions(+), 9 deletions(-) rename rose-stem/app/lfric2lfric/opt/{rose-app-C12.conf => rose-app-dst_C12.conf} (58%) create mode 100644 rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-C12.conf b/rose-stem/app/lfric2lfric/opt/rose-app-dst_C12.conf similarity index 58% rename from rose-stem/app/lfric2lfric/opt/rose-app-C12.conf rename to rose-stem/app/lfric2lfric/opt/rose-app-dst_C12.conf index 87cbe9951d..95c1cb635c 100644 --- a/rose-stem/app/lfric2lfric/opt/rose-app-C12.conf +++ b/rose-stem/app/lfric2lfric/opt/rose-app-dst_C12.conf @@ -1,5 +1,3 @@ [namelist:lfric2lfric] destination_mesh_name='dynamics' destination_meshfile_prefix='${MESH_DIR}/C12/mesh_C12' -source_mesh_name='dynamics' -source_meshfile_prefix='${MESH_DIR}/C12/mesh_C12' diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf b/rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf new file mode 100644 index 0000000000..6e98d032c4 --- /dev/null +++ b/rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf @@ -0,0 +1,8 @@ +[file:lfric2lfric_clim_gal9_C12_MG.nc] +source="$BIG_DATA_DIR/start_dumps/proto-ral/AppsTicket110/lfric_atm_clim_gal9_C12_dt-1800p0_intel_64-bit_fast-debug_000072.nc" + +[namelist:lfric2lfric] +source_meshfile_prefix='${MESH_DIR}/C12/mesh_C12' + +[namelist:files] +start_dump_filename='lfric2lfric_clim_gal9_C12_MG' \ No newline at end of file diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index 24dede6112..3d9dedd05d 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -147,7 +147,7 @@ {% elif task_ns.conf_name == "oasis_C12L70_to_seukL38" %} {% do task_dict.update({ - "opt_confs": ["oasis","src_C12_L70","src_L70_80km","dst_L38_40km"], + "opt_confs": ["oasis","src_C12_L70","dst_seuk","src_L70_80km","dst_L38_40km"], "resolution": ["C24_C12", "seuk_MG"], "dst_mesh": "seuk_MG", "dst_name": "dynamics", @@ -160,13 +160,13 @@ {% elif task_ns.conf_name == "oasis_C12L70_to_C12L38" %} {% do task_dict.update({ - "opt_confs": ["oasis","src_C12_L70","src_L70_80km","dst_L38_40km"], - "resolution": "C24_C12", - "dst_mesh": "C24_C12", - "dst_name": "C12", + "opt_confs": ["oasis","src_C12","dst_C12","src_L70_80km","dst_L38_40km"], + "resolution": "C12", + "dst_mesh": "C12", + "dst_name": "dynamics", "dst_type": "global", - "src_mesh": "C24_C12", - "src_name": "C12", + "src_mesh": "C12", + "src_name": "dynamics", "src_type": "global", }) %} From 145f84de509d719d8216402008fddbcae011a8fb Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 7 Sep 2026 11:35:21 +0100 Subject: [PATCH 48/53] src_C12 should be src_c12_c70 --- rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf | 8 -------- rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc | 8 ++++---- 2 files changed, 4 insertions(+), 12 deletions(-) delete mode 100644 rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf diff --git a/rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf b/rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf deleted file mode 100644 index 6e98d032c4..0000000000 --- a/rose-stem/app/lfric2lfric/opt/rose-app-src_C12.conf +++ /dev/null @@ -1,8 +0,0 @@ -[file:lfric2lfric_clim_gal9_C12_MG.nc] -source="$BIG_DATA_DIR/start_dumps/proto-ral/AppsTicket110/lfric_atm_clim_gal9_C12_dt-1800p0_intel_64-bit_fast-debug_000072.nc" - -[namelist:lfric2lfric] -source_meshfile_prefix='${MESH_DIR}/C12/mesh_C12' - -[namelist:files] -start_dump_filename='lfric2lfric_clim_gal9_C12_MG' \ No newline at end of file diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index 3d9dedd05d..e32dde76b8 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -160,13 +160,13 @@ {% elif task_ns.conf_name == "oasis_C12L70_to_C12L38" %} {% do task_dict.update({ - "opt_confs": ["oasis","src_C12","dst_C12","src_L70_80km","dst_L38_40km"], - "resolution": "C12", + "opt_confs": ["oasis","src_C12_L70","dst_C12","src_L70_80km","dst_L38_40km"], + "resolution": ["C24_C12", C12"], "dst_mesh": "C12", "dst_name": "dynamics", "dst_type": "global", - "src_mesh": "C12", - "src_name": "dynamics", + "src_mesh": "C24_C12", + "src_name": "C12", "src_type": "global", }) %} From e46d21ed38b0aab820d2a8d00424670d1d57198b Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 7 Sep 2026 11:38:10 +0100 Subject: [PATCH 49/53] typo --- rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc index e32dde76b8..ebdb1a500b 100644 --- a/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc +++ b/rose-stem/site/common/lfric2lfric/tasks_lfric2lfric.cylc @@ -161,7 +161,7 @@ {% do task_dict.update({ "opt_confs": ["oasis","src_C12_L70","dst_C12","src_L70_80km","dst_L38_40km"], - "resolution": ["C24_C12", C12"], + "resolution": ["C24_C12", "C12"], "dst_mesh": "C12", "dst_name": "dynamics", "dst_type": "global", From 3623bd66a0a8773e0583685dd3900f8d6146772c Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 14 Sep 2026 10:49:25 +0100 Subject: [PATCH 50/53] compiles and runs example --- .../lfric2lfric/example/configuration.nml | 3 +- applications/lfric2lfric/example/iodef.xml | 31 +- .../lfric-lfric2lfric/HEAD/rose-meta.conf | 8 +- .../algorithm/lfric2lfric_multidata_mod.x90 | 275 ++++++++++++++++++ .../algorithm/lfric2lfric_tiles_mod.x90 | 123 -------- .../source/driver/lfric2lfric_driver_mod.F90 | 5 +- ...lfric_multidata_map_surface_kernel_mod.F90 | 99 +++++++ .../lfric2lfric_multidata_snow_kernel_mod.F90 | 126 ++++++++ 8 files changed, 530 insertions(+), 140 deletions(-) create mode 100644 applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 delete mode 100644 applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 create mode 100644 applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_surface_kernel_mod.F90 create mode 100644 applications/lfric2lfric/source/kernel/lfric2lfric_multidata_snow_kernel_mod.F90 diff --git a/applications/lfric2lfric/example/configuration.nml b/applications/lfric2lfric/example/configuration.nml index c51a1dc063..407f6555d0 100644 --- a/applications/lfric2lfric/example/configuration.nml +++ b/applications/lfric2lfric/example/configuration.nml @@ -112,5 +112,6 @@ coord_space = 'Wchi', / &dst_jules_surface_types - multidata_map = 1,2,11,6,6,6,7,8,9 +! https://github.com/MetOffice/um/blob/main/rose-stem/app/um_seukv_eg/opt/rose-app-reconukv.conf + multidata_map = 1,2,3,4,5,6,6,7,8,9 / diff --git a/applications/lfric2lfric/example/iodef.xml b/applications/lfric2lfric/example/iodef.xml index 4568a3f594..f36076995a 100644 --- a/applications/lfric2lfric/example/iodef.xml +++ b/applications/lfric2lfric/example/iodef.xml @@ -2,7 +2,7 @@ - + @@ -15,17 +15,21 @@ - + + - + - + - + + + + @@ -44,12 +48,12 @@ - + - + @@ -57,17 +61,20 @@ - + - + - + - - + + + + + diff --git a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf index dfb8e75960..bec7946a78 100644 --- a/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf +++ b/applications/lfric2lfric/rose-meta/lfric-lfric2lfric/HEAD/rose-meta.conf @@ -415,8 +415,14 @@ title=dst_jules_surface_types [namelist:dst_jules_surface_types=multidata_map] compulsory=true description=Multidata map for surface/land tiles. -help=List multidata levels to map to the +help=List the multidata levels to map to the =destination multidata field. + =For example, if src_field has 4 multidata fields + =and dst_field has 3 multidata fields. + =If multidata_map = 1,4,2 then + =dst_field(1) = src_field(1) + =dst_field(2) = src_field(4) + =dst_field(3) = src_field(2) !kind=default length=: ns=namelist/lfric2lfric/configuration diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 new file mode 100644 index 0000000000..2eb6f1a699 --- /dev/null +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 @@ -0,0 +1,275 @@ +!----------------------------------------------------------------------------- +! (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 Reconfiguration associated with changes in number of multidata fields (tiles). +module lfric2lfric_multidata_mod + + use constants_mod, only: str_def, i_def, r_def, l_def + use driver_modeldb_mod, only: modeldb_type + use extrusion_mod, only: TWOD + use field_parent_mod, only: field_parent_type + use field_mod, only: field_type + use field_collection_mod, only: field_collection_type + use field_collection_iterator_mod, & + only: field_collection_iterator_type + use function_space_mod, only: function_space_type + use mesh_mod, only: mesh_type + use lfric2lfric_multidata_map_surface_kernel_mod, & + only: lfric2lfric_multidata_map_surface_type + use lfric2lfric_multidata_snow_kernel_mod, & + only: lfric2lfric_multidata_snow_type + use sci_field_minmax_alg_mod, only: get_field_minmax + use log_mod, only: log_event, & + log_level_debug, & + log_level_info, & + log_level_error, & + log_scratch_space + + implicit none + + private + public :: lfric2lfric_multidata, lfric2lfric_retile_surface_tiles + +contains + + !> @brief Apply the changes associated with the change in size of multidata fields. + !> @details Loop over the fields in the source_fields collection, + !! and deal with the change in tiles, depending on the tile type. + !> @param modeldb Model state object + !> @param source_fields The collection of fields to be regridded + !> @param target_fields The collection of regridded fields + subroutine lfric2lfric_multidata( modeldb, source_fields, target_fields ) + + implicit none + + type(modeldb_type), intent(inout) :: modeldb + type(field_collection_type), intent(inout) :: source_fields + type(field_collection_type), intent(inout) :: target_fields + + type(field_collection_iterator_type) :: iter + + class(field_parent_type), pointer :: field + type(field_type), pointer :: field_src + type(field_type), pointer :: field_dst + type(field_type), pointer :: field_src_n_snow_layers + type(field_type), pointer :: field_src_snow_layer + type(field_type), pointer :: field_dst_snow_layer + type(mesh_type), pointer :: mesh + type(function_space_type), pointer :: fs_type + + integer(kind=i_def) :: ndata_dst, ndata_src + integer(kind=i_def) :: n_snow_layers_src, n_snow_layers_dst + integer(kind=i_def) :: n_land_tiles_src, n_land_tiles_dst + real(kind=r_def) :: number_snow_layers, dummy + character(len=str_def) :: field_name + integer(i_def), allocatable :: multidata_map(:) + + write(log_scratch_space, '(A)') "Starting lfric2lfric_multidata" + call log_event(log_scratch_space, log_level_debug) + + !---- Precalculations + + !-- Find the number of snow layers in the source data + call source_fields%get_field('n_snow_layers', field_src_n_snow_layers) + call get_field_minmax(field_src_n_snow_layers, dummy, number_snow_layers) + n_snow_layers_src = nint(number_snow_layers) + + !-- Determine the number of snow layers in the target data + ! Assume for now that it is the same as the source data + ! Otherwise this could be added to a rose namelist + n_snow_layers_dst = n_snow_layers_src + + !-- Determine n_land_tiles_src + ! Derive effective number of land tiles in source field from snow fields + call source_fields%get_field('snow_layer_temp', field_src_snow_layer) + fs_type => field_src_snow_layer%get_function_space() + ndata_src = fs_type%get_ndata() + n_land_tiles_src = ndata_src / n_snow_layers_src + + !-- Determine n_land_tiles_dst + ! Derive effective number of land tiles in destination field from snow fields + call target_fields%get_field('snow_layer_temp', field_dst_snow_layer) + fs_type => field_dst_snow_layer%get_function_space() + ndata_dst = fs_type%get_ndata() + n_land_tiles_dst = ndata_dst / n_snow_layers_dst + + !-- Check multidata map + multidata_map = modeldb%config%dst_jules_surface_types%multidata_map() + + write(log_scratch_space, '(*(g0,1x))') "multidata ", multidata_map + call log_event(log_scratch_space, log_level_debug) + + if ( size(multidata_map) /= n_land_tiles_dst ) then + write(log_scratch_space, '(A,I5,A,I5)') & + "size of multidata map = ", size(multidata_map), & + " not equal to n_land_tiles_dst = ", n_land_tiles_dst + call log_event(log_scratch_space, log_level_error) + end if + + !------ Main loop over fields to be processed + call iter%initialise(source_fields) + do + ! Locate the field to be processed in the field collections + if ( .not. iter%has_next() ) exit + field => iter%next() + field_name = field%get_name() + + call source_fields%get_field(field_name, field_src) + call target_fields%get_field(field_name, field_dst) + + ! Continue if it is a 2D mesh field + mesh => field_src%get_mesh() + if (mesh%get_extrusion_id() == TWOD) then + + write(log_scratch_space, '(A,A)') "Processing lfric field", & + trim(field_name) + call log_event(log_scratch_space, log_level_debug) + + ! Find the size of the multidata field + fs_type => field_src%get_function_space() + ndata_src = fs_type%get_ndata() + fs_type => field_dst%get_function_space() + ndata_dst = fs_type%get_ndata() + + write(log_scratch_space, '(A,I5)') "ndata_dst ", ndata_dst + call log_event(log_scratch_space, log_level_debug) + write(log_scratch_space, '(A,I5)') "ndata_src ", ndata_src + call log_event(log_scratch_space, log_level_debug) + + ! if multidata field + if ((ndata_dst > 1) .or. (ndata_src > 1)) then + + ! Based on UM rcf_field_calcs + select case (field_name) + + ! Surface tiles - based on rcf_calc_tiles, rcf_init_field_on_tiles (L240) + case ('tile_fraction' , & + 'tile_temperature' , & + 'screen_temperature' , & + 'tile_canopy_water' , & + 'tile_lw_grey_albedo', & + 'tile_snow_mass' , & + 'tile_snow_rgrain' , & + 'n_snow_layers' , & + 'snow_depth' , & + 'snowpack_density' , & + 'snow_under_canopy' ) + + if (n_land_tiles_src /= n_land_tiles_dst) then + ! As the fields might use surface_tiles, only loop over land_tiles + call lfric2lfric_retile_surface_tiles( & + modeldb, field_dst, field_src, n_land_tiles_dst, n_land_tiles_src ) + else + ! Copy field_src to field_dst - but careful if one is n_land tiles and one is n_surface + !... + end if + + ! Snow Layers and Tiles - based on rcf_ml_snowpack + case ('snow_layer_temp' , & + 'snow_layer_thickness' , & + 'snow_layer_ice_mass' , & + 'snow_layer_liq_mass' , & + 'snow_layer_rgrain') + + if ( (n_land_tiles_src /= n_land_tiles_dst) ) then + ! Assume size land_tiles & n_snow - need to check + ! Assume snow layers same - need to check + call lfric2lfric_retile_snow( & + modeldb, field_dst, field_src, n_snow_layers_dst, n_land_tiles_dst, n_snow_layers_src, n_land_tiles_src ) + else + ! Copy + end if + + ! Sea Ice Categories - sea_ice_temperature based on rcf_derv_sea_ice_temp + case ('sea_ice_temperature') + ! Need to check, add error message or copy + + ! Sea Ice Categories - sea_ice_thickness based on rcf_derv_ice_cat_thick + case ('sea_ice_thickness') + ! Need to check, add error message or copy + + ! Soil Levels - based on rcf_init_soil_temp + case ('soil_temperature') + ! Need to check, add error message or copy + + case default + write(log_scratch_space, '(A,A)') & + trim(field_name), " needs to have code added" + call log_event(log_scratch_space, log_level_error) + + end select + else + ! Straightforward copy if not multidata ?? + call invoke( setval_X(field_dst, field_src)) + end if + end if + end do + + end subroutine lfric2lfric_multidata + + !> @brief Retile a field with surface_tiles + !> @details Map a multidata field where the source and destination have different sizes + !! and the mapping is governed by a multidata map. + !> @param modeldb Model state object + !> @param field_dst Destination multidata field + !> @param field_src Source multidata field + !> @param nland_tiles_dst Number of land tiles in destination field + !> @param nland_tiles_src Number of land tiles in source field + subroutine lfric2lfric_retile_surface_tiles( modeldb, field_dst, field_src, n_land_tiles_dst, n_land_tiles_src ) + + implicit none + + type(modeldb_type), intent(inout) :: modeldb + type(field_type), intent(inout) :: field_dst + type(field_type), intent(in) :: field_src + integer(kind=i_def), intent(in) :: n_land_tiles_dst + integer(kind=i_def), intent(in) :: n_land_tiles_src + + write(log_scratch_space, '(A)') "Starting lfric2lfric_retile_surface_tiles" + call log_event(log_scratch_space, log_level_debug) + + call invoke( lfric2lfric_multidata_map_surface_type( field_dst, n_land_tiles_dst, & + field_src, n_land_tiles_src)) + + end subroutine lfric2lfric_retile_surface_tiles + + !> @brief Retile a field with snow_layers_and_tiles + !> @details Map a multidata snow field where the source and destination have different sizes + !> @param modeldb Model state object + !> @param field_dst Destination multidata field + !> @param field_src Source multidata field + !> @param n_snow_layers_dst Source number of snow layers in destination + !> @param n_tiles_dst Source number of land tiles in destination + !> @param n_snow_layers_src Source number of snow layers in source + !> @param n_tiles_src Source number of land tiles in source + subroutine lfric2lfric_retile_snow( modeldb, field_dst, field_src, & + n_snow_layers_dst, n_tiles_dst, n_snow_layers_src, n_tiles_src ) + + implicit none + + type(modeldb_type), intent(inout) :: modeldb + type(field_type), intent(inout) :: field_dst + type(field_type), intent(in) :: field_src + integer(kind=i_def), intent(in) :: n_snow_layers_dst + integer(kind=i_def), intent(in) :: n_tiles_dst + integer(kind=i_def), intent(in) :: n_snow_layers_src + integer(kind=i_def), intent(in) :: n_tiles_src + + logical(l_def), parameter :: ndata_first = .false. + + write(log_scratch_space, '(A)') "Starting lfric2lfric_retile_snow" + call log_event(log_scratch_space, log_level_debug) + + call invoke( lfric2lfric_multidata_snow_type( field_dst, & + field_src, & + n_snow_layers_dst, & + n_tiles_dst, & + n_snow_layers_src, & + n_tiles_src, & + ndata_first )) + + end subroutine lfric2lfric_retile_snow + +end module lfric2lfric_multidata_mod diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 deleted file mode 100644 index d3e10c0bec..0000000000 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_tiles_mod.x90 +++ /dev/null @@ -1,123 +0,0 @@ -!----------------------------------------------------------------------------- -! (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 Reconfiguration associated with changes in tiles -module lfric2lfric_tiles_mod - - use constants_mod, only: str_def, i_def, l_def - use driver_modeldb_mod, only: modeldb_type - use extrusion_mod, only: TWOD - use field_parent_mod, only: field_parent_type - use field_mod, only: field_type - use field_collection_mod, only: field_collection_type - use field_collection_iterator_mod, & - only: field_collection_iterator_type - use function_space_mod, only: function_space_type - use mesh_mod, only: mesh_type - use lfric2lfric_multidata_map_kernel_mod, & - only: lfric2lfric_multidata_map_type - use log_mod, only: log_event, & - log_level_debug, & - log_level_info, & - log_level_error, & - log_scratch_space - - implicit none - - private - public :: lfric2lfric_tiles - -contains - - !> @brief Apply the changes associated with the change in tiles. - !> @details Loop over the fields in the source_fields collection, - !! and deal with the change in tiles. - !> @param modeldb Model state object - !> @param source_fields The collection of fields to be regridded - !> @param target_fields The collection of regridded fields - subroutine lfric2lfric_tiles( modeldb, source_fields, target_fields ) - - implicit none - - type(modeldb_type), intent(inout) :: modeldb - type(field_collection_type), intent(inout) :: source_fields - type(field_collection_type), intent(inout) :: target_fields - - type(field_collection_iterator_type) :: iter - - class(field_parent_type), pointer :: field - type(field_type), pointer :: field_src - type(field_type), pointer :: field_dst - type(mesh_type), pointer :: mesh - type(function_space_type), pointer :: fs_type - integer(i_def), allocatable :: multidata_map(:) - integer(kind=i_def) :: ndata_dst, ndata_src - character(len=str_def) :: field_name - logical(l_def), parameter :: ndata_first = .false. - - write(log_scratch_space, '(A)') "Tiles " - call log_event(log_scratch_space, log_level_info) - - ! Main loop over fields to be processed - call iter%initialise(source_fields) - do - ! Locate the field to be processed in the field collections - if ( .not.iter%has_next() ) exit - field => iter%next() - field_name = field%get_name() - - call source_fields%get_field(field_name, field_src) - call target_fields%get_field(field_name, field_dst) - - ! Continue if it is a 2D mesh field - mesh => field_src%get_mesh() - if (mesh%get_extrusion_id() == TWOD) then - - write(log_scratch_space, '(A,A)') "Processing lfric field ", & - trim(field_name) - call log_event(log_scratch_space, log_level_info) - - fs_type => field_src%get_function_space() - ndata_src = fs_type%get_ndata() - fs_type => field_dst%get_function_space() - ndata_dst = fs_type%get_ndata() - - write(log_scratch_space, '(A,I5)') "ndata_dst ", ndata_dst - call log_event(log_scratch_space, log_level_debug) - write(log_scratch_space, '(A,I5)') "ndata_src ", ndata_src - call log_event(log_scratch_space, log_level_debug) - - if (ndata_src /= ndata_dst) then - - ! Need to add full list of fields on surface tiles - if ( field_name == 'tile_snow_rgrain' ) then - - multidata_map = modeldb%config%dst_jules_surface_types%multidata_map() - - write(log_scratch_space, '(*(g0,1x))') "multidata ", multidata_map - call log_event(log_scratch_space, log_level_debug) - - if ( size(multidata_map) /= ndata_dst ) then - write(log_scratch_space, '(A,I5,A,I5)') & - "size of multidata map = ", size(multidata_map), & - " not equal to ndata_dst = ", ndata_dst - call log_event(log_scratch_space, log_level_error) - end if - - call invoke( lfric2lfric_multidata_map_type( field_dst, ndata_dst, & - field_src, ndata_src, & - ndata_first )) - end if - ! If field name is a sea-ice field - ! rederive - - end if - - end if - end do - - end subroutine lfric2lfric_tiles - -end module lfric2lfric_tiles_mod diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index 00e63865fa..e254c24988 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -36,8 +36,7 @@ module lfric2lfric_driver_mod interm_collection_name use lfric2lfric_regrid_mod, only: lfric2lfric_regrid use lfric2lfric_vert_mod, only: lfric2lfric_vert - use lfric2lfric_tiles_mod, only: lfric2lfric_tiles - + use lfric2lfric_multidata_mod, only: lfric2lfric_multidata implicit none @@ -154,7 +153,7 @@ subroutine run( modeldb, oasis_clock ) call lfric2lfric_vert(modeldb, interm_fields, target_fields) end if if (tile_change) then - call lfric2lfric_tiles(modeldb, interm_fields, target_fields) + call lfric2lfric_multidata(modeldb, interm_fields, target_fields) end if ! Write output diff --git a/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_surface_kernel_mod.F90 b/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_surface_kernel_mod.F90 new file mode 100644 index 0000000000..c5f8267065 --- /dev/null +++ b/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_map_surface_kernel_mod.F90 @@ -0,0 +1,99 @@ +!----------------------------------------------------------------------------- +! (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 Map 2D multidata fields with different ndata numbers. +!> @details This is used for lfric2lfric reconfiguration, most likely +!! for regridding 2D fields on surface tiles. The multidata_map +!! is read from configuration and is an integer array (of size of +!! the destination ndata) containing a list of the array positions +!! from the source data. +module lfric2lfric_multidata_map_surface_kernel_mod + + use argument_mod, only: arg_type, & + GH_FIELD, & + GH_SCALAR, & + GH_REAL, & + GH_INTEGER, & + GH_READ, & + GH_WRITE, & + CELL_COLUMN, & + ANY_SPACE_1, & + ANY_SPACE_2 + use constants_mod, only: i_def, r_def, l_def + use kernel_mod, only: kernel_type + use dst_jules_surface_types_config_mod, & + only: multidata_map + + implicit none + + private + + type, public, extends(kernel_type) :: lfric2lfric_multidata_map_surface_type + private + type(arg_type), dimension(4) :: meta_args = (/ & + arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_SPACE_1), & ! field_dst + arg_type(GH_SCALAR, GH_INTEGER, GH_READ), & + arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_SPACE_2), & ! field_src + arg_type(GH_SCALAR, GH_INTEGER, GH_READ) & + /) + integer :: operates_on = CELL_COLUMN + contains + procedure, nopass :: lfric2lfric_multidata_map_surface_code + end type lfric2lfric_multidata_map_surface_type + + public :: lfric2lfric_multidata_map_surface_code + +contains + +!> @brief Map a multidata field to another multidata field +!! @param[in] nlayers Number of layers +!! @param[in,out] field_dst Output (destination) multidata field +!! @param[in] ndata_dst +!! @param[in] field_src Input (source) multidata field +!! @param[in] ndata_src +!! @param[in] ndf_dst Number of dofs per cell for field_dst +!! @param[in] undf_dst Total number of dofs per cell for field_dst +!! @param[in] map_dst Cell dofmap for field_dst +!! @param[in] ndf_src Number of dofs per cell for field_src +!! @param[in] undf_src Total number of dofs per cell for field_src +!! @param[in] map_src Cell dofmap for field_src +subroutine lfric2lfric_multidata_map_surface_code(nlayers, & + field_dst, & + ndata_dst, & + field_src, & + ndata_src, & + ndf_dst, & + undf_dst, & + map_dst, & + ndf_src, & + undf_src, & + map_src) + + integer(kind=i_def), intent(in) :: nlayers + + integer(kind=i_def), intent(in) :: ndata_src + integer(kind=i_def), intent(in) :: ndf_src + integer(kind=i_def), intent(in) :: undf_src + integer(kind=i_def), intent(in) :: map_src(ndf_src) + + integer(kind=i_def), intent(in) :: ndata_dst + integer(kind=i_def), intent(in) :: ndf_dst + integer(kind=i_def), intent(in) :: undf_dst + integer(kind=i_def), intent(in) :: map_dst(ndf_dst) + + real(kind=r_def), intent(in) :: field_src(undf_src) + real(kind=r_def), intent(out) :: field_dst(undf_dst) + + integer(kind=i_def) :: df, i_dst, i_src + + i_dst = map_dst(1) + i_src = map_src(1) + do df = 0, ndata_dst -1 + field_dst( i_dst + df ) = field_src( i_src + multidata_map(df+1) -1 ) + end do + +end subroutine lfric2lfric_multidata_map_surface_code + +end module lfric2lfric_multidata_map_surface_kernel_mod diff --git a/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_snow_kernel_mod.F90 b/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_snow_kernel_mod.F90 new file mode 100644 index 0000000000..a9cc78b0ef --- /dev/null +++ b/applications/lfric2lfric/source/kernel/lfric2lfric_multidata_snow_kernel_mod.F90 @@ -0,0 +1,126 @@ +!----------------------------------------------------------------------------- +! (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 Map multidata snow fields with different ndata numbers. +!> @details This is used for lfric2lfric reconfiguration, most likely +!! for regridding 2D fields on snow layers and tiles. +module lfric2lfric_multidata_snow_kernel_mod + + use argument_mod, only: arg_type, & + GH_FIELD, & + GH_SCALAR, & + GH_REAL, & + GH_INTEGER, & + GH_READ, & + GH_WRITE, & + GH_LOGICAL, & + CELL_COLUMN, & + ANY_SPACE_1, & + ANY_SPACE_2 + use constants_mod, only: i_def, r_def, l_def + use kernel_mod, only: kernel_type + use dst_jules_surface_types_config_mod, & + only: multidata_map + + implicit none + + private + + type, public, extends(kernel_type) :: lfric2lfric_multidata_snow_type + private + type(arg_type), dimension(7) :: meta_args = (/ & + arg_type(GH_FIELD, GH_REAL, GH_WRITE, ANY_SPACE_1), & ! field_dst + arg_type(GH_FIELD, GH_REAL, GH_READ, ANY_SPACE_2), & ! field_src + arg_type(GH_SCALAR, GH_INTEGER, GH_READ), & ! n_snow_layers_dst + arg_type(GH_SCALAR, GH_INTEGER, GH_READ), & ! n_land_tiles_dst + arg_type(GH_SCALAR, GH_INTEGER, GH_READ), & ! n_snow_layers_src + arg_type(GH_SCALAR, GH_INTEGER, GH_READ), & ! n_land_tiles_src + arg_type(GH_SCALAR, GH_LOGICAL, GH_READ) & ! ntiles_first + /) + integer :: operates_on = CELL_COLUMN + contains + procedure, nopass :: lfric2lfric_multidata_snow_code + end type lfric2lfric_multidata_snow_type + + public :: lfric2lfric_multidata_snow_code + +contains + +!> @brief Map a multidata field to another multidata field +!! @param[in] nlayers Number of layers +!! @param[in,out] field_dst Output (destination) multidata field +!! @param[in] field_src Input (source) multidata field +!! @parm[in] n_snow_layers_dst +!! @param[in] n_tiles_dst +!! @parm[in] n_snow_layers_src +!! @param[in] n_tiles_src +!! @param[in] ntiles_first Data layout (tiles- or layer-first) +!! @param[in] ndf_dst Number of dofs per cell for field_dst +!! @param[in] undf_dst Total number of dofs per cell for field_dst +!! @param[in] map_dst Cell dofmap for field_dst +!! @param[in] ndf_src Number of dofs per cell for field_src +!! @param[in] undf_src Total number of dofs per cell for field_src +!! @param[in] map_src Cell dofmap for field_src +subroutine lfric2lfric_multidata_snow_code(nlayers, & + field_dst, & + field_src, & + n_snow_layers_dst, & + n_tiles_dst, & + n_snow_layers_src, & + n_tiles_src, & + ntiles_first, & + ndf_dst, & + undf_dst, & + map_dst, & + ndf_src, & + undf_src, & + map_src) + + integer(kind=i_def), intent(in) :: nlayers + + integer(kind=i_def), intent(in) :: ndf_src + integer(kind=i_def), intent(in) :: undf_src + integer(kind=i_def), intent(in) :: map_src(ndf_src) + + integer(kind=i_def), intent(in) :: ndf_dst + integer(kind=i_def), intent(in) :: undf_dst + integer(kind=i_def), intent(in) :: map_dst(ndf_dst) + + integer(kind=i_def), intent(in) :: n_snow_layers_dst, n_tiles_dst + integer(kind=i_def), intent(in) :: n_snow_layers_src, n_tiles_src + + logical(kind=l_def), intent(in) :: ntiles_first + + real(kind=r_def), intent(in) :: field_src(undf_src) + real(kind=r_def), intent(out) :: field_dst(undf_dst) + + integer(kind=i_def) :: df, i_dst, i_src, k + + if (ntiles_first) then + ! Data layout is tiles first: + ! L1T1, L1T2, L1T3, ..., L2T1, L2T2, L2T3, ... + do k = 0, n_snow_layers_dst - 1 + i_dst = map_dst(1) + k * n_tiles_dst + i_src = map_src(1) + k * n_tiles_src + do df = 0, n_tiles_dst -1 + field_dst( i_dst + df ) = field_src( i_src + multidata_map(df+1) -1 ) + end do + end do + + else + ! Data layout is layers first: + ! L1T1, L2T1, ..., L1T2, L2T2, ..., L1T3, L2T3, ... + do df = 0, n_tiles_dst - 1 + i_dst = map_dst(1) + df * n_snow_layers_dst + i_src = map_src(1) + (multidata_map(df+1) - 1) * n_snow_layers_src + do k =0, n_snow_layers_dst - 1 + field_dst( i_dst + k ) = field_src( i_src + k ) + end do + end do + end if + +end subroutine lfric2lfric_multidata_snow_code + +end module lfric2lfric_multidata_snow_kernel_mod From 2430f821a5091db946ddcf9587e29309a26b65b5 Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:29:49 +0100 Subject: [PATCH 51/53] Copy fields if not vertical regrid or multidata --- .../algorithm/lfric2lfric_multidata_mod.x90 | 73 +++++++++++-------- .../source/algorithm/lfric2lfric_vert_mod.x90 | 64 +++++++++++----- .../source/driver/lfric2lfric_driver_mod.F90 | 7 +- 3 files changed, 90 insertions(+), 54 deletions(-) diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 index 2eb6f1a699..0c56fcd9be 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 @@ -65,12 +65,16 @@ contains real(kind=r_def) :: number_snow_layers, dummy character(len=str_def) :: field_name integer(i_def), allocatable :: multidata_map(:) + + logical(kind=l_def), pointer :: tile_change write(log_scratch_space, '(A)') "Starting lfric2lfric_multidata" call log_event(log_scratch_space, log_level_debug) !---- Precalculations + call modeldb%values%get_value("tile_change", tile_change) + !-- Find the number of snow layers in the source data call source_fields%get_field('n_snow_layers', field_src_n_snow_layers) call get_field_minmax(field_src_n_snow_layers, dummy, number_snow_layers) @@ -119,29 +123,30 @@ contains call source_fields%get_field(field_name, field_src) call target_fields%get_field(field_name, field_dst) - ! Continue if it is a 2D mesh field mesh => field_src%get_mesh() + + ! Find the size of the multidata field + fs_type => field_src%get_function_space() + ndata_src = fs_type%get_ndata() + fs_type => field_dst%get_function_space() + ndata_dst = fs_type%get_ndata() + + ! If it is a 2D if (mesh%get_extrusion_id() == TWOD) then - write(log_scratch_space, '(A,A)') "Processing lfric field", & - trim(field_name) - call log_event(log_scratch_space, log_level_debug) - - ! Find the size of the multidata field - fs_type => field_src%get_function_space() - ndata_src = fs_type%get_ndata() - fs_type => field_dst%get_function_space() - ndata_dst = fs_type%get_ndata() - - write(log_scratch_space, '(A,I5)') "ndata_dst ", ndata_dst - call log_event(log_scratch_space, log_level_debug) - write(log_scratch_space, '(A,I5)') "ndata_src ", ndata_src - call log_event(log_scratch_space, log_level_debug) - - ! if multidata field - if ((ndata_dst > 1) .or. (ndata_src > 1)) then - - ! Based on UM rcf_field_calcs + ! If multidata field and multidata regridding (tile_change) is on + if ( ((ndata_src >1) .or. (ndata_dst >1)) .and. & + tile_change ) then + + write(log_scratch_space, '(A,A)') "Multidata Mapping lfric field", & + trim(field_name) + call log_event(log_scratch_space, log_level_debug) + + write(log_scratch_space, '(A,I5)') "ndata_dst ", ndata_dst + call log_event(log_scratch_space, log_level_debug) + write(log_scratch_space, '(A,I5)') "ndata_src ", ndata_src + call log_event(log_scratch_space, log_level_debug) + select case (field_name) ! Surface tiles - based on rcf_calc_tiles, rcf_init_field_on_tiles (L240) @@ -158,12 +163,12 @@ contains 'snow_under_canopy' ) if (n_land_tiles_src /= n_land_tiles_dst) then - ! As the fields might use surface_tiles, only loop over land_tiles + ! As the fields might use surface_tiles, only loop over land_tiles call lfric2lfric_retile_surface_tiles( & - modeldb, field_dst, field_src, n_land_tiles_dst, n_land_tiles_src ) + modeldb, field_dst, field_src, n_land_tiles_dst, n_land_tiles_src ) else - ! Copy field_src to field_dst - but careful if one is n_land tiles and one is n_surface - !... + ! Copy field_src to field_dst - but careful if one is n_land tiles and one is n_surface + !... end if ! Snow Layers and Tiles - based on rcf_ml_snowpack @@ -174,10 +179,10 @@ contains 'snow_layer_rgrain') if ( (n_land_tiles_src /= n_land_tiles_dst) ) then - ! Assume size land_tiles & n_snow - need to check - ! Assume snow layers same - need to check + ! Assume size land_tiles & n_snow - need to check + ! Assume snow layers same - need to check call lfric2lfric_retile_snow( & - modeldb, field_dst, field_src, n_snow_layers_dst, n_land_tiles_dst, n_snow_layers_src, n_land_tiles_src ) + modeldb, field_dst, field_src, n_snow_layers_dst, n_land_tiles_dst, n_snow_layers_src, n_land_tiles_src ) else ! Copy end if @@ -186,11 +191,11 @@ contains case ('sea_ice_temperature') ! Need to check, add error message or copy - ! Sea Ice Categories - sea_ice_thickness based on rcf_derv_ice_cat_thick + ! Sea Ice Categories - sea_ice_thickness based on rcf_derv_ice_cat_thick case ('sea_ice_thickness') ! Need to check, add error message or copy - ! Soil Levels - based on rcf_init_soil_temp + ! Soil Levels - based on rcf_init_soil_temp case ('soil_temperature') ! Need to check, add error message or copy @@ -200,9 +205,15 @@ contains call log_event(log_scratch_space, log_level_error) end select + else - ! Straightforward copy if not multidata ?? - call invoke( setval_X(field_dst, field_src)) + ! copy 2D from src to dst + write(log_scratch_space, '(A,A)') "Copying lfric field ", & + trim(field_name) + call log_event(log_scratch_space, log_level_debug) + + call invoke(setval_X(field_dst, field_src)) + end if end if end do diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 index dbbd966d00..906bbe787d 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -8,8 +8,9 @@ !! meshes. module lfric2lfric_vert_mod - use constants_mod, only: str_def, i_def + use constants_mod, only: str_def, i_def, l_def use driver_modeldb_mod, only: modeldb_type + use extrusion_mod, only: TWOD use field_parent_mod, only: field_parent_type use field_mod, only: field_type use field_collection_mod, only: field_collection_type @@ -57,6 +58,10 @@ contains character(len=str_def) :: field_name integer(kind=i_def) :: fs_src, fs_dst + logical(kind=l_def), pointer :: vertical_change + + call modeldb%values%get_value("vertical_change", vertical_change) + ! Main loop over fields to be processed call iter%initialise(source_fields) do @@ -68,26 +73,45 @@ contains call source_fields%get_field(field_name, field_src) call target_fields%get_field(field_name, field_dst) - write(log_scratch_space, '(A,A)') "Processing lfric field ", & - trim(field_name) - call log_event(log_scratch_space, log_level_info) - mesh_src => field_src%get_mesh() - mesh_dst => field_dst%get_mesh() - fs_src = field_src%which_function_space() - fs_dst = field_dst%which_function_space() - - ! Get the associated heights, ready for vertical interpolation kernels - height_src => get_height_fv(modeldb%config, mesh_src, fs_src) - height_dst => get_height_fv(modeldb%config, mesh_dst, fs_dst) - - ! Dummy initialisation - just writing out the heights - ! TODO Replaced the dummy initialisation with actual - ! vertical regridding from #253. i.e. - ! call invoke( lfric2lfric_vert_lin_interp_lin_extrap_code_r_single( & - ! field_dst, field_src, height_dst, height_src)) - call invoke(setval_X(field_dst, height_dst)) - enddo + + ! Vertical regridding is only for 3D fields + if (mesh_src%get_extrusion_id() /= TWOD) then + + if (vertical_change) then + + ! All 3D fields are regridded in vertical + + write(log_scratch_space, '(A,A)') "Vertical regridding lfric field ", & + trim(field_name) + call log_event(log_scratch_space, log_level_info) + + mesh_src => field_src%get_mesh() + mesh_dst => field_dst%get_mesh() + fs_src = field_src%which_function_space() + fs_dst = field_dst%which_function_space() + + ! Get the associated heights, ready for vertical interpolation kernels + height_src => get_height_fv(modeldb%config, mesh_src, fs_src) + height_dst => get_height_fv(modeldb%config, mesh_dst, fs_dst) + + ! Dummy initialisation - just writing out the heights + ! TODO Replaced the dummy initialisation with actual + ! vertical regridding from #253. i.e. + ! call invoke( lfric2lfric_vert_lin_interp_lin_extrap_code_r_single( & + ! field_dst, field_src, height_dst, height_src)) + call invoke(setval_X(field_dst, height_dst)) + else + + ! All 3D fields are copied from src to dst + write(log_scratch_space, '(A,A)') "Copying lfric field ", & + trim(field_name) + call log_event(log_scratch_space, log_level_info) + + call invoke(setval_X(field_dst, field_src)) + end if + end if + end do end subroutine lfric2lfric_vert diff --git a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 index e254c24988..451fa57c69 100644 --- a/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 +++ b/applications/lfric2lfric/source/driver/lfric2lfric_driver_mod.F90 @@ -36,6 +36,7 @@ module lfric2lfric_driver_mod interm_collection_name use lfric2lfric_regrid_mod, only: lfric2lfric_regrid use lfric2lfric_vert_mod, only: lfric2lfric_vert + use lfric2lfric_copy_mod, only: lfric2lfric_copy use lfric2lfric_multidata_mod, only: lfric2lfric_multidata implicit none @@ -149,10 +150,10 @@ subroutine run( modeldb, oasis_clock ) call lfric2lfric_regrid(modeldb, oasis_clock, source_fields, & interm_fields, regrid_method) end if - if (vertical_change) then + if (vertical_or_tile_change) then + ! 3D fields call lfric2lfric_vert(modeldb, interm_fields, target_fields) - end if - if (tile_change) then + ! 2D fields call lfric2lfric_multidata(modeldb, interm_fields, target_fields) end if From 9086c7a3a30d3ff90cad6188c833432d562a02fb Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:42:49 +0100 Subject: [PATCH 52/53] tidy --- .../algorithm/lfric2lfric_multidata_mod.x90 | 244 +++++++++++------- .../source/algorithm/lfric2lfric_vert_mod.x90 | 13 +- 2 files changed, 156 insertions(+), 101 deletions(-) diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 index 0c56fcd9be..adeeefb147 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 @@ -29,8 +29,8 @@ module lfric2lfric_multidata_mod implicit none - private - public :: lfric2lfric_multidata, lfric2lfric_retile_surface_tiles + private :: lfric2lfric_retile_surface_tiles, lfric2lfric_retile_snow + public :: lfric2lfric_multidata contains @@ -68,84 +68,94 @@ contains logical(kind=l_def), pointer :: tile_change - write(log_scratch_space, '(A)') "Starting lfric2lfric_multidata" - call log_event(log_scratch_space, log_level_debug) + write( log_scratch_space, '(A)') "Starting lfric2lfric_multidata" + call log_event( log_scratch_space, log_level_debug ) - !---- Precalculations + !---- Precalculations and checks - call modeldb%values%get_value("tile_change", tile_change) + ! Determine whether retiling is required for any fields - !-- Find the number of snow layers in the source data - call source_fields%get_field('n_snow_layers', field_src_n_snow_layers) - call get_field_minmax(field_src_n_snow_layers, dummy, number_snow_layers) + call modeldb%values%get_value( "tile_change", tile_change ) + + ! Determine the number of snow layers in the source data + + call source_fields%get_field( 'n_snow_layers', field_src_n_snow_layers ) + call get_field_minmax( field_src_n_snow_layers, dummy, number_snow_layers ) n_snow_layers_src = nint(number_snow_layers) - !-- Determine the number of snow layers in the target data + ! Determine the number of snow layers in the target data ! Assume for now that it is the same as the source data - ! Otherwise this could be added to a rose namelist + ! Otherwise this could be added to a rose namelist or be derived from jules + n_snow_layers_dst = n_snow_layers_src - !-- Determine n_land_tiles_src + ! Determine n_land_tiles_src ! Derive effective number of land tiles in source field from snow fields - call source_fields%get_field('snow_layer_temp', field_src_snow_layer) + + call source_fields%get_field( 'snow_layer_temp', field_src_snow_layer ) + fs_type => field_src_snow_layer%get_function_space() ndata_src = fs_type%get_ndata() n_land_tiles_src = ndata_src / n_snow_layers_src - !-- Determine n_land_tiles_dst + ! Determine n_land_tiles_dst ! Derive effective number of land tiles in destination field from snow fields - call target_fields%get_field('snow_layer_temp', field_dst_snow_layer) + + call target_fields%get_field( 'snow_layer_temp', field_dst_snow_layer ) + fs_type => field_dst_snow_layer%get_function_space() ndata_dst = fs_type%get_ndata() n_land_tiles_dst = ndata_dst / n_snow_layers_dst - !-- Check multidata map + ! Check multidata map + multidata_map = modeldb%config%dst_jules_surface_types%multidata_map() - write(log_scratch_space, '(*(g0,1x))') "multidata ", multidata_map - call log_event(log_scratch_space, log_level_debug) + write( log_scratch_space, '(*(g0,1x))' ) "multidata ", multidata_map + call log_event( log_scratch_space, log_level_debug ) - if ( size(multidata_map) /= n_land_tiles_dst ) then - write(log_scratch_space, '(A,I5,A,I5)') & - "size of multidata map = ", size(multidata_map), & + if ( size( multidata_map ) /= n_land_tiles_dst ) then + write( log_scratch_space, '(A,I5,A,I5)' ) & + "size of multidata map = ", size( multidata_map ), & " not equal to n_land_tiles_dst = ", n_land_tiles_dst - call log_event(log_scratch_space, log_level_error) + call log_event( log_scratch_space, log_level_error ) end if !------ Main loop over fields to be processed - call iter%initialise(source_fields) + call iter%initialise( source_fields ) do ! Locate the field to be processed in the field collections if ( .not. iter%has_next() ) exit field => iter%next() field_name = field%get_name() - call source_fields%get_field(field_name, field_src) - call target_fields%get_field(field_name, field_dst) + call source_fields%get_field( field_name, field_src ) + call target_fields%get_field( field_name, field_dst ) mesh => field_src%get_mesh() - ! Find the size of the multidata field - fs_type => field_src%get_function_space() - ndata_src = fs_type%get_ndata() - fs_type => field_dst%get_function_space() - ndata_dst = fs_type%get_ndata() - - ! If it is a 2D - if (mesh%get_extrusion_id() == TWOD) then + ! Only consider 2D fields + if ( mesh%get_extrusion_id() == TWOD ) then - ! If multidata field and multidata regridding (tile_change) is on - if ( ((ndata_src >1) .or. (ndata_dst >1)) .and. & + ! Find the size of the multidata field + fs_type => field_src%get_function_space() + ndata_src = fs_type%get_ndata() + fs_type => field_dst%get_function_space() + ndata_dst = fs_type%get_ndata() + + ! If multidata field and multidata regridding (tile_change) is true + ! apply field-specific multidata mapping (retiling). + if ( ( ( ndata_src >1 ) .or. ( ndata_dst >1 ) ) .and. & tile_change ) then - write(log_scratch_space, '(A,A)') "Multidata Mapping lfric field", & - trim(field_name) - call log_event(log_scratch_space, log_level_debug) + write( log_scratch_space, '(A,A)' ) "Multidata Mapping lfric field", & + trim( field_name ) + call log_event( log_scratch_space, log_level_debug ) - write(log_scratch_space, '(A,I5)') "ndata_dst ", ndata_dst - call log_event(log_scratch_space, log_level_debug) - write(log_scratch_space, '(A,I5)') "ndata_src ", ndata_src - call log_event(log_scratch_space, log_level_debug) + write( log_scratch_space, '(A,I5)' ) "ndata_dst ", ndata_dst + call log_event( log_scratch_space, log_level_debug ) + write( log_scratch_space, '(A,I5)') "ndata_src ", ndata_src + call log_event( log_scratch_space, log_level_debug ) select case (field_name) @@ -162,14 +172,9 @@ contains 'snowpack_density' , & 'snow_under_canopy' ) - if (n_land_tiles_src /= n_land_tiles_dst) then - ! As the fields might use surface_tiles, only loop over land_tiles - call lfric2lfric_retile_surface_tiles( & - modeldb, field_dst, field_src, n_land_tiles_dst, n_land_tiles_src ) - else - ! Copy field_src to field_dst - but careful if one is n_land tiles and one is n_surface - !... - end if + call lfric2lfric_retile_surface_tiles( & + modeldb, field_dst, field_src, ndata_dst, ndata_src, & + n_land_tiles_dst, n_land_tiles_src ) ! Snow Layers and Tiles - based on rcf_ml_snowpack case ('snow_layer_temp' , & @@ -178,41 +183,30 @@ contains 'snow_layer_liq_mass' , & 'snow_layer_rgrain') - if ( (n_land_tiles_src /= n_land_tiles_dst) ) then - ! Assume size land_tiles & n_snow - need to check - ! Assume snow layers same - need to check - call lfric2lfric_retile_snow( & - modeldb, field_dst, field_src, n_snow_layers_dst, n_land_tiles_dst, n_snow_layers_src, n_land_tiles_src ) - else - ! Copy - end if + call lfric2lfric_retile_snow( & + modeldb, field_dst, field_src, ndata_dst, ndata_src, & + n_snow_layers_dst, n_snow_layers_src, & + n_land_tiles_dst, n_land_tiles_src ) - ! Sea Ice Categories - sea_ice_temperature based on rcf_derv_sea_ice_temp - case ('sea_ice_temperature') - ! Need to check, add error message or copy + case default + write( log_scratch_space, '(A,A)' ) & + trim( field_name ), " needs retiling code to be added" + call log_event( log_scratch_space, log_level_error ) + ! Other possible fields and categories are: + ! Sea Ice Categories - sea_ice_temperature based on rcf_derv_sea_ice_temp ! Sea Ice Categories - sea_ice_thickness based on rcf_derv_ice_cat_thick - case ('sea_ice_thickness') - ! Need to check, add error message or copy - ! Soil Levels - based on rcf_init_soil_temp - case ('soil_temperature') - ! Need to check, add error message or copy - - case default - write(log_scratch_space, '(A,A)') & - trim(field_name), " needs to have code added" - call log_event(log_scratch_space, log_level_error) - end select else - ! copy 2D from src to dst + ! If not a multidata field or multidata mapping is not required then + ! copy from src to dst write(log_scratch_space, '(A,A)') "Copying lfric field ", & trim(field_name) - call log_event(log_scratch_space, log_level_debug) + call log_event( log_scratch_space, log_level_debug) - call invoke(setval_X(field_dst, field_src)) + call invoke( setval_X( field_dst, field_src ) ) end if end if @@ -226,24 +220,53 @@ contains !> @param modeldb Model state object !> @param field_dst Destination multidata field !> @param field_src Source multidata field - !> @param nland_tiles_dst Number of land tiles in destination field - !> @param nland_tiles_src Number of land tiles in source field - subroutine lfric2lfric_retile_surface_tiles( modeldb, field_dst, field_src, n_land_tiles_dst, n_land_tiles_src ) + !> @param n_data_dst Number of multidata levels in destination field + !> @param n_data_src Number of multidata levels in source field + !> @param n_land_tiles_dst Number of land tiles in destination field + !> @param n_land_tiles_src Number of land tiles in source field + subroutine lfric2lfric_retile_surface_tiles( modeldb, field_dst, field_src, & + n_data_dst, n_data_src, & + n_land_tiles_dst, n_land_tiles_src ) implicit none type(modeldb_type), intent(inout) :: modeldb type(field_type), intent(inout) :: field_dst type(field_type), intent(in) :: field_src + integer(kind=i_def), intent(in) :: n_data_dst + integer(kind=i_def), intent(in) :: n_data_src integer(kind=i_def), intent(in) :: n_land_tiles_dst integer(kind=i_def), intent(in) :: n_land_tiles_src - write(log_scratch_space, '(A)') "Starting lfric2lfric_retile_surface_tiles" - call log_event(log_scratch_space, log_level_debug) + write( log_scratch_space, '(A)' ) "Starting lfric2lfric_retile_surface_tiles" + call log_event( log_scratch_space, log_level_debug ) - call invoke( lfric2lfric_multidata_map_surface_type( field_dst, n_land_tiles_dst, & - field_src, n_land_tiles_src)) + if ( ( n_land_tiles_src == n_land_tiles_dst ) .and. & + ( ndata_src /= ndata_dst ) ) then + write( log_scratch_space, '(A)' ) & + "The number of land tiles has not changed but the multidata axis size is different " + call log_event( log_scratch_space, log_level_error ) + end if + if ( ndata_dst < n_land_tiles_dst ) then + write( log_scratch_space, '(A)' ) & + "The number of surface tiles is smaller than the number of land tiles " + call log_event( log_scratch_space, log_level_error ) + end if + + if ( n_land_tiles_src /= n_land_tiles_dst ) then + ! Retile using the multidata map + call invoke( lfric2lfric_multidata_map_surface_type( field_dst, & + n_land_tiles_dst, & + field_src, & + n_land_tiles_src ) ) + + else + ! Copy + call invoke( setval_X( field_dst, field_src ) ) + + end if + end subroutine lfric2lfric_retile_surface_tiles !> @brief Retile a field with snow_layers_and_tiles @@ -251,12 +274,16 @@ contains !> @param modeldb Model state object !> @param field_dst Destination multidata field !> @param field_src Source multidata field + !> @param n_data_dst Number of multidata levels in destination field + !> @param n_data_src Number of multidata levels in source field !> @param n_snow_layers_dst Source number of snow layers in destination - !> @param n_tiles_dst Source number of land tiles in destination !> @param n_snow_layers_src Source number of snow layers in source + !> @param n_tiles_dst Source number of land tiles in destination !> @param n_tiles_src Source number of land tiles in source - subroutine lfric2lfric_retile_snow( modeldb, field_dst, field_src, & - n_snow_layers_dst, n_tiles_dst, n_snow_layers_src, n_tiles_src ) + subroutine lfric2lfric_retile_snow( modeldb, field_dst, field_src, & + ndata_dst, ndata_src, & + n_snow_layers_dst, n_snow_layers_src, & + n_tiles_dst, n_tiles_src ) implicit none @@ -264,22 +291,49 @@ contains type(field_type), intent(inout) :: field_dst type(field_type), intent(in) :: field_src integer(kind=i_def), intent(in) :: n_snow_layers_dst - integer(kind=i_def), intent(in) :: n_tiles_dst integer(kind=i_def), intent(in) :: n_snow_layers_src + integer(kind=i_def), intent(in) :: n_tiles_dst integer(kind=i_def), intent(in) :: n_tiles_src + integer(kind=i_def), intent(in) :: ndata_dst + integer(kind=i_def), intent(in) :: ndata_src logical(l_def), parameter :: ndata_first = .false. - write(log_scratch_space, '(A)') "Starting lfric2lfric_retile_snow" - call log_event(log_scratch_space, log_level_debug) + write( log_scratch_space, '(A)' ) "Starting lfric2lfric_retile_snow" + call log_event( log_scratch_space, log_level_debug ) + + ! Assume size land_tiles * n_snow = number snow layers and tiles + if ( n_snow_layers_dst * n_tiles_dst /= ndata_dst ) then + write( log_scratch_space, '(A)' ) & + "The number of snow layers x number of tiles is not equal to the number of snow_layers_tiles in the destination " + call log_event( log_scratch_space, log_level_error ) + end if + if ( n_snow_layers_src * n_tiles_src /= ndata_src ) then + write( log_scratch_space, '(A)' ) & + "The number of snow layers x number of tiles is not equal to the number of snow_layers_tiles in the source " + call log_event( log_scratch_space, log_level_error ) + end if + + ! Assume snow layers same in source and destination + if ( n_snow_layers_src /= n_snow_layers_dst ) then + write( log_scratch_space, '(A)' ) & + "The number of snow layers in the destination is not the same as the source " + call log_event( log_scratch_space, log_level_error ) + end if - call invoke( lfric2lfric_multidata_snow_type( field_dst, & - field_src, & - n_snow_layers_dst, & - n_tiles_dst, & - n_snow_layers_src, & - n_tiles_src, & - ndata_first )) + if ( ( n_land_tiles_src /= n_land_tiles_dst ) ) then + ! Retile + call invoke( lfric2lfric_multidata_snow_type( field_dst, & + field_src, & + n_snow_layers_dst, & + n_tiles_dst, & + n_snow_layers_src, & + n_tiles_src, & + ndata_first ) ) + else + ! Copy + call invoke( setval_X( field_dst, field_src ) ) + end if end subroutine lfric2lfric_retile_snow diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 index 906bbe787d..ba0fe033b2 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -21,6 +21,7 @@ module lfric2lfric_vert_mod use mesh_mod, only: mesh_type use log_mod, only: log_event, & log_level_info, & + log_level_debug log_scratch_space implicit none @@ -75,21 +76,21 @@ contains mesh_src => field_src%get_mesh() - ! Vertical regridding is only for 3D fields + ! Only consider 3D fields if (mesh_src%get_extrusion_id() /= TWOD) then if (vertical_change) then - ! All 3D fields are regridded in vertical + ! All 3D fields are regridded in vertical if vertical_change is true write(log_scratch_space, '(A,A)') "Vertical regridding lfric field ", & trim(field_name) - call log_event(log_scratch_space, log_level_info) + call log_event(log_scratch_space, log_level_debug) mesh_src => field_src%get_mesh() mesh_dst => field_dst%get_mesh() fs_src = field_src%which_function_space() - fs_dst = field_dst%which_function_space() + fs_dst = field_dst%which_function_space() ! Get the associated heights, ready for vertical interpolation kernels height_src => get_height_fv(modeldb%config, mesh_src, fs_src) @@ -103,10 +104,10 @@ contains call invoke(setval_X(field_dst, height_dst)) else - ! All 3D fields are copied from src to dst + ! All 3D fields are copied from src to dst if vertical change is false write(log_scratch_space, '(A,A)') "Copying lfric field ", & trim(field_name) - call log_event(log_scratch_space, log_level_info) + call log_event(log_scratch_space, log_level_debug) call invoke(setval_X(field_dst, field_src)) end if From 84711238f1d2c7e58a55e12c911208e022bdbb8f Mon Sep 17 00:00:00 2001 From: Christine Johnson <74597224+cjohnson-pi@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:40:09 +0100 Subject: [PATCH 53/53] Loop surface fields over surface fields --- .../lfric2lfric/example/configuration.nml | 2 +- .../algorithm/lfric2lfric_multidata_mod.x90 | 48 +++++++------------ .../source/algorithm/lfric2lfric_vert_mod.x90 | 6 +-- 3 files changed, 22 insertions(+), 34 deletions(-) diff --git a/applications/lfric2lfric/example/configuration.nml b/applications/lfric2lfric/example/configuration.nml index 407f6555d0..d44ca96dff 100644 --- a/applications/lfric2lfric/example/configuration.nml +++ b/applications/lfric2lfric/example/configuration.nml @@ -113,5 +113,5 @@ coord_space = 'Wchi', &dst_jules_surface_types ! https://github.com/MetOffice/um/blob/main/rose-stem/app/um_seukv_eg/opt/rose-app-reconukv.conf - multidata_map = 1,2,3,4,5,6,6,7,8,9 + multidata_map = 1,2,3,4,5,6,6,7,8,9,10 / diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 index adeeefb147..145bb8c729 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_multidata_mod.x90 @@ -54,12 +54,14 @@ contains type(field_type), pointer :: field_src type(field_type), pointer :: field_dst type(field_type), pointer :: field_src_n_snow_layers + type(field_type), pointer :: field_dst_n_snow_layers type(field_type), pointer :: field_src_snow_layer type(field_type), pointer :: field_dst_snow_layer type(mesh_type), pointer :: mesh type(function_space_type), pointer :: fs_type integer(kind=i_def) :: ndata_dst, ndata_src + integer(kind=i_def) :: n_surface_tiles_dst integer(kind=i_def) :: n_snow_layers_src, n_snow_layers_dst integer(kind=i_def) :: n_land_tiles_src, n_land_tiles_dst real(kind=r_def) :: number_snow_layers, dummy @@ -89,6 +91,12 @@ contains n_snow_layers_dst = n_snow_layers_src + ! Determine the number of surface tiles + + call source_fields%get_field( 'n_snow_layers', field_dst_n_snow_layers ) + fs_type => field_dst_n_snow_layers%get_function_space() + n_surface_tiles_dst = fs_type%get_ndata() + ! Determine n_land_tiles_src ! Derive effective number of land tiles in source field from snow fields @@ -114,10 +122,10 @@ contains write( log_scratch_space, '(*(g0,1x))' ) "multidata ", multidata_map call log_event( log_scratch_space, log_level_debug ) - if ( size( multidata_map ) /= n_land_tiles_dst ) then + if ( size( multidata_map ) /= n_surface_tiles_dst ) then write( log_scratch_space, '(A,I5,A,I5)' ) & "size of multidata map = ", size( multidata_map ), & - " not equal to n_land_tiles_dst = ", n_land_tiles_dst + " not equal to n_surface_tiles_dst = ", n_surface_tiles_dst call log_event( log_scratch_space, log_level_error ) end if @@ -173,8 +181,7 @@ contains 'snow_under_canopy' ) call lfric2lfric_retile_surface_tiles( & - modeldb, field_dst, field_src, ndata_dst, ndata_src, & - n_land_tiles_dst, n_land_tiles_src ) + modeldb, field_dst, field_src, ndata_dst, ndata_src ) ! Snow Layers and Tiles - based on rcf_ml_snowpack case ('snow_layer_temp' , & @@ -222,11 +229,8 @@ contains !> @param field_src Source multidata field !> @param n_data_dst Number of multidata levels in destination field !> @param n_data_src Number of multidata levels in source field - !> @param n_land_tiles_dst Number of land tiles in destination field - !> @param n_land_tiles_src Number of land tiles in source field subroutine lfric2lfric_retile_surface_tiles( modeldb, field_dst, field_src, & - n_data_dst, n_data_src, & - n_land_tiles_dst, n_land_tiles_src ) + n_data_dst, n_data_src ) implicit none @@ -235,32 +239,16 @@ contains type(field_type), intent(in) :: field_src integer(kind=i_def), intent(in) :: n_data_dst integer(kind=i_def), intent(in) :: n_data_src - integer(kind=i_def), intent(in) :: n_land_tiles_dst - integer(kind=i_def), intent(in) :: n_land_tiles_src write( log_scratch_space, '(A)' ) "Starting lfric2lfric_retile_surface_tiles" call log_event( log_scratch_space, log_level_debug ) - if ( ( n_land_tiles_src == n_land_tiles_dst ) .and. & - ( ndata_src /= ndata_dst ) ) then - write( log_scratch_space, '(A)' ) & - "The number of land tiles has not changed but the multidata axis size is different " - call log_event( log_scratch_space, log_level_error ) - end if - - if ( ndata_dst < n_land_tiles_dst ) then - write( log_scratch_space, '(A)' ) & - "The number of surface tiles is smaller than the number of land tiles " - call log_event( log_scratch_space, log_level_error ) - end if - - if ( n_land_tiles_src /= n_land_tiles_dst ) then + if ( n_data_src /= n_data_dst ) then ! Retile using the multidata map - call invoke( lfric2lfric_multidata_map_surface_type( field_dst, & - n_land_tiles_dst, & - field_src, & - n_land_tiles_src ) ) - + call invoke( lfric2lfric_multidata_map_surface_type( field_dst, & + n_data_dst, & + field_src, & + n_data_src ) ) else ! Copy call invoke( setval_X( field_dst, field_src ) ) @@ -321,7 +309,7 @@ contains call log_event( log_scratch_space, log_level_error ) end if - if ( ( n_land_tiles_src /= n_land_tiles_dst ) ) then + if ( ( n_tiles_src /= n_tiles_dst ) ) then ! Retile call invoke( lfric2lfric_multidata_snow_type( field_dst, & field_src, & diff --git a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 index ba0fe033b2..a4aec1f976 100644 --- a/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 +++ b/applications/lfric2lfric/source/algorithm/lfric2lfric_vert_mod.x90 @@ -19,9 +19,9 @@ module lfric2lfric_vert_mod use sci_geometric_constants_mod, & only: get_height_fv use mesh_mod, only: mesh_type - use log_mod, only: log_event, & - log_level_info, & - log_level_debug + use log_mod, only: log_event, & + log_level_info, & + log_level_debug, & log_scratch_space implicit none