1
!*****************************************************************************
3
!*****************************************************************************
5
! Project: MolecularDynamics
7
! Created on: Mon 4 Jun 10:42:01 2018 by Eduardo R. Hernandez
9
! Last Modified: Mon 5 Nov 18:15:31 2018
12
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
13
! This file is distributed under the terms of the
14
! GNU General Public License: see COPYING in the top directory
15
! or http://www.gnu.org/copyleft/gpl.txt .
18
! This module defines the State derived type. This type contains information
19
! about the atomic positions, velocities (momenta), cell, extended variables
20
! (thermostat and/or barostat) etc. In short, it contains all the information
21
! needed to characterise the state of a simulated system, bundled into one
22
! object. All the data in State is private, and must be accessed through
23
! the corresponding get() and put() routines, also provided here.
25
! Internally, positions, momenta and forces are usually stored most commonly
26
! in Cartesian representation; however, some MD integration algorithms,
27
! in particular those that involve constant-pressure, require them in a lattice
28
! representation. It is therefore possible to transform from one representation
29
! to the other; the transformation is different and independent for each type
30
! of variable. A logical flag is used to keep track of the current representation
33
!*****************************************************************************
36
use md_precision_module
37
use md_constants_module
39
!*****************************************************************************
40
! No implicits please!
44
!*****************************************************************************
45
! derived type definitions
50
! there is no position; that role is played by the cell metricTensor
51
real (dp), dimension (3,3) :: momentum
53
end type barostat_type
57
real (dp) :: kinetic ! thermostat is used
58
real (dp) :: potential
59
real (dp) :: thermostat
61
real (dp) :: constantOfMotion ! may be different from total energy
65
type energyOrigin_type
67
logical :: set ! true if origin is set
70
end type energyOrigin_type
74
real (dp), dimension(3) :: a ! lattice vectors
75
real (dp), dimension(3) :: b
76
real (dp), dimension(3) :: c
77
real (dp) :: a_modulus ! their modulus
78
real (dp) :: b_modulus
79
real (dp) :: c_modulus
80
real (dp) :: alpha ! their angles
83
real (dp) :: volume ! cell volume
84
real (dp), dimension (3,3) :: metricTensor
88
type representation_type
90
logical :: position ! .true. if Cartesian rep; .false. otherwise
94
end type representation_type
99
real (dp), dimension(3,3) :: cartesian
100
real (dp), dimension(3,3) :: lattice
107
real (dp) :: position
108
real (dp) :: momentum
110
! the following are parameters used only
111
! in the particular case of Recursive-Nosé-Poincaré chains
116
end type thermostat_type
120
type ( representation_type ), private :: representation
122
! atom-related variables
124
integer, private :: nAtoms
125
integer, private :: nDegreesOfFreedom
126
real (dp), private, pointer, dimension (:,:) :: position
127
real (dp), private, pointer, dimension (:,:) :: force
128
real (dp), private, pointer, dimension (:,:) :: momentum
129
real (dp), private, pointer, dimension (:) :: mass
131
! cell-related variables
132
type ( lattice_type ), private :: Cell
133
type ( lattice_type ), private :: reciprocalCell
134
type ( stress_type ), private :: stress
136
! extended-system variables, if any
137
integer :: nThermostats
138
type ( thermostat_type ), private, pointer, dimension (:) :: thermostat
139
type ( barostat_type ), private :: barostat
141
! energy of the system
143
type ( energy_type ), private :: energy
145
type ( energyOrigin_type ), private :: H0 ! constant, only used if Nose thermostat(s) used
149
!*****************************************************************************
150
! private module variables
152
logical, private, parameter :: debug = .false.
153
logical, private :: PBC ! periodic boundary conditions (true if)
155
real (dp) :: energyConversionFactor
156
real (dp), private :: forceConversionFactor
157
real (dp), private :: lengthConversionFactor
158
real (dp), private :: massConversionFactor
159
real (dp) :: pressureConversionFactor
160
real (dp) :: timeConversionFactor
161
real (dp), private :: velConversionFactor
163
type ( state_type ), private :: state ! the current state of the system
165
!*****************************************************************************
166
! private module subroutines
168
private generateMomenta
169
private calculateKineticEnergy
170
private transformCoordinates2Cartesian
171
private transformCoordinates2Lattice
172
private transformForces2Cartesian
173
private transformForces2Lattice
174
private transformMomenta2Cartesian
175
private transformMomenta2Lattice
179
!*****************************************************************************
180
subroutine calculateKineticEnergy( state )
181
!*****************************************************************************
183
! Project: MolecularDynamics
187
! Created on: Wed 27 Jun 17:37:12 2018 by Eduardo R. Hernandez
189
! Last Modified: Wed 18 Jul 17:16:46 2018
192
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
193
! This file is distributed under the terms of the
194
! GNU General Public License: see COPYING in the top directory
195
! or http://www.gnu.org/copyleft/gpl.txt .
198
! Given the momentum contained in state (and if appropriate, any thermostats)
199
! this routine calculates the kinetic energy of the system.
201
!*****************************************************************************
204
!*****************************************************************************
205
! No implicits please!
209
!*****************************************************************************
212
type ( state_type ), intent (INOUT) :: state
214
!*****************************************************************************
219
real (dp) E_kin, factor, prefactor
221
!*****************************************************************************
222
! Start of subroutine
224
if ( debug ) write(*,*) 'Entering calculateKineticEnergy()'
226
! consider the different possible cases regarding thermostats
230
! make sure momenta are in Cartesian coordinates
232
call transformMomenta2Cartesian( state )
234
do i=1, state % nAtoms
236
factor = half / state % mass(i)
238
E_kin = E_kin + factor * &
239
dot_product( state % momentum(1:3,i), state % momentum(1:3,i) )
245
if ( state % nThermostats > 0 ) then ! this is the standard NVE case
247
do n=1, state % nThermostats
249
prefactor = prefactor / state % thermostat(n) % position
253
prefactor = prefactor * prefactor
257
state % energy % kinetic = prefactor * E_kin
259
if ( debug ) write(*,*) 'Exiting calculateKineticEnergy()'
261
end subroutine calculateKineticEnergy
263
!*****************************************************************************
264
subroutine createState( state, nAtoms, &
265
nThermostats, thermostatMass, barostatMass )
266
!*****************************************************************************
268
! Project: MolecularDynamics
272
! Created on: Tue 12 Jun 11:42:03 2018 by Eduardo R. Hernandez
274
! Last Modified: Mon 5 Nov 18:17:18 2018
277
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
278
! This file is distributed under the terms of the
279
! GNU General Public License: see COPYING in the top directory
280
! or http://www.gnu.org/copyleft/gpl.txt .
283
! This subroutine is called to create a new instance of State; the state instance
284
! is allocated, but not "filled"; this must be done by either initialiseState (in
285
! case of a brand new simulation) or by readRestart (in case of a continuation
290
! type ( state_type ), intent (INOUT) :: state
291
! this is the state that is going to be allocated and filled with the data
294
! integer, intent (IN) :: nAtoms
295
! the number of atoms in the system; used to dimension several arrays below
297
! integer, intent (IN), optional :: nThermostats
298
! the number of thermostats in the thermostat chain. For NVE or NPH simulations
299
! that have no thermostat, this variable is either set to zero or absent (default = 0);
300
! for simulations with a thermostat or a thermostat chain (NVT, NPT), nThermostats
301
! is a positive integer indicating the number of Nosé-Poincaré thermostats in the
304
! real (dp), dimension (:), intent (IN), optional :: thermostatMass
305
! if nThermostats > 0, thermostatMass is an array of length nThermostats providing the
306
! masses of each thermostat in the chain, in Daltons (1/12 of the mass of C12)
308
! real (dp), intent (IN), optional :: barostatMass
309
! if the simulation is a constant-pressure one, this specifies the mass of the barostat
310
! in Daltons (1/12 of the mass of C12)
312
!*****************************************************************************
315
!*****************************************************************************
316
! No implicits please!
320
!*****************************************************************************
323
type ( state_type ), intent (INOUT) :: state
325
integer, intent (IN) :: nAtoms
327
integer, intent (IN), optional :: nThermostats
329
real (dp), dimension (:), intent (IN), optional :: thermostatMass
330
real (dp), intent (IN), optional :: barostatMass
332
!*****************************************************************************
337
real (dp), dimension (3,3) :: LatticeVectors
339
real (dp), allocatable, dimension (:,:) :: momentum
341
!*****************************************************************************
344
if ( debug ) write(*,*) 'Entering createState()'
346
! assign nAtoms and allocate variables that depend on it
348
state % nAtoms = nAtoms
349
state % nDegreesOfFreedom = 3 * state % nAtoms - 3
351
allocate( state % position( 3, state % nAtoms ) )
352
allocate( state % force( 3, state % nAtoms ) )
353
allocate( state % momentum( 3, state % nAtoms ) )
354
allocate( state % mass( state % nAtoms ) )
356
if ( present( nThermostats ) ) then
358
state % nThermostats = nThermostats
360
allocate( state % thermostat( nThermostats ) )
362
do i = 1, state % nThermostats
363
state % thermostat(i) % mass = massConversionFactor * thermostatMass(i)
364
state % thermostat(i) % position = one
365
state % thermostat(i) % momentum = zero
366
state % thermostat(i) % a = one
367
state % thermostat(i) % C = one
368
write(*,*) 'thermostat mass ', i, state % thermostat(i) % mass
373
state % nThermostats = 0 ! no thermostat is defined
377
if ( present( barostatMass ) ) then
379
state % barostat % mass = massConversionFactor * barostatMass
381
state % barostat % momentum = zero
385
! these are initialised to zero; they will be set prorperly if needed later
387
state % energy % thermostat = zero
388
state % energy % barostat = zero
390
state % H0 % set = .false.
391
state % H0 % E = zero
393
if ( debug ) write(*,*) 'Exiting createState'
395
end subroutine createState
397
!*****************************************************************************
398
subroutine deleteState( state )
399
!*****************************************************************************
401
! Project: MolecularDynamics
405
! Created on: Thu 19 Jul 11:28:36 2018 by Eduardo R. Hernandez
407
! Last Modified: Fri 2 Nov 17:27:20 2018
410
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
411
! This file is distributed under the terms of the
412
! GNU General Public License: see COPYING in the top directory
413
! or http://www.gnu.org/copyleft/gpl.txt .
416
! type ( state_type ), intent (INOUT) :: state
417
! this is the state that is going to be deallocated.
419
!*****************************************************************************
422
!*****************************************************************************
423
! No implicits please!
427
!*****************************************************************************
430
type ( state_type ), intent (INOUT) :: state
432
!*****************************************************************************
435
!*****************************************************************************
438
if ( debug ) write(*,*) 'Entering deleteState()'
440
deallocate( state % position )
441
deallocate( state % force )
442
deallocate( state % momentum )
443
deallocate( state % mass )
444
if ( state % nThermostats .gt. 0 ) deallocate( state % thermostat )
446
if ( debug ) write(*,*) 'Exiting deleteState'
448
end subroutine deleteState
450
!*****************************************************************************
451
subroutine generateMomenta( state, target_temperature )
452
!*****************************************************************************
454
! Project: MolecularDynamics
456
! Created on: Wed 11 Apr 12:27:49 2018 by Eduardo R. Hernandez
458
! Last Modified: Thu 26 Jul 16:37:05 2018
461
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
462
! This file is distributed under the terms of the
463
! GNU General Public License: see COPYING in the top directory
464
! or http://www.gnu.org/copyleft/gpl.txt .
467
!*****************************************************************************
470
!*****************************************************************************
471
! No implicits please!
475
!*****************************************************************************
478
type ( state_type ), intent (INOUT) :: state
480
real (dp), intent (IN) :: target_temperature
482
!**************************************************************************
487
real (dp) :: r, r2, rnum, total_mass, variance, v1, v2
488
real (dp) :: determinant, determinant_1, E_kin, factor, temperature
490
real (dp) :: angular_momentum( 3 ), angular_velocity( 3 )
491
real (dp) :: centre_of_mass( 3 )
492
real (dp) :: cm_velocity( 3 )
493
real (dp) :: inertia_tensor(3,3)
494
real (dp) :: matrix(3,3)
496
!**************************************************************************
497
! Start of subroutine
499
if ( debug ) write(*,*) 'Entering generateMomenta()'
503
! loop over atoms and assign each atom a random velocity
504
! according to its mass and the target temperature
508
do i=1, state % nAtoms
510
total_mass = total_mass + state % mass(i)
511
variance = dsqrt( boltzmann_k * target_temperature / state % mass(i) )
516
do while ( r .gt. one )
517
call random_number( rnum )
518
v1 = two * rnum - one
519
call random_number( rnum )
520
v2 = two * rnum - one
521
r = v1 * v1 + v2 * v2
523
r = variance * v1 * sqrt( -two * log( r ) / r )
524
state % momentum(n,i) = state % mass(i) * r
528
! now calculate the amount of velocity to take out for each atom
531
cm_velocity( n ) = zero
532
do i=1, state % nAtoms
533
cm_velocity(n) = cm_velocity(n) + state % momentum(n,i)
535
cm_velocity(n) = cm_velocity(n) / total_mass
538
! now substract from each atom the velocity necessary so as
539
! to ensure that the total momentum is zero
542
do i=1, state % nAtoms
543
state % momentum(n,i) = state % momentum(n,i) - &
544
state % mass(i) * cm_velocity(n)
548
! calculate the instantaneous temperature
552
do i=1, state % nAtoms
554
factor = half / state % mass(i)
556
E_kin = E_kin + factor * ( &
557
dot_product( state % momentum(1:3,i), state % momentum(1:3,i) ) )
561
temperature = two * E_kin / ( ( three * dfloat(state % nAtoms) - three ) * boltzmann_k )
563
! calculate the scaling factor and scale the velocities accordingly
565
write(*,*) 'temperature = ', temperature, target_temperature
567
factor = dsqrt( target_temperature / temperature )
569
state % momentum = factor * state % momentum
573
do i=1, state % nAtoms
575
factor = half / state % mass(i)
577
E_kin = E_kin + factor * ( &
578
dot_product( state % momentum(1:3,i), state % momentum(1:3,i) ) )
582
temperature = two * E_kin / ( ( three * dfloat(state % nAtoms) - three ) * boltzmann_k )
587
do i=1, state % nAtoms
588
cm_velocity(n) = cm_velocity(n) + state % momentum(n,i)
590
cm_velocity(n) = cm_velocity(n) / total_mass
593
write(*,*) 'centre of mass velocity = ', cm_velocity(1:3), temperature
594
write(*,*) 'kinetic energy = ', E_kin
595
write(*,*) 'momentum 1 ', state % momentum(1:3,1)
597
! if the system is not periodic in any direction (i.e. cluster or molecule)
598
! then we must make sure that it does have zero angular momentum (no rotation)
600
if ( .not. PBC ) then
602
! we will refer momentarily the positions with respect to the centre of mass
604
centre_of_mass = zero
606
do i=1, state % nAtoms
608
centre_of_mass(1) = centre_of_mass(1) + &
609
state % mass(i) * state % position(1,i)
610
centre_of_mass(2) = centre_of_mass(2) + &
611
state % mass(i) * state % position(2,i)
612
centre_of_mass(3) = centre_of_mass(3) + &
613
state % mass(i) * state % position(3,i)
617
centre_of_mass = centre_of_mass / total_mass
619
state % position(1,1:state % nAtoms) = &
620
state % position(1,1:state % nAtoms) - centre_of_mass(1)
621
state % position(2,1:state % nAtoms) = &
622
state % position(2,1:state % nAtoms) - centre_of_mass(2)
623
state % position(3,1:state % nAtoms) = &
624
state % position(3,1:state % nAtoms) - centre_of_mass(3)
626
angular_momentum = zero
627
inertia_tensor = zero
629
do i=1, state % nAtoms
631
angular_momentum(1) = angular_momentum(1) + &
632
( state % position(2,i) * state % momentum(3,i) - &
633
state % position(3,i) * state % momentum(2,i) )
634
angular_momentum(2) = angular_momentum(2) + &
635
( state % position(3,i) * state % momentum(1,i) - &
636
state % position(1,i) * state % momentum(3,i) )
637
angular_momentum(3) = angular_momentum(3) + &
638
( state % position(1,i) * state % momentum(2,i) - &
639
state % position(2,i) * state % momentum(1,i) )
641
r2 = dot_product( state % position(1:3,i), state % position(1:3,i))
643
inertia_tensor(1,1) = inertia_tensor(1,1) + state % mass(i) * &
644
( r2 - state % position(1,i) * state % position(1,i) )
645
inertia_tensor(1,2) = inertia_tensor(1,2) - state % mass(i) * &
646
state % position(1,i) * state % position(2,i)
647
inertia_tensor(1,3) = inertia_tensor(1,3) - state % mass(i) * &
648
state % position(1,i) * state % position(3,i)
650
inertia_tensor(2,1) = inertia_tensor(2,1) - state % mass(i) * &
651
state % position(2,i) * state % position(1,i)
652
inertia_tensor(2,2) = inertia_tensor(2,2) + state % mass(i) * &
653
( r2 - state % position(2,i) * state % position(2,i) )
654
inertia_tensor(2,3) = inertia_tensor(2,3) - state % mass(i) * &
655
state % position(2,i) * state % position(3,i)
657
inertia_tensor(3,1) = inertia_tensor(3,1) - state % mass(i) * &
658
state % position(3,i) * state % position(1,i)
659
inertia_tensor(3,2) = inertia_tensor(3,2) - state % mass(i) * &
660
state % position(3,i) * state % position(2,i)
661
inertia_tensor(3,3) = inertia_tensor(3,3) + state % mass(i) * &
662
( r2 - state % position(3,i) * state % position(3,i) )
666
determinant = inertia_tensor(1,1) * ( &
667
inertia_tensor(2,2) * inertia_tensor(3,3) - &
668
inertia_tensor(2,3) * inertia_tensor(3,2) ) - &
669
inertia_tensor(1,2) * ( &
670
inertia_tensor(2,1) * inertia_tensor(3,3) - &
671
inertia_tensor(2,3) * inertia_tensor(3,1) ) + &
672
inertia_tensor(1,3) * ( &
673
inertia_tensor(2,1) * inertia_tensor(3,2) - &
674
inertia_tensor(2,2) * inertia_tensor(3,1) )
676
! calculate the components of the angular velocity
678
matrix = inertia_tensor
679
matrix(1:3,1) = angular_momentum
681
determinant_1 = matrix(1,1) * ( &
682
matrix(2,2) * matrix(3,3) - matrix(2,3) * matrix(3,2) ) - &
684
matrix(2,1) * matrix(3,3) - matrix(2,3) * matrix(3,1) ) + &
686
matrix(2,1) * matrix(3,2) - matrix(2,2) * matrix(3,1) )
688
angular_velocity(1) = determinant_1 / determinant
690
matrix = inertia_tensor
691
matrix(1:3,2) = angular_momentum
693
determinant_1 = matrix(1,1) * ( &
694
matrix(2,2) * matrix(3,3) - matrix(2,3) * matrix(3,2) ) - &
696
matrix(2,1) * matrix(3,3) - matrix(2,3) * matrix(3,1) ) + &
698
matrix(2,1) * matrix(3,2) - matrix(2,2) * matrix(3,1) )
700
angular_velocity(2) = determinant_1 / determinant
702
matrix = inertia_tensor
703
matrix(1:3,3) = angular_momentum
705
determinant_1 = matrix(1,1) * ( &
706
matrix(2,2) * matrix(3,3) - matrix(2,3) * matrix(3,2) ) - &
708
matrix(2,1) * matrix(3,3) - matrix(2,3) * matrix(3,1) ) + &
710
matrix(2,1) * matrix(3,2) - matrix(2,2) * matrix(3,1) )
712
angular_velocity(3) = determinant_1 / determinant
714
angular_velocity = -angular_velocity
716
do i=1, state % nAtoms
718
state % momentum(1,i) = state % momentum(1,i) + &
719
state % mass(i) * ( &
720
state % position(3,i) * angular_velocity(2) - &
721
state % position(2,i) * angular_velocity(3) )
723
state % momentum(2,i) = state % momentum(2,i) + &
724
state % mass(i) * ( &
725
state % position(1,i) * angular_velocity(3) - &
726
state % position(3,i) * angular_velocity(1) )
728
state % momentum(3,i) = state % momentum(3,i) + &
729
state % mass(i) * ( &
730
state % position(2,i) * angular_velocity(1) - &
731
state % position(1,i) * angular_velocity(2) )
737
angular_momentum = zero
739
do i=1, state % nAtoms
741
angular_momentum(1) = angular_momentum(1) + &
742
( state % position(2,i) * state % momentum(3,i) - &
743
state % position(3,i) * state % momentum(2,i) )
744
angular_momentum(2) = angular_momentum(2) + &
745
( state % position(3,i) * state % momentum(1,i) - &
746
state % position(1,i) * state % momentum(3,i) )
747
angular_momentum(3) = angular_momentum(3) + &
748
( state % position(1,i) * state % momentum(2,i) - &
749
state % position(2,i) * state % momentum(1,i) )
753
write(*,*) 'angular momentum components ', angular_momentum(1:3)
755
state % position(1,1:state % nAtoms) = &
756
state % position(1,1:state % nAtoms) + centre_of_mass(1)
757
state % position(2,1:state % nAtoms) = &
758
state % position(2,1:state % nAtoms) + centre_of_mass(2)
759
state % position(3,1:state % nAtoms) = &
760
state % position(3,1:state % nAtoms) + centre_of_mass(3)
764
! finally, calculate the kinetic energy and store it in type energy
768
do i=1, state % nAtoms
770
factor = half / state % mass(i)
772
E_kin = E_kin + factor * ( &
773
dot_product( state % momentum(1:3,i), state % momentum(1:3,i) ) )
777
state % energy % kinetic = E_kin
779
state % representation % momentum = .true. ! momenta are in cartesian rep.
781
if ( debug ) write(*,*) 'Exiting generateMomenta()'
783
end subroutine generateMomenta
785
!*****************************************************************************
786
subroutine get( state, nAtoms, nDegreesOfFreedom, nThermostats, &
787
position, force, momentum, mass, &
788
thermostat, barostat, energy, H0, &
789
Cell, reciprocalCell, stress, representation )
790
!*****************************************************************************
792
! Project: MolecularDynamics
796
! Created on: Fri 8 Jun 14:53:35 2018 by Eduardo R. Hernandez
798
! Last Modified: Mon 5 Nov 18:16:11 2018
801
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
802
! This file is distributed under the terms of the
803
! GNU General Public License: see COPYING in the top directory
804
! or http://www.gnu.org/copyleft/gpl.txt .
807
! This subroutine extracts from an object of type State_type specific values
808
! as requested by the caller. The first variable, which is mandatory, is the
809
! state object being interrogated. Then follows a keyword-list of desired
810
! values (temperature, pressure, etc), all of which are optional, that are
811
! returned upon request.
813
!*****************************************************************************
816
!*****************************************************************************
817
! No implicits please!
821
!*****************************************************************************
824
type ( state_type ), intent (INOUT) :: state ! the state being interrogated
826
integer, intent (OUT), optional :: nAtoms
827
integer, intent (OUT), optional :: nDegreesOfFreedom
828
integer, intent (OUT), optional :: nThermostats
830
real (dp), intent (OUT), optional :: H0
832
real (dp), dimension (:,:), intent (OUT), optional :: position
833
real (dp), dimension (:,:), intent (OUT), optional :: force
834
real (dp), dimension (:,:), intent (OUT), optional :: momentum
835
real (dp), dimension (:), intent (OUT), optional :: mass
837
type ( thermostat_type ), dimension (:), intent (OUT), optional :: thermostat
838
type ( barostat_type ), intent (OUT), optional :: barostat
840
type ( energy_type ), intent (OUT), optional :: energy
842
type ( lattice_type ), intent (OUT), optional :: Cell
843
type ( lattice_type ), intent (OUT), optional :: reciprocalCell
845
type ( stress_type ), intent (OUT), optional :: stress
847
type ( representation_type ), intent (IN), optional :: representation
849
!*****************************************************************************
854
!*****************************************************************************
855
! start of subroutine
857
if ( debug ) write(*,*) 'Entering get()'
859
if ( present( nAtoms ) ) then
861
nAtoms = state % nAtoms
865
if ( present( nDegreesOfFreedom ) ) then
867
nDegreesOfFreedom = state % nDegreesOfFreedom
871
if ( present( nThermostats ) ) then
873
nThermostats = state % nThermostats
877
if ( present( position ) ) then
879
if ( present( representation ) ) then
881
if ( representation % position ) then ! coordinates are needed in cartesian rep.
883
call transformCoordinates2Cartesian( state )
885
else ! coordinates are needed in lattice rep.
887
call transformCoordinates2Lattice( state )
891
else ! default; make sure they are in cartesian
893
call transformCoordinates2Cartesian( state )
897
position = state % position
901
if ( present( force ) ) then
903
if ( present( representation ) ) then
905
if ( representation % force ) then ! forces are needed in cartesian rep.
907
call transformForces2Cartesian( state )
909
else ! forces are needed in lattice rep.
911
call transformForces2Lattice( state )
915
else ! default, we return them in cartesian, so make sure they are in that rep.
917
call transformForces2Cartesian( state )
921
force = state % force ! copy forces
925
if ( present( momentum ) ) then
927
if ( present( representation ) ) then
929
if ( representation % momentum ) then ! momenta are needed in cartesian rep.
931
call transformMomenta2Cartesian( state )
933
else ! momenta are needed in lattice rep.
935
call transformMomenta2Lattice( state )
939
else ! default case, we return them in cartesian
941
call transformMomenta2Cartesian( state )
945
momentum = state % momentum ! copy momenta
949
if ( present( mass ) ) then
955
if ( present( thermostat ) ) then
957
do i = 1, state % nThermostats
959
thermostat(i) = state % thermostat(i)
965
if ( present( barostat ) ) then
967
barostat = state % barostat
971
if ( present( energy ) ) then
973
energy = state % energy
977
if ( present( H0 ) ) then
983
if ( present( Cell ) ) then
989
if ( present( reciprocalCell ) ) then
991
reciprocalCell = state % reciprocalCell
995
if ( present( stress ) ) then
997
stress = state % stress
1001
if ( debug ) write(*,*) 'Exiting get()'
1005
!*****************************************************************************
1006
subroutine getConfiguration( state, nAtoms, a, b, c, position, lattice )
1007
!*****************************************************************************
1009
! Project: MolecularDynamics
1013
! Created on: Wed 13 Jun 18:04:27 2018 by Eduardo R. Hernandez
1015
! Last Modified: Wed 18 Jul 17:12:54 2018
1018
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1019
! This file is distributed under the terms of the
1020
! GNU General Public License: see COPYING in the top directory
1021
! or http://www.gnu.org/copyleft/gpl.txt .
1024
! This subroutine is designed as a means of communicating with the client
1025
! program; the latter will need to be told the lattice vectors and atom positions
1026
! in units that it understands. Lattice vectors and ionic positions are
1027
! privately held by state, and are thus directly not accessible to the
1028
! client program. This subroutine provides, given an instance of state, the
1029
! lattice vectors a, b, c and the ionic positions, in the chosen length
1030
! units of the client program. Optionally, atomic positions can be returned
1031
! in lattice coordinates, by appropriately setting the optional flag Lattice
1034
!*****************************************************************************
1037
!*****************************************************************************
1038
! No implicits please!
1042
!*****************************************************************************
1045
type ( state_type ), intent (INOUT) :: state
1047
integer , intent (OUT) :: nAtoms
1049
real (dp), dimension (3), intent (OUT) :: a
1050
real (dp), dimension (3), intent (OUT) :: b ! the three lattice vectors
1051
real (dp), dimension (3), intent (OUT) :: c
1053
real (dp), dimension ( 3, state % nAtoms ), intent (OUT) :: position
1055
logical, optional, intent (IN) :: lattice
1057
!*****************************************************************************
1060
!*****************************************************************************
1061
! start of subroutine
1063
if ( debug ) write(*,*) 'Entering getConfiguration()'
1065
! convert lattice vectors to client program length units
1067
a = lengthConversionFactor * state % Cell % a
1068
b = lengthConversionFactor * state % Cell % b
1069
c = lengthConversionFactor * state % Cell % c
1071
! the number of atoms
1073
nAtoms = state % nAtoms
1075
! now atomic coordinates
1077
if ( present( lattice ) ) then ! check if client wants coordinates in lattice rep.
1081
call transformCoordinates2Lattice( state ) ! make sure they are in lattice rep.
1083
position = state % position
1087
call transformCoordinates2Cartesian( state ) ! make sure they are in cartesian rep.
1089
position = lengthConversionFactor * state % position
1093
else ! the default case is that coordinates are returned in Cartesian rep.
1095
call transformCoordinates2Cartesian( state ) ! make sure they are in cartesian rep.
1097
position = lengthConversionFactor * state % position
1101
if ( debug ) write(*,*) 'Exiting getConfiguration()'
1103
end subroutine getConfiguration
1105
!*****************************************************************************
1106
subroutine initialiseState( state, &
1108
mass, position, temperature, velocity, lattice, &
1110
!*****************************************************************************
1112
! Project: MolecularDynamics
1116
! Created on: Fri 2 Nov 15:55:03 2018 by Eduardo R. Hernandez
1118
! Last Modified: Fri 2 Nov 16:17:40 2018
1121
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1122
! This file is distributed under the terms of the
1123
! GNU General Public License: see COPYING in the top directory
1124
! or http://www.gnu.org/copyleft/gpl.txt .
1127
! This subroutine is called to "fill" an empty but allocated instance of State
1128
! with state information (atom coordinates, cell parameters, etc)
1132
! type ( state_type ), intent (INOUT) :: state
1133
! this is the state that is going to be allocated and filled with the data
1136
! integer, intent (IN) :: nAtoms
1137
! the number of atoms in the system; used to dimension several arrays below
1139
! real (dp), dimension (3), intent (IN) :: a, b, c
1140
! the lattice vectors of the simulation cell
1142
! real (dp), dimension (:), intent (IN) :: mass
1143
! an array of dimension (nAtoms) containing the masses of all atoms in
1144
! Daltons (1/12 of the mass of C12)
1146
! real (dp), dimension (:,:), intent (IN) :: position
1147
! an array of dimension (3,nAtoms) containing the coordinates of atoms;
1148
! if the optional flag 'lattice' (see below) is passed as .true., these
1149
! are assumed to be passed in lattice representation (x,y,z in [0,10])
1151
! real (dp), intent(IN), optional :: temperature
1152
! the temperature of the simulation; the user can provide either the simulation
1153
! temperature (in which case random initial momenta are generated according to
1154
! the Maxwel-Boltzmann distribution at that temperature), or else a set of
1155
! initial velocities (see next entry)
1157
! real (dp), dimension (:,:), intent (IN), optional :: velocity
1158
! optionally, the client program can pass initial velocities to be used
1159
! in the construction of the momenta that are used internally; if absent,
1160
! random momental will be sampled from the Maxwell-Boltzmann distribution
1161
! corresponding to the temperature of the simulation. If provided, velocities
1162
! must be in units compatible with the position; also note that if the flag
1163
! 'lattice' is set to .true., the velocities must also be in this representation,
1164
! to be compatible with the atomic coordinates (see position, above)
1166
! logical, intent (IN), optional :: lattice
1167
! if .true., this variable indicates that coordinates (position) and velocity are
1168
! given in lattice representation. If set to .false. (or absent), it is assumed
1169
! that coordinates (and velocities) are in Cartesian representation in units
1170
! of the client program.
1172
! logical, intent (IN), optional :: periodic
1173
! if .true. (default) this indicates that periodic boundary conditions will be
1174
! imposed; if .false. then a cluster geometry is assumed. The only relevance of this
1175
! here is that in the latter case the momenta are generated such that not only the
1176
! total linear momentum is zero, but also the total angular momentum is zero, to
1177
! avoid whole-cluster rotation, which makes analysis more cumbersome.
1179
!*****************************************************************************
1182
!*****************************************************************************
1183
! No implicits please!
1187
!*****************************************************************************
1190
type ( state_type ), intent (INOUT) :: state
1192
real (dp), dimension (3), intent (IN) :: a ! lattice vectors in
1193
real (dp), dimension (3), intent (IN) :: b ! length units of the
1194
real (dp), dimension (3), intent (IN) :: c ! client program
1196
real (dp), dimension (:), intent (IN) :: mass
1197
real (dp), dimension (:,:), intent (IN) :: position
1199
real (dp), intent (IN), optional :: temperature
1200
real (dp), dimension (:,:), intent (IN), optional :: velocity
1202
logical, intent (IN), optional :: lattice
1203
logical, intent (IN), optional :: periodic
1205
!*****************************************************************************
1210
real (dp), dimension (3,3) :: LatticeVectors
1212
real (dp), allocatable, dimension (:,:) :: momentum
1214
!*****************************************************************************
1217
if ( debug ) write(*,*) 'Entering initialiseState()'
1221
LatticeVectors(1:3,1) = lengthConversionFactor * a
1222
LatticeVectors(1:3,2) = lengthConversionFactor * b
1223
LatticeVectors(1:3,3) = lengthConversionFactor * c
1225
call updateCell( state % Cell, state % reciprocalCell, LatticeVectors = LatticeVectors )
1227
! store masses internally
1229
state % mass = massConversionFactor * mass
1231
! now the atomic positions
1233
if ( present( lattice ) ) then
1235
if ( lattice ) then ! coordinates are in lattice representation
1237
state % position = position
1238
state % representation % position = .false.
1242
state % position = lengthConversionFactor * position
1243
state % representation % position = .true.
1249
state % position = lengthConversionFactor * position
1250
state % representation % position = .true.
1254
if ( present( periodic ) ) then
1264
if ( present( temperature ) .and. ( .not. present( velocity ) ) ) then
1266
call generateMomenta( state, temperature )
1268
else if ( present( velocity ) ) then
1270
if ( present( lattice ) ) then
1272
if ( lattice ) then ! velocities are in lattice units
1274
allocate( momentum( 3, state % nAtoms ) )
1276
do i = 1, state % nAtoms
1277
momentum(1:3,i) = state % mass(i) * velocity(1:3,i)
1280
state % momentum = momentum
1281
state % representation % momentum = .false.
1283
deallocate( momentum )
1287
do i = 1, state % nAtoms
1288
state % momentum(1:3,i) = &
1289
velConversionFactor * state % mass(i) * velocity(1:3,i)
1292
state % representation % momentum = .true. ! cartesian rep. for momenta
1296
else ! lattice not present, so Cartesian
1298
do i = 1, state % nAtoms
1299
state % momentum(1:3,i) = &
1300
state % mass(i) * velocity(1:3,i)
1301
!velConversionFactor * state % mass(i) * velocity(1:3,i)
1304
state % representation % momentum = .true. ! cartesian rep. for momenta
1308
! write(*,*) 'velConversionFactor = ', velConversionFactor
1309
! write(*,*) 'vel in createState ', velocity(1:3,1)
1310
! write(*,*) 'createState ', state % momentum(1:3,1)
1314
if ( debug ) write(*,*) 'Exiting initialiseState'
1316
end subroutine initialiseState
1318
!*****************************************************************************
1319
subroutine inquire( state, temperature, pressure, stress, &
1320
kineticEnergy, potentialEnergy, thermostatEnergy, &
1321
barostatEnergy, constantOfMotion )
1322
!*****************************************************************************
1324
! Project: MolecularDynamics
1328
! Created on: Fri 27 Apr 12:15:38 2018 by Eduardo R. Hernandez
1330
! Last Modified: Fri 29 Jun 16:43:24 2018
1333
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1334
! This file is distributed under the terms of the
1335
! GNU General Public License: see COPYING in the top directory
1336
! or http://www.gnu.org/copyleft/gpl.txt .
1339
! This subroutine inquires state to obtain properties of the current system
1340
! configuration, such as the temperature, pressure, or different energy
1341
! components. Properties are output in the chosen units of the client program.
1343
!*****************************************************************************
1346
!*****************************************************************************
1347
! No implicits please!
1351
!*****************************************************************************
1354
type ( state_type ), intent (INOUT) :: state
1356
real (dp), intent (OUT), optional :: temperature
1357
real (dp), intent (OUT), optional :: pressure
1358
real (dp), intent (OUT), dimension (3,3), optional :: stress
1359
real (dp), intent (OUT), optional :: kineticEnergy
1360
real (dp), intent (OUT), optional :: potentialEnergy
1361
real (dp), intent (OUT), optional :: thermostatEnergy
1362
real (dp), intent (OUT), optional :: barostatEnergy
1363
real (dp), intent (OUT), optional :: constantOfMotion
1365
!*****************************************************************************
1373
!*****************************************************************************
1374
! start of subroutine
1376
if ( debug ) write(*,*) 'Entering inquire()'
1378
! make sure that the kinetic energy is consistent with current momenta
1380
call calculateKineticEnergy( state )
1382
if ( present( temperature ) ) then
1384
temperature = two * state % energy % kinetic / ( state % nDegreesOfFreedom * boltzmann_k )
1388
if ( present ( pressure ) ) then
1392
if ( present( stress ) ) then
1394
stress = pressureConversionFactor * state % stress % cartesian
1398
if ( present( kineticEnergy ) ) then
1400
kineticEnergy = energyConversionFactor * state % energy % kinetic
1404
if ( present( potentialEnergy ) ) then
1406
potentialEnergy = energyConversionFactor * state % energy % potential
1410
if ( present( thermostatEnergy ) ) then
1412
thermostatEnergy = energyConversionFactor * state % energy % thermostat
1416
if ( present( barostatEnergy ) ) then
1418
barostatEnergy = energyConversionFactor * state % energy % barostat
1422
if ( present( constantOfMotion ) ) then
1424
constantOfMotion = energyConversionFactor * state % energy % constantOfMotion
1428
if ( debug ) write(*,*) 'Exiting inquire()'
1430
end subroutine inquire
1432
!*****************************************************************************
1433
subroutine set( state, H, G, &
1434
position, force, momentum, mass, &
1435
thermostat, barostat, energy, &
1436
Cell, reciprocalCell, representation )
1437
!*****************************************************************************
1439
! Project: MolecularDynamics
1443
! Created on: Fri 8 Jun 14:32:53 2018 by Eduardo R. Hernandez
1445
! Last Modified: Tue 6 Nov 09:38:52 2018
1448
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1449
! This file is distributed under the terms of the
1450
! GNU General Public License: see COPYING in the top directory
1451
! or http://www.gnu.org/copyleft/gpl.txt .
1454
! This subroutine has the purpose of setting the values of variables contained
1455
! in an instance of State to new numerical values. An object of type State
1456
! must be passed as first argument; the remaining arguments are optional and
1457
! identified by keyword, so that a single variable, a subset or the whole set
1458
! can be specified in one go. The updated State object is then returned.
1460
!*****************************************************************************
1463
!*****************************************************************************
1464
! No implicits please!
1468
!*****************************************************************************
1471
type ( state_type ), intent (INOUT) :: state ! the state being modified
1473
real (dp), dimension (3,3), intent (IN), optional :: H ! the lattice vectors (one per row)
1474
real (dp), dimension (3,3), intent (IN), optional :: G ! the metric tensor
1476
real (dp), dimension ( 3, state % nAtoms ), intent (IN), optional :: position
1477
real (dp), dimension ( 3, state % nAtoms ), intent (IN), optional :: force
1478
real (dp), dimension ( 3, state % nAtoms ), intent (IN), optional :: momentum
1479
real (dp), dimension ( state % nAtoms ), intent (IN), optional :: mass
1481
type (thermostat_type), dimension ( state % nThermostats ), intent (IN), optional :: thermostat
1482
type (barostat_type), intent (IN), optional :: barostat
1484
type (energy_type), intent (IN), optional :: energy
1486
type (lattice_type), intent (IN), optional :: Cell
1487
type (lattice_type), intent (IN), optional :: reciprocalCell
1489
type (representation_type), intent (IN), optional :: representation
1491
!*****************************************************************************
1496
!*****************************************************************************
1499
if ( debug ) write(*,*) 'Entering set()'
1501
! the user must provide either cell vectors or metric tensor, but not both,
1502
! hence the if-then-else
1504
if ( present( H ) ) then
1506
call updateCell( state % Cell, state % reciprocalCell, LatticeVectors = H )
1508
else if ( present( G ) ) then
1510
call updateCell( state % Cell, state % reciprocalCell, MetricTensor = G )
1514
if ( present( position ) ) then
1516
if ( present( representation ) ) then
1518
if ( representation % position ) then
1520
state % representation % position = .true. ! coordinates are input in cartesian rep.
1524
state % representation % position = .false. ! coordinates are input in lattice rep.
1528
else ! default case; it is assumed coordinates provided in cartesian
1530
state % representation % position = .true.
1534
state % position = position
1538
if ( present( force ) ) then
1540
if ( present( representation ) ) then
1542
if ( representation % force ) then
1544
state % representation % force = .true. ! forces are input in cartesian rep.
1548
state % representation % force = .false. ! they are in lattice rep.
1554
state % representation % force = .true. ! default, they are in cartesian
1558
state % force = force
1562
if ( present( momentum ) ) then
1564
if ( present( representation ) ) then
1566
if ( representation % momentum ) then
1568
state % representation % momentum = .true. ! momenta are input in cartesian rep.
1572
state % representation % momentum = .false. ! nope, they are in lattice rep.
1578
state % representation % momentum = .true. ! default case, they are in cartesian
1582
state % momentum = momentum
1586
if ( present( mass ) ) state % mass = mass
1588
if ( present( thermostat ) ) then
1590
do n = 1, state % nThermostats
1591
state % thermostat(n) = thermostat(n)
1596
if ( present( barostat ) ) then
1598
state % barostat = barostat
1602
if ( present( energy ) ) then
1604
state % energy = energy
1606
if ( .not. state % H0 % set ) then
1608
state % H0 % E = state % energy % kinetic + state % energy % potential + &
1609
state % energy % barostat + state % energy % thermostat
1611
state % H0 % set = .true.
1617
if ( present( Cell ) ) then
1623
if ( present( reciprocalCell ) ) then
1625
state % reciprocalCell = reciprocalCell
1629
if ( debug ) write(*,*) 'Exiting set()'
1633
!*****************************************************************************
1634
subroutine setForce( state, potential_energy, force, stress, lattice )
1635
!*****************************************************************************
1637
! Project: MolecularDynamics
1641
! Created on: Thu 14 Jun 09:33:11 2018 by Eduardo R. Hernandez
1643
! Last Modified: Thu 26 Jul 17:16:33 2018
1646
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1647
! This file is distributed under the terms of the
1648
! GNU General Public License: see COPYING in the top directory
1649
! or http://www.gnu.org/copyleft/gpl.txt .
1652
! This subroutine receives the forces, and optionally the stress tensor, as
1653
! calculated by the client program, and stores this information in State.
1654
! It is assumed that force and stress information are input in Cartesian
1655
! representation. The client program will normally pass the forces in
1656
! Cartesian representation, but if the optional flag lattice is set tot .true.,
1657
! then it is understood that forces are passed in lattice representation.
1659
!*****************************************************************************
1662
!*****************************************************************************
1663
! No implicits please!
1667
!*****************************************************************************
1670
type ( state_type ), intent (INOUT) :: state
1672
real (dp), intent (IN) :: potential_energy
1673
real (dp), dimension ( 3, state % nAtoms ), intent (IN) :: force
1674
real (dp), dimension ( 3, 3 ), intent (IN), optional :: stress
1676
logical, intent (IN), optional :: lattice
1678
!*****************************************************************************
1681
real (dp), dimension ( 3, 3 ) :: matrix_a
1682
real (dp), dimension ( 3, 3 ) :: matrix_b
1684
!*****************************************************************************
1685
! start of subroutine
1687
if ( debug ) write(*,*) 'Entering setForce()'
1689
state % energy % potential = potential_energy / energyConversionFactor
1691
if ( present( lattice ) ) then
1693
if ( lattice ) then ! forces are given in lattice rep;
1694
! TODO: make sure conversion factor
1695
! is right in this case
1696
state % representation % force = .false.
1700
state % representation % force = .true. ! cartesian
1706
state % representation % force = .true.
1710
state % force = force / forceConversionFactor
1712
! if stress has been passed, convert it too
1714
if ( present( stress ) ) then
1716
! state % stress % cartesian = stress / pressureConversionFactor
1717
state % stress % cartesian = stress
1719
matrix_a(1:3,1) = state % reciprocalCell % a
1720
matrix_a(1:3,2) = state % reciprocalCell % b
1721
matrix_a(1:3,3) = state % reciprocalCell % c
1723
matrix_b = matmul( state % stress % cartesian, matrix_a )
1725
state % stress % lattice = half * matmul( transpose( matrix_a ), matrix_b )
1729
state % stress % cartesian = zero
1730
state % stress % lattice = zero
1734
if ( debug ) write(*,*) 'Exiting setForce()'
1736
end subroutine setForce
1738
!*****************************************************************************
1739
subroutine setUnits( length, energy, pressure )
1740
!*****************************************************************************
1742
! Project: MolecularDynamics
1746
! Created on: Thu 14 Jun 11:22:27 2018 by Eduardo R. Hernandez
1748
! Last Modified: Mon 25 Jun 18:00:04 2018
1751
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1752
! This file is distributed under the terms of the
1753
! GNU General Public License: see COPYING in the top directory
1754
! or http://www.gnu.org/copyleft/gpl.txt .
1757
! This subroutine is called once at the begining, and its purpose is to
1758
! set a number of unit conversion factors in order to manage communication
1759
! to/from the client program. The idea is that both the State type and
1760
! the routines in the MolecularDynamics module work with the same unit system,
1761
! namely atomic units (Bohr, Hartree, etc); the client program will probably
1762
! use other units (typical choices are Angstrom, eV, etc), so we must
1763
! cater for the appropriate conversion factors.
1765
!!!!!!!!!!!!!!! MANDATORY ARGUMENTS !!!!!!!!!!!!!!!
1767
! length (INT): 0 specifies client length unit is bohr (atomic unit)
1768
! 1 client length unit is Angstrom
1770
! energy (INT): 0 specifies client energy unit is hartree (atomic unit)
1771
! 1 specifies client energy unit is rydberg
1772
! 2 specifies client energy unit is eV
1774
!!!!!!!!!!!!!!! OPTIONAL ARGUMENTS !!!!!!!!!!!!!!!
1776
! pressure (INT): if this is a constant-pressure simulation, or if the
1777
! user is going to ask for values of the instantaneous
1778
! internal pressure, specify here the units pressure is to be
1780
! 0: specifies client pressure/stress is in kB
1781
! 1: specifies client pressure/stress is in GPa
1783
!*****************************************************************************
1786
!*****************************************************************************
1787
! No implicits please!
1791
!*****************************************************************************
1794
integer, intent (IN) :: length
1795
integer, intent (IN) :: energy
1796
integer, intent (IN), optional :: pressure
1798
!*****************************************************************************
1801
if ( debug ) write(*,*) 'Entering setUnits()'
1803
! set the length unit conversion factor
1805
select case ( length )
1807
case ( 0 ) ! client length units are in bohr, good choice!
1809
lengthConversionFactor = one
1811
case ( 1 ) ! uh uh, user chose Angstrom
1813
lengthConversionFactor = Ang
1817
! set the energy unit conversion factor
1819
! set the energy unit conversion factor
1821
select case ( energy )
1823
case ( 0 ) ! client is clever and is using hartree units
1825
energyConversionFactor = one
1827
case ( 1 ) ! client is using rydbergs; well, could be worse
1829
energyConversionFactor = half
1831
case ( 2 ) ! client is one of those renegades using eV
1833
energyConversionFactor = 1.0_dp / 27.2116_dp
1837
! with length and energy units, we can set the conversion factors
1838
! for other magnitudes
1840
forceConversionFactor = energyConversionFactor / lengthConversionFactor
1841
massConversionFactor = 1822.8885302342505_dp ! convert Dalton to electron masses
1842
timeConversionFactor = sqrt( au_to_joules / amu ) / adu
1843
velConversionFactor = lengthConversionFactor / timeConversionFactor
1845
! finally, pressure units, if required
1847
if ( present( pressure ) ) then
1849
select case( pressure )
1851
case ( 0 ) ! client units are kB
1853
pressureConversionFactor = 3.398923e-4_dp
1855
case ( 1 ) ! client units are GPa
1857
pressureConversionFactor = 3.398923e-5_dp
1861
else ! use default as GPa
1863
pressureConversionFactor = 3.398923e-5_dp
1867
if ( debug ) write(*,*) 'Exiting setUnits()'
1869
end subroutine setUnits
1871
!*****************************************************************************
1872
subroutine transformCoordinates2Lattice( state )
1873
!*****************************************************************************
1875
! Project: MolecularDynamics
1879
! Created on: Thu 8 Mar 11:39:29 2018 by Eduardo R. Hernandez
1881
! Last Modified: Wed 18 Jul 14:29:25 2018
1884
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1885
! This file is distributed under the terms of the
1886
! GNU General Public License: see COPYING in the top directory
1887
! or http://www.gnu.org/copyleft/gpl.txt .
1890
! This subroutine transforms the coordinates from Cartesian to Lattice
1891
! representation. Internally, type State contains the coordinates in Cartesian
1892
! representation, but they may be required by MD routines or client program
1893
! in Lattice representation. This soubroutine takes care of the transformation.
1894
! The internal representation is not changed, only the copied array is.
1896
!*****************************************************************************
1899
!*****************************************************************************
1900
! No implicits please!
1904
!*****************************************************************************
1905
! interface variables
1907
type ( state_type ), intent (INOUT) :: state
1909
!*****************************************************************************
1910
! internal variables
1914
real (dp), dimension (3) :: coordinates
1916
!*****************************************************************************
1919
if ( debug ) write(*,*) 'Entering transformCoordinates2Lattice()'
1921
if ( state % representation % position ) then ! coordinates are in cartesian rep., so work to do
1923
do i=1, state % nAtoms
1925
coordinates = state % position(1:3,i)
1927
state % position(1,i) = dot_product( state % reciprocalCell % a, &
1929
state % position(2,i) = dot_product( state % reciprocalCell % b, &
1931
state % position(3,i) = dot_product( state % reciprocalCell % c, &
1936
state % representation % position = .false. ! now they are in lattice rep.
1938
else ! coordinates are in lattice already, so there is nothing to do
1944
if ( debug ) write(*,*) 'Exiting transformCoordinates2Lattice()'
1946
end subroutine transformCoordinates2Lattice
1948
!*****************************************************************************
1949
subroutine transformCoordinates2Cartesian( state )
1950
!*****************************************************************************
1954
! Created on: Tue 19 Jun 13:44:20 2018 by Eduardo R. Hernandez
1956
! Last Modified: Wed 18 Jul 14:30:26 2018
1959
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
1960
! This file is distributed under the terms of the
1961
! GNU General Public License: see COPYING in the top directory
1962
! or http://www.gnu.org/copyleft/gpl.txt .
1965
! This subroutine transforms the coordinates from Lattice to Cartesian representation,
1966
! when the client program provides them in that representation.
1968
!*****************************************************************************
1971
!*****************************************************************************
1972
! No implicits please!
1976
!*****************************************************************************
1977
! interface variables
1979
type ( state_type ), intent (INOUT) :: state
1981
!*****************************************************************************
1982
! internal variables
1986
real (dp), dimension (3) :: coordinates, r, s, t
1988
!*****************************************************************************
1991
if ( debug ) write(*,*) 'Entering transformCoordinates2Cartesian()'
1993
if ( state % representation % position ) then ! if coordinates are already cartesian, do nothing
1997
else ! coordinates are in lattice rep., so transform them
1999
r = (/ state % cell % a(1), state % cell % b(1), state % cell % c(1) /)
2000
s = (/ state % cell % a(2), state % cell % b(2), state % cell % c(2) /)
2001
t = (/ state % cell % a(3), state % cell % b(3), state % cell % c(3) /)
2003
do i=1, state % nAtoms
2005
coordinates = state % position(1:3,i)
2007
state % position(1,i) = dot_product( r, coordinates )
2008
state % position(2,i) = dot_product( s, coordinates )
2009
state % position(3,i) = dot_product( t, coordinates )
2013
state % representation % position = .true.
2017
if ( debug ) write(*,*) 'Exiting transformCoordinates2Cartesian()'
2019
end subroutine transformCoordinates2Cartesian
2021
!*****************************************************************************
2022
subroutine transformForces2Lattice( state )
2023
!*****************************************************************************
2025
! Project: MolecularDynamics
2029
! Created on: Thu 8 Mar 12:10:34 2018 by Eduardo R. Hernandez
2031
! Last Modified: Wed 18 Jul 16:43:32 2018
2034
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
2035
! This file is distributed under the terms of the
2036
! GNU General Public License: see COPYING in the top directory
2037
! or http://www.gnu.org/copyleft/gpl.txt .
2040
! This subroutine transforms the forces from Cartesian representation (the
2041
! way they are stored internally) to Lattice, when they are requested in this
2042
! representation by the program calling get() (usually this call will be from
2043
! a subroutine in MolecularDynamics module).
2045
!*****************************************************************************
2048
!*****************************************************************************
2049
! No implicits please!
2053
!*****************************************************************************
2054
! interface variables
2056
type ( state_type ), intent (INOUT) :: state
2058
!*****************************************************************************
2059
! internal variables
2063
real(dp), dimension (3) :: vector
2065
!*****************************************************************************
2068
if ( debug ) write(*,*) 'Entering transformForces2Lattice()'
2070
if ( state % representation % force ) then ! forces are in cartesian rep., so transform
2072
do i=1, state % nAtoms
2074
vector = state % force(1:3,i)
2076
state % force(1,i) = dot_product( state % cell % a, vector )
2077
state % force(2,i) = dot_product( state % cell % b, vector )
2078
state % force(3,i) = dot_product( state % cell % c, vector )
2082
state % representation % force = .false. ! now they are in lattice rep.
2084
else ! forces already in lattice rep., so do nothing
2090
if ( debug ) write(*,*) 'Exiting transformForces2Lattice()'
2092
end subroutine transformForces2Lattice
2094
!*****************************************************************************
2095
subroutine transformForces2Cartesian( state )
2096
!*****************************************************************************
2098
! Project: MolecularDynamics
2100
! Created on: Thu 8 Mar 12:10:34 2018 by Eduardo R. Hernandez
2102
! Last Modified: Wed 18 Jul 16:42:30 2018
2105
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
2106
! This file is distributed under the terms of the
2107
! GNU General Public License: see COPYING in the top directory
2108
! or http://www.gnu.org/copyleft/gpl.txt .
2111
! This is a subroutine of module configuration_module; it transforms the
2112
! forces from Lattice representation, if the client provides them in that way
2113
! to Cartesian, the way in which they are stored by State type.
2115
!*****************************************************************************
2118
!*****************************************************************************
2119
! No implicits please!
2123
!*****************************************************************************
2124
! interface variables
2126
type ( state_type ), intent (INOUT) :: state
2128
!*****************************************************************************
2129
! internal variables
2133
real(dp), dimension (3) :: force, r, s, t
2135
!*****************************************************************************
2138
if ( debug ) write(*,*) 'Entering transformForces2Cartesian()'
2140
if ( state % representation % force ) then ! forces already Cartesian; do nothing
2144
else ! forces in lattice rep., so transform
2146
r = (/ state % cell % a(1), state % cell % b(1), state % cell % c(1) /)
2147
s = (/ state % cell % a(2), state % cell % b(2), state % cell % c(2) /)
2148
t = (/ state % cell % a(3), state % cell % b(3), state % cell % c(3) /)
2150
do i=1, state % nAtoms
2152
force = state % force(1:3,i)
2154
state % force(1,i) = dot_product( r, force(1:3) )
2155
state % force(2,i) = dot_product( s, force(1:3) )
2156
state % force(3,i) = dot_product( t, force(1:3) )
2160
state % representation % force = .true.
2164
if ( debug ) write(*,*) 'Exiting transformForces2Cartesian()'
2166
end subroutine transformForces2Cartesian
2168
!*****************************************************************************
2169
subroutine transformMomenta2Lattice( state )
2170
!*****************************************************************************
2172
! Project: MolecularDynamics
2176
! Created on: Thu 8 Mar 12:23:32 2018 by Eduardo R. Hernandez
2178
! Last Modified: Wed 18 Jul 14:49:27 2018
2181
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
2182
! This file is distributed under the terms of the
2183
! GNU General Public License: see COPYING in the top directory
2184
! or http://www.gnu.org/copyleft/gpl.txt .
2187
! This subroutine transforms the atomic momenta from Cartesian to Lattice
2188
! representation. Internally, State stores all atomic variables in Cartesian
2189
! representation, but they may be requested by the calling program in
2190
! Lattice representation; this routine performs the appropriate transformation
2193
!*****************************************************************************
2196
!*****************************************************************************
2197
! No implicits please!
2201
!*****************************************************************************
2202
! interface variables
2204
type ( state_type ), intent (INOUT) :: state
2206
!*****************************************************************************
2211
real (dp), dimension (3) :: vector
2213
!*****************************************************************************
2216
if ( debug ) write(*,*) 'Entering transformMomenta2Lattice()'
2218
if ( state % representation % momentum ) then ! momenta are in cartesian, so transform
2220
do i=1, state % nAtoms
2222
vector(1) = dot_product( state % reciprocalCell % a, &
2223
state % momentum(1:3,i) )
2224
vector(2) = dot_product( state % reciprocalCell % b, &
2225
state % momentum(1:3,i) )
2226
vector(3) = dot_product( state % reciprocalCell % c, &
2227
state % momentum(1:3,i) )
2229
state % momentum(1:3,i) = matmul( state % cell % metricTensor, vector )
2233
state % representation % momentum = .false. ! now they are in lattice
2235
else ! momenta already in lattice rep, so nothing to do
2241
if ( debug ) write(*,*) 'Exiting transformMomenta2Lattice()'
2243
end subroutine transformMomenta2Lattice
2245
!*****************************************************************************
2246
subroutine transformMomenta2Cartesian( state )
2247
!*****************************************************************************
2249
! Project: MolecularDynamics
2251
! Created on: Thu 8 Mar 12:23:32 2018 by Eduardo R. Hernandez
2253
! Last Modified: Wed 18 Jul 14:34:42 2018
2256
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
2257
! This file is distributed under the terms of the
2258
! GNU General Public License: see COPYING in the top directory
2259
! or http://www.gnu.org/copyleft/gpl.txt .
2262
!*****************************************************************************
2265
!*****************************************************************************
2266
! No implicits please!
2270
!*****************************************************************************
2271
! interface variables
2273
type ( state_type ), intent (INOUT) :: state
2275
!*****************************************************************************
2280
real(dp), dimension (3) :: p, r, s, t
2282
!*****************************************************************************
2285
if ( debug ) write(*,*) 'Entering transformMomenta2Cartesian()'
2287
if ( state % representation % momentum ) then ! momenta already cartesian; do nothing
2291
else ! no, we need to transform to cartesian, so do it here
2293
r = (/ state % cell % a(1), state % cell % b(1), state % cell % c(1) /)
2294
s = (/ state % cell % a(2), state % cell % b(2), state % cell % c(2) /)
2295
t = (/ state % cell % a(3), state % cell % b(3), state % cell % c(3) /)
2297
do i=1, state % nAtoms
2299
p = matmul( state % reciprocalCell % metricTensor, state % momentum(1:3,i) )
2301
state % momentum(1,i) = dot_product( r, p )
2302
state % momentum(2,i) = dot_product( s, p )
2303
state % momentum(3,i) = dot_product( t, p )
2307
state % representation % momentum = .true.
2311
if ( debug ) write(*,*) 'Exiting transformMomenta2Cartesian()'
2313
end subroutine transformMomenta2Cartesian
2315
!*****************************************************************************
2316
subroutine updateCell( Cell, reciprocalCell , LatticeVectors, MetricTensor )
2317
!*****************************************************************************
2319
! Project: MolecularDynamics
2323
! Created on: Mon 19 Mar 10:53:13 2018 by Eduardo R. Hernandez
2325
! Last Modified: Tue 3 Jul 17:30:42 2018
2328
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
2329
! This file is distributed under the terms of the
2330
! GNU General Public License: see COPYING in the top directory
2331
! or http://www.gnu.org/copyleft/gpl.txt .
2334
! From the current lattice vectors, or alternatively, the metric tensor,
2335
! this subroutine updates (recalculates) the
2336
! current cell (cell vectors, angles, moduli, etc) as well as its reciprocal
2337
! cell; this is only needed in case of flexible-cell dynamics.
2339
!*****************************************************************************
2342
!*****************************************************************************
2343
! No implicits please!
2347
!*****************************************************************************
2350
type ( lattice_type ), intent (INOUT) :: Cell
2351
type ( lattice_type ), intent (INOUT) :: reciprocalCell
2353
real (dp), dimension (3,3), intent (IN), optional :: LatticeVectors
2354
! a lattice vector per column, a(1:3) = LatticeVectors(1:3,1), etc
2355
real (dp), dimension (3,3), intent (IN), optional :: MetricTensor
2357
!*****************************************************************************
2362
double precision :: cos_angle, det_metric, factor
2364
double precision :: vector(3)
2366
double precision :: matrix_a(3,3)
2367
double precision :: matrix_b(3,3)
2369
!*****************************************************************************
2370
! start of subroutine
2372
if ( debug ) write(*,*) 'Entering updateCell()'
2374
if ( present( LatticeVectors ) ) then
2376
Cell % a(1:3) = LatticeVectors(1:3,1)
2377
Cell % b(1:3) = LatticeVectors(1:3,2)
2378
Cell % c(1:3) = LatticeVectors(1:3,3)
2380
Cell % metricTensor(1,1) = dot_product( Cell % a, Cell % a )
2381
Cell % metricTensor(1,2) = dot_product( Cell % a, Cell % b )
2382
Cell % metricTensor(1,3) = dot_product( Cell % a, Cell % c )
2384
Cell % metricTensor(2,1) = dot_product( Cell % b, Cell % a )
2385
Cell % metricTensor(2,2) = dot_product( Cell % b, Cell % b )
2386
Cell % metricTensor(2,3) = dot_product( Cell % b, Cell % c )
2388
Cell % metricTensor(3,1) = dot_product( Cell % c, Cell % a )
2389
Cell % metricTensor(3,2) = dot_product( Cell % c, Cell % b )
2390
Cell % metricTensor(3,3) = dot_product( Cell % c, Cell % c )
2392
else if ( present( MetricTensor ) ) then
2394
Cell % metricTensor = MetricTensor
2396
else if ( ( .not. present( LatticeVectors ) ) .and. ( .not. present( MetricTensor ) ) ) then
2398
write(*,*) 'Error in updateCell: either lattice vectors or metric tensor must be provided!'
2403
Cell % a(1) = sqrt( Cell % metricTensor(1,1) )
2407
Cell % b(1) = Cell % metricTensor(1,2) / sqrt( Cell % metricTensor(1,1) )
2408
Cell % b(2) = sqrt( Cell % metricTensor(2,2) - &
2409
Cell % metricTensor(1,2) * Cell % metricTensor(1,2) / &
2410
Cell % metricTensor(1,1) )
2413
Cell % c(1) = Cell % metricTensor(1,3) / sqrt( Cell % metricTensor(1,1) )
2414
Cell % c(2) = ( Cell % metricTensor(1,1) * Cell % metricTensor(2,3) - &
2415
Cell % metricTensor(1,2) * Cell % metricTensor(1,3) ) / &
2416
sqrt( Cell % metricTensor(1,1) * Cell % metricTensor(1,1) * &
2417
Cell % metricTensor(2,2) - Cell % metricTensor(1,1) * &
2418
Cell % metricTensor(1,2) * Cell % metricTensor(1,2) )
2419
Cell % c(3) = sqrt( Cell % metricTensor(3,3) - &
2420
Cell % c(1) * Cell % c(1) - Cell % c(2) * Cell % c(2) )
2422
Cell % a_modulus = sqrt( dot_product( Cell % a, Cell % a ) )
2423
Cell % b_modulus = sqrt( dot_product( Cell % b, Cell % b ) )
2424
Cell % c_modulus = sqrt( dot_product( Cell % c, Cell % c ) )
2426
cos_angle = dot_product( Cell % b, Cell % c ) / &
2427
( Cell % b_modulus * Cell % c_modulus )
2429
Cell % alpha = acos ( cos_angle ) * rad_to_deg
2431
cos_angle = dot_product( Cell % a, Cell % c ) / &
2432
( Cell % a_modulus * Cell % c_modulus )
2434
Cell % beta = acos ( cos_angle ) * rad_to_deg
2436
cos_angle = dot_product( Cell % a, Cell % b ) / &
2437
( Cell % a_modulus * Cell % b_modulus )
2439
Cell % gamma = acos ( cos_angle ) * rad_to_deg
2441
vector(1) = Cell % b(2) * Cell % c(3) - Cell % c(2) * Cell % b(3)
2442
vector(2) = Cell % b(3) * Cell % c(1) - Cell % c(3) * Cell % b(1)
2443
vector(3) = Cell % b(1) * Cell % c(2) - Cell % c(1) * Cell % b(2)
2445
Cell % volume = dot_product( vector, Cell % a )
2447
! calculate the reciprocal lattice vectors
2448
! these are the reciprocal lattice vectors but for a factor of 2pi
2450
reciprocalCell % a = vector / Cell % volume
2452
vector(1) = Cell % c(2) * Cell % a(3) - Cell % a(2) * Cell % c(3)
2453
vector(2) = Cell % c(3) * Cell % a(1) - Cell % a(3) * Cell % c(1)
2454
vector(3) = Cell % c(1) * Cell % a(2) - Cell % a(1) * Cell % c(2)
2456
reciprocalCell % b = vector / Cell % volume
2458
vector(1) = Cell % a(2) * Cell % b(3) - Cell % b(2) * Cell % a(3)
2459
vector(2) = Cell % a(3) * Cell % b(1) - Cell % b(3) * Cell % a(1)
2460
vector(3) = Cell % a(1) * Cell % b(2) - Cell % b(1) * Cell % a(2)
2462
reciprocalCell % c = vector / Cell % volume
2464
reciprocalCell % a_modulus = &
2465
sqrt( dot_product( reciprocalCell % a, reciprocalCell % a ) )
2466
reciprocalCell % b_modulus = &
2467
sqrt( dot_product( reciprocalCell % b, reciprocalCell % b ) )
2468
reciprocalCell % c_modulus = &
2469
sqrt( dot_product( reciprocalCell % c, reciprocalCell % c ) )
2471
cos_angle = dot_product( reciprocalCell % b, reciprocalCell % c ) / &
2472
( reciprocalCell % b_modulus * reciprocalCell % c_modulus )
2474
reciprocalCell % alpha = acos ( cos_angle ) * rad_to_deg
2476
cos_angle = dot_product( reciprocalCell % a, reciprocalCell % c ) / &
2477
( reciprocalCell % a_modulus * reciprocalCell % c_modulus )
2479
reciprocalCell % beta = acos ( cos_angle ) * rad_to_deg
2481
cos_angle = dot_product( reciprocalCell % a, reciprocalCell % b ) / &
2482
( reciprocalCell % a_modulus * reciprocalCell % b_modulus )
2484
reciprocalCell % gamma = acos ( cos_angle ) * rad_to_deg
2486
reciprocalCell % volume = one / Cell % volume
2488
! calculate the reciprocal metric tensor
2490
reciprocalCell % metricTensor(1,1) = &
2491
dot_product( reciprocalCell % a, reciprocalCell % a )
2492
reciprocalCell % metricTensor(1,2) = &
2493
dot_product( reciprocalCell % a, reciprocalCell % b )
2494
reciprocalCell % metricTensor(1,3) = &
2495
dot_product( reciprocalCell % a, reciprocalCell % c )
2497
reciprocalCell % metricTensor(2,1) = &
2498
dot_product( reciprocalCell % b, reciprocalCell % a )
2499
reciprocalCell % metricTensor(2,2) = &
2500
dot_product( reciprocalCell % b, reciprocalCell % b )
2501
reciprocalCell % metricTensor(2,3) = &
2502
dot_product( reciprocalCell % b, reciprocalCell % c )
2504
reciprocalCell % metricTensor(3,1) = &
2505
dot_product( reciprocalCell % c, reciprocalCell % a )
2506
reciprocalCell % metricTensor(3,2) = &
2507
dot_product( reciprocalCell % c, reciprocalCell % b )
2508
reciprocalCell % metricTensor(3,3) = &
2509
dot_product( reciprocalCell % c, reciprocalCell % c )
2511
if ( debug ) write(*,*) 'Exiting updateCell()'
2513
end subroutine updateCell
2515
!*****************************************************************************
2516
subroutine readRestart( state, restartFile, nSteps )
2517
!*****************************************************************************
2519
! Project: MolecularDynamics
2521
! Created on: Fri 2 Nov 12:33:45 2018 by Eduardo R. Hernandez
2523
! Last Modified: Mon 5 Nov 18:17:59 2018
2526
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
2527
! This file is distributed under the terms of the
2528
! GNU General Public License: see COPYING in the top directory
2529
! or http://www.gnu.org/copyleft/gpl.txt .
2532
!*****************************************************************************
2535
!*****************************************************************************
2536
! No implicits please!
2540
!*****************************************************************************
2543
type ( state_type ), intent (INOUT) :: state ! the state to be read
2545
character ( len = 30 ), intent (IN) :: restartFile
2547
integer, intent (INOUT), optional :: nSteps
2549
!*****************************************************************************
2555
!*****************************************************************************
2558
if ( debug ) write(*,*) 'Entering readRestart()'
2560
open( unit = 9, file = restartFile )
2562
! if the number of steps has been passed, write it; else write a zero
2563
! this is so that the continuation run can start counting steps from a
2564
! the counter of a previous run, if desired
2568
! write the H0 constant, needed for calculating the constant of motion
2570
read(9,*) state % H0 % E
2571
state % H0 % set = .true.
2573
! write the representation flags
2575
read(9,*) state % representation % position, &
2576
state % representation % momentum, &
2577
state % representation % force
2579
! now write the number of atoms, positions, forces, momenta and mass
2581
read(9,*) state % nAtoms
2582
read(9,*) state % nDegreesOfFreedom
2584
do i=1, state % nAtoms
2585
read(9,*) state % position(1:3,i)
2588
do i=1, state % nAtoms
2589
read(9,*) state % momentum(1:3,i)
2592
do i=1, state % nAtoms
2593
read(9,*) state % mass(i)
2596
! write the cell metric tensor; with this, the rest of the cell info
2597
! can be easily reconstructed
2599
read(9,*) state % cell % metricTensor(1:3,1)
2600
read(9,*) state % cell % metricTensor(1:3,2)
2601
read(9,*) state % cell % metricTensor(1:3,3)
2603
call updateCell( state % cell, state % reciprocalCell, &
2604
MetricTensor = state % cell % metricTensor )
2606
! write associated barostat variables
2608
read(9,*) state % barostat % mass
2610
read(9,*) state % barostat % momentum(1:3,1)
2611
read(9,*) state % barostat % momentum(1:3,2)
2612
read(9,*) state % barostat % momentum(1:3,3)
2614
! now write the thermostat information
2616
read(9,*) state % nThermostats
2618
do i=1, state % nThermostats
2620
read(9,*) state % thermostat(i) % mass, &
2621
state % thermostat(i) % position, &
2622
state % thermostat(i) % momentum, &
2623
state % thermostat(i) % a, &
2624
state % thermostat(i) % C
2630
if ( debug ) write(*,*) 'Exiting readRestart()'
2632
end subroutine readRestart
2633
!*****************************************************************************
2634
subroutine writeRestart( state, restartFileName, nSteps )
2635
!*****************************************************************************
2637
! Project: MolecularDynamics
2639
! Created on: Fri 2 Nov 11:05:47 2018 by Eduardo R. Hernandez
2641
! Last Modified: Tue 6 Nov 09:40:31 2018
2644
! Copyright (C) 2018 Eduardo R. Hernandez - ICMM
2645
! This file is distributed under the terms of the
2646
! GNU General Public License: see COPYING in the top directory
2647
! or http://www.gnu.org/copyleft/gpl.txt .
2650
! This subroutine writes to a file the current state of the system, with the
2651
! purpose of serving as a continuation file for subsequent runs.
2653
!*****************************************************************************
2656
!*****************************************************************************
2657
! No implicits please!
2661
!*****************************************************************************
2664
type ( state_type ), intent (IN) :: state ! the state to be stored
2666
character ( len = 30 ), intent (IN) :: restartFileName
2668
integer, intent (IN), optional :: nSteps
2670
!*****************************************************************************
2676
!*****************************************************************************
2679
if ( debug ) write(*,*) 'Entering writeRestart()'
2681
open( unit = 9, file = restartFileName )
2683
! if the number of steps has been passed, write it; else write a zero
2684
! this is so that the continuation run can start counting steps from a
2685
! the counter of a previous run, if desired
2687
if ( present( nSteps ) ) then
2695
! write the H0 constant, needed for calculating the constant of motion
2697
write(9,*) state % H0 % E
2699
! write the representation flags
2701
write(9,*) state % representation % position, &
2702
state % representation % momentum, &
2703
state % representation % force
2705
! now write the number of atoms, positions, forces, momenta and mass
2707
write(9,*) state % nAtoms
2708
write(9,*) state % nDegreesOfFreedom
2710
do i=1, state % nAtoms
2711
write(9,*) state % position(1:3,i)
2714
do i=1, state % nAtoms
2715
write(9,*) state % momentum(1:3,i)
2718
do i=1, state % nAtoms
2719
write(9,*) state % mass(i)
2722
! write the cell metric tensor; with this, the rest of the cell info
2723
! can be easily reconstructed
2725
write(9,*) state % cell % metricTensor(1:3,1)
2726
write(9,*) state % cell % metricTensor(1:3,2)
2727
write(9,*) state % cell % metricTensor(1:3,3)
2729
! write associated barostat variables
2731
write(9,*) state % barostat % mass
2733
write(9,*) state % barostat % momentum(1:3,1)
2734
write(9,*) state % barostat % momentum(1:3,2)
2735
write(9,*) state % barostat % momentum(1:3,3)
2737
! now write the thermostat information
2739
write(9,*) state % nThermostats
2741
do i=1, state % nThermostats
2743
write(9,*) state % thermostat(i) % mass, &
2744
state % thermostat(i) % position, &
2745
state % thermostat(i) % momentum, &
2746
state % thermostat(i) % a, &
2747
state % thermostat(i) % C
2753
if ( debug ) write(*,*) 'Exiting writeRestart()'
2755
end subroutine writeRestart
2757
end module md_state_module