LCOV - code coverage report
Current view: top level - src/swarm - swarm_message.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 75.7 % 382 289
Test Date: 2025-07-25 12:55:17 Functions: 66.7 % 39 26

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Swarm-message, a convenient data-container for with build-in serialization.
      10              : !> \author Ole Schuett
      11              : ! **************************************************************************************************
      12              : MODULE swarm_message
      13              : 
      14              :    USE cp_parser_methods, ONLY: parser_get_next_line
      15              :    USE cp_parser_types, ONLY: cp_parser_type
      16              :    USE kinds, ONLY: default_string_length, &
      17              :                     int_4, &
      18              :                     int_8, &
      19              :                     real_4, &
      20              :                     real_8
      21              :    USE message_passing, ONLY: mp_comm_type
      22              : #include "../base/base_uses.f90"
      23              : 
      24              :    IMPLICIT NONE
      25              :    PRIVATE
      26              : 
      27              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'swarm_message'
      28              : 
      29              :    TYPE swarm_message_type
      30              :       PRIVATE
      31              :       TYPE(message_entry_type), POINTER :: root => Null()
      32              :    END TYPE swarm_message_type
      33              : 
      34              :    INTEGER, PARAMETER  :: key_length = 20
      35              : 
      36              :    TYPE message_entry_type
      37              :       CHARACTER(LEN=key_length)                      :: key = ""
      38              :       TYPE(message_entry_type), POINTER              :: next => Null()
      39              :       CHARACTER(LEN=default_string_length), POINTER  :: value_str => Null()
      40              :       INTEGER(KIND=int_4), POINTER                   :: value_i4 => Null()
      41              :       INTEGER(KIND=int_8), POINTER                   :: value_i8 => Null()
      42              :       REAL(KIND=real_4), POINTER                     :: value_r4 => Null()
      43              :       REAL(KIND=real_8), POINTER                     :: value_r8 => Null()
      44              :       INTEGER(KIND=int_4), DIMENSION(:), POINTER     :: value_1d_i4 => Null()
      45              :       INTEGER(KIND=int_8), DIMENSION(:), POINTER     :: value_1d_i8 => Null()
      46              :       REAL(KIND=real_4), DIMENSION(:), POINTER       :: value_1d_r4 => Null()
      47              :       REAL(KIND=real_8), DIMENSION(:), POINTER       :: value_1d_r8 => Null()
      48              :    END TYPE message_entry_type
      49              : 
      50              : ! **************************************************************************************************
      51              : !> \brief Adds an entry from a swarm-message.
      52              : !> \author Ole Schuett
      53              : ! **************************************************************************************************
      54              :    INTERFACE swarm_message_add
      55              :       MODULE PROCEDURE swarm_message_add_str
      56              :       MODULE PROCEDURE swarm_message_add_i4, swarm_message_add_i8
      57              :       MODULE PROCEDURE swarm_message_add_r4, swarm_message_add_r8
      58              :       MODULE PROCEDURE swarm_message_add_1d_i4, swarm_message_add_1d_i8
      59              :       MODULE PROCEDURE swarm_message_add_1d_r4, swarm_message_add_1d_r8
      60              :    END INTERFACE swarm_message_add
      61              : 
      62              : ! **************************************************************************************************
      63              : !> \brief Returns an entry from a swarm-message.
      64              : !> \author Ole Schuett
      65              : ! **************************************************************************************************
      66              :    INTERFACE swarm_message_get
      67              :       MODULE PROCEDURE swarm_message_get_str
      68              :       MODULE PROCEDURE swarm_message_get_i4, swarm_message_get_i8
      69              :       MODULE PROCEDURE swarm_message_get_r4, swarm_message_get_r8
      70              :       MODULE PROCEDURE swarm_message_get_1d_i4, swarm_message_get_1d_i8
      71              :       MODULE PROCEDURE swarm_message_get_1d_r4, swarm_message_get_1d_r8
      72              :    END INTERFACE swarm_message_get
      73              : 
      74              :    PUBLIC :: swarm_message_type, swarm_message_add, swarm_message_get
      75              :    PUBLIC :: swarm_message_mpi_send, swarm_message_mpi_recv, swarm_message_mpi_bcast
      76              :    PUBLIC :: swarm_message_file_write, swarm_message_file_read
      77              :    PUBLIC :: swarm_message_haskey, swarm_message_equal
      78              :    PUBLIC :: swarm_message_free
      79              : 
      80              : CONTAINS
      81              : 
      82              : ! **************************************************************************************************
      83              : !> \brief Returns the number of entries contained in a swarm-message.
      84              : !> \param msg ...
      85              : !> \return ...
      86              : !> \author Ole Schuett
      87              : ! **************************************************************************************************
      88          282 :    FUNCTION swarm_message_length(msg) RESULT(l)
      89              :       TYPE(swarm_message_type), INTENT(IN)               :: msg
      90              :       INTEGER                                            :: l
      91              : 
      92              :       TYPE(message_entry_type), POINTER                  :: curr_entry
      93              : 
      94          282 :       l = 0
      95          282 :       curr_entry => msg%root
      96         1078 :       DO WHILE (ASSOCIATED(curr_entry))
      97          796 :          l = l + 1
      98          796 :          curr_entry => curr_entry%next
      99              :       END DO
     100          282 :    END FUNCTION swarm_message_length
     101              : 
     102              : ! **************************************************************************************************
     103              : !> \brief Checks if a swarm-message contains an entry with the given key.
     104              : !> \param msg ...
     105              : !> \param key ...
     106              : !> \return ...
     107              : !> \author Ole Schuett
     108              : ! **************************************************************************************************
     109          371 :    FUNCTION swarm_message_haskey(msg, key) RESULT(res)
     110              :       TYPE(swarm_message_type), INTENT(IN)               :: msg
     111              :       CHARACTER(LEN=*), INTENT(IN)                       :: key
     112              :       LOGICAL                                            :: res
     113              : 
     114              :       TYPE(message_entry_type), POINTER                  :: curr_entry
     115              : 
     116          371 :       res = .FALSE.
     117          371 :       curr_entry => msg%root
     118         1348 :       DO WHILE (ASSOCIATED(curr_entry))
     119          977 :          IF (TRIM(curr_entry%key) == TRIM(key)) THEN
     120              :             res = .TRUE.
     121              :             EXIT
     122              :          END IF
     123          977 :          curr_entry => curr_entry%next
     124              :       END DO
     125          371 :    END FUNCTION swarm_message_haskey
     126              : 
     127              : ! **************************************************************************************************
     128              : !> \brief Deallocates all entries contained in a swarm-message.
     129              : !> \param msg ...
     130              : !> \author Ole Schuett
     131              : ! **************************************************************************************************
     132          134 :    SUBROUTINE swarm_message_free(msg)
     133              :       TYPE(swarm_message_type), INTENT(INOUT)            :: msg
     134              : 
     135              :       TYPE(message_entry_type), POINTER                  :: ENTRY, old_entry
     136              : 
     137          134 :       ENTRY => msg%root
     138          838 :       DO WHILE (ASSOCIATED(ENTRY))
     139          704 :          IF (ASSOCIATED(entry%value_str)) DEALLOCATE (entry%value_str)
     140          704 :          IF (ASSOCIATED(entry%value_i4)) DEALLOCATE (entry%value_i4)
     141          704 :          IF (ASSOCIATED(entry%value_i8)) DEALLOCATE (entry%value_i8)
     142          704 :          IF (ASSOCIATED(entry%value_r4)) DEALLOCATE (entry%value_r4)
     143          704 :          IF (ASSOCIATED(entry%value_r8)) DEALLOCATE (entry%value_r8)
     144          704 :          IF (ASSOCIATED(entry%value_1d_i4)) DEALLOCATE (entry%value_1d_i4)
     145          704 :          IF (ASSOCIATED(entry%value_1d_i8)) DEALLOCATE (entry%value_1d_i8)
     146          704 :          IF (ASSOCIATED(entry%value_1d_r4)) DEALLOCATE (entry%value_1d_r4)
     147          704 :          IF (ASSOCIATED(entry%value_1d_r8)) DEALLOCATE (entry%value_1d_r8)
     148          704 :          old_entry => ENTRY
     149          704 :          ENTRY => entry%next
     150          838 :          DEALLOCATE (old_entry)
     151              :       END DO
     152              : 
     153          134 :       NULLIFY (msg%root)
     154              : 
     155          134 :       CPASSERT(swarm_message_length(msg) == 0)
     156          134 :    END SUBROUTINE swarm_message_free
     157              : 
     158              : ! **************************************************************************************************
     159              : !> \brief Checks if two swarm-messages are equal
     160              : !> \param msg1 ...
     161              : !> \param msg2 ...
     162              : !> \return ...
     163              : !> \author Ole Schuett
     164              : ! **************************************************************************************************
     165            4 :    FUNCTION swarm_message_equal(msg1, msg2) RESULT(res)
     166              :       TYPE(swarm_message_type), INTENT(IN)               :: msg1, msg2
     167              :       LOGICAL                                            :: res
     168              : 
     169              :       res = swarm_message_equal_oneway(msg1, msg2) .AND. &
     170            4 :             swarm_message_equal_oneway(msg2, msg1)
     171              : 
     172            4 :    END FUNCTION swarm_message_equal
     173              : 
     174              : ! **************************************************************************************************
     175              : !> \brief Sends a swarm message via MPI.
     176              : !> \param msg ...
     177              : !> \param group ...
     178              : !> \param dest ...
     179              : !> \param tag ...
     180              : !> \author Ole Schuett
     181              : ! **************************************************************************************************
     182           56 :    SUBROUTINE swarm_message_mpi_send(msg, group, dest, tag)
     183              :       TYPE(swarm_message_type), INTENT(IN)               :: msg
     184              :       CLASS(mp_comm_type), INTENT(IN) :: group
     185              :       INTEGER, INTENT(IN)                                :: dest, tag
     186              : 
     187              :       TYPE(message_entry_type), POINTER                  :: curr_entry
     188              : 
     189           56 :       CALL group%send(swarm_message_length(msg), dest, tag)
     190           56 :       curr_entry => msg%root
     191          366 :       DO WHILE (ASSOCIATED(curr_entry))
     192          310 :          CALL swarm_message_entry_mpi_send(curr_entry, group, dest, tag)
     193          310 :          curr_entry => curr_entry%next
     194              :       END DO
     195           56 :    END SUBROUTINE swarm_message_mpi_send
     196              : 
     197              : ! **************************************************************************************************
     198              : !> \brief Receives a swarm message via MPI.
     199              : !> \param msg ...
     200              : !> \param group ...
     201              : !> \param src ...
     202              : !> \param tag ...
     203              : !> \author Ole Schuett
     204              : ! **************************************************************************************************
     205           56 :    SUBROUTINE swarm_message_mpi_recv(msg, group, src, tag)
     206              :       TYPE(swarm_message_type), INTENT(INOUT)            :: msg
     207              :       CLASS(mp_comm_type), INTENT(IN)                                :: group
     208              :       INTEGER, INTENT(INOUT)                             :: src, tag
     209              : 
     210              :       INTEGER                                            :: i, length
     211              :       TYPE(message_entry_type), POINTER                  :: new_entry
     212              : 
     213           56 :       IF (ASSOCIATED(msg%root)) CPABORT("message not empty")
     214           56 :       CALL group%recv(length, src, tag)
     215          366 :       DO i = 1, length
     216          310 :          ALLOCATE (new_entry)
     217          310 :          CALL swarm_message_entry_mpi_recv(new_entry, group, src, tag)
     218          310 :          new_entry%next => msg%root
     219          366 :          msg%root => new_entry
     220              :       END DO
     221              : 
     222           56 :    END SUBROUTINE swarm_message_mpi_recv
     223              : 
     224              : ! **************************************************************************************************
     225              : !> \brief Broadcasts a swarm message via MPI.
     226              : !> \param msg ...
     227              : !> \param src ...
     228              : !> \param group ...
     229              : !> \author Ole Schuett
     230              : ! **************************************************************************************************
     231           28 :    SUBROUTINE swarm_message_mpi_bcast(msg, src, group)
     232              :       TYPE(swarm_message_type), INTENT(INOUT)            :: msg
     233              :       INTEGER, INTENT(IN)                                :: src
     234              :       CLASS(mp_comm_type), INTENT(IN) :: group
     235              : 
     236              :       INTEGER                                            :: i, length
     237              :       TYPE(message_entry_type), POINTER                  :: curr_entry
     238              : 
     239              :       ASSOCIATE (mepos => group%mepos)
     240              : 
     241            0 :          IF (mepos /= src .AND. ASSOCIATED(msg%root)) CPABORT("message not empty")
     242           28 :          length = swarm_message_length(msg)
     243           28 :          CALL group%bcast(length, src)
     244              : 
     245           28 :          IF (mepos == src) curr_entry => msg%root
     246              : 
     247          185 :          DO i = 1, length
     248          129 :             IF (mepos /= src) ALLOCATE (curr_entry)
     249              : 
     250          129 :             CALL swarm_message_entry_mpi_bcast(curr_entry, src, group, mepos)
     251              : 
     252          157 :             IF (mepos == src) THEN
     253          129 :                curr_entry => curr_entry%next
     254              :             ELSE
     255            0 :                curr_entry%next => msg%root
     256            0 :                msg%root => curr_entry
     257              :             END IF
     258              :          END DO
     259              :       END ASSOCIATE
     260              : 
     261           28 :    END SUBROUTINE swarm_message_mpi_bcast
     262              : 
     263              : ! **************************************************************************************************
     264              : !> \brief Write a swarm-message to a given file / unit.
     265              : !> \param msg ...
     266              : !> \param unit ...
     267              : !> \author Ole Schuett
     268              : ! **************************************************************************************************
     269          128 :    SUBROUTINE swarm_message_file_write(msg, unit)
     270              :       TYPE(swarm_message_type), INTENT(IN)               :: msg
     271              :       INTEGER, INTENT(IN)                                :: unit
     272              : 
     273              :       INTEGER                                            :: handle
     274              :       TYPE(message_entry_type), POINTER                  :: curr_entry
     275              : 
     276           64 :       IF (unit <= 0) RETURN
     277              : 
     278           64 :       CALL timeset("swarm_message_file_write", handle)
     279           64 :       WRITE (unit, "(A)") "BEGIN SWARM_MESSAGE"
     280           64 :       WRITE (unit, "(A,I10)") "msg_length: ", swarm_message_length(msg)
     281              : 
     282           64 :       curr_entry => msg%root
     283          421 :       DO WHILE (ASSOCIATED(curr_entry))
     284          357 :          CALL swarm_message_entry_file_write(curr_entry, unit)
     285          357 :          curr_entry => curr_entry%next
     286              :       END DO
     287              : 
     288           64 :       WRITE (unit, "(A)") "END SWARM_MESSAGE"
     289           64 :       WRITE (unit, "()")
     290           64 :       CALL timestop(handle)
     291              :    END SUBROUTINE swarm_message_file_write
     292              : 
     293              : ! **************************************************************************************************
     294              : !> \brief Reads a swarm-message from a given file / unit.
     295              : !> \param msg ...
     296              : !> \param parser ...
     297              : !> \param at_end ...
     298              : !> \author Ole Schuett
     299              : ! **************************************************************************************************
     300           22 :    SUBROUTINE swarm_message_file_read(msg, parser, at_end)
     301              :       TYPE(swarm_message_type), INTENT(OUT)              :: msg
     302              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     303              :       LOGICAL, INTENT(INOUT)                             :: at_end
     304              : 
     305              :       INTEGER                                            :: handle
     306              : 
     307           11 :       CALL timeset("swarm_message_file_read", handle)
     308           11 :       CALL swarm_message_file_read_low(msg, parser, at_end)
     309           11 :       CALL timestop(handle)
     310           11 :    END SUBROUTINE swarm_message_file_read
     311              : 
     312              : ! **************************************************************************************************
     313              : !> \brief Helper routine, does the actual work of swarm_message_file_read().
     314              : !> \param msg ...
     315              : !> \param parser ...
     316              : !> \param at_end ...
     317              : !> \author Ole Schuett
     318              : ! **************************************************************************************************
     319           11 :    SUBROUTINE swarm_message_file_read_low(msg, parser, at_end)
     320              :       TYPE(swarm_message_type), INTENT(OUT)              :: msg
     321              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     322              :       LOGICAL, INTENT(INOUT)                             :: at_end
     323              : 
     324              :       CHARACTER(LEN=20)                                  :: label
     325              :       INTEGER                                            :: i, length
     326              :       TYPE(message_entry_type), POINTER                  :: new_entry
     327              : 
     328           11 :       CALL parser_get_next_line(parser, 1, at_end)
     329           11 :       at_end = at_end .OR. LEN_TRIM(parser%input_line(1:10)) == 0
     330           11 :       IF (at_end) RETURN
     331           10 :       CPASSERT(TRIM(parser%input_line(1:20)) == "BEGIN SWARM_MESSAGE")
     332              : 
     333           10 :       CALL parser_get_next_line(parser, 1, at_end)
     334           10 :       at_end = at_end .OR. LEN_TRIM(parser%input_line(1:10)) == 0
     335           10 :       IF (at_end) RETURN
     336           10 :       READ (parser%input_line(1:40), *) label, length
     337           10 :       CPASSERT(TRIM(label) == "msg_length:")
     338              : 
     339           61 :       DO i = 1, length
     340           51 :          ALLOCATE (new_entry)
     341           51 :          CALL swarm_message_entry_file_read(new_entry, parser, at_end)
     342           51 :          new_entry%next => msg%root
     343           61 :          msg%root => new_entry
     344              :       END DO
     345              : 
     346           10 :       CALL parser_get_next_line(parser, 1, at_end)
     347           10 :       at_end = at_end .OR. LEN_TRIM(parser%input_line(1:10)) == 0
     348           10 :       IF (at_end) RETURN
     349           10 :       CPASSERT(TRIM(parser%input_line(1:20)) == "END SWARM_MESSAGE")
     350              : 
     351              :    END SUBROUTINE swarm_message_file_read_low
     352              : 
     353              : ! **************************************************************************************************
     354              : !> \brief Helper routine for swarm_message_equal
     355              : !> \param msg1 ...
     356              : !> \param msg2 ...
     357              : !> \return ...
     358              : !> \author Ole Schuett
     359              : ! **************************************************************************************************
     360            8 :    FUNCTION swarm_message_equal_oneway(msg1, msg2) RESULT(res)
     361              :       TYPE(swarm_message_type), INTENT(IN)               :: msg1, msg2
     362              :       LOGICAL                                            :: res
     363              : 
     364              :       LOGICAL                                            :: found
     365              :       TYPE(message_entry_type), POINTER                  :: entry1, entry2
     366              : 
     367            8 :       res = .FALSE.
     368              : 
     369              :       !loop over entries of msg1
     370            8 :       entry1 => msg1%root
     371           46 :       DO WHILE (ASSOCIATED(entry1))
     372              : 
     373              :          ! finding matching entry in msg2
     374           38 :          entry2 => msg2%root
     375           38 :          found = .FALSE.
     376          110 :          DO WHILE (ASSOCIATED(entry2))
     377          110 :             IF (TRIM(entry2%key) == TRIM(entry1%key)) THEN
     378              :                found = .TRUE.
     379              :                EXIT
     380              :             END IF
     381           72 :             entry2 => entry2%next
     382              :          END DO
     383           38 :          IF (.NOT. found) RETURN
     384              : 
     385              :          !compare the two entries
     386           38 :          IF (ASSOCIATED(entry1%value_str)) THEN
     387            8 :             IF (.NOT. ASSOCIATED(entry2%value_str)) RETURN
     388            8 :             IF (TRIM(entry1%value_str) /= TRIM(entry2%value_str)) RETURN
     389              : 
     390           30 :          ELSE IF (ASSOCIATED(entry1%value_i4)) THEN
     391           16 :             IF (.NOT. ASSOCIATED(entry2%value_i4)) RETURN
     392           16 :             IF (entry1%value_i4 /= entry2%value_i4) RETURN
     393              : 
     394           14 :          ELSE IF (ASSOCIATED(entry1%value_i8)) THEN
     395            0 :             IF (.NOT. ASSOCIATED(entry2%value_i8)) RETURN
     396            0 :             IF (entry1%value_i8 /= entry2%value_i8) RETURN
     397              : 
     398           14 :          ELSE IF (ASSOCIATED(entry1%value_r4)) THEN
     399            0 :             IF (.NOT. ASSOCIATED(entry2%value_r4)) RETURN
     400            0 :             IF (ABS(entry1%value_r4 - entry2%value_r4) > 1e-5) RETURN
     401              : 
     402           14 :          ELSE IF (ASSOCIATED(entry1%value_r8)) THEN
     403            8 :             IF (.NOT. ASSOCIATED(entry2%value_r8)) RETURN
     404            8 :             IF (ABS(entry1%value_r8 - entry2%value_r8) > 1e-10) RETURN
     405              : 
     406            6 :          ELSE IF (ASSOCIATED(entry1%value_1d_i4)) THEN
     407            0 :             IF (.NOT. ASSOCIATED(entry2%value_1d_i4)) RETURN
     408            0 :             IF (ANY(entry1%value_1d_i4 /= entry2%value_1d_i4)) RETURN
     409              : 
     410            6 :          ELSE IF (ASSOCIATED(entry1%value_1d_i8)) THEN
     411            0 :             IF (.NOT. ASSOCIATED(entry2%value_1d_i8)) RETURN
     412            0 :             IF (ANY(entry1%value_1d_i8 /= entry2%value_1d_i8)) RETURN
     413              : 
     414            6 :          ELSE IF (ASSOCIATED(entry1%value_1d_r4)) THEN
     415            0 :             IF (.NOT. ASSOCIATED(entry2%value_1d_r4)) RETURN
     416            0 :             IF (ANY(ABS(entry1%value_1d_r4 - entry2%value_1d_r4) > 1e-5)) RETURN
     417              : 
     418            6 :          ELSE IF (ASSOCIATED(entry1%value_1d_r8)) THEN
     419            6 :             IF (.NOT. ASSOCIATED(entry2%value_1d_r8)) RETURN
     420          186 :             IF (ANY(ABS(entry1%value_1d_r8 - entry2%value_1d_r8) > 1e-10)) RETURN
     421              :          ELSE
     422            0 :             CPABORT("no value ASSOCIATED")
     423              :          END IF
     424              : 
     425           38 :          entry1 => entry1%next
     426              :       END DO
     427              : 
     428              :       ! if we reach this point no differences were found
     429            8 :       res = .TRUE.
     430              :    END FUNCTION swarm_message_equal_oneway
     431              : 
     432              : ! **************************************************************************************************
     433              : !> \brief Helper routine for swarm_message_mpi_send.
     434              : !> \param ENTRY ...
     435              : !> \param group ...
     436              : !> \param dest ...
     437              : !> \param tag ...
     438              : !> \author Ole Schuett
     439              : ! **************************************************************************************************
     440          310 :    SUBROUTINE swarm_message_entry_mpi_send(ENTRY, group, dest, tag)
     441              :       TYPE(message_entry_type), INTENT(IN)               :: ENTRY
     442              :       CLASS(mp_comm_type), INTENT(IN) :: group
     443              :       INTEGER, INTENT(IN)                                :: dest, tag
     444              : 
     445              :       INTEGER, DIMENSION(default_string_length)          :: value_str_arr
     446              :       INTEGER, DIMENSION(key_length)                     :: key_arr
     447              : 
     448          310 :       key_arr = str2iarr(entry%key)
     449          310 :       CALL group%send(key_arr, dest, tag)
     450              : 
     451          310 :       IF (ASSOCIATED(entry%value_i4)) THEN
     452          156 :          CALL group%send(1, dest, tag)
     453          156 :          CALL group%send(entry%value_i4, dest, tag)
     454              : 
     455          154 :       ELSE IF (ASSOCIATED(entry%value_i8)) THEN
     456            0 :          CALL group%send(2, dest, tag)
     457            0 :          CALL group%send(entry%value_i8, dest, tag)
     458              : 
     459          154 :       ELSE IF (ASSOCIATED(entry%value_r4)) THEN
     460            0 :          CALL group%send(3, dest, tag)
     461            0 :          CALL group%send(entry%value_r4, dest, tag)
     462              : 
     463          154 :       ELSE IF (ASSOCIATED(entry%value_r8)) THEN
     464           50 :          CALL group%send(4, dest, tag)
     465           50 :          CALL group%send(entry%value_r8, dest, tag)
     466              : 
     467          104 :       ELSE IF (ASSOCIATED(entry%value_1d_i4)) THEN
     468            0 :          CALL group%send(5, dest, tag)
     469            0 :          CALL group%send(SIZE(entry%value_1d_i4), dest, tag)
     470            0 :          CALL group%send(entry%value_1d_i4, dest, tag)
     471              : 
     472          104 :       ELSE IF (ASSOCIATED(entry%value_1d_i8)) THEN
     473            0 :          CALL group%send(6, dest, tag)
     474            0 :          CALL group%send(SIZE(entry%value_1d_i8), dest, tag)
     475            0 :          CALL group%send(entry%value_1d_i8, dest, tag)
     476              : 
     477          104 :       ELSE IF (ASSOCIATED(entry%value_1d_r4)) THEN
     478            0 :          CALL group%send(7, dest, tag)
     479            0 :          CALL group%send(SIZE(entry%value_1d_r4), dest, tag)
     480            0 :          CALL group%send(entry%value_1d_r4, dest, tag)
     481              : 
     482          104 :       ELSE IF (ASSOCIATED(entry%value_1d_r8)) THEN
     483           48 :          CALL group%send(8, dest, tag)
     484           48 :          CALL group%send(SIZE(entry%value_1d_r8), dest, tag)
     485         1488 :          CALL group%send(entry%value_1d_r8, dest, tag)
     486              : 
     487           56 :       ELSE IF (ASSOCIATED(entry%value_str)) THEN
     488           56 :          CALL group%send(9, dest, tag)
     489           56 :          value_str_arr = str2iarr(entry%value_str)
     490           56 :          CALL group%send(value_str_arr, dest, tag)
     491              :       ELSE
     492            0 :          CPABORT("no value ASSOCIATED")
     493              :       END IF
     494          310 :    END SUBROUTINE swarm_message_entry_mpi_send
     495              : 
     496              : ! **************************************************************************************************
     497              : !> \brief Helper routine for swarm_message_mpi_recv.
     498              : !> \param ENTRY ...
     499              : !> \param group ...
     500              : !> \param src ...
     501              : !> \param tag ...
     502              : !> \author Ole Schuett
     503              : ! **************************************************************************************************
     504          310 :    SUBROUTINE swarm_message_entry_mpi_recv(ENTRY, group, src, tag)
     505              :       TYPE(message_entry_type), INTENT(INOUT)            :: ENTRY
     506              :       CLASS(mp_comm_type), INTENT(IN)                                :: group
     507              :       INTEGER, INTENT(INOUT)                             :: src, tag
     508              : 
     509              :       INTEGER                                            :: datatype, s
     510              :       INTEGER, DIMENSION(default_string_length)          :: value_str_arr
     511              :       INTEGER, DIMENSION(key_length)                     :: key_arr
     512              : 
     513          310 :       CALL group%recv(key_arr, src, tag)
     514          310 :       entry%key = iarr2str(key_arr)
     515              : 
     516          310 :       CALL group%recv(datatype, src, tag)
     517              : 
     518          156 :       SELECT CASE (datatype)
     519              :       CASE (1)
     520          156 :          ALLOCATE (entry%value_i4)
     521          156 :          CALL group%recv(entry%value_i4, src, tag)
     522              :       CASE (2)
     523            0 :          ALLOCATE (entry%value_i8)
     524            0 :          CALL group%recv(entry%value_i8, src, tag)
     525              :       CASE (3)
     526            0 :          ALLOCATE (entry%value_r4)
     527            0 :          CALL group%recv(entry%value_r4, src, tag)
     528              :       CASE (4)
     529           50 :          ALLOCATE (entry%value_r8)
     530           50 :          CALL group%recv(entry%value_r8, src, tag)
     531              :       CASE (5)
     532            0 :          CALL group%recv(s, src, tag)
     533            0 :          ALLOCATE (entry%value_1d_i4(s))
     534            0 :          CALL group%recv(entry%value_1d_i4, src, tag)
     535              :       CASE (6)
     536            0 :          CALL group%recv(s, src, tag)
     537            0 :          ALLOCATE (entry%value_1d_i8(s))
     538            0 :          CALL group%recv(entry%value_1d_i8, src, tag)
     539              :       CASE (7)
     540            0 :          CALL group%recv(s, src, tag)
     541            0 :          ALLOCATE (entry%value_1d_r4(s))
     542            0 :          CALL group%recv(entry%value_1d_r4, src, tag)
     543              :       CASE (8)
     544           48 :          CALL group%recv(s, src, tag)
     545          144 :          ALLOCATE (entry%value_1d_r8(s))
     546         2928 :          CALL group%recv(entry%value_1d_r8, src, tag)
     547              :       CASE (9)
     548           56 :          ALLOCATE (entry%value_str)
     549           56 :          CALL group%recv(value_str_arr, src, tag)
     550           56 :          entry%value_str = iarr2str(value_str_arr)
     551              :       CASE DEFAULT
     552          310 :          CPABORT("unknown datatype")
     553              :       END SELECT
     554          310 :    END SUBROUTINE swarm_message_entry_mpi_recv
     555              : 
     556              : ! **************************************************************************************************
     557              : !> \brief Helper routine for swarm_message_mpi_bcast.
     558              : !> \param ENTRY ...
     559              : !> \param src ...
     560              : !> \param group ...
     561              : !> \param mepos ...
     562              : !> \author Ole Schuett
     563              : ! **************************************************************************************************
     564          129 :    SUBROUTINE swarm_message_entry_mpi_bcast(ENTRY, src, group, mepos)
     565              :       TYPE(message_entry_type), INTENT(INOUT)            :: ENTRY
     566              :       INTEGER, INTENT(IN)                                :: src, mepos
     567              :       CLASS(mp_comm_type), INTENT(IN) :: group
     568              : 
     569              :       INTEGER                                            :: datasize, datatype
     570              :       INTEGER, DIMENSION(default_string_length)          :: value_str_arr
     571              :       INTEGER, DIMENSION(key_length)                     :: key_arr
     572              : 
     573          129 :       IF (src == mepos) key_arr = str2iarr(entry%key)
     574          129 :       CALL group%bcast(key_arr, src)
     575          129 :       IF (src /= mepos) entry%key = iarr2str(key_arr)
     576              : 
     577          129 :       IF (src == mepos) THEN
     578          129 :          datasize = 1
     579          129 :          IF (ASSOCIATED(entry%value_i4)) THEN
     580           53 :             datatype = 1
     581           76 :          ELSE IF (ASSOCIATED(entry%value_i8)) THEN
     582            0 :             datatype = 2
     583           76 :          ELSE IF (ASSOCIATED(entry%value_r4)) THEN
     584            0 :             datatype = 3
     585           76 :          ELSE IF (ASSOCIATED(entry%value_r8)) THEN
     586           25 :             datatype = 4
     587           51 :          ELSE IF (ASSOCIATED(entry%value_1d_i4)) THEN
     588            0 :             datatype = 5
     589            0 :             datasize = SIZE(entry%value_1d_i4)
     590           51 :          ELSE IF (ASSOCIATED(entry%value_1d_i8)) THEN
     591            0 :             datatype = 6
     592            0 :             datasize = SIZE(entry%value_1d_i8)
     593           51 :          ELSE IF (ASSOCIATED(entry%value_1d_r4)) THEN
     594            0 :             datatype = 7
     595            0 :             datasize = SIZE(entry%value_1d_r4)
     596           51 :          ELSE IF (ASSOCIATED(entry%value_1d_r8)) THEN
     597           23 :             datatype = 8
     598           23 :             datasize = SIZE(entry%value_1d_r8)
     599           28 :          ELSE IF (ASSOCIATED(entry%value_str)) THEN
     600           28 :             datatype = 9
     601              :          ELSE
     602            0 :             CPABORT("no value ASSOCIATED")
     603              :          END IF
     604              :       END IF
     605          129 :       CALL group%bcast(datatype, src)
     606          129 :       CALL group%bcast(datasize, src)
     607              : 
     608           53 :       SELECT CASE (datatype)
     609              :       CASE (1)
     610           53 :          IF (src /= mepos) ALLOCATE (entry%value_i4)
     611           53 :          CALL group%bcast(entry%value_i4, src)
     612              :       CASE (2)
     613            0 :          IF (src /= mepos) ALLOCATE (entry%value_i8)
     614            0 :          CALL group%bcast(entry%value_i8, src)
     615              :       CASE (3)
     616            0 :          IF (src /= mepos) ALLOCATE (entry%value_r4)
     617            0 :          CALL group%bcast(entry%value_r4, src)
     618              :       CASE (4)
     619           25 :          IF (src /= mepos) ALLOCATE (entry%value_r8)
     620           25 :          CALL group%bcast(entry%value_r8, src)
     621              :       CASE (5)
     622            0 :          IF (src /= mepos) ALLOCATE (entry%value_1d_i4(datasize))
     623            0 :          CALL group%bcast(entry%value_1d_i4, src)
     624              :       CASE (6)
     625            0 :          IF (src /= mepos) ALLOCATE (entry%value_1d_i8(datasize))
     626            0 :          CALL group%bcast(entry%value_1d_i8, src)
     627              :       CASE (7)
     628            0 :          IF (src /= mepos) ALLOCATE (entry%value_1d_r4(datasize))
     629            0 :          CALL group%bcast(entry%value_1d_r4, src)
     630              :       CASE (8)
     631           23 :          IF (src /= mepos) ALLOCATE (entry%value_1d_r8(datasize))
     632         1403 :          CALL group%bcast(entry%value_1d_r8, src)
     633              :       CASE (9)
     634           28 :          IF (src == mepos) value_str_arr = str2iarr(entry%value_str)
     635           28 :          CALL group%bcast(value_str_arr, src)
     636           28 :          IF (src /= mepos) THEN
     637            0 :             ALLOCATE (entry%value_str)
     638            0 :             entry%value_str = iarr2str(value_str_arr)
     639              :          END IF
     640              :       CASE DEFAULT
     641          129 :          CPABORT("unknown datatype")
     642              :       END SELECT
     643              : 
     644          129 :    END SUBROUTINE swarm_message_entry_mpi_bcast
     645              : 
     646              : ! **************************************************************************************************
     647              : !> \brief Helper routine for swarm_message_file_write.
     648              : !> \param ENTRY ...
     649              : !> \param unit ...
     650              : !> \author Ole Schuett
     651              : ! **************************************************************************************************
     652          357 :    SUBROUTINE swarm_message_entry_file_write(ENTRY, unit)
     653              :       TYPE(message_entry_type), INTENT(IN)               :: ENTRY
     654              :       INTEGER, INTENT(IN)                                :: unit
     655              : 
     656              :       INTEGER                                            :: i
     657              : 
     658          357 :       WRITE (unit, "(A,A)") "key: ", entry%key
     659          357 :       IF (ASSOCIATED(entry%value_i4)) THEN
     660          180 :          WRITE (unit, "(A)") "datatype: i4"
     661          180 :          WRITE (unit, "(A,I10)") "value: ", entry%value_i4
     662              : 
     663          177 :       ELSE IF (ASSOCIATED(entry%value_i8)) THEN
     664            0 :          WRITE (unit, "(A)") "datatype: i8"
     665            0 :          WRITE (unit, "(A,I20)") "value: ", entry%value_i8
     666              : 
     667          177 :       ELSE IF (ASSOCIATED(entry%value_r4)) THEN
     668            0 :          WRITE (unit, "(A)") "datatype: r4"
     669            0 :          WRITE (unit, "(A,E30.20)") "value: ", entry%value_r4
     670              : 
     671          177 :       ELSE IF (ASSOCIATED(entry%value_r8)) THEN
     672           58 :          WRITE (unit, "(A)") "datatype: r8"
     673           58 :          WRITE (unit, "(A,E30.20)") "value: ", entry%value_r8
     674              : 
     675          119 :       ELSE IF (ASSOCIATED(entry%value_str)) THEN
     676           64 :          WRITE (unit, "(A)") "datatype: str"
     677           64 :          WRITE (unit, "(A,A)") "value: ", entry%value_str
     678              : 
     679           55 :       ELSE IF (ASSOCIATED(entry%value_1d_i4)) THEN
     680            0 :          WRITE (unit, "(A)") "datatype: 1d_i4"
     681            0 :          WRITE (unit, "(A,I10)") "size: ", SIZE(entry%value_1d_i4)
     682            0 :          DO i = 1, SIZE(entry%value_1d_i4)
     683            0 :             WRITE (unit, *) entry%value_1d_i4(i)
     684              :          END DO
     685              : 
     686           55 :       ELSE IF (ASSOCIATED(entry%value_1d_i8)) THEN
     687            0 :          WRITE (unit, "(A)") "datatype: 1d_i8"
     688            0 :          WRITE (unit, "(A,I20)") "size: ", SIZE(entry%value_1d_i8)
     689            0 :          DO i = 1, SIZE(entry%value_1d_i8)
     690            0 :             WRITE (unit, *) entry%value_1d_i8(i)
     691              :          END DO
     692              : 
     693           55 :       ELSE IF (ASSOCIATED(entry%value_1d_r4)) THEN
     694            0 :          WRITE (unit, "(A)") "datatype: 1d_r4"
     695            0 :          WRITE (unit, "(A,I8)") "size: ", SIZE(entry%value_1d_r4)
     696            0 :          DO i = 1, SIZE(entry%value_1d_r4)
     697            0 :             WRITE (unit, "(1X,E30.20)") entry%value_1d_r4(i)
     698              :          END DO
     699              : 
     700           55 :       ELSE IF (ASSOCIATED(entry%value_1d_r8)) THEN
     701           55 :          WRITE (unit, "(A)") "datatype: 1d_r8"
     702           55 :          WRITE (unit, "(A,I8)") "size: ", SIZE(entry%value_1d_r8)
     703         1705 :          DO i = 1, SIZE(entry%value_1d_r8)
     704         1705 :             WRITE (unit, "(1X,E30.20)") entry%value_1d_r8(i)
     705              :          END DO
     706              : 
     707              :       ELSE
     708            0 :          CPABORT("no value ASSOCIATED")
     709              :       END IF
     710          357 :    END SUBROUTINE swarm_message_entry_file_write
     711              : 
     712              : ! **************************************************************************************************
     713              : !> \brief Helper routine for swarm_message_file_read.
     714              : !> \param ENTRY ...
     715              : !> \param parser ...
     716              : !> \param at_end ...
     717              : !> \author Ole Schuett
     718              : ! **************************************************************************************************
     719           51 :    SUBROUTINE swarm_message_entry_file_read(ENTRY, parser, at_end)
     720              :       TYPE(message_entry_type), INTENT(INOUT)            :: ENTRY
     721              :       TYPE(cp_parser_type), INTENT(INOUT)                :: parser
     722              :       LOGICAL, INTENT(INOUT)                             :: at_end
     723              : 
     724              :       CHARACTER(LEN=15)                                  :: datatype, label
     725              :       INTEGER                                            :: arr_size, i
     726              :       LOGICAL                                            :: is_scalar
     727              : 
     728           51 :       CALL parser_get_next_line(parser, 1, at_end)
     729           51 :       at_end = at_end .OR. LEN_TRIM(parser%input_line(1:10)) == 0
     730           95 :       IF (at_end) RETURN
     731           51 :       READ (parser%input_line(1:key_length + 10), *) label, entry%key
     732           51 :       CPASSERT(TRIM(label) == "key:")
     733              : 
     734           51 :       CALL parser_get_next_line(parser, 1, at_end)
     735           51 :       at_end = at_end .OR. LEN_TRIM(parser%input_line(1:10)) == 0
     736           51 :       IF (at_end) RETURN
     737           51 :       READ (parser%input_line(1:30), *) label, datatype
     738           51 :       CPASSERT(TRIM(label) == "datatype:")
     739              : 
     740           51 :       CALL parser_get_next_line(parser, 1, at_end)
     741           51 :       at_end = at_end .OR. LEN_TRIM(parser%input_line(1:10)) == 0
     742           51 :       IF (at_end) RETURN
     743              : 
     744           51 :       is_scalar = .TRUE.
     745           77 :       SELECT CASE (TRIM(datatype))
     746              :       CASE ("i4")
     747           26 :          ALLOCATE (entry%value_i4)
     748           26 :          READ (parser%input_line(1:40), *) label, entry%value_i4
     749              :       CASE ("i8")
     750            0 :          ALLOCATE (entry%value_i8)
     751            0 :          READ (parser%input_line(1:40), *) label, entry%value_i8
     752              :       CASE ("r4")
     753            0 :          ALLOCATE (entry%value_r4)
     754            0 :          READ (parser%input_line(1:40), *) label, entry%value_r4
     755              :       CASE ("r8")
     756            8 :          ALLOCATE (entry%value_r8)
     757            8 :          READ (parser%input_line(1:40), *) label, entry%value_r8
     758              :       CASE ("str")
     759           10 :          ALLOCATE (entry%value_str)
     760           10 :          READ (parser%input_line(1:40), *) label, entry%value_str
     761              :       CASE DEFAULT
     762           51 :          is_scalar = .FALSE.
     763              :       END SELECT
     764              : 
     765              :       IF (is_scalar) THEN
     766           44 :          CPASSERT(TRIM(label) == "value:")
     767           44 :          RETURN
     768              :       END IF
     769              : 
     770              :       ! musst be an array-datatype
     771            7 :       READ (parser%input_line(1:30), *) label, arr_size
     772            7 :       CPASSERT(TRIM(label) == "size:")
     773              : 
     774            7 :       SELECT CASE (TRIM(datatype))
     775              :       CASE ("1d_i4")
     776            0 :          ALLOCATE (entry%value_1d_i4(arr_size))
     777              :       CASE ("1d_i8")
     778            0 :          ALLOCATE (entry%value_1d_i8(arr_size))
     779              :       CASE ("1d_r4")
     780            0 :          ALLOCATE (entry%value_1d_r4(arr_size))
     781              :       CASE ("1d_r8")
     782           21 :          ALLOCATE (entry%value_1d_r8(arr_size))
     783              :       CASE DEFAULT
     784            7 :          CPABORT("unknown datatype")
     785              :       END SELECT
     786              : 
     787          217 :       DO i = 1, arr_size
     788          210 :          CALL parser_get_next_line(parser, 1, at_end)
     789          210 :          at_end = at_end .OR. LEN_TRIM(parser%input_line(1:10)) == 0
     790          210 :          IF (at_end) RETURN
     791              : 
     792              :          !Numbers were written with at most 31 characters.
     793            7 :          SELECT CASE (TRIM(datatype))
     794              :          CASE ("1d_i4")
     795            0 :             READ (parser%input_line(1:31), *) entry%value_1d_i4(i)
     796              :          CASE ("1d_i8")
     797            0 :             READ (parser%input_line(1:31), *) entry%value_1d_i8(i)
     798              :          CASE ("1d_r4")
     799            0 :             READ (parser%input_line(1:31), *) entry%value_1d_r4(i)
     800              :          CASE ("1d_r8")
     801          210 :             READ (parser%input_line(1:31), *) entry%value_1d_r8(i)
     802              :          CASE DEFAULT
     803          210 :             CPABORT("swarm_message_entry_file_read: unknown datatype")
     804              :          END SELECT
     805              :       END DO
     806              : 
     807              :    END SUBROUTINE swarm_message_entry_file_read
     808              : 
     809              : ! **************************************************************************************************
     810              : !> \brief Helper routine, converts a string into an integer-array
     811              : !> \param str ...
     812              : !> \return ...
     813              : !> \author Ole Schuett
     814              : ! **************************************************************************************************
     815          523 :    PURE FUNCTION str2iarr(str) RESULT(arr)
     816              :       CHARACTER(LEN=*), INTENT(IN)                       :: str
     817              :       INTEGER, DIMENSION(LEN(str))                       :: arr
     818              : 
     819              :       INTEGER                                            :: i
     820              : 
     821        16023 :       DO i = 1, LEN(str)
     822        16023 :          arr(i) = ICHAR(str(i:i))
     823              :       END DO
     824          523 :    END FUNCTION str2iarr
     825              : 
     826              : ! **************************************************************************************************
     827              : !> \brief Helper routine, converts an integer-array into a string
     828              : !> \param arr ...
     829              : !> \return ...
     830              : !> \author Ole Schuett
     831              : ! **************************************************************************************************
     832          366 :    PURE FUNCTION iarr2str(arr) RESULT(str)
     833              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: arr
     834              :       CHARACTER(LEN=SIZE(arr))                           :: str
     835              : 
     836              :       INTEGER                                            :: i
     837              : 
     838        11046 :       DO i = 1, SIZE(arr)
     839        11046 :          str(i:i) = CHAR(arr(i))
     840              :       END DO
     841          366 :    END FUNCTION iarr2str
     842              : 
     843              :    #:set instances = {'str'   : 'CHARACTER(LEN=*)', &
     844              :       'i4'    : 'INTEGER(KIND=int_4)', &
     845              :       'i8'    : 'INTEGER(KIND=int_8)', &
     846              :       'r4'    : 'REAL(KIND=real_4)', &
     847              :       'r8'    : 'REAL(KIND=real_8)', &
     848              :       '1d_i4' : 'INTEGER(KIND=int_4), DIMENSION(:)', &
     849              :       '1d_i8' : 'INTEGER(KIND=int_8), DIMENSION(:)', &
     850              :       '1d_r4' : 'REAL(KIND=real_4), DIMENSION(:)', &
     851              :       '1d_r8' : 'REAL(KIND=real_8), DIMENSION(:)' }
     852              : 
     853              :    #:for label, type in instances.items()
     854              : 
     855              : ! **************************************************************************************************
     856              : !> \brief Addes an entry from a swarm-message.
     857              : !> \param msg ...
     858              : !> \param key ...
     859              : !> \param value ...
     860              : !> \author Ole Schuett
     861              : ! **************************************************************************************************
     862          396 :       SUBROUTINE swarm_message_add_${label}$ (msg, key, value)
     863              :          TYPE(swarm_message_type), INTENT(INOUT)   :: msg
     864              :          CHARACTER(LEN=*), INTENT(IN)              :: key
     865              :          ${type}$, INTENT(IN)                      :: value
     866              : 
     867              :          TYPE(message_entry_type), POINTER :: new_entry
     868              : 
     869          343 :          IF (swarm_message_haskey(msg, key)) &
     870            0 :             CPABORT("swarm_message_add_${label}$: key already exists: "//TRIM(key))
     871              : 
     872          343 :          ALLOCATE (new_entry)
     873          343 :          new_entry%key = key
     874              : 
     875              :          #:if label.startswith("1d_")
     876          159 :             ALLOCATE (new_entry%value_${label}$ (SIZE(value)))
     877              :          #:else
     878          290 :             ALLOCATE (new_entry%value_${label}$)
     879              :          #:endif
     880              : 
     881         1933 :          new_entry%value_${label}$ = value
     882              : 
     883              :          !WRITE (*,*) "swarm_message_add_${label}$: key=",key, " value=",new_entry%value_${label}$
     884              : 
     885          343 :          IF (.NOT. ASSOCIATED(msg%root)) THEN
     886           65 :             msg%root => new_entry
     887              :          ELSE
     888          278 :             new_entry%next => msg%root
     889          278 :             msg%root => new_entry
     890              :          END IF
     891              : 
     892          343 :       END SUBROUTINE swarm_message_add_${label}$
     893              : 
     894              : ! **************************************************************************************************
     895              : !> \brief Returns an entry from a swarm-message.
     896              : !> \param msg ...
     897              : !> \param key ...
     898              : !> \param value ...
     899              : !> \author Ole Schuett
     900              : ! **************************************************************************************************
     901          643 :       SUBROUTINE swarm_message_get_${label}$ (msg, key, value)
     902              :          TYPE(swarm_message_type), INTENT(IN)  :: msg
     903              :          CHARACTER(LEN=*), INTENT(IN)          :: key
     904              : 
     905              :          #:if label=="str"
     906              :             CHARACTER(LEN=default_string_length)  :: value
     907              :          #:elif label.startswith("1d_")
     908              :             ${type}$, POINTER                     :: value
     909              :          #:else
     910              :             ${type}$, INTENT(OUT)                 :: value
     911              :          #:endif
     912              : 
     913              :          TYPE(message_entry_type), POINTER :: curr_entry
     914              :          !WRITE (*,*) "swarm_message_get_${label}$: key=",key
     915              : 
     916              :          #:if label.startswith("1d_")
     917           66 :             IF (ASSOCIATED(value)) CPABORT("swarm_message_get_${label}$: value already associated")
     918              :          #:endif
     919              : 
     920          643 :          curr_entry => msg%root
     921         2094 :          DO WHILE (ASSOCIATED(curr_entry))
     922         2094 :             IF (TRIM(curr_entry%key) == TRIM(key)) THEN
     923          643 :                IF (.NOT. ASSOCIATED(curr_entry%value_${label}$)) &
     924            0 :                   CPABORT("swarm_message_get_${label}$: value not associated key: "//TRIM(key))
     925              :                #:if label.startswith("1d_")
     926          198 :                   ALLOCATE (value(SIZE(curr_entry%value_${label}$)))
     927              :                #:endif
     928         4603 :                value = curr_entry%value_${label}$
     929              :                !WRITE (*,*) "swarm_message_get_${label}$: value=",value
     930          643 :                RETURN
     931              :             END IF
     932         1451 :             curr_entry => curr_entry%next
     933              :          END DO
     934            0 :          CPABORT("swarm_message_get: key not found: "//TRIM(key))
     935              :       END SUBROUTINE swarm_message_get_${label}$
     936              : 
     937              :    #:endfor
     938              : 
     939            0 : END MODULE swarm_message
     940              : 
        

Generated by: LCOV version 2.0-1