Formatting the HISTORY files of DL_MESO_DPD

Purpose of Module

This module format_history.f90 is a post-processing utility for DL_MESO_DPD, the Dissipative Particle Dynamics (DPD) code from the DL_MESO package.

It converts the trajectory (HISTORY) files from unformatted to a human readable form, (optionally) including explicative comments about all the quantities. This module is mainly for learning/checking purposes. The first aim is to help the user to check that the system was prepared as intended (e.g., showing all the bead properties and initial positions, all the bonds etc). The idea is to use it on small systems when familiarizing with the structure of input files needed for the simulation. Secondly, it can be used as a starting point for a user-defined analysis of trajectories.

Background Information

The base code for this module is DL_MESO_DPD, the Dissipative Particle Dynamics code from the mesoscopic simulation package DL_MESO, developed by M. Seaton at Daresbury Laboratory. This open source code is available from STFC under both academic (free) and commercial (paid) licenses. The module is to be used with DL_MESO in its last released version, version 2.6 (dating November 2015).

Testing

The present module is compiled with the available Fortran90 compiler, e.g.:

gfortran -o format.exe format_history.f90

and the executable must be in the same directory of the HISTORY* files to be analyzed. To test the module, run the simulation with the toy input files given in the following. (Note that these files contain commented lines as suggestions for further tests.) For the CONTROL file

Simple test

volume 3.0  3.0  3.0
temperature 1.0
cutoff 1.0

timestep 0.01
steps 6
equilibration steps 2
traj  2  2  0
stats every 2
stack size 2
print every 2
job time 100.0
close time 10.0

#surface shear y
#surface frozen  x
#surface hard  x

ensemble nvt mdvv

finish

and for the FIELD file

Simple test

SPECIES 3
A    1.0  0.0   1   0
B    1.0  0.0   0   0
C    1.0  0.0   0   0 

MOLECULES 2
AB
nummols 1
beads 2
A    0.0 0.0 0.0
B    0.1 0.0 0.0
bonds 1
harm 1 2 5.0 0.0
finish
AC
nummols 1
beads 2
A    0.0 0.0 0.0
C    0.1 0.0 0.0
bonds 1
harm 1 2 3.0 0.0
finish

INTERACTIONS 3
A    A    dpd 25.0 1.0 4.5
B    B    dpd 25.0 1.0 4.5
C    C    dpd 25.0 1.0 4.5

#EXTERNAL
#shear  3.0  0.0  0.0

CLOSE

After analyzing the trajectories, for a serial run (i.e., a single HISTORY file) and for both lcomm and lmcheck set to .TRUE., this output should be printed on the screen

 Number of nodes used in calculations ?
 # Check of beads: i, ltp(i), ltm(i), mole(i)
           1           1           0           0
           2           1           1           1
           3           2           1           1
           4           1           2           2
           5           3           2           2
 # Check of molecules: nammol(i), nbdmol(i), nbomol(i), nmol(i)
 AB                 2           1           1
 AC                 2           1           1
 # Total number of molecules =            2
 # Check of bonds: bndbtl(i,1), bndbtl(i,2)
           2           3
           4           5

