Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
3a2f4643
Commit
3a2f4643
authored
Jul 12, 2013
by
Peter Eastman
Browse files
Cleanup and bugfixes to MonteCarloAnisotropicBarostat
parent
7a55f02c
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
509 additions
and
391 deletions
+509
-391
openmmapi/include/openmm/MonteCarloAnisotropicBarostat.h
openmmapi/include/openmm/MonteCarloAnisotropicBarostat.h
+17
-28
openmmapi/include/openmm/MonteCarloBarostat.h
openmmapi/include/openmm/MonteCarloBarostat.h
+1
-9
openmmapi/include/openmm/internal/AssertionUtilities.h
openmmapi/include/openmm/internal/AssertionUtilities.h
+3
-1
openmmapi/src/MonteCarloAnisotropicBarostatImpl.cpp
openmmapi/src/MonteCarloAnisotropicBarostatImpl.cpp
+18
-17
platforms/cuda/tests/TestCudaMonteCarloAnisotropicBarostat.cpp
...orms/cuda/tests/TestCudaMonteCarloAnisotropicBarostat.cpp
+152
-159
platforms/opencl/tests/TestOpenCLMonteCarloAnisotropicBarostat.cpp
.../opencl/tests/TestOpenCLMonteCarloAnisotropicBarostat.cpp
+153
-160
platforms/reference/tests/TestReferenceMonteCarloAnisotropicBarostat.cpp
...ence/tests/TestReferenceMonteCarloAnisotropicBarostat.cpp
+165
-17
No files found.
openmmapi/include/openmm/MonteCarloAnisotropicBarostat.h
View file @
3a2f4643
...
@@ -9,8 +9,8 @@
...
@@ -9,8 +9,8 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2010 Stanford University and the Authors.
*
* Portions copyright (c) 2010
-2013
Stanford University and the Authors. *
* Authors: Peter Eastman
*
* Authors: Peter Eastman
, Lee-Ping Wang
*
* Contributors: *
* Contributors: *
* *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* Permission is hereby granted, free of charge, to any person obtaining a *
...
@@ -43,9 +43,12 @@ namespace OpenMM {
...
@@ -43,9 +43,12 @@ namespace OpenMM {
* This class uses a Monte Carlo algorithm to adjust the size of the periodic box, simulating the
* This class uses a Monte Carlo algorithm to adjust the size of the periodic box, simulating the
* effect of constant pressure.
* effect of constant pressure.
*
*
* Compared to MonteCarloBarostat, this class scales the three axes of the simulation cell independently.
* This class is similar to MonteCarloBarostat, but each Monte Carlo move is applied to only one axis
* The user supplies three doubles to specify the pressure along each axis.
* of the periodic box (unlike MonteCarloBarostat, which scales the entire box isotropically). This
*
* means that the box may change shape as well as size over the course of the simulation. It also
* allows you to specify a different pressure for each axis of the box, or to keep the box size fixed
* along certain axes while still allowing it to change along others.
*
* This class assumes the simulation is also being run at constant temperature, and requires you
* This class assumes the simulation is also being run at constant temperature, and requires you
* to specify the system temperature (since it affects the acceptance probability for Monte Carlo
* to specify the system temperature (since it affects the acceptance probability for Monte Carlo
* moves). It does not actually perform temperature regulation, however. You must use another
* moves). It does not actually perform temperature regulation, however. You must use another
...
@@ -84,39 +87,33 @@ public:
...
@@ -84,39 +87,33 @@ public:
* @param defaultPressure The default pressure acting on each axis (in bar)
* @param defaultPressure The default pressure acting on each axis (in bar)
* @param temperature the temperature at which the system is being maintained (in Kelvin)
* @param temperature the temperature at which the system is being maintained (in Kelvin)
* @param frequency the frequency at which Monte Carlo pressure changes should be attempted (in time steps)
* @param frequency the frequency at which Monte Carlo pressure changes should be attempted (in time steps)
* @param scaleX
on/off switch for
whether to
scale
the X
axis
* @param scaleX whether to
allow
the X
dimension of the periodic box to change size
* @param scaleY
on/off switch for
whether to
scale
the Y
axis
* @param scaleY whether to
allow
the Y
dimension of the periodic box to change size
* @param scaleZ
on/off switch for
whether to
scale
the Z
axis
* @param scaleZ whether to
allow
the Z
dimension of the periodic box to change size
*/
*/
MonteCarloAnisotropicBarostat
(
const
Vec3
&
defaultPressure
,
double
temperature
,
int
frequency
=
25
,
bool
scaleX
=
1
,
bool
scaleY
=
1
,
bool
scaleZ
=
1
);
MonteCarloAnisotropicBarostat
(
const
Vec3
&
defaultPressure
,
double
temperature
,
int
frequency
=
25
,
bool
scaleX
=
1
,
bool
scaleY
=
1
,
bool
scaleZ
=
1
);
/**
/**
* Get the default pressure (in bar).
* Get the default pressure (in bar).
*
*
* @return the default pressure acting
on the system
, measured in bar.
* @return the default pressure acting
along each axis
, measured in bar.
*/
*/
Vec3
getDefaultPressure
()
const
{
const
Vec3
&
getDefaultPressure
()
const
{
return
defaultPressure
;
return
defaultPressure
;
}
}
/**
/**
* Get the true/false flag for scaling the X-axis.
* Get whether to allow the X dimension of the periodic box to change size.
*
* @return the true/false flag for scaling the X-axis.
*/
*/
bool
getScaleX
()
const
{
bool
getScaleX
()
const
{
return
scaleX
;
return
scaleX
;
}
}
/**
/**
* Get the true/false flag for scaling the Y-axis.
* Get whether to allow the Y dimension of the periodic box to change size.
*
* @return the true/false flag for scaling the Y-axis.
*/
*/
bool
getScaleY
()
const
{
bool
getScaleY
()
const
{
return
scaleY
;
return
scaleY
;
}
}
/**
/**
* Get the true/false flag for scaling the Z-axis.
* Get whether to allow the Z dimension of the periodic box to change size.
*
* @return the true/false flag for scaling the Z-axis.
*/
*/
bool
getScaleZ
()
const
{
bool
getScaleZ
()
const
{
return
scaleZ
;
return
scaleZ
;
...
@@ -172,15 +169,7 @@ private:
...
@@ -172,15 +169,7 @@ private:
double
temperature
;
double
temperature
;
bool
scaleX
,
scaleY
,
scaleZ
;
bool
scaleX
,
scaleY
,
scaleZ
;
int
frequency
,
randomNumberSeed
;
int
frequency
,
randomNumberSeed
;
};
double
GetTemperature
()
const
{
return
temperature
;
}
void
SetTemperature
(
double
temperature
)
{
this
->
temperature
=
temperature
;
}
};
}
// namespace OpenMM
}
// namespace OpenMM
...
...
openmmapi/include/openmm/MonteCarloBarostat.h
View file @
3a2f4643
...
@@ -123,15 +123,7 @@ protected:
...
@@ -123,15 +123,7 @@ protected:
private:
private:
double
defaultPressure
,
temperature
;
double
defaultPressure
,
temperature
;
int
frequency
,
randomNumberSeed
;
int
frequency
,
randomNumberSeed
;
};
double
GetTemperature
()
const
{
return
temperature
;
}
void
SetTemperature
(
double
temperature
)
{
this
->
temperature
=
temperature
;
}
};
}
// namespace OpenMM
}
// namespace OpenMM
...
...
openmmapi/include/openmm/internal/AssertionUtilities.h
View file @
3a2f4643
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
2
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Authors: Peter Eastman *
* Authors: Peter Eastman *
* Contributors: *
* Contributors: *
* *
* *
...
@@ -54,6 +54,8 @@ void OPENMM_EXPORT throwException(const char* file, int line, const std::string&
...
@@ -54,6 +54,8 @@ void OPENMM_EXPORT throwException(const char* file, int line, const std::string&
#define ASSERT_EQUAL_VEC(expected, found, tol) {double _norm_ = std::sqrt((expected).dot(expected)); double _scale_ = _norm_ > 1.0 ? _norm_ : 1.0; if ((std::abs(((expected)[0])-((found)[0]))/_scale_ > (tol)) || (std::abs(((expected)[1])-((found)[1]))/_scale_ > (tol)) || (std::abs(((expected)[2])-((found)[2]))/_scale_ > (tol))) {std::stringstream details; details << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_EQUAL_VEC(expected, found, tol) {double _norm_ = std::sqrt((expected).dot(expected)); double _scale_ = _norm_ > 1.0 ? _norm_ : 1.0; if ((std::abs(((expected)[0])-((found)[0]))/_scale_ > (tol)) || (std::abs(((expected)[1])-((found)[1]))/_scale_ > (tol)) || (std::abs(((expected)[2])-((found)[2]))/_scale_ > (tol))) {std::stringstream details; details << " Expected "<<(expected)<<", found "<<(found); throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_USUALLY_TRUE(cond) {if (!(cond)) throwException(__FILE__, __LINE__, "(This test is stochastic and may occasionally fail)");};
#define ASSERT_USUALLY_EQUAL_TOL(expected, found, tol) {double _scale_ = std::abs(expected) > 1.0 ? std::abs(expected) : 1.0; if (!(std::abs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << "Expected "<<(expected)<<", found "<<(found)<<" (This test is stochastic and may occasionally fail)"; throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_USUALLY_EQUAL_TOL(expected, found, tol) {double _scale_ = std::abs(expected) > 1.0 ? std::abs(expected) : 1.0; if (!(std::abs((expected)-(found))/_scale_ <= (tol))) {std::stringstream details; details << "Expected "<<(expected)<<", found "<<(found)<<" (This test is stochastic and may occasionally fail)"; throwException(__FILE__, __LINE__, details.str());}};
#define ASSERT_VALID_INDEX(index, vector) {if (index < 0 || index >= (int) vector.size()) throwException(__FILE__, __LINE__, "Index out of range");};
#define ASSERT_VALID_INDEX(index, vector) {if (index < 0 || index >= (int) vector.size()) throwException(__FILE__, __LINE__, "Index out of range");};
...
...
openmmapi/src/MonteCarloAnisotropicBarostatImpl.cpp
View file @
3a2f4643
...
@@ -6,8 +6,8 @@
...
@@ -6,8 +6,8 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2010 Stanford University and the Authors.
*
* Portions copyright (c) 2010
-2013
Stanford University and the Authors. *
* Authors: Peter Eastman
*
* Authors: Peter Eastman
, Lee-Ping Wang
*
* Contributors: *
* Contributors: *
* *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* Permission is hereby granted, free of charge, to any person obtaining a *
...
@@ -65,7 +65,7 @@ void MonteCarloAnisotropicBarostatImpl::initialize(ContextImpl& context) {
...
@@ -65,7 +65,7 @@ void MonteCarloAnisotropicBarostatImpl::initialize(ContextImpl& context) {
void
MonteCarloAnisotropicBarostatImpl
::
updateContextState
(
ContextImpl
&
context
)
{
void
MonteCarloAnisotropicBarostatImpl
::
updateContextState
(
ContextImpl
&
context
)
{
if
(
++
step
<
owner
.
getFrequency
()
||
owner
.
getFrequency
()
==
0
)
if
(
++
step
<
owner
.
getFrequency
()
||
owner
.
getFrequency
()
==
0
)
return
;
return
;
if
(
owner
.
getScaleX
()
==
0
&&
owner
.
getScaleY
()
==
0
&&
owner
.
getScaleZ
()
==
0
)
if
(
!
owner
.
getScaleX
()
&&
!
owner
.
getScaleY
()
&&
!
owner
.
getScaleZ
())
return
;
return
;
step
=
0
;
step
=
0
;
...
@@ -75,23 +75,26 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context)
...
@@ -75,23 +75,26 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context)
double
pressure
;
double
pressure
;
// Choose which axis to modify at random.
// Choose which axis to modify at random.
double
rnd
=
genrand_real2
(
random
)
*
3.0
;
int
axis
;
int
axis
;
while
(
1
)
{
while
(
true
)
{
if
(
rnd
<
1.0
&&
owner
.
getScaleX
())
{
double
rnd
=
genrand_real2
(
random
)
*
3.0
;
axis
=
0
;
if
(
rnd
<
1.0
)
{
pressure
=
context
.
getParameter
(
MonteCarloAnisotropicBarostat
::
PressureX
())
*
(
AVOGADRO
*
1e-25
);
if
(
owner
.
getScaleX
())
{
break
;
axis
=
0
;
}
else
if
(
rnd
<
2.0
&&
owner
.
getScaleY
())
{
pressure
=
context
.
getParameter
(
MonteCarloAnisotropicBarostat
::
PressureX
())
*
(
AVOGADRO
*
1e-25
);
axis
=
1
;
break
;
pressure
=
context
.
getParameter
(
MonteCarloAnisotropicBarostat
::
PressureY
())
*
(
AVOGADRO
*
1e-25
);
}
break
;
}
else
if
(
rnd
<
2.0
)
{
if
(
owner
.
getScaleY
())
{
axis
=
1
;
pressure
=
context
.
getParameter
(
MonteCarloAnisotropicBarostat
::
PressureY
())
*
(
AVOGADRO
*
1e-25
);
break
;
}
}
else
if
(
owner
.
getScaleZ
())
{
}
else
if
(
owner
.
getScaleZ
())
{
axis
=
2
;
axis
=
2
;
pressure
=
context
.
getParameter
(
MonteCarloAnisotropicBarostat
::
PressureZ
())
*
(
AVOGADRO
*
1e-25
);
pressure
=
context
.
getParameter
(
MonteCarloAnisotropicBarostat
::
PressureZ
())
*
(
AVOGADRO
*
1e-25
);
break
;
break
;
}
}
rnd
=
genrand_real2
(
random
)
*
3.0
;
}
}
// Modify the periodic box size.
// Modify the periodic box size.
...
@@ -101,9 +104,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context)
...
@@ -101,9 +104,7 @@ void MonteCarloAnisotropicBarostatImpl::updateContextState(ContextImpl& context)
double
volume
=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
double
volume
=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
double
deltaVolume
=
volumeScale
[
axis
]
*
2
*
(
genrand_real2
(
random
)
-
0.5
);
double
deltaVolume
=
volumeScale
[
axis
]
*
2
*
(
genrand_real2
(
random
)
-
0.5
);
double
newVolume
=
volume
+
deltaVolume
;
double
newVolume
=
volume
+
deltaVolume
;
Vec3
lengthScale
;
Vec3
lengthScale
(
1.0
,
1.0
,
1.0
);
for
(
int
i
=
0
;
i
<
3
;
i
++
)
lengthScale
[
i
]
=
1.0
;
lengthScale
[
axis
]
=
newVolume
/
volume
;
lengthScale
[
axis
]
=
newVolume
/
volume
;
kernel
.
getAs
<
ApplyMonteCarloBarostatKernel
>
().
scaleCoordinates
(
context
,
lengthScale
[
0
],
lengthScale
[
1
],
lengthScale
[
2
]);
kernel
.
getAs
<
ApplyMonteCarloBarostatKernel
>
().
scaleCoordinates
(
context
,
lengthScale
[
0
],
lengthScale
[
1
],
lengthScale
[
2
]);
context
.
getOwner
().
setPeriodicBoxVectors
(
box
[
0
]
*
lengthScale
[
0
],
box
[
1
]
*
lengthScale
[
1
],
box
[
2
]
*
lengthScale
[
2
]);
context
.
getOwner
().
setPeriodicBoxVectors
(
box
[
0
]
*
lengthScale
[
0
],
box
[
1
]
*
lengthScale
[
1
],
box
[
2
]
*
lengthScale
[
2
]);
...
...
platforms/cuda/tests/TestCudaMonteCarloAnisotropicBarostat.cpp
View file @
3a2f4643
...
@@ -6,8 +6,8 @@
...
@@ -6,8 +6,8 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
2
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Authors: Peter Eastman
*
* Authors: Peter Eastman
, Lee-Ping Wang
*
* Contributors: *
* Contributors: *
* *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* Permission is hereby granted, free of charge, to any person obtaining a *
...
@@ -191,24 +191,24 @@ void testIdealGasAxis(int axis) {
...
@@ -191,24 +191,24 @@ void testIdealGasAxis(int axis) {
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
boxX
=
box
[
0
][
0
];
boxX
=
box
[
0
][
0
];
boxY
=
box
[
1
][
1
];
boxY
=
box
[
1
][
1
];
boxZ
=
box
[
2
][
2
];
boxZ
=
box
[
2
][
2
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
integrator
.
step
(
frequency
);
}
}
volume
/=
steps
;
volume
/=
steps
;
double
expected
=
(
numParticles
+
1
)
*
BOLTZ
*
temp
[
i
]
/
pressureInMD
;
double
expected
=
(
numParticles
+
1
)
*
BOLTZ
*
temp
[
i
]
/
pressureInMD
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
volume
,
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
volume
,
3
/
std
::
sqrt
((
double
)
steps
));
if
(
!
scaleX
)
{
if
(
!
scaleX
)
{
ASSERT
(
boxX
==
initialLength
);
ASSERT
(
boxX
==
initialLength
);
}
}
if
(
!
scaleY
)
{
if
(
!
scaleY
)
{
ASSERT
(
boxY
==
0.5
*
initialLength
);
ASSERT
(
boxY
==
0.5
*
initialLength
);
}
}
if
(
!
scaleZ
)
{
if
(
!
scaleZ
)
{
ASSERT
(
boxZ
==
2
*
initialLength
);
ASSERT
(
boxZ
==
2
*
initialLength
);
}
}
}
}
}
}
...
@@ -274,155 +274,148 @@ void testRandomSeed() {
...
@@ -274,155 +274,148 @@ void testRandomSeed() {
}
}
}
}
/**
* Run a constant pressure simulation on an anisotropic Einstein crystal
* using isotropic and anisotropic barostats. There are a total of 15 simulations:
*
* 1) 3 pressures: 9.0, 10.0, 11.0 bar, for each of the following groups:
* 2) 3 groups of simulations that scale just one axis: x, y, z
* 3) 1 group of simulations that scales all three axes in the anisotropic barostat
* 4) 1 group of simulations that scales all three axes in the isotropic barostat
*
* Results that we will check:
*
* a) In each group of simulations, the volume should decrease with increasing pressure
* b) In the three simulation groups that scale just one axis, the compressibility (i.e. incremental volume change
* with increasing pressure) should go like kx > ky > kz (because the spring constant is largest in the z-direction)
* c) The anisotropic barostat should produce the same result as the isotropic barostat when all three axes are scaled
*/
void
testEinsteinCrystal
()
{
void
testEinsteinCrystal
()
{
/*
const
int
numParticles
=
64
;
const
int
frequency
=
2
;
Run a constant pressure simulation on an anisotropic Einstein crystal
const
int
equil
=
10000
;
using isotropic and anisotropic barostats. There are a total of 15 simulations:
const
int
steps
=
5000
;
const
double
pressure
=
10.0
;
1) 3 pressures: 9.0, 10.0, 11.0 bar, for each of the following groups:
const
double
pressureInMD
=
pressure
*
(
AVOGADRO
*
1e-25
);
// pressure in kJ/mol/nm^3
2) 3 groups of simulations that scale just one axis: x, y, z
const
double
temp
=
300.0
;
// Only test one temperature since we're looking at three pressures.
3) 1 group of simulations that scales all three axes in the anisotropic barostat
const
double
pres3
[]
=
{
2.0
,
8.0
,
15.0
};
4) 1 group of simulations that scales all three axes in the isotropic barostat
const
double
initialVolume
=
numParticles
*
BOLTZ
*
temp
/
pressureInMD
;
const
double
initialLength
=
std
::
pow
(
initialVolume
,
1.0
/
3.0
);
Results that we will check:
vector
<
double
>
initialPositions
(
3
);
vector
<
double
>
results
;
a) In each group of simulations, the volume should decrease with increasing pressure
// Run four groups of anisotropic simulations; scaling just x, y, z, then all three.
b) In the three simulation groups that scale just one axis, the compressibility (i.e. incremental volume change
for
(
int
a
=
0
;
a
<
4
;
a
++
)
{
with increasing pressure) should go like kx > ky > kz (because the spring constant is largest in the z-direction)
// Test barostat for three different pressures.
c) The anisotropic barostat should produce the same result as the isotropic barostat when all three axes are scaled
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
*/
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
const
int
numParticles
=
64
;
vector
<
Vec3
>
positions
(
numParticles
);
const
int
frequency
=
10
;
OpenMM_SFMT
::
SFMT
sfmt
;
const
int
equil
=
10000
;
init_gen_rand
(
0
,
sfmt
);
const
int
steps
=
10000
;
// Anisotropic force constants.
const
double
pressure
=
10.0
;
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
const
double
pressureInMD
=
pressure
*
(
AVOGADRO
*
1e-25
);
// pressure in kJ/mol/nm^3
force
->
addPerParticleParameter
(
"x0"
);
const
double
temp
=
300.0
;
// Only test one temperature since we're looking at three pressures.
force
->
addPerParticleParameter
(
"y0"
);
const
double
pres3
[]
=
{
9.0
,
10.0
,
11.0
};
force
->
addPerParticleParameter
(
"z0"
);
const
double
initialVolume
=
numParticles
*
BOLTZ
*
temp
/
pressureInMD
;
NonbondedForce
*
nb
=
new
NonbondedForce
();
const
double
initialLength
=
std
::
pow
(
initialVolume
,
1.0
/
3.0
);
nb
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
vector
<
double
>
initialPositions
(
3
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
// All results.
system
.
addParticle
(
1.0
);
double
results
[]
=
{
0.0
,
0.0
,
0.0
,
0.0
,
0.0
,
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
0.0
,
0.0
,
0.0
,
0.0
,
0.0
,
initialPositions
[
0
]
=
positions
[
i
][
0
];
0.0
,
0.0
,
0.0
,
0.0
,
0.0
};
initialPositions
[
1
]
=
positions
[
i
][
1
];
int
simNum
=
0
;
initialPositions
[
2
]
=
positions
[
i
][
2
];
// Run four groups of anisotropic simulations; scaling just x, y, z, then all three.
force
->
addParticle
(
i
,
initialPositions
);
for
(
int
a
=
0
;
a
<
4
;
a
++
)
{
nb
->
addParticle
(
0
,
initialLength
/
6
,
0.1
);
// Test barostat for three different pressures.
}
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
system
.
addForce
(
force
);
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
system
.
addForce
(
nb
);
System
system
;
// Create the barostat.
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
MonteCarloAnisotropicBarostat
*
barostat
=
new
MonteCarloAnisotropicBarostat
(
Vec3
(
pres3
[
p
],
pres3
[
p
],
pres3
[
p
]),
temp
,
frequency
,
(
a
==
0
||
a
==
3
),
(
a
==
1
||
a
==
3
),
(
a
==
2
||
a
==
3
));
vector
<
Vec3
>
positions
(
numParticles
);
system
.
addForce
(
barostat
);
OpenMM_SFMT
::
SFMT
sfmt
;
barostat
->
setTemperature
(
temp
);
init_gen_rand
(
0
,
sfmt
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.01
);
// Anisotropic force constants.
Context
context
(
system
,
integrator
,
platform
);
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
context
.
setPositions
(
positions
);
force
->
addPerParticleParameter
(
"x0"
);
// Let it equilibrate.
force
->
addPerParticleParameter
(
"y0"
);
integrator
.
step
(
equil
);
force
->
addPerParticleParameter
(
"z0"
);
// Now run it for a while and see if the volume is correct.
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
double
volume
=
0.0
;
system
.
addParticle
(
1.0
);
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
Vec3
box
[
3
];
initialPositions
[
0
]
=
positions
[
i
][
0
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
initialPositions
[
1
]
=
positions
[
i
][
1
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
integrator
.
step
(
frequency
);
force
->
addParticle
(
i
,
initialPositions
);
}
}
volume
/=
steps
;
system
.
addForce
(
force
);
results
.
push_back
(
volume
);
// Create the barostat.
}
MonteCarloAnisotropicBarostat
*
barostat
=
new
MonteCarloAnisotropicBarostat
(
Vec3
(
pres3
[
p
],
pres3
[
p
],
pres3
[
p
]),
temp
,
frequency
,
(
a
==
0
||
a
==
3
),
(
a
==
1
||
a
==
3
),
(
a
==
2
||
a
==
3
));
system
.
addForce
(
barostat
);
barostat
->
setTemperature
(
temp
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
equil
);
// Now run it for a while and see if the volume is correct.
double
volume
=
0.0
;
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
}
volume
/=
steps
;
results
[
simNum
]
=
volume
;
simNum
+=
1
;
}
}
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
// Anisotropic force constants.
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
force
->
addPerParticleParameter
(
"x0"
);
force
->
addPerParticleParameter
(
"y0"
);
force
->
addPerParticleParameter
(
"z0"
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
1.0
);
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
initialPositions
[
0
]
=
positions
[
i
][
0
];
initialPositions
[
1
]
=
positions
[
i
][
1
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
force
->
addParticle
(
i
,
initialPositions
);
}
}
system
.
addForce
(
force
);
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create the barostat.
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
MonteCarloBarostat
*
barostat
=
new
MonteCarloBarostat
(
pres3
[
p
],
temp
,
frequency
);
System
system
;
system
.
addForce
(
barostat
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
barostat
->
setTemperature
(
temp
);
vector
<
Vec3
>
positions
(
numParticles
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.01
);
OpenMM_SFMT
::
SFMT
sfmt
;
Context
context
(
system
,
integrator
,
platform
);
init_gen_rand
(
0
,
sfmt
);
context
.
setPositions
(
positions
);
// Anisotropic force constants.
// Let it equilibrate.
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
integrator
.
step
(
equil
);
force
->
addPerParticleParameter
(
"x0"
);
// Now run it for a while and see if the volume is correct.
force
->
addPerParticleParameter
(
"y0"
);
double
volume
=
0.0
;
force
->
addPerParticleParameter
(
"z0"
);
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
NonbondedForce
*
nb
=
new
NonbondedForce
();
Vec3
box
[
3
];
nb
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
system
.
addParticle
(
1.0
);
integrator
.
step
(
frequency
);
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
initialPositions
[
0
]
=
positions
[
i
][
0
];
initialPositions
[
1
]
=
positions
[
i
][
1
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
force
->
addParticle
(
i
,
initialPositions
);
nb
->
addParticle
(
0
,
initialLength
/
6
,
0.1
);
}
system
.
addForce
(
force
);
system
.
addForce
(
nb
);
// Create the barostat.
MonteCarloBarostat
*
barostat
=
new
MonteCarloBarostat
(
pres3
[
p
],
temp
,
frequency
);
system
.
addForce
(
barostat
);
barostat
->
setTemperature
(
temp
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.001
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
equil
);
// Now run it for a while and see if the volume is correct.
double
volume
=
0.0
;
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
}
volume
/=
steps
;
results
.
push_back
(
volume
);
}
}
volume
/=
steps
;
results
[
simNum
]
=
volume
;
// Check to see if volumes decrease with increasing pressure.
simNum
+=
1
;
ASSERT_USUALLY_TRUE
(
results
[
0
]
>
results
[
1
]);
}
ASSERT_USUALLY_TRUE
(
results
[
1
]
>
results
[
2
]);
ASSERT_USUALLY_TRUE
(
results
[
3
]
>
results
[
4
]);
/*
ASSERT_USUALLY_TRUE
(
results
[
4
]
>
results
[
5
]);
for (int j = 0; j < 15; j++) {
ASSERT_USUALLY_TRUE
(
results
[
6
]
>
results
[
7
]);
printf("%.6f\n",results[j]);
ASSERT_USUALLY_TRUE
(
results
[
7
]
>
results
[
8
]);
}
*/
// Check to see if volumes decrease with increasing pressure.
ASSERT
(
results
[
0
]
>
results
[
1
]);
ASSERT
(
results
[
1
]
>
results
[
2
]);
ASSERT
(
results
[
3
]
>
results
[
4
]);
ASSERT
(
results
[
4
]
>
results
[
5
]);
ASSERT
(
results
[
6
]
>
results
[
7
]);
ASSERT
(
results
[
7
]
>
results
[
8
]);
// Check to see if incremental volume changes with increasing pressure go like kx > ky > kz.
// Check to see if incremental volume changes with increasing pressure go like kx > ky > kz.
ASSERT
((
results
[
0
]
-
results
[
1
])
>
(
results
[
3
]
-
results
[
4
]));
ASSERT
_USUALLY_TRUE
((
results
[
0
]
-
results
[
1
])
>
(
results
[
3
]
-
results
[
4
]));
ASSERT
((
results
[
1
]
-
results
[
2
])
>
(
results
[
4
]
-
results
[
5
]));
ASSERT
_USUALLY_TRUE
((
results
[
1
]
-
results
[
2
])
>
(
results
[
4
]
-
results
[
5
]));
ASSERT
((
results
[
3
]
-
results
[
4
])
>
(
results
[
6
]
-
results
[
7
]));
ASSERT
_USUALLY_TRUE
((
results
[
3
]
-
results
[
4
])
>
(
results
[
6
]
-
results
[
7
]));
ASSERT
((
results
[
4
]
-
results
[
5
])
>
(
results
[
7
]
-
results
[
8
]));
ASSERT
_USUALLY_TRUE
((
results
[
4
]
-
results
[
5
])
>
(
results
[
7
]
-
results
[
8
]));
// Check to see if the volumes are equal for isotropic and anisotropic (all axis).
// Check to see if the volumes are equal for isotropic and anisotropic (all axis).
ASSERT_USUALLY_EQUAL_TOL
(
results
[
9
],
results
[
12
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
9
],
results
[
12
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
10
],
results
[
13
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
10
],
results
[
13
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
11
],
results
[
14
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
11
],
results
[
14
],
3
/
std
::
sqrt
((
double
)
steps
));
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
...
...
platforms/opencl/tests/TestOpenCLMonteCarloAnisotropicBarostat.cpp
View file @
3a2f4643
...
@@ -6,8 +6,8 @@
...
@@ -6,8 +6,8 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
2
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Authors: Peter Eastman
*
* Authors: Peter Eastman
, Lee-Ping Wang
*
* Contributors: *
* Contributors: *
* *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* Permission is hereby granted, free of charge, to any person obtaining a *
...
@@ -51,7 +51,7 @@
...
@@ -51,7 +51,7 @@
using
namespace
OpenMM
;
using
namespace
OpenMM
;
using
namespace
std
;
using
namespace
std
;
static
OpenCLPlatform
platform
;
OpenCLPlatform
platform
;
void
testChangingBoxSize
()
{
void
testChangingBoxSize
()
{
System
system
;
System
system
;
...
@@ -191,24 +191,24 @@ void testIdealGasAxis(int axis) {
...
@@ -191,24 +191,24 @@ void testIdealGasAxis(int axis) {
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
boxX
=
box
[
0
][
0
];
boxX
=
box
[
0
][
0
];
boxY
=
box
[
1
][
1
];
boxY
=
box
[
1
][
1
];
boxZ
=
box
[
2
][
2
];
boxZ
=
box
[
2
][
2
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
integrator
.
step
(
frequency
);
}
}
volume
/=
steps
;
volume
/=
steps
;
double
expected
=
(
numParticles
+
1
)
*
BOLTZ
*
temp
[
i
]
/
pressureInMD
;
double
expected
=
(
numParticles
+
1
)
*
BOLTZ
*
temp
[
i
]
/
pressureInMD
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
volume
,
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
volume
,
3
/
std
::
sqrt
((
double
)
steps
));
if
(
!
scaleX
)
{
if
(
!
scaleX
)
{
ASSERT
(
boxX
==
initialLength
);
ASSERT
(
boxX
==
initialLength
);
}
}
if
(
!
scaleY
)
{
if
(
!
scaleY
)
{
ASSERT
(
boxY
==
0.5
*
initialLength
);
ASSERT
(
boxY
==
0.5
*
initialLength
);
}
}
if
(
!
scaleZ
)
{
if
(
!
scaleZ
)
{
ASSERT
(
boxZ
==
2
*
initialLength
);
ASSERT
(
boxZ
==
2
*
initialLength
);
}
}
}
}
}
}
...
@@ -274,155 +274,148 @@ void testRandomSeed() {
...
@@ -274,155 +274,148 @@ void testRandomSeed() {
}
}
}
}
/**
* Run a constant pressure simulation on an anisotropic Einstein crystal
* using isotropic and anisotropic barostats. There are a total of 15 simulations:
*
* 1) 3 pressures: 9.0, 10.0, 11.0 bar, for each of the following groups:
* 2) 3 groups of simulations that scale just one axis: x, y, z
* 3) 1 group of simulations that scales all three axes in the anisotropic barostat
* 4) 1 group of simulations that scales all three axes in the isotropic barostat
*
* Results that we will check:
*
* a) In each group of simulations, the volume should decrease with increasing pressure
* b) In the three simulation groups that scale just one axis, the compressibility (i.e. incremental volume change
* with increasing pressure) should go like kx > ky > kz (because the spring constant is largest in the z-direction)
* c) The anisotropic barostat should produce the same result as the isotropic barostat when all three axes are scaled
*/
void
testEinsteinCrystal
()
{
void
testEinsteinCrystal
()
{
/*
const
int
numParticles
=
64
;
const
int
frequency
=
2
;
Run a constant pressure simulation on an anisotropic Einstein crystal
const
int
equil
=
10000
;
using isotropic and anisotropic barostats. There are a total of 15 simulations:
const
int
steps
=
5000
;
const
double
pressure
=
10.0
;
1) 3 pressures: 9.0, 10.0, 11.0 bar, for each of the following groups:
const
double
pressureInMD
=
pressure
*
(
AVOGADRO
*
1e-25
);
// pressure in kJ/mol/nm^3
2) 3 groups of simulations that scale just one axis: x, y, z
const
double
temp
=
300.0
;
// Only test one temperature since we're looking at three pressures.
3) 1 group of simulations that scales all three axes in the anisotropic barostat
const
double
pres3
[]
=
{
2.0
,
8.0
,
15.0
};
4) 1 group of simulations that scales all three axes in the isotropic barostat
const
double
initialVolume
=
numParticles
*
BOLTZ
*
temp
/
pressureInMD
;
const
double
initialLength
=
std
::
pow
(
initialVolume
,
1.0
/
3.0
);
Results that we will check:
vector
<
double
>
initialPositions
(
3
);
vector
<
double
>
results
;
a) In each group of simulations, the volume should decrease with increasing pressure
// Run four groups of anisotropic simulations; scaling just x, y, z, then all three.
b) In the three simulation groups that scale just one axis, the compressibility (i.e. incremental volume change
for
(
int
a
=
0
;
a
<
4
;
a
++
)
{
with increasing pressure) should go like kx > ky > kz (because the spring constant is largest in the z-direction)
// Test barostat for three different pressures.
c) The anisotropic barostat should produce the same result as the isotropic barostat when all three axes are scaled
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
*/
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
const
int
numParticles
=
64
;
vector
<
Vec3
>
positions
(
numParticles
);
const
int
frequency
=
10
;
OpenMM_SFMT
::
SFMT
sfmt
;
const
int
equil
=
10000
;
init_gen_rand
(
0
,
sfmt
);
const
int
steps
=
10000
;
// Anisotropic force constants.
const
double
pressure
=
10.0
;
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
const
double
pressureInMD
=
pressure
*
(
AVOGADRO
*
1e-25
);
// pressure in kJ/mol/nm^3
force
->
addPerParticleParameter
(
"x0"
);
const
double
temp
=
300.0
;
// Only test one temperature since we're looking at three pressures.
force
->
addPerParticleParameter
(
"y0"
);
const
double
pres3
[]
=
{
9.0
,
10.0
,
11.0
};
force
->
addPerParticleParameter
(
"z0"
);
const
double
initialVolume
=
numParticles
*
BOLTZ
*
temp
/
pressureInMD
;
NonbondedForce
*
nb
=
new
NonbondedForce
();
const
double
initialLength
=
std
::
pow
(
initialVolume
,
1.0
/
3.0
);
nb
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
vector
<
double
>
initialPositions
(
3
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
// All results.
system
.
addParticle
(
1.0
);
double
results
[]
=
{
0.0
,
0.0
,
0.0
,
0.0
,
0.0
,
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
0.0
,
0.0
,
0.0
,
0.0
,
0.0
,
initialPositions
[
0
]
=
positions
[
i
][
0
];
0.0
,
0.0
,
0.0
,
0.0
,
0.0
};
initialPositions
[
1
]
=
positions
[
i
][
1
];
int
simNum
=
0
;
initialPositions
[
2
]
=
positions
[
i
][
2
];
// Run four groups of anisotropic simulations; scaling just x, y, z, then all three.
force
->
addParticle
(
i
,
initialPositions
);
for
(
int
a
=
0
;
a
<
4
;
a
++
)
{
nb
->
addParticle
(
0
,
initialLength
/
6
,
0.1
);
// Test barostat for three different pressures.
}
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
system
.
addForce
(
force
);
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
system
.
addForce
(
nb
);
System
system
;
// Create the barostat.
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
MonteCarloAnisotropicBarostat
*
barostat
=
new
MonteCarloAnisotropicBarostat
(
Vec3
(
pres3
[
p
],
pres3
[
p
],
pres3
[
p
]),
temp
,
frequency
,
(
a
==
0
||
a
==
3
),
(
a
==
1
||
a
==
3
),
(
a
==
2
||
a
==
3
));
vector
<
Vec3
>
positions
(
numParticles
);
system
.
addForce
(
barostat
);
OpenMM_SFMT
::
SFMT
sfmt
;
barostat
->
setTemperature
(
temp
);
init_gen_rand
(
0
,
sfmt
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.01
);
// Anisotropic force constants.
Context
context
(
system
,
integrator
,
platform
);
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
context
.
setPositions
(
positions
);
force
->
addPerParticleParameter
(
"x0"
);
// Let it equilibrate.
force
->
addPerParticleParameter
(
"y0"
);
integrator
.
step
(
equil
);
force
->
addPerParticleParameter
(
"z0"
);
// Now run it for a while and see if the volume is correct.
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
double
volume
=
0.0
;
system
.
addParticle
(
1.0
);
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
Vec3
box
[
3
];
initialPositions
[
0
]
=
positions
[
i
][
0
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
initialPositions
[
1
]
=
positions
[
i
][
1
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
integrator
.
step
(
frequency
);
force
->
addParticle
(
i
,
initialPositions
);
}
}
volume
/=
steps
;
system
.
addForce
(
force
);
results
.
push_back
(
volume
);
// Create the barostat.
}
MonteCarloAnisotropicBarostat
*
barostat
=
new
MonteCarloAnisotropicBarostat
(
Vec3
(
pres3
[
p
],
pres3
[
p
],
pres3
[
p
]),
temp
,
frequency
,
(
a
==
0
||
a
==
3
),
(
a
==
1
||
a
==
3
),
(
a
==
2
||
a
==
3
));
system
.
addForce
(
barostat
);
barostat
->
setTemperature
(
temp
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
equil
);
// Now run it for a while and see if the volume is correct.
double
volume
=
0.0
;
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
}
volume
/=
steps
;
results
[
simNum
]
=
volume
;
simNum
+=
1
;
}
}
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
// Anisotropic force constants.
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
force
->
addPerParticleParameter
(
"x0"
);
force
->
addPerParticleParameter
(
"y0"
);
force
->
addPerParticleParameter
(
"z0"
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
1.0
);
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
initialPositions
[
0
]
=
positions
[
i
][
0
];
initialPositions
[
1
]
=
positions
[
i
][
1
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
force
->
addParticle
(
i
,
initialPositions
);
}
}
system
.
addForce
(
force
);
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create the barostat.
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
MonteCarloBarostat
*
barostat
=
new
MonteCarloBarostat
(
pres3
[
p
],
temp
,
frequency
);
System
system
;
system
.
addForce
(
barostat
);
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
barostat
->
setTemperature
(
temp
);
vector
<
Vec3
>
positions
(
numParticles
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.01
);
OpenMM_SFMT
::
SFMT
sfmt
;
Context
context
(
system
,
integrator
,
platform
);
init_gen_rand
(
0
,
sfmt
);
context
.
setPositions
(
positions
);
// Anisotropic force constants.
// Let it equilibrate.
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
integrator
.
step
(
equil
);
force
->
addPerParticleParameter
(
"x0"
);
// Now run it for a while and see if the volume is correct.
force
->
addPerParticleParameter
(
"y0"
);
double
volume
=
0.0
;
force
->
addPerParticleParameter
(
"z0"
);
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
NonbondedForce
*
nb
=
new
NonbondedForce
();
Vec3
box
[
3
];
nb
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
system
.
addParticle
(
1.0
);
integrator
.
step
(
frequency
);
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
initialPositions
[
0
]
=
positions
[
i
][
0
];
initialPositions
[
1
]
=
positions
[
i
][
1
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
force
->
addParticle
(
i
,
initialPositions
);
nb
->
addParticle
(
0
,
initialLength
/
6
,
0.1
);
}
system
.
addForce
(
force
);
system
.
addForce
(
nb
);
// Create the barostat.
MonteCarloBarostat
*
barostat
=
new
MonteCarloBarostat
(
pres3
[
p
],
temp
,
frequency
);
system
.
addForce
(
barostat
);
barostat
->
setTemperature
(
temp
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.001
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
equil
);
// Now run it for a while and see if the volume is correct.
double
volume
=
0.0
;
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
}
volume
/=
steps
;
results
.
push_back
(
volume
);
}
}
volume
/=
steps
;
results
[
simNum
]
=
volume
;
// Check to see if volumes decrease with increasing pressure.
simNum
+=
1
;
ASSERT_USUALLY_TRUE
(
results
[
0
]
>
results
[
1
]);
}
ASSERT_USUALLY_TRUE
(
results
[
1
]
>
results
[
2
]);
ASSERT_USUALLY_TRUE
(
results
[
3
]
>
results
[
4
]);
/*
ASSERT_USUALLY_TRUE
(
results
[
4
]
>
results
[
5
]);
for (int j = 0; j < 15; j++) {
ASSERT_USUALLY_TRUE
(
results
[
6
]
>
results
[
7
]);
printf("%.6f\n",results[j]);
ASSERT_USUALLY_TRUE
(
results
[
7
]
>
results
[
8
]);
}
*/
// Check to see if volumes decrease with increasing pressure.
ASSERT
(
results
[
0
]
>
results
[
1
]);
ASSERT
(
results
[
1
]
>
results
[
2
]);
ASSERT
(
results
[
3
]
>
results
[
4
]);
ASSERT
(
results
[
4
]
>
results
[
5
]);
ASSERT
(
results
[
6
]
>
results
[
7
]);
ASSERT
(
results
[
7
]
>
results
[
8
]);
// Check to see if incremental volume changes with increasing pressure go like kx > ky > kz.
// Check to see if incremental volume changes with increasing pressure go like kx > ky > kz.
ASSERT
((
results
[
0
]
-
results
[
1
])
>
(
results
[
3
]
-
results
[
4
]));
ASSERT
_USUALLY_TRUE
((
results
[
0
]
-
results
[
1
])
>
(
results
[
3
]
-
results
[
4
]));
ASSERT
((
results
[
1
]
-
results
[
2
])
>
(
results
[
4
]
-
results
[
5
]));
ASSERT
_USUALLY_TRUE
((
results
[
1
]
-
results
[
2
])
>
(
results
[
4
]
-
results
[
5
]));
ASSERT
((
results
[
3
]
-
results
[
4
])
>
(
results
[
6
]
-
results
[
7
]));
ASSERT
_USUALLY_TRUE
((
results
[
3
]
-
results
[
4
])
>
(
results
[
6
]
-
results
[
7
]));
ASSERT
((
results
[
4
]
-
results
[
5
])
>
(
results
[
7
]
-
results
[
8
]));
ASSERT
_USUALLY_TRUE
((
results
[
4
]
-
results
[
5
])
>
(
results
[
7
]
-
results
[
8
]));
// Check to see if the volumes are equal for isotropic and anisotropic (all axis).
// Check to see if the volumes are equal for isotropic and anisotropic (all axis).
ASSERT_USUALLY_EQUAL_TOL
(
results
[
9
],
results
[
12
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
9
],
results
[
12
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
10
],
results
[
13
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
10
],
results
[
13
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
11
],
results
[
14
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
11
],
results
[
14
],
3
/
std
::
sqrt
((
double
)
steps
));
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
...
...
platforms/reference/tests/TestReferenceMonteCarloAnisotropicBarostat.cpp
View file @
3a2f4643
...
@@ -6,8 +6,8 @@
...
@@ -6,8 +6,8 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* *
* Portions copyright (c) 2008-201
0
Stanford University and the Authors. *
* Portions copyright (c) 2008-201
3
Stanford University and the Authors. *
* Authors: Peter Eastman
*
* Authors: Peter Eastman
, Lee-Ping Wang
*
* Contributors: *
* Contributors: *
* *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* Permission is hereby granted, free of charge, to any person obtaining a *
...
@@ -34,6 +34,8 @@
...
@@ -34,6 +34,8 @@
*/
*/
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/CustomExternalForce.h"
#include "openmm/MonteCarloBarostat.h"
#include "openmm/MonteCarloAnisotropicBarostat.h"
#include "openmm/MonteCarloAnisotropicBarostat.h"
#include "openmm/Context.h"
#include "openmm/Context.h"
#include "ReferencePlatform.h"
#include "ReferencePlatform.h"
...
@@ -190,24 +192,24 @@ void testIdealGasAxis(int axis) {
...
@@ -190,24 +192,24 @@ void testIdealGasAxis(int axis) {
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
boxX
=
box
[
0
][
0
];
boxX
=
box
[
0
][
0
];
boxY
=
box
[
1
][
1
];
boxY
=
box
[
1
][
1
];
boxZ
=
box
[
2
][
2
];
boxZ
=
box
[
2
][
2
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
integrator
.
step
(
frequency
);
}
}
volume
/=
steps
;
volume
/=
steps
;
double
expected
=
(
numParticles
+
1
)
*
BOLTZ
*
temp
[
i
]
/
pressureInMD
;
double
expected
=
(
numParticles
+
1
)
*
BOLTZ
*
temp
[
i
]
/
pressureInMD
;
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
volume
,
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
expected
,
volume
,
3
/
std
::
sqrt
((
double
)
steps
));
if
(
!
scaleX
)
{
if
(
!
scaleX
)
{
ASSERT
(
boxX
==
initialLength
);
ASSERT
(
boxX
==
initialLength
);
}
}
if
(
!
scaleY
)
{
if
(
!
scaleY
)
{
ASSERT
(
boxY
==
0.5
*
initialLength
);
ASSERT
(
boxY
==
0.5
*
initialLength
);
}
}
if
(
!
scaleZ
)
{
if
(
!
scaleZ
)
{
ASSERT
(
boxZ
==
2
*
initialLength
);
ASSERT
(
boxZ
==
2
*
initialLength
);
}
}
}
}
}
}
...
@@ -274,13 +276,159 @@ void testRandomSeed() {
...
@@ -274,13 +276,159 @@ void testRandomSeed() {
}
}
}
}
/**
* Run a constant pressure simulation on an anisotropic Einstein crystal
* using isotropic and anisotropic barostats. There are a total of 15 simulations:
*
* 1) 3 pressures: 9.0, 10.0, 11.0 bar, for each of the following groups:
* 2) 3 groups of simulations that scale just one axis: x, y, z
* 3) 1 group of simulations that scales all three axes in the anisotropic barostat
* 4) 1 group of simulations that scales all three axes in the isotropic barostat
*
* Results that we will check:
*
* a) In each group of simulations, the volume should decrease with increasing pressure
* b) In the three simulation groups that scale just one axis, the compressibility (i.e. incremental volume change
* with increasing pressure) should go like kx > ky > kz (because the spring constant is largest in the z-direction)
* c) The anisotropic barostat should produce the same result as the isotropic barostat when all three axes are scaled
*/
void
testEinsteinCrystal
()
{
const
int
numParticles
=
64
;
const
int
frequency
=
2
;
const
int
equil
=
10000
;
const
int
steps
=
5000
;
const
double
pressure
=
10.0
;
const
double
pressureInMD
=
pressure
*
(
AVOGADRO
*
1e-25
);
// pressure in kJ/mol/nm^3
const
double
temp
=
300.0
;
// Only test one temperature since we're looking at three pressures.
const
double
pres3
[]
=
{
2.0
,
8.0
,
15.0
};
const
double
initialVolume
=
numParticles
*
BOLTZ
*
temp
/
pressureInMD
;
const
double
initialLength
=
std
::
pow
(
initialVolume
,
1.0
/
3.0
);
ReferencePlatform
platform
;
vector
<
double
>
initialPositions
(
3
);
vector
<
double
>
results
;
// Run four groups of anisotropic simulations; scaling just x, y, z, then all three.
for
(
int
a
=
0
;
a
<
4
;
a
++
)
{
// Test barostat for three different pressures.
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
// Anisotropic force constants.
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
force
->
addPerParticleParameter
(
"x0"
);
force
->
addPerParticleParameter
(
"y0"
);
force
->
addPerParticleParameter
(
"z0"
);
NonbondedForce
*
nb
=
new
NonbondedForce
();
nb
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
1.0
);
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
initialPositions
[
0
]
=
positions
[
i
][
0
];
initialPositions
[
1
]
=
positions
[
i
][
1
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
force
->
addParticle
(
i
,
initialPositions
);
nb
->
addParticle
(
0
,
initialLength
/
6
,
0.1
);
}
system
.
addForce
(
force
);
system
.
addForce
(
nb
);
// Create the barostat.
MonteCarloAnisotropicBarostat
*
barostat
=
new
MonteCarloAnisotropicBarostat
(
Vec3
(
pres3
[
p
],
pres3
[
p
],
pres3
[
p
]),
temp
,
frequency
,
(
a
==
0
||
a
==
3
),
(
a
==
1
||
a
==
3
),
(
a
==
2
||
a
==
3
));
system
.
addForce
(
barostat
);
barostat
->
setTemperature
(
temp
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.01
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
equil
);
// Now run it for a while and see if the volume is correct.
double
volume
=
0.0
;
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
}
volume
/=
steps
;
results
.
push_back
(
volume
);
}
}
for
(
int
p
=
0
;
p
<
3
;
p
++
)
{
// Create a system of noninteracting particles attached by harmonic springs to their initial positions.
System
system
;
system
.
setDefaultPeriodicBoxVectors
(
Vec3
(
initialLength
,
0
,
0
),
Vec3
(
0
,
initialLength
,
0
),
Vec3
(
0
,
0
,
initialLength
));
vector
<
Vec3
>
positions
(
numParticles
);
OpenMM_SFMT
::
SFMT
sfmt
;
init_gen_rand
(
0
,
sfmt
);
// Anisotropic force constants.
CustomExternalForce
*
force
=
new
CustomExternalForce
(
"0.005*(x-x0)^2 + 0.01*(y-y0)^2 + 0.02*(z-z0)^2"
);
force
->
addPerParticleParameter
(
"x0"
);
force
->
addPerParticleParameter
(
"y0"
);
force
->
addPerParticleParameter
(
"z0"
);
NonbondedForce
*
nb
=
new
NonbondedForce
();
nb
->
setNonbondedMethod
(
NonbondedForce
::
CutoffPeriodic
);
for
(
int
i
=
0
;
i
<
numParticles
;
++
i
)
{
system
.
addParticle
(
1.0
);
positions
[
i
]
=
Vec3
(((
i
/
16
)
%
4
+
0.5
)
*
initialLength
/
4
,
((
i
/
4
)
%
4
+
0.5
)
*
initialLength
/
4
,
(
i
%
4
+
0.5
)
*
initialLength
/
4
);
initialPositions
[
0
]
=
positions
[
i
][
0
];
initialPositions
[
1
]
=
positions
[
i
][
1
];
initialPositions
[
2
]
=
positions
[
i
][
2
];
force
->
addParticle
(
i
,
initialPositions
);
nb
->
addParticle
(
0
,
initialLength
/
6
,
0.1
);
}
system
.
addForce
(
force
);
system
.
addForce
(
nb
);
// Create the barostat.
MonteCarloBarostat
*
barostat
=
new
MonteCarloBarostat
(
pres3
[
p
],
temp
,
frequency
);
system
.
addForce
(
barostat
);
barostat
->
setTemperature
(
temp
);
LangevinIntegrator
integrator
(
temp
,
0.1
,
0.001
);
Context
context
(
system
,
integrator
,
platform
);
context
.
setPositions
(
positions
);
// Let it equilibrate.
integrator
.
step
(
equil
);
// Now run it for a while and see if the volume is correct.
double
volume
=
0.0
;
for
(
int
j
=
0
;
j
<
steps
;
++
j
)
{
Vec3
box
[
3
];
context
.
getState
(
0
).
getPeriodicBoxVectors
(
box
[
0
],
box
[
1
],
box
[
2
]);
volume
+=
box
[
0
][
0
]
*
box
[
1
][
1
]
*
box
[
2
][
2
];
integrator
.
step
(
frequency
);
}
volume
/=
steps
;
results
.
push_back
(
volume
);
}
// Check to see if volumes decrease with increasing pressure.
ASSERT_USUALLY_TRUE
(
results
[
0
]
>
results
[
1
]);
ASSERT_USUALLY_TRUE
(
results
[
1
]
>
results
[
2
]);
ASSERT_USUALLY_TRUE
(
results
[
3
]
>
results
[
4
]);
ASSERT_USUALLY_TRUE
(
results
[
4
]
>
results
[
5
]);
ASSERT_USUALLY_TRUE
(
results
[
6
]
>
results
[
7
]);
ASSERT_USUALLY_TRUE
(
results
[
7
]
>
results
[
8
]);
// Check to see if incremental volume changes with increasing pressure go like kx > ky > kz.
ASSERT_USUALLY_TRUE
((
results
[
0
]
-
results
[
1
])
>
(
results
[
3
]
-
results
[
4
]));
ASSERT_USUALLY_TRUE
((
results
[
1
]
-
results
[
2
])
>
(
results
[
4
]
-
results
[
5
]));
ASSERT_USUALLY_TRUE
((
results
[
3
]
-
results
[
4
])
>
(
results
[
6
]
-
results
[
7
]));
ASSERT_USUALLY_TRUE
((
results
[
4
]
-
results
[
5
])
>
(
results
[
7
]
-
results
[
8
]));
// Check to see if the volumes are equal for isotropic and anisotropic (all axis).
ASSERT_USUALLY_EQUAL_TOL
(
results
[
9
],
results
[
12
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
10
],
results
[
13
],
3
/
std
::
sqrt
((
double
)
steps
));
ASSERT_USUALLY_EQUAL_TOL
(
results
[
11
],
results
[
14
],
3
/
std
::
sqrt
((
double
)
steps
));
}
int
main
()
{
int
main
()
{
try
{
try
{
testIdealGas
();
testIdealGas
();
testIdealGasAxis
(
0
);
testIdealGasAxis
(
0
);
testIdealGasAxis
(
1
);
testIdealGasAxis
(
1
);
testIdealGasAxis
(
2
);
testIdealGasAxis
(
2
);
testRandomSeed
();
testRandomSeed
();
testEinsteinCrystal
();
}
}
catch
(
const
exception
&
e
)
{
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment