RMPCDMD
common.f90
Go to the documentation of this file.
1 ! This file is part of RMPCDMD
2 ! Copyright (c) 2015-2017 Pierre de Buyl and contributors
3 ! License: BSD 3-clause (see file LICENSE)
4 
11 
12 module common
13  use iso_c_binding
14  implicit none
15  private
16 
17  public :: rel_pos
18  public :: profile_t
19  public :: histogram_t
20  public :: switch
21  public :: get_input_filename
22  public :: get_input_args
23  public :: timer_t
24  public :: timer_list_t
25  public :: args_t
26  public :: cross
27  public :: pi
28  public :: alist_t
29  public :: enzyme_kinetics_t
30  public :: numbered_string
31 
32  ! bitmask data
33  public :: reac_bit
34  public :: md_bit
35  public :: wall_bit
36  public :: past_md_bit
37  public :: outbound_bit
38  public :: catalyzed_bit
39  public :: enzyme_region_bit
40  public :: reac_mask
41  public :: md_mask
42  public :: wall_mask
43  public :: catalyzed_mask
44  public :: enzyme_region_mask
45 
46  integer, parameter :: max_path_length = 255
47  double precision, parameter :: pi = 4*atan(1.d0)
48 
49  integer, parameter :: reac_bit = 1
50  integer, parameter :: md_bit = 2
51  integer, parameter :: wall_bit = 3
52  integer, parameter :: past_md_bit = 4
53  integer, parameter :: outbound_bit = 5
54  integer, parameter :: catalyzed_bit = 6
55  integer, parameter :: enzyme_region_bit = 7
56 
57  integer, parameter :: reac_mask = ibset(0, reac_bit)
58  integer, parameter :: md_mask = ibset(0, md_bit)
59  integer, parameter :: wall_mask = ibset(0, wall_bit)
60  integer, parameter :: catalyzed_mask = ibset(0, catalyzed_bit)
61  integer, parameter :: enzyme_region_mask = ibset(0, enzyme_region_bit)
62 
66  type profile_t
67  double precision, allocatable :: data(:)
68  integer, allocatable :: count(:)
69  double precision :: xmin
70  double precision :: dx
71  integer :: n
72  contains
73  generic, public :: init => profile_init
74  procedure, private :: profile_init
75  generic, public :: bin => profile_bin
76  procedure, private :: profile_bin
77  generic, public :: reset => profile_reset
78  procedure, private :: profile_reset
79  generic, public :: norm => profile_norm
80  procedure, private :: profile_norm
81  end type profile_t
82 
87  double precision, allocatable :: data(:,:)
88  double precision :: xmin
89  double precision :: dx
90  integer :: n
91  integer :: n_species
92  contains
93  generic, public :: init => histogram_init
94  procedure, private :: histogram_init
95  generic, public :: bin => histogram_bin
96  procedure, private :: histogram_bin
97  end type histogram_t
98 
99  type timer_t
100  double precision :: tic_time
101  double precision :: total
102  character(len=32) :: name
103  contains
104  generic, public :: init => timer_init
105  procedure, private :: timer_init
106  procedure :: tic
107  procedure :: tac
108  end type timer_t
109 
111  type(timer_t), pointer :: p
112  end type timer_pointer_t
113 
115  type(timer_pointer_t), allocatable :: timers(:)
116  integer :: current_idx
117  contains
118  generic, public :: init => timer_list_init
119  procedure, private :: timer_list_init
120  generic, public :: append => timer_list_append
121  procedure, private :: timer_list_append
122  generic, public :: write => timer_list_write
123  procedure, private :: timer_list_write
124  end type timer_list_t
125 
126  interface switch
127  module procedure :: switch_d2
128  module procedure :: switch_i1
129  module procedure :: switch_i2
130  end interface switch
131 
133  type args_t
134  character(len=max_path_length) :: input_file
135  character(len=max_path_length) :: output_file
136  integer(c_int64_t) :: seed
137  end type args_t
138 
140  type alist_t
141  double precision, allocatable :: data(:)
142  integer :: current_idx
143  integer :: block_size
144  contains
145  generic, public :: init => alist_init
146  procedure, private :: alist_init
147  generic, public :: append => alist_append
148  procedure, private :: alist_append
149  end type alist_t
150 
153  type(alist_t) :: bind_substrate
154  type(alist_t) :: release_substrate
155  type(alist_t) :: bind_product
156  type(alist_t) :: release_product
157  end type enzyme_kinetics_t
158 
159 contains
160 
162  pure function rel_pos(x, y, L) result(r)
163  double precision, intent(in) :: x(3), y(3), L(3)
164 
165  double precision :: r(3)
166  integer :: dim
167 
168  r = x - y
169 
170  do dim=1,3
171  if ( r(dim) < -0.5d0*l(dim) ) then
172  r(dim) = r(dim) + l(dim)
173  else if ( r(dim) > 0.5d0*l(dim) ) then
174  r(dim) = r(dim) - l(dim)
175  end if
176  end do
177 
178  end function rel_pos
179 
180  subroutine profile_init(this, xmin, xmax, n)
181  class(profile_t), intent(out) :: this
182  double precision, intent(in) :: xmin, xmax
183  integer, intent(in) :: n
184 
185  this% n = n
186  this% xmin = xmin
187  this% dx = (xmax - xmin) / n
188  if (this% dx <= 0) error stop 'negative step in profile_init'
189  allocate(this% data(n))
190  this% data = 0
191  allocate(this% count(n))
192  this% count = 0
193 
194  end subroutine profile_init
195 
196  subroutine profile_bin(this, x, value)
197  class(profile_t), intent(inout) :: this
198  double precision, intent(in) :: x, value
199 
200  integer :: idx
201 
202  idx = floor( (x - this% xmin) / this% dx ) + 1
203  if ( ( idx > 0 ) .and. ( idx <= this% n ) ) then
204  this% data(idx) = this% data(idx) + value
205  this% count(idx) = this% count(idx) + 1
206  end if
207 
208  end subroutine profile_bin
209 
210  subroutine profile_reset(this)
211  class(profile_t), intent(inout) :: this
212 
213  this% data = 0
214  this% count = 0
215 
216  end subroutine profile_reset
217 
218  subroutine profile_norm(this)
219  class(profile_t), intent(inout) :: this
220 
221  where (this% count > 0)
222  this% data = this% data / this% count
223  end where
224 
225  end subroutine profile_norm
226 
227  subroutine histogram_init(this, xmin, xmax, n, n_species)
228  class(histogram_t), intent(out) :: this
229  double precision, intent(in) :: xmin, xmax
230  integer, intent(in) :: n
231  integer, optional, intent(in) :: n_species
232 
233  if (present(n_species)) then
234  this%n_species = n_species
235  else
236  this%n_species = 1
237  end if
238 
239  this% n = n
240  this% xmin = xmin
241  this% dx = (xmax - xmin) / n
242  if (this% dx <= 0) error stop 'negative step in histogram_init'
243  allocate(this% data(this%n_species, n))
244  this% data = 0
245 
246  end subroutine histogram_init
247 
248  subroutine histogram_bin(this, x, s)
249  class(histogram_t), intent(inout) :: this
250  double precision, intent(in) :: x
251  integer, optional, intent(in) :: s
252 
253  integer :: idx, s_var
254 
255  if (present(s)) then
256  s_var = s
257  else
258  s_var = 1
259  end if
260 
261  idx = floor( (x - this% xmin) / this% dx ) + 1
262  if ( ( idx > 0 ) .and. ( idx <= this% n ) ) then
263  this% data(s_var, idx) = this% data(s_var, idx) + 1
264  end if
265 
266  end subroutine histogram_bin
267 
268  subroutine switch_d2(p1, p2)
269  double precision, pointer, dimension(:,:), intent(inout) :: p1, p2
270  double precision, pointer, dimension(:,:) :: p
271 
272  p => p1
273  p1 => p2
274  p2 => p
275 
276  end subroutine switch_d2
277 
278  subroutine switch_i1(p1, p2)
279  integer, pointer, dimension(:), intent(inout) :: p1, p2
280  integer, pointer, dimension(:) :: p
281 
282  p => p1
283  p1 => p2
284  p2 => p
285 
286  end subroutine switch_i1
287 
288  subroutine switch_i2(p1, p2)
289  integer, pointer, dimension(:,:), intent(inout) :: p1, p2
290  integer, pointer, dimension(:,:) :: p
291 
292  p => p1
293  p1 => p2
294  p2 => p
295 
296  end subroutine switch_i2
297 
298  character(len=max_path_length) function get_input_filename() result(r)
300  if (command_argument_count() < 1) then
301  error stop 'missing argument for parameter file'
302  end if
303 
304  call get_command_argument(1, r)
305 
306  end function get_input_filename
307 
308  type(args_t) function get_input_args() result(args)
310  integer :: iostat
311  character(max_path_length) :: r
312 
313  if (command_argument_count() /= 3) then
314  write(*,*) 'Welcome to RMPCMD http://lab.pdebuyl.be/rmpcdmd/'
315  write(*,*) 'Usage:'
316  write(*,*) ' rmpcdmd run program_name input output seed'
317  write(*,*) &
318  ' where input is the filename of the parameters file, output is the name'
319  write(*,*) &
320  ' of the H5MD output file and seed is a signed 64-bit integer'
321  error stop
322  end if
323 
324  call get_command_argument(1, args%input_file)
325  call get_command_argument(2, args%output_file)
326  call get_command_argument(3, r)
327  read(r, *, iostat=iostat) args%seed
328  if (iostat /= 0) then
329  write(*,*) 'Error when reading the seed value (third command-line argument)'
330  error stop
331  end if
332 
333  end function get_input_args
334 
335  subroutine timer_init(this, name, system_name)
336  class(timer_t), intent(out) :: this
337  character(len=*), intent(in) :: name
338  character(len=*), optional, intent(in) :: system_name
339 
340  if (present(system_name)) then
341  if (len(system_name) > 0) then
342  this%name = system_name//' '//name
343  else
344  this%name = name
345  end if
346  else
347  this%name = name
348  end if
349  this%total = 0
350 
351  end subroutine timer_init
352 
353  subroutine tic(this)
354  use omp_lib
355  class(timer_t), intent(inout) :: this
356  this%tic_time = omp_get_wtime()
357  end subroutine tic
358 
359  subroutine tac(this)
360  use omp_lib
361  class(timer_t), intent(inout) :: this
362  this%total = this%total + omp_get_wtime() - this%tic_time
363  end subroutine tac
364 
365  subroutine timer_list_init(this, n)
366  class(timer_list_t), intent(out) :: this
367  integer, intent(in) :: n
368 
369  allocate(this%timers(n))
370  this%current_idx = 0
371 
372  end subroutine timer_list_init
373 
374  subroutine timer_list_append(this, timer_target)
375  class(timer_list_t), intent(inout) :: this
376  type(timer_t), target, intent(in) :: timer_target
377 
378  this%current_idx = this%current_idx + 1
379  if (this%current_idx > size(this%timers)) error stop 'exceeded timer_list_t size'
380  this%timers(this%current_idx)%p => timer_target
381 
382  end subroutine timer_list_append
383 
384  subroutine timer_list_write(this, group, total_out)
385  use hdf5, only: hid_t
386  use h5md_module, only: h5md_write_dataset
387  implicit none
388  class(timer_list_t), intent(inout) :: this
389  integer(HID_T), intent(inout) :: group
390  double precision, optional, intent(out) :: total_out
391 
392  integer :: i
393 
394  total_out = 0
395  do i = 1, size(this%timers)
396  if (associated(this%timers(i)%p)) then
397  call h5md_write_dataset(group, this%timers(i)%p%name, this%timers(i)%p%total)
398  total_out = total_out + this%timers(i)%p%total
399  end if
400  end do
401 
402  end subroutine timer_list_write
403 
404  pure function cross(x1, x2) result(r)
405  double precision, intent(in) :: x1(3), x2(3)
406  double precision :: r(3)
407 
408  r(1) = x1(2)*x2(3) - x1(3)*x2(2)
409  r(2) = x1(3)*x2(1) - x1(1)*x2(3)
410  r(3) = x1(1)*x2(2) - x1(2)*x2(1)
411 
412  end function cross
413 
414  subroutine alist_init(this, block_size)
415  class(alist_t), intent(out) :: this
416  integer, intent(in) :: block_size
417 
418  allocate(this%data(block_size))
419  this%current_idx = 0
420  this%block_size = block_size
421 
422  end subroutine alist_init
423 
424  subroutine alist_append(this, value)
425  class(alist_t), intent(inout) :: this
426  double precision, intent(in) :: value
427 
428  integer :: idx, len
429  double precision, allocatable :: tmp_data(:)
430 
431  idx = this%current_idx
432  len = size(this%data)
433 
434  if (idx == len) then
435  call move_alloc(this%data, tmp_data)
436  allocate(this%data(len+this%block_size))
437  this%data(1:len) = tmp_data
438  deallocate(tmp_data)
439  end if
440 
441  idx = idx + 1
442  this%data(idx) = value
443  this%current_idx = idx
444 
445  end subroutine alist_append
446 
447  function numbered_string(base_string, index, length) result(s)
448  character(len=*), intent(in) :: base_string
449  integer, intent(in) :: index
450  integer, intent(in) :: length
451  character(len=:), allocatable :: s
452 
453  character(len=12) format_string
454 
455  allocate(character(len=len(trim(base_string))+length) :: s)
456 
457  s(1:len(trim(base_string))) = base_string
458 
459  write(format_string, '(a,i3.3,a,i3.3,a)') '(a,i', length, '.', length, ')'
460  write(s, format_string) trim(base_string), index
461 
462  end function numbered_string
463 
464 end module common
integer, parameter, public enzyme_region_bit
Definition: common.f90:55
subroutine timer_init(this, name, system_name)
Definition: common.f90:336
Appendable lists of double precision data.
Definition: common.f90:140
subroutine switch_d2(p1, p2)
Definition: common.f90:269
integer, parameter, public catalyzed_mask
Definition: common.f90:60
subroutine tic(this)
Definition: common.f90:354
character(len=max_path_length) function, public get_input_filename()
Definition: common.f90:299
subroutine alist_init(this, block_size)
Definition: common.f90:415
integer, parameter max_path_length
Definition: common.f90:46
integer, parameter, public md_mask
Definition: common.f90:58
subroutine histogram_init(this, xmin, xmax, n, n_species)
Definition: common.f90:228
subroutine histogram_bin(this, x, s)
Definition: common.f90:249
integer, parameter, public md_bit
Definition: common.f90:50
integer, parameter, public enzyme_region_mask
Definition: common.f90:61
subroutine profile_norm(this)
Definition: common.f90:219
integer, parameter, public outbound_bit
Definition: common.f90:53
character(len=:) function, allocatable, public numbered_string(base_string, index, length)
Definition: common.f90:448
integer, parameter, public reac_mask
Definition: common.f90:57
type(args_t) function, public get_input_args()
Definition: common.f90:309
pure double precision function, dimension(3), public cross(x1, x2)
Definition: common.f90:405
subroutine profile_bin(this, x, value)
Definition: common.f90:197
subroutine switch_i1(p1, p2)
Definition: common.f90:279
subroutine timer_list_append(this, timer_target)
Definition: common.f90:375
integer, parameter, public wall_bit
Definition: common.f90:51
integer, parameter, public reac_bit
Definition: common.f90:49
Utility routines.
Definition: common.f90:12
integer, parameter, public past_md_bit
Definition: common.f90:52
Container for a profile, e.g. v(x)
Definition: common.f90:66
pure double precision function, dimension(3), public rel_pos(x, y, L)
Return x-y distance with minimum image convention.
Definition: common.f90:163
Container for a histogram, e.g. p(x)
Definition: common.f90:86
subroutine tac(this)
Definition: common.f90:360
Container for the standard command-line arguments to RMPCDMD.
Definition: common.f90:133
subroutine switch_i2(p1, p2)
Definition: common.f90:289
subroutine profile_reset(this)
Definition: common.f90:211
subroutine timer_list_write(this, group, total_out)
Definition: common.f90:385
subroutine alist_append(this, value)
Definition: common.f90:425
subroutine timer_list_init(this, n)
Definition: common.f90:366
subroutine profile_init(this, xmin, xmax, n)
Definition: common.f90:181
integer, parameter, public catalyzed_bit
Definition: common.f90:54
Container for the list of times for enzymatic kinetics.
Definition: common.f90:152
double precision, parameter, public pi
Definition: common.f90:47
integer, parameter, public wall_mask
Definition: common.f90:59