2 Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
3 (HOOMD-blue) Open Source Software License Copyright 2009-2014 The Regents of
4 the University of Michigan All rights reserved.
6 HOOMD-blue may contain modifications ("Contributions") provided, and to which
7 copyright is held, by various Contributors who have granted The Regents of the
8 University of Michigan the right to modify and/or distribute such Contributions.
10 You may redistribute, use, and create derivate works of HOOMD-blue, in source
11 and binary forms, provided you abide by the following conditions:
13 * Redistributions of source code must retain the above copyright notice, this
14 list of conditions, and the following disclaimer both in the code and
15 prominently in any materials provided with the distribution.
17 * Redistributions in binary form must reproduce the above copyright notice, this
18 list of conditions, and the following disclaimer in the documentation and/or
19 other materials provided with the distribution.
21 * All publications and presentations based on HOOMD-blue, including any reports
22 or published results obtained, in whole or in part, with HOOMD-blue, will
23 acknowledge its use according to the terms posted at the time of submission on:
24 http://codeblue.umich.edu/hoomd-blue/citations.html
26 * Any electronic documents citing HOOMD-Blue will link to the HOOMD-Blue website:
27 http://codeblue.umich.edu/hoomd-blue/
29 * Apart from the above required attributions, neither the name of the copyright
30 holder nor the names of HOOMD-blue's contributors may be used to endorse or
31 promote products derived from this software without specific prior written
36 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND
37 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR ANY
39 WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.
41 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
43 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
46 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 // Maintainer: joaander
52 #ifndef __POTENTIAL_PAIR_H__
53 #define __POTENTIAL_PAIR_H__
57 #include <boost/shared_ptr.hpp>
58 #include <boost/python.hpp>
60 #include "HOOMDMath.h"
63 #include "ForceCompute.h"
64 #include "NeighborList.h"
67 #include "Communicator.h"
71 #pragma warning( push )
72 #pragma warning( disable : 4103 4244 )
75 /*! \file PotentialPair.h
76 \brief Defines the template class for standard pair potentials
77 \details The heart of the code that computes pair potentials is in this file.
78 \note This header cannot be compiled by nvcc
82 #error This header cannot be compiled by nvcc
85 //! Template class for computing pair potentials
87 PotentialPair computes standard pair potentials (and forces) between all particle pairs in the simulation. It
88 employs the use of a neighbor list to limit the number of computations done to only those particles with the
89 cuttoff radius of each other. The computation of the actual V(r) is not performed directly by this class, but
90 by an evaluator class (e.g. EvaluatorPairLJ) which is passed in as a template parameter so the compuations
91 are performed as efficiently as possible.
93 PotentialPair handles most of the gory internal details common to all standard pair potentials.
94 - A cuttoff radius to be specified per particle type pair
95 - The energy can be globally shifted to 0 at the cuttoff
96 - XPLOR switching can be enabled
97 - Per type pair parameters are stored and a set method is provided
98 - Logging methods are provided for the energy
99 - And all the details about looping through the particles, computing dr, computing the virial, etc. are handled
101 A note on the design of XPLOR switching:
102 We need to be able to handle smooth XPLOR switching in systems of mixed LJ/WCA particles. There are three modes to
103 enable all of the various use-cases:
104 - Mode 1: No shifting. All pair potentials are computed as is and not shifted to 0 at the cuttoff.
105 - Mode 2: Shift everything. All pair potentials (no matter what type pair) are shifted so they are 0 at the cuttoff
106 - Mode 3: XPLOR switching enabled. A r_on value is specified per type pair. When r_on is less than r_cut, normal
107 XPLOR switching will be applied to the unshifted potential. When r_on is greather than r_cut, the energy will
108 be shifted. In this manner, a valid r_on value can be given for the LJ interactions and r_on > r_cut can be set
109 for WCA (which will then be shifted).
111 XPLOR switching gets significantly more complicated for all pair potentials when shifted potentials are used. Thus,
112 the combination of XPLOR switching + shifted potentials will not be supported to avoid slowing down the calculation
115 <b>Implementation details</b>
117 rcutsq, ronsq, and the params are stored per particle type pair. It wastes a little bit of space, but benchmarks
118 show that storing the symmetric type pairs and indexing with Index2D is faster than not storing redudant pairs
119 and indexing with Index2DUpperTriangular. All of these values are stored in GPUArray
120 for easy access on the GPU by a derived class. The type of the parameters is defined by \a param_type in the
121 potential evaluator class passed in. See the appropriate documentation for the evaluator for the definition of each
122 element of the parameters.
124 For profiling and logging, PotentialPair needs to know the name of the potential. For now, that will be queried from
125 the evaluator. Perhaps in the future we could allow users to change that so multiple pair potentials could be logged
128 \sa export_PotentialPair()
130 template < class evaluator
>
131 class PotentialPair
: public ForceCompute
134 //! Param type from evaluator
135 typedef typename
evaluator::param_type param_type
;
137 //! Construct the pair potential
138 PotentialPair(boost::shared_ptr
<SystemDefinition
> sysdef
,
139 boost::shared_ptr
<NeighborList
> nlist
,
140 const std::string
& log_suffix
="");
142 virtual ~PotentialPair();
144 //! Set the pair parameters for a single type pair
145 virtual void setParams(unsigned int typ1
, unsigned int typ2
, const param_type
& param
);
146 //! Set the rcut for a single type pair
147 virtual void setRcut(unsigned int typ1
, unsigned int typ2
, Scalar rcut
);
148 //! Set ron for a single type pair
149 virtual void setRon(unsigned int typ1
, unsigned int typ2
, Scalar ron
);
151 //! Returns a list of log quantities this compute calculates
152 virtual std::vector
< std::string
> getProvidedLogQuantities();
153 //! Calculates the requested log value and returns it
154 virtual Scalar
getLogValue(const std::string
& quantity
, unsigned int timestep
);
156 //! Shifting modes that can be applied to the energy
164 //! Set the mode to use for shifting the energy
165 void setShiftMode(energyShiftMode mode
)
171 //! Get ghost particle fields requested by this pair potential
172 virtual CommFlags
getRequestedCommFlags(unsigned int timestep
);
176 boost::shared_ptr
<NeighborList
> m_nlist
; //!< The neighborlist to use for the computation
177 energyShiftMode m_shift_mode
; //!< Store the mode with which to handle the energy shift at r_cut
178 Index2D m_typpair_idx
; //!< Helper class for indexing per type pair arrays
179 GPUArray
<Scalar
> m_rcutsq
; //!< Cuttoff radius squared per type pair
180 GPUArray
<Scalar
> m_ronsq
; //!< ron squared per type pair
181 GPUArray
<param_type
> m_params
; //!< Pair parameters per type pair
182 std::string m_prof_name
; //!< Cached profiler name
183 std::string m_log_name
; //!< Cached log name
185 //! Actually compute the forces
186 virtual void computeForces(unsigned int timestep
);
189 /*! \param sysdef System to compute forces on
190 \param nlist Neighborlist to use for computing the forces
191 \param log_suffix Name given to this instance of the force
193 template < class evaluator
>
194 PotentialPair
< evaluator
>::PotentialPair(boost::shared_ptr
<SystemDefinition
> sysdef
,
195 boost::shared_ptr
<NeighborList
> nlist
,
196 const std::string
& log_suffix
)
197 : ForceCompute(sysdef
), m_nlist(nlist
), m_shift_mode(no_shift
), m_typpair_idx(m_pdata
->getNTypes())
199 m_exec_conf
->msg
->notice(5) << "Constructing PotentialPair<" << evaluator::getName() << ">" << endl
;
204 GPUArray
<Scalar
> rcutsq(m_typpair_idx
.getNumElements(), exec_conf
);
205 m_rcutsq
.swap(rcutsq
);
206 GPUArray
<Scalar
> ronsq(m_typpair_idx
.getNumElements(), exec_conf
);
208 GPUArray
<param_type
> params(m_typpair_idx
.getNumElements(), exec_conf
);
209 m_params
.swap(params
);
212 m_prof_name
= std::string("Pair ") + evaluator::getName();
213 m_log_name
= std::string("pair_") + evaluator::getName() + std::string("_energy") + log_suffix
;
216 template< class evaluator
>
217 PotentialPair
< evaluator
>::~PotentialPair()
219 m_exec_conf
->msg
->notice(5) << "Destroying PotentialPair<" << evaluator::getName() << ">" << endl
;
222 /*! \param typ1 First type index in the pair
223 \param typ2 Second type index in the pair
224 \param param Parameter to set
225 \note When setting the value for (\a typ1, \a typ2), the parameter for (\a typ2, \a typ1) is automatically
228 template< class evaluator
>
229 void PotentialPair
< evaluator
>::setParams(unsigned int typ1
, unsigned int typ2
, const param_type
& param
)
231 if (typ1
>= m_pdata
->getNTypes() || typ2
>= m_pdata
->getNTypes())
233 this->m_exec_conf
->msg
->error() << "pair." << evaluator::getName() << ": Trying to set pair params for a non existant type! "
234 << typ1
<< "," << typ2
<< std::endl
;
235 throw std::runtime_error("Error setting parameters in PotentialPair");
238 ArrayHandle
<param_type
> h_params(m_params
, access_location::host
, access_mode::readwrite
);
239 h_params
.data
[m_typpair_idx(typ1
, typ2
)] = param
;
240 h_params
.data
[m_typpair_idx(typ2
, typ1
)] = param
;
243 /*! \param typ1 First type index in the pair
244 \param typ2 Second type index in the pair
245 \param rcut Cuttoff radius to set
246 \note When setting the value for (\a typ1, \a typ2), the parameter for (\a typ2, \a typ1) is automatically
249 template< class evaluator
>
250 void PotentialPair
< evaluator
>::setRcut(unsigned int typ1
, unsigned int typ2
, Scalar rcut
)
252 if (typ1
>= m_pdata
->getNTypes() || typ2
>= m_pdata
->getNTypes())
254 this->m_exec_conf
->msg
->error() << "pair." << evaluator::getName() << ": Trying to set rcut for a non existant type! "
255 << typ1
<< "," << typ2
<< std::endl
;
256 throw std::runtime_error("Error setting parameters in PotentialPair");
259 ArrayHandle
<Scalar
> h_rcutsq(m_rcutsq
, access_location::host
, access_mode::readwrite
);
260 h_rcutsq
.data
[m_typpair_idx(typ1
, typ2
)] = rcut
* rcut
;
261 h_rcutsq
.data
[m_typpair_idx(typ2
, typ1
)] = rcut
* rcut
;
264 /*! \param typ1 First type index in the pair
265 \param typ2 Second type index in the pair
266 \param ron XPLOR r_on radius to set
267 \note When setting the value for (\a typ1, \a typ2), the parameter for (\a typ2, \a typ1) is automatically
270 template< class evaluator
>
271 void PotentialPair
< evaluator
>::setRon(unsigned int typ1
, unsigned int typ2
, Scalar ron
)
273 if (typ1
>= m_pdata
->getNTypes() || typ2
>= m_pdata
->getNTypes())
275 this->m_exec_conf
->msg
->error() << "pair." << evaluator::getName() << ": Trying to set ron for a non existant type! "
276 << typ1
<< "," << typ2
<< std::endl
;
277 throw std::runtime_error("Error setting parameters in PotentialPair");
280 ArrayHandle
<Scalar
> h_ronsq(m_ronsq
, access_location::host
, access_mode::readwrite
);
281 h_ronsq
.data
[m_typpair_idx(typ1
, typ2
)] = ron
* ron
;
282 h_ronsq
.data
[m_typpair_idx(typ2
, typ1
)] = ron
* ron
;
285 /*! PotentialPair provides:
286 - \c pair_"name"_energy
287 where "name" is replaced with evaluator::getName()
289 template< class evaluator
>
290 std::vector
< std::string
> PotentialPair
< evaluator
>::getProvidedLogQuantities()
293 list
.push_back(m_log_name
);
297 /*! \param quantity Name of the log value to get
298 \param timestep Current timestep of the simulation
300 template< class evaluator
>
301 Scalar PotentialPair
< evaluator
>::getLogValue(const std::string
& quantity
, unsigned int timestep
)
303 if (quantity
== m_log_name
)
306 return calcEnergySum();
310 this->m_exec_conf
->msg
->error() << "pair." << evaluator::getName() << ": " << quantity
<< " is not a valid log quantity"
312 throw std::runtime_error("Error getting log value");
316 /*! \post The pair forces are computed for the given timestep. The neighborlist's compute method is called to ensure
317 that it is up to date before proceeding.
319 \param timestep specifies the current time step of the simulation
321 template< class evaluator
>
322 void PotentialPair
< evaluator
>::computeForces(unsigned int timestep
)
324 // start by updating the neighborlist
325 m_nlist
->compute(timestep
);
327 // start the profile for this compute
328 if (m_prof
) m_prof
->push(m_prof_name
);
330 // depending on the neighborlist settings, we can take advantage of newton's third law
331 // to reduce computations at the cost of memory access complexity: set that flag now
332 bool third_law
= m_nlist
->getStorageMode() == NeighborList::half
;
334 // access the neighbor list, particle data, and system box
335 ArrayHandle
<unsigned int> h_n_neigh(m_nlist
->getNNeighArray(), access_location::host
, access_mode::read
);
336 ArrayHandle
<unsigned int> h_nlist(m_nlist
->getNListArray(), access_location::host
, access_mode::read
);
337 Index2D nli
= m_nlist
->getNListIndexer();
339 ArrayHandle
<Scalar4
> h_pos(m_pdata
->getPositions(), access_location::host
, access_mode::read
);
340 ArrayHandle
<Scalar
> h_diameter(m_pdata
->getDiameters(), access_location::host
, access_mode::read
);
341 ArrayHandle
<Scalar
> h_charge(m_pdata
->getCharges(), access_location::host
, access_mode::read
);
345 ArrayHandle
<Scalar4
> h_force(m_force
,access_location::host
, access_mode::overwrite
);
346 ArrayHandle
<Scalar
> h_virial(m_virial
,access_location::host
, access_mode::overwrite
);
349 const BoxDim
& box
= m_pdata
->getGlobalBox();
350 ArrayHandle
<Scalar
> h_ronsq(m_ronsq
, access_location::host
, access_mode::read
);
351 ArrayHandle
<Scalar
> h_rcutsq(m_rcutsq
, access_location::host
, access_mode::read
);
352 ArrayHandle
<param_type
> h_params(m_params
, access_location::host
, access_mode::read
);
354 PDataFlags flags
= this->m_pdata
->getFlags();
355 bool compute_virial
= flags
[pdata_flag::pressure_tensor
] || flags
[pdata_flag::isotropic_virial
];
357 // need to start from a zero force, energy and virial
358 memset((void*)h_force
.data
,0,sizeof(Scalar4
)*m_force
.getNumElements());
359 memset((void*)h_virial
.data
,0,sizeof(Scalar
)*m_virial
.getNumElements());
362 for (int i
= 0; i
< (int)m_pdata
->getN(); i
++)
364 // access the particle's position and type (MEM TRANSFER: 4 scalars)
365 Scalar3 pi
= make_scalar3(h_pos
.data
[i
].x
, h_pos
.data
[i
].y
, h_pos
.data
[i
].z
);
366 unsigned int typei
= __scalar_as_int(h_pos
.data
[i
].w
);
369 assert(typei
< m_pdata
->getNTypes());
371 // access diameter and charge (if needed)
372 Scalar di
= Scalar(0.0);
373 Scalar qi
= Scalar(0.0);
374 if (evaluator::needsDiameter())
375 di
= h_diameter
.data
[i
];
376 if (evaluator::needsCharge())
377 qi
= h_charge
.data
[i
];
379 // initialize current particle force, potential energy, and virial to 0
380 Scalar3 fi
= make_scalar3(0, 0, 0);
382 Scalar virialxxi
= 0.0;
383 Scalar virialxyi
= 0.0;
384 Scalar virialxzi
= 0.0;
385 Scalar virialyyi
= 0.0;
386 Scalar virialyzi
= 0.0;
387 Scalar virialzzi
= 0.0;
389 // loop over all of the neighbors of this particle
390 const unsigned int size
= (unsigned int)h_n_neigh
.data
[i
];
391 for (unsigned int k
= 0; k
< size
; k
++)
393 // access the index of this neighbor (MEM TRANSFER: 1 scalar)
394 unsigned int j
= h_nlist
.data
[nli(i
, k
)];
395 assert(j
< m_pdata
->getN() + m_pdata
->getNGhosts());
397 // calculate dr_ji (MEM TRANSFER: 3 scalars / FLOPS: 3)
398 Scalar3 pj
= make_scalar3(h_pos
.data
[j
].x
, h_pos
.data
[j
].y
, h_pos
.data
[j
].z
);
399 Scalar3 dx
= pi
- pj
;
401 // access the type of the neighbor particle (MEM TRANSFER: 1 scalar)
402 unsigned int typej
= __scalar_as_int(h_pos
.data
[j
].w
);
403 assert(typej
< m_pdata
->getNTypes());
405 // access diameter and charge (if needed)
406 Scalar dj
= Scalar(0.0);
407 Scalar qj
= Scalar(0.0);
408 if (evaluator::needsDiameter())
409 dj
= h_diameter
.data
[j
];
410 if (evaluator::needsCharge())
411 qj
= h_charge
.data
[j
];
413 // apply periodic boundary conditions
414 dx
= box
.minImage(dx
);
416 // calculate r_ij squared (FLOPS: 5)
417 Scalar rsq
= dot(dx
, dx
);
419 // get parameters for this type pair
420 unsigned int typpair_idx
= m_typpair_idx(typei
, typej
);
421 param_type param
= h_params
.data
[typpair_idx
];
422 Scalar rcutsq
= h_rcutsq
.data
[typpair_idx
];
423 Scalar ronsq
= Scalar(0.0);
424 if (m_shift_mode
== xplor
)
425 ronsq
= h_ronsq
.data
[typpair_idx
];
427 // design specifies that energies are shifted if
428 // 1) shift mode is set to shift
429 // or 2) shift mode is explor and ron > rcut
430 bool energy_shift
= false;
431 if (m_shift_mode
== shift
)
433 else if (m_shift_mode
== xplor
)
439 // compute the force and potential energy
440 Scalar force_divr
= Scalar(0.0);
441 Scalar pair_eng
= Scalar(0.0);
442 evaluator
eval(rsq
, rcutsq
, param
);
443 if (evaluator::needsDiameter())
444 eval
.setDiameter(di
, dj
);
445 if (evaluator::needsCharge())
446 eval
.setCharge(qi
, qj
);
448 bool evaluated
= eval
.evalForceAndEnergy(force_divr
, pair_eng
, energy_shift
);
452 // modify the potential for xplor shifting
453 if (m_shift_mode
== xplor
)
455 if (rsq
>= ronsq
&& rsq
< rcutsq
)
457 // Implement XPLOR smoothing (FLOPS: 16)
458 Scalar old_pair_eng
= pair_eng
;
459 Scalar old_force_divr
= force_divr
;
461 // calculate 1.0 / (xplor denominator)
462 Scalar xplor_denom_inv
=
463 Scalar(1.0) / ((rcutsq
- ronsq
) * (rcutsq
- ronsq
) * (rcutsq
- ronsq
));
465 Scalar rsq_minus_r_cut_sq
= rsq
- rcutsq
;
466 Scalar s
= rsq_minus_r_cut_sq
* rsq_minus_r_cut_sq
*
467 (rcutsq
+ Scalar(2.0) * rsq
- Scalar(3.0) * ronsq
) * xplor_denom_inv
;
468 Scalar ds_dr_divr
= Scalar(12.0) * (rsq
- ronsq
) * rsq_minus_r_cut_sq
* xplor_denom_inv
;
470 // make modifications to the old pair energy and force
471 pair_eng
= old_pair_eng
* s
;
472 // note: I'm not sure why the minus sign needs to be there: my notes have a +
473 // But this is verified correct via plotting
474 force_divr
= s
* old_force_divr
- ds_dr_divr
* old_pair_eng
;
478 Scalar force_div2r
= force_divr
* Scalar(0.5);
479 // add the force, potential energy and virial to the particle i
482 pei
+= pair_eng
* Scalar(0.5);
485 virialxxi
+= force_div2r
*dx
.x
*dx
.x
;
486 virialxyi
+= force_div2r
*dx
.x
*dx
.y
;
487 virialxzi
+= force_div2r
*dx
.x
*dx
.z
;
488 virialyyi
+= force_div2r
*dx
.y
*dx
.y
;
489 virialyzi
+= force_div2r
*dx
.y
*dx
.z
;
490 virialzzi
+= force_div2r
*dx
.z
*dx
.z
;
493 // add the force to particle j if we are using the third law (MEM TRANSFER: 10 scalars / FLOPS: 8)
494 // only add force to local particles
495 if (third_law
&& j
< m_pdata
->getN())
497 unsigned int mem_idx
= j
;
498 h_force
.data
[mem_idx
].x
-= dx
.x
*force_divr
;
499 h_force
.data
[mem_idx
].y
-= dx
.y
*force_divr
;
500 h_force
.data
[mem_idx
].z
-= dx
.z
*force_divr
;
501 h_force
.data
[mem_idx
].w
+= pair_eng
* Scalar(0.5);
504 h_virial
.data
[0*m_virial_pitch
+mem_idx
] += force_div2r
*dx
.x
*dx
.x
;
505 h_virial
.data
[1*m_virial_pitch
+mem_idx
] += force_div2r
*dx
.x
*dx
.y
;
506 h_virial
.data
[2*m_virial_pitch
+mem_idx
] += force_div2r
*dx
.x
*dx
.z
;
507 h_virial
.data
[3*m_virial_pitch
+mem_idx
] += force_div2r
*dx
.y
*dx
.y
;
508 h_virial
.data
[4*m_virial_pitch
+mem_idx
] += force_div2r
*dx
.y
*dx
.z
;
509 h_virial
.data
[5*m_virial_pitch
+mem_idx
] += force_div2r
*dx
.z
*dx
.z
;
515 // finally, increment the force, potential energy and virial for particle i
516 unsigned int mem_idx
= i
;
517 h_force
.data
[mem_idx
].x
+= fi
.x
;
518 h_force
.data
[mem_idx
].y
+= fi
.y
;
519 h_force
.data
[mem_idx
].z
+= fi
.z
;
520 h_force
.data
[mem_idx
].w
+= pei
;
523 h_virial
.data
[0*m_virial_pitch
+mem_idx
] += virialxxi
;
524 h_virial
.data
[1*m_virial_pitch
+mem_idx
] += virialxyi
;
525 h_virial
.data
[2*m_virial_pitch
+mem_idx
] += virialxzi
;
526 h_virial
.data
[3*m_virial_pitch
+mem_idx
] += virialyyi
;
527 h_virial
.data
[4*m_virial_pitch
+mem_idx
] += virialyzi
;
528 h_virial
.data
[5*m_virial_pitch
+mem_idx
] += virialzzi
;
532 if (m_prof
) m_prof
->pop();
536 /*! \param timestep Current time step
538 template < class evaluator
>
539 CommFlags PotentialPair
< evaluator
>::getRequestedCommFlags(unsigned int timestep
)
541 CommFlags flags
= CommFlags(0);
543 if (evaluator::needsCharge())
544 flags
[comm_flag::charge
] = 1;
546 if (evaluator::needsDiameter())
547 flags
[comm_flag::diameter
] = 1;
549 flags
|= ForceCompute::getRequestedCommFlags(timestep
);
555 //! Export this pair potential to python
556 /*! \param name Name of the class in the exported python module
557 \tparam T Class type to export. \b Must be an instantiated PotentialPair class template.
559 template < class T
> void export_PotentialPair(const std::string
& name
)
561 boost::python::scope in_pair
=
562 boost::python::class_
<T
, boost::shared_ptr
<T
>, boost::python::bases
<ForceCompute
>, boost::noncopyable
>
563 (name
.c_str(), boost::python::init
< boost::shared_ptr
<SystemDefinition
>, boost::shared_ptr
<NeighborList
>, const std::string
& >())
564 .def("setParams", &T::setParams
)
565 .def("setRcut", &T::setRcut
)
566 .def("setRon", &T::setRon
)
567 .def("setShiftMode", &T::setShiftMode
)
570 boost::python::enum_
<typename
T::energyShiftMode
>("energyShiftMode")
571 .value("no_shift", T::no_shift
)
572 .value("shift", T::shift
)
573 .value("xplor", T::xplor
)
578 #pragma warning( pop )
581 #endif // __POTENTIAL_PAIR_H__