From e94d80ebf789e9e647f40e1242acb9d5e48f4249 Mon Sep 17 00:00:00 2001 From: Ricky Wong <141156427+mo-rickywong@users.noreply.github.com> Date: Wed, 19 Aug 2026 14:19:57 +0100 Subject: [PATCH 1/6] Commit branch that seems to work --- components/driver/source/driver_fem_mod.f90 | 26 ++- components/driver/source/driver_mesh_mod.f90 | 17 +- .../driver/source/mesh/add_mesh_map_mod.f90 | 74 ++++---- .../source/mesh/load_global_mesh_mod.f90 | 46 ++++- .../source/mesh/load_local_mesh_mod.f90 | 8 +- .../source/mesh/runtime_partition_mod.f90 | 158 ++++++++++++++++-- .../source/lfric_xios_setup_mod.x90 | 105 +++++++----- .../algorithm/sci_mapping_constants_mod.x90 | 20 ++- infrastructure/source/field/field_mod.t90 | 6 +- .../function_space_collection_mod.F90 | 17 +- .../function_space/function_space_mod.F90 | 9 +- infrastructure/source/io/ugrid_2d_mod.F90 | 33 +++- .../source/mesh/global_mesh_mod.F90 | 48 +++++- .../source/mesh/local_mesh_collection_mod.f90 | 16 ++ infrastructure/source/mesh/local_mesh_mod.f90 | 48 +++++- infrastructure/source/mesh/mesh_mod.F90 | 4 +- .../source/mesh/panel_decomposition_mod.f90 | 81 +++++++-- .../source/mesh/ugrid_mesh_data_mod.f90 | 20 ++- .../support/generate_local_objects_mod.f90 | 2 +- 19 files changed, 559 insertions(+), 179 deletions(-) diff --git a/components/driver/source/driver_fem_mod.f90 b/components/driver/source/driver_fem_mod.f90 index 8d2bfe5e4..99d39fe52 100644 --- a/components/driver/source/driver_fem_mod.f90 +++ b/components/driver/source/driver_fem_mod.f90 @@ -107,10 +107,27 @@ subroutine init_fem(config, chi_inventory, panel_id_inventory) ! To loop through mesh collection, get all mesh names ! Then get mesh from collection using these names all_mesh_names = mesh_collection%get_mesh_names() - - call chi_inventory%initialise(name="chi", table_len=size(all_mesh_names)) - call panel_id_inventory%initialise(name="panel_id", & - table_len=size(all_mesh_names)) +!!$ +!!$ if (prime_mesh_name == cmdi) then +!!$ mesh => mesh_collection%get_mesh(all_mesh_names(1)) +!!$ else +!!$ mesh => mesh_collection%get_mesh(prime_mesh_name) +!!$ end if +!!$ +!!$ if (mesh%is_geometry_planar()) then +!!$ geometry = geometry_planar +!!$ else if (mesh%is_geometry_spherical()) then +!!$ geometry = geometry_spherical +!!$ end if +!!$ +!!$ if (mesh%is_topology_periodic()) then +!!$ topology = topology_fully_periodic +!!$ else if (mesh%is_topology_non_periodic()) then +!!$ topology = topology_non_periodic +!!$ end if +!!$ +!!$ call init_chi_transforms( geometry, topology, & +!!$ mesh_collection=mesh_collection ) ! ======================================================================== ! ! Loop through all 3D meshes @@ -133,7 +150,6 @@ subroutine init_fem(config, chi_inventory, panel_id_inventory) topology = topology_non_periodic end if - ! Initialise coordinate transformations call init_chi_transforms( geometry, topology, & mesh_collection=mesh_collection ) diff --git a/components/driver/source/driver_mesh_mod.f90 b/components/driver/source/driver_mesh_mod.f90 index 40157459a..237a0831e 100644 --- a/components/driver/source/driver_mesh_mod.f90 +++ b/components/driver/source/driver_mesh_mod.f90 @@ -40,7 +40,8 @@ module driver_mesh_mod log_scratch_space, & log_level_debug, & log_level_error - use panel_decomposition_mod, only: panel_decomposition_type + use panel_decomposition_mod, only: panel_decomposition_type, & + calc_mapping_factor use partition_mod, only: partitioner_interface use runtime_partition_lfric_mod, only: get_partition_parameters @@ -138,6 +139,9 @@ subroutine init_mesh( config, & character(str_def), allocatable :: tmp_mesh_names(:) character(str_max_filename) :: input_mesh_file integer(i_def), allocatable :: stencil_depths(:) + integer(i_def), allocatable :: mapping_factors(:) + + type(global_mesh_type), pointer :: global_mesh procedure(partitioner_interface), pointer :: partitioner_ptr @@ -147,6 +151,9 @@ subroutine init_mesh( config, & integer(i_def) :: i, n_digit + nullify(global_mesh) + nullify(partitioner_ptr) + !============================================================================ ! Extract configuration variables !============================================================================ @@ -314,6 +321,13 @@ subroutine init_mesh( config, & !=========================================================== call check_global_mesh( config, mesh_names ) + allocate(mapping_factors(size(mesh_names))) + do i=1, size(mesh_names) + global_mesh => global_mesh_collection%get_global_mesh(mesh_names(i)) + mapping_factors(i) = calc_mapping_factor(global_mesh, & + global_mesh_collection) + end do + ! 2.2e Partition the global meshes !=========================================================== call create_local_mesh( mesh_names, & @@ -322,6 +336,7 @@ subroutine init_mesh( config, & stencil_depths, & generate_inner_halos, & partitioner_ptr, & + mapping_factors, & enforce_constraints=check_partitions ) diff --git a/components/driver/source/mesh/add_mesh_map_mod.f90 b/components/driver/source/mesh/add_mesh_map_mod.f90 index b5e275a30..7b00b2d34 100644 --- a/components/driver/source/mesh/add_mesh_map_mod.f90 +++ b/components/driver/source/mesh/add_mesh_map_mod.f90 @@ -24,14 +24,11 @@ module add_mesh_map_mod geometric_extrusion_type, & quadratic_extrusion_type use local_mesh_mod, only: local_mesh_type + use mesh_collection_mod, only: mesh_collection use mesh_mod, only: mesh_type use sci_query_mod, only: check_lbc use ugrid_mesh_data_mod, only: ugrid_mesh_data_type - - use local_mesh_collection_mod, only: local_mesh_collection - use mesh_collection_mod, only: mesh_collection - implicit none private @@ -54,11 +51,16 @@ subroutine assign_mesh_maps( mesh_names ) character(str_def), allocatable :: target_mesh_names(:) character(str_def), allocatable :: local_mesh_names(:) - type(mesh_type), pointer :: mesh => null() - type(local_mesh_type), pointer :: local_mesh => null() + type(mesh_type), pointer :: mesh + type(local_mesh_type), pointer :: local_mesh + + type(mesh_type), pointer :: mesh_A + type(mesh_type), pointer :: mesh_B integer(i_def) :: i, j, k + nullify( mesh, mesh_A, mesh_B, local_mesh ) + if (size(mesh_names) > 1) then !============================================================================ @@ -122,7 +124,10 @@ subroutine assign_mesh_maps( mesh_names ) end do if (mesh_name_B /= cmdi) then - call add_mesh_map( mesh_name_A, mesh_name_B ) + mesh_A => mesh_collection%get_mesh(mesh_name_A) + mesh_B => mesh_collection%get_mesh(mesh_name_B) +! call add_mesh_map( mesh_name_A, mesh_name_B ) + call add_mesh_map( mesh_A, mesh_B ) end if end do @@ -141,50 +146,29 @@ end subroutine assign_mesh_maps !! application mesh collection. !> @param[in] target_mesh_name Name of source_mesh in the !! application mesh collection -subroutine add_mesh_map( source_mesh_name, & - target_mesh_name ) +subroutine add_mesh_map( source_mesh, target_mesh ) implicit none - character(len=str_def), intent(in) :: source_mesh_name - character(len=str_def), intent(in) :: target_mesh_name - - type(mesh_type), pointer :: source_mesh => null() - type(mesh_type), pointer :: target_mesh => null() - - - source_mesh => mesh_collection % get_mesh( source_mesh_name ) - target_mesh => mesh_collection % get_mesh( target_mesh_name ) - - if ( associated(source_mesh) .and. & - associated(target_mesh) ) then - - ! Mesh tag names may be different but "could point to the same mesh - ! So check the IDs are not the same - if (source_mesh%get_id() == target_mesh%get_id()) then - write(log_scratch_space,'(A)') & - 'Unable to create intergrid map: Source('// & - trim(source_mesh_name)//' and target('// & - trim(target_mesh_name)//') mesh IDs are the same' - call log_event( log_scratch_space, LOG_LEVEL_ERROR ) - end if - - call source_mesh % add_mesh_map (target_mesh) - write(log_scratch_space,'(A,I0,A)') & - 'Adding intergrid map "'// & - trim(source_mesh_name)//'"-->"'// & - trim(target_mesh_name)//'"' - call log_event( log_scratch_space, LOG_LEVEL_INFO ) - else - write(log_scratch_space,'(A,I0,A)') & - 'Unable to create mesh map between "'// & - trim(source_mesh_name)//'"-"'// & - trim(target_mesh_name)//'"' + type(mesh_type), intent(inout) :: source_mesh + type(mesh_type), intent(inout) :: target_mesh + + ! Mesh tag names may be different but "could point to the same mesh + ! So check the IDs are not the same + if (source_mesh%get_id() == target_mesh%get_id()) then + write(log_scratch_space,'(A)') & + 'Unable to create intergrid map: Source('// & + trim(source_mesh%get_mesh_name())//' and target('// & + trim(target_mesh%get_mesh_name())//') mesh IDs are the same' call log_event( log_scratch_space, LOG_LEVEL_ERROR ) end if - nullify(source_mesh) - nullify(target_mesh) + call source_mesh % add_mesh_map (target_mesh) + write(log_scratch_space,'(A,I0,A)') & + 'Adding intergrid map "'// & + trim(source_mesh%get_mesh_name())//'"-->"'// & + trim(target_mesh%get_mesh_name())//'"' + call log_event( log_scratch_space, LOG_LEVEL_INFO ) return end subroutine add_mesh_map diff --git a/components/driver/source/mesh/load_global_mesh_mod.f90 b/components/driver/source/mesh/load_global_mesh_mod.f90 index 074b27e54..7ece9ddfc 100644 --- a/components/driver/source/mesh/load_global_mesh_mod.f90 +++ b/components/driver/source/mesh/load_global_mesh_mod.f90 @@ -14,8 +14,8 @@ module load_global_mesh_mod LOG_LEVEL_INFO use ugrid_mesh_data_mod, only: ugrid_mesh_data_type - - use global_mesh_collection_mod, only: global_mesh_collection + use global_mesh_collection_mod, only: global_mesh_collection_type, & + global_mesh_collection implicit none @@ -37,18 +37,34 @@ module load_global_mesh_mod !> @param[in] mesh_names The names of the global meshes to load !> from the . subroutine load_global_mesh_multiple( input_mesh_file, & - mesh_names ) + mesh_names, & + rename_to ) + implicit none character(str_max_filename), intent(in) :: input_mesh_file character(str_def), intent(in) :: mesh_names(:) + character(str_def), optional :: rename_to(:) + + character(str_def), allocatable :: names(:) + integer(i_def) :: i + + allocate(names, source=mesh_names) + + if ( present(rename_to) ) then + if (size(rename_to) == size(mesh_names)) then + deallocate(names) + allocate(names, source=rename_to) + end if + end if + do i=1, size(mesh_names) call load_global_mesh_single( input_mesh_file, & - mesh_names(i) ) + mesh_names(i), rename_to=names(i) ) end do end subroutine load_global_mesh_multiple @@ -61,17 +77,29 @@ end subroutine load_global_mesh_multiple !> @param[in] mesh_name The name of the global mesh to load !> from the . subroutine load_global_mesh_single( input_mesh_file, & - mesh_name ) + mesh_name, rename_to ) implicit none - character(str_max_filename), intent(in) :: input_mesh_file - character(str_def), intent(in) :: mesh_name + character(*), intent(in) :: input_mesh_file + character(*), intent(in) :: mesh_name + + character(*), optional, intent(in) :: rename_to + type(ugrid_mesh_data_type) :: ugrid_mesh_data type(global_mesh_type) :: global_mesh - if (.not. global_mesh_collection%check_for(mesh_name)) then + character(str_def) :: name + + + if ( present(rename_to) ) then + name=rename_to + else + name=mesh_name + end if + + if (.not. global_mesh_collection%check_for(name)) then write(log_scratch_space,'(A)') & 'Reading global mesh: "'//trim(mesh_name)//'"' @@ -81,7 +109,7 @@ subroutine load_global_mesh_single( input_mesh_file, & call ugrid_mesh_data%read_from_file( trim(input_mesh_file), & mesh_name ) - global_mesh = global_mesh_type( ugrid_mesh_data ) + global_mesh = global_mesh_type( ugrid_mesh_data, rename_to=name ) call ugrid_mesh_data%clear() call global_mesh_collection%add_new_global_mesh ( global_mesh ) diff --git a/components/driver/source/mesh/load_local_mesh_mod.f90 b/components/driver/source/mesh/load_local_mesh_mod.f90 index 2488e7ce3..ae0d2a6f2 100644 --- a/components/driver/source/mesh/load_local_mesh_mod.f90 +++ b/components/driver/source/mesh/load_local_mesh_mod.f90 @@ -36,8 +36,7 @@ module load_local_mesh_mod !> populate objects. !> @param[in] mesh_names The names of the local mesh data to !> load from the . -subroutine load_local_mesh_multiple( input_mesh_file, & - mesh_names ) +subroutine load_local_mesh_multiple( input_mesh_file, mesh_names ) implicit none character(str_max_filename), intent(in) :: input_mesh_file @@ -46,7 +45,7 @@ subroutine load_local_mesh_multiple( input_mesh_file, & integer(i_def) :: i do i=1, size(mesh_names) - call load_local_mesh_single( input_mesh_file, mesh_names(i) ) + call load_local_mesh_single( input_mesh_file, mesh_names(i)) end do end subroutine load_local_mesh_multiple @@ -58,8 +57,7 @@ end subroutine load_local_mesh_multiple !> populate objects. !> @param[in] mesh_name The name of the local mesh data to !> load from the . -subroutine load_local_mesh_single( input_mesh_file, & - mesh_name ) +subroutine load_local_mesh_single( input_mesh_file, mesh_name ) implicit none diff --git a/components/driver/source/mesh/runtime_partition_mod.f90 b/components/driver/source/mesh/runtime_partition_mod.f90 index aa849c9a8..35c71daf2 100644 --- a/components/driver/source/mesh/runtime_partition_mod.f90 +++ b/components/driver/source/mesh/runtime_partition_mod.f90 @@ -12,6 +12,7 @@ module runtime_partition_mod use global_mesh_mod, only: global_mesh_type use log_mod, only: log_event, & log_scratch_space, & + log_level_info, & log_level_error, & log_level_debug use local_mesh_mod, only: local_mesh_type @@ -22,12 +23,12 @@ module runtime_partition_mod partitioner_cubedsphere, & partitioner_planar - use panel_decomposition_mod, only: panel_decomposition_type, & - calc_mapping_factor + use panel_decomposition_mod, only: panel_decomposition_type!, & +! calc_mapping_factor use sci_query_mod, only: is_lbc - use local_mesh_collection_mod, only: local_mesh_collection - use global_mesh_collection_mod, only: global_mesh_collection + use local_mesh_collection_mod, only: local_mesh_collection + use global_mesh_collection_mod, only: global_mesh_collection implicit none @@ -36,6 +37,11 @@ module runtime_partition_mod public :: create_local_mesh public :: create_local_mesh_maps + interface create_local_mesh_maps + module procedure create_local_mesh_maps_king + module procedure create_local_mesh_maps_kong + end interface create_local_mesh_maps + integer, public, parameter :: mesh_cubedsphere = 34 integer, public, parameter :: mesh_planar = 28 @@ -122,8 +128,8 @@ subroutine create_local_mesh( mesh_names, & stencil_depths, & generate_inner_halos, & partitioner_ptr, & + mapping_factors, & enforce_constraints ) - implicit none character(len=str_def), intent(in) :: mesh_names(:) @@ -136,6 +142,8 @@ subroutine create_local_mesh( mesh_names, & logical(l_def), intent(in) :: generate_inner_halos + integer(i_def), intent(in) :: mapping_factors(:) + logical(l_def), intent(in), optional :: enforce_constraints procedure(partitioner_interface), intent(in), pointer :: partitioner_ptr @@ -145,7 +153,6 @@ subroutine create_local_mesh( mesh_names, & type(local_mesh_type) :: local_mesh integer(i_def) :: local_mesh_id, i - integer(i_def) :: mapping_factor logical(l_def) :: enforce_constraints_choice @@ -159,8 +166,6 @@ subroutine create_local_mesh( mesh_names, & global_mesh_ptr => global_mesh_collection%get_global_mesh( mesh_names(i) ) - mapping_factor = calc_mapping_factor( global_mesh_collection, global_mesh_ptr ) - ! Create partition partition = partition_type( global_mesh_ptr, & partitioner_ptr, & @@ -170,7 +175,7 @@ subroutine create_local_mesh( mesh_names, & enforce_constraints_choice, & local_rank, & total_ranks, & - mapping_factor ) + mapping_factors(i) ) ! Create local_mesh call local_mesh%initialise( global_mesh_ptr, partition ) @@ -198,11 +203,11 @@ end subroutine create_local_mesh !! mesh object. !! !> @param[in] input_mesh_file Input file to load mesh maps from. -subroutine create_local_mesh_maps( input_mesh_file ) +subroutine create_local_mesh_maps_king( input_mesh_file ) implicit none - character(len=str_max_filename) :: input_mesh_file + character(len=str_max_filename), intent(in) :: input_mesh_file type(ncdf_quad_type) :: file_handler @@ -214,15 +219,18 @@ subroutine create_local_mesh_maps( input_mesh_file ) integer(i_def) :: i, j, n, x, y integer(i_def) :: n_meshes - type(global_mesh_type), pointer :: source_global_mesh => null() + type(global_mesh_type), pointer :: source_global_mesh - type(local_mesh_type), pointer :: source_local_mesh => null() - type(local_mesh_type), pointer :: target_local_mesh => null() + type(local_mesh_type), pointer :: source_local_mesh + type(local_mesh_type), pointer :: target_local_mesh integer(i_def) :: ntarget_per_source_cell_x, ntarget_per_source_cell_y integer(i_def) :: ncells integer(i_def) :: target_local_mesh_id + nullify(source_local_mesh, source_global_mesh) + nullify(target_local_mesh) + ! Read in the maps for each global mesh !================================================================= call file_handler%file_open(trim(input_mesh_file)) @@ -299,6 +307,126 @@ subroutine create_local_mesh_maps( input_mesh_file ) call file_handler%file_close() return -end subroutine create_local_mesh_maps +end subroutine create_local_mesh_maps_king + + + +subroutine create_local_mesh_maps_kong( source_local_mesh ) + + + implicit none + + type(local_mesh_type), intent(inout) :: source_local_mesh + + + type(ncdf_quad_type) :: file_handler + + integer(i_def), allocatable :: gid_mesh_map(:,:,:) + integer(i_def), allocatable :: lid_mesh_map(:,:,:) + + integer(i_def) :: i, j, n, x, y + integer(i_def) :: n_meshes + + type(global_mesh_type), pointer :: source_global_mesh + + type(local_mesh_type), pointer :: target_local_mesh + + integer(i_def) :: ntarget_per_source_cell_x, ntarget_per_source_cell_y + integer(i_def) :: ncells + integer(i_def) :: target_local_mesh_id, n_targets + + character(str_def), allocatable :: target_names(:) + + character(str_def), allocatable :: all_mesh_names(:) + character(str_def) :: mesh_name + + character(str_max_filename) :: origin_file, target_origin_file + character(str_def) :: origin_name, target_origin_name + + nullify(source_global_mesh) + nullify(target_local_mesh) + + + ! Written assume mesh maps are read from input files of non-partitioned meshes + allocate( all_mesh_names, & + source=local_mesh_collection%get_mesh_names() ) + + mesh_name = source_local_mesh%get_mesh_name() + origin_name = source_local_mesh%get_origin_name() + origin_file = source_local_mesh%get_origin_file() + + source_global_mesh => global_mesh_collection%get_global_mesh( mesh_name ) + call source_global_mesh%get_target_mesh_names(target_names) + + ! Read in the maps for each global mesh + !================================================================= + + if (allocated(target_names)) then + + call file_handler%file_open(trim(origin_file)) + + ! Loop over each mesh in collection to check if the specific + ! origin_file & origin_name of the target mesh has been loaded. + n_meshes = local_mesh_collection%n_meshes() + n_targets = size(target_names) + + do j=1, n_targets + do i=1, n_meshes + + target_local_mesh => local_mesh_collection%get_local_mesh(all_mesh_names(i)) + + if ( associated(target_local_mesh) ) then + + target_origin_file = target_local_mesh%get_origin_file() + target_origin_name = target_local_mesh%get_origin_name() + + if ( (trim(origin_file) == trim(target_origin_file)) .and. & + (trim(target_names(j)) == trim(target_origin_name)) ) then + + ! Read in the global mesh map + call file_handler%read_map( origin_name, & + target_origin_name, & + gid_mesh_map ) + + ! Create the local mesh map + ntarget_per_source_cell_x = size(gid_mesh_map, 1) + ntarget_per_source_cell_y = size(gid_mesh_map, 2) + ncells = source_local_mesh%get_num_cells_in_layer() + allocate( lid_mesh_map( ntarget_per_source_cell_x, & + ntarget_per_source_cell_y, & + ncells ) ) + + ! Convert global cell IDs in the global mesh map + ! into local cell IDs in a local mesh map + do x=1, ntarget_per_source_cell_x + do y=1, ntarget_per_source_cell_y + do n=1, ncells + lid_mesh_map(x, y, n) = target_local_mesh%get_lid_from_gid( & + gid_mesh_map(x, y, source_local_mesh%get_gid_from_lid(n)) ) + end do + end do + end do + + ! Put the local mesh map in the local mesh + target_local_mesh_id = target_local_mesh%get_id() + call source_local_mesh%add_local_mesh_map( target_local_mesh_id, & + lid_mesh_map ) + + if ( allocated(gid_mesh_map) ) deallocate( gid_mesh_map ) + if ( allocated(lid_mesh_map) ) deallocate( lid_mesh_map ) + + end if ! Checking if this is the correct target mesh + end if ! The pointer is associated + + end do ! loop over local meshes in collection + + end do ! Loop over the numner of targets listed by the source mesh + + call file_handler%file_close() + + end if ! test if the source has any targets listed + + return +end subroutine create_local_mesh_maps_kong end module runtime_partition_mod diff --git a/components/lfric-xios/source/lfric_xios_setup_mod.x90 b/components/lfric-xios/source/lfric_xios_setup_mod.x90 index 0e924dd32..d578f2321 100644 --- a/components/lfric-xios/source/lfric_xios_setup_mod.x90 +++ b/components/lfric-xios/source/lfric_xios_setup_mod.x90 @@ -92,7 +92,8 @@ contains !> !> @param [in] model_clock The model clock !> @param [in] calendar The model calendar - subroutine init_xios_calendar( model_clock, calendar, start_at_zero, context_clock_step ) + subroutine init_xios_calendar( model_clock, calendar, & + start_at_zero, context_clock_step ) implicit none @@ -185,7 +186,11 @@ contains type(field_type), optional, intent(in) :: alt_panel_ids(:) integer(i_def) :: i - type(mesh_type), pointer :: mesh => null() + + type(mesh_type), pointer :: mesh + type(function_space_type), pointer :: w0_domain_fs + type(function_space_type), pointer :: w3_domain_fs + ! Initialise XIOS prime mesh call init_xios_mesh( chi, panel_id, geometry, topology, & @@ -203,9 +208,12 @@ contains ! Initialise XIOS axes mesh => chi(1)%get_mesh() - call init_xios_axis( "vert_axis_full_levels", mesh, W0 ) - call init_xios_axis( "vert_axis_half_levels", mesh, W3 ) - call init_xios_axis( "radiation_levels", mesh, W0 ) + w0_domain_fs => function_space_collection%get_fs(mesh, 0, 0, W0) + w3_domain_fs => function_space_collection%get_fs(mesh, 0, 0, W3) + + call init_xios_axis( "vert_axis_full_levels", w0_domain_fs ) + call init_xios_axis( "vert_axis_half_levels", w3_domain_fs ) + call init_xios_axis( "radiation_levels", w0_domain_fs ) end subroutine init_xios_dimensions @@ -282,11 +290,12 @@ contains integer(kind=i_def) :: nodes_per_edge integer(kind=i_def) :: nodes_per_face integer(kind=i_def) :: num_edge_owned - type(mesh_type), pointer :: mesh => null() - type(mesh_type), pointer :: twod_mesh => null() + type(mesh_type), pointer :: mesh + type(mesh_type), pointer :: twod_mesh - type(function_space_type), pointer :: output_field_fs => null() - type(function_space_type), pointer :: w2h_fs => null() + type(function_space_type), pointer :: output_field_fs + type(function_space_type), pointer :: w2h_fs + type(function_space_type), pointer :: domain_fs ! Identify discontinuous spaces integer(kind=i_def) :: use_i_index(2) = (/ W3, Wtheta /) @@ -297,6 +306,11 @@ contains logical :: mesh_is_prime_mesh + nullify(mesh, twod_mesh) + nullify(output_field_fs) + nullify(w2h_fs) + nullify(domain_fs) + ! Set optional prime_mesh_flag if (present(prime_mesh)) then mesh_is_prime_mesh = prime_mesh @@ -394,24 +408,38 @@ contains if (mesh_is_prime_mesh) then call set_prime_io_mesh(mesh) call set_prime_io_mesh(twod_mesh) - call init_xios_ugrid_domain( "node", mesh, W0, sample_chi, & - bnd_nodes_lon, bnd_nodes_lat, & + + domain_fs => function_space_collection%get_fs(mesh, 0, 0, W0) + call init_xios_ugrid_domain( "node", domain_fs, sample_chi, & + bnd_nodes_lon, bnd_nodes_lat, & "Mesh2d", nverts=1 ) - call init_xios_ugrid_domain( "edge", mesh, W2H, sample_chi, & - bnd_edges_lon, bnd_edges_lat, & + + domain_fs => function_space_collection%get_fs(mesh, 0, 0, W2H) + call init_xios_ugrid_domain( "edge", domain_fs, sample_chi, & + bnd_edges_lon, bnd_edges_lat, & "Mesh2d", nverts=2 ) - call init_xios_ugrid_domain( "face", mesh, W3, sample_chi, & - bnd_faces_lon, bnd_faces_lat, & + + domain_fs => function_space_collection%get_fs(mesh, 0, 0, W3) + call init_xios_ugrid_domain( "face", domain_fs, sample_chi, & + bnd_faces_lon, bnd_faces_lat, & "Mesh2d", nverts=4 ) else - call init_xios_ugrid_domain( trim(adjustl(mesh%get_mesh_name()))//"_node", mesh, W0, & - sample_chi, bnd_nodes_lon, bnd_nodes_lat, & + + domain_fs => function_space_collection%get_fs(mesh, 0, 0, W0) + call init_xios_ugrid_domain( trim(adjustl(mesh%get_mesh_name()))//"_node", & + domain_fs, sample_chi, & + bnd_nodes_lon, bnd_nodes_lat, & trim(adjustl(mesh%get_mesh_name())), nverts=1 ) - call init_xios_ugrid_domain( trim(adjustl(mesh%get_mesh_name()))//"_edge", mesh, W2H, & - sample_chi, bnd_edges_lon, bnd_edges_lat, & + + domain_fs => function_space_collection%get_fs(mesh, 0, 0, W2h) + call init_xios_ugrid_domain( trim(adjustl(mesh%get_mesh_name()))//"_edge", & + domain_fs, sample_chi, & + bnd_edges_lon, bnd_edges_lat, & trim(adjustl(mesh%get_mesh_name())), nverts=2 ) - call init_xios_ugrid_domain( trim(adjustl(mesh%get_mesh_name()))//"_face", mesh, W3, & - sample_chi, bnd_faces_lon, bnd_faces_lat, & + domain_fs => function_space_collection%get_fs(mesh, 0, 0, W3) + call init_xios_ugrid_domain( trim(adjustl(mesh%get_mesh_name()))//"_face", & + domain_fs, sample_chi, & + bnd_faces_lon, bnd_faces_lat, & trim(adjustl(mesh%get_mesh_name())), nverts=4 ) end if @@ -902,23 +930,21 @@ contains !> @param[in] nverts Number of vertices bounding each domain !! element !> - subroutine init_xios_ugrid_domain( domain_id, mesh, fs_id, chi, & - lon_bounds, lat_bounds, mesh_name, & - nverts ) + subroutine init_xios_ugrid_domain( domain_id, domain_fs, chi, & + lon_bounds, lat_bounds, & + mesh_name, nverts ) implicit none - character(len=*), intent(in) :: domain_id - type(mesh_type), pointer, intent(in) :: mesh - integer(kind=i_def), intent(in) :: fs_id + character(len=*), intent(in) :: domain_id + type(function_space_type), intent(in) :: domain_fs + type(field_type), intent(in) :: chi(:) real(dp_xios), allocatable, intent(inout) :: lat_bounds(:,:) real(dp_xios), allocatable, intent(inout) :: lon_bounds(:,:) character(len=*), intent(in) :: mesh_name integer(kind=i_def), intent(in) :: nverts - type(function_space_type), pointer :: domain_fs => null() - type( field_type ) :: coord_output(3) type(field_proxy_type), target :: proxy_coord_output(3) @@ -942,6 +968,12 @@ contains ! set as 1.0 for planar mesh real(kind=r_def) :: r2d + type(mesh_type), pointer :: mesh + integer(kind=i_def) :: fs_id + + fs_id = domain_fs%which() + mesh => domain_fs%get_mesh() + if ( mesh%is_geometry_spherical() ) then r2d = radians_to_degrees else @@ -954,10 +986,6 @@ contains all_undfs = 0 - ! Here we use information from the input function space to calculate the - ! physical coordinates for the horizontal domain - domain_fs => function_space_collection%get_fs( mesh, 0, 0, fs_id ) - ! Get the function space levels information dp_levels = real( domain_fs%get_levels(), kind=dp_xios ) n_levels = size(dp_levels) @@ -1090,7 +1118,6 @@ contains deallocate(lat_data) deallocate(lon_data) deallocate(domain_index) - nullify(domain_fs) end subroutine init_xios_ugrid_domain @@ -1103,23 +1130,19 @@ contains !> @param[in] fs_id The id of the function space corresponding to the !> domain !> - subroutine init_xios_axis( axis_id, mesh, fs_id ) + subroutine init_xios_axis( axis_id, domain_fs ) implicit none - character(len=*), intent(in) :: axis_id - type(mesh_type), pointer, intent(in) :: mesh - integer(kind=i_def), intent(in) :: fs_id + character(len=*), intent(in) :: axis_id + type(function_space_type), intent(in) :: domain_fs - type(function_space_type), pointer :: domain_fs => null() real(dp_xios), allocatable :: dp_levels(:) integer(kind=i_def) :: n_levels type(xios_axisgroup) :: axis_definition type(xios_axis) :: new_axis - domain_fs => function_space_collection%get_fs( mesh,0, 0, fs_id ) - ! Get the function space levels information dp_levels = real( domain_fs%get_levels(), kind=dp_xios ) n_levels = size(dp_levels) diff --git a/components/science/source/algorithm/sci_mapping_constants_mod.x90 b/components/science/source/algorithm/sci_mapping_constants_mod.x90 index e295d9b75..51eaef90b 100644 --- a/components/science/source/algorithm/sci_mapping_constants_mod.x90 +++ b/components/science/source/algorithm/sci_mapping_constants_mod.x90 @@ -666,9 +666,14 @@ contains if (.not. constant_exists) then if (.not. coarse_mesh%query_mesh_map(fine_mesh)) then - write(log_scratch_space, '(A,I6,A,I6)') & - 'No mesh map exists for mapping between meshes ', & - coarse_mesh%get_id(), ' and ', fine_mesh%get_id() + + write(log_scratch_space, '(2(A,I0),A)') & + 'No mesh map exists for mapping between meshes '// & + trim(coarse_mesh%get_mesh_name())//'(', & + coarse_mesh%get_id(), & + ') and '//trim(fine_mesh%get_mesh_name())//'(', & + fine_mesh%get_id(), & + ')' call log_event(log_scratch_space, LOG_LEVEL_ERROR) end if @@ -734,9 +739,12 @@ contains if (.not. constant_exists) then if (.not. coarse_mesh%query_mesh_map(fine_mesh)) then - write(log_scratch_space, '(A,I6,A,I6)') & - 'No mesh map exists for mapping between meshes ', & - coarse_mesh%get_id(), ' and ', fine_mesh%get_id() + write(log_scratch_space, '(2(A,I0),A)') & + 'No mesh map exists for mapping between meshes ' //& + trim(coarse_mesh%get_mesh_name()) //'(', & + coarse_mesh%get_id(), ') and ' // & + trim(fine_mesh%get_mesh_name()) //'(', & + fine_mesh%get_id(), ')' call log_event(log_scratch_space, LOG_LEVEL_ERROR) end if diff --git a/infrastructure/source/field/field_mod.t90 b/infrastructure/source/field/field_mod.t90 index d7fdacc4c..60d33b45e 100644 --- a/infrastructure/source/field/field_mod.t90 +++ b/infrastructure/source/field/field_mod.t90 @@ -260,9 +260,9 @@ contains implicit none - class(field_{{kind}}_type), intent(inout) :: self - type(function_space_type), pointer, intent(in) :: vector_space - character(*), optional, intent(in) :: name + class(field_{{kind}}_type), intent(inout) :: self + type(function_space_type), intent(in) :: vector_space + character(*), optional, intent(in) :: name {{type}}({{kind}}), target, optional, intent(in) :: override_data( : ) integer(i_def), optional, intent(in) :: halo_depth diff --git a/infrastructure/source/function_space/function_space_collection_mod.F90 b/infrastructure/source/function_space/function_space_collection_mod.F90 index cd0e9cebd..2e2214282 100644 --- a/infrastructure/source/function_space/function_space_collection_mod.F90 +++ b/infrastructure/source/function_space/function_space_collection_mod.F90 @@ -106,7 +106,6 @@ function get_fs( self, & type(function_space_type), pointer :: fs integer(i_def) :: ndata_sz - integer(i_def) :: mesh_id character(str_short) :: name logical(l_def) :: ndata_first_sz @@ -135,10 +134,8 @@ function get_fs( self, & call log_event(log_scratch_space, LOG_LEVEL_ERROR) end if - mesh_id = mesh%get_id() - fs => get_existing_fs( self, & - mesh_id, & + mesh, & element_order_h, & element_order_v, & lfric_fs, & @@ -148,7 +145,7 @@ function get_fs( self, & if (.not. associated(fs)) then call self%fs_list%insert_item( & - function_space_type( mesh_id, & + function_space_type( mesh, & element_order_h, & element_order_v, & lfric_fs, & @@ -161,7 +158,7 @@ function get_fs( self, & call log_event(log_scratch_space, LOG_LEVEL_TRACE) fs => get_existing_fs( self, & - mesh_id, & + mesh, & element_order_h, & element_order_v, & lfric_fs, & @@ -238,7 +235,7 @@ end subroutine function_space_collection_destructor !> @param[in] ndata_first Flag to set data to be layer first (false) or !! ndata first (true) function get_existing_fs( self, & - mesh_id, & + mesh, & element_order_h, & element_order_v, & lfric_fs, & @@ -248,7 +245,9 @@ function get_existing_fs( self, & implicit none class(function_space_collection_type) :: self - integer(i_def), intent(in) :: mesh_id + + type(mesh_type), intent(in) :: mesh + integer(i_def), intent(in) :: element_order_h integer(i_def), intent(in) :: element_order_v integer(i_def), intent(in) :: lfric_fs @@ -285,7 +284,7 @@ function get_existing_fs( self, & fs_id = generate_fs_id(lfric_fs, & element_order_h, & element_order_v, & - mesh_id, & + mesh%get_id(), & ndata, & ndata_first) diff --git a/infrastructure/source/function_space/function_space_mod.F90 b/infrastructure/source/function_space/function_space_mod.F90 index 03e74bdaf..eb73b2041 100644 --- a/infrastructure/source/function_space/function_space_mod.F90 +++ b/infrastructure/source/function_space/function_space_mod.F90 @@ -34,7 +34,6 @@ module function_space_mod compute_global_vert_dof_id_2d use linked_list_data_mod, only : linked_list_data_type use linked_list_mod, only : linked_list_type, linked_list_item_type - use mesh_collection_mod, only : mesh_collection use timing_mod, only : start_timing, stop_timing, & tik, LPROF @@ -426,7 +425,7 @@ module function_space_mod !> @param[in] ndata_first Flag to set data to be layer first (false) or !! ndata first (true) !> @return A pointer to the function space held in this module - function fs_constructor( mesh_id, & + function fs_constructor( mesh, & element_order_h, & element_order_v, & lfric_fs, & @@ -435,7 +434,7 @@ function fs_constructor( mesh_id, & implicit none - integer(i_def), intent(in) :: mesh_id + type(mesh_type), target, intent(in) :: mesh integer(i_def), intent(in) :: element_order_h integer(i_def), intent(in) :: element_order_v integer(i_def), intent(in) :: lfric_fs @@ -461,12 +460,12 @@ function fs_constructor( mesh_id, & instance%ndata = 1 end if - instance%mesh => mesh_collection%get_mesh(mesh_id) + instance%mesh => mesh instance%fs = lfric_fs instance%element_order_h = element_order_h instance%element_order_v = element_order_v - id = generate_fs_id(lfric_fs, element_order_h, element_order_v, mesh_id, & + id = generate_fs_id(lfric_fs, element_order_h, element_order_v, mesh%get_id(), & instance%ndata, instance%ndata_first) call instance%set_id(id) diff --git a/infrastructure/source/io/ugrid_2d_mod.F90 b/infrastructure/source/io/ugrid_2d_mod.F90 index 007ea13ad..7d147ebf5 100644 --- a/infrastructure/source/io/ugrid_2d_mod.F90 +++ b/infrastructure/source/io/ugrid_2d_mod.F90 @@ -12,7 +12,7 @@ module ugrid_2d_mod use constants_mod, only: i_def, r_def, str_def, str_longlong, l_def, & - imdi, rmdi, cmdi + imdi, rmdi, cmdi, str_max_filename use file_mod, only: file_mode_write use ugrid_file_mod, only: ugrid_file_type @@ -38,6 +38,9 @@ module ugrid_2d_mod character(str_def) :: mesh_name + character(str_def) :: origin_name = cmdi + character(str_max_filename) :: origin_file = cmdi + character(str_def) :: geometry character(str_def) :: topology character(str_def) :: coord_sys @@ -137,6 +140,8 @@ module ugrid_2d_mod contains procedure :: get_n_meshes procedure :: get_mesh_names + procedure :: get_origin_file + procedure :: get_origin_name procedure :: get_dimensions procedure :: set_by_generator procedure :: set_file_handler @@ -552,6 +557,9 @@ subroutine set_from_file_read(self, mesh_name, filename) self%populated_with_mesh = .true. + self%origin_file = trim(filename) + self%origin_name = trim(self%mesh_name) + return end subroutine set_from_file_read @@ -1680,6 +1688,29 @@ function is_local(self) result(answer) end function is_local +function get_origin_name( self ) result ( origin_name ) + + implicit none + + class(ugrid_2d_type), intent(in) :: self + + character(str_def) :: origin_name + + origin_name = self%origin_name + +end function get_origin_name + +function get_origin_file( self ) result ( origin_file ) + + implicit none + + class(ugrid_2d_type), intent(in) :: self + + character(str_max_filename) :: origin_file + + origin_file = self%origin_file + +end function get_origin_file !------------------------------------------------------------------------------- !> @brief Finalizer routine which should automatically call clear diff --git a/infrastructure/source/mesh/global_mesh_mod.F90 b/infrastructure/source/mesh/global_mesh_mod.F90 index ae0046794..7d6ee8934 100644 --- a/infrastructure/source/mesh/global_mesh_mod.F90 +++ b/infrastructure/source/mesh/global_mesh_mod.F90 @@ -49,6 +49,9 @@ module global_mesh_mod ! Tag name of mesh. character(str_def) :: mesh_name + character(str_max_filename) :: origin_file = cmdi + character(str_def) :: origin_name = cmdi + ! Flag to indicate if this a mesh represents coverage ! of a global model. logical(l_def) :: global_model = .false. @@ -172,6 +175,8 @@ module global_mesh_mod contains procedure, public :: get_mesh_name + procedure, public :: get_origin_name + procedure, public :: get_origin_file procedure, public :: get_npanels procedure, public :: get_mesh_periodicity procedure, public :: get_cell_id @@ -258,13 +263,14 @@ module global_mesh_mod !> !> @return Freshly minted global_mesh_type object. !> - function global_mesh_constructor( ugrid_mesh_data ) result(self) + function global_mesh_constructor( ugrid_mesh_data, rename_to ) result(self) use ugrid_mesh_data_mod, only: ugrid_mesh_data_type implicit none - type(ugrid_mesh_data_type), intent(in) :: ugrid_mesh_data + type(ugrid_mesh_data_type), intent(in) :: ugrid_mesh_data + character(str_def), optional, intent(in) :: rename_to type(global_mesh_type) :: self @@ -277,7 +283,12 @@ function global_mesh_constructor( ugrid_mesh_data ) result(self) ! loop counter over entities (vertices or edges). integer(i_def) :: ientity + global_mesh_id_counter = global_mesh_id_counter + 1 + + call self%set_id(global_mesh_id_counter) + call ugrid_mesh_data%get_data( self%mesh_name, & + self%origin_file, & geometry, & topology, & coord_sys, & @@ -307,9 +318,10 @@ function global_mesh_constructor( ugrid_mesh_data ) result(self) self%edge_on_cell_2d, & self%vert_on_edge_2d ) - global_mesh_id_counter = global_mesh_id_counter + 1 - - call self%set_id(global_mesh_id_counter) + self%origin_name = self%mesh_name + if (present(rename_to)) then + self%mesh_name = trim(rename_to) + end if select case (trim(geometry)) @@ -911,6 +923,32 @@ function get_mesh_name( self ) result ( mesh_name ) end function get_mesh_name + function get_origin_name( self ) result ( origin_name ) + + implicit none + + class(global_mesh_type), intent(in) :: self + + character(str_def) :: origin_name + + origin_name = self%origin_name + + end function get_origin_name + + function get_origin_file( self ) result ( origin_file ) + + implicit none + + class(global_mesh_type), intent(in) :: self + + character(str_max_filename) :: origin_file + + origin_file = self%origin_file + + end function get_origin_file + + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !> @brief Returns values for the X and Y periodicity. diff --git a/infrastructure/source/mesh/local_mesh_collection_mod.f90 b/infrastructure/source/mesh/local_mesh_collection_mod.f90 index bbae65ac3..9e9e33a05 100644 --- a/infrastructure/source/mesh/local_mesh_collection_mod.f90 +++ b/infrastructure/source/mesh/local_mesh_collection_mod.f90 @@ -33,6 +33,7 @@ module local_mesh_collection_mod generic, public :: get_local_mesh => get_mesh_by_id, & get_mesh_by_name procedure, public :: get_mesh_names + procedure, public :: n_meshes procedure, public :: check_for procedure, public :: clear @@ -223,6 +224,21 @@ function get_mesh_by_name( self, local_mesh_name ) result( local_mesh ) end function get_mesh_by_name + + function n_meshes(self) result(number_of_meshes) + + implicit none + + class(local_mesh_collection_type), intent(in) :: self + + integer(i_def) :: number_of_meshes + + number_of_meshes = self%local_mesh_list%get_length() + + return + end function n_meshes + + !=========================================================================== !> @brief Requests a local mesh object with specified ID from !> the collection. diff --git a/infrastructure/source/mesh/local_mesh_mod.f90 b/infrastructure/source/mesh/local_mesh_mod.f90 index 481d8ef3f..a2e0fb288 100644 --- a/infrastructure/source/mesh/local_mesh_mod.f90 +++ b/infrastructure/source/mesh/local_mesh_mod.f90 @@ -10,11 +10,11 @@ !> module local_mesh_mod - use constants_mod, only: r_def, i_def, i_halo_index, & - l_def, str_def, integer_type, & - str_longlong, & - imdi, rmdi, cmdi, emdi, & - degrees_to_radians, & + use constants_mod, only: r_def, i_def, i_halo_index, & + l_def, str_def, integer_type, & + str_longlong, str_max_filename, & + imdi, rmdi, cmdi, emdi, & + degrees_to_radians, & radians_to_degrees use global_mesh_map_collection_mod, only: global_mesh_map_collection_type @@ -52,6 +52,10 @@ module local_mesh_mod !==================================== ! Tag name of mesh. character(str_def) :: mesh_name + + character(str_max_filename) :: origin_file = cmdi + character(str_def) :: origin_name = cmdi + ! Domain surface geometry. integer(i_def) :: geometry = emdi ! Domain boundaries topology. @@ -186,6 +190,8 @@ module local_mesh_mod procedure, public :: clear procedure, public :: get_mesh_name + procedure, public :: get_origin_file + procedure, public :: get_origin_name procedure, public :: get_nverts_per_cell procedure, public :: get_nverts_per_edge procedure, public :: get_nedges_per_cell @@ -297,6 +303,9 @@ subroutine initialise_full ( self, & self%mesh_name = global_mesh%get_mesh_name() end if + self%origin_file = global_mesh%get_origin_file() + self%origin_name = global_mesh%get_origin_name() + ! Inherit mesh properties from the parent global mesh. if (global_mesh%is_geometry_spherical()) then self%geometry = spherical_domain @@ -1133,7 +1142,7 @@ end subroutine initialise_lbc !> @param [in] ugrid_mesh_data which was populated !> directly from file read !> - subroutine initialise_from_ugrid_data(self, ugrid_mesh_data) + subroutine initialise_from_ugrid_data(self, ugrid_mesh_data, rename_to) use ugrid_mesh_data_mod, only: ugrid_mesh_data_type @@ -1141,7 +1150,8 @@ subroutine initialise_from_ugrid_data(self, ugrid_mesh_data) class(local_mesh_type) :: self - type(ugrid_mesh_data_type), intent(in) :: ugrid_mesh_data + type(ugrid_mesh_data_type), intent(in) :: ugrid_mesh_data + character(str_def), optional, intent(in) :: rename_to integer(i_def) :: nfaces ! number of faces in this local mesh. ! should be same as last ghost cell @@ -1165,6 +1175,7 @@ subroutine initialise_from_ugrid_data(self, ugrid_mesh_data) ! Get ugrid data which describes the mesh. call ugrid_mesh_data%get_data( & self%mesh_name, & + self%origin_file, & geometry_str, & topology_str, & coord_sys_str, & @@ -1193,6 +1204,11 @@ subroutine initialise_from_ugrid_data(self, ugrid_mesh_data) self%vert_on_cell, & self%edge_on_cell ) + self%origin_name = self%mesh_name + if (present(rename_to)) then + self%mesh_name = trim(rename_to) + end if + select case (trim(geometry_str)) case ('spherical') self%geometry = spherical_domain @@ -1560,6 +1576,24 @@ function get_mesh_name( self ) result ( mesh_name ) end function get_mesh_name + function get_origin_file( self ) result ( origin_file ) + implicit none + class(local_mesh_type), intent(in) :: self + character(str_max_filename) :: origin_file + + origin_file = self%origin_file + + end function get_origin_file + + function get_origin_name( self ) result ( origin_name ) + implicit none + class(local_mesh_type), intent(in) :: self + character(str_def) :: origin_name + + origin_name = self%origin_name + + end function get_origin_name + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !> @brief Returns the north pole location of mesh. !> @details A mesh may have been transformed before being written to file. diff --git a/infrastructure/source/mesh/mesh_mod.F90 b/infrastructure/source/mesh/mesh_mod.F90 index 58aecbdf8..bf4c968f8 100644 --- a/infrastructure/source/mesh/mesh_mod.F90 +++ b/infrastructure/source/mesh/mesh_mod.F90 @@ -2320,8 +2320,8 @@ subroutine add_mesh_map(self, target_mesh) implicit none - class(mesh_type), intent(inout) :: self - type(mesh_type), intent(in), pointer :: target_mesh + class(mesh_type), intent(inout) :: self + type(mesh_type), intent(in) :: target_mesh type(local_mesh_type), pointer :: source_local_mesh diff --git a/infrastructure/source/mesh/panel_decomposition_mod.f90 b/infrastructure/source/mesh/panel_decomposition_mod.f90 index b6713da9c..847e51c65 100644 --- a/infrastructure/source/mesh/panel_decomposition_mod.f90 +++ b/infrastructure/source/mesh/panel_decomposition_mod.f90 @@ -10,7 +10,7 @@ module panel_decomposition_mod use global_mesh_mod, only: global_mesh_type use global_mesh_collection_mod, only: global_mesh_collection_type - use constants_mod, only: i_def, l_def, r_def + use constants_mod, only: i_def, l_def, r_def, str_def use log_mod, only: log_event, log_scratch_space, & LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG @@ -125,6 +125,11 @@ end function get_nprocs_interface end interface + interface calc_mapping_factor + module procedure calc_mapping_factor_multiple + module procedure calc_mapping_factor_single + end interface calc_mapping_factor + contains !> @brief Partition the panel into a given number of x and y processes @@ -985,50 +990,92 @@ end subroutine nonuniform_decomposition !> to align partitions for mapped grids !> @param[in] global-mesh_collection The global mesh collection !> @param[in] global_mesh The global mesh to calculate the factor for - function calc_mapping_factor( global_mesh_collection, global_mesh ) result(mp) + function calc_mapping_factor_multiple( global_mesh, & + global_mesh_collection ) result(mp) + implicit none - type(global_mesh_collection_type), intent(in) :: global_mesh_collection - type(global_mesh_type), intent(in), pointer :: global_mesh + type(global_mesh_type), intent(in) :: global_mesh + type(global_mesh_collection_type), & + intent(in) :: global_mesh_collection integer(i_def) :: mp - type(global_mesh_type), pointer :: comparison_global_mesh - integer(i_def) :: this_panel_width, shortest_panel_width, n_meshes, i + type(global_mesh_type), pointer :: reference_global_mesh - this_panel_width = calc_panel_width(global_mesh) + integer(i_def) :: panel_width, shortest_panel_width + integer(i_def) :: reference_panel_width + integer(i_def) :: i - n_meshes = global_mesh_collection%n_meshes() + character(str_def), allocatable :: mesh_names(:) shortest_panel_width = huge(0_i_def) - do i = 1, n_meshes - comparison_global_mesh => global_mesh_collection%get_mesh_by_id(i) - if ( associated(comparison_global_mesh) ) then - shortest_panel_width = min( shortest_panel_width, & - calc_panel_width(comparison_global_mesh)) + panel_width = calc_panel_width(global_mesh) + mesh_names = global_mesh_collection%get_mesh_names() + + do i=1, size(mesh_names) + + reference_global_mesh => global_mesh_collection%get_global_mesh(mesh_names(i)) + + if ( associated(reference_global_mesh) ) then + reference_panel_width = calc_panel_width(reference_global_mesh) + shortest_panel_width = min( shortest_panel_width, reference_panel_width ) end if + end do - ! If no meshes were found, or if this_panel_width < shortest_panel_width, then return 1. + ! If no meshes were found, or + ! if this_panel_width < shortest_panel_width, then return 1. if ( shortest_panel_width < huge(0_i_def) ) then - mp = max(1, this_panel_width / shortest_panel_width) + mp = max(1, panel_width / shortest_panel_width) else mp = 1 end if - end function calc_mapping_factor + end function calc_mapping_factor_multiple + + + function calc_mapping_factor_single( global_mesh, reference_global_mesh ) result(mp) + + implicit none + + type(global_mesh_type), intent(in) :: global_mesh + type(global_mesh_type), intent(in) :: reference_global_mesh + + integer(i_def) :: mp + + integer(i_def) :: reference_panel_width + integer(i_def) :: panel_width + integer(i_def) :: shortest_panel_width + + shortest_panel_width = huge(0_i_def) + reference_panel_width = calc_panel_width(reference_global_mesh) + panel_width = calc_panel_width(global_mesh) + + shortest_panel_width = min( reference_panel_width, panel_width ) + + if ( shortest_panel_width < huge(0_i_def) ) then + mp = max(1, panel_width / shortest_panel_width) + else + mp = 1 + end if + + end function calc_mapping_factor_single + + !> @brief Calculate the width of the mesh panel. On a spherical mesh this is !> the C number. !> @param[in] gloabl_mesh The mesh to calculate the panel width of function calc_panel_width( global_mesh ) result(panel_edge_ncells_x) + use reference_element_mod, only : W, E implicit none - type(global_mesh_type), intent(in), pointer :: global_mesh + type(global_mesh_type), intent(in) :: global_mesh integer(i_def) :: void_cell ! Cell id that marks the cell as a cell ! outside of the partition. diff --git a/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 b/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 index 2e6206df5..a0679651f 100644 --- a/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 +++ b/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 @@ -12,8 +12,10 @@ module ugrid_mesh_data_mod - use constants_mod, only: r_def, i_def, l_def, str_def, & - str_longlong, cmdi, imdi, rmdi + use constants_mod, only: r_def, i_def, l_def, str_def, & + str_longlong, cmdi, imdi, rmdi, & + str_max_filename + use log_mod, only: log_event, log_scratch_space, & LOG_LEVEL_ERROR, LOG_LEVEL_TRACE @@ -25,9 +27,13 @@ module ugrid_mesh_data_mod integer(i_def), parameter :: GLOBAL_MESH_FLAG = 101 type, public :: ugrid_mesh_data_type + !> Name of ugrid mesh topology. character(str_def) :: global_mesh_name + character(str_max_filename) :: origin_file + character(str_def) :: origin_name + integer(i_def) :: mesh_extents logical(l_def) :: is_local_mesh @@ -188,6 +194,8 @@ subroutine read_from_file( self, filename, global_mesh_name ) call self%clear() + self%origin_file = trim(filename) + allocate( ncdf_quad_type :: file_handler ) call ugrid_2d%set_file_handler( file_handler ) call ugrid_2d%set_from_file_read( trim(global_mesh_name), trim(filename) ) @@ -248,6 +256,7 @@ end subroutine read_from_file !> subroutine get_data( self, & mesh_name, & + origin, & geometry, & topology, & coord_sys, & @@ -280,11 +289,14 @@ subroutine get_data( self, & implicit none class (ugrid_mesh_data_type), intent(in) :: self + character(str_def), intent(out) :: mesh_name character(str_def), intent(out) :: geometry character(str_def), intent(out) :: topology character(str_def), intent(out) :: coord_sys + character(str_max_filename), intent(out) :: origin + integer(i_def), intent(out) :: nnode integer(i_def), intent(out) :: nedge integer(i_def), intent(out) :: nface @@ -321,6 +333,7 @@ subroutine get_data( self, & integer(i_def), optional, intent(out) :: max_stencil_depth mesh_name = self%global_mesh_name + origin = self%origin_file geometry = self%geometry topology = self%topology coord_sys = self%coord_sys @@ -651,6 +664,9 @@ subroutine set_by_ugrid_2d( self, ugrid_2d ) self%mesh_extents = GLOBAL_MESH_FLAG end if + self%origin_name = self%global_mesh_name + self%origin_file = ugrid_2d%get_origin_file() + return end subroutine set_by_ugrid_2d diff --git a/mesh_tools/source/support/generate_local_objects_mod.f90 b/mesh_tools/source/support/generate_local_objects_mod.f90 index 0f4018921..c7897cc12 100644 --- a/mesh_tools/source/support/generate_local_objects_mod.f90 +++ b/mesh_tools/source/support/generate_local_objects_mod.f90 @@ -122,7 +122,7 @@ subroutine generate_local_objects( local_mesh_bank, & source_name = mesh_names(i) source_global_mesh_ptr => global_mesh_bank%get_global_mesh(source_name) - mapping_factor = calc_mapping_factor(global_mesh_bank, source_global_mesh_ptr) + mapping_factor = calc_mapping_factor(source_global_mesh_ptr, global_mesh_bank) call log_event( 'Partitioning mesh:'//trim(source_name), log_level_debug ) From a495fb621caaf9a7d35ee81771c656d886896dc6 Mon Sep 17 00:00:00 2001 From: Ricky Wong <141156427+mo-rickywong@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:31:16 +0100 Subject: [PATCH 2/6] Commit changes to fir with linked ticket --- components/driver/source/driver_fem_mod.f90 | 26 ++++--------------- .../driver/source/mesh/add_mesh_map_mod.f90 | 1 - .../source/mesh/load_local_mesh_mod.f90 | 8 +++--- .../source/mesh/runtime_partition_mod.f90 | 20 +++++++------- 4 files changed, 19 insertions(+), 36 deletions(-) diff --git a/components/driver/source/driver_fem_mod.f90 b/components/driver/source/driver_fem_mod.f90 index 99d39fe52..8d2bfe5e4 100644 --- a/components/driver/source/driver_fem_mod.f90 +++ b/components/driver/source/driver_fem_mod.f90 @@ -107,27 +107,10 @@ subroutine init_fem(config, chi_inventory, panel_id_inventory) ! To loop through mesh collection, get all mesh names ! Then get mesh from collection using these names all_mesh_names = mesh_collection%get_mesh_names() -!!$ -!!$ if (prime_mesh_name == cmdi) then -!!$ mesh => mesh_collection%get_mesh(all_mesh_names(1)) -!!$ else -!!$ mesh => mesh_collection%get_mesh(prime_mesh_name) -!!$ end if -!!$ -!!$ if (mesh%is_geometry_planar()) then -!!$ geometry = geometry_planar -!!$ else if (mesh%is_geometry_spherical()) then -!!$ geometry = geometry_spherical -!!$ end if -!!$ -!!$ if (mesh%is_topology_periodic()) then -!!$ topology = topology_fully_periodic -!!$ else if (mesh%is_topology_non_periodic()) then -!!$ topology = topology_non_periodic -!!$ end if -!!$ -!!$ call init_chi_transforms( geometry, topology, & -!!$ mesh_collection=mesh_collection ) + + call chi_inventory%initialise(name="chi", table_len=size(all_mesh_names)) + call panel_id_inventory%initialise(name="panel_id", & + table_len=size(all_mesh_names)) ! ======================================================================== ! ! Loop through all 3D meshes @@ -150,6 +133,7 @@ subroutine init_fem(config, chi_inventory, panel_id_inventory) topology = topology_non_periodic end if + ! Initialise coordinate transformations call init_chi_transforms( geometry, topology, & mesh_collection=mesh_collection ) diff --git a/components/driver/source/mesh/add_mesh_map_mod.f90 b/components/driver/source/mesh/add_mesh_map_mod.f90 index 7b00b2d34..5733fd306 100644 --- a/components/driver/source/mesh/add_mesh_map_mod.f90 +++ b/components/driver/source/mesh/add_mesh_map_mod.f90 @@ -126,7 +126,6 @@ subroutine assign_mesh_maps( mesh_names ) if (mesh_name_B /= cmdi) then mesh_A => mesh_collection%get_mesh(mesh_name_A) mesh_B => mesh_collection%get_mesh(mesh_name_B) -! call add_mesh_map( mesh_name_A, mesh_name_B ) call add_mesh_map( mesh_A, mesh_B ) end if end do diff --git a/components/driver/source/mesh/load_local_mesh_mod.f90 b/components/driver/source/mesh/load_local_mesh_mod.f90 index ae0d2a6f2..2488e7ce3 100644 --- a/components/driver/source/mesh/load_local_mesh_mod.f90 +++ b/components/driver/source/mesh/load_local_mesh_mod.f90 @@ -36,7 +36,8 @@ module load_local_mesh_mod !> populate objects. !> @param[in] mesh_names The names of the local mesh data to !> load from the . -subroutine load_local_mesh_multiple( input_mesh_file, mesh_names ) +subroutine load_local_mesh_multiple( input_mesh_file, & + mesh_names ) implicit none character(str_max_filename), intent(in) :: input_mesh_file @@ -45,7 +46,7 @@ subroutine load_local_mesh_multiple( input_mesh_file, mesh_names ) integer(i_def) :: i do i=1, size(mesh_names) - call load_local_mesh_single( input_mesh_file, mesh_names(i)) + call load_local_mesh_single( input_mesh_file, mesh_names(i) ) end do end subroutine load_local_mesh_multiple @@ -57,7 +58,8 @@ end subroutine load_local_mesh_multiple !> populate objects. !> @param[in] mesh_name The name of the local mesh data to !> load from the . -subroutine load_local_mesh_single( input_mesh_file, mesh_name ) +subroutine load_local_mesh_single( input_mesh_file, & + mesh_name ) implicit none diff --git a/components/driver/source/mesh/runtime_partition_mod.f90 b/components/driver/source/mesh/runtime_partition_mod.f90 index 35c71daf2..342246d7e 100644 --- a/components/driver/source/mesh/runtime_partition_mod.f90 +++ b/components/driver/source/mesh/runtime_partition_mod.f90 @@ -12,7 +12,6 @@ module runtime_partition_mod use global_mesh_mod, only: global_mesh_type use log_mod, only: log_event, & log_scratch_space, & - log_level_info, & log_level_error, & log_level_debug use local_mesh_mod, only: local_mesh_type @@ -23,12 +22,11 @@ module runtime_partition_mod partitioner_cubedsphere, & partitioner_planar - use panel_decomposition_mod, only: panel_decomposition_type!, & -! calc_mapping_factor + use panel_decomposition_mod, only: panel_decomposition_type use sci_query_mod, only: is_lbc - use local_mesh_collection_mod, only: local_mesh_collection - use global_mesh_collection_mod, only: global_mesh_collection + use local_mesh_collection_mod, only: local_mesh_collection + use global_mesh_collection_mod, only: global_mesh_collection implicit none @@ -38,8 +36,8 @@ module runtime_partition_mod public :: create_local_mesh_maps interface create_local_mesh_maps - module procedure create_local_mesh_maps_king - module procedure create_local_mesh_maps_kong + module procedure create_local_mesh_maps_from_file + module procedure create_local_mesh_maps_from_object end interface create_local_mesh_maps integer, public, parameter :: mesh_cubedsphere = 34 @@ -203,7 +201,7 @@ end subroutine create_local_mesh !! mesh object. !! !> @param[in] input_mesh_file Input file to load mesh maps from. -subroutine create_local_mesh_maps_king( input_mesh_file ) +subroutine create_local_mesh_maps_from_file( input_mesh_file ) implicit none @@ -307,11 +305,11 @@ subroutine create_local_mesh_maps_king( input_mesh_file ) call file_handler%file_close() return -end subroutine create_local_mesh_maps_king +end subroutine create_local_mesh_maps_from_file -subroutine create_local_mesh_maps_kong( source_local_mesh ) +subroutine create_local_mesh_maps_from_object( source_local_mesh ) implicit none @@ -427,6 +425,6 @@ subroutine create_local_mesh_maps_kong( source_local_mesh ) end if ! test if the source has any targets listed return -end subroutine create_local_mesh_maps_kong +end subroutine create_local_mesh_maps_from_object end module runtime_partition_mod From 2ab0c15522296c8296b27356086d33e094de1db8 Mon Sep 17 00:00:00 2001 From: Ricky Wong <141156427+mo-rickywong@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:54:30 +0100 Subject: [PATCH 3/6] Update UMLs and add Doxygen comments --- .../field/function_space_collection_mod.iuml | 2 +- .../uml/field/function_space_mod.iuml | 2 +- .../documentation/uml/io/ugrid_2d_mod.iuml | 10 ++- .../uml/mesh/global_mesh_mod.iuml | 16 +++- .../uml/mesh/local_mesh_collection_mod.iuml | 3 + .../uml/mesh/local_mesh_mod.iuml | 11 ++- .../uml/mesh/ugrid_mesh_data_mod.iuml | 10 ++- .../function_space_collection_mod.F90 | 2 +- infrastructure/source/io/ugrid_2d_mod.F90 | 15 +++- .../mesh/global_mesh_collection_mod.F90 | 2 +- .../source/mesh/global_mesh_mod.F90 | 41 ++++++--- .../source/mesh/local_mesh_collection_mod.f90 | 38 +++++--- infrastructure/source/mesh/local_mesh_mod.f90 | 50 ++++++++--- .../source/mesh/panel_decomposition_mod.f90 | 68 +++++++------- infrastructure/source/mesh/partition_mod.F90 | 5 +- .../source/mesh/ugrid_mesh_data_mod.f90 | 67 +++++++------- .../function_space/function_space_mod_test.pf | 89 ++++++++----------- .../unit-test/mesh/global_mesh_mod_test.pf | 82 ++++++++--------- .../mesh/ugrid_mesh_data_mod_test.pf | 10 ++- 19 files changed, 301 insertions(+), 222 deletions(-) diff --git a/infrastructure/documentation/uml/field/function_space_collection_mod.iuml b/infrastructure/documentation/uml/field/function_space_collection_mod.iuml index 7aaa70b09..fc2d9bec5 100644 --- a/infrastructure/documentation/uml/field/function_space_collection_mod.iuml +++ b/infrastructure/documentation/uml/field/function_space_collection_mod.iuml @@ -9,7 +9,7 @@ class function_space_collection_mod::function_space_collection_type { <>+function_space_collection_destructor() +clear() - +get_fs( <>mesh: mesh_type, <>element_order_h: integer, <>element_order_v: integer, <>gungho_fs: integer, <>ndata: integer) : function_space_type + +get_fs( <>mesh: mesh_type, <>element_order_h: integer, <>element_order_v: integer, <>gungho_fs: integer, <>ndata: integer) : function_space_type +get_fs_collection_size() : integer } diff --git a/infrastructure/documentation/uml/field/function_space_mod.iuml b/infrastructure/documentation/uml/field/function_space_mod.iuml index 4fa626430..6392c6c6d 100644 --- a/infrastructure/documentation/uml/field/function_space_mod.iuml +++ b/infrastructure/documentation/uml/field/function_space_mod.iuml @@ -38,7 +38,7 @@ class function_space_mod::function_space_type { -fractional_levels: double precision[:] <> -readonly: logical - <>+fs_constructor( <>mesh_id: integer, <>element_order_h: integer, <>element_order_v: integer, <>gungho_fs: integer, <>ndata: integer ) : function_space_type + <>+fs_constructor( <>mesh: mesh_type, <>element_order_h: integer, <>element_order_v: integer, <>gungho_fs: integer, <>ndata: integer ) : function_space_type <>+function_space_destructor() +clear() diff --git a/infrastructure/documentation/uml/io/ugrid_2d_mod.iuml b/infrastructure/documentation/uml/io/ugrid_2d_mod.iuml index 8e38c29f9..6f21f92e9 100644 --- a/infrastructure/documentation/uml/io/ugrid_2d_mod.iuml +++ b/infrastructure/documentation/uml/io/ugrid_2d_mod.iuml @@ -5,6 +5,8 @@ class ugrid_2d_mod::ugrid_2d_type { -mesh_name: string + -origin_name: string + -origin_file: string -geometry: string -topology: string -coord_sys: string @@ -12,6 +14,7 @@ class ugrid_2d_mod::ugrid_2d_type { -north_pole: real[2] -null_island: real[2] -equatorial_latitude: real + -populated_with_mesh: logical -periodic_xy: logical[2] -constructor_inputs: string -coord_units_xy: string[2] @@ -27,7 +30,7 @@ class ugrid_2d_mod::ugrid_2d_type { -max_num_faces_per_node: integer -rim_depth: integer - -domain_size: real[2] + -domain_extents: real[2,4] -partition_of: string -inner_depth: integer @@ -65,15 +68,18 @@ class ugrid_2d_mod::ugrid_2d_type { -target_edge_cells_x: integer[:] <> -target_edge_cells_y: integer[:] <> -target_global_mesh_maps: global_mesh_map_collection_type + -target_local_mesh_maps: local_mesh_map_collection_type -file_handler: ugrid_file_type <> - +<>ugrid_2d_destructor() +clear() +get_n_meshes( <> filename: string, <> n_meshes: integer ) +get_mesh_names( <> filename: string, <> mesh_names: string[:] ) + +get_origin_name(): string + +get_origin_file(): string + +get_dimensions( <> num_nodes: integer, <> num_edges: integer, <> num_faces: integer, <> num_nodes_per_face: integer, <> num_edges_per_face: integer, <> num_nodes_per_edge: integer, <> max_num_faces_per_node: integer ) +set_by_generator( <> generator_strategy: ugrid_generator_type ) +set_file_handler( <> file_handler: ugrid_file_type ) diff --git a/infrastructure/documentation/uml/mesh/global_mesh_mod.iuml b/infrastructure/documentation/uml/mesh/global_mesh_mod.iuml index 9b6a7e532..5f3c7574d 100644 --- a/infrastructure/documentation/uml/mesh/global_mesh_mod.iuml +++ b/infrastructure/documentation/uml/mesh/global_mesh_mod.iuml @@ -4,13 +4,15 @@ class global_mesh_mod::global_mesh_type { -mesh_name: string + -origin_name: string + -origin_file: string -global_model: logical -geometry: integer -topology: integer -coord_sys: integer -coord_units_xy: string[2] -constructor_inputs: string - -domain_size: real[2] + -domain_extents: real[2,4] -north_pole: real[2] -null_island: real[2] -equatorial_latitude: real @@ -32,6 +34,7 @@ class global_mesh_mod::global_mesh_type { -nedges_per_cell: integer -max_cells_per_vertex: integer -npanels: integer + -void_cell: integer -ntarget_meshes: integer -target_global_mesh_names: string[] <> -global_mesh_maps: global_mesh_map_collection_type <> @@ -44,11 +47,14 @@ class global_mesh_mod::global_mesh_type { +clear() +get_mesh_name(): string + +get_origin_name(): string + +get_origin_file(): string +get_npanels(): integer +get_mesh_periodicity: logical[2] +get_cell_id(<>cell_number: integer,<>x_cells: integer,<>y_cells: integer ): integer +get_cell_on_vert( <>vertex_number: integer, <>cells: integer[] ) +get_cell_on_edge( <>edge_number: integer, <>cells: integer[] ) + +get_void_cell(): integer +get_nverts(): integer +get_nedges(): integer +get_ncells(): integer @@ -62,7 +68,11 @@ class global_mesh_mod::global_mesh_type { +get_nedges_per_cell(): integer +get_cell_next( <>cell_gid: integer, <>cell_next: integer[] ) +get_all_cells_next(): integer[::] - +get_vert_coords( <>vert_gid: integer, <>vert_coords: real[] ) + + +get_a_vert_coords( <>vert_gid: integer, <>vert_coords: real[] ) + +get_all_vert_coords( <>vert_coords: real[::] ) + +get_vert_coords<>: get_a_vert_coords(...), get_all_vert_coords(...) + +get_cell_coords( <>cell_gid: integer, <>cell_coords: real[] ) +get_vert_cell_owner( vert: integer ): integer +get_edge_cell_owner( <>edge: integer ): integer @@ -81,7 +91,7 @@ class global_mesh_mod::global_mesh_type { +is_coord_sys_ll(): logical +get_rim_depth(): integer - +get_domain_size(): integer + +get_domain_extents(): integer[2,4] +get_north_pole(): real[2] +get_null_island(): real[2] +get_equatorial_latitude(): real diff --git a/infrastructure/documentation/uml/mesh/local_mesh_collection_mod.iuml b/infrastructure/documentation/uml/mesh/local_mesh_collection_mod.iuml index 806d33601..dba964dee 100644 --- a/infrastructure/documentation/uml/mesh/local_mesh_collection_mod.iuml +++ b/infrastructure/documentation/uml/mesh/local_mesh_collection_mod.iuml @@ -11,6 +11,9 @@ class local_mesh_collection_mod::local_mesh_collection_type { +clear() +add_new_local_mesh(<>local_mesh_to_add: local_mesh_type ) : local_mesh_id <> + +n_meshes(): integer + +get_mesh_names(): string[:] <> + +check_for( <>mesh_name: string): logical ) +get_mesh_by_id( <>local_mesh_id: integer ): local_mesh_type <> +get_mesh_by_name( <>local_mesh_name: string ): local_mesh_type <> +get_local_mesh() <>: get_local_mesh_by_id(...), get_local_mesh_by_name(...) diff --git a/infrastructure/documentation/uml/mesh/local_mesh_mod.iuml b/infrastructure/documentation/uml/mesh/local_mesh_mod.iuml index d96f4c3b5..c2560e7af 100644 --- a/infrastructure/documentation/uml/mesh/local_mesh_mod.iuml +++ b/infrastructure/documentation/uml/mesh/local_mesh_mod.iuml @@ -5,10 +5,13 @@ class local_mesh_mod::local_mesh_type { -mesh_name: string + -origin_name: string + -origin_file: string -geometry: integer -topology: integer -coord_sys: integer -coord_units_xy: string[2] + -void_cell: integer -north_pole: real[2] -null_island: real[2] -equatorial_latitude: real @@ -42,16 +45,14 @@ class local_mesh_mod::local_mesh_type { -num_ghost: integer -last_ghost_cell: integer -max_stencil_depth: integer - -lbc_mesh: logical -ntarget_meshes: integer -target_mesh_names: string[:] <> -local_mesh_maps: local_mesh_map_collection_type <> - -npanels: integer -ncells_global_mesh: integer - -domain_size: real[2] + -domain_extents: real[2,4] -rim_depth: integer -constructor_inputs: string @@ -60,7 +61,7 @@ class local_mesh_mod::local_mesh_type { +initialise_full(<>global_mesh: global_mesh_type, <>partition: partition_type, <><>name: string) +initialise_lbc(\n\t<> global_lam_mesh: global_mesh_type,\n\t<> global_lbc_mesh: global_mesh_type,\n\t<> local_lam_mesh: local_mesh_type,\n\t<> name: string,\n\t<> cell_map: integer[:],\n\t<> edge_map: integer[:],\n\t<> vert_map: integer[:]) - +initialise_from_ugrid_data(<>ugrid_mesh_data: ugrid_mesh_data_type) + +initialise_from_ugrid_data(<>ugrid_mesh_data: ugrid_mesh_data_type, <>rename_to: string) +initialise_unit_test() +initialise() <>: initialise_full(...), initialise_lbc(...), initialise_from_ugrid_data, initialise_unit_test(...) +init_cell_owner() @@ -79,6 +80,8 @@ class local_mesh_mod::local_mesh_type { +get_equatorial_latitude(): real +get_mesh_name(): string + +get_origin_name(): string + +get_origin_file(): string +get_nverts_per_cell(): integer +get_nverts_per_edge(): integer +get_nedges_per_cell(): integer diff --git a/infrastructure/documentation/uml/mesh/ugrid_mesh_data_mod.iuml b/infrastructure/documentation/uml/mesh/ugrid_mesh_data_mod.iuml index 1c0d4a863..9ad1ad3ec 100644 --- a/infrastructure/documentation/uml/mesh/ugrid_mesh_data_mod.iuml +++ b/infrastructure/documentation/uml/mesh/ugrid_mesh_data_mod.iuml @@ -5,9 +5,9 @@ class ugrid_mesh_data_mod::ugrid_mesh_data_type { -global_mesh_name: string - + -origin_file: string + -origin_name: string -mesh_extents: integer - -is_local_mesh: logical -geometry: string -topology: string -coord_sys: string @@ -37,7 +37,7 @@ class ugrid_mesh_data_mod::ugrid_mesh_data_type { -null_island: real[2] -north_pole: real[2] -equatorial_latitude: real - -domain_size: real[2] + -domain_extents: real[2,4] -void_cell: integer -inner_depth: integer @@ -57,13 +57,15 @@ class ugrid_mesh_data_mod::ugrid_mesh_data_type { -node_on_cell_gid: integer[::] <> -edge_on_cell_gid: integer[::] <> + -populated_with_mesh: logical + +<> ugrid_mesh_data_destructor() +clear() +read_from_file(filename: string, global_mesh_name: string) +set_by_ugrid_2d(ugrid_2d: ugrid_2d_type) +is_local(): anwser: locgical - +get_data(\n\t mesh_name: string,\n\t geometry: string,\n\t topology: string,\n\t coord_sys: string,\n\t npanels: intger,\n\t nnode: integer,\n\t nedge: integer,\n\t nface: integer,\n\t nnodes_per_cell: integer,\n\t nnodes_per_edge: integer,\n\t nedges_per_face: integer,\n\t max_faces_per_node: integer,\n\t periodic_xy: logical[2],\n\t ntarget_meshes: integer,\n\t target_global_mesh_names: string[:] <>,\n\t node_coords: real[::] <>,\n\t face_coords: real[::] <>,\n\t coord_units_xy: string[2],\n\t north_pole: real[2],\n\t null_island: real[2],\n\t equatorial_latitude: real,\n\t constructor_inputs: string,\n\t rim_depth: integer,\n\t domain_size: real[2],\n\t void_cell: integer,\n\t face_next_2d: integer[::] <>,\n\t node_on_face_2d: integer[::] <>,\n\t edge_on_face_2d: integer[::] <>,\n\t max_stencil_depth: integer <> ) + +get_data(\n\t mesh_name: string,\n\t origin_file: string,\n\t geometry: string,\n\t topology: string,\n\t coord_sys: string,\n\t npanels: intger,\n\t nnode: integer,\n\t nedge: integer,\n\t nface: integer,\n\t nnodes_per_cell: integer,\n\t nnodes_per_edge: integer,\n\t nedges_per_face: integer,\n\t max_faces_per_node: integer,\n\t periodic_xy: logical[2],\n\t ntarget_meshes: integer,\n\t target_global_mesh_names: string[:] <>,\n\t node_coords: real[::] <>,\n\t face_coords: real[::] <>,\n\t coord_units_xy: string[2],\n\t north_pole: real[2],\n\t null_island: real[2],\n\t equatorial_latitude: real,\n\t constructor_inputs: string,\n\t rim_depth: integer,\n\t domain_size: real[2],\n\t void_cell: integer,\n\t face_next_2d: integer[::] <>,\n\t node_on_face_2d: integer[::] <>,\n\t edge_on_face_2d: integer[::] <>,\n\t max_stencil_depth: integer <> ) +get_partition_data(\n\t max_stencil_depth: integer,\n\t inner_depth: integer,\n\t halo_depth: integer,\n\t num_inner: integer[:] <>,\n\t num_edge: integer,\n\t num_halo: integer[:] <>,\n\t num_ghost: integer,\n\t last_inner_cell: integer[:] <>,\n\t last_edge_cell: integer,\n\t last_halo_cell: integer[:] <>,\n\t last_ghost_cell: integer,\n\t node_cell_owner: integer[:] <>,\n\t edge_cell_owner: integer[:] <>,\n\t num_faces_global: integer,\n\t cell_gid: integer[:] <>,\n\t node_on_cell_gid: integer[::] <>,\n\t edge_on_cell_gid: integer[::]) diff --git a/infrastructure/source/function_space/function_space_collection_mod.F90 b/infrastructure/source/function_space/function_space_collection_mod.F90 index 2e2214282..58088c3c4 100644 --- a/infrastructure/source/function_space/function_space_collection_mod.F90 +++ b/infrastructure/source/function_space/function_space_collection_mod.F90 @@ -226,7 +226,7 @@ end subroutine function_space_collection_destructor ! with the given properties and return a pointer to it. A null pointer is ! returned if the requested function space does not exist. ! - !> @param[in] mesh_id ID of mesh object + !> @param[in] mesh Mesh object !> @param[in] element_order_h function space order in horizontal !> @param[in] element_order_v function space order in vertical !> @param[in] lfric_fs lfric id code for given supported function space diff --git a/infrastructure/source/io/ugrid_2d_mod.F90 b/infrastructure/source/io/ugrid_2d_mod.F90 index 7d147ebf5..57913cdc2 100644 --- a/infrastructure/source/io/ugrid_2d_mod.F90 +++ b/infrastructure/source/io/ugrid_2d_mod.F90 @@ -16,7 +16,6 @@ module ugrid_2d_mod use file_mod, only: file_mode_write use ugrid_file_mod, only: ugrid_file_type - use local_mesh_map_collection_mod, only: local_mesh_map_collection_type use global_mesh_map_collection_mod, only: global_mesh_map_collection_type @@ -1623,7 +1622,10 @@ subroutine clear(self) if (allocated(self%file_handler)) deallocate( self%file_handler ) - self%mesh_name = cmdi + self%mesh_name = cmdi + self%origin_name = cmdi + self%origin_file = cmdi + self%geometry = cmdi self%topology = cmdi self%coord_sys = cmdi @@ -1688,6 +1690,11 @@ function is_local(self) result(answer) end function is_local +!------------------------------------------------------------------------------ +!> @brief Returns original mesh name as referenced in the orignal source file. +!> @return origin_name Tag name of mesh that identifies it in the +!> UGRID file that it was read in from. +! function get_origin_name( self ) result ( origin_name ) implicit none @@ -1700,6 +1707,10 @@ function get_origin_name( self ) result ( origin_name ) end function get_origin_name +!--------------------------------------------------------------------------- +!> @brief Returns name of source file from which the mesh data was read. +!> @return origin_file Filename of UGRID file that mesh data was read from. +! function get_origin_file( self ) result ( origin_file ) implicit none diff --git a/infrastructure/source/mesh/global_mesh_collection_mod.F90 b/infrastructure/source/mesh/global_mesh_collection_mod.F90 index a5410f61d..1c033b753 100644 --- a/infrastructure/source/mesh/global_mesh_collection_mod.F90 +++ b/infrastructure/source/mesh/global_mesh_collection_mod.F90 @@ -170,7 +170,7 @@ end subroutine add_new_global_mesh !> @detail This function returns the number of unique mesh !> tag names in this collection. !> - !> @return Number of mesh tag names avaible to query. + !> @return Number of mesh tag names available to query. !> function n_meshes(self) result(number_of_meshes) diff --git a/infrastructure/source/mesh/global_mesh_mod.F90 b/infrastructure/source/mesh/global_mesh_mod.F90 index 7d6ee8934..e40626a49 100644 --- a/infrastructure/source/mesh/global_mesh_mod.F90 +++ b/infrastructure/source/mesh/global_mesh_mod.F90 @@ -47,10 +47,13 @@ module global_mesh_mod ! Mesh metadata information. !====================================================== ! Tag name of mesh. - character(str_def) :: mesh_name + character(str_def) :: mesh_name = cmdi + ! Source file containing original data character(str_max_filename) :: origin_file = cmdi - character(str_def) :: origin_name = cmdi + + ! Original mesh name referenced in source file + character(str_def) :: origin_name = cmdi ! Flag to indicate if this a mesh represents coverage ! of a global model. @@ -251,17 +254,19 @@ module global_mesh_mod contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !> @brief Constructs a global mesh object from mesh file and reference - !> element. + !> @brief Constructs a global mesh object. !> - !> This global mesh object holds the connectivities which fully describe - !> the 2D topology of the mesh. + !> @description This global mesh object holds the connectivities + !> which fully describe the 2D topology of the mesh. !> - !> @param[in] filename Filename for global 2D mesh(es) ugrid file. - !> @param[in] global_mesh_name Name of ugrid mesh topology to create - !> global mesh object from. + !> @param[in] ugrid_mesh_data Ugrid data object to construct global + !> mesh object from. + !> @param[in] rename_to [optional] Name used to identify + !> the instance of the global_mesh_object. + !> If omitted, the name is inherited from + !> the ugrid_mesh_data object. !> - !> @return Freshly minted global_mesh_type object. + !> @return global_mesh_type object !> function global_mesh_constructor( ugrid_mesh_data, rename_to ) result(self) @@ -909,7 +914,7 @@ end function is_coord_sys_ll !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !> @brief Returns mesh tag name. !> @return mesh_name Tag name of mesh that identifies it in the - !> UGRID file that it was read in from. + !> application. !> function get_mesh_name( self ) result ( mesh_name ) @@ -923,6 +928,12 @@ function get_mesh_name( self ) result ( mesh_name ) end function get_mesh_name + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !> @brief Returns original mesh name as referenced in the orignal source file. + !> @return origin_name Tag name of mesh that identifies it in the + !> UGRID file that it was read in from. + !> function get_origin_name( self ) result ( origin_name ) implicit none @@ -935,6 +946,11 @@ function get_origin_name( self ) result ( origin_name ) end function get_origin_name + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !> @brief Returns name of source file from which the mesh data was read. + !> @return origin_file Filename of UGRID file that mesh data was read from. + !> function get_origin_file( self ) result ( origin_file ) implicit none @@ -948,8 +964,6 @@ function get_origin_file( self ) result ( origin_file ) end function get_origin_file - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !> @brief Returns values for the X and Y periodicity. !> @@ -964,6 +978,7 @@ end function get_origin_file !> @return periodic_xy Mesh domain periodicity in x/y-axes. !> function get_mesh_periodicity( self ) result ( periodic_xy ) + implicit none class(global_mesh_type), intent(in) :: self diff --git a/infrastructure/source/mesh/local_mesh_collection_mod.f90 b/infrastructure/source/mesh/local_mesh_collection_mod.f90 index 9e9e33a05..8bff40fac 100644 --- a/infrastructure/source/mesh/local_mesh_collection_mod.f90 +++ b/infrastructure/source/mesh/local_mesh_collection_mod.f90 @@ -28,12 +28,14 @@ module local_mesh_collection_mod type(linked_list_type) :: local_mesh_list contains procedure, public :: add_new_local_mesh + + procedure, public :: n_meshes + procedure, public :: get_mesh_names + procedure, public :: get_mesh_by_name procedure, public :: get_mesh_by_id generic, public :: get_local_mesh => get_mesh_by_id, & get_mesh_by_name - procedure, public :: get_mesh_names - procedure, public :: n_meshes procedure, public :: check_for procedure, public :: clear @@ -106,6 +108,27 @@ function add_new_local_mesh( self, local_mesh_to_add ) result( local_mesh_id ) end function add_new_local_mesh + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !> @brief Returns the number of meshes in collection. + !> + !> @detail This function returns the number of unique mesh + !> tag names in this collection. + !> + !> @return Number of mesh tag names available to query. + !> + function n_meshes(self) result(number_of_meshes) + + implicit none + + class(local_mesh_collection_type), intent(in) :: self + + integer(i_def) :: number_of_meshes + + number_of_meshes = self%local_mesh_list%get_length() + + return + end function n_meshes + !=========================================================================== !> @brief Returns mesh tag names of mesh objects in the collection. @@ -225,18 +248,7 @@ end function get_mesh_by_name - function n_meshes(self) result(number_of_meshes) - - implicit none - class(local_mesh_collection_type), intent(in) :: self - - integer(i_def) :: number_of_meshes - - number_of_meshes = self%local_mesh_list%get_length() - - return - end function n_meshes !=========================================================================== diff --git a/infrastructure/source/mesh/local_mesh_mod.f90 b/infrastructure/source/mesh/local_mesh_mod.f90 index a2e0fb288..ac5dc67ab 100644 --- a/infrastructure/source/mesh/local_mesh_mod.f90 +++ b/infrastructure/source/mesh/local_mesh_mod.f90 @@ -51,11 +51,11 @@ module local_mesh_mod ! Variables referring to local mesh !==================================== ! Tag name of mesh. - character(str_def) :: mesh_name - + character(str_def) :: mesh_name = cmdi + ! Source file containing original data character(str_max_filename) :: origin_file = cmdi - character(str_def) :: origin_name = cmdi - + ! Original mesh name referenced in source file + character(str_def) :: origin_name = cmdi ! Domain surface geometry. integer(i_def) :: geometry = emdi ! Domain boundaries topology. @@ -1139,8 +1139,12 @@ end subroutine initialise_lbc !> @details Direct initialisation from a allows a local !> mesh object to be populated directly from file read. !> - !> @param [in] ugrid_mesh_data which was populated - !> directly from file read + !> @param [in] ugrid_mesh_data Ugrid data object to construct local + !> mesh object from. + !> @param[in] rename_to [optional] Name used to identify + !> the instance of the local_mesh_object. + !> If omitted, the name is inherited from + !> the ugrid_mesh_data object. !> subroutine initialise_from_ugrid_data(self, ugrid_mesh_data, rename_to) @@ -1568,7 +1572,9 @@ end subroutine clear !> @return mesh_name Tag name of mesh. !> function get_mesh_name( self ) result ( mesh_name ) + implicit none + class(local_mesh_type), intent(in) :: self character(str_def) :: mesh_name @@ -1576,17 +1582,16 @@ function get_mesh_name( self ) result ( mesh_name ) end function get_mesh_name - function get_origin_file( self ) result ( origin_file ) - implicit none - class(local_mesh_type), intent(in) :: self - character(str_max_filename) :: origin_file - - origin_file = self%origin_file - - end function get_origin_file + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !> @brief Returns original mesh name as referenced in the orignal source file. + !> @return origin_name Tag name of mesh that identifies it in the + !> UGRID file that it was read in from. + !> function get_origin_name( self ) result ( origin_name ) + implicit none + class(local_mesh_type), intent(in) :: self character(str_def) :: origin_name @@ -1594,6 +1599,23 @@ function get_origin_name( self ) result ( origin_name ) end function get_origin_name + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !> @brief Returns name of source file from which the mesh data was read. + !> @return origin_file Filename of UGRID file that mesh data was read from. + !> + function get_origin_file( self ) result ( origin_file ) + + implicit none + + class(local_mesh_type), intent(in) :: self + character(str_max_filename) :: origin_file + + origin_file = self%origin_file + + end function get_origin_file + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !> @brief Returns the north pole location of mesh. !> @details A mesh may have been transformed before being written to file. diff --git a/infrastructure/source/mesh/panel_decomposition_mod.f90 b/infrastructure/source/mesh/panel_decomposition_mod.f90 index 847e51c65..979fcc312 100644 --- a/infrastructure/source/mesh/panel_decomposition_mod.f90 +++ b/infrastructure/source/mesh/panel_decomposition_mod.f90 @@ -12,7 +12,7 @@ module panel_decomposition_mod use global_mesh_collection_mod, only: global_mesh_collection_type use constants_mod, only: i_def, l_def, r_def, str_def use log_mod, only: log_event, log_scratch_space, & - LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG + log_level_error, log_level_debug implicit none @@ -125,6 +125,7 @@ end function get_nprocs_interface end interface + ! Overload call to calculation of mapping factor interface calc_mapping_factor module procedure calc_mapping_factor_multiple module procedure calc_mapping_factor_single @@ -171,7 +172,7 @@ subroutine get_custom_partition( self, & integer(i_def) :: num_xprocs, num_yprocs - call log_event("Using custom decomposition", LOG_LEVEL_INFO) + call log_event("using custom decomposition", log_level_debug) num_xprocs = self%num_xprocs num_yprocs = self%num_yprocs @@ -181,7 +182,7 @@ subroutine get_custom_partition( self, & "Total ranks per panel ", panel_ranks, & " must be the product of xprocs ", self%num_xprocs, & " and yprocs ", self%num_yprocs - call log_event( log_scratch_space, LOG_LEVEL_ERROR ) + call log_event( log_scratch_space, log_level_error ) end if @@ -207,7 +208,7 @@ subroutine get_custom_partition( self, & " partition_y_pos ", partition_y_pos, & " partition_width ", partition_width, & " partition_height ", partition_height - call log_event(log_scratch_space, LOG_LEVEL_DEBUG) + call log_event(log_scratch_space, log_level_debug) end subroutine get_custom_partition @@ -284,7 +285,7 @@ subroutine get_auto_partition( self, & integer(i_def) :: start_xprocs, start_width, i logical :: found_partition - call log_event("Using auto decomposition", LOG_LEVEL_INFO) + call log_event("Using auto decomposition", log_level_debug) ! For automatic partitioning, try to partition into the squarest ! possible partitions. @@ -340,7 +341,7 @@ subroutine get_auto_partition( self, & end do if (.not. found_partition) call log_event( & - "Could not automatically partition domain.", LOG_LEVEL_ERROR ) + "Could not automatically partition domain.", log_level_error ) call xy_defensive_checks( num_cells_x, & num_cells_y, & @@ -364,7 +365,7 @@ subroutine get_auto_partition( self, & " partition_y_pos ", partition_y_pos, & " partition_width ", partition_width, & " partition_height ", partition_height - call log_event(log_scratch_space, LOG_LEVEL_DEBUG) + call log_event(log_scratch_space, log_level_debug) end subroutine get_auto_partition @@ -426,7 +427,7 @@ subroutine get_row_partition( self, & integer(i_def) :: num_xprocs, num_yprocs - call log_event("Using row decomposition", LOG_LEVEL_INFO) + call log_event("Using row decomposition", log_level_debug) num_xprocs = panel_ranks num_yprocs = 1_i_def @@ -453,7 +454,7 @@ subroutine get_row_partition( self, & " partition_y_pos ", partition_y_pos, & " partition_width ", partition_width, & " partition_height ", partition_height - call log_event(log_scratch_space, LOG_LEVEL_DEBUG) + call log_event(log_scratch_space, log_level_debug) end subroutine get_row_partition @@ -515,7 +516,7 @@ subroutine get_column_partition( self, & integer(i_def) :: num_xprocs, num_yprocs - call log_event("Using column decomposiiton", LOG_LEVEL_INFO) + call log_event("Using column decomposiiton", log_level_debug) num_xprocs = 1_i_def num_yprocs = panel_ranks @@ -542,7 +543,7 @@ subroutine get_column_partition( self, & " partition_y_pos ", partition_y_pos, & " partition_width ", partition_width, & " partition_height ", partition_height - call log_event(log_scratch_space, LOG_LEVEL_DEBUG) + call log_event(log_scratch_space, log_level_debug) end subroutine get_column_partition @@ -606,7 +607,7 @@ subroutine get_auto_nonuniform_partition( self, & integer(i_def) :: start_xprocs, start_width, i logical ::found_factors - call log_event("Using auto_nonuniform decomposition", LOG_LEVEL_INFO) + call log_event("Using auto_nonuniform decomposition", log_level_debug) mp_num_cells_x = num_cells_x / mapping_factor mp_num_cells_y = num_cells_y / mapping_factor @@ -641,7 +642,7 @@ subroutine get_auto_nonuniform_partition( self, & end do if (.not. found_factors) call log_event( & - "Could not automatically partition domain.", LOG_LEVEL_ERROR ) + "Could not automatically partition domain.", log_level_error ) call nonuniform_decomposition(relative_rank, & panel_ranks, & @@ -659,7 +660,7 @@ subroutine get_auto_nonuniform_partition( self, & " partition_y_pos ", partition_y_pos, & " partition_width ", partition_width, & " partition_height ", partition_height - call log_event(log_scratch_space, LOG_LEVEL_DEBUG) + call log_event(log_scratch_space, log_level_debug) end subroutine get_auto_nonuniform_partition @@ -721,27 +722,27 @@ subroutine get_guided_nonuniform_partition( self, & integer(i_def) :: num_xprocs - call log_event("Using guided_nonuniform decomposition", LOG_LEVEL_INFO) + call log_event("Using guided_nonuniform decomposition", log_level_debug) num_xprocs = self%num_xprocs ! Defensive checks if ( num_xprocs <= 0 ) then call log_event( "Number of x processes must be strictly positive.", & - LOG_LEVEL_ERROR ) + log_level_error ) end if if ( num_cells_x < num_xprocs ) then write(log_scratch_space, '(A)') & "Must have more cells than partitions in x direction." - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if if ( check_constraints .and. ( mod(num_cells_x, num_xprocs) /= 0 ) ) then write(log_scratch_space, '(2(A,I0))') & "Requested number of ranks in x direction ", num_xprocs, & " must divide panel x dimension ", num_cells_x - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if call nonuniform_decomposition(relative_rank, & @@ -760,7 +761,7 @@ subroutine get_guided_nonuniform_partition( self, & " partition_y_pos ", partition_y_pos, & " partition_width ", partition_width, & " partition_height ", partition_height - call log_event(log_scratch_space, LOG_LEVEL_DEBUG) + call log_event(log_scratch_space, log_level_debug) end subroutine get_guided_nonuniform_partition @@ -871,21 +872,21 @@ subroutine xy_defensive_checks( num_cells_x, & write(log_scratch_space, "(a,i0,a,i0,a)") & "Number of x processes ", num_xprocs, " and y processes ", num_yprocs, & " must both be strictly positive." - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if if ( num_cells_x < num_xprocs ) then write(log_scratch_space, "(a,i0,a,i0)") & "Number of cells in x direction ", num_cells_x, & " must be greater than number of processes in x direction ", num_xprocs - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if if ( num_cells_y < num_yprocs ) then write(log_scratch_space, "(a,i0,a,i0)") & "Number of cells in y direction ", num_cells_y, & " must be greater than number of processes in y direction ", num_yprocs - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if ! Equal divisions are only required if there are maps between meshes @@ -895,14 +896,14 @@ subroutine xy_defensive_checks( num_cells_x, & write(log_scratch_space, "(2(A,I0))") & "Requested number of ranks in x direction ", num_xprocs, & " must divide panel x dimension ", num_cells_x - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if if ( mod(num_cells_y, num_yprocs) /= 0 ) then write(log_scratch_space, "(2(A,I0))") & "Requested number of ranks in y direction ", num_yprocs, & " must divide panel y dimension ", num_cells_y - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if end if @@ -910,7 +911,7 @@ subroutine xy_defensive_checks( num_cells_x, & write(log_scratch_space, "(2(A,I0))") & "Requested number of partitions ", num_xprocs * num_yprocs, & " must equal available number of ranks per panel ", panel_ranks - call log_event(log_scratch_space, LOG_LEVEL_ERROR) + call log_event(log_scratch_space, log_level_error) end if end subroutine xy_defensive_checks @@ -986,10 +987,11 @@ subroutine nonuniform_decomposition( relative_rank, & end subroutine nonuniform_decomposition - !> @brief Calculate the ratio in resolution between this and the coarsest mesh - !> to align partitions for mapped grids - !> @param[in] global-mesh_collection The global mesh collection - !> @param[in] global_mesh The global mesh to calculate the factor for + !> @brief Calculate the ratio in resolution between a given global mesh and + !> all meshes in a given global_mesh_collection to align partitions + !> for mapped grids + !> @param[in] global_mesh Global mesh to calculate the factor for + !> @param[in] global_mesh_collection Global mesh collection with reference meshes. function calc_mapping_factor_multiple( global_mesh, & global_mesh_collection ) result(mp) @@ -1025,7 +1027,7 @@ function calc_mapping_factor_multiple( global_mesh, & end do - ! If no meshes were found, or + ! If no meshes were found, or ! if this_panel_width < shortest_panel_width, then return 1. if ( shortest_panel_width < huge(0_i_def) ) then mp = max(1, panel_width / shortest_panel_width) @@ -1036,6 +1038,10 @@ function calc_mapping_factor_multiple( global_mesh, & end function calc_mapping_factor_multiple + !> @brief Calculate the ratio in resolution between a global mesh object and + !> another used as reference to align partitions for mapped grids. + !> @param[in] global_mesh Global mesh to calculate the factor for + !> @param[in] reference_global_mesh Reference global mesh object function calc_mapping_factor_single( global_mesh, reference_global_mesh ) result(mp) implicit none @@ -1064,8 +1070,6 @@ function calc_mapping_factor_single( global_mesh, reference_global_mesh ) result end function calc_mapping_factor_single - - !> @brief Calculate the width of the mesh panel. On a spherical mesh this is !> the C number. !> @param[in] gloabl_mesh The mesh to calculate the panel width of diff --git a/infrastructure/source/mesh/partition_mod.F90 b/infrastructure/source/mesh/partition_mod.F90 index ba5ab1c11..e75f291a0 100644 --- a/infrastructure/source/mesh/partition_mod.F90 +++ b/infrastructure/source/mesh/partition_mod.F90 @@ -975,8 +975,9 @@ subroutine partitioner_rectangular_panels( global_mesh, & " num_x ", num_x, & " num_y ", num_y call log_event( log_scratch_space, LOG_LEVEL_DEBUG ) - write(log_scratch_space,"(a,i0,a,i0)") "Number of cells in partition ", num_x, " X ", num_y - call log_event( log_scratch_space, lOG_LEVEL_INFO ) + write(log_scratch_space,"(a,i0,a,i0)") & + "Number of cells in partition ", num_x, " X ", num_y + call log_event( log_scratch_space, lOG_LEVEL_DEBUG ) ! Create a linked list of all cells in the partition and at the same time ! create a linked-list of all edge cells known to the partition, excluding halos. diff --git a/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 b/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 index a0679651f..4360ad3b5 100644 --- a/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 +++ b/infrastructure/source/mesh/ugrid_mesh_data_mod.f90 @@ -29,14 +29,14 @@ module ugrid_mesh_data_mod type, public :: ugrid_mesh_data_type !> Name of ugrid mesh topology. - character(str_def) :: global_mesh_name - - character(str_max_filename) :: origin_file - character(str_def) :: origin_name - - integer(i_def) :: mesh_extents - logical(l_def) :: is_local_mesh - + character(str_def) :: global_mesh_name = cmdi + !> Source file containing original data + character(str_max_filename) :: origin_file = cmdi + !> Original mesh name referenced in source file + character(str_def) :: origin_name = cmdi + !> Enumeration indicating whether the mesh extends across + !> the global model on across a local partition. + integer(i_def) :: mesh_extents !> Domain geometry of global mesh. character(str_def) :: geometry !> Topology of mesh. @@ -222,14 +222,15 @@ end subroutine read_from_file !> @brief Provides access to the data within the ugrid_mesh_data object - that !> can be used to construct a global mesh object. !> - !> @param[out] mesh_name Name of ugrid mesh topology. - !> @param[out] geometry Domain surface geometry. - !> @param[out] topology Domain topology. - !> @param[out] coord_sys Coordinate system used to position nodes. - !> @param[out] npanels Number of groups of uniform cell orientations on global mesh. - !> @param[out] nnode Total number of nodes in the full domain. - !> @param[out] nedge Total number of edges in the full domain. - !> @param[out] nface Total number of faces in full domain. + !> @param[out] mesh_name Name of ugrid mesh topology. + !> @param[out] origin_file File the mesh data was sourced from. + !> @param[out] geometry Domain surface geometry. + !> @param[out] topology Domain topology. + !> @param[out] coord_sys Coordinate system used to position nodes. + !> @param[out] npanels Number of groups of uniform cell orientations on global mesh. + !> @param[out] nnode Total number of nodes in the full domain. + !> @param[out] nedge Total number of edges in the full domain. + !> @param[out] nface Total number of faces in full domain. !> @param[out] nnodes_per_face Number of nodes on each face. !> @param[out] nnodes_per_edge Number of nodes on each edge. !> @param[out] nedges_per_face Number of edges on each cell. @@ -254,16 +255,16 @@ end subroutine read_from_file !> @param[out] node_on_edge_2d Full domain nodes on an edge. !> @param[out] max_stencil_depth Max stencil depth supported by this mesh. !> - subroutine get_data( self, & - mesh_name, & - origin, & - geometry, & - topology, & - coord_sys, & - npanels, & - nnode, & - nedge, & - nface, & + subroutine get_data( self, & + mesh_name, & + origin_file, & + geometry, & + topology, & + coord_sys, & + npanels, & + nnode, & + nedge, & + nface, & nnodes_per_face, & nnodes_per_edge, & nedges_per_face, & @@ -295,7 +296,7 @@ subroutine get_data( self, & character(str_def), intent(out) :: topology character(str_def), intent(out) :: coord_sys - character(str_max_filename), intent(out) :: origin + character(str_max_filename), intent(out) :: origin_file integer(i_def), intent(out) :: nnode integer(i_def), intent(out) :: nedge @@ -332,12 +333,12 @@ subroutine get_data( self, & ! Only valid if the ugrid file contains a local mesh integer(i_def), optional, intent(out) :: max_stencil_depth - mesh_name = self%global_mesh_name - origin = self%origin_file - geometry = self%geometry - topology = self%topology - coord_sys = self%coord_sys - npanels = self%npanels + mesh_name = self%global_mesh_name + origin_file = self%origin_file + geometry = self%geometry + topology = self%topology + coord_sys = self%coord_sys + npanels = self%npanels nnode = self%nnode nedge = self%nedge diff --git a/infrastructure/unit-test/function_space/function_space_mod_test.pf b/infrastructure/unit-test/function_space/function_space_mod_test.pf index 9b35d7b50..29a0d4faa 100644 --- a/infrastructure/unit-test/function_space/function_space_mod_test.pf +++ b/infrastructure/unit-test/function_space/function_space_mod_test.pf @@ -121,7 +121,7 @@ module function_space_mod_test logical(l_def) :: test_dofmap type(local_mesh_type) :: unit_test_local_mesh - integer(i_def) :: mesh_id + type(mesh_type), pointer :: mesh real(r_def), allocatable :: test_diff_basis(:,:,:,:) real(r_def), allocatable :: test_basis(:,:,:,:) contains @@ -232,7 +232,7 @@ contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine setUp( this ) - use mesh_mod, only : mesh_type, PLANE_BI_PERIODIC + use mesh_mod, only: mesh_type, PLANE_BI_PERIODIC implicit none @@ -241,6 +241,7 @@ contains type(local_mesh_type), pointer :: unit_test_local_mesh_ptr type(mesh_type) :: unit_test_mesh type(lfric_comm_type) :: lfric_comm + integer(i_def) :: mesh_id call lfric_comm%set_comm_mpi_val(this%getMpiCommunicator()) @@ -255,7 +256,8 @@ contains ! Dummy mesh mod has 9 cells, 3 layers and is uniform in vertical unit_test_mesh = mesh_type( PLANE_BI_PERIODIC, unit_test_local_mesh_ptr ) - this%mesh_id = mesh_collection%add_new_mesh( unit_test_mesh ) + mesh_id = mesh_collection%add_new_mesh( unit_test_mesh ) + this%mesh => mesh_collection%get_mesh( mesh_id ) end subroutine setUp @@ -325,8 +327,6 @@ contains integer(i_def) :: known_global_edge_dof_id_2d(18) integer(i_def) :: known_global_vert_dof_id_2d(9) - integer(i_def) :: i - integer(i_def) :: nqp_h integer(i_def) :: nqp_v @@ -423,7 +423,7 @@ contains basis_diff_function => fs2htk0_basis_diff_function end select - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -509,7 +509,8 @@ contains ! Now test multidata function spaces ndat = 4 - test_fs = function_space_type( this%mesh_id, & + + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space, & @@ -550,7 +551,7 @@ contains integer(i_def) :: cell_counter,dof_counter logical :: identical - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -593,7 +594,7 @@ contains integer(i_def), pointer :: stencil_map(:,:) => null() integer(i_def), pointer :: map(:) => null() - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -620,12 +621,11 @@ contains type(function_space_type) :: test_fs - type(stencil_dofmap_type), pointer :: stencil_dofmap => null() - integer(i_def), pointer :: stencil_map(:,:) => null() - integer(i_def), pointer :: map(:) => null() - type(mesh_type), pointer :: mesh => null() + type(stencil_dofmap_type), pointer :: stencil_dofmap + integer(i_def), pointer :: stencil_map(:,:) + integer(i_def), pointer :: map(:) - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -633,17 +633,15 @@ contains stencil_dofmap => test_fs%get_stencil_dofmap( STENCIL_1DX, 1 ) stencil_map => stencil_dofmap%get_dofmap( 1 ) - mesh =>mesh_collection%get_mesh(this%mesh_id) - map => test_fs%get_cell_dofmap(1) @assertEqual( map, stencil_map(:,1) ) - map => test_fs%get_cell_dofmap(mesh%get_cell_next( W, 1 )) + map => test_fs%get_cell_dofmap(this%mesh%get_cell_next( W, 1 )) @assertEqual( map, stencil_map(:,2) ) - map => test_fs%get_cell_dofmap(mesh%get_cell_next( E, 1 )) + map => test_fs%get_cell_dofmap(this%mesh%get_cell_next( E, 1 )) @assertEqual( map, stencil_map(:,3) ) call test_fs%clear() - nullify( stencil_dofmap, stencil_map, map, mesh ) + nullify( stencil_dofmap, stencil_map, map ) end subroutine test_stencil_1dx @@ -659,12 +657,11 @@ contains type(function_space_type) :: test_fs - type(stencil_dofmap_type), pointer :: stencil_dofmap => null() - integer(i_def), pointer :: stencil_map(:,:) => null() - integer(i_def), pointer :: map(:) => null() - type(mesh_type), pointer :: mesh => null() + type(stencil_dofmap_type), pointer :: stencil_dofmap + integer(i_def), pointer :: stencil_map(:,:) + integer(i_def), pointer :: map(:) - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -672,17 +669,16 @@ contains stencil_dofmap => test_fs%get_stencil_dofmap( STENCIL_1DY, 1 ) stencil_map => stencil_dofmap%get_dofmap(1) - mesh =>mesh_collection%get_mesh(this%mesh_id) - map => test_fs%get_cell_dofmap(1) @assertEqual( map, stencil_map(:,1) ) - map => test_fs%get_cell_dofmap(mesh%get_cell_next( S, 1 )) + map => test_fs%get_cell_dofmap(this%mesh%get_cell_next( S, 1 )) @assertEqual( map, stencil_map(:,2) ) - map => test_fs%get_cell_dofmap(mesh%get_cell_next( N, 1 )) + map => test_fs%get_cell_dofmap(this%mesh%get_cell_next( N, 1 )) @assertEqual( map, stencil_map(:,3) ) call test_fs%clear() - nullify( stencil_dofmap, stencil_map, map, mesh ) + + nullify( stencil_dofmap, stencil_map, map ) end subroutine test_stencil_1dy @@ -698,14 +694,13 @@ contains type(function_space_type) :: test_fs - type(stencil_dofmap_type), pointer :: stencil_dofmap => null() - integer(i_def), pointer :: stencil_map(:,:) => null() - integer(i_def), pointer :: map(:) => null() - type(mesh_type), pointer :: mesh => null() + type(stencil_dofmap_type), pointer :: stencil_dofmap + integer(i_def), pointer :: stencil_map(:,:) + integer(i_def), pointer :: map(:) integer :: i - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -713,17 +708,15 @@ contains stencil_dofmap => test_fs%get_stencil_dofmap(STENCIL_CROSS,1) stencil_map => stencil_dofmap%get_dofmap(1) - mesh =>mesh_collection%get_mesh(this%mesh_id) - map => test_fs%get_cell_dofmap(1) @assertEqual( map, stencil_map(:,1) ) do i = 1,4 - map => test_fs%get_cell_dofmap(mesh%get_cell_next(i,1)) + map => test_fs%get_cell_dofmap(this%mesh%get_cell_next(i,1)) @assertEqual( map, stencil_map(:,i+1) ) end do call test_fs%clear() - nullify( stencil_dofmap, stencil_map, map, mesh ) + nullify( stencil_dofmap, stencil_map, map ) end subroutine test_stencil_cross @@ -736,9 +729,9 @@ contains class(test_function_space_type), intent(inout) :: this type(function_space_type) :: test_fs - type(mesh_type), pointer :: mesh_out => null() + type(mesh_type), pointer :: mesh_out - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -774,16 +767,15 @@ contains class(test_function_space_type), intent(inout) :: this - type(function_space_type) :: test_fs - type(mesh_type), pointer :: mesh => null() - integer(i_def), pointer :: entity_dofs(:) => null() + type(function_space_type) :: test_fs + integer(i_def), pointer :: entity_dofs(:) integer(i_def) :: reference(this%ndof_cell) integer(i_def) :: edge_array(12) integer(i_def) :: face_array(6) integer(i_def) :: vert_array(8) integer(i_def) :: ndf, k_h, k_v, idx1, idx2 - integer(i_def) :: edge, face, vert + integer(i_def) :: edge, face integer(i_def) :: ndof_vol, & ndof_face_h, ndof_face_v, & ndof_edge_h, ndof_edge_v, & @@ -805,7 +797,7 @@ contains vert_array = (/ SWB, SEB, NEB, NWB, SWT, SET, NET, NWT /) reference(:) = 0 - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -1005,13 +997,10 @@ contains end select - mesh => mesh_collection%get_mesh( this%mesh_id ) entity_dofs => test_fs%get_entity_dofs() - @assertEqual( entity_dofs(1:test_fs%get_ndf()), reference(1:ndf) ) call test_fs%clear() - nullify( mesh ) end subroutine test_entities @@ -1027,7 +1016,7 @@ contains integer(i_def) :: undf, last_dof_annexed, last_dof_owned, last_dof_halo - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) @@ -1089,7 +1078,7 @@ contains is_writable_expected=.false. end if - test_fs = function_space_type( this%mesh_id, & + test_fs = function_space_type( this%mesh, & this%element_order_h, & this%element_order_v, & this%function_space ) diff --git a/infrastructure/unit-test/mesh/global_mesh_mod_test.pf b/infrastructure/unit-test/mesh/global_mesh_mod_test.pf index d4654bca6..f2bdaef70 100644 --- a/infrastructure/unit-test/mesh/global_mesh_mod_test.pf +++ b/infrastructure/unit-test/mesh/global_mesh_mod_test.pf @@ -22,61 +22,44 @@ module global_mesh_mod_test implicit none private + + public :: set_up, tear_down public :: test_cubedsphere_global_mesh, & test_cubedsphere_single_file_intergrid, & test_cubedsphere_adding_intergrid_map, & - test_biperiodic_global_mesh, & - setUp, tearDown - - @testCase - type, public, extends( TestCase ) :: global_mesh_test_type - private - contains - private - procedure, public :: setUp - procedure, public :: tearDown - procedure, public :: test_cubedsphere_global_mesh - procedure, public :: test_biperiodic_global_mesh - procedure, public :: test_cubedsphere_single_file_intergrid - procedure, public :: test_cubedsphere_adding_intergrid_map - - end type global_mesh_test_type + test_biperiodic_global_mesh character(str_def), parameter :: mesh_name = 'unit_test' integer(i_def), parameter :: npanels = 6 contains - subroutine setUp( this ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + @before + subroutine set_up() implicit none - class( global_mesh_test_type ), intent( inout ) :: this - - ! Create top level collections global_mesh_collection = global_mesh_collection_type() - end subroutine setUp + end subroutine set_up - subroutine tearDown( this ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + @after + subroutine tear_down() implicit none - class( global_mesh_test_type ), intent( inout ) :: this - call global_mesh_collection%clear() - end subroutine tearDown + end subroutine tear_down - ! Test global_mesh module functionality - ! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @test - subroutine test_biperiodic_global_mesh( this ) + subroutine test_biperiodic_global_mesh() implicit none - class( global_mesh_test_type ), intent( inout ) :: this - type(ugrid_mesh_data_type) :: ugrid_mesh_data type(global_mesh_type) :: global_mesh @@ -103,12 +86,12 @@ contains !------------------------------------- ! Test construction of a biperiodic mesh !------------------------------------- - filename = 'data/mesh_BiP8x8-750x250.nc' call ugrid_mesh_data%read_from_file(trim(filename), mesh_name) global_mesh = global_mesh_type( ugrid_mesh_data ) call ugrid_mesh_data%clear() + ! Check the global mesh id global_mesh_id1 = global_mesh%get_id() @assertTrue(global_mesh_id1 > 0) @@ -230,13 +213,12 @@ contains end subroutine test_biperiodic_global_mesh + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @test - subroutine test_cubedsphere_global_mesh( this ) + subroutine test_cubedsphere_global_mesh() implicit none - class( global_mesh_test_type ), intent( inout ) :: this - type(ugrid_mesh_data_type) :: ugrid_mesh_data type(global_mesh_type) :: global_mesh character(len = str_max_filename) :: filename @@ -259,18 +241,32 @@ contains real(r_def) :: cell_coords(2) real(r_def) :: vert_coords(2) + character(str_max_filename) :: test_str1 + character(str_def) :: test_str2 + + character(str_def), parameter :: new_name = 'mesh_under_test' + !--------------------------------------- ! Test construction of a cubed-sphere mesh !--------------------------------------- filename = 'data/mesh_C4.nc' call ugrid_mesh_data%read_from_file(trim(filename), mesh_name) - global_mesh = global_mesh_type( ugrid_mesh_data ) + global_mesh = global_mesh_type( ugrid_mesh_data, rename_to=new_name ) call ugrid_mesh_data%clear() ! Check the global mesh id global_mesh_id2 = global_mesh%get_id() @assertTrue(global_mesh_id2 > 0) + test_str1 = global_mesh%get_origin_file() + @assertTrue(trim(test_str1) == trim(filename)) + + test_str2 = global_mesh%get_origin_name() + @assertTrue(trim(test_str2) == trim(mesh_name)) + + test_str2 = global_mesh%get_mesh_name() + @assertTrue(trim(test_str2) == new_name) + ! Check getting a cell id from an x- and y-distance from a starting cell. ! First test that providing zero distances gives same id cell_id = global_mesh%get_cell_id( 1, 0, 0 ) @@ -386,16 +382,14 @@ contains end subroutine test_cubedsphere_global_mesh - + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @test - subroutine test_cubedsphere_single_file_intergrid(this) + subroutine test_cubedsphere_single_file_intergrid() - use ncdf_quad_mod, only: ncdf_quad_type + use ncdf_quad_mod, only: ncdf_quad_type implicit none - class( global_mesh_test_type ), intent( inout ) :: this - type(ugrid_mesh_data_type) :: ugrid_mesh_data character(len = str_max_filename) :: filename @@ -506,15 +500,14 @@ contains end subroutine test_cubedsphere_single_file_intergrid + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @test - subroutine test_cubedsphere_adding_intergrid_map(this) + subroutine test_cubedsphere_adding_intergrid_map() - use ncdf_quad_mod, only: ncdf_quad_type + use ncdf_quad_mod, only: ncdf_quad_type implicit none - class( global_mesh_test_type ), intent( inout ) :: this - type(ugrid_mesh_data_type) :: ugrid_mesh_data character(len = str_max_filename) :: filename @@ -637,7 +630,6 @@ contains target_mesh_ptr => global_mesh_collection%get_global_mesh( target_name ) global_mesh_map => global_mesh_ptr%get_global_mesh_map( target_mesh_ptr%get_id() ) - end subroutine test_cubedsphere_adding_intergrid_map end module global_mesh_mod_test diff --git a/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf b/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf index 74bc38346..728e27312 100644 --- a/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf +++ b/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf @@ -9,7 +9,8 @@ module ugrid_mesh_data_mod_test use constants_mod, only: r_def, i_def, l_def, imdi, & - str_def, str_longlong + str_def, str_longlong, & + str_max_filename use lfric_mpi_mod, only: global_mpi, & lfric_comm_type use ugrid_mesh_data_mod, only: ugrid_mesh_data_type @@ -68,6 +69,9 @@ contains character(str_def) :: filename character(str_def) :: mesh_name_in character(str_def) :: mesh_name_out + + character(str_max_filename) :: origin_file + integer(i_def) :: nnode integer(i_def) :: nedge integer(i_def) :: nface @@ -111,6 +115,7 @@ contains call ugrid_mesh_data%get_data( & mesh_name_out, & + origin_file, & geometry, & topology, & coord_sys, & @@ -215,6 +220,8 @@ contains character(str_def) :: mesh_name_in character(str_def) :: mesh_name_out + character(str_max_filename) :: origin_file + integer(i_def) :: nnode integer(i_def) :: nedge integer(i_def) :: nface @@ -461,6 +468,7 @@ contains call ugrid_mesh_data%get_data( & mesh_name_out, & + origin_file, & geometry, & topology, & coord_sys, & From 2171cfa9cb10588fb68be43cfd5174374250104b Mon Sep 17 00:00:00 2001 From: Ricky Wong <141156427+mo-rickywong@users.noreply.github.com> Date: Fri, 21 Aug 2026 12:01:22 +0100 Subject: [PATCH 4/6] Update doxygen --- .../driver/source/mesh/add_mesh_map_mod.f90 | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/components/driver/source/mesh/add_mesh_map_mod.f90 b/components/driver/source/mesh/add_mesh_map_mod.f90 index 5733fd306..3dc4ccde7 100644 --- a/components/driver/source/mesh/add_mesh_map_mod.f90 +++ b/components/driver/source/mesh/add_mesh_map_mod.f90 @@ -15,8 +15,8 @@ module add_mesh_map_mod use constants_mod, only: i_def, str_def, cmdi use log_mod, only: log_event, & log_scratch_space, & - LOG_LEVEL_ERROR, & - LOG_LEVEL_INFO + log_level_error, & + log_level_info use extrusion_mod, only: extrusion_type, & @@ -140,11 +140,9 @@ end subroutine assign_mesh_maps !> @brief Creates integrid map between two mesh_type objects. -!> @description The meshes should be contain valid local mesh integrid maps. -!> @param[in] source_mesh_name Name of source_mesh in the -!! application mesh collection. -!> @param[in] target_mesh_name Name of source_mesh in the -!! application mesh collection +!> @description The meshes should contain valid local mesh integrid maps. +!> @param[in] source_mesh Soure mesh object +!> @param[in] target_mesh Target mesh object subroutine add_mesh_map( source_mesh, target_mesh ) implicit none @@ -159,15 +157,15 @@ subroutine add_mesh_map( source_mesh, target_mesh ) 'Unable to create intergrid map: Source('// & trim(source_mesh%get_mesh_name())//' and target('// & trim(target_mesh%get_mesh_name())//') mesh IDs are the same' - call log_event( log_scratch_space, LOG_LEVEL_ERROR ) + call log_event( log_scratch_space, log_level_error ) end if call source_mesh % add_mesh_map (target_mesh) - write(log_scratch_space,'(A,I0,A)') & + write(log_scratch_space,'(a,i0,a)') & 'Adding intergrid map "'// & trim(source_mesh%get_mesh_name())//'"-->"'// & trim(target_mesh%get_mesh_name())//'"' - call log_event( log_scratch_space, LOG_LEVEL_INFO ) + call log_event( log_scratch_space, log_level_info ) return end subroutine add_mesh_map From f46c0501998662690be823e96bf7cc3fc8966e30 Mon Sep 17 00:00:00 2001 From: Ricky Wong <141156427+mo-rickywong@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:00:40 +0100 Subject: [PATCH 5/6] Remove trailing whitespace --- infrastructure/source/mesh/panel_decomposition_mod.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/source/mesh/panel_decomposition_mod.f90 b/infrastructure/source/mesh/panel_decomposition_mod.f90 index 979fcc312..86a6d62f3 100644 --- a/infrastructure/source/mesh/panel_decomposition_mod.f90 +++ b/infrastructure/source/mesh/panel_decomposition_mod.f90 @@ -125,7 +125,7 @@ end function get_nprocs_interface end interface - ! Overload call to calculation of mapping factor + ! Overload call to calculation of mapping factor interface calc_mapping_factor module procedure calc_mapping_factor_multiple module procedure calc_mapping_factor_single From 0348f7a5c3e1b531968f4d138b47ebe673d24f8a Mon Sep 17 00:00:00 2001 From: Ricky Wong <141156427+mo-rickywong@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:28:05 +0100 Subject: [PATCH 6/6] Test the ugrid_data object --- infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf | 1 + 1 file changed, 1 insertion(+) diff --git a/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf b/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf index 728e27312..648249a88 100644 --- a/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf +++ b/infrastructure/unit-test/mesh/ugrid_mesh_data_mod_test.pf @@ -145,6 +145,7 @@ contains edge_on_face_2d ) @assertEqual(mesh_name_in, mesh_name_out) + @assertEqual(filename, origin_file) @assertEqual(64_i_def, nnode) @assertEqual(128_i_def, nedge) @assertEqual(64_i_def, nface)