MONC
configurationparser.F90
Go to the documentation of this file.
1 
5  use sax_xml_parser_mod, only : xml_parse
16  implicit none
17 
18 #ifndef TEST_MODE
19  private
20 #endif
21 
22  character(len=STRING_LENGTH), parameter :: default_file_title = "MONC diagnostics"
26  integer, parameter :: monc_size_stride=100, data_size_stride=10
27 
29 
32  end interface get_data_value_by_field_name
33 
35  integer :: data_type, dimensions, dim_sizes(4)
36  real(kind=default_precision), dimension(:), allocatable :: values
37  character(len=STRING_LENGTH), dimension(:), allocatable :: string_values
38  type(map_type) :: map_values
39  end type data_values_type
40 
43  type(map_type) :: registered_monc_types, registered_monc_buffer_sizes
44  type(map_type), dimension(:), allocatable :: field_start_locations, field_end_locations, dimensions
45  character(len=STRING_LENGTH), dimension(:), allocatable :: definition_names
46  integer :: active_threads, active_mutex, deactivate_condition_variable, local_dim_sizes(3), local_dim_starts(3), &
47  local_dim_ends(3), source_id
49 
52  character(len=STRING_LENGTH) :: name, namespace, dim_size_defns(4), units
53  integer :: field_type, data_type, dimensions
54  logical :: optional, collective
56 
59  character(len=STRING_LENGTH) :: name, namespace
60  logical :: send_on_terminate
61  integer :: number_of_data_fields, frequency
62  type(map_type) :: compiled_fields, trigger_field_types
63  type(io_configuration_field_type), dimension(:), allocatable :: fields
65 
67  character(len=STRING_LENGTH) :: name
68  integer :: message_tag
69  procedure(handle_recv_data_from_io_server), pointer, nopass :: handling_procedure
71 
73  character(len=STRING_LENGTH) :: type, namespace
74  type(map_type) :: embellishments
76 
78  character(len=STRING_LENGTH) :: name, dim_size_defns(4), units, namespace
79  integer :: field_type, data_type, dimensions
80  logical :: collective
81  type(list_type) :: members
83 
85  character(len=STRING_LENGTH) :: name, namespace
86  type(list_type) :: members
88 
90  integer :: facet_type, time_manipulation_type
91  real :: output_time_frequency
92  character(len=STRING_LENGTH) :: facet_name
94 
96  character(len=STRING_LENGTH) :: file_name, title
97  integer :: number_of_contents, write_timestep_frequency
98  real :: write_time_frequency
99  logical :: write_on_model_time, write_on_terminate, include_in_io_state_write
100  type(io_configuration_file_writer_facet_type), dimension(:), allocatable :: contents
102 
105  integer :: number_of_data_definitions, number_of_diagnostics, io_communicator, number_of_moncs, &
106  number_of_io_servers, my_io_rank, active_moncs, number_inter_io_communications, number_of_threads, number_of_groups, &
107  number_of_writers, number_of_distinct_data_fields, number_of_global_moncs, general_info_mutex
108  type(io_configuration_data_definition_type), dimension(:), allocatable :: data_definitions
109  type(io_configuration_diagnostic_field_type), dimension(:), allocatable :: diagnostics
110  type(io_configuration_group_type), dimension(:), allocatable :: groups
111  type(io_configuration_file_writer_type), dimension(:), allocatable :: file_writers
112  type(io_configuration_registered_monc_type), dimension(:), allocatable :: registered_moncs
113  type(io_configuration_inter_communication_description), dimension(:), allocatable :: inter_io_communications
114  type(map_type) :: monc_to_index, dimension_sizing
116  real(kind=default_precision), dimension(:), allocatable :: zn_field
117  real(kind=default_precision), dimension(:), allocatable :: z_field
118  type(list_type) :: q_field_names
119  logical :: general_info_set
120  character, dimension(:), allocatable :: text_configuration
121  end type io_configuration_type
122 
123  #ifndef DOXYGEN_SHOULD_SKIP_THIS
124  abstract interface
125  subroutine handle_recv_data_from_io_server(io_configuration, data_buffer, inter_io_index)
126  import io_configuration_type
127  type(io_configuration_type), intent(inout) :: io_configuration
128  character, dimension(:), intent(inout) :: data_buffer
129  integer, intent(in) :: inter_io_index
130  end subroutine handle_recv_data_from_io_server
131  end interface
132  #endif /* DOXYGEN_SHOULD_SKIP_THIS */
133 
134 
135  integer, parameter :: file_str_stride=10000, file_line_len=2000
136 
142  character(len=STRING_LENGTH) :: data_handling_namespace
143 
146 
147  character(len=STRING_LENGTH), dimension(:), allocatable :: cond_request, diag_request, cond_long, diag_long
148  integer :: ncond, ndiag
149 
150 
153  time_averaged_type, instantaneous_type, none_type, group_type, field_type, io_state_type, handle_recv_data_from_io_server, &
162 
163 contains
164 
169  recursive function get_io_xml(filename, funit_num) result(io_xml)
170  character(len=*), intent(in) :: filename
171  integer, intent(in), optional :: funit_num
172  character, dimension(:), allocatable :: io_xml, temp_io_xml
173 
174  character(len=FILE_LINE_LEN) :: temp_line, adjusted_io_line
175  character(len=FILE_STR_STRIDE) :: reading_buffer
176  integer :: ierr, first_quote, last_quote, chosen_unit
177 
178  if (present(funit_num)) then
179  chosen_unit=funit_num
180  else
181  chosen_unit=2
182  end if
183 
184  reading_buffer=""
185  open (unit=chosen_unit, file=filename, status='OLD', iostat=ierr)
186  if (ierr .ne. 0) call log_log(log_error, "Error opening file '"//trim(filename)//"'")
187  do while (ierr == 0)
188  read(chosen_unit,"(A)",iostat=ierr) temp_line
189  adjusted_io_line=adjustl(temp_line)
190  if (ierr == 0 .and. adjusted_io_line(1:1) .ne. "!" .and. adjusted_io_line(1:2) .ne. "//") then
191  if (index(temp_line, "#include") .ne. 0) then
192  first_quote=index(temp_line, """")
193  last_quote=index(temp_line, """", back=.true.)
194  if (first_quote .ne. 0 .and. last_quote .ne. 0) then
195  call add_in_specific_line(io_xml, reading_buffer)
196  temp_io_xml=get_io_xml(temp_line(first_quote+1:last_quote-1), chosen_unit+1)
197  call combine_xml_arrays(io_xml, temp_io_xml)
198  deallocate(temp_io_xml)
199  reading_buffer=new_line("A")
200  else
201  call log_log(log_error, "Malformed IO XML, include directives must have filename in quotes")
202  end if
203  else
204  if (len_trim(reading_buffer) + len_trim(temp_line) .ge. file_str_stride) then
205  call add_in_specific_line(io_xml, reading_buffer)
206  reading_buffer=""
207  end if
208  reading_buffer=trim(reading_buffer)//trim(temp_line)//new_line("A")
209  end if
210  end if
211  end do
212  if (len_trim(reading_buffer) .gt. 0) call add_in_specific_line(io_xml, reading_buffer)
213  close(chosen_unit)
214  end function get_io_xml
215 
219  subroutine configuration_parse(provided_options_database, raw_configuration, parsed_configuration)
220  type(hashmap_type), intent(inout) :: provided_options_database
221  character, dimension(:), intent(in) :: raw_configuration
222  type(io_configuration_type), intent(out) :: parsed_configuration
223 
224  options_database=provided_options_database
225 
226  inside_data_definition=.false.
228  inside_server_config=.false.
230  inside_group_config=.false.
231  inside_generic_writing=.false.
239  building_config%number_of_writers=0
240  building_config%number_of_groups=0
241  building_config%number_of_threads=-1
242  allocate(building_config%data_definitions(data_size_stride))
243  allocate(building_config%diagnostics(data_size_stride))
244  allocate(building_config%groups(data_size_stride))
245  allocate(building_config%file_writers(data_size_stride))
246  allocate(building_config%inter_io_communications(data_size_stride))
247  call xml_parse(raw_configuration, start_element_callback, end_element_callback)
248  call add_in_dimensions(provided_options_database)
249  building_config%options_database=options_database
250  building_config%number_of_distinct_data_fields=c_size(data_field_names)
251  building_config%number_of_moncs=0
252  building_config%active_moncs=0
253  allocate(building_config%registered_moncs(monc_size_stride))
254  parsed_configuration=building_config
255  parsed_configuration%number_inter_io_communications=0
256  parsed_configuration%general_info_set=.false.
258  allocate(parsed_configuration%text_configuration(size(raw_configuration)), source=raw_configuration)
259  end subroutine configuration_parse
260 
261  subroutine add_in_dimensions(provided_options_database)
262  type(hashmap_type), intent(inout) :: provided_options_database
263 
264  integer :: dim_size
265 
266  call c_put_integer(building_config%dimension_sizing, "x", options_get_integer(provided_options_database, "x_size"))
267  call c_put_integer(building_config%dimension_sizing, "y", options_get_integer(provided_options_database, "y_size"))
268 
269  dim_size=options_get_integer(provided_options_database, "z_size")
270  call c_put_integer(building_config%dimension_sizing, "z", dim_size)
271  call c_put_integer(building_config%dimension_sizing, "zn", dim_size)
272  call c_put_integer(building_config%dimension_sizing, "qfields", &
273  options_get_integer(provided_options_database, "number_q_fields"))
274  call c_put_integer(building_config%dimension_sizing, "number_options", c_size(provided_options_database))
275  call c_put_integer(building_config%dimension_sizing, "active_q_indicies", get_number_active_q_indices())
276 
278  ! netcdf file, only let these exist when the corresponding code is enabled.
279  if (options_get_logical(options_database, "conditional_diagnostics_column_enabled")) then
280  ncond = options_get_array_size(options_database, "cond_request")*2
281  allocate(cond_request(ncond))
282  allocate(cond_long(ncond))
283  call c_put_integer(building_config%dimension_sizing, "nc", ncond)
285  allocate(diag_request(ndiag))
286  allocate(diag_long(ndiag))
287  call c_put_integer(building_config%dimension_sizing, "nd", ndiag)
288  end if
289  end subroutine add_in_dimensions
290 
296  subroutine start_element_callback(element_name, number_of_attributes, attribute_names, attribute_values)
297  character(len=*), intent(in) :: element_name
298  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
299  integer, intent(in) :: number_of_attributes
300 
301  integer :: namespace_index
302 
303  if (inside_data_definition) then
304  if (element_name == "field") then
305  call process_xml_into_field_description(attribute_names, attribute_values)
306  end if
307  else if (inside_handling_definition) then
308  if (inside_diagnostic_config) then
309  call add_misc_member_to_diagnostic(element_name, attribute_names, attribute_values)
310  else
311  if (element_name == "diagnostic") then
312  call define_diagnostic(attribute_names, attribute_values)
314  end if
315  end if
316  else if (inside_server_config) then
317  if (element_name == "thread_pool") then
318  call handle_thread_pool_configuration(attribute_names, attribute_values)
319  end if
320  else if (inside_group_config) then
321  call add_diagnostic_field_to_group(element_name, attribute_names, attribute_values)
322  else if (inside_generic_writing) then
324  if (element_name == "include") then
325  call add_include_to_file_writer(attribute_names, attribute_values)
326  end if
327  else if (element_name == "file") then
329  call define_file_writer(attribute_names, attribute_values)
330  end if
331  else if (element_name == "data-writing") then
333  else if (element_name == "data-definition") then
335  call handle_new_data_definition(attribute_names, attribute_values)
336  else if (element_name == "data-handling") then
337  namespace_index=get_field_index_from_name(attribute_names, "namespace")
338  if (namespace_index == 0) then
340  else
341  data_handling_namespace=retrieve_string_value(attribute_values(namespace_index), string_data_type)
342  end if
344  else if (element_name == "group") then
345  call define_group(attribute_names, attribute_values)
346  inside_group_config=.true.
347  else if (element_name == "server-configuration") then
348  inside_server_config=.true.
349  end if
350  end subroutine start_element_callback
351 
354  subroutine end_element_callback(element_name)
355  character(len=*), intent(in) :: element_name
356 
357  integer :: i
358 
359  if (element_name == "data-definition") then
360  building_config%data_definitions(current_building_definition)%number_of_data_fields=current_building_field-1
361  do i=1, current_building_field-1
362  building_config%data_definitions(current_building_definition)%fields(i)%namespace=&
363  building_config%data_definitions(current_building_definition)%namespace
364  end do
366  building_config%number_of_data_definitions=current_building_definition
368  inside_data_definition=.false.
369  else if (element_name == "data-handling") then
370  building_config%number_of_diagnostics=current_building_diagnostic-1
372  else if (element_name == "server-configuration") then
373  inside_server_config=.false.
374  else if (element_name == "action") then
375  inside_action_config=.false.
376  else if (element_name == "diagnostic") then
379  else if (element_name == "data-writing") then
380  inside_generic_writing=.false.
382  else if (element_name == "group") then
384  building_config%number_of_groups=building_config%number_of_groups+1
385  inside_group_config=.false.
386  else if (element_name == "file") then
389  end if
390  end subroutine end_element_callback
391 
392  subroutine handle_thread_pool_configuration(attribute_names, attribute_values)
393  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
394 
395  integer :: number_index
396 
397  number_index=get_field_index_from_name(attribute_names, "number")
398 
399  if (number_index /= 0) then
400  building_config%number_of_threads=conv_to_integer(attribute_values(number_index))
401  end if
402  end subroutine handle_thread_pool_configuration
403 
408  subroutine handle_new_data_definition(attribute_names, attribute_values)
409  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
410 
411  integer :: name_index, frequency_index, namespace_index, send_on_termination_index
412  character(len=STRING_LENGTH) :: namespace
413 
414  name_index=get_field_index_from_name(attribute_names, "name")
415  frequency_index=get_field_index_from_name(attribute_names, "frequency")
416  namespace_index=get_field_index_from_name(attribute_names, "namespace")
417  send_on_termination_index=get_field_index_from_name(attribute_names, "send_on_terminate")
418  if (name_index /= 0 .and. frequency_index /=0) then
419  if (current_building_definition .gt. size(building_config%data_definitions)) call extend_data_definition_array()
420  building_config%data_definitions(current_building_definition)%name=&
421  retrieve_string_value(attribute_values(name_index), string_data_type)
422  building_config%data_definitions(current_building_definition)%frequency=&
423  conv_to_integer(retrieve_string_value(attribute_values(frequency_index), integer_data_type))
424  if (namespace_index /= 0) then
425  namespace=retrieve_string_value(attribute_values(namespace_index), string_data_type)
426  building_config%data_definitions(current_building_definition)%namespace=namespace
427  else
428  namespace=""
429  building_config%data_definitions(current_building_definition)%namespace=""
430  end if
431  if (send_on_termination_index /= 0) then
432  building_config%data_definitions(current_building_definition)%send_on_terminate=&
433  retrieve_string_value(attribute_values(send_on_termination_index), string_data_type) == "true"
434  else
435  building_config%data_definitions(current_building_definition)%send_on_terminate=.false.
436  end if
437  else
438  call log_log(log_error, "A data definition requires a name and frequency")
439  end if
440  allocate(building_config%data_definitions(current_building_definition)%fields(data_size_stride))
441 
442  building_config%data_definitions(current_building_definition)%fields(1)%name="timestep"
443  building_config%data_definitions(current_building_definition)%fields(1)%namespace=namespace
444  building_config%data_definitions(current_building_definition)%fields(1)%field_type=scalar_field_type
445  building_config%data_definitions(current_building_definition)%fields(1)%dimensions=0
446  building_config%data_definitions(current_building_definition)%fields(1)%data_type=integer_data_type
447  building_config%data_definitions(current_building_definition)%fields(1)%optional=.false.
448  building_config%data_definitions(current_building_definition)%fields(1)%collective=.false.
449  building_config%data_definitions(current_building_definition)%fields(1)%units=""
450 
451  building_config%data_definitions(current_building_definition)%fields(2)%name="time"
452  building_config%data_definitions(current_building_definition)%fields(2)%namespace=namespace
453  building_config%data_definitions(current_building_definition)%fields(2)%field_type=scalar_field_type
454  building_config%data_definitions(current_building_definition)%fields(2)%dimensions=0
455  building_config%data_definitions(current_building_definition)%fields(2)%data_type=double_data_type
456  building_config%data_definitions(current_building_definition)%fields(2)%optional=.false.
457  building_config%data_definitions(current_building_definition)%fields(2)%collective=.false.
458  building_config%data_definitions(current_building_definition)%fields(2)%units=""
459 
460  building_config%data_definitions(current_building_definition)%fields(3)%name="terminated"
461  building_config%data_definitions(current_building_definition)%fields(3)%namespace=namespace
462  building_config%data_definitions(current_building_definition)%fields(3)%field_type=scalar_field_type
463  building_config%data_definitions(current_building_definition)%fields(3)%dimensions=0
464  building_config%data_definitions(current_building_definition)%fields(3)%data_type=boolean_data_type
465  building_config%data_definitions(current_building_definition)%fields(3)%optional=.false.
466  building_config%data_definitions(current_building_definition)%fields(3)%collective=.false.
467  building_config%data_definitions(current_building_definition)%fields(3)%units=""
468 
470  end subroutine handle_new_data_definition
471 
472  subroutine add_misc_member_to_diagnostic(element_name, attribute_names, attribute_values)
473  character(len=*), intent(in) :: element_name
474  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
475 
476  type(io_configuration_misc_item_type), pointer :: misc_member
477  class(*), pointer :: generic
478  integer :: i
479 
480  allocate(misc_member)
481 
482  misc_member%type=retrieve_string_value(element_name, string_data_type)
483  misc_member%namespace=data_handling_namespace
484  do i=1, size(attribute_names)
485  call c_put_string(misc_member%embellishments, retrieve_string_value(attribute_names(i), string_data_type), &
486  retrieve_string_value(attribute_values(i), string_data_type))
487  end do
488  generic=>misc_member
489  call c_add_generic(building_config%diagnostics(current_building_diagnostic)%members, generic, .false.)
490  end subroutine add_misc_member_to_diagnostic
491 
492  subroutine add_diagnostic_field_to_group(element_name, attribute_names, attribute_values)
493  character(len=*), intent(in) :: element_name
494  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
495 
496  integer :: field_index
497 
498  if (element_name == "member") then
499  field_index=get_field_index_from_name(attribute_names, "name")
500  if (field_index .gt. 0) then
501  call c_add_string(building_config%groups(current_building_group)%members, &
502  retrieve_string_value(attribute_values(field_index), string_data_type))
503  else
504  call log_log(log_error, "A diagnostics group member requires a name")
505  end if
506  else
507  call log_log(log_error, "Unrecognised diagnostics group participant, name is '"//trim(element_name)//"'")
508  end if
509  end subroutine add_diagnostic_field_to_group
510 
511  subroutine define_group(attribute_names, attribute_values)
512  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
513 
514  integer :: field_index
515 
516  if (current_building_group .gt. size(building_config%groups)) call extend_groups_array()
517 
518  field_index=get_field_index_from_name(attribute_names, "name")
519  if (field_index .gt. 0) then
520  building_config%groups(current_building_group)%name=retrieve_string_value(attribute_values(field_index), string_data_type)
521  field_index=get_field_index_from_name(attribute_names, "namespace")
522  if (field_index .gt. 0) then
523  building_config%groups(current_building_group)%namespace=&
524  retrieve_string_value(attribute_values(field_index), string_data_type)
525  else
526  building_config%groups(current_building_group)%namespace=""
527  end if
528  else
529  call log_log(log_error, "A diagnostics group requires a name")
530  end if
531  end subroutine define_group
532 
533  subroutine add_include_to_file_writer(attribute_names, attribute_values)
534  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
535 
536  integer :: field_index, number_of_contents
537 
538  number_of_contents=building_config%file_writers(current_building_file_writer)%number_of_contents+1
539 
540  if (number_of_contents .gt. &
542 
543  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%facet_type=0
544  field_index=get_field_index_from_name(attribute_names, "group")
545  if (field_index .gt. 0) then
546  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%facet_name=&
547  retrieve_string_value(attribute_values(field_index), string_data_type)
548  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%facet_type=group_type
549  call add_include_group_or_field_to_file_writer(attribute_names, attribute_values, number_of_contents)
550  else
551  field_index=get_field_index_from_name(attribute_names, "field")
552  if (field_index .gt. 0) then
553  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%facet_name=&
554  retrieve_string_value(attribute_values(field_index), string_data_type)
555  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%facet_type=field_type
556  call add_include_group_or_field_to_file_writer(attribute_names, attribute_values, number_of_contents)
557  else
558  field_index=get_field_index_from_name(attribute_names, "state")
559  if (field_index .gt. 0) then
560  if (trim(retrieve_string_value(attribute_values(field_index), string_data_type)) .eq. "io") then
561  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%facet_type=io_state_type
562  end if
563  end if
564  end if
565  end if
566 
567  if (building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%facet_type == 0) then
568  call log_log(log_error, "Inclusion to file writer requires a field or group to include")
569  end if
570 
571  building_config%file_writers(current_building_file_writer)%number_of_contents=&
572  building_config%file_writers(current_building_file_writer)%number_of_contents+1
573  end subroutine add_include_to_file_writer
574 
575  subroutine add_include_group_or_field_to_file_writer(attribute_names, attribute_values, number_of_contents)
576  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
577  integer, intent(in) :: number_of_contents
578 
579  character(len=STRING_LENGTH) :: time_manip
580  integer :: field_index
581 
582  field_index=get_field_index_from_name(attribute_names, "time_manipulation")
583  if (field_index .gt. 0) then
584  time_manip=retrieve_string_value(attribute_values(field_index), string_data_type)
585  if (time_manip == "instantaneous") then
586  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%time_manipulation_type=&
588  else if (time_manip == "averaged") then
589  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%time_manipulation_type=&
591  else if (time_manip == "none") then
592  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%time_manipulation_type=&
593  none_type
594  else
595  call log_log(log_error, "Time manipulation '"//trim(time_manip)//"' option not recognised")
596  end if
597  else
598  call log_log(log_error, "Inclusion to file writer requires time manipulation")
599  end if
600 
601  field_index=get_field_index_from_name(attribute_names, "output_frequency")
602  if (field_index .gt. 0) then
604  contents(number_of_contents)%output_time_frequency=&
605  conv_to_real(retrieve_string_value(attribute_values(field_index), double_data_type))
606  else if (building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%time_manipulation_type &
607  == none_type) then
608  building_config%file_writers(current_building_file_writer)%contents(number_of_contents)%output_time_frequency=-1.0
609  else
610  call log_log(log_error, "Inclusion to file writer requires an output frequency")
611  end if
613 
614  subroutine define_file_writer(attribute_names, attribute_values)
615  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
616 
617  integer :: field_index
618 
619  if (current_building_file_writer .gt. size(building_config%file_writers)) call extend_file_writer_array()
620 
621  field_index=get_field_index_from_name(attribute_names, "name")
622  if (field_index .gt. 0) then
623  building_config%file_writers(current_building_file_writer)%file_name=&
624  retrieve_string_value(attribute_values(field_index), string_data_type)
625  else
626  call log_log(log_error, "File writer requires a file name")
627  end if
628 
629  field_index=get_field_index_from_name(attribute_names, "write_time_frequency")
630  if (field_index .gt. 0) then
631  building_config%file_writers(current_building_file_writer)%write_time_frequency=&
632  conv_to_real(retrieve_string_value(attribute_values(field_index), double_data_type))
633  building_config%file_writers(current_building_file_writer)%write_on_model_time=.true.
634  else
635  field_index=get_field_index_from_name(attribute_names, "write_timestep_frequency")
636  if (field_index .gt. 0) then
637  building_config%file_writers(current_building_file_writer)%write_timestep_frequency=&
638  conv_to_real(retrieve_string_value(attribute_values(field_index), integer_data_type))
639  building_config%file_writers(current_building_file_writer)%write_on_model_time=.false.
640  else
641  call log_log(log_error, "File writer requires either a write time frequency or write timestep frequency")
642  end if
643  end if
644 
645  field_index=get_field_index_from_name(attribute_names, "title")
646  if (field_index .gt. 0) then
647  building_config%file_writers(current_building_file_writer)%title=&
648  retrieve_string_value(attribute_values(field_index), string_data_type)
649  else
651  end if
652 
653  field_index=get_field_index_from_name(attribute_names, "write_on_terminate")
654  if (field_index .gt. 0) then
655  building_config%file_writers(current_building_file_writer)%write_on_terminate=&
656  retrieve_string_value(attribute_values(field_index), string_data_type) == "true"
657  else
658  building_config%file_writers(current_building_file_writer)%write_on_terminate=.false.
659  end if
660 
661  field_index=get_field_index_from_name(attribute_names, "store_state")
662  if (field_index .gt. 0) then
663  building_config%file_writers(current_building_file_writer)%include_in_io_state_write=&
664  retrieve_string_value(attribute_values(field_index), string_data_type) == "true"
665  else
666  building_config%file_writers(current_building_file_writer)%include_in_io_state_write=.true.
667  end if
668 
669  building_config%file_writers(current_building_file_writer)%number_of_contents=0
670  allocate(building_config%file_writers(current_building_file_writer)%contents(data_size_stride))
671  end subroutine define_file_writer
672 
678  subroutine define_diagnostic(attribute_names, attribute_values)
679  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
680 
681  integer :: field_index, type_field_index, data_field_index
682  character(len=STRING_LENGTH) :: field_type_str, field_data_type_str, size_definitions
683 
684  if (current_building_diagnostic .gt. size(building_config%diagnostics)) call extend_diagnostics_array()
685 
686  field_index=get_field_index_from_name(attribute_names, "field")
687  type_field_index=get_field_index_from_name(attribute_names, "type")
688  data_field_index=get_field_index_from_name(attribute_names, "data_type")
689 
690  if (field_index == 0 .or. type_field_index == 0 .or. data_field_index == 0) then
691  call log_log(log_error, "Each diagnostic definition requires a field name, field type and data type")
692  else
693  building_config%diagnostics(current_building_diagnostic)%name=&
694  retrieve_string_value(attribute_values(field_index), string_data_type)
696  field_type_str=retrieve_string_value(attribute_values(type_field_index), string_data_type)
697  building_config%diagnostics(current_building_diagnostic)%field_type=get_field_type_from_attribute(field_type_str)
698  if (building_config%diagnostics(current_building_diagnostic)%field_type==0) then
699  call log_log(log_error, "The field type of '"//trim(field_type_str)//"' is not recognised")
700  end if
701  field_data_type_str=retrieve_string_value(attribute_values(data_field_index), string_data_type)
702  building_config%diagnostics(current_building_diagnostic)%data_type=get_field_datatype_from_attribute(field_data_type_str)
703  if (building_config%diagnostics(current_building_diagnostic)%data_type==0) then
704  call log_log(log_error, "The field data type of '"//trim(field_data_type_str)//"' is not recognised")
705  end if
706  field_index=get_field_index_from_name(attribute_names, "units")
707  if (field_index .ne. 0) then
708  building_config%diagnostics(current_building_diagnostic)%units=&
709  retrieve_string_value(attribute_values(field_index), string_data_type)
710  else
711  building_config%diagnostics(current_building_diagnostic)%units=""
712  end if
713  if (building_config%diagnostics(current_building_diagnostic)%field_type == array_field_type .or. &
714  building_config%diagnostics(current_building_diagnostic)%field_type == map_field_type) then
715  field_index=get_field_index_from_name(attribute_names, "size")
716  if (field_index .ne. 0) then
717  size_definitions=retrieve_string_value(attribute_values(field_index), string_data_type)
718  building_config%diagnostics(current_building_diagnostic)%dimensions=process_sizing_definition(size_definitions, &
719  building_config%diagnostics(current_building_diagnostic)%dim_size_defns)
720  else
721  call log_log(log_error, "A diagnostic of field type array or map requires sizing a definition")
722  end if
723  field_index=get_field_index_from_name(attribute_names, "collective")
724  if (field_index .ne. 0) then
725  building_config%diagnostics(current_building_diagnostic)%collective=&
726  retrieve_string_value(attribute_values(field_index), string_data_type) == "true"
727  else
728  building_config%diagnostics(current_building_diagnostic)%collective=.false.
729  end if
730  else
731  building_config%diagnostics(current_building_diagnostic)%dimensions=0
732  building_config%diagnostics(current_building_diagnostic)%collective=.false.
733  end if
734  end if
735  end subroutine define_diagnostic
736 
737  integer function process_sizing_definition(size_definitions, individual_str_defn)
738  character(len=*), intent(in) :: size_definitions
739  character(len=STRING_LENGTH), intent(out) :: individual_str_defn(4)
740 
741  integer :: comma_index, sizing_index, cp
742 
743  cp=1
744  sizing_index=1
745  comma_index=index(size_definitions(cp:), ",")
746  do while (comma_index .ne. 0)
747  comma_index=comma_index+cp-1
748  individual_str_defn(sizing_index)= trim(size_definitions(cp:comma_index-1))
749  cp=comma_index+1
750  sizing_index=sizing_index+1
751  comma_index=index(size_definitions(cp:), ",")
752  if (sizing_index .gt. 4) then
753  call log_log(log_error, "Can only have a maximum of four diagnostic field sizing dimensions")
754  end if
755  end do
756  if (cp .le. len(size_definitions)) then
757  individual_str_defn(sizing_index)=trim(size_definitions(cp:))
758  sizing_index=sizing_index+1
759  end if
760  process_sizing_definition=sizing_index-1
761  end function process_sizing_definition
762 
769  subroutine process_xml_into_field_description(attribute_names, attribute_values)
770  character(len=*), dimension(:), intent(in) :: attribute_names, attribute_values
771 
772  character(len=STRING_LENGTH) :: field_type_str, field_data_type_str, sizing_defn_str
773  integer :: name_field_index, type_field_index, data_field_index, field_index, optional_field_index, idx
774 
775 
776  name_field_index=get_field_index_from_name(attribute_names, "name")
777  type_field_index=get_field_index_from_name(attribute_names, "type")
778  data_field_index=get_field_index_from_name(attribute_names, "data_type")
779 
780  if (name_field_index == 0 .or. type_field_index == 0 .or. data_field_index == 0) then
781  call log_log(log_error, "Each data field definition requires a name, field type and data type")
782  else
783  if (current_building_field .eq. size(building_config%data_definitions(current_building_definition)%fields)) &
784  call extend_field_array()
785 
787  retrieve_string_value(attribute_values(name_field_index), string_data_type)
788 
791 
792  field_type_str=retrieve_string_value(attribute_values(type_field_index), string_data_type)
793  building_config%data_definitions(current_building_definition)%fields(current_building_field)%field_type=&
794  get_field_type_from_attribute(field_type_str)
795 
796  if (building_config%data_definitions(current_building_definition)%fields(current_building_field)%field_type==0) then
797  call log_log(log_error, "The field type of '"//trim(field_type_str)//"' is not recognised")
798  end if
799 
800  building_config%data_definitions(current_building_definition)%fields(current_building_field)%dimensions=0
801 
802  if (building_config%data_definitions(current_building_definition)%fields(current_building_field)%field_type == &
803  array_field_type .or. &
804  building_config%data_definitions(current_building_definition)%fields(current_building_field)%field_type == &
805  map_field_type) then
806  idx=get_field_index_from_name(attribute_names, "size")
807  if (idx .ne. 0) then
808  sizing_defn_str=retrieve_string_value(attribute_values(idx), string_data_type)
809  building_config%data_definitions(current_building_definition)%fields(current_building_field)%dimensions=&
810  process_sizing_definition(sizing_defn_str, &
811  building_config%data_definitions(current_building_definition)%fields(current_building_field)%dim_size_defns)
812  end if
813 
814  field_index=get_field_index_from_name(attribute_names, "collective")
815  if (field_index .ne. 0) then
816  building_config%data_definitions(current_building_definition)%fields(current_building_field)%collective=&
817  retrieve_string_value(attribute_values(field_index), string_data_type) == "true"
818  else
819  building_config%data_definitions(current_building_definition)%fields(current_building_field)%collective=.false.
820  end if
821  else
822  building_config%data_definitions(current_building_definition)%fields(current_building_field)%collective=.false.
823  end if
824 
825  field_index=get_field_index_from_name(attribute_names, "units")
826  if (field_index .ne. 0) then
827  building_config%data_definitions(current_building_definition)%fields(current_building_field)%units=&
828  retrieve_string_value(attribute_values(field_index), string_data_type)
829  else
830  building_config%data_definitions(current_building_definition)%fields(current_building_field)%units=""
831  end if
832 
833  field_data_type_str=retrieve_string_value(attribute_values(data_field_index), string_data_type)
834  building_config%data_definitions(current_building_definition)%fields(current_building_field)%data_type=&
835  get_field_datatype_from_attribute(field_data_type_str)
836 
837  if (building_config%data_definitions(current_building_definition)%fields(current_building_field)%data_type==0) then
838  call log_log(log_error, "The field data type of '"//trim(field_data_type_str)//"' is not recognised")
839  end if
840 
841  if (building_config%data_definitions(current_building_definition)%fields(current_building_field)%field_type == &
842  map_field_type .and. building_config%data_definitions(current_building_definition)%fields(&
843  current_building_field)%data_type/=string_data_type) then
844  call log_log(log_error, "A map field type must have a data type of ""string""")
845  end if
846 
847  optional_field_index=get_field_index_from_name(attribute_names, "optional")
848  if (optional_field_index .ne. 0) then
849  if (retrieve_string_value(attribute_values(optional_field_index), string_data_type) == "true") then
850  building_config%data_definitions(current_building_definition)%fields(current_building_field)%optional=.true.
851  else
852  building_config%data_definitions(current_building_definition)%fields(current_building_field)%optional=.false.
853  end if
854  else
855  building_config%data_definitions(current_building_definition)%fields(current_building_field)%optional=.false.
856  end if
858  end if
860 
861  integer function get_field_type_from_attribute(field_type_str)
862  character(len=*), intent(in) :: field_type_str
863 
865  if (field_type_str == "scalar") get_field_type_from_attribute=scalar_field_type
866  if (field_type_str == "array") get_field_type_from_attribute=array_field_type
867  if (field_type_str == "map") get_field_type_from_attribute=map_field_type
868  end function get_field_type_from_attribute
869 
870  integer function get_field_datatype_from_attribute(field_data_type_str)
871  character(len=*), intent(in) :: field_data_type_str
872 
874  if (field_data_type_str == "integer") get_field_datatype_from_attribute=integer_data_type
875  if (field_data_type_str == "boolean") get_field_datatype_from_attribute=boolean_data_type
876  if (field_data_type_str == "string") get_field_datatype_from_attribute=string_data_type
877  if (field_data_type_str == "float") get_field_datatype_from_attribute=float_data_type
878  if (field_data_type_str == "double") get_field_datatype_from_attribute=double_data_type
880 
885  subroutine replace_characters_in_string(original_string, new_string, to_replace)
886  character(len=*), intent(in) :: original_string, to_replace
887  character(len=*), intent(out) :: new_string
888 
889  integer :: current_index, string_len, occurance
890 
891  current_index=1
892  string_len=len(original_string)
893  new_string=""
894  do while (current_index .lt. string_len)
895  occurance=index(original_string(current_index:), to_replace)
896  if (occurance .eq. 0) then
897  occurance=len(original_string)
898  else
899  occurance=occurance+current_index
900  end if
901  new_string=trim(new_string)//trim(original_string(current_index:occurance-len(to_replace)-1))
902  current_index=current_index+occurance+len(to_replace)-2
903  end do
904  end subroutine replace_characters_in_string
905 
906  character(len=STRING_LENGTH) function retrieve_string_value(original_string, field_value_type)
907  character(len=*), intent(in) :: original_string
908  integer, intent(in) :: field_value_type
909 
910  integer :: last_char
911  character(len=STRING_LENGTH) :: lookup_key
912 
913  call replace_characters_in_string(original_string, retrieve_string_value, """")
914 
916  if (retrieve_string_value(1:1)=="{") then
917  last_char=len_trim(retrieve_string_value)
918  if (retrieve_string_value(last_char:last_char)=="}") then
919  lookup_key=retrieve_string_value(2:last_char-1)
920  if (options_has_key(options_database, lookup_key)) then
921  if (field_value_type==integer_data_type) then
923  else if (field_value_type==boolean_data_type) then
925  else if (field_value_type==double_data_type) then
927  else if (field_value_type==string_data_type) then
929  end if
930  else
931  call log_log(log_error, "Can not find IO configuration key '"//trim(lookup_key)//"' in the options database")
932  end if
933  end if
934  end if
935  end function retrieve_string_value
936 
940  integer function get_field_index_from_name(attribute_names, search_name)
941  character(len=*), intent(in) :: search_name
942  character(len=*), dimension(:) :: attribute_names
943 
944  integer :: i, size_of_names
945 
946  size_of_names=size(attribute_names)
947  do i=1,size_of_names
948  if (attribute_names(i) == search_name) then
950  return
951  end if
952  end do
954  end function get_field_index_from_name
955 
959  subroutine extend_inter_io_comm_array(io_configuration)
960  type(io_configuration_type), intent(inout) :: io_configuration
961 
962  type(io_configuration_inter_communication_description), dimension(:), allocatable :: temp_descriptions
963 
964  allocate(temp_descriptions(lbound(io_configuration%inter_io_communications,1):&
965  ubound(io_configuration%inter_io_communications,1)+data_size_stride))
966  temp_descriptions(lbound(io_configuration%inter_io_communications,1):&
967  ubound(io_configuration%inter_io_communications,1)) = io_configuration%inter_io_communications
968  call move_alloc(from=temp_descriptions,to=io_configuration%inter_io_communications)
969  end subroutine extend_inter_io_comm_array
970 
972  type(io_configuration_file_writer_facet_type), dimension(:), allocatable :: temp_filewriter_contents
973 
974  allocate(temp_filewriter_contents(lbound(building_config%file_writers(current_building_file_writer)%contents,1): &
975  ubound(building_config%file_writers(current_building_file_writer)%contents,1)+data_size_stride))
976  temp_filewriter_contents(lbound(building_config%file_writers(current_building_file_writer)%contents,1):&
977  ubound(building_config%file_writers(current_building_file_writer)%contents,1)) = &
978  building_config%file_writers(current_building_file_writer)%contents
979  call move_alloc(from=temp_filewriter_contents,to=building_config%file_writers(current_building_file_writer)%contents)
980  end subroutine extend_file_writer_contents_array
981 
983  type(io_configuration_file_writer_type), dimension(:), allocatable :: temp_filewriter
984 
985  allocate(temp_filewriter(lbound(building_config%file_writers,1): ubound(building_config%file_writers,1)+data_size_stride))
986  temp_filewriter(lbound(building_config%file_writers,1):ubound(building_config%file_writers,1)) = building_config%file_writers
987  call move_alloc(from=temp_filewriter,to=building_config%file_writers)
988  end subroutine extend_file_writer_array
989 
992  type(io_configuration_diagnostic_field_type), dimension(:), allocatable :: temp_diagnostics
993 
994  allocate(temp_diagnostics(lbound(building_config%diagnostics,1): ubound(building_config%diagnostics,1)+data_size_stride))
995  temp_diagnostics(lbound(building_config%diagnostics,1):ubound(building_config%diagnostics,1)) = building_config%diagnostics
996  call move_alloc(from=temp_diagnostics,to=building_config%diagnostics)
997  end subroutine extend_diagnostics_array
998 
999  subroutine extend_groups_array()
1000  type(io_configuration_group_type), dimension(:), allocatable :: temp_groups
1001 
1002  allocate(temp_groups(lbound(building_config%groups,1): ubound(building_config%groups,1)+data_size_stride))
1003  temp_groups(lbound(building_config%groups,1):ubound(building_config%groups,1)) = building_config%groups
1004  call move_alloc(from=temp_groups,to=building_config%groups)
1005  end subroutine extend_groups_array
1006 
1008  subroutine extend_field_array()
1009  type(io_configuration_field_type), dimension(:), allocatable :: temp_fields
1010 
1011  allocate(temp_fields(lbound(building_config%data_definitions(current_building_definition)%fields,1):&
1012  ubound(building_config%data_definitions(current_building_definition)%fields,1)+data_size_stride))
1013  temp_fields(lbound(building_config%data_definitions(current_building_definition)%fields,1):&
1014  ubound(building_config%data_definitions(current_building_definition)%fields,1)) = &
1015  building_config%data_definitions(current_building_definition)%fields
1016  call move_alloc(from=temp_fields,to=building_config%data_definitions(current_building_definition)%fields)
1017  end subroutine extend_field_array
1018 
1021  type(io_configuration_data_definition_type), dimension(:), allocatable :: temp_data_definitions
1022 
1023  allocate(temp_data_definitions(lbound(building_config%data_definitions, 1):&
1024  ubound(building_config%data_definitions,1)+data_size_stride))
1025  temp_data_definitions(lbound(building_config%data_definitions, 1):&
1026  ubound(building_config%data_definitions, 1)) = building_config%data_definitions
1027  call move_alloc(from=temp_data_definitions,to=building_config%data_definitions)
1028  end subroutine extend_data_definition_array
1029 
1032  subroutine extend_registered_moncs_array(io_configuration)
1033  type(io_configuration_type), intent(inout) :: io_configuration
1034 
1035  type(io_configuration_registered_monc_type), dimension(:), allocatable :: temp_registered_moncs
1036 
1037  allocate(temp_registered_moncs(lbound(io_configuration%registered_moncs, 1):&
1038  io_configuration%number_of_moncs+monc_size_stride))
1039  temp_registered_moncs(lbound(io_configuration%registered_moncs, 1):&
1040  ubound(io_configuration%registered_moncs, 1)) = io_configuration%registered_moncs
1041  call move_alloc(from=temp_registered_moncs,to=io_configuration%registered_moncs)
1042  end subroutine extend_registered_moncs_array
1043 
1048  integer function retrieve_data_definition(io_configuration, key)
1049  type(io_configuration_type), intent(inout) :: io_configuration
1050  character(len=*), intent(in) :: key
1051 
1052  integer :: i
1053 
1054  do i=1,io_configuration%number_of_data_definitions
1055  if (io_configuration%data_definitions(i)%name .eq. key) then
1057  return
1058  end if
1059  end do
1061  end function retrieve_data_definition
1062 
1068  logical function retrieve_monc_definition(io_configuration, source, monc_defn)
1069  type(io_configuration_type), intent(inout) :: io_configuration
1070  integer, intent(in) :: source
1071  type(io_configuration_registered_monc_type), intent(out) :: monc_defn
1072 
1073  class(*), pointer :: generic
1074  integer :: location
1075 
1076  generic=>c_get_generic(io_configuration%monc_to_index, conv_to_string(source))
1077  if (associated(generic)) then
1078  location=conv_to_integer(generic, .false.)
1079  monc_defn=io_configuration%registered_moncs(location)
1081  else
1082  retrieve_monc_definition=.false.
1083  end if
1084  end function retrieve_monc_definition
1085 
1090  type(io_configuration_type), intent(inout) :: io_configuration
1092 
1093  integer :: i
1094 
1095  allocate(build_definition_description_type_from_configuration(io_configuration%number_of_data_definitions))
1096 
1097  do i=1, io_configuration%number_of_data_definitions
1098  build_definition_description_type_from_configuration(i)%definition_name=io_configuration%data_definitions(i)%name
1100  io_configuration%data_definitions(i)%send_on_terminate
1102  io_configuration%data_definitions(i)%number_of_data_fields
1103  build_definition_description_type_from_configuration(i)%frequency=io_configuration%data_definitions(i)%frequency
1104  end do
1106 
1111  type(io_configuration_type), intent(inout) :: io_configuration
1113 
1114  integer :: i, j, field_index
1115 
1117  field_index=1
1118  do i=1, io_configuration%number_of_data_definitions
1119  do j=1, io_configuration%data_definitions(i)%number_of_data_fields
1120  build_field_description_type_from_configuration(field_index)%definition_name=io_configuration%data_definitions(i)%name
1121  build_field_description_type_from_configuration(field_index)%field_name=&
1122  io_configuration%data_definitions(i)%fields(j)%name
1123  build_field_description_type_from_configuration(field_index)%field_type=&
1124  io_configuration%data_definitions(i)%fields(j)%field_type
1125  build_field_description_type_from_configuration(field_index)%data_type=&
1126  io_configuration%data_definitions(i)%fields(j)%data_type
1127  build_field_description_type_from_configuration(field_index)%optional=&
1128  io_configuration%data_definitions(i)%fields(j)%optional
1129  field_index=field_index+1
1130  end do
1131  end do
1133 
1137  integer function get_total_number_fields(io_configuration)
1138  type(io_configuration_type), intent(inout) :: io_configuration
1139 
1140  integer :: i
1141 
1143  do i=1, io_configuration%number_of_data_definitions
1144  get_total_number_fields=get_total_number_fields+io_configuration%data_definitions(i)%number_of_data_fields
1145  end do
1146  end function get_total_number_fields
1147 
1155  integer function get_number_field_dimensions(io_configuration, field_name, source, data_id)
1156  type(io_configuration_type), intent(inout) :: io_configuration
1157  character(len=*), intent(in) :: field_name
1158  integer, intent(in) :: source, data_id
1159 
1160  integer :: monc_location
1161 
1162  monc_location=c_get_integer(io_configuration%monc_to_index, conv_to_string(source))
1163  get_number_field_dimensions=c_get_integer(io_configuration%registered_moncs(monc_location)%dimensions(data_id), field_name)
1164  end function get_number_field_dimensions
1165 
1170  function get_data_value_from_hashmap_by_field_name(collection, field_name)
1171  type(hashmap_type), intent(inout) :: collection
1172  character(len=*), intent(in) :: field_name
1174 
1175  class(*), pointer :: generic
1176 
1177  generic=>c_get_generic(collection, field_name)
1178  if (associated(generic)) then
1179  select type(generic)
1180  type is (data_values_type)
1182  end select
1183  else
1185  end if
1187 
1192  function get_data_value_from_map_by_field_name(collection, field_name)
1193  type(map_type), intent(inout) :: collection
1194  character(len=*), intent(in) :: field_name
1196 
1197  class(*), pointer :: generic
1198 
1199  generic=>c_get_generic(collection, field_name)
1200  if (associated(generic)) then
1201  select type(generic)
1202  type is (data_values_type)
1204  end select
1205  else
1207  end if
1209 
1213  function get_data_value_from_map_entry(map_entry)
1214  type(mapentry_type), intent(in) :: map_entry
1216 
1217  class(*), pointer :: generic
1218 
1219  generic=>c_get_generic(map_entry)
1220  if (associated(generic)) then
1221  select type(generic)
1222  type is (data_values_type)
1224  end select
1225  else
1227  end if
1228  end function get_data_value_from_map_entry
1229 
1233  integer function get_monc_location(io_configuration, source)
1234  type(io_configuration_type), intent(inout) :: io_configuration
1235  integer, intent(in) :: source
1236 
1237  get_monc_location=c_get_integer(io_configuration%monc_to_index, conv_to_string(source))
1238  end function get_monc_location
1239 
1245  logical function get_diagnostic_field_configuration(io_configuration, field_name, field_namespace, diagnostic_config)
1246  type(io_configuration_type), intent(inout) :: io_configuration
1247  character(len=*), intent(in) :: field_name, field_namespace
1248  type(io_configuration_diagnostic_field_type), intent(out) :: diagnostic_config
1249 
1250  integer :: i
1251 
1252  do i=1, size(io_configuration%diagnostics)
1253  if (io_configuration%diagnostics(i)%name == field_name .and. &
1254  io_configuration%diagnostics(i)%namespace == field_namespace) then
1255  diagnostic_config=io_configuration%diagnostics(i)
1257  return
1258  end if
1259  end do
1262 
1268  logical function get_prognostic_field_configuration(io_configuration, field_name, field_namespace, &
1269  prognostic_config, prognostic_containing_data_defn)
1270  type(io_configuration_type), intent(inout) :: io_configuration
1271  character(len=*), intent(in) :: field_name, field_namespace
1272  type(io_configuration_field_type), intent(out) :: prognostic_config
1273  type(io_configuration_data_definition_type), intent(out), optional :: prognostic_containing_data_defn
1274 
1275  integer :: i, j
1276  do i=1, io_configuration%number_of_data_definitions
1277  do j=1, io_configuration%data_definitions(i)%number_of_data_fields
1278  if (io_configuration%data_definitions(i)%fields(j)%name == field_name .and. &
1279  io_configuration%data_definitions(i)%fields(j)%namespace == field_namespace) then
1280  prognostic_config=io_configuration%data_definitions(i)%fields(j)
1281  if (present(prognostic_containing_data_defn)) then
1282  prognostic_containing_data_defn=io_configuration%data_definitions(i)
1283  end if
1285  return
1286  end if
1287  end do
1288  end do
1291 
1296  subroutine add_in_specific_line(io_xml, reading_buffer)
1297  character, dimension(:), allocatable, intent(inout) :: io_xml
1298  character(len=*), intent(in) :: reading_buffer
1299 
1300  character, dimension(:), allocatable :: temp_io_xml
1301  integer :: i
1302 
1303  if (.not. allocated(io_xml)) then
1304  allocate(io_xml(len_trim(reading_buffer)))
1305  do i=1, len_trim(reading_buffer)
1306  io_xml(i)=reading_buffer(i:i)
1307  end do
1308  else
1309  allocate(temp_io_xml(size(io_xml)+len_trim(reading_buffer)))
1310  temp_io_xml(:size(io_xml)) = io_xml
1311  do i=1, len_trim(reading_buffer)
1312  temp_io_xml(size(io_xml)+i) = reading_buffer(i:i)
1313  end do
1314  call move_alloc(from=temp_io_xml,to=io_xml)
1315  end if
1316  end subroutine add_in_specific_line
1317 
1321  subroutine combine_xml_arrays(io_xml, other_xml_array)
1322  character, dimension(:), allocatable, intent(inout) :: io_xml, other_xml_array
1323 
1324  character, dimension(:), allocatable :: temp_io_xml
1325 
1326  if (.not. allocated(other_xml_array)) return
1327 
1328  if (.not. allocated(io_xml)) then
1329  allocate(io_xml(size(other_xml_array)), source=other_xml_array)
1330  else
1331  allocate(temp_io_xml(size(io_xml)+size(other_xml_array)))
1332  temp_io_xml(:size(io_xml)) = io_xml
1333  temp_io_xml(size(io_xml)+1:) = other_xml_array
1334  call move_alloc(from=temp_io_xml,to=io_xml)
1335  end if
1336  end subroutine combine_xml_arrays
1337 end module configuration_parser_mod
configuration_parser_mod::define_file_writer
subroutine define_file_writer(attribute_names, attribute_values)
Definition: configurationparser.F90:615
logging_mod::log_error
integer, parameter, public log_error
Only log ERROR messages.
Definition: logging.F90:11
conversions_mod
Conversion between common inbuilt FORTRAN data types.
Definition: conversions.F90:5
collections_mod::map_type
Map data structure that holds string (length 20 maximum) key value pairs.
Definition: collections.F90:86
collections_mod::c_add_generic
Adds a generic element to the end of the list.
Definition: collections.F90:204
configuration_parser_mod::cond_request
character(len=string_length), dimension(:), allocatable, public cond_request
Definition: configurationparser.F90:147
configuration_parser_mod::extend_diagnostics_array
subroutine extend_diagnostics_array()
Extends the rules array of a specific rule from the current size to the current size + data size stri...
Definition: configurationparser.F90:992
configuration_parser_mod::add_operator_type
integer, parameter, public add_operator_type
Definition: configurationparser.F90:23
io_server_client_mod::float_data_type
integer, parameter, public float_data_type
Definition: ioclient.F90:40
configuration_parser_mod::extend_groups_array
subroutine extend_groups_array()
Definition: configurationparser.F90:1000
configuration_parser_mod::add_include_to_file_writer
subroutine add_include_to_file_writer(attribute_names, attribute_values)
Definition: configurationparser.F90:534
configuration_parser_mod::or_operator_type
integer, parameter or_operator_type
Definition: configurationparser.F90:23
logging_mod::log_warn
integer, parameter, public log_warn
Log WARNING and ERROR messages.
Definition: logging.F90:12
configuration_parser_mod::gt_operator_type
integer, parameter, public gt_operator_type
Definition: configurationparser.F90:23
io_server_client_mod::string_data_type
integer, parameter, public string_data_type
Definition: ioclient.F90:40
optionsdatabase_mod::options_get_array_size
integer function, public options_get_array_size(options_database, key)
Gets the size of the array held in the options database corresponding to a specific key.
Definition: optionsdatabase.F90:342
configuration_parser_mod::retrieve_monc_definition
logical function, public retrieve_monc_definition(io_configuration, source, monc_defn)
Retrieves a specific MONC definition from the configuration which matches a source PID.
Definition: configurationparser.F90:1069
configuration_parser_mod::get_total_number_fields
integer function get_total_number_fields(io_configuration)
Retrieves the total number of fields held in all data definitions.
Definition: configurationparser.F90:1138
io_server_client_mod::field_description_type
Definition: ioclient.F90:21
configuration_parser_mod::diag_long
character(len=string_length), dimension(:), allocatable, public diag_long
Definition: configurationparser.F90:147
conversions_mod::conv_to_integer
Converts data types to integers.
Definition: conversions.F90:49
configuration_parser_mod::process_sizing_definition
integer function process_sizing_definition(size_definitions, individual_str_defn)
Definition: configurationparser.F90:738
configuration_parser_mod::add_include_group_or_field_to_file_writer
subroutine add_include_group_or_field_to_file_writer(attribute_names, attribute_values, number_of_contents)
Definition: configurationparser.F90:576
io_server_client_mod::integer_data_type
integer, parameter, public integer_data_type
Definition: ioclient.F90:40
collections_mod
Collection data structures.
Definition: collections.F90:7
configuration_parser_mod::file_str_stride
integer, parameter file_str_stride
Definition: configurationparser.F90:135
configuration_parser_mod::gte_operator_type
integer, parameter, public gte_operator_type
Definition: configurationparser.F90:23
optionsdatabase_mod::options_get_integer
integer function, public options_get_integer(options_database, key, index)
Retrieves an integer value from the database that matches the provided key.
Definition: optionsdatabase.F90:217
configuration_parser_mod::data_field_names
type(hashset_type) data_field_names
Definition: configurationparser.F90:145
configuration_parser_mod::eq_operator_type
integer, parameter, public eq_operator_type
Definition: configurationparser.F90:23
configuration_parser_mod::extend_file_writer_array
subroutine extend_file_writer_array()
Definition: configurationparser.F90:983
configuration_parser_mod::diag_request
character(len=string_length), dimension(:), allocatable, public diag_request
Definition: configurationparser.F90:147
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
sax_xml_parser_mod
A SAX parser for XML files. This is used to parse the description of the data and rules....
Definition: saxparser.F90:5
io_server_client_mod::scalar_field_type
integer, parameter, public scalar_field_type
Definition: ioclient.F90:38
io_server_client_mod::map_field_type
integer, parameter, public map_field_type
Field data type identifiers.
Definition: ioclient.F90:38
configuration_parser_mod::start_element_callback
subroutine start_element_callback(element_name, number_of_attributes, attribute_names, attribute_values)
XML element start (opening) call back. This handles most of the configuration parsing.
Definition: configurationparser.F90:297
configuration_parser_mod::building_config
type(io_configuration_type), save building_config
IO configuration that is build built up from XML parsing.
Definition: configurationparser.F90:141
collections_mod::c_size
Returns the number of elements in the collection.
Definition: collections.F90:428
configuration_parser_mod::lte_operator_type
integer, parameter, public lte_operator_type
Definition: configurationparser.F90:23
configuration_parser_mod::io_configuration_misc_item_type
Definition: configurationparser.F90:72
configuration_parser_mod::ndiag
integer, public ndiag
Definition: configurationparser.F90:148
configuration_parser_mod::instantaneous_type
integer, parameter, public instantaneous_type
Definition: configurationparser.F90:28
configuration_parser_mod::lt_operator_type
integer, parameter, public lt_operator_type
Definition: configurationparser.F90:23
io_server_client_mod::array_field_type
integer, parameter, public array_field_type
Definition: ioclient.F90:38
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
configuration_parser_mod::multiply_operator_type
integer, parameter, public multiply_operator_type
Definition: configurationparser.F90:23
configuration_parser_mod::data_size_stride
integer, parameter, public data_size_stride
Definition: configurationparser.F90:26
configuration_parser_mod::io_configuration_file_writer_facet_type
Definition: configurationparser.F90:89
configuration_parser_mod::inside_action_config
logical inside_action_config
Definition: configurationparser.F90:137
configuration_parser_mod::inside_diagnostic_config
logical inside_diagnostic_config
Definition: configurationparser.F90:137
configuration_parser_mod::extend_inter_io_comm_array
subroutine, public extend_inter_io_comm_array(io_configuration)
Extends the array of inter io communications from its current suze to current size+data_stride+curren...
Definition: configurationparser.F90:960
configuration_parser_mod::io_configuration_data_definition_type
Configuration of a specific data definition.
Definition: configurationparser.F90:58
configuration_parser_mod::none_type
integer, parameter, public none_type
Definition: configurationparser.F90:28
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
configuration_parser_mod::current_building_definition
integer current_building_definition
Definition: configurationparser.F90:139
configuration_parser_mod::div_operator_type
integer, parameter, public div_operator_type
Definition: configurationparser.F90:23
configuration_parser_mod::inside_group_config
logical inside_group_config
Definition: configurationparser.F90:137
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
configuration_parser_mod::field_type
integer, parameter, public field_type
Definition: configurationparser.F90:28
sax_xml_parser_mod::xml_parse
subroutine, public xml_parse(raw_contents, start_element_callback, end_element_callback)
Parses some raw XML raw_contents The raw (unparsed) XML string start_element_callback Subroutine to c...
Definition: saxparser.F90:36
configuration_parser_mod::options_database
type(hashmap_type) options_database
Definition: configurationparser.F90:144
configuration_parser_mod::inside_specific_file_writing
logical inside_specific_file_writing
Definition: configurationparser.F90:137
q_indices_mod::get_number_active_q_indices
integer function, public get_number_active_q_indices()
Gets the number of active Q indicies (i.e. those allocated to specific uses)
Definition: q_indices.F90:87
optionsdatabase_mod::options_get_string
character(len=string_length) function, public options_get_string(options_database, key, index)
Retrieves a string value from the database that matches the provided key.
Definition: optionsdatabase.F90:280
io_server_client_mod::double_data_type
integer, parameter, public double_data_type
Definition: ioclient.F90:40
configuration_parser_mod::combine_xml_arrays
subroutine combine_xml_arrays(io_xml, other_xml_array)
Combines two IO XML arrays together (for instance one returned from a recursive include)
Definition: configurationparser.F90:1322
configuration_parser_mod::add_misc_member_to_diagnostic
subroutine add_misc_member_to_diagnostic(element_name, attribute_names, attribute_values)
Definition: configurationparser.F90:473
configuration_parser_mod::file_line_len
integer, parameter file_line_len
Definition: configurationparser.F90:135
configuration_parser_mod::process_xml_into_field_description
subroutine process_xml_into_field_description(attribute_names, attribute_values)
Process XML into a field description by identifying the attributes of the field and storing these in ...
Definition: configurationparser.F90:770
configuration_parser_mod::ncond
integer, public ncond
Definition: configurationparser.F90:148
configuration_parser_mod::add_diagnostic_field_to_group
subroutine add_diagnostic_field_to_group(element_name, attribute_names, attribute_values)
Definition: configurationparser.F90:493
configuration_parser_mod::add_in_specific_line
subroutine add_in_specific_line(io_xml, reading_buffer)
Adds a specific line into the io xml. The IO XML is always exactly the correct size,...
Definition: configurationparser.F90:1297
configuration_parser_mod::get_data_value_from_hashmap_by_field_name
type(data_values_type) function, pointer get_data_value_from_hashmap_by_field_name(collection, field_name)
Retrieves the data value (wrapper) by field name or null if no entry was found in the provided collec...
Definition: configurationparser.F90:1171
optionsdatabase_mod::options_has_key
logical function, public options_has_key(options_database, key)
Determines whether a specific key is in the database.
Definition: optionsdatabase.F90:76
configuration_parser_mod::configuration_parse
subroutine, public configuration_parse(provided_options_database, raw_configuration, parsed_configuration)
This will parse an XML string into the IO configuration.
Definition: configurationparser.F90:220
configuration_parser_mod::inside_handling_definition
logical inside_handling_definition
Definition: configurationparser.F90:137
configuration_parser_mod::handle_new_data_definition
subroutine handle_new_data_definition(attribute_names, attribute_values)
Creates a new data definition configuration item based upon the attributes supplied.
Definition: configurationparser.F90:409
configuration_parser_mod::get_field_datatype_from_attribute
integer function get_field_datatype_from_attribute(field_data_type_str)
Definition: configurationparser.F90:871
configuration_parser_mod::current_building_group
integer current_building_group
Definition: configurationparser.F90:139
configuration_parser_mod::io_state_type
integer, parameter, public io_state_type
Definition: configurationparser.F90:28
conversions_mod::conv_to_string
Converts data types to strings.
Definition: conversions.F90:38
configuration_parser_mod::io_configuration_diagnostic_field_type
Definition: configurationparser.F90:77
configuration_parser_mod::extend_file_writer_contents_array
subroutine extend_file_writer_contents_array()
Definition: configurationparser.F90:972
configuration_parser_mod::inside_server_config
logical inside_server_config
Definition: configurationparser.F90:137
configuration_parser_mod::default_file_title
character(len=string_length), parameter default_file_title
Definition: configurationparser.F90:22
configuration_parser_mod::io_configuration_group_type
Definition: configurationparser.F90:84
configuration_parser_mod::time_averaged_type
integer, parameter, public time_averaged_type
Definition: configurationparser.F90:28
configuration_parser_mod::extend_registered_moncs_array
subroutine, public extend_registered_moncs_array(io_configuration)
Extends the data definitions array from the current size to the current size + data size stride.
Definition: configurationparser.F90:1033
configuration_parser_mod::io_configuration_file_writer_type
Definition: configurationparser.F90:95
configuration_parser_mod::io_configuration_type
Overall IO configuration.
Definition: configurationparser.F90:104
configuration_parser_mod::handle_thread_pool_configuration
subroutine handle_thread_pool_configuration(attribute_names, attribute_values)
Definition: configurationparser.F90:393
collections_mod::c_put_integer
Puts an integer key-value pair into the map.
Definition: collections.F90:318
collections_mod::c_put_string
Puts a string key-value pair into the map.
Definition: collections.F90:331
configuration_parser_mod::get_diagnostic_field_configuration
logical function, public get_diagnostic_field_configuration(io_configuration, field_name, field_namespace, diagnostic_config)
Retrieves the diagnostics field configuration corresponding to a specific field name and returns whet...
Definition: configurationparser.F90:1246
configuration_parser_mod::extend_field_array
subroutine extend_field_array()
Extends the fields array of the current data definition from the current size to the current size + d...
Definition: configurationparser.F90:1009
collections_mod::c_free
Frees up all the allocatable, heap, memory associated with a list, stack, queue or map.
Definition: collections.F90:577
io_server_client_mod::definition_description_type
Definition: ioclient.F90:27
optionsdatabase_mod::options_get_logical
logical function, public options_get_logical(options_database, key, index)
Retrieves a logical value from the database that matches the provided key.
Definition: optionsdatabase.F90:154
configuration_parser_mod::build_definition_description_type_from_configuration
type(definition_description_type) function, dimension(:), allocatable, public build_definition_description_type_from_configuration(io_configuration)
Builds up the data definition description type from the structured definitions in the IO configuratio...
Definition: configurationparser.F90:1090
configuration_parser_mod::data_handling_namespace
character(len=string_length) data_handling_namespace
Definition: configurationparser.F90:142
configuration_parser_mod::end_element_callback
subroutine end_element_callback(element_name)
XML element end (closing) call back.
Definition: configurationparser.F90:355
configuration_parser_mod::define_diagnostic
subroutine define_diagnostic(attribute_names, attribute_values)
Defines a new data handling rule.
Definition: configurationparser.F90:679
configuration_parser_mod::inside_generic_writing
logical inside_generic_writing
Definition: configurationparser.F90:137
configuration_parser_mod::get_data_value_by_field_name
Definition: configurationparser.F90:30
configuration_parser_mod::io_configuration_registered_monc_type
Configuration that representes the state of a registered MONC process.
Definition: configurationparser.F90:42
configuration_parser_mod::group_type
integer, parameter, public group_type
Definition: configurationparser.F90:28
configuration_parser_mod::get_io_xml
recursive character function, dimension(:), allocatable, public get_io_xml(filename, funit_num)
Reads in textual data from a file and returns this, used to read the IO server XML configuration file...
Definition: configurationparser.F90:170
logging_mod
Logging utility.
Definition: logging.F90:2
datadefn_mod
Contains common definitions for the data and datatypes used by MONC.
Definition: datadefn.F90:2
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
q_indices_mod
This manages the Q variables and specifically the mapping between names and the index that they are s...
Definition: q_indices.F90:2
collections_mod::list_type
List data structure which implements a doubly linked list. This list will preserve its order.
Definition: collections.F90:60
configuration_parser_mod::monc_size_stride
integer, parameter monc_size_stride
Definition: configurationparser.F90:26
configuration_parser_mod::get_number_field_dimensions
integer function, public get_number_field_dimensions(io_configuration, field_name, source, data_id)
Retrieves the number of field dimensions that a specific field has from a MONC process within a data ...
Definition: configurationparser.F90:1156
configuration_parser_mod::get_data_value_from_map_by_field_name
type(data_values_type) function, pointer get_data_value_from_map_by_field_name(collection, field_name)
Retrieves the data value (wrapper) by field name or null if no entry was found in the provided collec...
Definition: configurationparser.F90:1193
configuration_parser_mod::get_monc_location
integer function, public get_monc_location(io_configuration, source)
A helper function to get the location of a MONC's configuration in the IO data structure.
Definition: configurationparser.F90:1234
configuration_parser_mod::define_group
subroutine define_group(attribute_names, attribute_values)
Definition: configurationparser.F90:512
configuration_parser_mod::current_trigger_index
integer current_trigger_index
Definition: configurationparser.F90:139
configuration_parser_mod::cond_long
character(len=string_length), dimension(:), allocatable, public cond_long
Definition: configurationparser.F90:147
configuration_parser_mod::add_in_dimensions
subroutine add_in_dimensions(provided_options_database)
Definition: configurationparser.F90:262
configuration_parser_mod::current_building_diagnostic
integer current_building_diagnostic
Definition: configurationparser.F90:139
configuration_parser_mod::get_field_type_from_attribute
integer function get_field_type_from_attribute(field_type_str)
Definition: configurationparser.F90:862
configuration_parser_mod::get_field_index_from_name
integer function get_field_index_from_name(attribute_names, search_name)
Given the name of an attribute will return the index of this in the names collection or 0 if it is no...
Definition: configurationparser.F90:941
conversions_mod::conv_to_real
Converts data types to real.
Definition: conversions.F90:60
configuration_parser_mod::and_operator_type
integer, parameter and_operator_type
Definition: configurationparser.F90:23
collections_mod::c_get_integer
Gets a specific integer element out of the list, stack, queue or map with the corresponding key.
Definition: collections.F90:378
configuration_parser_mod::current_building_file_writer
integer current_building_file_writer
Definition: configurationparser.F90:139
io_server_client_mod::boolean_data_type
integer, parameter, public boolean_data_type
Definition: ioclient.F90:40
configuration_parser_mod::current_building_field
integer current_building_field
Definition: configurationparser.F90:139
configuration_parser_mod::subtract_operator_type
integer, parameter, public subtract_operator_type
Definition: configurationparser.F90:23
configuration_parser_mod::io_configuration_field_type
Configuration associated with the representation of a specific data field.
Definition: configurationparser.F90:51
configuration_parser_mod::build_field_description_type_from_configuration
type(field_description_type) function, dimension(:), allocatable, public build_field_description_type_from_configuration(io_configuration)
Builds up the field definition description type from the structured definitions in the IO configurati...
Definition: configurationparser.F90:1111
collections_mod::c_add_string
Adds a string to the end of the list.
Definition: collections.F90:222
configuration_parser_mod::inside_data_definition
logical inside_data_definition
Definition: configurationparser.F90:137
optionsdatabase_mod
Manages the options database. Contains administration functions and deduce runtime options from the c...
Definition: optionsdatabase.F90:7
configuration_parser_mod::get_prognostic_field_configuration
logical function, public get_prognostic_field_configuration(io_configuration, field_name, field_namespace, prognostic_config, prognostic_containing_data_defn)
Retrieves the prognostic field configuration corresponding to a specific field name and returns wheth...
Definition: configurationparser.F90:1270
configuration_parser_mod::replace_characters_in_string
subroutine replace_characters_in_string(original_string, new_string, to_replace)
Replaces specific characters in a string and returns a new string with this replaced by nothing (i....
Definition: configurationparser.F90:886
configuration_parser_mod
Parses the XML configuration file to produce the io configuration description which contains the data...
Definition: configurationparser.F90:3
configuration_parser_mod::retrieve_string_value
character(len=string_length) function retrieve_string_value(original_string, field_value_type)
Definition: configurationparser.F90:907
configuration_parser_mod::extend_data_definition_array
subroutine extend_data_definition_array()
Extends the data definitions array from the current size to the current size + data size stride.
Definition: configurationparser.F90:1021
collections_mod::hashset_type
Hashset structure which will store unique strings. The hashing aspect means that lookup is very fast ...
Definition: collections.F90:102
optionsdatabase_mod::options_get_real
real(kind=default_precision) function, public options_get_real(options_database, key, index)
Retrieves a real value from the database that matches the provided key.
Definition: optionsdatabase.F90:91
configuration_parser_mod::mod_operator_type
integer, parameter, public mod_operator_type
Definition: configurationparser.F90:23
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
configuration_parser_mod::retrieve_data_definition
integer function, public retrieve_data_definition(io_configuration, key)
Retrieves a specific data definition from the configuration which matches a key.
Definition: configurationparser.F90:1049
configuration_parser_mod::io_configuration_inter_communication_description
Definition: configurationparser.F90:66
configuration_parser_mod::get_data_value_from_map_entry
type(data_values_type) function, pointer, public get_data_value_from_map_entry(map_entry)
Retrieves the data value (wrapper) by field name or null if no entry was found in the provided map en...
Definition: configurationparser.F90:1214