Commit a707b2b4 authored by peastman's avatar peastman
Browse files

Implemented cloning of objects by serialization

parent 5b074f80
...@@ -74,6 +74,18 @@ public: ...@@ -74,6 +74,18 @@ public:
static T* deserialize(std::istream& stream) { static T* deserialize(std::istream& stream) {
return reinterpret_cast<T*>(deserializeStream(stream)); return reinterpret_cast<T*>(deserializeStream(stream));
} }
/**
* Clone an object by first serializing it, then deserializing it again. This method constructs the
* new object directly from the SerializationNodes without first converting them to XML. This means
* it is faster and uses less memory than making separate calls to serialize() and deserialize().
*/
template <class T>
static T* clone(const T& object) {
const SerializationProxy& proxy = SerializationProxy::getProxy(typeid(object));
SerializationNode node;
proxy.serialize(&object, node);
return reinterpret_cast<T*>(proxy.deserialize(node));
}
private: private:
class StreamReader; class StreamReader;
static void serialize(const SerializationNode& node, std::ostream& stream); static void serialize(const SerializationNode& node, std::ostream& stream);
......
...@@ -40,32 +40,7 @@ ...@@ -40,32 +40,7 @@
using namespace OpenMM; using namespace OpenMM;
using namespace std; using namespace std;
void testSerialization() { void compareSystems(System& system, System& system2) {
// Create a System.
System system;
for (int i = 0; i < 5; i++)
system.addParticle(0.1*i+1);
for (int i = 0; i < 4; i++)
system.addParticle(0.0);
system.addConstraint(0, 1, 3.0);
system.addConstraint(1, 2, 2.5);
system.addConstraint(4, 1, 1.001);
system.setDefaultPeriodicBoxVectors(Vec3(5, 0, 0), Vec3(0, 4, 0), Vec3(0, 0, 1.5));
system.setVirtualSite(5, new TwoParticleAverageSite(0, 1, 0.3, 0.7));
system.setVirtualSite(6, new ThreeParticleAverageSite(2, 4, 3, 0.5, 0.2, 0.3));
system.setVirtualSite(7, new OutOfPlaneSite(0, 3, 1, 0.1, 0.2, 0.5));
system.addForce(new HarmonicBondForce());
// Serialize and then deserialize it.
stringstream buffer;
XmlSerializer::serialize<System>(&system, "System", buffer);
System* copy = XmlSerializer::deserialize<System>(buffer);
// Compare the two systems to see if they are identical.
System& system2 = *copy;
ASSERT_EQUAL(system.getNumParticles(), system2.getNumParticles()); ASSERT_EQUAL(system.getNumParticles(), system2.getNumParticles());
for (int i = 0; i < system.getNumParticles(); i++) for (int i = 0; i < system.getNumParticles(); i++)
ASSERT_EQUAL(system.getParticleMass(i), system2.getParticleMass(i)); ASSERT_EQUAL(system.getParticleMass(i), system2.getParticleMass(i));
...@@ -112,6 +87,38 @@ void testSerialization() { ...@@ -112,6 +87,38 @@ void testSerialization() {
ASSERT(typeid(system.getForce(i)) == typeid(system2.getForce(i))) ASSERT(typeid(system.getForce(i)) == typeid(system2.getForce(i)))
} }
void testSerialization() {
// Create a System.
System system;
for (int i = 0; i < 5; i++)
system.addParticle(0.1*i+1);
for (int i = 0; i < 4; i++)
system.addParticle(0.0);
system.addConstraint(0, 1, 3.0);
system.addConstraint(1, 2, 2.5);
system.addConstraint(4, 1, 1.001);
system.setDefaultPeriodicBoxVectors(Vec3(5, 0, 0), Vec3(0, 4, 0), Vec3(0, 0, 1.5));
system.setVirtualSite(5, new TwoParticleAverageSite(0, 1, 0.3, 0.7));
system.setVirtualSite(6, new ThreeParticleAverageSite(2, 4, 3, 0.5, 0.2, 0.3));
system.setVirtualSite(7, new OutOfPlaneSite(0, 3, 1, 0.1, 0.2, 0.5));
system.addForce(new HarmonicBondForce());
// Serialize and then deserialize it, then make sure the systems are identical.
stringstream buffer;
XmlSerializer::serialize<System>(&system, "System", buffer);
System* copy = XmlSerializer::deserialize<System>(buffer);
compareSystems(system, *copy);
delete copy;
// Now do the same thing but by calling clone().
copy = XmlSerializer::clone(system);
compareSystems(system, *copy);
delete copy;
}
int main() { int main() {
try { try {
testSerialization(); testSerialization();
......
...@@ -272,10 +272,15 @@ Parameters: ...@@ -272,10 +272,15 @@ Parameters:
def __setstate__(self, serializationString): def __setstate__(self, serializationString):
system = XmlSerializer.deserializeSystem(serializationString) system = XmlSerializer.deserializeSystem(serializationString)
self.this = system.this self.this = system.this
def __deepcopy__(self, memo):
return self.__copy__()
def getForces(self): def getForces(self):
"""Get the list of Forces in this System""" """Get the list of Forces in this System"""
return [self.getForce(i) for i in range(self.getNumForces())] return [self.getForce(i) for i in range(self.getNumForces())]
%} %}
OpenMM::System* __copy__() {
return OpenMM::XmlSerializer::clone<OpenMM::System>(*self);
}
} }
%extend OpenMM::XmlSerializer { %extend OpenMM::XmlSerializer {
...@@ -444,14 +449,12 @@ Parameters: ...@@ -444,14 +449,12 @@ Parameters:
%extend OpenMM::Force { %extend OpenMM::Force {
%pythoncode %{ %pythoncode %{
def __copy__(self):
copy = self.__class__.__new__(self.__class__)
copy.__init__(self)
return copy
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
return self.__copy__() return self.__copy__()
%} %}
OpenMM::Force* __copy__() {
return OpenMM::XmlSerializer::clone<OpenMM::Force>(*self);
}
} }
%extend OpenMM::Integrator { %extend OpenMM::Integrator {
...@@ -463,5 +466,11 @@ Parameters: ...@@ -463,5 +466,11 @@ Parameters:
def __setstate__(self, serializationString): def __setstate__(self, serializationString):
system = XmlSerializer.deserialize(serializationString) system = XmlSerializer.deserialize(serializationString)
self.this = system.this self.this = system.this
def __deepcopy__(self, memo):
return self.__copy__()
%} %}
OpenMM::Integrator* __copy__() {
return OpenMM::XmlSerializer::clone<OpenMM::Integrator>(*self);
}
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment