Page 1 of 1

getForce() can't get a new subclass Force

Posted: Mon Jan 06, 2020 7:17 am
by huanxi
Hello everyone,

I create a new subclass Force (named BForce) and BForceGenerator though a plugin(Bplugin), and added it into system. It works. However, getForce() can't get the new subclass Force. It print "<simtk.openmm.openmm.Force; proxy of <Swig Object of type 'OpenMM::Force *' at 0x7faed11c6de0> >". Others force can be obtained, such as "<simtk.openmm.openmm.HarmonicBondForce; proxy of <Swig Object of type 'OpenMM::HarmonicBondForce *' at 0x7faed11c6de0> >".

I hope to get 'OpenMM::BForce'.What is the best way of doing this?

Thanks!
Huanxi

Re: getForce() can't get a new subclass Force

Posted: Mon Jan 06, 2020 11:01 am
by peastman
Unfortunately that's difficult. It has to do with the way SWIG works. For C++ methods whose declared return type is an abstract superclass, you need to provide it with a list of all possible subclasses so it can generate the code to select a Python class. And that needs to be provided at the point when the wrapper module is created. So getForce() knows about all the built in Force subclasses and can return the proper Python class for each one. But for any other C++ subclass, all it can do is return the parent Force class.

The best approach is to keep around a reference to the original Python object. But that's only possible if you created it from Python. If the Force was originally created by C++ code (like by loading a serialized System), things get more complicated. The best approach is probably to add a C++ function to your plugin's SWIG wrapper that casts a Force to a BForce.

Re: getForce() can't get a new subclass Force

Posted: Wed Jan 08, 2020 4:36 pm
by peastman
I just implemented this in the example plugin. It actually turned out to be pretty easy. See https://github.com/peastman/openmmexamp ... l/17/files. If f is a Force, you can write ExampleForce.cast(f) to cast it to an ExampleForce.