and the HISTORY-F file should be

 # nspe, nmoldef, nusyst, nsyst, nbeads, nbonds
           3           2           1           5           5           2
 # dimx, dimy, dimz, volm
     3.000        3.000        3.000       27.000
 # keytrj, srfx, srfy, srfz
           0           0           0           0
 # SPECIES:
 # namspe, amass, rcii, lfrzn
 A               1.000        1.000    0
 B               1.000        1.000    0
 C               1.000        1.000    0
 # MOLECULES:
 # nammol
 AB      
 AC      
 # Simulation name:
 Simple test                                                                     
 # BEADS:
 # global, species, molecule, chain
           1           1           0           0
           2           1           1           1
           3           2           1           1
           4           1           2           2
           5           3           2           2
 # BONDS:
 # extremes of the bond
           2           3
           4           5
 # --- TRAJECTORIES --- (key =           0 )
 # mglobal, x, y, z
 # time, mbeads, dimx, dimy, dimz, shrdx, shrdy, shrdz
     0.000        5.000        3.000        3.000        3.000        0.000        0.000        0.000
 # snapshot number:           1
       1.0   1.471873E+00    1.525203E+00    1.507395E+00
       2.0   1.364570E+00    2.228593E+00    2.475293E+00
       3.0   1.300679E+00    2.256132E+00    2.340013E+00
       4.0   2.306000E+00    2.535871E+00    2.718987E-01
       5.0   2.292338E+00    2.576789E+00    2.972781E-01
 # time, mbeads, dimx, dimy, dimz, shrdx, shrdy, shrdz
     0.020        5.000        3.000        3.000        3.000        0.000        0.000        0.000
 # snapshot number:           2
       1.0   1.443747E+00    1.550407E+00    1.514791E+00
       2.0   1.403396E+00    2.234155E+00    2.504685E+00
       3.0   1.294301E+00    2.264003E+00    2.309210E+00
       4.0   2.296760E+00    2.511000E+00    2.881257E-01
       5.0   2.297256E+00    2.563023E+00    2.750665E-01
 # time, mbeads, dimx, dimy, dimz, shrdx, shrdy, shrdz
     0.040        5.000        3.000        3.000        3.000        0.000        0.000        0.000
 # snapshot number:           3
       1.0   1.415620E+00    1.575610E+00    1.522186E+00
       2.0   1.444185E+00    2.239136E+00    2.537687E+00
       3.0   1.285960E+00    2.272457E+00    2.274797E+00
       4.0   2.287877E+00    2.466031E+00    3.080055E-01
       5.0   2.301818E+00    2.569355E+00    2.492021E-01
 # time, mbeads, dimx, dimy, dimz, shrdx, shrdy, shrdz
     0.040        5.000        3.000        3.000        3.000        0.000        0.000        0.000

