MONC
ioclient.F90
Go to the documentation of this file.
1 
8  use mpi, only : mpi_character, mpi_int, mpi_logical, mpi_real, mpi_double_precision, mpi_address_kind
9  implicit none
10 
11 #ifndef TEST_MODE
12  private
13 #endif
14 
15 
17  character(len=STRING_LENGTH) :: field_name
18  integer :: dimensions, dim_sizes(4)
20 
22  character(len=STRING_LENGTH) :: definition_name, field_name
23  integer :: field_type, data_type
24  logical :: optional
25  end type field_description_type
26 
28  character(len=STRING_LENGTH) :: definition_name
29  logical :: send_on_terminate
30  integer :: number_fields, frequency
32 
33  ! Constants used in sending and receiving IO data
36 
37 
38  integer, parameter :: scalar_field_type = 1, array_field_type=2, map_field_type=3
39 
42 
43  character(len=STRING_LENGTH), parameter :: local_sizes_key="local_sizes", local_start_points_key="local_start_points", &
44  local_end_points_key="local_end_points", number_q_indicies_key="num_q_indicies"
45 
53 
54 contains
55 
59  function populate_mpi_type_extents()
60  integer :: populate_mpi_type_extents(5)
61 
62  integer :: ierr
63  integer(kind=MPI_ADDRESS_KIND) :: large_number_extents(5)
64 
65  call mpi_type_extent(mpi_int, large_number_extents(integer_data_type), ierr)
66  call mpi_type_extent(mpi_logical, large_number_extents(boolean_data_type), ierr)
67  call mpi_type_extent(mpi_character, large_number_extents(string_data_type), ierr)
68  call mpi_type_extent(mpi_real, large_number_extents(float_data_type), ierr)
69  call mpi_type_extent(mpi_double_precision, large_number_extents(double_data_type), ierr)
70 
71  populate_mpi_type_extents=int(large_number_extents)
72  end function populate_mpi_type_extents
73 
75  integer function build_mpi_type_definition_description()
76  integer :: new_type, ierr, block_counts(4), old_types(4), offsets(4)
77  integer(MPI_ADDRESS_KIND) :: num_addr, base_addr
78 
79  type(definition_description_type) :: basic_type
80 
81  call mpi_get_address(basic_type, base_addr, ierr)
82  old_types(1) = mpi_character
83  block_counts(1) = string_length
84  offsets(1)=0
85 
86  call mpi_get_address(basic_type%send_on_terminate, num_addr, ierr)
87  old_types(2) = mpi_logical
88  block_counts(2) = 1
89  offsets(2)=int(num_addr-base_addr)
90 
91  call mpi_get_address(basic_type%number_fields, num_addr, ierr)
92  old_types(3) = mpi_int
93  block_counts(3) = 1
94  offsets(3)=int(num_addr-base_addr)
95 
96  call mpi_get_address(basic_type%frequency, num_addr, ierr)
97  old_types(4) = mpi_int
98  block_counts(4) = 1
99  offsets(4)=int(num_addr-base_addr)
100 
101  call mpi_type_struct(4, block_counts, offsets, old_types, new_type, ierr)
102  call mpi_type_commit(new_type, ierr)
105 
107  integer function build_mpi_type_field_description()
108  integer :: new_type, ierr, old_types(5), block_counts(5), offsets(5)
109  integer(MPI_ADDRESS_KIND) :: num_addr, base_addr
110 
111  type(field_description_type) :: basic_type
112 
113  call mpi_get_address(basic_type, base_addr, ierr)
114  old_types(1) = mpi_character
115  block_counts(1) = string_length
116  offsets(1)=0
117 
118  call mpi_get_address(basic_type%field_name, num_addr, ierr)
119  old_types(2) = mpi_character
120  block_counts(2) = string_length
121  offsets(2)=int(num_addr-base_addr)
122 
123  call mpi_get_address(basic_type%field_type, num_addr, ierr)
124  old_types(3) = mpi_int
125  block_counts(3) = 1
126  offsets(3)=int(num_addr-base_addr)
127 
128  call mpi_get_address(basic_type%data_type, num_addr, ierr)
129  old_types(4) = mpi_int
130  block_counts(4) = 1
131  offsets(4)=int(num_addr-base_addr)
132 
133  call mpi_get_address(basic_type%optional, num_addr, ierr)
134  old_types(5) = mpi_logical
135  block_counts(5) = 1
136  offsets(5)=int(num_addr-base_addr)
137 
138  call mpi_type_struct(5, block_counts, offsets, old_types, new_type, ierr)
139  call mpi_type_commit(new_type, ierr)
142 
146  integer function build_mpi_type_data_sizing_description()
147  integer :: new_type, ierr, block_counts(3), old_types(3), offsets(3)
148  integer(kind=MPI_ADDRESS_KIND) :: num_addr, base_addr
149 
150  type(data_sizing_description_type) :: basic_type
151 
152  call mpi_get_address(basic_type, base_addr, ierr)
153  old_types(1) = mpi_character
154  block_counts(1) = string_length
155  offsets(1)=0
156 
157  call mpi_get_address(basic_type%dimensions, num_addr, ierr)
158  old_types(2) = mpi_int
159  block_counts(2) = 1
160  offsets(2)=int(num_addr-base_addr)
161 
162  call mpi_get_address(basic_type%dim_sizes, num_addr, ierr)
163  old_types(3) = mpi_int
164  block_counts(3) = 4
165  offsets(3)=int(num_addr-base_addr)
166 
167  call mpi_type_struct(3, block_counts, offsets, old_types, new_type, ierr)
168  call mpi_type_commit(new_type, ierr)
171 
184  subroutine append_mpi_datatype(field_start, field_end, field_array_sizes, data_type, &
185  type_extents, prev_data_type, type_index, old_types, offsets, block_counts)
186  integer, intent(in) :: field_start, field_end, field_array_sizes, data_type, type_index, prev_data_type, type_extents(5)
187  integer, intent(inout) :: old_types(20), offsets(20), block_counts(20)
188 
189  block_counts(type_index)=(field_end-field_start) + 1 + field_array_sizes
190  old_types(type_index)=get_mpi_datatype_from_internal_representation(data_type)
191  if (type_index == 1) then
192  offsets(1)=0
193  else
194  offsets(type_index)=offsets(type_index-1)+type_extents(prev_data_type) * block_counts(type_index-1)
195  end if
196  end subroutine append_mpi_datatype
197 
202  integer function get_mpi_datatype_from_internal_representation(type_code)
203  integer, intent(in) :: type_code
204 
205  if (type_code==integer_data_type) then
207  else if (type_code==boolean_data_type) then
209  else if (type_code==string_data_type) then
211  else if (type_code==float_data_type) then
213  else if (type_code==double_data_type) then
215  end if
217 
223  integer function pack_map_field(buffer, start_offset, map_to_pack)
224  character, dimension(:), intent(inout) :: buffer
225  integer, intent(in) :: start_offset
226  type(hashmap_type) :: map_to_pack
227 
228  integer :: i, target_end, current_offset
229  character(len=STRING_LENGTH) :: temp_string
230  character(len=STRING_LENGTH), pointer :: sized_raw_character
231  class(*), pointer :: raw_data, raw_to_string
232  type(iterator_type) :: map_iterator
233  type(mapentry_type) :: specific_mapentry
234 
235  current_offset=start_offset
236  map_iterator=c_get_iterator(map_to_pack)
237  do while (c_has_next(map_iterator))
238  specific_mapentry=c_next_mapentry(map_iterator)
239  temp_string=specific_mapentry%key
240  target_end=current_offset+string_length-1
241  buffer(current_offset:target_end)=transfer(temp_string, buffer(current_offset:target_end))
242  current_offset=target_end+1
243 
244  raw_data=>c_get_generic(specific_mapentry)
245  raw_to_string=>raw_data
246  select type (raw_data)
247  type is(integer)
248  temp_string=conv_to_string(raw_data)
249  type is(real(4))
250  temp_string=conv_to_string(raw_data)
251  type is (real(8))
252  temp_string=conv_to_string(raw_data)
253  type is(logical)
254  temp_string=conv_to_string(raw_data)
255  type is(character(len=*))
256  sized_raw_character=>conv_to_string(raw_to_string, .false., string_length)
257  temp_string=sized_raw_character
258  end select
259  target_end=current_offset+string_length-1
260  buffer(current_offset:target_end)=transfer(temp_string, buffer(current_offset:target_end))
261  current_offset=target_end+1
262  end do
263  pack_map_field=current_offset
264  end function pack_map_field
265 
272  integer function pack_array_field(buffer, start_offset, int_array, real_array_1d, real_array_2d, real_array_3d, real_array_4d)
273  character, dimension(:), intent(inout) :: buffer
274  integer, intent(in) :: start_offset
275  integer, dimension(:), intent(in), optional :: int_array
276  real(kind=DEFAULT_PRECISION), dimension(:), intent(in), optional :: real_array_1d
277  real(kind=DEFAULT_PRECISION), dimension(:,:), intent(in), optional :: real_array_2d
278  real(kind=DEFAULT_PRECISION), dimension(:,:,:), intent(in), optional :: real_array_3d
279  real(kind=DEFAULT_PRECISION), dimension(:,:,:,:), intent(in), optional :: real_array_4d
280 
281  integer :: target_end
282 
283  if (present(int_array)) then
284  target_end=start_offset+kind(int_array)*size(int_array)-1
285  buffer(start_offset:target_end) = transfer(int_array, buffer(start_offset:target_end))
286  else if (present(real_array_1d)) then
287  target_end=start_offset+kind(real_array_1d)*size(real_array_1d)-1
288  buffer(start_offset:target_end) = transfer(real_array_1d, buffer(start_offset:target_end))
289  else if (present(real_array_2d)) then
290  target_end=start_offset+kind(real_array_2d)*size(real_array_2d)-1
291  buffer(start_offset:target_end) = transfer(real_array_2d, buffer(start_offset:target_end))
292  else if (present(real_array_3d)) then
293  target_end=start_offset+kind(real_array_3d)*size(real_array_3d)-1
294  buffer(start_offset:target_end) = transfer(real_array_3d, buffer(start_offset:target_end))
295  else if (present(real_array_4d)) then
296  target_end=start_offset+kind(real_array_4d)*size(real_array_4d)-1
297  buffer(start_offset:target_end) = transfer(real_array_4d, buffer(start_offset:target_end))
298  end if
299  pack_array_field=target_end+1
300  end function pack_array_field
301 
310  integer function pack_scalar_field(buffer, start_offset, int_value, real_value, single_real_value, double_real_value, &
311  string_value, logical_value)
312  character, dimension(:), intent(inout) :: buffer
313  integer, intent(in) :: start_offset
314  integer, intent(in), optional :: int_value
315  real(kind=DEFAULT_PRECISION), intent(in), optional :: real_value
316  real(kind=SINGLE_PRECISION), intent(in), optional :: single_real_value
317  real(kind=DOUBLE_PRECISION), intent(in), optional :: double_real_value
318  character(len=*), intent(in), optional :: string_value
319  logical, intent(in), optional :: logical_value
320 
321  integer :: target_end
322  character(len=STRING_LENGTH) :: string_to_insert
323 
324  if (present(int_value)) then
325  target_end=start_offset+kind(int_value)-1
326  buffer(start_offset:target_end) = transfer(int_value, buffer(start_offset:target_end))
327  else if (present(real_value)) then
328  target_end=start_offset+kind(real_value)-1
329  buffer(start_offset:target_end) = transfer(real_value, buffer(start_offset:target_end))
330  else if (present(single_real_value)) then
331  target_end=start_offset+kind(single_real_value)-1
332  buffer(start_offset:target_end) = transfer(single_real_value, buffer(start_offset:target_end))
333  else if (present(double_real_value)) then
334  target_end=start_offset+kind(double_real_value)-1
335  buffer(start_offset:target_end) = transfer(double_real_value, buffer(start_offset:target_end))
336  else if (present(string_value)) then
337  target_end=start_offset+string_length-1
338  string_to_insert=string_value
339  buffer(start_offset:target_end) = transfer(string_to_insert, buffer(start_offset:target_end))
340  else if (present(logical_value)) then
341  target_end=start_offset+kind(logical_value)-1
342  buffer(start_offset:target_end) = transfer(logical_value, buffer(start_offset:target_end))
343  else
344  target_end=start_offset-1
345  end if
346  pack_scalar_field=target_end+1
347  end function pack_scalar_field
348 
354  logical function get_data_description_from_name(descriptions, name, field_description)
355  type(data_sizing_description_type), dimension(:), intent(in) :: descriptions
356  type(data_sizing_description_type), intent(out), optional :: field_description
357  character(len=*), intent(in) :: name
358 
359  integer :: i
360  do i=1,size(descriptions)
361  if (descriptions(i)%field_name == name) then
362  if (present(field_description)) field_description=descriptions(i)
364  return
365  end if
366  end do
368  end function get_data_description_from_name
369 end module io_server_client_mod
Gets a specific generic element out of the list, stack, queue or map with the corresponding key...
integer, parameter, public float_data_type
Definition: ioclient.F90:40
integer function, public get_mpi_datatype_from_internal_representation(type_code)
Gets the MPI datatype from out internal representation of the field data type (as in the configuratio...
Definition: ioclient.F90:203
integer, parameter, public array_field_type
Definition: ioclient.F90:38
integer, parameter, public boolean_data_type
Definition: ioclient.F90:40
character(len=string_length), parameter, public local_end_points_key
Definition: ioclient.F90:43
integer, parameter, public register_command
Definition: ioclient.F90:34
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data.
Definition: datadefn.F90:17
integer, parameter, public command_tag
Definition: ioclient.F90:34
Contains common definitions for the data and datatypes used by MONC.
Definition: datadefn.F90:2
A hashmap structure, the same as a map but uses hashing for greatly improved performance when storing...
Definition: collections.F90:94
Conversion between common inbuilt FORTRAN data types.
Definition: conversions.F90:5
integer, parameter, public double_data_type
Definition: ioclient.F90:40
character(len=string_length), parameter, public local_sizes_key
Definition: ioclient.F90:43
Converts data types to strings.
Definition: conversions.F90:36
integer, parameter, public single_precision
Single precision (32 bit) kind.
Definition: datadefn.F90:13
integer, parameter, public inter_io_communication
Field type identifiers.
Definition: ioclient.F90:34
integer, parameter, public double_precision
Double precision (64 bit) kind.
Definition: datadefn.F90:14
integer, parameter, public string_data_type
Definition: ioclient.F90:40
This defines some constants and procedures that are useful to the IO server and clients that call it...
Definition: ioclient.F90:3
integer, parameter, public integer_data_type
Definition: ioclient.F90:40
integer function, public pack_map_field(buffer, start_offset, map_to_pack)
Packs a map into the send buffer.
Definition: ioclient.F90:224
Collection data structures.
Definition: collections.F90:7
integer, parameter, public data_command_start
Definition: ioclient.F90:34
integer, parameter, public string_length
Default length of strings.
Definition: datadefn.F90:10
integer function, dimension(5), public populate_mpi_type_extents()
Provides the type extents of the types that we are using in construction of the MPI data type...
Definition: ioclient.F90:60
logical function, public get_data_description_from_name(descriptions, name, field_description)
Look up the data description that corresponds to a specific field keyed by its name.
Definition: ioclient.F90:355
integer function, public build_mpi_type_definition_description()
Builds the MPI data type for sending data descriptions to registree MONCs.
Definition: ioclient.F90:76
subroutine, public append_mpi_datatype(field_start, field_end, field_array_sizes, data_type, type_extents, prev_data_type, type_index, old_types, offsets, block_counts)
Appends the MPI datatype details to the block counts, old types and offsets arrays. This will lump together multiple concurrent fields with the same type.
Definition: ioclient.F90:186
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
character(len=string_length), parameter, public number_q_indicies_key
Definition: ioclient.F90:43
integer, parameter, public scalar_field_type
Definition: ioclient.F90:38
integer function, public build_mpi_type_data_sizing_description()
Builds the MPI type used for sending to the IO server a description of the data, namely the size of t...
Definition: ioclient.F90:147
integer function, public build_mpi_type_field_description()
Builds the MPI data type for sending field descriptions to registree MONCs.
Definition: ioclient.F90:108
integer, parameter, public map_field_type
Field data type identifiers.
Definition: ioclient.F90:38
integer, parameter, public data_tag
Definition: ioclient.F90:34
integer, parameter, public deregister_command
Definition: ioclient.F90:34
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
character(len=string_length), parameter, public local_start_points_key
Definition: ioclient.F90:43