MONC
writer_types.F90
Go to the documentation of this file.
1 
10  use logging_mod, only : log_error, log_log
13  implicit none
14 
15 #ifndef TEST_MODE
16  private
17 #endif
18 
19  #ifndef DOXYGEN_SHOULD_SKIP_THIS
20  abstract interface
21 
22  type(data_values_type) function perform_time_manipulation(instant_values, output_frequency, field_name, timestep, time)
24  real(kind=default_precision), dimension(:), intent(in) :: instant_values
25  real, intent(in) :: output_frequency
26  real(kind=default_precision), intent(in) :: time
27  character(len=*), intent(in) :: field_name
28  integer, intent(in) :: timestep
29  end function perform_time_manipulation
30 
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
35  end interface
36  #endif /* DOXYGEN_SHOULD_SKIP_THIS */
37 
38 
40  integer :: timestep
41  real :: write_time
42  logical :: terminated_write
43  end type pending_write_type
44 
45 
47  type(map_type) :: monc_values
49 
50 
52  integer, dimension(:), allocatable :: absolute_start, count
53  integer :: split_dim
54  type(list_type) :: specific_monc_info
56 
57 
59  integer :: relative_dimension_start, counts(3), monc_location, monc_source
61 
62 
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
75  end type writer_field_type
76 
77 
79  character(len=STRING_LENGTH) :: filename, title
80  type(writer_field_type), dimension(:), allocatable :: contents
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
86  end type writer_type
87 
88 
90  integer, dimension(:), allocatable :: dimensions
92 
94  integer :: netcdf_dim_id, netcdf_var_id, num_entries
95  real :: last_write_point
96  logical :: variable_written
98 
99 
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
104  type(writer_type), pointer :: corresponding_writer_entry
105  logical :: termination_write
106  end type netcdf_diagnostics_type
107 
113 contains
114 
118  integer(kind=8) function prepare_to_serialise_writer_type(writer_to_serialise)
119  type(writer_type), intent(inout) :: writer_to_serialise
120 
121  integer :: i
122 
123  prepare_to_serialise_writer_type=(kind(writer_to_serialise%write_timestep) * 6) + &
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))
127 
128  call check_thread_status(forthread_mutex_lock(writer_to_serialise%num_fields_to_write_mutex))
129 
130  if (size(writer_to_serialise%contents) .gt. 0) then
131  do i=1, size(writer_to_serialise%contents)
133  prepare_to_serialise_writer_field_type(writer_to_serialise%contents(i))+kind(prepare_to_serialise_writer_type)
134  end do
135  end if
137 
141  subroutine serialise_writer_type(writer_to_serialise, byte_data)
142  type(writer_type), intent(inout) :: writer_to_serialise
143  character, dimension(:), allocatable, intent(inout) :: byte_data
144 
145  integer :: prev_pt, i, current_data_point
146 
147  type(iterator_type) :: iterator
148  class(*), pointer :: generic
149 
150  current_data_point=1
151 
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))
164 
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)
169  select type(generic)
170  type is (pending_write_type)
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)
173  end select
174  end do
175  end if
176 
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)
181  call serialise_writer_field_type(writer_to_serialise%contents(i), byte_data, current_data_point)
182  prev_pt=pack_scalar_field(byte_data, prev_pt, (current_data_point-prev_pt)-kind(current_data_point))
183  end do
184  end if
185  end subroutine serialise_writer_type
186 
190  subroutine unserialise_writer_type(writer_to_unserialise, byte_data)
191  type(writer_type), intent(inout) :: writer_to_unserialise
192  character, dimension(:), intent(in) :: byte_data
193 
194  integer :: current_data_point, byte_size, expected_pending_writes, expected_contents, i
195  type(pending_write_type), pointer :: pwt
196  class(*), pointer :: generic
197 
198  current_data_point=1
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)
209 
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")
212  end if
213 
214  if (expected_pending_writes .gt. 0) then
215  do i=1, expected_pending_writes
216  allocate(pwt)
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)
219  generic=>pwt
220  call c_push_generic(writer_to_unserialise%pending_writes, generic, .false.)
221  end do
222  end if
223 
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)
227  call unserialise_writer_field_type(writer_to_unserialise%contents(i), &
228  byte_data(current_data_point:current_data_point+byte_size-1))
229  current_data_point=current_data_point+byte_size
230  end do
231  end if
232  end subroutine unserialise_writer_type
233 
237  integer(kind=8) function prepare_to_serialise_writer_field_type(writer_field_to_serialise)
238  type(writer_field_type), intent(inout) :: writer_field_to_serialise
239 
240  type(iterator_type) :: iterator
241  class(*), pointer :: generic
242  type(mapentry_type) :: map_entry
243 
244  call check_thread_status(forthread_mutex_lock(writer_field_to_serialise%values_mutex))
245  prepare_to_serialise_writer_field_type=(kind(writer_field_to_serialise%latest_timestep_values) * 2) + &
246  (kind(writer_field_to_serialise%previous_write_time) * 2)
247 
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
253  select type(generic)
254  type is (data_values_type)
257  (kind(prepare_to_serialise_writer_field_type)*3)+len(trim(map_entry%key))
261  (kind(prepare_to_serialise_writer_field_type)*3)+len(trim(map_entry%key))
262  class default
263  call log_log(log_error, "Unknown data type in writer field type")
264  end select
265  end if
266  end do
268 
273  subroutine serialise_writer_field_type(writer_field_to_serialise, byte_data, current_data_point)
274  type(writer_field_type), intent(inout) :: writer_field_to_serialise
275  character, dimension(:), allocatable, intent(inout) :: byte_data
276  integer, intent(inout) :: current_data_point
277 
278  integer :: prev_pt, byte_size, entry_type
279  class(*), pointer :: generic
280  type(mapentry_type) :: map_entry
281  type(iterator_type) :: iterator
282 
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)
288 
289  current_data_point=pack_scalar_field(byte_data, current_data_point, c_size(writer_field_to_serialise%values_to_write))
290 
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)
302  select type(generic)
303  type is (data_values_type)
304  call serialise_data_values_type(generic, byte_data, current_data_point)
305  entry_type=1
307  call serialise_collective_values_type(generic, byte_data, current_data_point)
308  entry_type=2
309  class default
310  call log_log(log_error, "Unknown data type in writer field type")
311  end select
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)
314  end if
315  end do
316  call check_thread_status(forthread_mutex_unlock(writer_field_to_serialise%values_mutex))
317  end subroutine serialise_writer_field_type
318 
322  subroutine unserialise_writer_field_type(writer_field_to_unserialise, byte_data)
323  type(writer_field_type), intent(inout) :: writer_field_to_unserialise
324  character, dimension(:), intent(in) :: byte_data
325 
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
329 
330  current_data_point=1
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)
335 
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
345  generic=>unserialise_data_values_type(byte_data(current_data_point:current_data_point+byte_size-1))
346  else if (entry_type == 2) then
347  generic=>unserialise_collective_values_type(byte_data(current_data_point:current_data_point+byte_size-1))
348  else
349  call log_log(log_error, "Unknown entry type in writer field type serialisation bytes")
350  end if
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
353  end do
354  end if
355  end subroutine unserialise_writer_field_type
356 
360  integer(kind=8) function prepare_to_serialise_collective_values_type(collective_values_to_serialise)
361  type(write_field_collective_values_type), intent(inout) :: collective_values_to_serialise
362 
363  class(*), pointer :: generic
364  type(mapentry_type) :: map_entry
365  type(iterator_type) :: iterator
366 
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
374  select type(generic)
375  type is (data_values_type)
378  (kind(prepare_to_serialise_collective_values_type)*2)+len(trim(map_entry%key))
379  class default
380  call log_log(log_error, "Unknown data type in collective values type")
381  end select
382  end if
383  end do
384  end if
386 
391  subroutine serialise_collective_values_type(collective_values_to_serialise, byte_data, current_data_point)
392  type(write_field_collective_values_type), intent(inout) :: collective_values_to_serialise
393  character, dimension(:), allocatable, intent(inout) :: byte_data
394  integer, intent(inout) :: current_data_point
395 
396  integer :: prev_pt
397  class(*), pointer :: generic
398  type(mapentry_type) :: map_entry
399  type(iterator_type) :: iterator
400 
401  current_data_point=pack_scalar_field(byte_data, current_data_point, c_size(collective_values_to_serialise%monc_values))
402 
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
409  select type(generic)
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))
415 
416  prev_pt=current_data_point
417  current_data_point=current_data_point+kind(current_data_point)
418  call serialise_data_values_type(generic, byte_data, current_data_point)
419 
420  prev_pt=pack_scalar_field(byte_data, prev_pt, (current_data_point-kind(current_data_point))-prev_pt)
421  class default
422  call log_log(log_error, "Unknown data type in collective values type")
423  end select
424  end if
425  end do
426  end if
427  end subroutine serialise_collective_values_type
428 
433  character, dimension(:), intent(in) :: byte_data
435 
436  integer :: current_data_point, number_entries, i, key_size, byte_size
437  character(len=STRING_LENGTH) :: value_key
438  class(*), pointer :: generic
439 
441 
442  current_data_point=1
443  number_entries=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
444 
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)
452  generic=>unserialise_data_values_type(byte_data(current_data_point:current_data_point+byte_size-1))
453  call c_put_generic(unserialise_collective_values_type%monc_values, value_key, generic, .false.)
454  current_data_point=current_data_point+byte_size
455  end do
456  end if
458 
462  integer(kind=8) function prepare_to_serialise_data_values_type(data_values_to_serialise)
463  type(data_values_type), intent(inout) :: data_values_to_serialise
464 
465  integer :: values_size
466 
468 
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)
475  else
477  prepare_to_serialise_string_map(data_values_to_serialise%map_values)
478  end if
480 
485  subroutine serialise_data_values_type(data_values_to_serialise, byte_data, current_data_point)
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
489 
490  integer :: values_size, prev_pt
491  character, dimension(:), allocatable :: dvt_byte_data, temp
492 
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
497  else
498  values_size=0
499  end if
500 
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))
515  else
516  current_data_point=pack_scalar_field(byte_data, current_data_point, 3)
517  call serialise_string_map(data_values_to_serialise%map_values, byte_data, current_data_point)
518  end if
519  end subroutine serialise_data_values_type
520 
524  function unserialise_data_values_type(byte_data)
525  character, dimension(:), intent(in) :: byte_data
526  type(data_values_type), pointer :: unserialise_data_values_type
527 
528  integer :: current_data_point, i, values_size, byte_size, values_type
529 
531  current_data_point=1
532  unserialise_data_values_type%data_type=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
533  unserialise_data_values_type%dimensions=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
534  do i=1, 4
535  unserialise_data_values_type%dim_sizes(i)=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
536  end do
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)
540  allocate(unserialise_data_values_type%values(values_size))
541  byte_size=values_size*kind(unserialise_data_values_type%values)
542  unserialise_data_values_type%values=transfer(byte_data(current_data_point:current_data_point+byte_size-1), &
544  else if (values_type == 2) then
545  values_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
546  allocate(unserialise_data_values_type%string_values(values_size))
547  byte_size=values_size*string_length
548  unserialise_data_values_type%string_values=transfer(byte_data(current_data_point:current_data_point+byte_size-1), &
549  unserialise_data_values_type%string_values)
550  else if (values_type == 3) then
551  byte_size=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
552  unserialise_data_values_type%map_values=unserialise_string_map(byte_data(current_data_point:current_data_point+byte_size-1))
553  else
554  call log_log(log_error, "Unknown values type in data values serialisation bytes")
555  end if
556  end function unserialise_data_values_type
557 
561  integer(kind=8) function prepare_to_serialise_string_map(map_to_serialise)
562  type(map_type), intent(inout) :: map_to_serialise
563 
564  type(mapentry_type) :: map_entry
565  type(iterator_type) :: iterator
566  character(len=STRING_LENGTH) :: str_value
567 
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)
574  len(trim(str_value)) + (kind(prepare_to_serialise_string_map) * 2)
575  end do
576  end function prepare_to_serialise_string_map
577 
582  subroutine serialise_string_map(map_to_serialise, byte_data, current_data_point)
583  type(map_type), intent(inout) :: map_to_serialise
584  character, dimension(:), allocatable, intent(inout) :: byte_data
585  integer, intent(inout) :: current_data_point
586 
587  type(mapentry_type) :: map_entry
588  type(iterator_type) :: iterator
589  character(len=STRING_LENGTH) :: str_value
590 
591  current_data_point=pack_scalar_field(byte_data, current_data_point, c_size(map_to_serialise))
592 
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)
597 
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))
606  end if
607  current_data_point=current_data_point+len(trim(str_value))
608  end do
609  end subroutine serialise_string_map
610 
614  function unserialise_string_map(byte_data)
615  character, dimension(:), intent(in) :: byte_data
616  type(map_type), pointer :: unserialise_string_map
617 
618  integer :: current_data_point, number_entries, i, key_size, value_size
619  character(len=STRING_LENGTH) :: value_key, value_value
620 
621  allocate(unserialise_string_map)
622  current_data_point=1
623  number_entries=unpack_scalar_integer_from_bytedata(byte_data, current_data_point)
624 
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)
634  else
635  value_value=""
636  end if
637  current_data_point=current_data_point+value_size
638  call c_put_string(unserialise_string_map, value_key, value_value)
639  end do
640  end if
641  end function unserialise_string_map
642 end module writer_types_mod
logging_mod::log_error
integer, parameter, public log_error
Only log ERROR messages.
Definition: logging.F90:11
collections_mod::map_type
Map data structure that holds string (length 20 maximum) key value pairs.
Definition: collections.F90:86
forthread_mod::forthread_mutex_lock
integer function forthread_mutex_lock(mutex_id)
Definition: forthread.F90:284
collections_mod::c_put_generic
Puts a generic key-value pair into the map.
Definition: collections.F90:305
data_utils_mod
Contains functionality for managing and extracting data from the raw data dumps that the IO server re...
Definition: datautils.F90:3
collections_mod
Collection data structures.
Definition: collections.F90:7
writer_types_mod::writer_field_type
Definition: writer_types.F90:63
collections_mod::c_get_string
Gets a specific string element out of the list, stack, queue or map with the corresponding key.
Definition: collections.F90:388
collections_mod::c_has_next
Definition: collections.F90:586
collections_mod::hashmap_type
A hashmap structure, the same as a map but uses hashing for greatly improved performance when storing...
Definition: collections.F90:94
writer_types_mod::serialise_data_values_type
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.
Definition: writer_types.F90:486
writer_types_mod
Writer types which are shared across writing functionality. Also includes serialisation functionality...
Definition: writer_types.F90:2
collections_mod::c_size
Returns the number of elements in the collection.
Definition: collections.F90:428
forthread_mod
Definition: forthread.F90:1
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
io_server_client_mod::pack_array_field
integer function, public pack_array_field(buffer, start_offset, int_array, real_array_1d, real_array_2d, real_array_3d, real_array_4d)
Packs an array field into the sending buffer.
Definition: ioclient.F90:273
writer_types_mod::netcdf_diagnostics_timeseries_type
Definition: writer_types.F90:93
writer_types_mod::serialise_writer_field_type
subroutine serialise_writer_field_type(writer_field_to_serialise, byte_data, current_data_point)
Serialises a specific writer field type for storage or transmission. This releases any locks issued d...
Definition: writer_types.F90:274
writer_types_mod::prepare_to_serialise_writer_type
integer(kind=8) function, public prepare_to_serialise_writer_type(writer_to_serialise)
Prepares to serialise the writer type by issuing locks and determining the size of serialised bytes n...
Definition: writer_types.F90:119
io_server_client_mod
This defines some constants and procedures that are useful to the IO server and clients that call it....
Definition: ioclient.F90:3
collections_mod::mapentry_type
Definition: collections.F90:46
writer_types_mod::writer_type
Definition: writer_types.F90:78
collections_mod::c_get_generic
Gets a specific generic element out of the list, stack, queue or map with the corresponding key.
Definition: collections.F90:367
writer_types_mod::prepare_to_serialise_writer_field_type
integer(kind=8) function prepare_to_serialise_writer_field_type(writer_field_to_serialise)
Prepares to serialise a specific writer field, both determines the data size and issues any locks.
Definition: writer_types.F90:238
writer_types_mod::unserialise_string_map
type(map_type) function, pointer unserialise_string_map(byte_data)
Inflates some byte data into a string map.
Definition: writer_types.F90:615
writer_types_mod::write_field_collective_values_type
Definition: writer_types.F90:46
threadpool_mod
This is a thread pool and the single management "main" thread will spawn out free threads in the pool...
Definition: threadpool.F90:5
writer_types_mod::write_field_collective_descriptor_type
Definition: writer_types.F90:51
threadpool_mod::check_thread_status
subroutine, public check_thread_status(ierr)
Checks the error status of any thread operation and reports an error if it failed.
Definition: threadpool.F90:229
writer_types_mod::prepare_to_serialise_string_map
integer(kind=8) function prepare_to_serialise_string_map(map_to_serialise)
Prepares a map for serialisation, both determines the size of storage required and also issues any lo...
Definition: writer_types.F90:562
writer_types_mod::netcdf_diagnostics_type
Definition: writer_types.F90:100
writer_types_mod::prepare_to_serialise_data_values_type
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...
Definition: writer_types.F90:463
collections_mod::queue_type
Queue (FIFO) data structure.
Definition: collections.F90:70
collections_mod::iterator_type
Definition: collections.F90:51
writer_types_mod::serialise_collective_values_type
subroutine serialise_collective_values_type(collective_values_to_serialise, byte_data, current_data_point)
Serialises collective values. This releases any locks issued during preparation.
Definition: writer_types.F90:392
data_utils_mod::unpack_scalar_integer_from_bytedata
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...
Definition: datautils.F90:34
collections_mod::c_put_string
Puts a string key-value pair into the map.
Definition: collections.F90:331
writer_types_mod::serialise_string_map
subroutine serialise_string_map(map_to_serialise, byte_data, current_data_point)
Serialises a string map, where the values are assumed to be strings. This releases any locks issued d...
Definition: writer_types.F90:583
writer_types_mod::serialise_writer_type
subroutine, public serialise_writer_type(writer_to_serialise, byte_data)
Serialises a specific writer type into byte data (for storage or transmission.) Releases any locks is...
Definition: writer_types.F90:142
writer_types_mod::collective_q_field_representation_type
Definition: writer_types.F90:89
collections_mod::c_next_generic
Definition: collections.F90:610
writer_types_mod::write_field_collective_monc_info_type
Definition: writer_types.F90:58
logging_mod
Logging utility.
Definition: logging.F90:2
writer_types_mod::unserialise_writer_field_type
subroutine unserialise_writer_field_type(writer_field_to_unserialise, byte_data)
Unserialises byte data into a writer field type.
Definition: writer_types.F90:323
datadefn_mod
Contains common definitions for the data and datatypes used by MONC.
Definition: datadefn.F90:2
writer_types_mod::prepare_to_serialise_collective_values_type
integer(kind=8) function prepare_to_serialise_collective_values_type(collective_values_to_serialise)
Prepares to serialise a specific collective value, both determines the required byte storate size and...
Definition: writer_types.F90:361
configuration_parser_mod::data_values_type
Definition: configurationparser.F90:34
datadefn_mod::string_length
integer, parameter, public string_length
Default length of strings.
Definition: datadefn.F90:10
forthread_mod::forthread_mutex_unlock
integer function forthread_mutex_unlock(mutex_id)
Definition: forthread.F90:302
collections_mod::c_get_iterator
Definition: collections.F90:581
collections_mod::list_type
List data structure which implements a doubly linked list. This list will preserve its order.
Definition: collections.F90:60
data_utils_mod::unpack_scalar_real_from_bytedata
real function, public unpack_scalar_real_from_bytedata(data, start_point)
Unpacks a scalar real from some byte data, this is a very simple unpack routine wrapping the transfer...
Definition: datautils.F90:75
writer_types_mod::unserialise_writer_type
subroutine, public unserialise_writer_type(writer_to_unserialise, byte_data)
Unserialises some byte data into the writer in order to recreate the state of the writer.
Definition: writer_types.F90:191
writer_types_mod::unserialise_collective_values_type
type(write_field_collective_values_type) function, pointer unserialise_collective_values_type(byte_data)
Unserialsies collective values contained in some data.
Definition: writer_types.F90:433
collections_mod::c_next_mapentry
Definition: collections.F90:606
writer_types_mod::pending_write_type
Definition: writer_types.F90:39
collections_mod::c_push_generic
Pushes a generic element onto the stack or queue.
Definition: collections.F90:113
writer_types_mod::unserialise_data_values_type
type(data_values_type) function, pointer, public unserialise_data_values_type(byte_data)
Unserialises some byte data into data values.
Definition: writer_types.F90:525
configuration_parser_mod
Parses the XML configuration file to produce the io configuration description which contains the data...
Definition: configurationparser.F90:3
io_server_client_mod::pack_scalar_field
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.
Definition: ioclient.F90:312
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