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
5cef29ce
Unverified
Commit
5cef29ce
authored
Nov 04, 2019
by
Andy Simmonett
Browse files
Small fix for travis, make NHC public and add serialization code
parent
9f46a7fc
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
328 additions
and
28 deletions
+328
-28
olla/include/openmm/kernels.h
olla/include/openmm/kernels.h
+1
-1
openmmapi/include/OpenMM.h
openmmapi/include/OpenMM.h
+1
-0
openmmapi/include/openmm/NoseHooverChain.h
openmmapi/include/openmm/NoseHooverChain.h
+1
-1
openmmapi/include/openmm/NoseHooverIntegrator.h
openmmapi/include/openmm/NoseHooverIntegrator.h
+24
-11
openmmapi/src/NoseHooverChain.cpp
openmmapi/src/NoseHooverChain.cpp
+1
-1
openmmapi/src/NoseHooverIntegrator.cpp
openmmapi/src/NoseHooverIntegrator.cpp
+20
-4
platforms/opencl/include/OpenCLKernels.h
platforms/opencl/include/OpenCLKernels.h
+1
-1
plugins/drude/openmmapi/src/DrudeNoseHooverIntegrator.cpp
plugins/drude/openmmapi/src/DrudeNoseHooverIntegrator.cpp
+1
-0
plugins/drude/tests/TestDrudeNoseHoover.h
plugins/drude/tests/TestDrudeNoseHoover.h
+1
-1
serialization/include/openmm/serialization/NoseHooverIntegratorProxy.h
.../include/openmm/serialization/NoseHooverIntegratorProxy.h
+17
-0
serialization/src/NoseHooverIntegratorProxy.cpp
serialization/src/NoseHooverIntegratorProxy.cpp
+126
-0
serialization/src/SerializationProxyRegistration.cpp
serialization/src/SerializationProxyRegistration.cpp
+4
-1
serialization/tests/TestSerializeNoseHooverIntegrator.cpp
serialization/tests/TestSerializeNoseHooverIntegrator.cpp
+122
-0
tests/TestNoseHooverThermostat.h
tests/TestNoseHooverThermostat.h
+1
-1
wrappers/python/setup.py
wrappers/python/setup.py
+1
-1
wrappers/python/src/swig_doxygen/swigInputConfig.py
wrappers/python/src/swig_doxygen/swigInputConfig.py
+6
-5
No files found.
olla/include/openmm/kernels.h
View file @
5cef29ce
...
@@ -55,7 +55,6 @@
...
@@ -55,7 +55,6 @@
#include "openmm/KernelImpl.h"
#include "openmm/KernelImpl.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/LangevinIntegrator.h"
#include "openmm/MonteCarloBarostat.h"
#include "openmm/MonteCarloBarostat.h"
#include "openmm/internal/NoseHooverChain.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/RMSDForce.h"
#include "openmm/RMSDForce.h"
...
@@ -65,6 +64,7 @@
...
@@ -65,6 +64,7 @@
#include "openmm/VariableVerletIntegrator.h"
#include "openmm/VariableVerletIntegrator.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/NoseHooverChain.h"
#include <iosfwd>
#include <iosfwd>
#include <set>
#include <set>
#include <string>
#include <string>
...
...
openmmapi/include/OpenMM.h
View file @
5cef29ce
...
@@ -75,6 +75,7 @@
...
@@ -75,6 +75,7 @@
#include "openmm/Vec3.h"
#include "openmm/Vec3.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/VerletIntegrator.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/NoseHooverChain.h"
#include "openmm/VirtualSite.h"
#include "openmm/VirtualSite.h"
#include "openmm/Platform.h"
#include "openmm/Platform.h"
#include "openmm/serialization/XmlSerializer.h"
#include "openmm/serialization/XmlSerializer.h"
...
...
openmmapi/include/openmm/
internal/
NoseHooverChain.h
→
openmmapi/include/openmm/NoseHooverChain.h
View file @
5cef29ce
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
#include <string>
#include <string>
#include <vector>
#include <vector>
#include "openmm/OpenMMException.h"
#include "openmm/OpenMMException.h"
#include "windowsExport.h"
#include "
internal/
windowsExport.h"
namespace
OpenMM
{
namespace
OpenMM
{
...
...
openmmapi/include/openmm/NoseHooverIntegrator.h
View file @
5cef29ce
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
#include "Integrator.h"
#include "Integrator.h"
#include "openmm/State.h"
#include "openmm/State.h"
#include "openmm/Kernel.h"
#include "openmm/Kernel.h"
#include "
internal/
NoseHooverChain.h"
#include "NoseHooverChain.h"
#include "internal/windowsExport.h"
#include "internal/windowsExport.h"
namespace
OpenMM
{
namespace
OpenMM
{
...
@@ -118,7 +118,7 @@ public:
...
@@ -118,7 +118,7 @@ public:
/**
/**
* Get the temperature of the i-th chain for controling absolute particle motion (in Kelvin).
* Get the temperature of the i-th chain for controling absolute particle motion (in Kelvin).
*
*
* @param chainID the index of the Nose-Hoover chain (default=0).
* @param chainID the index of the Nose-Hoover chain
thermostat
(default=0).
*
*
* @return the temperature.
* @return the temperature.
*/
*/
...
@@ -127,13 +127,13 @@ public:
...
@@ -127,13 +127,13 @@ public:
* set the (absolute motion) temperature of the i-th chain.
* set the (absolute motion) temperature of the i-th chain.
*
*
* @param temperature the temperature for the Nose-Hoover chain thermostat (in Kelvin).
* @param temperature the temperature for the Nose-Hoover chain thermostat (in Kelvin).
* @param chainID The id of the Nose-Hoover chain for which the temperature is set (default=0).
* @param chainID The id of the Nose-Hoover chain
thermostat
for which the temperature is set (default=0).
*/
*/
void
setTemperature
(
double
temperature
,
int
chainID
=
0
);
void
setTemperature
(
double
temperature
,
int
chainID
=
0
);
/**
/**
* Get the temperature of the i-th chain for controling pairs' relative particle motion (in Kelvin).
* Get the temperature of the i-th chain for controling pairs' relative particle motion (in Kelvin).
*
*
* @param chainID the index of the Nose-Hoover chain (default=0).
* @param chainID the index of the Nose-Hoover chain
thermostat
(default=0).
*
*
* @return the temperature.
* @return the temperature.
*/
*/
...
@@ -142,13 +142,13 @@ public:
...
@@ -142,13 +142,13 @@ public:
* set the (relative pair motion) temperature of the i-th chain.
* set the (relative pair motion) temperature of the i-th chain.
*
*
* @param temperature the temperature for the Nose-Hoover chain thermostat (in Kelvin).
* @param temperature the temperature for the Nose-Hoover chain thermostat (in Kelvin).
* @param chainID The id of the Nose-Hoover chain for which the temperature is set (default=0).
* @param chainID The id of the Nose-Hoover chain
thermostat
for which the temperature is set (default=0).
*/
*/
void
setRelativeTemperature
(
double
temperature
,
int
chainID
=
0
);
void
setRelativeTemperature
(
double
temperature
,
int
chainID
=
0
);
/**
/**
* Get the collision frequency for absolute motion of the i-th chain (in 1/picosecond).
* Get the collision frequency for absolute motion of the i-th chain (in 1/picosecond).
*
*
* @param chainID the index of the Nose-Hoover chain (default=0).
* @param chainID the index of the Nose-Hoover chain
thermostat
(default=0).
*
*
* @return the collision frequency.
* @return the collision frequency.
*/
*/
...
@@ -157,13 +157,13 @@ public:
...
@@ -157,13 +157,13 @@ public:
* Set the collision frequency for absolute motion of the i-th chain.
* Set the collision frequency for absolute motion of the i-th chain.
*
*
* @param frequency the collision frequency in picosecond.
* @param frequency the collision frequency in picosecond.
* @param chainID the index of the Nose-Hoover chain (default=0).
* @param chainID the index of the Nose-Hoover chain
thermostat
(default=0).
*/
*/
void
setCollisionFrequency
(
double
frequency
,
int
chainID
=
0
);
void
setCollisionFrequency
(
double
frequency
,
int
chainID
=
0
);
/**
/**
* Get the collision frequency for pairs' relative motion of the i-th chain (in 1/picosecond).
* Get the collision frequency for pairs' relative motion of the i-th chain (in 1/picosecond).
*
*
* @param chainID the index of the Nose-Hoover chain (default=0).
* @param chainID the index of the Nose-Hoover chain
thermostat
(default=0).
*
*
* @return the collision frequency.
* @return the collision frequency.
*/
*/
...
@@ -172,7 +172,7 @@ public:
...
@@ -172,7 +172,7 @@ public:
* Set the collision frequency for pairs' relative motion of the i-th chain.
* Set the collision frequency for pairs' relative motion of the i-th chain.
*
*
* @param frequency the collision frequency in picosecond.
* @param frequency the collision frequency in picosecond.
* @param chainID the index of the Nose-Hoover chain (default=0).
* @param chainID the index of the Nose-Hoover chain
thermostat
(default=0).
*/
*/
void
setRelativeCollisionFrequency
(
double
frequency
,
int
chainID
=
0
);
void
setRelativeCollisionFrequency
(
double
frequency
,
int
chainID
=
0
);
/**
/**
...
@@ -183,9 +183,15 @@ public:
...
@@ -183,9 +183,15 @@ public:
/**
/**
* Get the number of Nose-Hoover chains registered with this integrator.
* Get the number of Nose-Hoover chains registered with this integrator.
*/
*/
int
getNumNoseHoover
Chain
s
()
const
{
int
getNumNoseHoover
Thermostat
s
()
const
{
return
noseHooverChains
.
size
();
return
noseHooverChains
.
size
();
}
}
/**
* Get the NoseHooverChain thermostat
*
* @param chainID the index of the Nose-Hoover chain thermostat (default=0).
*/
const
NoseHooverChain
&
getNoseHooverThermostat
(
int
chainID
=
0
)
const
;
/**
/**
* This will be called by the Context when the user modifies aspects of the context state, such
* This will be called by the Context when the user modifies aspects of the context state, such
* as positions, velocities, or parameters. This gives the Integrator a chance to discard cached
* as positions, velocities, or parameters. This gives the Integrator a chance to discard cached
...
@@ -198,7 +204,13 @@ public:
...
@@ -198,7 +204,13 @@ public:
virtual
void
stateChanged
(
State
::
DataType
changed
)
{
virtual
void
stateChanged
(
State
::
DataType
changed
)
{
if
(
State
::
Positions
==
changed
)
forcesAreValid
=
false
;
if
(
State
::
Positions
==
changed
)
forcesAreValid
=
false
;
}
}
/**
* Return false, if this integrator was set up with the 'default constructor' that thermostats the whole system,
* true otherwise. Required for serialization.
*/
bool
hasSubsystemThermostats
()
const
{
return
hasSubsystemThermostats_
;
}
protected:
protected:
/**
/**
* Advance any Nose-Hoover chains associated with this integrator and determine
* Advance any Nose-Hoover chains associated with this integrator and determine
...
@@ -236,6 +248,7 @@ protected:
...
@@ -236,6 +248,7 @@ protected:
std
::
vector
<
NoseHooverChain
>
noseHooverChains
;
std
::
vector
<
NoseHooverChain
>
noseHooverChains
;
bool
forcesAreValid
;
bool
forcesAreValid
;
Kernel
vvKernel
,
nhcKernel
;
Kernel
vvKernel
,
nhcKernel
;
bool
hasSubsystemThermostats_
;
};
};
}
// namespace OpenMM
}
// namespace OpenMM
...
...
openmmapi/src/NoseHooverChain.cpp
View file @
5cef29ce
...
@@ -29,7 +29,7 @@
...
@@ -29,7 +29,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "openmm/
internal/
NoseHooverChain.h"
#include "openmm/NoseHooverChain.h"
#include "openmm/OpenMMException.h"
#include "openmm/OpenMMException.h"
using
namespace
OpenMM
;
using
namespace
OpenMM
;
...
...
openmmapi/src/NoseHooverIntegrator.cpp
View file @
5cef29ce
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
#include "openmm/Context.h"
#include "openmm/Context.h"
#include "openmm/Force.h"
#include "openmm/Force.h"
#include "openmm/System.h"
#include "openmm/System.h"
#include "openmm/
internal/
NoseHooverChain.h"
#include "openmm/NoseHooverChain.h"
#include "openmm/OpenMMException.h"
#include "openmm/OpenMMException.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/ContextImpl.h"
...
@@ -48,13 +48,17 @@ using std::string;
...
@@ -48,13 +48,17 @@ using std::string;
using
std
::
vector
;
using
std
::
vector
;
NoseHooverIntegrator
::
NoseHooverIntegrator
(
double
stepSize
)
:
NoseHooverIntegrator
::
NoseHooverIntegrator
(
double
stepSize
)
:
forcesAreValid
(
false
)
forcesAreValid
(
false
),
hasSubsystemThermostats_
(
true
)
{
{
setStepSize
(
stepSize
);
setStepSize
(
stepSize
);
setConstraintTolerance
(
1e-5
);
setConstraintTolerance
(
1e-5
);
}
}
NoseHooverIntegrator
::
NoseHooverIntegrator
(
double
temperature
,
double
collisionFrequency
,
double
stepSize
,
NoseHooverIntegrator
::
NoseHooverIntegrator
(
double
temperature
,
double
collisionFrequency
,
double
stepSize
,
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
:
forcesAreValid
(
false
)
{
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
:
forcesAreValid
(
false
),
hasSubsystemThermostats_
(
false
)
{
setStepSize
(
stepSize
);
setStepSize
(
stepSize
);
setConstraintTolerance
(
1e-5
);
setConstraintTolerance
(
1e-5
);
addThermostat
(
temperature
,
collisionFrequency
,
chainLength
,
numMTS
,
numYoshidaSuzuki
);
addThermostat
(
temperature
,
collisionFrequency
,
chainLength
,
numMTS
,
numYoshidaSuzuki
);
...
@@ -69,7 +73,7 @@ std::pair<double, double> NoseHooverIntegrator::propagateChain(std::pair<double,
...
@@ -69,7 +73,7 @@ std::pair<double, double> NoseHooverIntegrator::propagateChain(std::pair<double,
int
NoseHooverIntegrator
::
addThermostat
(
double
temperature
,
double
collisionFrequency
,
int
NoseHooverIntegrator
::
addThermostat
(
double
temperature
,
double
collisionFrequency
,
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
{
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
{
hasSubsystemThermostats_
=
false
;
return
addSubsystemThermostat
(
std
::
vector
<
int
>
(),
std
::
vector
<
std
::
pair
<
int
,
int
>>
(),
temperature
,
return
addSubsystemThermostat
(
std
::
vector
<
int
>
(),
std
::
vector
<
std
::
pair
<
int
,
int
>>
(),
temperature
,
collisionFrequency
,
temperature
,
collisionFrequency
,
chainLength
,
numMTS
,
numYoshidaSuzuki
);
collisionFrequency
,
temperature
,
collisionFrequency
,
chainLength
,
numMTS
,
numYoshidaSuzuki
);
}
}
...
@@ -80,6 +84,14 @@ int NoseHooverIntegrator::addSubsystemThermostat(const std::vector<int>& thermos
...
@@ -80,6 +84,14 @@ int NoseHooverIntegrator::addSubsystemThermostat(const std::vector<int>& thermos
double
relativeTemperature
,
double
relativeCollisionFrequency
,
double
relativeTemperature
,
double
relativeCollisionFrequency
,
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
{
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
{
int
chainID
=
noseHooverChains
.
size
();
int
chainID
=
noseHooverChains
.
size
();
// check if one thermostat already applies to all atoms or pairs
if
(
(
chainID
>
0
)
&&
(
noseHooverChains
[
0
].
getThermostatedAtoms
().
size
()
*
noseHooverChains
[
0
].
getThermostatedPairs
().
size
()
==
0
)
)
{
throw
OpenMMException
(
"Cannot add thermostat, since one of the thermostats already in the integrator applies to all particles. "
"To manually add thermostats, use the constructor that takes only the "
"step size as an input argument."
);
}
int
nDOF
=
0
;
// is set in initializeThermostats()
int
nDOF
=
0
;
// is set in initializeThermostats()
noseHooverChains
.
emplace_back
(
temperature
,
relativeTemperature
,
noseHooverChains
.
emplace_back
(
temperature
,
relativeTemperature
,
collisionFrequency
,
relativeCollisionFrequency
,
collisionFrequency
,
relativeCollisionFrequency
,
...
@@ -89,6 +101,10 @@ int NoseHooverIntegrator::addSubsystemThermostat(const std::vector<int>& thermos
...
@@ -89,6 +101,10 @@ int NoseHooverIntegrator::addSubsystemThermostat(const std::vector<int>& thermos
return
chainID
;
return
chainID
;
}
}
const
NoseHooverChain
&
NoseHooverIntegrator
::
getNoseHooverThermostat
(
int
chainID
)
const
{
ASSERT_VALID_INDEX
(
chainID
,
noseHooverChains
);
return
noseHooverChains
[
chainID
];
}
void
NoseHooverIntegrator
::
initializeThermostats
(
const
System
&
system
)
{
void
NoseHooverIntegrator
::
initializeThermostats
(
const
System
&
system
)
{
...
...
platforms/opencl/include/OpenCLKernels.h
View file @
5cef29ce
...
@@ -36,13 +36,13 @@
...
@@ -36,13 +36,13 @@
#include "openmm/kernels.h"
#include "openmm/kernels.h"
#include "openmm/internal/CompiledExpressionSet.h"
#include "openmm/internal/CompiledExpressionSet.h"
#include "openmm/internal/CustomIntegratorUtilities.h"
#include "openmm/internal/CustomIntegratorUtilities.h"
#include "openmm/internal/NoseHooverChain.h"
#include "lepton/CompiledExpression.h"
#include "lepton/CompiledExpression.h"
#include "lepton/ExpressionProgram.h"
#include "lepton/ExpressionProgram.h"
#include "openmm/System.h"
#include "openmm/System.h"
namespace
OpenMM
{
namespace
OpenMM
{
/**
/**
* This kernel is invoked at the beginning and end of force and energy computations. It gives the
* This kernel is invoked at the beginning and end of force and energy computations. It gives the
* Platform a chance to clear buffers and do other initialization at the beginning, and to do any
* Platform a chance to clear buffers and do other initialization at the beginning, and to do any
...
...
plugins/drude/openmmapi/src/DrudeNoseHooverIntegrator.cpp
View file @
5cef29ce
...
@@ -51,6 +51,7 @@ DrudeNoseHooverIntegrator::DrudeNoseHooverIntegrator(double temperature, double
...
@@ -51,6 +51,7 @@ DrudeNoseHooverIntegrator::DrudeNoseHooverIntegrator(double temperature, double
double
stepSize
,
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
:
double
stepSize
,
int
chainLength
,
int
numMTS
,
int
numYoshidaSuzuki
)
:
NoseHooverIntegrator
(
stepSize
)
{
NoseHooverIntegrator
(
stepSize
)
{
hasSubsystemThermostats_
=
false
;
addSubsystemThermostat
(
std
::
vector
<
int
>
(),
std
::
vector
<
std
::
pair
<
int
,
int
>>
(),
temperature
,
addSubsystemThermostat
(
std
::
vector
<
int
>
(),
std
::
vector
<
std
::
pair
<
int
,
int
>>
(),
temperature
,
collisionFrequency
,
drudeTemperature
,
drudeCollisionFrequency
,
collisionFrequency
,
drudeTemperature
,
drudeCollisionFrequency
,
chainLength
,
numMTS
,
numYoshidaSuzuki
);
chainLength
,
numMTS
,
numYoshidaSuzuki
);
...
...
plugins/drude/tests/TestDrudeNoseHoover.h
View file @
5cef29ce
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/
internal/
NoseHooverChain.h"
#include "openmm/NoseHooverChain.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/CMMotionRemover.h"
#include "openmm/DrudeNoseHooverIntegrator.h"
#include "openmm/DrudeNoseHooverIntegrator.h"
#include "openmm/Context.h"
#include "openmm/Context.h"
...
...
serialization/include/openmm/serialization/NoseHooverIntegratorProxy.h
0 → 100644
View file @
5cef29ce
#ifndef OPENMM_NOSE_HOOVER_INTEGRATOR_PROXY_H_
#define OPENMM_NOSE_HOOVER_INTEGRATOR_PROXY_H_
#include "openmm/serialization/XmlSerializer.h"
namespace
OpenMM
{
class
NoseHooverIntegratorProxy
:
public
SerializationProxy
{
public:
NoseHooverIntegratorProxy
();
void
serialize
(
const
void
*
object
,
SerializationNode
&
node
)
const
;
void
*
deserialize
(
const
SerializationNode
&
node
)
const
;
};
}
#endif
/*OPENMM_NOSE_HOOVER_INTEGRATOR_PROXY_H_*/
serialization/src/NoseHooverIntegratorProxy.cpp
0 → 100644
View file @
5cef29ce
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010 Stanford University and the Authors. *
* Authors: Andrew C. Simmonett, Andreas Krämer *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/serialization/NoseHooverIntegratorProxy.h"
#include <vector>
#include <OpenMM.h>
using
namespace
std
;
using
namespace
OpenMM
;
NoseHooverIntegratorProxy
::
NoseHooverIntegratorProxy
()
:
SerializationProxy
(
"NoseHooverIntegrator"
)
{
}
void
NoseHooverIntegratorProxy
::
serialize
(
const
void
*
object
,
SerializationNode
&
node
)
const
{
node
.
setIntProperty
(
"version"
,
1
);
const
NoseHooverIntegrator
&
integrator
=
*
reinterpret_cast
<
const
NoseHooverIntegrator
*>
(
object
);
node
.
setDoubleProperty
(
"stepSize"
,
integrator
.
getStepSize
());
node
.
setDoubleProperty
(
"constraintTolerance"
,
integrator
.
getConstraintTolerance
());
node
.
setBoolProperty
(
"hasSubsystemThermostats"
,
integrator
.
hasSubsystemThermostats
());
if
(
integrator
.
hasSubsystemThermostats
())
{
// Serialize all thermostats separately
for
(
int
i
=
0
;
i
<
integrator
.
getNumNoseHooverThermostats
();
i
++
){
const
auto
&
chain
=
integrator
.
getNoseHooverThermostat
(
i
);
auto
&
chainNode
=
node
.
createChildNode
(
"Thermostat"
);
chainNode
.
setDoubleProperty
(
"temperature"
,
chain
.
getDefaultTemperature
());
chainNode
.
setDoubleProperty
(
"collisionFrequency"
,
chain
.
getDefaultCollisionFrequency
());
chainNode
.
setDoubleProperty
(
"relativeTemperature"
,
chain
.
getDefaultRelativeTemperature
());
chainNode
.
setDoubleProperty
(
"relativeCollisionFrequency"
,
chain
.
getDefaultRelativeCollisionFrequency
());
chainNode
.
setIntProperty
(
"chainLength"
,
chain
.
getDefaultChainLength
());
chainNode
.
setIntProperty
(
"numMTS"
,
chain
.
getDefaultNumMultiTimeSteps
());
chainNode
.
setIntProperty
(
"numYS"
,
chain
.
getDefaultNumYoshidaSuzukiTimeSteps
());
auto
&
particlesNode
=
chainNode
.
createChildNode
(
"ThermostatedAtoms"
);
for
(
int
particle
:
chain
.
getThermostatedAtoms
()){
particlesNode
.
createChildNode
(
"Particle"
).
setIntProperty
(
"index"
,
particle
);
}
auto
&
pairsNode
=
chainNode
.
createChildNode
(
"ThermostatedPairs"
);
for
(
auto
&
pair
:
chain
.
getThermostatedPairs
()){
auto
&
pairNode
=
pairsNode
.
createChildNode
(
"Pair"
);
pairNode
.
setIntProperty
(
"index1"
,
pair
.
first
);
pairNode
.
setIntProperty
(
"index2"
,
pair
.
second
);
}
}
}
else
{
// Serialize standard thermostat
node
.
setDoubleProperty
(
"temperature"
,
integrator
.
getTemperature
());
node
.
setDoubleProperty
(
"collisionFrequency"
,
integrator
.
getCollisionFrequency
());
node
.
setIntProperty
(
"chainLength"
,
integrator
.
getNoseHooverThermostat
().
getDefaultChainLength
());
node
.
setIntProperty
(
"numMTS"
,
integrator
.
getNoseHooverThermostat
().
getDefaultNumMultiTimeSteps
());
node
.
setIntProperty
(
"numYS"
,
integrator
.
getNoseHooverThermostat
().
getDefaultNumYoshidaSuzukiTimeSteps
());
}
}
void
*
NoseHooverIntegratorProxy
::
deserialize
(
const
SerializationNode
&
node
)
const
{
if
(
node
.
getIntProperty
(
"version"
)
!=
1
)
throw
OpenMMException
(
"Unsupported version number"
);
NoseHooverIntegrator
*
integrator
;
if
(
node
.
getBoolProperty
(
"hasSubsystemThermostats"
)){
// deserialize all chains
integrator
=
new
NoseHooverIntegrator
(
node
.
getDoubleProperty
(
"stepSize"
));
for
(
auto
&
chainNode
:
node
.
getChildren
())
{
// particles
const
auto
&
particlesNode
=
chainNode
.
getChildNode
(
"ThermostatedAtoms"
);
vector
<
int
>
particles
;
for
(
auto
&
particleNode
:
particlesNode
.
getChildren
()){
particles
.
push_back
(
particleNode
.
getIntProperty
(
"index"
));
}
// pairs
const
auto
&
pairsNode
=
chainNode
.
getChildNode
(
"ThermostatedPairs"
);
vector
<
pair
<
int
,
int
>>
pairs
;
for
(
auto
&
pairNode
:
pairsNode
.
getChildren
()){
pairs
.
emplace_back
(
pairNode
.
getIntProperty
(
"index1"
),
pairNode
.
getIntProperty
(
"index2"
));
}
integrator
->
addSubsystemThermostat
(
particles
,
pairs
,
chainNode
.
getDoubleProperty
(
"temperature"
),
chainNode
.
getDoubleProperty
(
"collisionFrequency"
),
chainNode
.
getDoubleProperty
(
"relativeTemperature"
),
chainNode
.
getDoubleProperty
(
"relativeCollisionFrequency"
),
chainNode
.
getIntProperty
(
"chainLength"
),
chainNode
.
getIntProperty
(
"numMTS"
),
chainNode
.
getIntProperty
(
"numYS"
)
);
}
}
else
{
integrator
=
new
NoseHooverIntegrator
(
node
.
getDoubleProperty
(
"temperature"
),
node
.
getDoubleProperty
(
"collisionFrequency"
),
node
.
getDoubleProperty
(
"stepSize"
),
node
.
getIntProperty
(
"chainLength"
),
node
.
getIntProperty
(
"numMTS"
),
node
.
getIntProperty
(
"numYS"
)
);
}
integrator
->
setConstraintTolerance
(
node
.
getDoubleProperty
(
"constraintTolerance"
));
return
integrator
;
}
serialization/src/SerializationProxyRegistration.cpp
View file @
5cef29ce
...
@@ -55,6 +55,7 @@
...
@@ -55,6 +55,7 @@
#include "openmm/MonteCarloBarostat.h"
#include "openmm/MonteCarloBarostat.h"
#include "openmm/MonteCarloMembraneBarostat.h"
#include "openmm/MonteCarloMembraneBarostat.h"
#include "openmm/NonbondedForce.h"
#include "openmm/NonbondedForce.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/PeriodicTorsionForce.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/RBTorsionForce.h"
#include "openmm/RMSDForce.h"
#include "openmm/RMSDForce.h"
...
@@ -91,6 +92,7 @@
...
@@ -91,6 +92,7 @@
#include "openmm/serialization/MonteCarloBarostatProxy.h"
#include "openmm/serialization/MonteCarloBarostatProxy.h"
#include "openmm/serialization/MonteCarloMembraneBarostatProxy.h"
#include "openmm/serialization/MonteCarloMembraneBarostatProxy.h"
#include "openmm/serialization/NonbondedForceProxy.h"
#include "openmm/serialization/NonbondedForceProxy.h"
#include "openmm/serialization/NoseHooverIntegratorProxy.h"
#include "openmm/serialization/PeriodicTorsionForceProxy.h"
#include "openmm/serialization/PeriodicTorsionForceProxy.h"
#include "openmm/serialization/RBTorsionForceProxy.h"
#include "openmm/serialization/RBTorsionForceProxy.h"
#include "openmm/serialization/RMSDForceProxy.h"
#include "openmm/serialization/RMSDForceProxy.h"
...
@@ -148,6 +150,7 @@ extern "C" void registerSerializationProxies() {
...
@@ -148,6 +150,7 @@ extern "C" void registerSerializationProxies() {
SerializationProxy
::
registerProxy
(
typeid
(
MonteCarloBarostat
),
new
MonteCarloBarostatProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
MonteCarloBarostat
),
new
MonteCarloBarostatProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
MonteCarloMembraneBarostat
),
new
MonteCarloMembraneBarostatProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
MonteCarloMembraneBarostat
),
new
MonteCarloMembraneBarostatProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
NonbondedForce
),
new
NonbondedForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
NonbondedForce
),
new
NonbondedForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
NoseHooverIntegrator
),
new
NoseHooverIntegratorProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
PeriodicTorsionForce
),
new
PeriodicTorsionForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
PeriodicTorsionForce
),
new
PeriodicTorsionForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
RBTorsionForce
),
new
RBTorsionForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
RBTorsionForce
),
new
RBTorsionForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
RMSDForce
),
new
RMSDForceProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
RMSDForce
),
new
RMSDForceProxy
());
...
@@ -156,4 +159,4 @@ extern "C" void registerSerializationProxies() {
...
@@ -156,4 +159,4 @@ extern "C" void registerSerializationProxies() {
SerializationProxy
::
registerProxy
(
typeid
(
VariableLangevinIntegrator
),
new
VariableLangevinIntegratorProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
VariableLangevinIntegrator
),
new
VariableLangevinIntegratorProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
VariableVerletIntegrator
),
new
VariableVerletIntegratorProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
VariableVerletIntegrator
),
new
VariableVerletIntegratorProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
VerletIntegrator
),
new
VerletIntegratorProxy
());
SerializationProxy
::
registerProxy
(
typeid
(
VerletIntegrator
),
new
VerletIntegratorProxy
());
}
}
\ No newline at end of file
serialization/tests/TestSerializeNoseHooverIntegrator.cpp
0 → 100644
View file @
5cef29ce
/* -------------------------------------------------------------------------- *
* OpenMM *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2010-2014 Stanford University and the Authors. *
* Authors: Andrew C. Simmonett and Andreas Kraemer
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/serialization/XmlSerializer.h"
#include "openmm/System.h"
#include "openmm/Context.h"
#include <iostream>
#include <sstream>
using
namespace
OpenMM
;
using
namespace
std
;
void
assertIntegratorsEqual
(
const
NoseHooverIntegrator
&
integrator1
,
const
NoseHooverIntegrator
&
integrator2
){
ASSERT_EQUAL
(
integrator1
.
getStepSize
(),
integrator2
.
getStepSize
());
ASSERT_EQUAL
(
integrator1
.
getConstraintTolerance
(),
integrator2
.
getConstraintTolerance
());
ASSERT_EQUAL
(
integrator1
.
getNumNoseHooverThermostats
(),
integrator2
.
getNumNoseHooverThermostats
());
for
(
int
i
=
0
;
i
<
integrator1
.
getNumNoseHooverThermostats
();
i
++
)
{
const
auto
&
thermostat1
=
integrator1
.
getNoseHooverThermostat
(
i
);
const
auto
&
thermostat2
=
integrator2
.
getNoseHooverThermostat
(
i
);
ASSERT_EQUAL
(
thermostat1
.
getDefaultTemperature
(),
thermostat2
.
getDefaultTemperature
());
ASSERT_EQUAL
(
thermostat1
.
getDefaultCollisionFrequency
(),
thermostat2
.
getDefaultCollisionFrequency
());
ASSERT_EQUAL
(
thermostat1
.
getDefaultRelativeTemperature
(),
thermostat2
.
getDefaultRelativeTemperature
());
ASSERT_EQUAL
(
thermostat1
.
getDefaultRelativeCollisionFrequency
(),
thermostat2
.
getDefaultRelativeCollisionFrequency
());
ASSERT_EQUAL
(
thermostat1
.
getDefaultChainLength
(),
thermostat2
.
getDefaultChainLength
());
ASSERT_EQUAL
(
thermostat1
.
getDefaultNumMultiTimeSteps
(),
thermostat2
.
getDefaultNumMultiTimeSteps
());
ASSERT_EQUAL
(
thermostat1
.
getDefaultNumYoshidaSuzukiTimeSteps
(),
thermostat2
.
getDefaultNumYoshidaSuzukiTimeSteps
());
ASSERT_EQUAL
(
thermostat1
.
getDefaultChainID
(),
thermostat2
.
getDefaultChainID
());
const
auto
&
thermostat1Atoms
=
thermostat1
.
getThermostatedAtoms
();
const
auto
&
thermostat2Atoms
=
thermostat2
.
getThermostatedAtoms
();
ASSERT_EQUAL
(
thermostat1Atoms
.
size
(),
thermostat2Atoms
.
size
());
for
(
int
j
=
0
;
j
<
thermostat1Atoms
.
size
();
++
j
)
{
ASSERT_EQUAL
(
thermostat1Atoms
[
j
],
thermostat2Atoms
[
j
]);
}
const
auto
&
thermostat1Pairs
=
thermostat1
.
getThermostatedPairs
();
const
auto
&
thermostat2Pairs
=
thermostat2
.
getThermostatedPairs
();
ASSERT_EQUAL
(
thermostat1Pairs
.
size
(),
thermostat2Pairs
.
size
());
for
(
int
j
=
0
;
j
<
thermostat1Pairs
.
size
();
++
j
)
{
ASSERT_EQUAL
(
thermostat1Pairs
[
j
].
first
,
thermostat2Pairs
[
j
].
first
);
ASSERT_EQUAL
(
thermostat1Pairs
[
j
].
second
,
thermostat2Pairs
[
j
].
second
);
}
}
}
void
testSerialization
()
{
// Check with custom subsystem thermostats
NoseHooverIntegrator
integrator_sub
(
0.0006
);
integrator_sub
.
setConstraintTolerance
(
0.0404
);
integrator_sub
.
addSubsystemThermostat
(
{
0
,
1
,
2
,
3
,
4
,
7
},
{{
0
,
7
}},
301.1
,
1.1
,
1.2
,
1.3
,
9
,
2
,
5
);
// Serialize and then deserialize it.
stringstream
buffer
;
XmlSerializer
::
serialize
<
NoseHooverIntegrator
>
(
&
integrator_sub
,
"Integrator"
,
buffer
);
NoseHooverIntegrator
*
copy
=
XmlSerializer
::
deserialize
<
NoseHooverIntegrator
>
(
buffer
);
assertIntegratorsEqual
(
integrator_sub
,
*
copy
);
// Check with default constructor
System
system
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
system
.
addParticle
(
1.0
);
NoseHooverIntegrator
integrator
(
331
,
1.1
,
0.004
,
5
,
5
,
5
);
Context
context
(
system
,
integrator
);
// Serialize and then deserialize it.
stringstream
buffer2
;
XmlSerializer
::
serialize
<
NoseHooverIntegrator
>
(
&
integrator
,
"Integrator"
,
buffer2
);
copy
=
XmlSerializer
::
deserialize
<
NoseHooverIntegrator
>
(
buffer2
);
// for thermostats that apply to the whole system, the particles are not serialized ...
ASSERT_EQUAL
(
copy
->
getNoseHooverThermostat
(
0
).
getThermostatedAtoms
().
size
(),
0
);
// ... but assigned when creating a context.
Context
context2
(
system
,
*
copy
);
assertIntegratorsEqual
(
integrator
,
*
copy
);
}
int
main
()
{
try
{
testSerialization
();
}
catch
(
const
exception
&
e
)
{
cout
<<
"exception: "
<<
e
.
what
()
<<
endl
;
return
1
;
}
cout
<<
"Done"
<<
endl
;
return
0
;
}
tests/TestNoseHooverThermostat.h
View file @
5cef29ce
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/internal/AssertionUtilities.h"
#include "openmm/
internal/
NoseHooverChain.h"
#include "openmm/NoseHooverChain.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/NoseHooverIntegrator.h"
#include "openmm/Context.h"
#include "openmm/Context.h"
#include "openmm/State.h"
#include "openmm/State.h"
...
...
wrappers/python/setup.py
View file @
5cef29ce
...
@@ -193,7 +193,7 @@ def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM,
...
@@ -193,7 +193,7 @@ def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM,
extra_compile_args
.
append
(
'/EHsc'
)
extra_compile_args
.
append
(
'/EHsc'
)
else
:
else
:
if
platform
.
system
()
==
'Darwin'
:
if
platform
.
system
()
==
'Darwin'
:
extra_compile_args
+=
[
'
-std=c++11
-stdlib=libc++'
,
'-mmacosx-version-min=10.7'
]
extra_compile_args
+=
[
'-stdlib=libc++'
,
'-mmacosx-version-min=10.7'
]
extra_link_args
+=
[
'-stdlib=libc++'
,
'-mmacosx-version-min=10.7'
,
'-Wl'
,
'-rpath'
,
openmm_lib_path
]
extra_link_args
+=
[
'-stdlib=libc++'
,
'-mmacosx-version-min=10.7'
,
'-Wl'
,
'-rpath'
,
openmm_lib_path
]
# Hard-code CC and CXX to clang, since gcc/g++ will *not* work with
# Hard-code CC and CXX to clang, since gcc/g++ will *not* work with
# Anaconda, despite the fact that distutils will try to use them.
# Anaconda, despite the fact that distutils will try to use them.
...
...
wrappers/python/src/swig_doxygen/swigInputConfig.py
View file @
5cef29ce
...
@@ -482,9 +482,9 @@ UNITS = {
...
@@ -482,9 +482,9 @@ UNITS = {
(
"RPMDIntegrator"
,
"getState"
):
(
None
,(
None
,
None
,
None
,
None
)),
(
"RPMDIntegrator"
,
"getState"
):
(
None
,(
None
,
None
,
None
,
None
)),
(
"RMSDForce"
,
"getReferencePositions"
)
:
(
"unit.nanometer"
,
()),
(
"RMSDForce"
,
"getReferencePositions"
)
:
(
"unit.nanometer"
,
()),
(
"RMSDForce"
,
"getParticles"
)
:
(
None
,
()),
(
"RMSDForce"
,
"getParticles"
)
:
(
None
,
()),
#
("NoseHooverChain", "getThermostatedPairs") : (None, ()),
(
"NoseHooverChain"
,
"getThermostatedPairs"
)
:
(
None
,
()),
#
("NoseHooverChain", "getThermostatedAtoms") : (None, ()),
(
"NoseHooverChain"
,
"getThermostatedAtoms"
)
:
(
None
,
()),
#
("NoseHooverChain", "getDefaultYoshidaSuzukiWeights") : (None, ()),
(
"NoseHooverChain"
,
"getDefaultYoshidaSuzukiWeights"
)
:
(
None
,
()),
(
"NoseHooverIntegrator"
,
"setTemperature"
)
:
(
None
,
(
"unit.kelvin"
,
None
)),
(
"NoseHooverIntegrator"
,
"setTemperature"
)
:
(
None
,
(
"unit.kelvin"
,
None
)),
(
"NoseHooverIntegrator"
,
"setRelativeTemperature"
)
:
(
None
,
(
"unit.kelvin"
,
None
)
),
(
"NoseHooverIntegrator"
,
"setRelativeTemperature"
)
:
(
None
,
(
"unit.kelvin"
,
None
)
),
(
"NoseHooverIntegrator"
,
"setCollisionFrequency"
)
:
(
None
,
(
"unit.picosecond**-1"
,
None
)),
(
"NoseHooverIntegrator"
,
"setCollisionFrequency"
)
:
(
None
,
(
"unit.picosecond**-1"
,
None
)),
...
@@ -492,6 +492,7 @@ UNITS = {
...
@@ -492,6 +492,7 @@ UNITS = {
(
"NoseHooverIntegrator"
,
"computeHeatBathEnergy"
)
:
(
"unit.kilojoules_per_mole"
,
()),
(
"NoseHooverIntegrator"
,
"computeHeatBathEnergy"
)
:
(
"unit.kilojoules_per_mole"
,
()),
(
"NoseHooverIntegrator"
,
"addThermostat"
):
(
None
,
(
"unit.kelvin"
,
"unit.picosecond**-1"
,
None
,
None
,
None
)),
(
"NoseHooverIntegrator"
,
"addThermostat"
):
(
None
,
(
"unit.kelvin"
,
"unit.picosecond**-1"
,
None
,
None
,
None
)),
(
"NoseHooverIntegrator"
,
"addSubsystemThermostat"
):
(
"NoseHooverIntegrator"
,
"addSubsystemThermostat"
):
(
None
,
(
None
,
None
,
"unit.kelvin"
,
"unit.picosecond**-1"
,
"unit.kelvin"
,
"unit.picosecond**-1"
,
None
,
None
,
None
))
(
None
,
(
None
,
None
,
"unit.kelvin"
,
"unit.picosecond**-1"
,
"unit.kelvin"
,
"unit.picosecond**-1"
,
None
,
None
,
None
)),
(
"NoseHooverIntegrator"
,
"getNumNoseHooverThermostats"
)
:
(
None
,
()),
(
"NoseHooverIntegrator"
,
"getNoseHooverThermostat"
)
:
(
None
,
()),
}
}
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