19 #ifndef DOXYGEN_SHOULD_SKIP_THIS
22 type(data_values_type) function perform_time_manipulation(instant_values, output_frequency, field_name, timestep, time)
25 real,
intent(in) :: output_frequency
27 character(len=*),
intent(in) :: field_name
28 integer,
intent(in) :: timestep
29 end function perform_time_manipulation
31 logical function is_field_ready_to_write(latest_time, output_frequency, write_time, latest_timestep, write_timestep)
32 real,
intent(in) :: latest_time, output_frequency, write_time
33 integer,
intent(in) :: latest_timestep, write_timestep
34 end function is_field_ready_to_write
36 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
42 logical :: terminated_write
47 type(map_type) :: monc_values
52 integer,
dimension(:),
allocatable :: absolute_start, count
54 type(list_type) :: specific_monc_info
59 integer :: relative_dimension_start, counts(3), monc_location, monc_source
64 character(len=STRING_LENGTH) :: field_name, field_namespace, dim_size_defns(4), units
65 procedure(perform_time_manipulation),
pointer,
nopass :: time_manipulation
66 procedure(is_field_ready_to_write),
pointer,
nopass :: ready_to_write
67 integer :: time_manipulation_type, values_mutex, dimensions, field_type, data_type, timestep_frequency, &
68 actual_dim_size(4), latest_timestep_values, max_num_collective_writes, max_num_collective_writes_request_handle
69 real :: output_frequency, previous_write_time, previous_tracked_write_point
70 logical :: collective_write, collective_initialised, collective_contiguous_optimisation, &
71 pending_to_write, enabled, expected_here, issue_write
72 type(map_type) :: values_to_write
73 type(list_type) :: collective_descriptors
74 logical :: duplicate_field_name, prognostic_field, diagnostic_field
79 character(len=STRING_LENGTH) :: filename, title
81 integer :: trigger_and_write_mutex, write_timestep, previous_write_timestep, num_fields_to_write, &
82 num_fields_to_write_mutex, pending_writes_mutex, write_timestep_frequency, latest_pending_write_timestep
83 real :: write_time_frequency, previous_write_time, latest_pending_write_time, write_time, defined_write_time
84 logical :: write_on_model_time, contains_io_status_dump, write_on_terminate, include_in_io_state_write
85 type(queue_type) :: pending_writes
90 integer,
dimension(:),
allocatable :: dimensions
94 integer :: netcdf_dim_id, netcdf_var_id, num_entries
95 real :: last_write_point
96 logical :: variable_written
101 integer :: ncid, mutex, key_value_dim_id, string_dim_id
102 type(map_type) :: dimension_to_id
103 type(hashmap_type) :: variable_to_id, timeseries_dimension
105 logical :: termination_write
119 type(
writer_type),
intent(inout) :: writer_to_serialise
124 (kind(writer_to_serialise%previous_write_time) * 4) + &
125 c_size(writer_to_serialise%pending_writes) * (kind(writer_to_serialise%write_timestep) + &
126 kind(writer_to_serialise%previous_write_time))
128 call check_thread_status(forthread_mutex_lock(writer_to_serialise%num_fields_to_write_mutex))
130 if (
size(writer_to_serialise%contents) .gt. 0)
then
131 do i=1,
size(writer_to_serialise%contents)
142 type(
writer_type),
intent(inout) :: writer_to_serialise
143 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
145 integer :: prev_pt, i, current_data_point
147 type(iterator_type) :: iterator
148 class(*),
pointer :: generic
152 current_data_point=pack_scalar_field(byte_data, current_data_point, writer_to_serialise%write_timestep)
153 current_data_point=pack_scalar_field(byte_data, current_data_point, writer_to_serialise%num_fields_to_write)
154 call check_thread_status(forthread_mutex_unlock(writer_to_serialise%num_fields_to_write_mutex))
155 current_data_point=pack_scalar_field(byte_data, current_data_point, writer_to_serialise%previous_write_timestep)
156 current_data_point=pack_scalar_field(byte_data, current_data_point, writer_to_serialise%latest_pending_write_timestep)
157 current_data_point=pack_scalar_field(byte_data, current_data_point, single_real_value=writer_to_serialise%previous_write_time)
158 current_data_point=pack_scalar_field(byte_data, current_data_point, &
159 single_real_value=writer_to_serialise%latest_pending_write_time)
160 current_data_point=pack_scalar_field(byte_data, current_data_point, single_real_value=writer_to_serialise%write_time)
161 current_data_point=pack_scalar_field(byte_data, current_data_point, single_real_value=writer_to_serialise%defined_write_time)
162 current_data_point=pack_scalar_field(byte_data, current_data_point, c_size(writer_to_serialise%pending_writes))
163 current_data_point=pack_scalar_field(byte_data, current_data_point,
size(writer_to_serialise%contents))
165 if (c_size(writer_to_serialise%pending_writes) .gt. 0)
then
166 iterator=c_get_iterator(writer_to_serialise%pending_writes)
167 do while (c_has_next(iterator))
168 generic=>c_next_generic(iterator)
171 current_data_point=pack_scalar_field(byte_data, current_data_point, generic%timestep)
172 current_data_point=pack_scalar_field(byte_data, current_data_point, single_real_value=generic%write_time)
177 if (
size(writer_to_serialise%contents) .gt. 0)
then
178 do i=1,
size(writer_to_serialise%contents)
179 prev_pt=current_data_point
180 current_data_point=current_data_point+kind(current_data_point)
182 prev_pt=pack_scalar_field(byte_data, prev_pt, (current_data_point-prev_pt)-kind(current_data_point))
191 type(
writer_type),
intent(inout) :: writer_to_unserialise
192 character,
dimension(:),
intent(in) :: byte_data
194 integer :: current_data_point, byte_size, expected_pending_writes, expected_contents, i
196 class(*),
pointer :: generic
199 writer_to_unserialise%write_timestep=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
200 writer_to_unserialise%num_fields_to_write=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
201 writer_to_unserialise%previous_write_timestep=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
202 writer_to_unserialise%latest_pending_write_timestep=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
203 writer_to_unserialise%previous_write_time=unpack_scalar_real_from_bytedata(byte_data, current_data_point)
204 writer_to_unserialise%latest_pending_write_time=unpack_scalar_real_from_bytedata(byte_data, current_data_point)
205 writer_to_unserialise%write_time=unpack_scalar_real_from_bytedata(byte_data, current_data_point)
206 writer_to_unserialise%defined_write_time=unpack_scalar_real_from_bytedata(byte_data, current_data_point)
207 expected_pending_writes=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
208 expected_contents=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
210 if (expected_contents .ne.
size(writer_to_unserialise%contents))
then
211 call log_log(log_error,
"Expected number of writer entry fields in the checkpoint does not match the configured number")
214 if (expected_pending_writes .gt. 0)
then
215 do i=1, expected_pending_writes
217 pwt%timestep=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
218 pwt%write_time=unpack_scalar_real_from_bytedata(byte_data, current_data_point)
220 call c_push_generic(writer_to_unserialise%pending_writes, generic, .false.)
224 if (expected_contents .gt. 0)
then
225 do i=1, expected_contents
226 byte_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
228 byte_data(current_data_point:current_data_point+byte_size-1))
229 current_data_point=current_data_point+byte_size
240 type(iterator_type) :: iterator
241 class(*),
pointer :: generic
242 type(mapentry_type) :: map_entry
244 call check_thread_status(forthread_mutex_lock(writer_field_to_serialise%values_mutex))
246 (kind(writer_field_to_serialise%previous_write_time) * 2)
248 iterator=c_get_iterator(writer_field_to_serialise%values_to_write)
249 do while (c_has_next(iterator))
250 map_entry=c_next_mapentry(iterator)
251 generic=>c_get_generic(map_entry)
252 if (
associated(generic))
then
254 type is (data_values_type)
263 call log_log(log_error,
"Unknown data type in writer field type")
275 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
276 integer,
intent(inout) :: current_data_point
278 integer :: prev_pt, byte_size, entry_type
279 class(*),
pointer :: generic
280 type(mapentry_type) :: map_entry
281 type(iterator_type) :: iterator
283 current_data_point=pack_scalar_field(byte_data, current_data_point, writer_field_to_serialise%latest_timestep_values)
284 current_data_point=pack_scalar_field(byte_data, current_data_point, &
285 single_real_value=writer_field_to_serialise%previous_write_time)
286 current_data_point=pack_scalar_field(byte_data, current_data_point, &
287 single_real_value=writer_field_to_serialise%previous_tracked_write_point)
289 current_data_point=pack_scalar_field(byte_data, current_data_point, c_size(writer_field_to_serialise%values_to_write))
291 iterator=c_get_iterator(writer_field_to_serialise%values_to_write)
292 do while (c_has_next(iterator))
293 map_entry=c_next_mapentry(iterator)
294 generic=>c_get_generic(map_entry)
295 if (
associated(generic))
then
296 current_data_point=pack_scalar_field(byte_data, current_data_point, len(trim(map_entry%key)))
297 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1) = transfer(trim(map_entry%key), &
298 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1))
299 current_data_point=current_data_point+len(trim(map_entry%key))
300 prev_pt=current_data_point
301 current_data_point=current_data_point+(kind(current_data_point)*2)
303 type is (data_values_type)
310 call log_log(log_error,
"Unknown data type in writer field type")
312 prev_pt=pack_scalar_field(byte_data, prev_pt, (current_data_point-(kind(current_data_point)*2)) - prev_pt)
313 prev_pt=pack_scalar_field(byte_data, prev_pt, entry_type)
316 call check_thread_status(forthread_mutex_unlock(writer_field_to_serialise%values_mutex))
324 character,
dimension(:),
intent(in) :: byte_data
326 integer :: current_data_point, number_values_stored, i, byte_size, key_size, entry_type
327 character(len=STRING_LENGTH) :: value_key
328 class(*),
pointer :: generic
331 writer_field_to_unserialise%latest_timestep_values=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
332 writer_field_to_unserialise%previous_write_time=unpack_scalar_real_from_bytedata(byte_data, current_data_point)
333 writer_field_to_unserialise%previous_tracked_write_point=unpack_scalar_real_from_bytedata(byte_data, current_data_point)
334 number_values_stored=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
336 if (number_values_stored .gt. 0)
then
337 do i=1, number_values_stored
338 key_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
339 value_key=transfer(byte_data(current_data_point:current_data_point+key_size-1), value_key)
340 value_key(key_size+1:)=
" "
341 current_data_point=current_data_point+key_size
342 byte_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
343 entry_type=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
344 if (entry_type == 1)
then
346 else if (entry_type == 2)
then
349 call log_log(log_error,
"Unknown entry type in writer field type serialisation bytes")
351 call c_put_generic(writer_field_to_unserialise%values_to_write, value_key, generic, .false.)
352 current_data_point=current_data_point+byte_size
363 class(*),
pointer :: generic
364 type(mapentry_type) :: map_entry
365 type(iterator_type) :: iterator
368 if (c_size(collective_values_to_serialise%monc_values) .gt. 0)
then
369 iterator=c_get_iterator(collective_values_to_serialise%monc_values)
370 do while (c_has_next(iterator))
371 map_entry=c_next_mapentry(iterator)
372 generic=>c_get_generic(map_entry)
373 if (
associated(generic))
then
375 type is (data_values_type)
380 call log_log(log_error,
"Unknown data type in collective values type")
393 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
394 integer,
intent(inout) :: current_data_point
397 class(*),
pointer :: generic
398 type(mapentry_type) :: map_entry
399 type(iterator_type) :: iterator
401 current_data_point=pack_scalar_field(byte_data, current_data_point, c_size(collective_values_to_serialise%monc_values))
403 if (c_size(collective_values_to_serialise%monc_values) .gt. 0)
then
404 iterator=c_get_iterator(collective_values_to_serialise%monc_values)
405 do while (c_has_next(iterator))
406 map_entry=c_next_mapentry(iterator)
407 generic=>c_get_generic(map_entry)
408 if (
associated(generic))
then
410 type is (data_values_type)
411 current_data_point=pack_scalar_field(byte_data, current_data_point, len(trim(map_entry%key)))
412 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1) = transfer(trim(map_entry%key), &
413 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1))
414 current_data_point=current_data_point+len(trim(map_entry%key))
416 prev_pt=current_data_point
417 current_data_point=current_data_point+kind(current_data_point)
420 prev_pt=pack_scalar_field(byte_data, prev_pt, (current_data_point-kind(current_data_point))-prev_pt)
422 call log_log(log_error,
"Unknown data type in collective values type")
433 character,
dimension(:),
intent(in) :: byte_data
436 integer :: current_data_point, number_entries, i, key_size, byte_size
437 character(len=STRING_LENGTH) :: value_key
438 class(*),
pointer :: generic
443 number_entries=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
445 if (number_entries .gt. 0)
then
446 do i=1, number_entries
447 key_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
448 value_key=transfer(byte_data(current_data_point:current_data_point+key_size-1), value_key)
449 value_key(key_size+1:)=
" "
450 current_data_point=current_data_point+key_size
451 byte_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
454 current_data_point=current_data_point+byte_size
463 type(data_values_type),
intent(inout) :: data_values_to_serialise
465 integer :: values_size
469 if (
allocated(data_values_to_serialise%values))
then
471 (kind(data_values_to_serialise%values)*
size(data_values_to_serialise%values))
472 else if (
allocated(data_values_to_serialise%string_values))
then
474 (
size(data_values_to_serialise%string_values) * string_length)
486 type(data_values_type),
intent(inout) :: data_values_to_serialise
487 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
488 integer,
intent(inout) :: current_data_point
490 integer :: values_size, prev_pt
491 character,
dimension(:),
allocatable :: dvt_byte_data, temp
493 if (
allocated(data_values_to_serialise%values))
then
494 values_size=kind(data_values_to_serialise%values)*
size(data_values_to_serialise%values)
495 else if (
allocated(data_values_to_serialise%string_values))
then
496 values_size=
size(data_values_to_serialise%string_values) * string_length
501 current_data_point=pack_scalar_field(byte_data, current_data_point, data_values_to_serialise%data_type)
502 current_data_point=pack_scalar_field(byte_data, current_data_point, data_values_to_serialise%dimensions)
503 current_data_point=pack_array_field(byte_data, current_data_point, data_values_to_serialise%dim_sizes)
504 if (
allocated(data_values_to_serialise%values))
then
505 current_data_point=pack_scalar_field(byte_data, current_data_point, 1)
506 current_data_point=pack_scalar_field(byte_data, current_data_point,
size(data_values_to_serialise%values))
507 current_data_point=pack_array_field(byte_data, current_data_point, real_array_1d=data_values_to_serialise%values)
508 else if (
allocated(data_values_to_serialise%string_values))
then
509 current_data_point=pack_scalar_field(byte_data, current_data_point, 2)
510 current_data_point=pack_scalar_field(byte_data, current_data_point, &
511 size(data_values_to_serialise%string_values) * string_length)
512 byte_data(current_data_point:current_data_point+(
size(data_values_to_serialise%string_values) * string_length)-1) = &
513 transfer(data_values_to_serialise%string_values, &
514 byte_data(current_data_point:current_data_point+(
size(data_values_to_serialise%string_values) * string_length)-1))
516 current_data_point=pack_scalar_field(byte_data, current_data_point, 3)
525 character,
dimension(:),
intent(in) :: byte_data
528 integer :: current_data_point, i, values_size, byte_size, values_type
537 values_type=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
538 if (values_type == 1)
then
539 values_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
544 else if (values_type == 2)
then
545 values_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
547 byte_size=values_size*string_length
550 else if (values_type == 3)
then
551 byte_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
554 call log_log(log_error,
"Unknown values type in data values serialisation bytes")
562 type(map_type),
intent(inout) :: map_to_serialise
564 type(mapentry_type) :: map_entry
565 type(iterator_type) :: iterator
566 character(len=STRING_LENGTH) :: str_value
569 iterator=c_get_iterator(map_to_serialise)
570 do while (c_has_next(iterator))
571 map_entry=c_next_mapentry(iterator)
572 str_value=c_get_string(map_entry)
583 type(map_type),
intent(inout) :: map_to_serialise
584 character,
dimension(:),
allocatable,
intent(inout) :: byte_data
585 integer,
intent(inout) :: current_data_point
587 type(mapentry_type) :: map_entry
588 type(iterator_type) :: iterator
589 character(len=STRING_LENGTH) :: str_value
591 current_data_point=pack_scalar_field(byte_data, current_data_point, c_size(map_to_serialise))
593 iterator=c_get_iterator(map_to_serialise)
594 do while (c_has_next(iterator))
595 map_entry=c_next_mapentry(iterator)
596 str_value=c_get_string(map_entry)
598 current_data_point=pack_scalar_field(byte_data, current_data_point, len(trim(map_entry%key)))
599 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1) = transfer(trim(map_entry%key), &
600 byte_data(current_data_point:current_data_point+len(trim(map_entry%key))-1))
601 current_data_point=current_data_point+len(trim(map_entry%key))
602 current_data_point=pack_scalar_field(byte_data, current_data_point, len(trim(str_value)))
603 if (len(trim(str_value)) .gt. 0)
then
604 byte_data(current_data_point:current_data_point+len(trim(str_value))-1) = transfer(trim(str_value), &
605 byte_data(current_data_point:current_data_point+len(trim(str_value))-1))
607 current_data_point=current_data_point+len(trim(str_value))
615 character,
dimension(:),
intent(in) :: byte_data
618 integer :: current_data_point, number_entries, i, key_size, value_size
619 character(len=STRING_LENGTH) :: value_key, value_value
623 number_entries=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
625 if (number_entries .gt. 0)
then
626 do i=1, number_entries
627 key_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
628 value_key=transfer(byte_data(current_data_point:current_data_point+key_size-1), value_key)
629 value_key(key_size+1:)=
" "
630 current_data_point=current_data_point+key_size
631 value_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
632 if (value_size .gt. 0)
then
633 value_value=transfer(byte_data(current_data_point:current_data_point+value_size-1), value_value)
637 current_data_point=current_data_point+value_size