32 character(len=STRING_LENGTH) :: field_name, field_namespace
33 integer :: timestep, frequency, source
35 real(kind=DEFAULT_PRECISION) :: time
40 integer :: access_mutex, last_timestep_access, frequency
60 logical,
intent(in) :: continuation_run
65 if (continuation_run)
then 80 integer,
intent(in) :: timestep
84 class(*),
pointer :: generic
94 if (generic%last_timestep_access .lt. timestep)
then 111 integer,
intent(in) :: source, data_id
112 character,
dimension(:),
allocatable,
intent(in) :: data_dump
114 integer :: i, num_fields, timestep
115 character(len=STRING_LENGTH) :: field_name, field_namespace
116 real(kind=DEFAULT_PRECISION) :: time
118 logical :: terminated_case
127 io_configuration%data_definitions(data_id)%send_on_terminate
129 terminated_case=.false.
132 num_fields=io_configuration%data_definitions(data_id)%number_of_data_fields
135 field_name=io_configuration%data_definitions(data_id)%fields(i)%name
136 field_namespace=io_configuration%data_definitions(data_id)%fields(i)%namespace
141 io_configuration%data_definitions(data_id)%frequency, source, terminated_case)
147 call log_log(
log_warn,
"Can not run pass MONC fields to writer federator without a time and timestep")
160 integer,
intent(in) :: source, data_id
161 character,
dimension(:),
allocatable,
intent(in) :: data_dump
162 character(len=*),
intent(in) :: field_name, field_namespace
168 integer :: field_data_type, field_field_type, i
169 integer,
dimension(:),
allocatable :: int_values
171 call get_type_of_field(io_configuration%data_definitions(data_id)%fields, field_name, field_namespace, &
172 field_field_type, field_data_type)
173 if (field_data_type == 0)
then 177 if (field_data_type == double_data_type)
then 179 get_value_from_monc_data%data_type=double_data_type
180 else if (field_data_type == integer_data_type)
then 181 get_value_from_monc_data%data_type=double_data_type
183 allocate(get_value_from_monc_data%values(
size(int_values)))
184 do i=1,
size(int_values)
185 get_value_from_monc_data%values(i)=
conv_to_real(int_values(i))
187 deallocate(int_values)
188 else if (field_data_type == string_data_type)
then 189 get_value_from_monc_data%data_type=string_data_type
190 if (field_field_type == scalar_field_type)
then 191 allocate(get_value_from_monc_data%string_values(1))
192 get_value_from_monc_data%string_values(1)=
get_string_from_monc(io_configuration, source, data_id, data_dump, field_name)
193 else if (field_field_type == map_field_type)
then 194 get_value_from_monc_data%map_values=
get_map_from_monc(io_configuration, source, data_id, data_dump, field_name)
203 subroutine get_type_of_field(fields, field_name, field_namespace, field_type, data_type)
205 character(len=*),
intent(in) :: field_name, field_namespace
206 integer,
intent(out) :: field_type, data_type
211 if (fields(i)%name .eq. field_name .and. fields(i)%namespace .eq. field_namespace)
then 212 data_type=fields(i)%data_type
213 field_type=fields(i)%field_type
222 field_values, timestep, time, frequency, source)
224 character(len=*),
intent(in) :: field_name, field_namespace
225 integer,
intent(in) :: timestep, frequency, source
226 real(kind=DEFAULT_PRECISION),
dimension(:),
intent(in) :: field_values
227 real(kind=DEFAULT_PRECISION),
intent(in) :: time
231 allocate(packaged_data%values(
size(field_values)))
232 packaged_data%values=field_values
233 packaged_data%data_type=double_data_type
235 timestep, time, frequency, source)
239 field_values, timestep, time, frequency)
241 character(len=*),
intent(in) :: field_name, field_namespace
242 integer,
intent(in) :: timestep, frequency
243 real(kind=DEFAULT_PRECISION),
dimension(:),
intent(in) :: field_values
244 real(kind=DEFAULT_PRECISION),
intent(in) :: time
247 field_values, timestep, time, frequency, -1)
258 field_values, timestep, time, frequency)
260 character(len=*),
intent(in) :: field_name, field_namespace
261 integer,
intent(in) :: timestep, frequency
263 real(kind=DEFAULT_PRECISION),
intent(in) :: time
266 field_values, timestep, time, frequency, -1)
278 field_values, timestep, time, frequency, source, terminated_case)
280 character(len=*),
intent(in) :: field_name, field_namespace
281 integer,
intent(in) :: timestep, frequency, source
283 real(kind=DEFAULT_PRECISION),
intent(in) :: time
284 logical,
intent(in),
optional :: terminated_case
287 class(*),
pointer :: generic
288 logical :: this_is_termination
290 if (
present(terminated_case))
then 291 this_is_termination=terminated_case
293 this_is_termination=.false.
298 if (timestep == field_ordering%last_timestep_access + frequency .or. this_is_termination)
then 299 if (.not. this_is_termination) field_ordering%last_timestep_access=timestep
301 field_values, timestep, time, source)
302 if (
allocated(field_values%values))
deallocate(field_values%values)
319 integer :: next_timestep
322 do while (.not.
c_is_empty(field_ordering%timestep_to_value))
323 next_timestep=field_ordering%last_timestep_access + field_ordering%frequency
327 field_ordering%last_timestep_access=next_timestep
329 field_ordering_value_at_timestep%field_namespace, field_ordering_value_at_timestep%field_values, &
330 field_ordering_value_at_timestep%timestep, field_ordering_value_at_timestep%time, &
331 field_ordering_value_at_timestep%source)
332 if (
allocated(field_ordering_value_at_timestep%field_values))
then 333 if (
allocated(field_ordering_value_at_timestep%field_values%values)) &
334 deallocate(field_ordering_value_at_timestep%field_values%values)
335 deallocate(field_ordering_value_at_timestep%field_values)
337 deallocate(field_ordering_value_at_timestep)
350 integer,
intent(in) :: timestep
353 class(*),
pointer :: generic
356 if (
associated(generic))
then 359 get_field_ordering_value_at_timestep=>generic
362 get_field_ordering_value_at_timestep=>null()
376 character(len=*),
intent(in) :: field_name, field_namespace
377 integer,
intent(in) :: timestep, frequency, source
379 real(kind=DEFAULT_PRECISION),
intent(in) :: time
382 allocate(generate_value_container)
383 generate_value_container%field_name=field_name
384 generate_value_container%field_namespace=field_namespace
385 generate_value_container%timestep=timestep
386 generate_value_container%frequency=frequency
387 generate_value_container%time=time
388 generate_value_container%source=source
389 allocate(generate_value_container%field_values, source=field_values)
398 character(len=*),
intent(in) :: field_name, field_namespace
399 integer,
intent(in) :: frequency, source
402 class(*),
pointer :: generic
403 character(len=STRING_LENGTH) :: entry_key
405 if (source .gt. -1)
then 406 entry_key=trim(field_name)//
"#"//trim(field_namespace)//
"#"//trim(
conv_to_string(source))
412 if (.not.
associated(get_or_add_field_ordering))
then 415 if (.not.
associated(get_or_add_field_ordering))
then 416 allocate(get_or_add_field_ordering)
417 get_or_add_field_ordering%last_timestep_access=0
418 get_or_add_field_ordering%frequency=frequency
420 generic=>get_or_add_field_ordering
432 character(len=*),
intent(in) :: field_name
433 logical,
intent(in) :: do_lock
436 class(*),
pointer :: generic
441 if (
associated(generic))
then 444 get_field_ordering=>generic
447 get_field_ordering=>null()
456 class(*),
pointer :: generic
465 if (
associated(generic))
then 479 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
481 integer :: current_data_point, prev_pt
484 class(*),
pointer :: generic
493 if (
associated(generic))
then 496 current_data_point=
pack_scalar_field(byte_data, current_data_point, len(trim(map_entry%key)))
497 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1) = transfer(trim(map_entry%key), &
498 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1))
499 current_data_point=current_data_point+len(trim(map_entry%key))
501 prev_pt=current_data_point
502 current_data_point=current_data_point+kind(current_data_point)
504 prev_pt=
pack_scalar_field(byte_data, prev_pt, (current_data_point-kind(current_data_point))-prev_pt)
515 character,
dimension(:),
intent(in) :: byte_data
517 integer :: current_data_point, number_of_entries, i, byte_size, key_size
518 character(len=STRING_LENGTH) :: value_key
519 class(*),
pointer :: generic
524 if (number_of_entries .gt. 0)
then 525 do i=1, number_of_entries
527 value_key=transfer(byte_data(current_data_point:current_data_point+key_size-1), value_key)
528 value_key(key_size+1:)=
" " 529 current_data_point=current_data_point+key_size
533 current_data_point=current_data_point+byte_size
546 class(*),
pointer :: generic
552 iterator=
c_get_iterator(specific_field_ordering%timestep_to_value)
556 if (
associated(generic))
then 561 len(trim(map_entry%key))
573 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
574 integer,
intent(inout) :: current_data_point
579 class(*),
pointer :: generic
581 current_data_point=
pack_scalar_field(byte_data, current_data_point, specific_field_ordering%last_timestep_access)
582 current_data_point=
pack_scalar_field(byte_data, current_data_point, specific_field_ordering%frequency)
583 current_data_point=
pack_scalar_field(byte_data, current_data_point,
c_size(specific_field_ordering%timestep_to_value))
585 iterator=
c_get_iterator(specific_field_ordering%timestep_to_value)
589 if (
associated(generic))
then 592 current_data_point=
pack_scalar_field(byte_data, current_data_point, len(trim(map_entry%key)))
593 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1) = transfer(trim(map_entry%key), &
594 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1))
595 current_data_point=current_data_point+len(trim(map_entry%key))
597 prev_pt=current_data_point
598 current_data_point=current_data_point+kind(current_data_point)
600 prev_pt=
pack_scalar_field(byte_data, prev_pt, (current_data_point-kind(current_data_point))-prev_pt)
612 character,
dimension(:),
intent(in) :: byte_data
615 integer :: current_data_point, number_of_values, byte_size, i, key_size
616 character(len=STRING_LENGTH) :: value_key
617 class(*),
pointer :: generic
619 allocate(unserialise_specific_field_ordering)
626 if (number_of_values .gt. 0)
then 627 do i=1, number_of_values
629 value_key=transfer(byte_data(current_data_point:current_data_point+key_size-1), value_key)
630 value_key(key_size+1:)=
" " 631 current_data_point=current_data_point+key_size
634 call c_put_generic(unserialise_specific_field_ordering%timestep_to_value, value_key, generic, .false.)
635 current_data_point=current_data_point+byte_size
649 (kind(specific_field_value%timestep) * 6) + len(trim(specific_field_value%field_name)) + &
650 len(trim(specific_field_value%field_namespace)) + kind(specific_field_value%time)
659 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
660 integer,
intent(inout) :: current_data_point
664 current_data_point=
pack_scalar_field(byte_data, current_data_point, specific_field_value%timestep)
665 current_data_point=
pack_scalar_field(byte_data, current_data_point, specific_field_value%frequency)
666 current_data_point=
pack_scalar_field(byte_data, current_data_point, specific_field_value%source)
667 current_data_point=
pack_scalar_field(byte_data, current_data_point, len(trim(specific_field_value%field_name)))
668 byte_data(current_data_point:current_data_point+len(trim(specific_field_value%field_name))-1) = &
669 transfer(trim(specific_field_value%field_name), byte_data(current_data_point:current_data_point+&
670 len(trim(specific_field_value%field_name))-1))
671 current_data_point=current_data_point+len(trim(specific_field_value%field_name))
672 current_data_point=
pack_scalar_field(byte_data, current_data_point, len(trim(specific_field_value%field_namespace)))
673 byte_data(current_data_point:current_data_point+len(trim(specific_field_value%field_namespace))-1) = &
674 transfer(trim(specific_field_value%field_namespace), byte_data(current_data_point:current_data_point+&
675 len(trim(specific_field_value%field_namespace))-1))
676 current_data_point=current_data_point+len(trim(specific_field_value%field_namespace))
677 current_data_point=
pack_scalar_field(byte_data, current_data_point, double_real_value=specific_field_value%time)
679 prev_pt=current_data_point
680 current_data_point=current_data_point+kind(current_data_point)
682 prev_pt=
pack_scalar_field(byte_data, prev_pt, (current_data_point-kind(current_data_point))-prev_pt)
689 character,
dimension(:),
intent(in) :: byte_data
692 integer :: current_data_point, byte_size, str_size
694 allocate(unserialise_field_ordering_value)
700 unserialise_field_ordering_value%field_name=transfer(byte_data(current_data_point:current_data_point+str_size-1), &
701 unserialise_field_ordering_value%field_name)
702 unserialise_field_ordering_value%field_name(str_size+1:)=
" " 703 current_data_point=current_data_point+str_size
705 unserialise_field_ordering_value%field_namespace=transfer(byte_data(current_data_point:current_data_point+str_size-1), &
706 unserialise_field_ordering_value%field_namespace)
707 unserialise_field_ordering_value%field_namespace(str_size+1:)=
" " 708 current_data_point=current_data_point+str_size
712 current_data_point+byte_size-1))
type(data_values_type) function, pointer, public unserialise_data_values_type(byte_data)
Unserialises some byte data into data values.
integer function, dimension(:), allocatable, public get_array_integer_from_monc(io_configuration, source, data_id, data_dump, key)
Retreives an array of integers with a corresponding key from the raw data dump. The size depends on t...
integer(kind=8) function prepare_to_serialise_field_manager_state()
Prepares to serialise the field manager state, both determines storage needed and also issues any loc...
subroutine, public set_serialise_write_field_manager_state(serialise_writer_field_manager_state_arg, prepare_to_serialise_writer_field_manager_state_arg, is_write_field_manager_up_to_date_arg)
Sets the procedure to call for serialises the field manager state, this is handled in this manner due...
type(field_ordering_type) function, pointer unserialise_specific_field_ordering(byte_data)
Unserialises some field ordering.
integer function forthread_rwlock_init(rwlock_id, attr_id)
Gets a specific generic element out of the list, stack, queue or map with the corresponding key...
Returns whether a collection is empty.
integer function forthread_mutex_unlock(mutex_id)
type(hashmap_type), volatile field_orderings
Overall IO configuration.
subroutine provide_field_to_writer_federator_rvalues_src(io_configuration, field_name, field_namespace, field_values, timestep, time, frequency, source)
integer, parameter, public log_error
Only log ERROR messages.
subroutine, public provide_ordered_field_to_writer_federator(io_configuration, field_name, field_namespace, field_values, timestep, time, source)
integer function forthread_mutex_destroy(mutex_id)
Reads the IO server state that was stored in a NetCDF checkpoint file.
Contains functionality for managing and extracting data from the raw data dumps that the IO server re...
logical function, public get_scalar_logical_from_monc(io_configuration, source, data_id, data_dump, key)
Retrieves a single logical element (scalar) from the data dump.
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data.
The writer field manager will manage aspects of the fields being provided to the writer federator...
type(field_ordering_type) function, pointer get_field_ordering(field_name, do_lock)
Retrieves a field ordering based upon the name or null if none can be found.
logical function, public is_field_used_by_writer_federator(field_name, field_namespace)
Determines whether a field is used by the writer federator or not.
logical function, public is_field_split_on_q(field_name)
Determines whether a field is split on Q or not.
subroutine serialise_field_ordering_value(specific_field_value, byte_data, current_data_point)
Serialises a field ordering value and releases any issued locks.
integer function forthread_rwlock_rdlock(lock_id)
Contains common definitions for the data and datatypes used by MONC.
A hashmap structure, the same as a map but uses hashing for greatly improved performance when storing...
integer function forthread_mutex_init(mutex_id, attr_id)
subroutine, public serialise_data_values_type(data_values_to_serialise, byte_data, current_data_point)
Serialises some data values to store or transmit. This releases any locks issued during preparation...
Conversion between common inbuilt FORTRAN data types.
integer, parameter, public double_data_type
character(len=string_length) function, public get_string_from_monc(io_configuration, source, data_id, data_dump, key)
Retrieves a string from the data dump.
Converts data types to strings.
integer function forthread_rwlock_wrlock(lock_id)
type(field_ordering_value_type) function, pointer unserialise_field_ordering_value(byte_data)
Unseralises some field ordering from its byte representation.
subroutine provide_field_to_writer_federator_src(io_configuration, field_name, field_namespace, field_values, timestep, time, frequency, source, terminated_case)
Provides a field to the write federator (a collective diagnostic or prognostic)
type(field_ordering_value_type) function, pointer get_field_ordering_value_at_timestep(collection, timestep)
Retrieves a specific field ordering value at the corresponding timestep or null if none is found...
integer(kind=8) function prepare_to_serialise_field_ordering_value(specific_field_value)
Prepares to serialise a specific field ordering value, determines both the storage size and issues lo...
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...
real(kind=double_precision) function, dimension(:), allocatable, public get_array_double_from_monc(io_configuration, source, data_id, data_dump, key)
Retreives an array of doubles with a corresponding key from the raw data dump. The size depends on th...
Writer types which are shared across writing functionality. Also includes serialisation functionality...
integer, parameter, public string_data_type
This defines some constants and procedures that are useful to the IO server and clients that call it...
integer, parameter, public integer_data_type
logical function, public is_field_present(io_configuration, source, data_id, key)
Map data structure that holds string (length 20 maximum) key value pairs.
type(field_ordering_type) function, pointer get_or_add_field_ordering(field_name, field_namespace, frequency, source)
Retrieves or adds ordering for a specific field (and MONC source)
This is a thread pool and the single management "main" thread will spawn out free threads in the pool...
Returns the number of elements in the collection.
real(kind=double_precision) function, public unpack_scalar_dp_real_from_bytedata(data, start_point)
Unpacks a double precision scalar real from some byte data, this is a very simple unpack routine wrap...
subroutine, public check_thread_status(ierr)
Checks the error status of any thread operation and reports an error if it failed.
integer function forthread_mutex_lock(mutex_id)
subroutine provide_field_to_writer_federator_rvalues_nosrc(io_configuration, field_name, field_namespace, field_values, timestep, time, frequency)
Collection data structures.
subroutine serialise_field_manager_state(byte_data)
Serialises the current field manager, releases any locks issued during preparation.
integer(kind=8) function, public prepare_to_serialise_data_values_type(data_values_to_serialise)
Prepares to serialise a specific data values type, both determines the byte size required and also is...
subroutine unserialise_field_manager_state(byte_data)
Unserialses from some byte data into the state.
integer, parameter, public log_warn
Log WARNING and ERROR messages.
logical function, public is_write_field_manager_up_to_date(timestep)
Determines whether the state of the write field manager is up to date with respect to the timestep th...
type(field_ordering_value_type) function, pointer generate_value_container(field_name, field_namespace, field_values, timestep, time, frequency, source)
Generates the field value container which is then filled in with appropriate values and added into th...
Converts data types to real.
integer(kind=8) function prepare_to_serialise_specific_field_ordering(specific_field_ordering)
Prepares to serialise a specific field ordering, both determines storage size and issues locks...
integer, parameter, public string_length
Default length of strings.
subroutine, public initialise_writer_field_manager(io_configuration, continuation_run)
Initialises the writer field manager.
This federates over the writing of diagnostic and prognostic data to the file system. It also manages the time manipulation of fields and groups.
integer function, public unpack_scalar_integer_from_bytedata(data, start_point)
Unpacks a scalar integer from some byte data, this is a very simple unpack routine wrapping the trans...
integer function forthread_rwlock_destroy(rwlock_id)
subroutine, public provide_monc_data_to_writer_federator(io_configuration, source, data_id, data_dump)
Data communicated from MONC is provided to this write federator and then included if the configuratio...
integer, volatile field_lock
subroutine serialise_specific_field_ordering(specific_field_ordering, byte_data, current_data_point)
Serialises a specific fields ordering and releases any locks issued during preparation.
integer function forthread_rwlock_unlock(lock_id)
subroutine provide_field_to_writer_federator_nosrc(io_configuration, field_name, field_namespace, field_values, timestep, time, frequency)
Provides a field to the write federator with no source (a none collective diagnostic) ...
Puts a generic key-value pair into the map.
integer function, public get_scalar_integer_from_monc(io_configuration, source, data_id, data_dump, key)
Retrieves a single integer element (scalar) from the data dump.
real(kind=double_precision) function, public get_scalar_real_from_monc(io_configuration, source, data_id, data_dump, key)
Retreives a scalar real with a corresponding key from the raw data dump.
subroutine, public finalise_writer_field_manager()
Finalises the writer field manager.
subroutine get_type_of_field(fields, field_name, field_namespace, field_type, data_type)
Retrieves the data type of a field or 0 if the field was not found.
Configuration associated with the representation of a specific data field.
subroutine, public reactivate_writer_field_manager_state(io_configuration, unserialise_writer_field_manager)
Reactivates the writer field manager state from the checkpoint file, for memory reasons this will ope...
Determines whether or not a map contains a specific key.
integer, parameter, public scalar_field_type
integer, parameter, public map_field_type
Field data type identifiers.
Gets a specific string element out of the list, stack, queue or map with the corresponding key...
Parses the XML configuration file to produce the io configuration description which contains the data...
The IO server state module which will write out the current state of the IO server to a NetCDF file...
subroutine process_queued_items(io_configuration, field_ordering)
Processes queued up items for a specific field's ordering. This will send any available fields to the...
type(map_type) function, public get_map_from_monc(io_configuration, source, data_id, data_dump, key)
Retrieves a map data structure with key->value pairs, each of which are strings.
integer function, public pack_scalar_field(buffer, start_offset, int_value, real_value, single_real_value, double_real_value, string_value, logical_value)
Packs the data of a scalar field into a buffer.
Removes a specific element from the list or map.
type(data_values_type) function get_value_from_monc_data(io_configuration, source, data_id, data_dump, field_name, field_namespace)
Retrieves a value from the communicated MONC data. If this was an integer then converts to a real...