MONC
Functions/Subroutines | Variables
netcdf_filetype_writer_mod Module Reference

The NetCDF file type writer which performs actual writing of NetCDF files to the parallel filesystem. These are opened by all IO servers and all IO servers can participate as variables might be located across the different IO processes. More...

Functions/Subroutines

subroutine, public initialise_netcdf_filetype ()
 Initialises the NetCDF writing functionality. More...
 
subroutine, public finalise_netcdf_filetype ()
 Finalises the NetCDF writing functionality. More...
 
subroutine, public define_netcdf_file (io_configuration, file_writer_information, timestep, time, time_points, termination_write)
 Defines a NetCDF file - which creates it, defines all dimensions and variables. This must be called by all IO server processes as the NetCDF operations here are collective. More...
 
subroutine, public store_io_server_state (io_configuration, writer_entries, time_points, file_writer_information, timestep)
 Stores the IO server state in the NetCDF file. More...
 
type(writer_type) function, pointer, public get_writer_entry_from_netcdf (field_name, timestep, terminated)
 Looks up and retrieves the writer entry that corresponds to this NetCDF file state. More...
 
subroutine, public close_netcdf_file (io_configuration, field_name, timestep)
 Call back for the inter IO reduction which actually does the NetCDF file closing which is a collective (synchronous) operation. This also cleans up the file state as it is no longer required. More...
 
subroutine, public write_variable (io_configuration, field_to_write_information, filename, timestep, time)
 Writes the contents of a variable to the NetCDF file. This also removes the written entries from the field information type in order to conserve memory. More...
 
integer function get_dimension_identifier (dim_name, is_auto_dimension)
 Translates a dimension name to its numeric corresponding identifier. More...
 
integer function get_dimension_original_size (dim_name, dimension_store)
 Retrieves the original size of a specific dimension (which is auto) More...
 
subroutine write_coordinate_variable (file_state, coord_var_id, field_values)
 Writes a coordinate variable into the NetCDF file. More...
 
subroutine write_condition_variable (file_state, c_var_id, field_values)
 Writes the conditional diagnostic variable names into the NetCDF file. More...
 
subroutine write_contiguous_collective_variable_to_diagnostics (io_configuration, field_to_write_information, timestep, time, file_state)
 Writes contiguous collective variable blocks into the NetCDF files. These are blocks of data spanning multiple variables and multiple time points, the idea being to minimise the number of overall writes into the file. These variables are defined collective, so it might be that other IO servers have less contiguous data and hence more writes, therefore empty writes might need to be issued (at the end) to match up against these other servers. More...
 
type(write_field_collective_descriptor_type) function, pointer get_next_collective_descriptor (iterator)
 Retrieves the next collective descriptor based upon the iterator. More...
 
type(write_field_collective_monc_info_type) function, pointer get_next_specific_monc_info (iterator)
 Retrieves the next specific monc information item from the iterator. More...
 
subroutine write_collective_variable_to_diagnostics (io_configuration, field_to_write_information, timestep, time, file_state)
 Writes collective variables, where we are working with the values from multiple MONCs and storing these in their own specific relative location in the diagnostics file. More...
 
subroutine write_independent_variable_to_diagnostics (field_to_write_information, timestep, time, file_state)
 Writes independent variables to the diagnostics file. This writes the entire variable and works by writing all the memory up and then doing the write in one call. More...
 
subroutine write_out_number_values (field_to_write_information, timestep, time, file_state)
 
subroutine write_out_map (field_to_write_information, timestep, time, file_state)
 
subroutine write_out_options (io_configuration, file_state)
 Writes out the options_database defining this model run. More...
 
subroutine define_time_series_dimensions (file_state, file_writer_information, time, time_points, termination_write)
 Defines dimensions for all required dimensions. This is usually the number required plus one, but in some cases is entirely required depending how the output frequency and diagnostics write times match up. More...
 
integer function get_number_timeseries_entries (time_points, previous_write_time, output_frequency, timestep_frequency, termination_write, last_write_entry)
 Retrieves the number of timeseries entries for a specific frequency and previous write time. This is based on the range of time points that are provided to the call. More...
 
integer function define_coordinate_variable (file_state, coord_name)
 Defines a coordinate variable in the NetCDF file. More...
 
integer function define_options_database_variable (file_state)
 Defines the options_database variable in the NetCDF file. More...
 
subroutine define_variables (io_configuration, file_state, file_writer_information)
 Defines all variables in the file writer state. More...
 
integer function retrieve_time_series_dimension_id_for_field (file_state, file_writer_information, field_index)
 For a specific field will retrieve the NetCDF id of the time series dimension most appropriate for this field. If a dimension can not be located then an error is raised. More...
 
type(netcdf_diagnostics_timeseries_type) function, pointer get_specific_timeseries_dimension (file_state, output_frequency, timestep_frequency)
 Given the file state and the output frequency of a field will retrive the appropriate time series dimension entry that corresponds to this or null if none can be found. More...
 
subroutine define_dimensions (file_state, dimension_sizing)
 Defines spatial dimensions in the diagnostics file. More...
 
type(netcdf_diagnostics_type) function, pointer get_file_state (filename, timestep, dolock)
 Retrieves a file state based upon its timestep or null if none is found. More...
 
character(len=string_length) function get_field_key (field_to_write_information)
 Retrieves the field key, corresponding to the field name in the NetCDF file and what we store against the id in the NetCDF file state internally. This is either the field name itself or the manipulation type appended if there is duplication. More...
 
subroutine generate_unique_filename (old_name, new_name, configured_write_time, timestep)
 Generates a unique filename based upon the base one specified and the number of completed timesteps. More...
 
subroutine write_out_global_attributes (io_configuration, ncid, file_writer_information, timestep, time)
 Writes out global attributes into the checkpoint. More...
 

Variables

type(hashmap_type), volatile file_states
 
integer, volatile file_states_rwlock
 
integer, volatile netcdf_mutex
 
logical l_nc_dim
 
logical l_nd_dim
 
integer nc_dim_id
 
integer nd_dim_id
 
integer nopt_dim_id
 
integer nc_var_id_s
 
integer nd_var_id_s
 
integer nc_var_id_l
 
integer nd_var_id_l
 
integer nopt_var_id
 

Detailed Description

The NetCDF file type writer which performs actual writing of NetCDF files to the parallel filesystem. These are opened by all IO servers and all IO servers can participate as variables might be located across the different IO processes.

Function/Subroutine Documentation

◆ close_netcdf_file()

subroutine, public netcdf_filetype_writer_mod::close_netcdf_file ( type(io_configuration_type), intent(inout)  io_configuration,
character(len=string_length)  field_name,
integer  timestep 
)

Call back for the inter IO reduction which actually does the NetCDF file closing which is a collective (synchronous) operation. This also cleans up the file state as it is no longer required.

Parameters
io_configurationThe IO server configuration
field_nameThe field name that is being communicated
timestepThe write timestep

Definition at line 193 of file netcdf_filetype.F90.

