Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions applications/io_demo/build/project.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@
# via the Makefile.

$(info io_demo miniapp project specials)
# Enable the use of the sleep() intrinsic for gfortran
export FFLAGS_GNU_OPTIONS = -fall-intrinsics
10 changes: 8 additions & 2 deletions applications/io_demo/example/configuration.nml
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,20 @@ coord_system='native'
use_xios_io = .true.
write_diag = .true.
diagnostic_frequency = 1
subroutine_timers = .false.
subroutine_timers = .true.
timer_output_path = 'timer.txt'
subroutine_counters = .false.
counter_output_suffix = 'counter.txt'
checkpoint_read = .false.
checkpoint_write = .false.
file_convention = 'UGRID'
/

&io_demo
multifile_io = .false.
io_benchmark = .true.
n_benchmark_fields = 10
benchmark_sleep_time = 0
/

&logging
Expand All @@ -57,7 +63,7 @@ coord_system='native'
&time
calendar = 'timestep'
timestep_start = '1'
timestep_end = '90'
timestep_end = '10'
calendar_type='gregorian'
calendar_start='2016-01-01 15:00:00'
calendar_origin='2016-01-01 15:00:00'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
import=lfric-driver/HEAD

[namelist:io=multifile_io]
[namelist:io_demo]
compulsory=true
description=Provides options for configuring the runtime behaviour of the IO_Demo app
ns=namelist/io_demo
sort-key=Section-A02
title=IO_Demo

[namelist:io_demo=benchmark_sleep_time]
compulsory=true
description=Number of seconds to sleep for each timestep in I/O benchmark mode
!kind=default
type=integer

[namelist:io_demo=io_benchmark]
compulsory=true
description=Configure application to run as an I/O benchmarking tool
help=Configure application to run as an I/O benchmarking tool
!kind=default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
!kind=default
!kind=default
trigger=namelist:io_demo=benchmark_sleep_time: .true. ;
=namelist:io_demo=n_benchmark_fields: .true. ;

These new benchmark variables are not relevant unless in benchmarking mode, so should only be triggered in the case that the io_benchmark=.true., as in the above suggestion.

An alternative would be to have a separate namelist just for benchmarklng variables, then you can trigger the whole namelist on the one logical rather that specifying each variable individually. Depends if you think benchmarking will benefit from more inputs in future.

type=logical
trigger=namelist:io_demo=benchmark_sleep_time: .true. ;
=namelist:io_demo=n_benchmark_fields: .true. ;

[namelist:io_demo=multifile_io]
compulsory=true
description=Use multifile_io functionality
help=This is used to turn the multifile_io functionality in the io_demo app
=on and off
!kind=default
type=logical

[namelist:io_demo=n_benchmark_fields]
compulsory=true
description=Number of fields created in I/O benchmark
!kind=default
type=integer

[namelist:multifile_io]
compulsory=false
duplicate=true
Expand Down
14 changes: 11 additions & 3 deletions applications/io_demo/source/algorithm/io_demo_alg_mod.x90
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,35 @@ contains
!> @details Calculates the diffusion increment for a field, and adds it to said field.
!> @param[in] modeldb Application state object
!> @param[inout] field_in Input Wtheta field
subroutine io_demo_alg( modeldb, field_in )
!> @param[in] visc_in Optional setting for viscosity value
subroutine io_demo_alg( modeldb, field_in, visc_in )

implicit none

type(modeldb_type), intent(in) :: modeldb

! Prognostic fields
type( field_type ), intent( inout ) :: field_in
type( field_type ), intent( inout ) :: field_in
real(r_def), optional, intent( in ) :: visc_in

! Diagnostic fields
type( field_type ) :: dfield_in
type( field_type ) :: visc

real(r_def), parameter :: visc_val = 100000.0_r_def
real(r_def) :: visc_val
integer(kind=i_def), parameter :: stencil_depth = 1_i_def

type(mesh_type), pointer :: mesh
type(field_type), pointer :: dx_at_w2
type(function_space_type), pointer :: fs

integer(i_def) :: order_h, order_v
! Set viscosity to default value if not present
if (present(visc_in)) then
visc_val = visc_in
else
visc_val = 100000.0_r_def
end if

call log_event( "io_demo: Running algorithm", LOG_LEVEL_TRACE )

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
!-----------------------------------------------------------------------------
! (C) Crown copyright Met Office. All rights reserved.
! The file LICENCE, distributed with this code, contains details of the terms
! under which the code may be used.
!-----------------------------------------------------------------------------