Source Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
PROGRAM format_history
!***********************************************************************************
!
! module to format dl_meso HISTORY files
!
! authors - m. a. seaton & s. chiacchiera, february 2017
!
!**********************************************************************************
IMPLICIT none
      INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND (15, 307)
      INTEGER, PARAMETER :: ntraj=10,nuser=5

      CHARACTER(80) :: text, a2
      CHARACTER(8), ALLOCATABLE :: namspe (:), nammol (:)
      CHARACTER(6) :: chan
      CHARACTER(8) :: a1
      
      INTEGER, ALLOCATABLE :: ltp (:), ltm (:), mole (:),  beads (:), bonds (:), bndtbl (:,:)
      INTEGER, ALLOCATABLE :: nbdmol (:), nbomol (:)
      INTEGER :: chain, imol, ioerror, i, k, j, nmoldef, ibond
      INTEGER :: nspe, nbeads, nusyst, nsyst, nbonds, global, species, molecule, numnodes, numbond
      INTEGER :: nummol, lfrzn, rnmol, keytrj, srfx, srfy, srfz
      INTEGER :: bead1, bead2
      INTEGER :: n1, n2, n3, n4
      INTEGER :: nform
      
      REAL(KIND=dp), ALLOCATABLE :: nmol (:)
      REAL(KIND=dp) :: volm, dimx, dimy, dimz, shrdx, shrdy, shrdz
      REAL(KIND=dp) :: amass, rcii
      REAL(KIND=dp) :: time, mbeads, mglobal, x, y, z, vx, vy, vz, fx, fy, fz
      REAL(KIND=dp) :: r1, r2, r3, r4
      
      LOGICAL :: eof, lcomm, lmcheck

      ! Switches for commenting and checking molecules
      
      lcomm =   .TRUE.
      lmcheck = .TRUE.

      ! Get number of nodes 

      WRITE (*,*) "Number of nodes used in calculations ?"
      READ (*,*) numnodes
      
      ALLOCATE (beads (numnodes), bonds (numnodes))
      
      ! Determine if HISTORY files exist

      IF (numnodes>1) THEN
         INQUIRE (file = 'HISTORY000000', EXIST = eof)
      ELSE
         INQUIRE (file = 'HISTORY', EXIST = eof)
      END IF
      IF (.NOT. eof) THEN
         WRITE (*,*) "ERROR: cannot find HISTORY files"
         STOP
      END IF

      ! Open the output files
      nform = ntraj + numnodes 
      DO j = 1, numnodes
         WRITE (chan, '(i6.6)') j-1
         IF (numnodes>1)THEN
            OPEN (nform+j-1, file = 'HISTORY'//chan//"-F", status = 'replace')
         ELSE
            OPEN (nform+j-1, file = 'HISTORY'//"-F", status = 'replace')
         END IF
      END DO
         
      ! First reading, where the number of beads, molecules and bonds are determined
      ! Arrays are filled with names of particles and molecules
      ! If multiple HISTORY files are present, it is checked they are compatible
      
      numbond = 0

      DO j = 1, numnodes
         WRITE (chan, '(i6.6)') j-1
         IF (numnodes>1) THEN
            OPEN (ntraj+j-1, file = 'HISTORY'//chan, access = 'sequential', form = 'unformatted', status = 'unknown')
         ELSE
            OPEN (ntraj, file = 'HISTORY', access = 'sequential', form = 'unformatted', status = 'unknown')
         END IF
         
         IF (j == 1) THEN
            READ (ntraj+j-1) nspe, nmoldef, nusyst, nsyst, nbeads, nbonds
            READ (ntraj+j-1) dimx, dimy, dimz, volm
            READ (ntraj+j-1) keytrj, srfx, srfy, srfz
         ELSE
            READ (ntraj+j-1) n1, n2, n3, n4, nbeads, nbonds
            READ (ntraj+j-1) r1, r2, r3, r4
            IF (n1 /= nspe .OR. n2 /= nmoldef .OR. n3 /= nusyst .OR. n4 /= nsyst &
                .OR. r1 /= dimx .OR. r2 /= dimy .OR. r3 /= dimz .OR. r4 /= volm) THEN
               WRITE (*,*) "ERROR: HISTORY files do not refer to the same system!"
               STOP
            ENDIF
            READ (ntraj+j-1) n1, n2, n3, n4
            IF (n1 /= keytrj .OR. n2 /= srfx .OR. n3 /= srfy .OR. n4 /= srfz) THEN
               WRITE (*,*) "ERROR: HISTORY files do not refer to the same system!"
               STOP
            ENDIF
         ENDIF

         beads (j) = nbeads
         bonds (j) = nbonds
         numbond = numbond + nbonds
         
         IF (lcomm) WRITE (nform+j-1,*) "# nspe, nmoldef, nusyst, nsyst, nbeads, nbonds"
         WRITE (nform+j-1,*) nspe, nmoldef, nusyst, nsyst, nbeads, nbonds
         IF (lcomm) WRITE (nform+j-1,*) "# dimx, dimy, dimz, volm"
         WRITE (nform+j-1,97) dimx, dimy, dimz, volm
         IF (lcomm) WRITE (nform+j-1,*) "# keytrj, srfx, srfy, srfz"
         WRITE (nform+j-1,*) keytrj, srfx, srfy, srfz
      END DO ! loop over nodes
               
      ALLOCATE (namspe (nspe), nammol (nmoldef))
      IF (lmcheck) THEN 
         ALLOCATE (ltp (1:nsyst), ltm (1:nsyst), mole (1:nsyst))
         ALLOCATE (nmol (1:nmoldef), nbdmol (1:nmoldef), nbomol (1:nmoldef))
         ALLOCATE (bndtbl (numbond, 2))
      ENDIF
      
      DO j = 1, numnodes
         IF (lcomm) WRITE (nform+j-1,*) "# SPECIES:"
         IF (lcomm) WRITE (nform+j-1,*) "# namspe, amass, rcii, lfrzn"
         DO i = 1, nspe
            IF (j == 1) THEN
               READ (ntraj+j-1) namspe (i), amass, rcii, lfrzn
            ELSE
               READ (ntraj+j-1) a1, amass, rcii, lfrzn
               IF (a1 /= namspe (i))THEN
                  WRITE (*,*) "ERROR: HISTORY files do not refer to the same system!"
                  STOP
               ENDIF
            ENDIF
            WRITE (nform+j-1,96) namspe (i), amass, rcii, lfrzn
         END DO

         IF (nmoldef>0) THEN
            IF (lcomm) WRITE (nform+j-1,*) "# MOLECULES:"
            IF (lcomm) WRITE (nform+j-1,*) "# nammol"
            DO i = 1, nmoldef
               IF (j==1) THEN
                  READ (ntraj+j-1) nammol (i)
               ELSE
                  READ (ntraj+j-1) a1
                  IF (a1 /= nammol (i))THEN
                     WRITE (*,*) "ERROR: HISTORY files do not refer to the same system!"
                     STOP
                  ENDIF
               END IF
               WRITE (nform+j-1,*) nammol (i)
            END DO
         END IF

         IF (j == 1) THEN
            READ (ntraj+j-1) text
         ELSE
            READ (ntraj+j-1) a2
            IF (a2 /= text) THEN 
               WRITE (*,*) "ERROR: HISTORY files do not refer to the same system!"            
               STOP
            ENDIF
         ENDIF
            
         IF (lcomm) WRITE (nform+j-1,*) "# Simulation name:"
         WRITE (nform+j-1,*) text

      ENDDO ! end of loop over nodes
               
      DO j = 1, numnodes
         CLOSE (ntraj+j-1)
      END DO
      
      ! Second reading, where (if required) arrays are filled with properties
      ! of beads and molecules. Then, the snapshots of trajectories are read.

      DO j = 1, numnodes
         WRITE (chan, '(i6.6)') j-1
         IF (numnodes>1) THEN
            OPEN (ntraj+j-1, file = 'HISTORY'//chan, access = 'sequential', form = 'unformatted', status = 'unknown')
         ELSE
            OPEN (ntraj, file = 'HISTORY', access = 'sequential', form = 'unformatted', status = 'unknown')
         END IF     
      
         READ (ntraj+j-1) !nspe, nmoldef, nusyst, nsyst, nbeads, nbonds
         READ (ntraj+j-1) !dimx, dimy, dimz, volm
         READ (ntraj+j-1) !keytrj, srfx, srfy, srfz

         DO i = 1, nspe
            READ (ntraj+j-1) !namspe (i), amass, rcii, lfrzn
         END DO
         
         DO i = 1, nmoldef
            READ (ntraj+j-1) !nammol (i)
         END DO
         
         READ (ntraj+j-1) !text
      END DO

            

      nummol = 0 !counter for number of molecules      
      ibond = 0  !counter for bonds
      
      !     fill in arrays for beads and bonds
      DO j = 1, numnodes
         IF (lcomm) WRITE (nform+j-1,*) "# BEADS:"
         IF (lcomm) WRITE (nform+j-1,*) "# global, species, molecule, chain"
         IF (lmcheck) THEN
            !Build ltp, ltm, mole
            DO i = 1, beads (j)
               READ (ntraj+j-1) global, species, molecule, chain
               ltp (global) = species
               ltm (global) = molecule
               mole (global) = chain
               nummol = MAX (nummol, chain)
               WRITE (nform+j-1,*) global, species, molecule, chain 
            END DO
         ELSE
            DO i = 1, beads (j)
               READ (ntraj+j-1) global, species, molecule, chain         
               WRITE (nform+j-1,*) global, species, molecule, chain 
            END DO
         ENDIF
         
         IF (bonds (j)>0) THEN
            IF (lcomm) WRITE (nform+j-1,*) "# BONDS:"
            IF (lcomm) WRITE (nform+j-1,*) "# extremes of the bond"
            IF (lmcheck) THEN
               ! Build bndtbl
               DO i = 1, bonds (j)
                  ibond = ibond + 1
                  READ (ntraj+j-1) bead1, bead2
                  bndtbl (ibond, 1) = bead1
                  bndtbl (ibond, 2) = bead2
                  WRITE (nform+j-1,*) bead1, bead2
               END DO
            ELSE
               DO i = 1, bonds (j)
                  READ (ntraj+j-1) bead1, bead2
                  WRITE (nform+j-1,*) bead1, bead2
               END DO
            END IF
         END IF
            
      END DO ! over nodes
      
      IF (lmcheck) THEN
      ! determine numbers of molecules, beads and bonds per molecule type
         nmol = 0.0_dp
         nbdmol = 0
         nbomol = 0 
         chain = 0
         imol = 0 !necessary to avoid out of bounds
         
         DO i = 1, nsyst
            IF (mole (i) /= chain) THEN
               chain = mole (i)
               imol = ltm (i)
               nmol (imol) = nmol (imol) + 1.0_dp
            END IF
            IF (imol > 0) nbdmol (imol) = nbdmol (imol) + 1
         END DO

         DO i = 1, numbond
            imol = ltm (bndtbl (i,1))
            nbomol (imol) = nbomol (imol) + 1
         END DO
            
         DO i = 1, nmoldef
            rnmol = NINT (nmol (i))
            IF (rnmol>0) THEN
               nbdmol (i) = nbdmol (i) / rnmol
               nbomol (i) = nbomol (i) / rnmol
            END IF
         END DO

         ! Write to std output the arrays built
         WRITE (*,*) "# Check of beads: i, ltp(i), ltm(i), mole(i)"
         DO i = 1, nsyst
            WRITE(*,*) i, ltp (i), ltm (i), mole (i)
         END DO

         !Check of molecule beads and numbers
         IF (nmoldef>0) THEN
            WRITE (*,*) "# Check of molecules: nammol(i), nbdmol(i), nbomol(i), nmol(i)"
            DO i = 1, nmoldef
               WRITE (*,*) nammol (i), nbdmol (i), nbomol (i), NINT(nmol(i))
            END DO
            WRITE (*,*) "# Total number of molecules = ",nummol
         END IF

         ! Write to std output bndtbl
         IF (numbond > 0) THEN
            WRITE (*,*) "# Check of bonds: bndbtl(i,1), bndbtl(i,2)"
            DO i = 1, numbond
               WRITE (*,*) bndtbl (i,1), bndtbl (i,2)
            END DO
         END IF
      END IF

      !reading trajectories 
      DO j = 1, numnodes
    
         eof = .false.
         k = 0
      
         IF (lcomm) WRITE (nform+j-1,*) "# --- TRAJECTORIES --- (key =", keytrj,")"
         SELECT CASE (keytrj)
         CASE (0)
            IF (lcomm) WRITE (nform+j-1,*) "# mglobal, x, y, z"
         CASE(1)
            IF (lcomm) WRITE (nform+j-1,*) "# mglobal, x, y, z, vx, vy, vz"
         CASE(2) 
            IF (lcomm) WRITE (nform+j-1,*) "# mglobal, x, y, z, vx, vy, vz, fx, fy, fz"
         END SELECT
         
         DO WHILE (.true.)
            READ (ntraj+j-1, IOSTAT=ioerror) time, mbeads, dimx, dimy, dimz, shrdx, shrdy, shrdz
            IF (lcomm) WRITE (nform+j-1,*) "# time, mbeads, dimx, dimy, dimz, shrdx, shrdy, shrdz"
            WRITE (nform+j-1,98) time, mbeads, dimx, dimy, dimz, shrdx, shrdy, shrdz
            
            IF (ioerror/=0) THEN
               eof = .true.
               IF (k==0) THEN
                  PRINT *, 'ERROR: cannot find trajectory data in HISTORY files'
                  STOP
               END IF
               EXIT
            END IF
            
            k = k + 1
            
            IF (lcomm) WRITE (nform+j-1,*) "# snapshot number:", k
            
            nbeads = NINT (mbeads)
            
            SELECT CASE (keytrj)
            CASE (0)
               DO i = 1, nbeads
                  READ (ntraj+j-1) mglobal, x, y, z
                  WRITE (nform+j-1,99) mglobal, x, y, z
               END DO
            CASE (1)
               DO i = 1, nbeads
                  READ (ntraj+j-1) mglobal, x, y, z, vx, vy, vz
                  WRITE (nform+j-1,99) mglobal, x, y, z, vx, vy, vz
               END DO
            CASE (2)
               DO i = 1, nbeads
                  READ (ntraj+j-1) mglobal, x, y, z, vx, vy, vz, fx, fy, fz
                  WRITE (nform+j-1,99) mglobal, x, y, z, vx, vy, vz, fx, fy, fz
               END DO
            END SELECT
            
         END DO
      END DO
         
      ! Close the trajectory files
      DO j = 1, numnodes
         CLOSE (ntraj+j-1)
      END DO

      ! close the output files
      DO j = 1, numnodes
         CLOSE (nform+j-1)
      END DO
               
      DEALLOCATE (beads, bonds)
      DEALLOCATE (namspe, nammol)
      IF (lmcheck) DEALLOCATE (ltp, ltm, mole, nmol, nbdmol, bndtbl, nbomol)

99    FORMAT(f10.1,2x,1p,9(e13.6,3x))
98    FORMAT(8(f10.3,3x))
97    FORMAT(4(f10.3,3x))
96    FORMAT(A9,3x,2(f10.3,3x),I2)
      
END PROGRAM format_history
Updated website