194  type(io_configuration_type), intent(inout) :: io_configuration
195  character(len=STRING_LENGTH) :: field_name
196  integer :: timestep
197 
198  type(iterator_type) :: iterator
199  class(*), pointer :: generic
200 
201  type(netcdf_diagnostics_type), pointer :: file_state
202 
203  file_state=>get_file_state(field_name, timestep, .true.)
204  call check_thread_status(forthread_mutex_lock(file_state%mutex))
205  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
206  call lock_mpi()
207  call check_netcdf_status(nf90_close(file_state%ncid))
208  call unlock_mpi()
209  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
210  call check_thread_status(forthread_mutex_unlock(file_state%mutex))
211  call check_thread_status(forthread_mutex_destroy(file_state%mutex))
212  call c_free(file_state%dimension_to_id)
213  call c_free(file_state%variable_to_id)
214  iterator=c_get_iterator(file_state%timeseries_dimension)
215  do while (c_has_next(iterator))
216  generic=>c_get_generic(c_next_mapentry(iterator))
217  select type(generic)
218  type is(netcdf_diagnostics_timeseries_type)
219  deallocate(generic)
220  end select
221  end do
222  call c_free(file_state%timeseries_dimension)
223  call check_thread_status(forthread_rwlock_wrlock(file_states_rwlock))
224  call c_remove(file_states, trim(field_name)//"#"//trim(conv_to_string(timestep)))
225  call check_thread_status(forthread_rwlock_unlock(file_states_rwlock))
226  if (log_get_logging_level() .ge. log_debug .and. log_is_master()) then
227  call log_master_log(log_debug, "Done physical close for NetCDF file at timestep "//trim(conv_to_string(timestep)))
228  end if
Here is the call graph for this function:

◆ define_coordinate_variable()

integer function netcdf_filetype_writer_mod::define_coordinate_variable ( type(netcdf_diagnostics_type), intent(inout)  file_state,
character(len=*), intent(in)  coord_name 
)
private

Defines a coordinate variable in the NetCDF file.

Parameters
file_stateThe NetCDF file state
coord_nameThe name of the coordinate
Returns
The resulting coordinate variable id

Definition at line 923 of file netcdf_filetype.F90.

924  type(netcdf_diagnostics_type), intent(inout) :: file_state
925  character(len=*), intent(in) :: coord_name
926 
927  integer :: field_id, dimension_ids(1)
928 
929  dimension_ids(1)=c_get_integer(file_state%dimension_to_id, trim(coord_name))
930  call lock_mpi()
931  call check_netcdf_status(nf90_def_var(file_state%ncid, trim(coord_name), nf90_double, dimension_ids, field_id))
932  call unlock_mpi()
933  define_coordinate_variable=field_id
Here is the call graph for this function:
Here is the caller graph for this function:

◆ define_dimensions()

subroutine netcdf_filetype_writer_mod::define_dimensions ( type(netcdf_diagnostics_type), intent(inout)  file_state,
type(map_type), intent(inout)  dimension_sizing 
)
private

Defines spatial dimensions in the diagnostics file.

Parameters
file_stateThe NetCDF file state
dimension_sizingAll dimension name to size key value pairs

Definition at line 1139 of file netcdf_filetype.F90.

1140  type(netcdf_diagnostics_type), intent(inout) :: file_state
1141  type(map_type), intent(inout) :: dimension_sizing
1142 
1143  integer :: ncdf_dimid, dim_length
1144  type(iterator_type) :: iterator
1145  type(mapentry_type) :: map_entry
1146 
1147 
1148  iterator=c_get_iterator(dimension_sizing)
1149  call lock_mpi()
1150  do while (c_has_next(iterator))
1151  map_entry=c_next_mapentry(iterator)
1152  dim_length=c_get_integer(map_entry)
1153  if (dim_length .gt. 0) then
1154  call check_netcdf_status(nf90_def_dim(file_state%ncid, map_entry%key, dim_length, ncdf_dimid))
1155  call c_put_integer(file_state%dimension_to_id, map_entry%key, ncdf_dimid)
1156  if (map_entry%key == "nc") then
1157  nc_dim_id=ncdf_dimid
1158  end if
1159  if (map_entry%key == "nd") then
1160  nd_dim_id=ncdf_dimid
1161  end if
1162  if (map_entry%key == "number_options") then
1163  nopt_dim_id=ncdf_dimid
1164  end if
1165  end if
1166  end do
1167  call check_netcdf_status(nf90_def_dim(file_state%ncid, "string", string_length, file_state%string_dim_id))
1168  call check_netcdf_status(nf90_def_dim(file_state%ncid, "kvp", 2, file_state%key_value_dim_id))
1169  call unlock_mpi()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ define_netcdf_file()

subroutine, public netcdf_filetype_writer_mod::define_netcdf_file ( type(io_configuration_type), intent(inout)  io_configuration,
type(writer_type), intent(inout), target  file_writer_information,
integer, intent(in)  timestep,
real, intent(in)  time,
type(map_type), intent(inout)  time_points,
logical, intent(in)  termination_write 
)

Defines a NetCDF file - which creates it, defines all dimensions and variables. This must be called by all IO server processes as the NetCDF operations here are collective.

Parameters
io_configurationThe IO server configuration
file_writer_informationThe writer entry that is being written
timestepThe write timestep
timeThe write time

Isolate these writes, as they may trip over one another

Write conditional diagnostics descriptors to file if file contains corresponding dimension.

Write options_database and height coordinates to all files.

Definition at line 69 of file netcdf_filetype.F90.

70  type(io_configuration_type), intent(inout) :: io_configuration
71  type(writer_type), intent(inout), target :: file_writer_information
72  type(map_type), intent(inout) :: time_points
73  integer, intent(in) :: timestep
74  real, intent(in) :: time
75  logical, intent(in) :: termination_write
76 
77  character(len=STRING_LENGTH) :: unique_filename
78  type(netcdf_diagnostics_type), pointer :: ncdf_writer_state
79  class(*), pointer :: generic
80  integer :: zn_var_id
81  integer :: z_var_id
82 
83  ncdf_writer_state=>get_file_state(file_writer_information%filename, timestep, .true.)
84  if (.not. associated(ncdf_writer_state)) then
85  call check_thread_status(forthread_rwlock_wrlock(file_states_rwlock))
86  ncdf_writer_state=>get_file_state(file_writer_information%filename, timestep, .false.)
87  if (.not. associated(ncdf_writer_state)) then
88  allocate(ncdf_writer_state)
89  ncdf_writer_state%corresponding_writer_entry=>file_writer_information
90  ncdf_writer_state%termination_write=termination_write
91  call check_thread_status(forthread_mutex_init(ncdf_writer_state%mutex, -1))
92  call check_thread_status(forthread_mutex_lock(ncdf_writer_state%mutex))
93  generic=>ncdf_writer_state
94  call c_put_generic(file_states, trim(file_writer_information%filename)//"#"//trim(conv_to_string(timestep)), &
95  generic, .false.)
96  call check_thread_status(forthread_rwlock_unlock(file_states_rwlock))
97 
98  if (file_writer_information%write_on_model_time) then
99  call generate_unique_filename(file_writer_information%filename, unique_filename, &
100  file_writer_information%defined_write_time)
101  else
102  call generate_unique_filename(file_writer_information%filename, unique_filename, timestep=timestep)
103  end if
104  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
105  call lock_mpi()
106  call check_netcdf_status(nf90_create(unique_filename, ior(nf90_netcdf4, nf90_mpiio), ncdf_writer_state%ncid, &
107  comm = io_configuration%io_communicator, info = mpi_info_null))
108  call unlock_mpi()
109  call write_out_global_attributes(io_configuration, ncdf_writer_state%ncid, file_writer_information, timestep, time)
110  call define_dimensions(ncdf_writer_state, io_configuration%dimension_sizing)
111  call define_time_series_dimensions(ncdf_writer_state, file_writer_information, time, time_points, termination_write)
112  call define_variables(io_configuration, ncdf_writer_state, file_writer_information)
113  zn_var_id = define_coordinate_variable(ncdf_writer_state,"zn")
114  z_var_id = define_coordinate_variable(ncdf_writer_state,"z")
115  nopt_var_id = define_options_database_variable(ncdf_writer_state)
116  call lock_mpi()
117  call check_netcdf_status(nf90_enddef(ncdf_writer_state%ncid))
118  call unlock_mpi()
119 
121  if (io_configuration%my_io_rank == 0) then
123  if (l_nc_dim) then
124  call write_condition_variable(ncdf_writer_state, nc_var_id_s, cond_request)
125  call write_condition_variable(ncdf_writer_state, nc_var_id_l, cond_long)
126  end if
127  if (l_nd_dim) then
128  call write_condition_variable(ncdf_writer_state, nd_var_id_s, diag_request)
129  call write_condition_variable(ncdf_writer_state, nd_var_id_l, diag_long)
130  end if
131 
133  call write_out_options(io_configuration, ncdf_writer_state)
134  call write_coordinate_variable(ncdf_writer_state, zn_var_id, io_configuration%zn_field)
135  call write_coordinate_variable(ncdf_writer_state, z_var_id, io_configuration%z_field)
136  end if ! end write isolation
137 
138  call check_thread_status(forthread_mutex_unlock(ncdf_writer_state%mutex))
139  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
140 
141  else
142  call check_thread_status(forthread_rwlock_unlock(file_states_rwlock))
143  end if
144  end if
Here is the call graph for this function:
Here is the caller graph for this function:

◆ define_options_database_variable()

integer function netcdf_filetype_writer_mod::define_options_database_variable ( type(netcdf_diagnostics_type), intent(inout)  file_state)
private

Defines the options_database variable in the NetCDF file.

Parameters
file_stateThe NetCDF file state
Returns
The resulting options_database variable id

Definition at line 939 of file netcdf_filetype.F90.

940  type(netcdf_diagnostics_type), intent(inout) :: file_state
941 
942  integer :: field_id, dimension_ids(3)
943 
944  dimension_ids(1)=file_state%string_dim_id
945  dimension_ids(2)=file_state%key_value_dim_id
946  dimension_ids(3)=nopt_dim_id
947  call lock_mpi()
948  call check_netcdf_status(nf90_def_var(file_state%ncid, "options_database", nf90_char, dimension_ids, field_id))
949  call unlock_mpi()
950  define_options_database_variable=field_id
Here is the call graph for this function:
Here is the caller graph for this function:

◆ define_time_series_dimensions()

subroutine netcdf_filetype_writer_mod::define_time_series_dimensions ( type(netcdf_diagnostics_type), intent(inout)  file_state,
type(writer_type), intent(inout)  file_writer_information,
real, intent(in)  time,
type(map_type), intent(inout)  time_points,
logical, intent(in)  termination_write 
)
private

Defines dimensions for all required dimensions. This is usually the number required plus one, but in some cases is entirely required depending how the output frequency and diagnostics write times match up.

Parameters
file_stateThe state of the NetCDF file
file_writer_informationWriter information
timeThe model write time

Definition at line 841 of file netcdf_filetype.F90.

842  type(netcdf_diagnostics_type), intent(inout) :: file_state
843  type(writer_type), intent(inout) :: file_writer_information
844  real, intent(in) :: time
845  type(map_type), intent(inout) :: time_points
846  logical, intent(in) :: termination_write
847 
848  integer :: i
849  character(len=STRING_LENGTH) :: dim_key
850  type(netcdf_diagnostics_timeseries_type), pointer :: timeseries_diag
851  class(*), pointer :: generic
852 
853  do i=1, size(file_writer_information%contents)
854  if (file_writer_information%contents(i)%output_frequency .lt. 0.0) then
855  dim_key="time_series_"//trim(conv_to_string(file_writer_information%contents(i)%timestep_frequency))
856  else
857  dim_key="time_series_"//trim(conv_to_string(file_writer_information%contents(i)%timestep_frequency))//"_"//&
858  trim(conv_to_string(file_writer_information%contents(i)%output_frequency))
859  end if
860  if (.not. c_contains(file_state%timeseries_dimension, dim_key)) then
861  allocate(timeseries_diag)
862  timeseries_diag%variable_written=.false.
863  timeseries_diag%num_entries=get_number_timeseries_entries(time_points, &
864  file_writer_information%contents(i)%previous_tracked_write_point, &
865  file_writer_information%contents(i)%output_frequency, file_writer_information%contents(i)%timestep_frequency, &
866  termination_write, timeseries_diag%last_write_point)
867  call lock_mpi()
868  call check_netcdf_status(nf90_def_dim(file_state%ncid, dim_key, timeseries_diag%num_entries, &
869  timeseries_diag%netcdf_dim_id))
870  call unlock_mpi()
871  generic=>timeseries_diag
872  call c_put_generic(file_state%timeseries_dimension, dim_key, generic, .false.)
873  end if
874  file_writer_information%contents(i)%previous_tracked_write_point=timeseries_diag%last_write_point
875  end do
Here is the call graph for this function:
Here is the caller graph for this function:

◆ define_variables()

subroutine netcdf_filetype_writer_mod::define_variables ( type(io_configuration_type), intent(inout)  io_configuration,
type(netcdf_diagnostics_type), intent(inout)  file_state,
type(writer_type), intent(in)  file_writer_information 
)
private

Defines all variables in the file writer state.

Parameters
file_stateThe NetCDF file state
file_writer_informationThe file writer information

Only enable writing of conditional diagnostics descriptor fields to this file if there is

Provide conditional diagnostic descriptions if data being used in this file.

Definition at line 956 of file netcdf_filetype.F90.

957  type(io_configuration_type), intent(inout) :: io_configuration
958  type(netcdf_diagnostics_type), intent(inout) :: file_state
959  type(writer_type), intent(in) :: file_writer_information
960 
961  integer :: i, j, data_type, field_id, map_dim_id
962  integer, dimension(:), allocatable :: dimension_ids
963  character(len=STRING_LENGTH) :: variable_key
964  type(netcdf_diagnostics_timeseries_type), pointer :: timeseries_diag
965  class(*), pointer :: generic
966  type(iterator_type) :: iterator
967  type(mapentry_type) :: map_entry
968 
969  l_nc_dim = .false.
970  l_nd_dim = .false.
971 
972  iterator=c_get_iterator(file_state%timeseries_dimension)
973  do while (c_has_next(iterator))
974  map_entry=c_next_mapentry(iterator)
975  generic=>c_get_generic(map_entry)
976  select type(generic)
977  type is(netcdf_diagnostics_timeseries_type)
978  timeseries_diag=>generic
979  end select
980  call lock_mpi()
981  call check_netcdf_status(nf90_def_var(file_state%ncid, map_entry%key, &
982  nf90_double, timeseries_diag%netcdf_dim_id, timeseries_diag%netcdf_var_id))
983  call unlock_mpi()
984  end do
985 
986  do i=1, size(file_writer_information%contents)
987  if (.not. file_writer_information%contents(i)%enabled) cycle
988  if (file_writer_information%contents(i)%data_type == double_data_type) then
989  data_type=nf90_double
990  else if (file_writer_information%contents(i)%data_type == integer_data_type) then
991  data_type=nf90_int
992  else if (file_writer_information%contents(i)%data_type == string_data_type) then
993  data_type=nf90_char
994  end if
995  variable_key=get_field_key(file_writer_information%contents(i))
996  if (file_writer_information%contents(i)%field_type == array_field_type) then
997  allocate(dimension_ids(file_writer_information%contents(i)%dimensions+1))
998  do j=1, file_writer_information%contents(i)%dimensions
999  if (c_contains(file_state%dimension_to_id, file_writer_information%contents(i)%dim_size_defns(j))) then
1000  dimension_ids(j)=c_get_integer(file_state%dimension_to_id, file_writer_information%contents(i)%dim_size_defns(j))
1001  else
1002  call log_log(log_error, "Can not find information for dimension named '"//&
1003  trim(file_writer_information%contents(i)%dim_size_defns(j))//"'")
1004  end if
1005  end do
1006  dimension_ids(j)=retrieve_time_series_dimension_id_for_field(file_state, file_writer_information, i)
1007 
1009  ! a data field using its dimensions.
1010  if (any(dimension_ids .eq. nc_dim_id) .or. any(dimension_ids .eq. nd_dim_id)) then
1011  l_nc_dim = .true.
1012  l_nd_dim = .true.
1013  end if
1014 
1015  call lock_mpi()
1016  call check_netcdf_status(nf90_def_var(file_state%ncid, variable_key, &
1017  data_type, dimension_ids, field_id))
1018 
1019  if (file_writer_information%contents(i)%collective_write .and. &
1020  file_writer_information%contents(i)%collective_contiguous_optimisation .and. &
1021  io_configuration%number_of_io_servers .gt. 1) then
1022  call check_netcdf_status(nf90_def_var_fill(file_state%ncid, field_id, 1, 1))
1023  call check_netcdf_status(nf90_var_par_access(file_state%ncid, field_id, nf90_collective))
1024  end if
1025  call unlock_mpi()
1026  deallocate(dimension_ids)
1027  else if (file_writer_information%contents(i)%field_type == scalar_field_type) then
1028  call lock_mpi()
1029  call check_netcdf_status(nf90_def_var(file_state%ncid, variable_key, &
1030  data_type, retrieve_time_series_dimension_id_for_field(file_state, file_writer_information, i), field_id))
1031  call unlock_mpi()
1032  else if (file_writer_information%contents(i)%field_type == map_field_type) then
1033  allocate(dimension_ids(4))
1034  dimension_ids(1)=file_state%string_dim_id
1035  dimension_ids(2)=file_state%key_value_dim_id
1036  dimension_ids(3)=c_get_integer(file_state%dimension_to_id, file_writer_information%contents(i)%dim_size_defns(1))
1037  dimension_ids(4)=retrieve_time_series_dimension_id_for_field(file_state, file_writer_information, i)
1038  call lock_mpi()
1039  call check_netcdf_status(nf90_def_var(file_state%ncid, variable_key, data_type, dimension_ids, field_id))
1040  call unlock_mpi()
1041  deallocate(dimension_ids)
1042  end if
1043  call c_put_integer(file_state%variable_to_id, variable_key, field_id)
1044  if (len_trim(file_writer_information%contents(i)%units) .gt. 0) then
1045  call lock_mpi()
1046  call check_netcdf_status(nf90_put_att(file_state%ncid, field_id, "units", file_writer_information%contents(i)%units))
1047  call unlock_mpi()
1048  end if
1049  end do
1050 
1052  if (l_nc_dim) then
1053  allocate(dimension_ids(2))
1054  dimension_ids(1)=file_state%string_dim_id
1055  dimension_ids(2)=nc_dim_id
1056  call lock_mpi()
1057  call check_netcdf_status(nf90_def_var(file_state%ncid, "conditions_fields_short", &
1058  nf90_char, dimension_ids, nc_var_id_s))
1059  call check_netcdf_status(nf90_def_var(file_state%ncid, "conditions_fields_long", &
1060  nf90_char, dimension_ids, nc_var_id_l))
1061  call unlock_mpi()
1062  deallocate(dimension_ids)
1063  end if
1064  if (l_nd_dim) then
1065  allocate(dimension_ids(2))
1066  dimension_ids(1)=file_state%string_dim_id
1067  dimension_ids(2)=nd_dim_id
1068  call lock_mpi()
1069  call check_netcdf_status(nf90_def_var(file_state%ncid, "diagnostics_fields_short", &
1070  nf90_char, dimension_ids, nd_var_id_s))
1071  call check_netcdf_status(nf90_def_var(file_state%ncid, "diagnostics_fields_long", &
1072  nf90_char, dimension_ids, nd_var_id_l))
1073  call unlock_mpi()
1074  deallocate(dimension_ids)
1075  end if
1076 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ finalise_netcdf_filetype()

subroutine, public netcdf_filetype_writer_mod::finalise_netcdf_filetype

Finalises the NetCDF writing functionality.

Definition at line 58 of file netcdf_filetype.F90.

59  call check_thread_status(forthread_rwlock_destroy(file_states_rwlock))
60  call check_thread_status(forthread_mutex_destroy(netcdf_mutex))
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_unique_filename()

subroutine netcdf_filetype_writer_mod::generate_unique_filename ( character(len=string_length), intent(in)  old_name,
character(len=string_length), intent(out)  new_name,
real, intent(in), optional  configured_write_time,
integer, intent(in), optional  timestep 
)
private

Generates a unique filename based upon the base one specified and the number of completed timesteps.

Parameters
old_nameThe existing name that is used as a base
timestepThe current model timestep
new_nameThe new name that is produced by this subroutine

Definition at line 1222 of file netcdf_filetype.F90.

1223  character(len=STRING_LENGTH), intent(in) :: old_name
1224  real, intent(in), optional :: configured_write_time
1225  integer, intent(in), optional :: timestep
1226  character(len=STRING_LENGTH), intent(out) :: new_name
1227 
1228  integer :: dot_posn
1229 
1230  dot_posn=index(old_name, ".")
1231  if (dot_posn .gt. 0) then
1232  new_name = old_name(1:dot_posn-1)
1233  else
1234  new_name=old_name
1235  end if
1236  if (present(configured_write_time)) then
1237  new_name=trim(new_name)//"_"//trim(conv_to_string(configured_write_time))
1238  else if (present(timestep)) then
1239  new_name=trim(new_name)//"_"//trim(conv_to_string(timestep))
1240  end if
1241  if (dot_posn .gt. 0) then
1242  new_name=trim(new_name)//old_name(dot_posn:len(old_name))
1243  end if
Here is the caller graph for this function:

◆ get_dimension_identifier()

integer function netcdf_filetype_writer_mod::get_dimension_identifier ( character(len=*), intent(in)  dim_name,
logical, intent(out), optional  is_auto_dimension 
)
private

Translates a dimension name to its numeric corresponding identifier.

Parameters
dim_nameThe name of the dimension to look up
is_auto_dimensionOptional parameter determining whether dimension is auto or not
Returns
Corresponding identifier

Definition at line 263 of file netcdf_filetype.F90.

264  character(len=*), intent(in) :: dim_name
265  logical, intent(out), optional :: is_auto_dimension
266 
267  integer :: dash_idx
268  logical :: is_modified_size
269 
270  dash_idx=index(dim_name, "_")
271  dash_idx=dash_idx-1
272  is_modified_size=dash_idx .ne. -1
273  if (.not. is_modified_size) dash_idx=len_trim(dim_name)
274 
275  if (dim_name(:dash_idx) .eq. "z" .or. dim_name(:dash_idx) .eq. "zn") then
276  get_dimension_identifier=z_index
277  else if (dim_name(:dash_idx) .eq. "y") then
278  get_dimension_identifier=y_index
279  else if (dim_name(:dash_idx) .eq. "x") then
280  get_dimension_identifier=x_index
281  else
282  get_dimension_identifier=-1
283  end if
284 
285  if (present(is_auto_dimension)) is_auto_dimension=is_modified_size
Here is the caller graph for this function:

◆ get_dimension_original_size()

integer function netcdf_filetype_writer_mod::get_dimension_original_size ( character(len=*), intent(in)  dim_name,
type(map_type), intent(inout)  dimension_store 
)
private

Retrieves the original size of a specific dimension (which is auto)

Parameters
dim_nameThe auto dimension (full) name
dimension_storeThe map of dimensions we are looking up
Returns
The original size of this auto dimension

Definition at line 292 of file netcdf_filetype.F90.

293  character(len=*), intent(in) :: dim_name
294  type(map_type), intent(inout) :: dimension_store
295 
296  integer :: dash_idx
297 
298  dash_idx=index(dim_name, "_")
299  dash_idx=dash_idx-1
300  if (dash_idx .eq. -1) dash_idx=len_trim(dim_name)
301 
302  get_dimension_original_size=c_get_integer(dimension_store, dim_name(:dash_idx))
Here is the caller graph for this function:

◆ get_field_key()

character(len=string_length) function netcdf_filetype_writer_mod::get_field_key ( type(writer_field_type), intent(in)  field_to_write_information)
private

Retrieves the field key, corresponding to the field name in the NetCDF file and what we store against the id in the NetCDF file state internally. This is either the field name itself or the manipulation type appended if there is duplication.

Parameters
field_to_write_informationThe field to get the key from
Returns
The field name key

Definition at line 1204 of file netcdf_filetype.F90.

1205  type(writer_field_type), intent(in) :: field_to_write_information
1206 
1207  get_field_key=field_to_write_information%field_name
1208  if (field_to_write_information%duplicate_field_name) then
1209  if (field_to_write_information%time_manipulation_type == instantaneous_type) then
1210  get_field_key=trim(get_field_key)//"_instantaneous"
1211  else if (field_to_write_information%time_manipulation_type == time_averaged_type) then
1212  get_field_key=trim(get_field_key)//"_timeaveraged"
1213  end if
1214  end if
Here is the caller graph for this function:

◆ get_file_state()

type(netcdf_diagnostics_type) function, pointer netcdf_filetype_writer_mod::get_file_state ( character(len=*), intent(in)  filename,
integer, intent(in)  timestep,
logical, intent(in)  dolock 
)
private

Retrieves a file state based upon its timestep or null if none is found.

Parameters
filenameThe filename to look up
timestepThe timestep to look up
dolockWhether to issue a read lock or not
Returns
The corresponding file state entry or null if none is found

Definition at line 1177 of file netcdf_filetype.F90.

1178  character(len=*), intent(in) :: filename
1179  integer, intent(in) :: timestep
1180  logical, intent(in) :: dolock
1181  type(netcdf_diagnostics_type), pointer :: get_file_state
1182 
1183  class(*), pointer :: generic
1184 
1185  if (dolock) call check_thread_status(forthread_rwlock_rdlock(file_states_rwlock))
1186  generic=>c_get_generic(file_states, trim(filename)//"#"//trim(conv_to_string(timestep)))
1187  if (dolock) call check_thread_status(forthread_rwlock_unlock(file_states_rwlock))
1188 
1189  if (associated(generic)) then
1190  select type(generic)
1191  type is (netcdf_diagnostics_type)
1192  get_file_state=>generic
1193  end select
1194  else
1195  get_file_state=>null()
1196  end if
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_next_collective_descriptor()

type(write_field_collective_descriptor_type) function, pointer netcdf_filetype_writer_mod::get_next_collective_descriptor ( type(iterator_type), intent(inout)  iterator)
private

Retrieves the next collective descriptor based upon the iterator.

Parameters
iteratorThe iterator to retrieve from, this is updated to reference the proceeding entry
Returns
The next collective descriptor

Definition at line 496 of file netcdf_filetype.F90.

497  type(iterator_type), intent(inout) :: iterator
498  type(write_field_collective_descriptor_type), pointer :: get_next_collective_descriptor
499 
500  class(*), pointer :: generic
501 
502  generic=>c_next_generic(iterator)
503  select type(generic)
504  type is (write_field_collective_descriptor_type)
505  get_next_collective_descriptor=>generic
506  end select
Here is the caller graph for this function:

◆ get_next_specific_monc_info()

type(write_field_collective_monc_info_type) function, pointer netcdf_filetype_writer_mod::get_next_specific_monc_info ( type(iterator_type iterator)
private

Retrieves the next specific monc information item from the iterator.

Parameters
iteratorThe iterator to retrieve from, this is updated to reference the proceeding entry
Returns
The next specific monc information item

Definition at line 512 of file netcdf_filetype.F90.

513  type(iterator_type) :: iterator
514  type(write_field_collective_monc_info_type), pointer :: get_next_specific_monc_info
515 
516  class(*), pointer :: generic
517 
518  generic=>c_next_generic(iterator)
519  select type(generic)
520  type is (write_field_collective_monc_info_type)
521  get_next_specific_monc_info=>generic
522  end select
Here is the caller graph for this function:

◆ get_number_timeseries_entries()

integer function netcdf_filetype_writer_mod::get_number_timeseries_entries ( type(map_type), intent(inout)  time_points,
real, intent(in)  previous_write_time,
real, intent(in)  output_frequency,
integer, intent(in)  timestep_frequency,
logical, intent(in)  termination_write,
real, intent(out)  last_write_entry 
)
private

Retrieves the number of timeseries entries for a specific frequency and previous write time. This is based on the range of time points that are provided to the call.

Parameters
time_pointsThe list of times that data has been sent over that is applicable to this write
previous_write_timeWhen the field was previously written
frequencyThe frequency of outputs of the field

Definition at line 883 of file netcdf_filetype.F90.

885  type(map_type), intent(inout) :: time_points
886  real, intent(in) :: output_frequency, previous_write_time
887  integer, intent(in) :: timestep_frequency
888  logical, intent(in) :: termination_write
889  real, intent(out) :: last_write_entry
890 
891  integer :: ts
892  real :: tp_entry, write_point
893  type(iterator_type) :: iterator
894  type(mapentry_type) :: map_entry
895  logical :: include_item
896 
897  get_number_timeseries_entries=0
898  write_point=previous_write_time
899  iterator=c_get_iterator(time_points)
900  do while (c_has_next(iterator))
901  map_entry=c_next_mapentry(iterator)
902  ts=conv_to_integer(map_entry%key)
903  if (timestep_frequency .gt. 0) then
904  include_item=mod(ts, timestep_frequency) == 0
905  else
906  include_item=.false.
907  end if
908  if (include_item .or. (.not. c_has_next(iterator) .and. termination_write)) then
909  tp_entry=c_get_real(map_entry)
910  if (tp_entry .ge. write_point+output_frequency) then
911  get_number_timeseries_entries=get_number_timeseries_entries+1
912  write_point=tp_entry
913  last_write_entry=tp_entry
914  end if
915  end if
916  end do
Here is the caller graph for this function:

◆ get_specific_timeseries_dimension()

type(netcdf_diagnostics_timeseries_type) function, pointer netcdf_filetype_writer_mod::get_specific_timeseries_dimension ( type(netcdf_diagnostics_type), intent(inout)  file_state,
real, intent(in)  output_frequency,
integer, intent(in)  timestep_frequency 
)
private

Given the file state and the output frequency of a field will retrive the appropriate time series dimension entry that corresponds to this or null if none can be found.

Parameters
file_stateThe NetCDF file state that is being written
output_frequencyTime frequency of writes
timestep_frequencyThe timestep frequency of data arrival/generation
Returns
The corresponding time series dimension entry or null if none is found

Definition at line 1110 of file netcdf_filetype.F90.

1111  type(netcdf_diagnostics_type), intent(inout) :: file_state
1112  real, intent(in) :: output_frequency
1113  integer, intent(in) :: timestep_frequency
1114  type(netcdf_diagnostics_timeseries_type), pointer :: get_specific_timeseries_dimension
1115 
1116  character(len=STRING_LENGTH) :: dim_key
1117  class(*), pointer :: generic
1118 
1119  if (output_frequency .lt. 0.0) then
1120  dim_key="time_series_"//trim(conv_to_string(timestep_frequency))
1121  else
1122  dim_key="time_series_"//trim(conv_to_string(timestep_frequency))//"_"// trim(conv_to_string(output_frequency))
1123  end if
1124  generic=>c_get_generic(file_state%timeseries_dimension, dim_key)
1125 
1126  if (associated(generic)) then
1127  select type(generic)
1128  type is(netcdf_diagnostics_timeseries_type)
1129  get_specific_timeseries_dimension=>generic
1130  end select
1131  else
1132  get_specific_timeseries_dimension=>null()
1133  end if
Here is the caller graph for this function:

◆ get_writer_entry_from_netcdf()

type(writer_type) function, pointer, public netcdf_filetype_writer_mod::get_writer_entry_from_netcdf ( character(len=string_length)  field_name,
integer  timestep,
logical, intent(out), optional  terminated 
)

Looks up and retrieves the writer entry that corresponds to this NetCDF file state.

Parameters
field_nameThe field name that is being communicated
timestepThe write timestep
Returns
The writer entry

Definition at line 175 of file netcdf_filetype.F90.

176  character(len=STRING_LENGTH) :: field_name
177  integer :: timestep
178  logical, intent(out), optional :: terminated
179  type(writer_type), pointer :: get_writer_entry_from_netcdf
180 
181  type(netcdf_diagnostics_type), pointer :: file_state
182 
183  file_state=>get_file_state(field_name, timestep, .true.)
184  if (present(terminated)) terminated=file_state%termination_write
185  get_writer_entry_from_netcdf=>file_state%corresponding_writer_entry
Here is the call graph for this function:

◆ initialise_netcdf_filetype()

subroutine, public netcdf_filetype_writer_mod::initialise_netcdf_filetype

Initialises the NetCDF writing functionality.

Definition at line 52 of file netcdf_filetype.F90.

53  call check_thread_status(forthread_rwlock_init(file_states_rwlock, -1))
54  call check_thread_status(forthread_mutex_init(netcdf_mutex, -1))
Here is the call graph for this function:
Here is the caller graph for this function:

◆ retrieve_time_series_dimension_id_for_field()

integer function netcdf_filetype_writer_mod::retrieve_time_series_dimension_id_for_field ( type(netcdf_diagnostics_type), intent(inout)  file_state,
type(writer_type), intent(in)  file_writer_information,
integer, intent(in)  field_index 
)
private

For a specific field will retrieve the NetCDF id of the time series dimension most appropriate for this field. If a dimension can not be located then an error is raised.

Parameters
file_stateNetCDF file state
file_writer_informationThe writer information
field_indexIndex of the field in the writer information contents that we are writing
Returns
The NetCDF dimension id

Definition at line 1086 of file netcdf_filetype.F90.

1087  type(netcdf_diagnostics_type), intent(inout) :: file_state
1088  type(writer_type), intent(in) :: file_writer_information
1089  integer, intent(in) :: field_index
1090 
1091  type(netcdf_diagnostics_timeseries_type), pointer :: timeseries_diag
1092 
1093  timeseries_diag=>get_specific_timeseries_dimension(file_state, &
1094  file_writer_information%contents(field_index)%output_frequency, &
1095  file_writer_information%contents(field_index)%timestep_frequency)
1096  if (associated(timeseries_diag)) then
1097  retrieve_time_series_dimension_id_for_field=timeseries_diag%netcdf_dim_id
1098  else
1099  call log_log(log_error, "Can not find time series dimension with output frequency "//&
1100  trim(conv_to_string(file_writer_information%contents(field_index)%output_frequency)))
1101  end if
Here is the call graph for this function:
Here is the caller graph for this function:

◆ store_io_server_state()

subroutine, public netcdf_filetype_writer_mod::store_io_server_state ( type(io_configuration_type), intent(inout)  io_configuration,
type(writer_type), dimension(:), intent(inout), volatile  writer_entries,
type(hashmap_type), intent(inout), volatile  time_points,
type(writer_type), intent(inout), target  file_writer_information,
integer, intent(in)  timestep 
)

Stores the IO server state in the NetCDF file.

Parameters
io_configurationThe IO server configuration
file_writer_informationThe file writer information
timestepThe write timestep

Definition at line 151 of file netcdf_filetype.F90.

152  type(io_configuration_type), intent(inout) :: io_configuration
153  type(writer_type), volatile, dimension(:), intent(inout) :: writer_entries
154  type(hashmap_type), volatile, intent(inout) :: time_points
155  type(writer_type), intent(inout), target :: file_writer_information
156  integer, intent(in) :: timestep
157 
158  type(netcdf_diagnostics_type), pointer :: ncdf_writer_state
159 
160  ncdf_writer_state=>get_file_state(file_writer_information%filename, timestep, .true.)
161  call lock_mpi()
162  call check_netcdf_status(nf90_redef(ncdf_writer_state%ncid))
163  call unlock_mpi()
164  call define_io_server_state_contributions(io_configuration, writer_entries, time_points, ncdf_writer_state)
165  call lock_mpi()
166  call check_netcdf_status(nf90_enddef(ncdf_writer_state%ncid))
167  call unlock_mpi()
168  call write_io_server_state(io_configuration, writer_entries, time_points, ncdf_writer_state)
Here is the call graph for this function:

◆ write_collective_variable_to_diagnostics()

subroutine netcdf_filetype_writer_mod::write_collective_variable_to_diagnostics ( type(io_configuration_type), intent(inout)  io_configuration,
type(writer_field_type), intent(inout)  field_to_write_information,
integer, intent(in)  timestep,
real, intent(in)  time,
type(netcdf_diagnostics_type), intent(inout)  file_state 
)
private

Writes collective variables, where we are working with the values from multiple MONCs and storing these in their own specific relative location in the diagnostics file.

Parameters
field_to_write_informationThe field that is going to be written
timestepThe write timestep
timeThe write time
file_stateFile storate state

Definition at line 531 of file netcdf_filetype.F90.

532  type(io_configuration_type), intent(inout) :: io_configuration
533  type(writer_field_type), intent(inout) :: field_to_write_information
534  integer, intent(in) :: timestep
535  real, intent(in) :: time
536  type(netcdf_diagnostics_type), intent(inout) :: file_state
537 
538  real :: value_to_test
539  integer :: i, k, included_num, field_id, start(field_to_write_information%dimensions+1), &
540  count(field_to_write_information%dimensions+1), monc_location, dim_identifier, auto_period, dim_start
541  class(*), pointer :: generic
542  type(write_field_collective_values_type), pointer :: multi_monc_entries
543  logical :: is_auto_dimension
544  real(kind=default_precision), dimension(:), allocatable :: timeseries_time_to_write
545  character(len=STRING_LENGTH), dimension(:), allocatable :: items_to_remove
546  type(data_values_type), pointer :: data_value
547  type(netcdf_diagnostics_timeseries_type), pointer :: timeseries_diag
548  type(iterator_type) :: value_to_write_iterator, monc_entries_iterator
549  type(mapentry_type) :: value_to_write_map_entry, monc_entries_map_entry
550 
551  timeseries_diag=>get_specific_timeseries_dimension(file_state, field_to_write_information%output_frequency, &
552  field_to_write_information%timestep_frequency)
553  if (.not. timeseries_diag%variable_written) allocate(timeseries_time_to_write(timeseries_diag%num_entries))
554 
555  allocate(items_to_remove(timeseries_diag%num_entries))
556  included_num=1
557  field_id=c_get_integer(file_state%variable_to_id, get_field_key(field_to_write_information))
558  value_to_write_iterator=c_get_iterator(field_to_write_information%values_to_write)
559  do while (c_has_next(value_to_write_iterator))
560  value_to_write_map_entry=c_next_mapentry(value_to_write_iterator)
561  value_to_test=conv_to_real(value_to_write_map_entry%key)
562  if (value_to_test .le. time .and. value_to_test .gt. field_to_write_information%previous_write_time) then
563  if (included_num .le. timeseries_diag%num_entries) then
564  if (allocated(timeseries_time_to_write)) timeseries_time_to_write(included_num)=value_to_test
565  generic=>c_get_generic(value_to_write_map_entry)
566  select type(generic)
567  type is(write_field_collective_values_type)
568  multi_monc_entries=>generic
569  end select
570  monc_entries_iterator=c_get_iterator(multi_monc_entries%monc_values)
571  do while(c_has_next(monc_entries_iterator))
572  monc_entries_map_entry=c_next_mapentry(monc_entries_iterator)
573  data_value=>get_data_value_by_field_name(multi_monc_entries%monc_values, monc_entries_map_entry%key)
574  monc_location=c_get_integer(io_configuration%monc_to_index, monc_entries_map_entry%key)
575  do k=1, field_to_write_information%dimensions
576  dim_identifier=get_dimension_identifier(field_to_write_information%dim_size_defns(k), is_auto_dimension)
577  if (dim_identifier .gt. -1) then
578  start(k)=io_configuration%registered_moncs(monc_location)%local_dim_starts(dim_identifier)
579  count(k)=io_configuration%registered_moncs(monc_location)%local_dim_sizes(dim_identifier)
580  if (is_auto_dimension) then
581  auto_period=ceiling(real(get_dimension_original_size(field_to_write_information%dim_size_defns(k), &
582  io_configuration%dimension_sizing))/field_to_write_information%actual_dim_size(k))
583  start(k)=(start(k)/auto_period)+1
584  if (io_configuration%registered_moncs(monc_location)%local_dim_starts(dim_identifier)==1) then
585  dim_start=1
586  else
587  dim_start=auto_period - &
588  mod(io_configuration%registered_moncs(monc_location)%local_dim_starts(dim_identifier)-2, auto_period)
589  end if
590  count(k)=ceiling(real(io_configuration%registered_moncs(monc_location)%local_dim_sizes(dim_identifier) - &
591  (dim_start-1))/auto_period)
592  end if
593  else
594  call log_log(log_error, "Can not locate dimension "//trim(field_to_write_information%dim_size_defns(k)))
595  end if
596  end do
597  start(field_to_write_information%dimensions+1) = included_num
598  count(field_to_write_information%dimensions+1) = 1
599  call check_thread_status(forthread_mutex_lock(file_state%mutex))
600  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
601  call lock_mpi()
602  call check_netcdf_status(nf90_put_var(file_state%ncid, field_id, data_value%values, start=start, count=count))
603  call unlock_mpi()
604  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
605  call check_thread_status(forthread_mutex_unlock(file_state%mutex))
606  deallocate(data_value%values)
607  deallocate(data_value)
608  end do
609  items_to_remove(included_num)=value_to_write_map_entry%key
610  included_num=included_num+1
611  call c_free(multi_monc_entries%monc_values)
612  deallocate(multi_monc_entries)
613  else
614  call log_log(log_warn, "Omitted time entry of field '"//trim(field_to_write_information%field_name)//&
615  "' as past dimension length at time "//conv_to_string(value_to_test))
616  end if
617  end if
618  end do
619  if (included_num-1 .ne. timeseries_diag%num_entries) then
620  call log_log(log_warn, "Miss match of time entries for field '"//trim(field_to_write_information%field_name)//&
621  "', included entries="//trim(conv_to_string(included_num-1))//" but expected entries="//&
622  trim(conv_to_string(timeseries_diag%num_entries)))
623  end if
624  if (allocated(timeseries_time_to_write)) then
625  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
626  call lock_mpi()
627  call check_netcdf_status(nf90_put_var(file_state%ncid, timeseries_diag%netcdf_var_id, &
628  timeseries_time_to_write, count=(/ timeseries_diag%num_entries /)))
629  call unlock_mpi()
630  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
631  timeseries_diag%variable_written=.true.
632  end if
633  if (included_num .gt. 1) then
634  do i=1, included_num-1
635  call c_remove(field_to_write_information%values_to_write, items_to_remove(i))
636  end do
637  end if
638  deallocate(items_to_remove)
639  if (allocated(timeseries_time_to_write)) deallocate(timeseries_time_to_write)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_condition_variable()

subroutine netcdf_filetype_writer_mod::write_condition_variable ( type(netcdf_diagnostics_type), intent(inout)  file_state,
integer, intent(in)  c_var_id,
character(len=string_length), dimension(:), intent(in)  field_values 
)
private

Writes the conditional diagnostic variable names into the NetCDF file.

Parameters
file_stateThe NetCDF file state
c_var_idThe variable id in the file
field_valuesThe field values to write

Definition at line 326 of file netcdf_filetype.F90.

327  type(netcdf_diagnostics_type), intent(inout) :: file_state
328  integer, intent(in) :: c_var_id
329  character(len=STRING_LENGTH), dimension(:), intent(in) :: field_values
330 
331  integer :: count_to_write(2), start_pos(2)
332  integer :: pos, string_size
333  character(len=STRING_LENGTH) :: dum_string
334 
335  count_to_write(2)=1 ! element count
336  start_pos(1)=1 ! string character start position
337  call lock_mpi()
338  do pos=1,size(field_values)
339  dum_string = trim(field_values(pos))
340  count_to_write(1) = len(trim(field_values(pos)))
341  start_pos(2)=pos
342  call check_netcdf_status(nf90_put_var(file_state%ncid, c_var_id, dum_string, &
343  start=start_pos, count=count_to_write))
344  end do
345  call unlock_mpi()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_contiguous_collective_variable_to_diagnostics()

subroutine netcdf_filetype_writer_mod::write_contiguous_collective_variable_to_diagnostics ( type(io_configuration_type), intent(inout)  io_configuration,
type(writer_field_type), intent(inout)  field_to_write_information,
integer, intent(in)  timestep,
real, intent(in)  time,
type(netcdf_diagnostics_type), intent(inout)  file_state 
)
private

Writes contiguous collective variable blocks into the NetCDF files. These are blocks of data spanning multiple variables and multiple time points, the idea being to minimise the number of overall writes into the file. These variables are defined collective, so it might be that other IO servers have less contiguous data and hence more writes, therefore empty writes might need to be issued (at the end) to match up against these other servers.

Parameters
io_configurationThe IO server configuration
field_to_write_informationThe field to write
timestepThe current model timestep
timeThe current model time
file_stateSpecific file state descriptor

Definition at line 357 of file netcdf_filetype.F90.

359  type(io_configuration_type), intent(inout) :: io_configuration
360  type(writer_field_type), intent(inout) :: field_to_write_information
361  integer, intent(in) :: timestep
362  real, intent(in) :: time
363  type(netcdf_diagnostics_type), intent(inout) :: file_state
364 
365  real :: value_to_test
366  real(kind=default_precision), dimension(:,:,:,:), allocatable :: contiguous_values
367  type(hashset_type) :: items_to_remove
368  real(kind=default_precision), dimension(:), allocatable :: timeseries_time_to_write
369  type(iterator_type) :: value_to_write_iterator, collective_descriptor_iterator, monc_iterator, value_to_remove_iterator
370  type(mapentry_type) :: value_to_write_map_entry
371  class(*), pointer :: generic
372  type(write_field_collective_descriptor_type), pointer :: collective_descriptor
373  type(netcdf_diagnostics_timeseries_type), pointer :: timeseries_diag
374  type(write_field_collective_monc_info_type), pointer :: monc_descriptor
375  type(write_field_collective_values_type), pointer :: multi_monc_entries
376  type(data_values_type), pointer :: data_value
377  integer :: number_time_entries, i, start(4), count(4), field_id, ierr
378  character(len=STRING_LENGTH) :: removal_key
379 
380  timeseries_diag=>get_specific_timeseries_dimension(file_state, field_to_write_information%output_frequency, &
381  field_to_write_information%timestep_frequency)
382  field_id=c_get_integer(file_state%variable_to_id, get_field_key(field_to_write_information))
383  if (.not. timeseries_diag%variable_written) allocate(timeseries_time_to_write(timeseries_diag%num_entries))
384 
385  number_time_entries=0
386  value_to_write_iterator=c_get_iterator(field_to_write_information%values_to_write)
387  do while (c_has_next(value_to_write_iterator))
388  value_to_write_map_entry=c_next_mapentry(value_to_write_iterator)
389  value_to_test=conv_to_real(value_to_write_map_entry%key)
390  if (value_to_test .le. time .and. value_to_test .gt. field_to_write_information%previous_write_time) then
391  number_time_entries=number_time_entries+1
392  call c_add_string(items_to_remove, value_to_write_map_entry%key)
393  end if
394  end do
395 
396  if (number_time_entries .ne. timeseries_diag%num_entries) then
397  call log_log(log_warn, "Expected "//trim(conv_to_string(timeseries_diag%num_entries))//&
398  " but have "//trim(conv_to_string(number_time_entries)))
399  if (number_time_entries .gt. timeseries_diag%num_entries) number_time_entries=timeseries_diag%num_entries
400  end if
401 
402  collective_descriptor_iterator=c_get_iterator(field_to_write_information%collective_descriptors)
403  do while (c_has_next(collective_descriptor_iterator))
404  collective_descriptor=>get_next_collective_descriptor(collective_descriptor_iterator)
405  allocate(contiguous_values(collective_descriptor%count(1), collective_descriptor%count(2), &
406  collective_descriptor%count(3), number_time_entries))
407  monc_iterator=c_get_iterator(collective_descriptor%specific_monc_info)
408  do while (c_has_next(monc_iterator))
409  monc_descriptor=>get_next_specific_monc_info(monc_iterator)
410  value_to_write_iterator=c_get_iterator(field_to_write_information%values_to_write)
411  i=0
412  do while (c_has_next(value_to_write_iterator))
413  value_to_write_map_entry=c_next_mapentry(value_to_write_iterator)
414  value_to_test=conv_to_real(value_to_write_map_entry%key)
415  if (value_to_test .le. time .and. value_to_test .gt. field_to_write_information%previous_write_time) then
416  i=i+1
417  if (allocated(timeseries_time_to_write)) timeseries_time_to_write(i)=value_to_test
418  generic=>c_get_generic(value_to_write_map_entry)
419  select type(generic)
420  type is(write_field_collective_values_type)
421  multi_monc_entries=>generic
422  end select
423  data_value=>get_data_value_by_field_name(multi_monc_entries%monc_values, &
424  trim(conv_to_string(monc_descriptor%monc_source)))
425  if (collective_descriptor%split_dim == y_index) then
426  contiguous_values(:,monc_descriptor%relative_dimension_start:monc_descriptor%relative_dimension_start+&
427  monc_descriptor%counts(y_index)-1,:,i)=reshape(data_value%values, (/ monc_descriptor%counts(z_index), &
428  monc_descriptor%counts(y_index), monc_descriptor%counts(x_index)/))
429  else
430  contiguous_values(:,:,monc_descriptor%relative_dimension_start:monc_descriptor%relative_dimension_start+&
431  monc_descriptor%counts(x_index)-1,i)=reshape(data_value%values, (/ monc_descriptor%counts(z_index), &
432  monc_descriptor%counts(y_index), monc_descriptor%counts(x_index)/))
433  end if
434  deallocate(data_value%values)
435  deallocate(data_value)
436  end if
437  end do
438  end do
439  count(1:3)=collective_descriptor%count
440  count(4)=number_time_entries
441  start(1:3)=collective_descriptor%absolute_start
442  start(4)=1
443  call check_thread_status(forthread_mutex_lock(file_state%mutex))
444  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
445  call lock_mpi()
446  call check_netcdf_status(nf90_put_var(file_state%ncid, field_id, contiguous_values, start=start, count=count))
447  call unlock_mpi()
448  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
449  call check_thread_status(forthread_mutex_unlock(file_state%mutex))
450  deallocate(contiguous_values)
451  if (allocated(timeseries_time_to_write)) then
452  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
453  call lock_mpi()
454  call check_netcdf_status(nf90_put_var(file_state%ncid, timeseries_diag%netcdf_var_id, &
455  timeseries_time_to_write, count=(/ timeseries_diag%num_entries /)))
456  call unlock_mpi()
457  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
458  timeseries_diag%variable_written=.true.
459  deallocate(timeseries_time_to_write)
460  end if
461  end do
462  if (.not. c_is_empty(items_to_remove)) then
463  value_to_remove_iterator=c_get_iterator(items_to_remove)
464  do while (c_has_next(value_to_remove_iterator))
465  removal_key=c_next_string(value_to_remove_iterator)
466  generic=>c_get_generic(field_to_write_information%values_to_write, removal_key)
467  select type(generic)
468  type is(write_field_collective_values_type)
469  multi_monc_entries=>generic
470  end select
471  call c_free(multi_monc_entries%monc_values)
472  deallocate(multi_monc_entries)
473  call c_remove(field_to_write_information%values_to_write, removal_key)
474  end do
475  call c_free(items_to_remove)
476  end if
477  if (field_to_write_information%max_num_collective_writes_request_handle .ne. mpi_request_null) then
478  call wait_for_mpi_request(field_to_write_information%max_num_collective_writes_request_handle)
479  end if
480  if (c_size(field_to_write_information%collective_descriptors) .lt. field_to_write_information%max_num_collective_writes) then
481  call check_thread_status(forthread_mutex_lock(file_state%mutex))
482  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
483  call lock_mpi()
484  do i=c_size(field_to_write_information%collective_descriptors), field_to_write_information%max_num_collective_writes-1
485  call check_netcdf_status(nf90_put_var(file_state%ncid, field_id, (/1.0/), start=(/1/), count=(/0/)))
486  end do
487  call unlock_mpi()
488  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
489  call check_thread_status(forthread_mutex_unlock(file_state%mutex))
490  end if
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_coordinate_variable()

subroutine netcdf_filetype_writer_mod::write_coordinate_variable ( type(netcdf_diagnostics_type), intent(inout)  file_state,
integer, intent(in)  coord_var_id,
real(kind=default_precision), dimension(:), intent(in)  field_values 
)
private

Writes a coordinate variable into the NetCDF file.

Parameters
file_stateThe NetCDF file state
coord_var_idThe coordinate variable id in the file
field_valuesThe field values to write

Definition at line 309 of file netcdf_filetype.F90.

310  type(netcdf_diagnostics_type), intent(inout) :: file_state
311  integer, intent(in) :: coord_var_id
312  real(kind=default_precision), dimension(:), intent(in) :: field_values
313 
314  integer :: count_to_write(1)
315 
316  count_to_write(1)=size(field_values)
317  call lock_mpi()
318  call check_netcdf_status(nf90_put_var(file_state%ncid, coord_var_id, field_values, count=count_to_write))
319  call unlock_mpi()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_independent_variable_to_diagnostics()

subroutine netcdf_filetype_writer_mod::write_independent_variable_to_diagnostics ( type(writer_field_type), intent(inout)  field_to_write_information,
integer, intent(in)  timestep,
real, intent(in)  time,
type(netcdf_diagnostics_type), intent(inout)  file_state 
)
private

Writes independent variables to the diagnostics file. This writes the entire variable and works by writing all the memory up and then doing the write in one call.

Parameters
field_to_write_informationThe field that is going to be written
timestepThe write timestep
timeThe write time
file_stateFile storate state

Definition at line 648 of file netcdf_filetype.F90.

649  type(writer_field_type), intent(inout) :: field_to_write_information
650  integer, intent(in) :: timestep
651  real, intent(in) :: time
652  type(netcdf_diagnostics_type), intent(inout) :: file_state
653 
654  if (field_to_write_information%field_type == array_field_type .or. &
655  field_to_write_information%field_type == scalar_field_type) then
656  if (field_to_write_information%data_type == double_data_type .or. &
657  field_to_write_information%data_type == integer_data_type) then
658  call write_out_number_values(field_to_write_information, timestep, time, file_state)
659  end if
660  else if (field_to_write_information%field_type == map_field_type) then
661  call write_out_map(field_to_write_information, timestep, time, file_state)
662  end if
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_out_global_attributes()

subroutine netcdf_filetype_writer_mod::write_out_global_attributes ( type(io_configuration_type), intent(inout)  io_configuration,
integer, intent(in)  ncid,
type(writer_type), intent(inout)  file_writer_information,
integer, intent(in)  timestep,
real, intent(in)  time 
)
private

Writes out global attributes into the checkpoint.

Parameters
ncidNetCDF file id

Definition at line 1248 of file netcdf_filetype.F90.

1249  type(io_configuration_type), intent(inout) :: io_configuration
1250  integer, intent(in) :: ncid, timestep
1251  type(writer_type), intent(inout) :: file_writer_information
1252  real, intent(in) :: time
1253 
1254  integer :: date_values(8), ierr
1255  character(len=50) :: date_time
1256 
1257  call date_and_time(values=date_values)
1258  call lock_mpi()
1259  call mpi_bcast(date_values, 8, mpi_int, 0, io_configuration%io_communicator, ierr)
1260  call unlock_mpi()
1261  date_time=trim(conv_to_string(date_values(3)))//"/"//&
1262  trim(conv_to_string(date_values(2)))//"/"//trim(conv_to_string(date_values(1)))//" "//trim(conv_to_string(&
1263  date_values(5)))// ":"//trim(conv_to_string(date_values(6)))//":"//trim(conv_to_string(date_values(7)))
1264 
1265  call lock_mpi()
1266  call check_netcdf_status(nf90_put_att(ncid, nf90_global, "title", file_writer_information%title))
1267  call check_netcdf_status(nf90_put_att(ncid, nf90_global, "created", date_time))
1268  call check_netcdf_status(nf90_put_att(ncid, nf90_global, "MONC time", trim(conv_to_string(time))))
1269  call check_netcdf_status(nf90_put_att(ncid, nf90_global, "MONC timestep", trim(conv_to_string(timestep))))
1270  call check_netcdf_status(nf90_put_att(ncid, nf90_global, "Diagnostic write frequency", &
1271  trim(conv_to_string(file_writer_information%write_time_frequency))))
1272  call check_netcdf_status(nf90_put_att(ncid, nf90_global, "Previous diagnostic write at", &
1273  trim(conv_to_string(file_writer_information%previous_write_time))))
1274  call unlock_mpi()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_out_map()

subroutine netcdf_filetype_writer_mod::write_out_map ( type(writer_field_type), intent(inout)  field_to_write_information,
integer, intent(in)  timestep,
real, intent(in)  time,
type(netcdf_diagnostics_type), intent(inout)  file_state 
)
private

Definition at line 749 of file netcdf_filetype.F90.

750  type(writer_field_type), intent(inout) :: field_to_write_information
751  integer, intent(in) :: timestep
752  real, intent(in) :: time
753  type(netcdf_diagnostics_type), intent(inout) :: file_state
754 
755  integer :: i, j, field_id, included_num
756  real :: value_to_test
757  type(iterator_type) :: iterator, map_data_iterator
758  type(mapentry_type) :: map_entry, map_data_entry
759  type(data_values_type), pointer :: data_value
760  character(len=STRING_LENGTH), dimension(:), allocatable :: items_to_remove
761 
762  field_id=c_get_integer(file_state%variable_to_id, get_field_key(field_to_write_information))
763  included_num=1
764  j=1
765  allocate(items_to_remove(c_size(field_to_write_information%values_to_write)))
766  iterator=c_get_iterator(field_to_write_information%values_to_write)
767  do while (c_has_next(iterator))
768  map_entry=c_next_mapentry(iterator)
769  value_to_test=conv_to_real(map_entry%key)
770  if (value_to_test .le. time .and. value_to_test .gt. field_to_write_information%previous_write_time) then
771  items_to_remove(included_num)=map_entry%key
772  included_num=included_num+1
773  data_value=>get_data_value_by_field_name(field_to_write_information%values_to_write, map_entry%key)
774  map_data_iterator=c_get_iterator(data_value%map_values)
775  i=1
776  call check_thread_status(forthread_mutex_lock(file_state%mutex))
777  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
778  call lock_mpi()
779  do while (c_has_next(map_data_iterator))
780  map_data_entry=c_next_mapentry(map_data_iterator)
781  call check_netcdf_status(nf90_put_var(file_state%ncid, field_id, trim(map_data_entry%key), (/ 1, 1, i, j /)))
782  call check_netcdf_status(nf90_put_var(file_state%ncid, field_id, trim(c_get_string(map_data_entry)), (/ 1, 2, i, j /)))
783  call c_remove(data_value%map_values, map_data_entry%key)
784  i=i+1
785  end do
786  call unlock_mpi()
787  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
788  call check_thread_status(forthread_mutex_unlock(file_state%mutex))
789  call c_free(data_value%map_values)
790  j=j+1
791  end if
792  end do
793  if (included_num .gt. 1) then
794  do i=1, included_num-1
795  call c_remove(field_to_write_information%values_to_write, items_to_remove(i))
796  end do
797  end if
798  deallocate(items_to_remove)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_out_number_values()

subroutine netcdf_filetype_writer_mod::write_out_number_values ( type(writer_field_type), intent(inout)  field_to_write_information,
integer, intent(in)  timestep,
real, intent(in)  time,
type(netcdf_diagnostics_type), intent(inout)  file_state 
)
private

Definition at line 665 of file netcdf_filetype.F90.

666  type(writer_field_type), intent(inout) :: field_to_write_information
667  integer, intent(in) :: timestep
668  real, intent(in) :: time
669  type(netcdf_diagnostics_type), intent(inout) :: file_state
670 
671  real(kind=default_precision), dimension(:), allocatable :: values_to_write, timeseries_time_to_write
672  real :: value_to_test
673  integer :: i, field_id, next_entry_index, array_size, included_num
674  integer, dimension(:), allocatable :: count_to_write
675  type(iterator_type) :: iterator
676  type(mapentry_type) :: map_entry
677 
678  type(data_values_type), pointer :: data_value
679  character(len=STRING_LENGTH), dimension(:), allocatable :: items_to_remove
680  type(netcdf_diagnostics_timeseries_type), pointer :: timeseries_diag
681 
682  timeseries_diag=>get_specific_timeseries_dimension(file_state, field_to_write_information%output_frequency, &
683  field_to_write_information%timestep_frequency)
684 
685  next_entry_index=1
686  included_num=1
687  array_size=1
688 
689  if (.not. timeseries_diag%variable_written) allocate(timeseries_time_to_write(timeseries_diag%num_entries))
690 
691  allocate(count_to_write(field_to_write_information%dimensions+1))
692  if (field_to_write_information%dimensions .gt. 0) then
693  do i=1, field_to_write_information%dimensions
694  array_size=array_size*field_to_write_information%actual_dim_size(i)
695  count_to_write(i)=field_to_write_information%actual_dim_size(i)
696  end do
697  end if
698  allocate(values_to_write(array_size*timeseries_diag%num_entries))
699  allocate(items_to_remove(timeseries_diag%num_entries))
700  iterator=c_get_iterator(field_to_write_information%values_to_write)
701  do while (c_has_next(iterator))
702  map_entry=c_next_mapentry(iterator)
703  value_to_test=conv_to_real(map_entry%key)
704  if (value_to_test .le. time .and. value_to_test .gt. field_to_write_information%previous_write_time) then
705  data_value=>get_data_value_by_field_name(field_to_write_information%values_to_write, map_entry%key)
706  if (size(values_to_write) .ge. next_entry_index+size(data_value%values)-1) then
707  values_to_write(next_entry_index: next_entry_index+size(data_value%values)-1)=data_value%values(:)
708  next_entry_index=next_entry_index+size(data_value%values)
709  deallocate(data_value%values)
710  deallocate(data_value)
711  items_to_remove(included_num)=map_entry%key
712  if (allocated(timeseries_time_to_write)) timeseries_time_to_write(included_num)=value_to_test
713  included_num=included_num+1
714  else
715  call log_log(log_warn, "Omitted time entry of field '"//trim(field_to_write_information%field_name)//&
716  "' as past time dimension length")
717  end if
718  end if
719  end do
720  count_to_write(size(count_to_write))=included_num-1
721  field_id=c_get_integer(file_state%variable_to_id, get_field_key(field_to_write_information))
722  if (included_num-1 .ne. timeseries_diag%num_entries) then
723  call log_log(log_warn, "Miss match of time entries for field '"//trim(field_to_write_information%field_name)//&
724  "', included entries="//trim(conv_to_string(included_num-1))//" but expected entries="//&
725  trim(conv_to_string(timeseries_diag%num_entries)))
726  end if
727  call check_thread_status(forthread_mutex_lock(file_state%mutex))
728  call check_thread_status(forthread_mutex_lock(netcdf_mutex))
729  call lock_mpi()
730  call check_netcdf_status(nf90_put_var(file_state%ncid, field_id, values_to_write, count=count_to_write))
731  if (allocated(timeseries_time_to_write)) then
732  call check_netcdf_status(nf90_put_var(file_state%ncid, timeseries_diag%netcdf_var_id, &
733  timeseries_time_to_write, count=(/ timeseries_diag%num_entries /)))
734  timeseries_diag%variable_written=.true.
735  end if
736  call unlock_mpi()
737  call check_thread_status(forthread_mutex_unlock(netcdf_mutex))
738  call check_thread_status(forthread_mutex_unlock(file_state%mutex))
739  deallocate(values_to_write)
740  if (included_num .gt. 1) then
741  do i=1, included_num-1
742  call c_remove(field_to_write_information%values_to_write, items_to_remove(i))
743  end do
744  end if
745  deallocate(items_to_remove)
746  if (allocated(timeseries_time_to_write)) deallocate(timeseries_time_to_write)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_out_options()

subroutine netcdf_filetype_writer_mod::write_out_options ( type(io_configuration_type), intent(inout)  io_configuration,
type(netcdf_diagnostics_type), intent(inout)  file_state 
)
private

Writes out the options_database defining this model run.

Parameters
io_configurationThe configuration of the IO server

Definition at line 803 of file netcdf_filetype.F90.

804  type(io_configuration_type), intent(inout) :: io_configuration
805  type(netcdf_diagnostics_type), intent(inout) :: file_state
806 
807  integer :: i
808  character(len=STRING_LENGTH), pointer :: sized_raw_character
809  class(*), pointer :: raw_data, raw_to_string
810 
811  call lock_mpi()
812  do i=1,options_size(io_configuration%options_database)
813  raw_data=> options_value_at(io_configuration%options_database, i)
814  raw_to_string=>raw_data
815  call check_netcdf_status(nf90_put_var(file_state%ncid, nopt_var_id, &
816  trim(options_key_at(io_configuration%options_database, i)), (/ 1, 1, i /)))
817  select type (raw_data)
818  type is(integer)
819  call check_netcdf_status(nf90_put_var(file_state%ncid, nopt_var_id, trim(conv_to_string(raw_data)), (/ 1, 2, i /)))
820  type is(real(kind=single_precision))
821  call check_netcdf_status(nf90_put_var(file_state%ncid, nopt_var_id, trim(conv_to_string(raw_data)), (/ 1, 2, i /)))
822  type is(real(kind=double_precision))
823  call check_netcdf_status(nf90_put_var(file_state%ncid, nopt_var_id, trim(conv_to_string(raw_data)), (/ 1, 2, i /)))
824  type is(logical)
825  call check_netcdf_status(nf90_put_var(file_state%ncid, nopt_var_id, trim(conv_to_string(raw_data)), (/ 1, 2, i /)))
826  type is(character(len=*))
827  ! Done this way to give the character size information and keep the (unsafe) cast in the conversion module
828  sized_raw_character=>conv_to_string(raw_to_string, .false., string_length)
829  call check_netcdf_status(nf90_put_var(file_state%ncid, nopt_var_id, trim(sized_raw_character), (/ 1, 2, i /)))
830  end select
831  end do
832  call unlock_mpi()
833 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_variable()

subroutine, public netcdf_filetype_writer_mod::write_variable ( type(io_configuration_type), intent(inout)  io_configuration,
type(writer_field_type), intent(inout)  field_to_write_information,
character(len=*), intent(in)  filename,
integer, intent(in)  timestep,
real, intent(in)  time 
)

Writes the contents of a variable to the NetCDF file. This also removes the written entries from the field information type in order to conserve memory.

Parameters
field_to_write_informationThe field that is going to be written
filenameThe name of the diagnostics file
timestepThe write timestep
timeThe write time

Definition at line 237 of file netcdf_filetype.F90.

238  type(io_configuration_type), intent(inout) :: io_configuration
239  type(writer_field_type), intent(inout) :: field_to_write_information
240  character(len=*), intent(in) :: filename
241  integer, intent(in) :: timestep
242  real, intent(in) :: time
243 
244  type(netcdf_diagnostics_type), pointer :: file_state
245 
246  file_state=>get_file_state(filename, timestep, .true.)
247  if (field_to_write_information%collective_write) then
248  if (field_to_write_information%collective_contiguous_optimisation) then
249  call write_contiguous_collective_variable_to_diagnostics(io_configuration, field_to_write_information, &
250  timestep, time, file_state)
251  else
252  call write_collective_variable_to_diagnostics(io_configuration, field_to_write_information, timestep, time, file_state)
253  end if
254  else
255  call write_independent_variable_to_diagnostics(field_to_write_information, timestep, time, file_state)
256  end if
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ file_states

type(hashmap_type), volatile netcdf_filetype_writer_mod::file_states
private

Definition at line 40 of file netcdf_filetype.F90.

40  type(hashmap_type), volatile :: file_states

◆ file_states_rwlock

integer, volatile netcdf_filetype_writer_mod::file_states_rwlock
private

Definition at line 41 of file netcdf_filetype.F90.

41  integer, volatile :: file_states_rwlock, netcdf_mutex

◆ l_nc_dim

logical netcdf_filetype_writer_mod::l_nc_dim
private

Definition at line 43 of file netcdf_filetype.F90.

43  logical :: l_nc_dim, l_nd_dim

◆ l_nd_dim

logical netcdf_filetype_writer_mod::l_nd_dim
private

Definition at line 43 of file netcdf_filetype.F90.

◆ nc_dim_id

integer netcdf_filetype_writer_mod::nc_dim_id
private

Definition at line 44 of file netcdf_filetype.F90.

44  integer :: nc_dim_id, nd_dim_id, nopt_dim_id

◆ nc_var_id_l

integer netcdf_filetype_writer_mod::nc_var_id_l
private

Definition at line 45 of file netcdf_filetype.F90.

◆ nc_var_id_s

integer netcdf_filetype_writer_mod::nc_var_id_s
private

Definition at line 45 of file netcdf_filetype.F90.

45  integer :: nc_var_id_s, nd_var_id_s, nc_var_id_l, nd_var_id_l, nopt_var_id

◆ nd_dim_id

integer netcdf_filetype_writer_mod::nd_dim_id
private

Definition at line 44 of file netcdf_filetype.F90.

◆ nd_var_id_l

integer netcdf_filetype_writer_mod::nd_var_id_l
private

Definition at line 45 of file netcdf_filetype.F90.

◆ nd_var_id_s

integer netcdf_filetype_writer_mod::nd_var_id_s
private

Definition at line 45 of file netcdf_filetype.F90.

◆ netcdf_mutex

integer, volatile netcdf_filetype_writer_mod::netcdf_mutex
private

Definition at line 41 of file netcdf_filetype.F90.

◆ nopt_dim_id

integer netcdf_filetype_writer_mod::nopt_dim_id
private

Definition at line 44 of file netcdf_filetype.F90.

◆ nopt_var_id

integer netcdf_filetype_writer_mod::nopt_var_id
private

Definition at line 45 of file netcdf_filetype.F90.

logging_mod::log_error
integer, parameter, public log_error
Only log ERROR messages.
Definition: logging.F90:11
logging_mod::log_warn
integer, parameter, public log_warn
Log WARNING and ERROR messages.
Definition: logging.F90:12
logging_mod::log_log
subroutine, public log_log(level, message, str)
Logs a message at the specified level. If the level is above the current level then the message is ig...
Definition: logging.F90:75
logging_mod::log_get_logging_level
integer function, public log_get_logging_level()
Retrieves the current logging level.
Definition: logging.F90:122
logging_mod::log_debug
integer, parameter, public log_debug
Log DEBUG, INFO, WARNING and ERROR messages.
Definition: logging.F90:14
logging_mod::log_master_log
subroutine, public log_master_log(level, message)
Will log just from the master process.
Definition: logging.F90:47
datadefn_mod::default_precision
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data.
Definition: datadefn.F90:17