!> @brief Setup infrastructure used for I/O benchmark
!> @details Handles the setup of all the fields that will be passed used to
!! benchmark the speed of XIOS reading and writing
module io_benchmark_setup_mod

use constants_mod, only: i_def, str_def
use driver_modeldb_mod, only: modeldb_type
use field_collection_mod, only: field_collection_type
use field_mod, only: field_type
use field_parent_mod, only: read_interface, write_interface
use file_mod, only: FILE_MODE_WRITE
use fs_continuity_mod, only: Wtheta
use function_space_mod, only: function_space_type
use function_space_collection_mod, only: function_space_collection
use lfric_xios_file_mod, only: lfric_xios_file_type, OPERATION_TIMESERIES
use lfric_xios_read_mod, only: read_field_generic
use lfric_xios_write_mod, only: write_field_generic
use linked_list_mod, only: linked_list_type
use mesh_mod, only: mesh_type
use mesh_collection_mod, only: mesh_collection

implicit none

public create_io_benchmark_fields, setup_io_benchmark_files

contains

!> @details Creates the fields needed for the IO benchmark
!> @param[in,out] modeldb The model database in which to store model data.
subroutine create_io_benchmark_fields(modeldb)

implicit none

type(modeldb_type), intent(inout) :: modeldb

type(mesh_type), pointer :: mesh
type(field_collection_type), pointer :: io_benchmark_fields
type(field_type) :: tmp_io_field
procedure(read_interface), pointer :: tmp_read_ptr
procedure(write_interface), pointer :: tmp_write_ptr
type(function_space_type), pointer :: wtheta_fs

character(str_def) :: prime_mesh_name, tmp_field_name
Comment on lines 48 to 49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
type(namelist_type), pointer :: base_mesh_nml
type(namelist_type), pointer :: finite_element_nml
type(namelist_type), pointer :: io_demo_nml
type(namelist_type), pointer :: io_nml
character(str_def) :: prime_mesh_name, tmp_field_name
type(function_space_type), pointer :: fs
character(str_def) :: prime_mesh_name, tmp_field_name
  • Namelist type pointers no longer needed with new api
  • Declare function space pointer to clean up code further down

integer(i_def) :: element_order_h
integer(i_def) :: element_order_v
integer(i_def) :: i
integer(i_def) :: n_benchmark_fields
integer(i_def) :: diagnostic_frequency

prime_mesh_name = modeldb%config%base_mesh%prime_mesh_name()
element_order_h = modeldb%config%finite_element%element_order_h()
element_order_v = modeldb%config%finite_element%element_order_v()
n_benchmark_fields = modeldb%config%io_demo%n_benchmark_fields()
diagnostic_frequency = modeldb%config%io%diagnostic_frequency()

mesh => mesh_collection%get_mesh(prime_mesh_name)

call modeldb%fields%add_empty_field_collection("io_benchmark_fields")
io_benchmark_fields => modeldb%fields%get_field_collection("io_benchmark_fields")
wtheta_fs => function_space_collection%get_fs( mesh, element_order_h, &
element_order_v, Wtheta )

do i = 1, n_benchmark_fields
write(tmp_field_name, "(A19, I3.3)") 'io_benchmark_field_', i
call tmp_io_field%initialise( vector_space = wtheta_fs, &
name=tmp_field_name )
tmp_read_ptr => read_field_generic
tmp_write_ptr => write_field_generic
call tmp_io_field%set_read_behaviour(tmp_read_ptr)
call tmp_io_field%set_write_behaviour(tmp_write_ptr)
call io_benchmark_fields%add_field(tmp_io_field)
end do
Comment on lines 69 to 78
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
do i = 1, n_benchmark_fields
write(tmp_field_name, "(A19, I3.3)") 'io_benchmark_field_', i
call tmp_io_field%initialise( vector_space = &
function_space_collection%get_fs(mesh, element_order_h, &
element_order_v, Wtheta), &
name=tmp_field_name )
tmp_read_ptr => read_field_generic
tmp_write_ptr => write_field_generic
call tmp_io_field%set_read_behaviour(tmp_read_ptr)
call tmp_io_field%set_write_behaviour(tmp_write_ptr)
call io_benchmark_fields%add_field(tmp_io_field)
end do
fs => function_space_collection%get_fs( mesh, &
element_order_h, &
element_order_v, &
Wtheta )
do i = 1, n_benchmark_fields
write(tmp_field_name, "(A19, I3.3)") 'io_benchmark_field_', i
call tmp_io_field%initialise( fs , name=tmp_field_name )
tmp_read_ptr => read_field_generic
tmp_write_ptr => write_field_generic
call tmp_io_field%set_read_behaviour(tmp_read_ptr)
call tmp_io_field%set_write_behaviour(tmp_write_ptr)
call io_benchmark_fields%add_field(tmp_io_field)
end do
  • Indent to 2-spaces, not 4
  • Function space is not changed so get it once and reuse to clean up code


