LCOV - code coverage report
Current view: top level - src/swarm - swarm_message.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:34ef472) Lines: 289 382 75.7 %
Date: 2024-04-26 08:30:29 Functions: 26 39 66.7 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 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         597 :    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         597 :       l = 0
      95         597 :       curr_entry => msg%root
      96        2408 :       DO WHILE (ASSOCIATED(curr_entry))
      97        1811 :          l = l + 1
      98        1811 :          curr_entry => curr_entry%next
      99             :       END DO
     100         597 :    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         826 :    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         826 :       res = .FALSE.
     117         826 :       curr_entry => msg%root
     118        3098 :       DO WHILE (ASSOCIATED(curr_entry))
     119        2272 :          IF (TRIM(curr_entry%key) == TRIM(key)) THEN
     120             :             res = .TRUE.
     121             :             EXIT
     122             :          END IF
     123        2272 :          curr_entry => curr_entry%next
     124             :       END DO
     125         826 :    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         274 :    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         274 :       ENTRY => msg%root
     138        1818 :       DO WHILE (ASSOCIATED(ENTRY))
     139        1544 :          IF (ASSOCIATED(entry%value_str)) DEALLOCATE (entry%value_str)
     140        1544 :          IF (ASSOCIATED(entry%value_i4)) DEALLOCATE (entry%value_i4)
     141        1544 :          IF (ASSOCIATED(entry%value_i8)) DEALLOCATE (entry%value_i8)
     142        1544 :          IF (ASSOCIATED(entry%value_r4)) DEALLOCATE (entry%value_r4)
     143        1544 :          IF (ASSOCIATED(entry%value_r8)) DEALLOCATE (entry%value_r8)
     144        1544 :          IF (ASSOCIATED(entry%value_1d_i4)) DEALLOCATE (entry%value_1d_i4)
     145        1544 :          IF (ASSOCIATED(entry%value_1d_i8)) DEALLOCATE (entry%value_1d_i8)
     146        1544 :          IF (ASSOCIATED(entry%value_1d_r4)) DEALLOCATE (entry%value_1d_r4)
     147        1544 :          IF (ASSOCIATED(entry%value_1d_r8)) DEALLOCATE (entry%value_1d_r8)
     148        1544 :          old_entry => ENTRY
     149        1544 :          ENTRY => entry%next
     150        1544 :          DEALLOCATE (old_entry)
     151             :       END DO
     152             : 
     153         274 :       NULLIFY (msg%root)
     154             : 
     155         274 :       CPASSERT(swarm_message_length(msg) == 0)
     156         274 :    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         126 :    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         126 :       CALL group%send(swarm_message_length(msg), dest, tag)
     190         126 :       curr_entry => msg%root
     191         856 :       DO WHILE (ASSOCIATED(curr_entry))
     192         730 :          CALL swarm_message_entry_mpi_send(curr_entry, group, dest, tag)
     193         730 :          curr_entry => curr_entry%next
     194             :       END DO
     195         126 :    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         126 :    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         126 :       IF (ASSOCIATED(msg%root)) CPABORT("message not empty")
     214         126 :       CALL group%recv(length, src, tag)
     215         856 :       DO i = 1, length
     216         730 :          ALLOCATE (new_entry)
     217         730 :          CALL swarm_message_entry_mpi_recv(new_entry, group, src, tag)
     218         730 :          new_entry%next => msg%root
     219         856 :          msg%root => new_entry
     220             :       END DO
     221             : 
     222         126 :    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          63 :    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          63 :          length = swarm_message_length(msg)
     243          63 :          CALL group%bcast(length, src)
     244             : 
     245          63 :          IF (mepos == src) curr_entry => msg%root
     246             : 
     247         430 :          DO i = 1, length
     248         304 :             IF (mepos /= src) ALLOCATE (curr_entry)
     249             : 
     250         304 :             CALL swarm_message_entry_mpi_bcast(curr_entry, src, group, mepos)
     251             : 
     252         367 :             IF (mepos == src) THEN
     253         304 :                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          63 :    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         268 :    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         134 :       IF (unit <= 0) RETURN
     277             : 
     278         134 :       CALL timeset("swarm_message_file_write", handle)
     279         134 :       WRITE (unit, "(A)") "BEGIN SWARM_MESSAGE"
     280         134 :       WRITE (unit, "(A,I10)") "msg_length: ", swarm_message_length(msg)
     281             : 
     282         134 :       curr_entry => msg%root
     283         911 :       DO WHILE (ASSOCIATED(curr_entry))
     284         777 :          CALL swarm_message_entry_file_write(curr_entry, unit)
     285         777 :          curr_entry => curr_entry%next
     286             :       END DO
     287             : 
     288         134 :       WRITE (unit, "(A)") "END SWARM_MESSAGE"
     289         134 :       WRITE (unit, "()")
     290         134 :       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          11 :    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         730 :    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         730 :       key_arr = str2iarr(entry%key)
     449         730 :       CALL group%send(key_arr, dest, tag)
     450             : 
     451         730 :       IF (ASSOCIATED(entry%value_i4)) THEN
     452         366 :          CALL group%send(1, dest, tag)
     453         366 :          CALL group%send(entry%value_i4, dest, tag)
     454             : 
     455         364 :       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         364 :       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         364 :       ELSE IF (ASSOCIATED(entry%value_r8)) THEN
     464         120 :          CALL group%send(4, dest, tag)
     465         120 :          CALL group%send(entry%value_r8, dest, tag)
     466             : 
     467         244 :       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         244 :       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         244 :       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         244 :       ELSE IF (ASSOCIATED(entry%value_1d_r8)) THEN
     483         118 :          CALL group%send(8, dest, tag)
     484         118 :          CALL group%send(SIZE(entry%value_1d_r8), dest, tag)
     485        3658 :          CALL group%send(entry%value_1d_r8, dest, tag)
     486             : 
     487         126 :       ELSE IF (ASSOCIATED(entry%value_str)) THEN
     488         126 :          CALL group%send(9, dest, tag)
     489         126 :          value_str_arr = str2iarr(entry%value_str)
     490         126 :          CALL group%send(value_str_arr, dest, tag)
     491             :       ELSE
     492           0 :          CPABORT("no value ASSOCIATED")
     493             :       END IF
     494         730 :    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         730 :    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         730 :       CALL group%recv(key_arr, src, tag)
     514         730 :       entry%key = iarr2str(key_arr)
     515             : 
     516         730 :       CALL group%recv(datatype, src, tag)
     517             : 
     518         366 :       SELECT CASE (datatype)
     519             :       CASE (1)
     520         366 :          ALLOCATE (entry%value_i4)
     521         366 :          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         120 :          ALLOCATE (entry%value_r8)
     530         120 :          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         118 :          CALL group%recv(s, src, tag)
     545         354 :          ALLOCATE (entry%value_1d_r8(s))
     546        7198 :          CALL group%recv(entry%value_1d_r8, src, tag)
     547             :       CASE (9)
     548         126 :          ALLOCATE (entry%value_str)
     549         126 :          CALL group%recv(value_str_arr, src, tag)
     550         126 :          entry%value_str = iarr2str(value_str_arr)
     551             :       CASE DEFAULT
     552         730 :          CPABORT("unknown datatype")
     553             :       END SELECT
     554         730 :    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         304 :    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         304 :       IF (src == mepos) key_arr = str2iarr(entry%key)
     574         304 :       CALL group%bcast(key_arr, src)
     575         304 :       IF (src /= mepos) entry%key = iarr2str(key_arr)
     576             : 
     577         304 :       IF (src == mepos) THEN
     578         304 :          datasize = 1
     579         304 :          IF (ASSOCIATED(entry%value_i4)) THEN
     580         123 :             datatype = 1
     581         181 :          ELSE IF (ASSOCIATED(entry%value_i8)) THEN
     582           0 :             datatype = 2
     583         181 :          ELSE IF (ASSOCIATED(entry%value_r4)) THEN
     584           0 :             datatype = 3
     585         181 :          ELSE IF (ASSOCIATED(entry%value_r8)) THEN
     586          60 :             datatype = 4
     587         121 :          ELSE IF (ASSOCIATED(entry%value_1d_i4)) THEN
     588           0 :             datatype = 5
     589           0 :             datasize = SIZE(entry%value_1d_i4)
     590         121 :          ELSE IF (ASSOCIATED(entry%value_1d_i8)) THEN
     591           0 :             datatype = 6
     592           0 :             datasize = SIZE(entry%value_1d_i8)
     593         121 :          ELSE IF (ASSOCIATED(entry%value_1d_r4)) THEN
     594           0 :             datatype = 7
     595           0 :             datasize = SIZE(entry%value_1d_r4)
     596         121 :          ELSE IF (ASSOCIATED(entry%value_1d_r8)) THEN
     597          58 :             datatype = 8
     598          58 :             datasize = SIZE(entry%value_1d_r8)
     599          63 :          ELSE IF (ASSOCIATED(entry%value_str)) THEN
     600          63 :             datatype = 9
     601             :          ELSE
     602           0 :             CPABORT("no value ASSOCIATED")
     603             :          END IF
     604             :       END IF
     605         304 :       CALL group%bcast(datatype, src)
     606         304 :       CALL group%bcast(datasize, src)
     607             : 
     608         123 :       SELECT CASE (datatype)
     609             :       CASE (1)
     610         123 :          IF (src /= mepos) ALLOCATE (entry%value_i4)
     611         123 :          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          60 :          IF (src /= mepos) ALLOCATE (entry%value_r8)
     620          60 :          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          58 :          IF (src /= mepos) ALLOCATE (entry%value_1d_r8(datasize))
     632        3538 :          CALL group%bcast(entry%value_1d_r8, src)
     633             :       CASE (9)
     634          63 :          IF (src == mepos) value_str_arr = str2iarr(entry%value_str)
     635          63 :          CALL group%bcast(value_str_arr, src)
     636          63 :          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         304 :          CPABORT("unknown datatype")
     642             :       END SELECT
     643             : 
     644         304 :    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         777 :    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         777 :       WRITE (unit, "(A,A)") "key: ", entry%key
     659         777 :       IF (ASSOCIATED(entry%value_i4)) THEN
     660         390 :          WRITE (unit, "(A)") "datatype: i4"
     661         390 :          WRITE (unit, "(A,I10)") "value: ", entry%value_i4
     662             : 
     663         387 :       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         387 :       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         387 :       ELSE IF (ASSOCIATED(entry%value_r8)) THEN
     672         128 :          WRITE (unit, "(A)") "datatype: r8"
     673         128 :          WRITE (unit, "(A,E30.20)") "value: ", entry%value_r8
     674             : 
     675         259 :       ELSE IF (ASSOCIATED(entry%value_str)) THEN
     676         134 :          WRITE (unit, "(A)") "datatype: str"
     677         134 :          WRITE (unit, "(A,A)") "value: ", entry%value_str
     678             : 
     679         125 :       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         125 :       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         125 :       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         125 :       ELSE IF (ASSOCIATED(entry%value_1d_r8)) THEN
     701         125 :          WRITE (unit, "(A)") "datatype: 1d_r8"
     702         125 :          WRITE (unit, "(A,I8)") "size: ", SIZE(entry%value_1d_r8)
     703        3875 :          DO i = 1, SIZE(entry%value_1d_r8)
     704        3875 :             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         777 :    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        1223 :    PURE FUNCTION str2iarr(str) RESULT(arr)
     816             :       CHARACTER(LEN=*), INTENT(IN)                       :: str
     817             :       INTEGER, DIMENSION(LEN(str))                       :: arr
     818             : 
     819             :       INTEGER                                            :: i
     820             : 
     821       37023 :       DO i = 1, LEN(str)
     822       37023 :          arr(i) = ICHAR(str(i:i))
     823             :       END DO
     824        1223 :    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         856 :    PURE FUNCTION iarr2str(arr) RESULT(str)
     833             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: arr
     834             :       CHARACTER(LEN=SIZE(arr))                           :: str
     835             : 
     836             :       INTEGER                                            :: i
     837             : 
     838       25536 :       DO i = 1, SIZE(arr)
     839       25536 :          str(i:i) = CHAR(arr(i))
     840             :       END DO
     841         856 :    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         886 :       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         763 :          IF (swarm_message_haskey(msg, key)) &
     870           0 :             CPABORT("swarm_message_add_${label}$: key already exists: "//TRIM(key))
     871             : 
     872         763 :          ALLOCATE (new_entry)
     873         763 :          new_entry%key = key
     874             : 
     875             :          #:if label.startswith("1d_")
     876         369 :             ALLOCATE (new_entry%value_${label}$ (SIZE(value)))
     877             :          #:else
     878         640 :             ALLOCATE (new_entry%value_${label}$)
     879             :          #:endif
     880             : 
     881        4453 :          new_entry%value_${label}$ = value
     882             : 
     883             :          !WRITE (*,*) "swarm_message_add_${label}$: key=",key, " value=",new_entry%value_${label}$
     884             : 
     885         763 :          IF (.NOT. ASSOCIATED(msg%root)) THEN
     886         135 :             msg%root => new_entry
     887             :          ELSE
     888         628 :             new_entry%next => msg%root
     889         628 :             msg%root => new_entry
     890             :          END IF
     891             : 
     892         763 :       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        1378 :       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         136 :             IF (ASSOCIATED(value)) CPABORT("swarm_message_get_${label}$: value already associated")
     918             :          #:endif
     919             : 
     920        1378 :          curr_entry => msg%root
     921        4509 :          DO WHILE (ASSOCIATED(curr_entry))
     922        4509 :             IF (TRIM(curr_entry%key) == TRIM(key)) THEN
     923        1378 :                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         408 :                   ALLOCATE (value(SIZE(curr_entry%value_${label}$)))
     927             :                #:endif
     928        9538 :                value = curr_entry%value_${label}$
     929             :                !WRITE (*,*) "swarm_message_get_${label}$: value=",value
     930        1378 :                RETURN
     931             :             END IF
     932        3131 :             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 1.15