nullify( mesh, io_benchmark_fields, wtheta_fs )

end subroutine create_io_benchmark_fields

subroutine setup_io_benchmark_files(file_list, modeldb)

implicit none

type(linked_list_type), intent(out) :: file_list
type(modeldb_type), optional, intent(inout) :: modeldb

integer(i_def) :: diagnostic_frequency
type(field_collection_type), pointer :: io_benchmark_fields

diagnostic_frequency = modeldb%config%io%diagnostic_frequency()

io_benchmark_fields => modeldb%fields%get_field_collection("io_benchmark_fields")

file_list = linked_list_type()
call file_list%insert_item( lfric_xios_file_type( "lfric_xios_write_benchmark", &
xios_id="lfric_xios_write_benchmark", &
io_mode=FILE_MODE_WRITE, &
operation=OPERATION_TIMESERIES, &
freq=diagnostic_frequency, &
fields_in_file=io_benchmark_fields ) )

nullify(io_benchmark_fields)

end subroutine setup_io_benchmark_files

end module io_benchmark_setup_mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
!-----------------------------------------------------------------------------
! (C) Crown copyright Met Office. All rights reserved.
! The file LICENCE, distributed with this code, contains details of the terms
! under which the code may be used.
!-----------------------------------------------------------------------------

!> Steps the I/O benchmark section of IO_demo
module io_benchmark_step_mod

use constants_mod, only: i_def, r_def
use driver_modeldb_mod, only: modeldb_type
use field_mod, only: field_type
use field_parent_mod, only: field_parent_type
use field_collection_iterator_mod, &
only: field_collection_iterator_type
use field_collection_mod, only: field_collection_type
use log_mod, only: log_event, &
log_scratch_space, &
LOG_LEVEL_INFO

implicit none

private
public :: step_io_benchmark

contains

!> A simple timestep algorithm that copies the diffusion field into the
!! various benchmark fields and divides the entire field by the fields number
!!
!> @param[in,out] modeldb The model database
subroutine step_io_benchmark(modeldb)

implicit none

type(modeldb_type), optional, intent(inout) :: modeldb

type(field_collection_type), pointer :: depository
type(field_collection_type), pointer :: io_benchmark_fields
type(field_collection_iterator_type) :: field_iter
class(field_parent_type), pointer :: step_field
type(field_type), pointer :: kernel_field
type(field_type), pointer :: diffusion_field

integer(i_def) :: i, sleep_duration
real(r_def) :: loop_factor

sleep_duration = modeldb%config%io_demo%benchmark_sleep_time()

! Get field data ready
depository => modeldb%fields%get_field_collection("depository")
io_benchmark_fields => modeldb%fields%get_field_collection("io_benchmark_fields")
call depository%get_field("diffusion_field", diffusion_field)

call field_iter%initialise(io_benchmark_fields)
do i = 1, io_benchmark_fields%get_length()
if ( .not. field_iter%has_next() ) exit
step_field => field_iter%next()
select type(step_field)
type is (field_type)
! Copy diffusion field values to new fields and adjust values
kernel_field => step_field
loop_factor = real(i, r_def)
call invoke( setval_X(kernel_field, diffusion_field), &
inc_X_divideby_a(kernel_field, loop_factor) )
end select

end do

write(log_scratch_space,'(A,I0,A)') "io_demo: sleeping for ", sleep_duration, " seconds"
call log_event(log_scratch_space, LOG_LEVEL_INFO)
call sleep(sleep_duration)

nullify(step_field)
nullify(kernel_field)
nullify(diffusion_field)

end subroutine step_io_benchmark

end module io_benchmark_step_mod
Loading