Update MTK documentation
[hoomd-blue.git] / python-module / hoomd_script / integrate.py
blobdeeddeafe8bb376caa898758d5233eb165031290
1 # -- start license --
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
32 # permission.
34 # Disclaimer
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.
48 # -- end license --
50 # Maintainer: joaander / All Developers are free to add commands for new features
52 ## \package hoomd_script.integrate
53 # \brief Commands that integrate the equations of motion
55 # To integrate the system forward in time, an integration mode must be set. Only one integration mode can be active at
56 # a time, and the last \c integrate.mode_* command before the run() command is the one that will take effect. It is
57 # possible to set one mode, run() for a certain number of steps and then switch to another mode before the next run()
58 # command.
60 # The most commonly used mode is integrate.mode_standard . It specifies a standard mode where, at each time
61 # step, all of the specified forces are evaluated and used in moving the system forward to the next step.
62 # integrate.mode_standard doesn't integrate any particles by itself, one or more compatible integration methods must
63 # be specified before the run() command. Like commands that specify forces, integration methods are \b persistent and
64 # remain set until they are disabled (this differs greatly from HOOMD-blue behavior in all versions prior to 0.9.0).
65 # The benefit and reason for this change is that now multiple integration methods can be specified on different particle
66 # groups, allowing portions of the system to be fixed, integrated at a different temperature, etc...
68 # To clarify, the following series of commands will run for 1000 time steps in the NVT ensemble and then switch to
69 # NVE for another 1000 steps.
71 # \code
72 # all = group.all()
73 # integrate.mode_standard(dt=0.005)
74 # nvt = integrate.nvt(group=all, T=1.2, tau=0.5)
75 # run(1000)
76 # nvt.disable()
77 # integrate.nve(group=all)
78 # run(1000)
79 # \endcode
81 # For more detailed information on the interaction of integration methods and integration modes, see
82 # integrate.mode_standard.
84 # Some integrators provide parameters that can be changed between runs.
85 # In order to access the integrator to change it, it needs to be saved
86 # in a variable. For example:
87 # \code
88 # integrator = integrate.nvt(group=all, T=1.2, tau=0.5)
89 # run(100)
90 # integrator.set_params(T=1.0)
91 # run(100)
92 # \endcode
93 # This code snippet runs the first 100 time steps with T=1.2 and the next 100 with T=1.0
95 import hoomd;
96 import copy;
97 from hoomd_script import globals;
98 from hoomd_script import compute;
99 import sys;
100 from hoomd_script import util;
101 from hoomd_script import variant;
102 from hoomd_script import init;
103 from hoomd_script import comm;
105 ## \internal
106 # \brief Base class for integrators
108 # An integrator in hoomd_script reflects an Integrator in c++. It is responsible
109 # for all high-level management that happens behind the scenes for hoomd_script
110 # writers. 1) The instance of the c++ integrator itself is tracked 2) All
111 # forces created so far in the simulation are updated in the cpp_integrator
112 # whenever run() is called.
113 class _integrator:
114 ## \internal
115 # \brief Constructs the integrator
117 # This doesn't really do much bet set some member variables to None
118 def __init__(self):
119 # check if initialization has occured
120 if not init.is_initialized():
121 globals.msg.error("Cannot create integrator before initialization\n");
122 raise RuntimeError('Error creating integrator');
124 # by default, integrators do not support methods
125 self.cpp_integrator = None;
126 self.supports_methods = False;
128 # save ourselves in the global variable
129 globals.integrator = self;
131 ## \var cpp_integrator
132 # \internal
133 # \brief Stores the C++ side Integrator managed by this class
135 ## \var supports_methods
136 # \internal
137 # \brief True if this integrator supports integration methods
138 # \note If hoomd ever needs to support multiple TYPES of methods, we could just change this to a string naming the
139 # type that is supported and add a type string to each of the integration_methods.
141 ## \internal
142 # \brief Checks that proper initialization has completed
143 def check_initialization(self):
144 # check that we have been initialized properly
145 if self.cpp_integrator is None:
146 globals.msg.error('Bug in hoomd_script: cpp_integrator not set, please report\n');
147 raise RuntimeError();
149 ## \internal
150 # \brief Updates the integrators in the reflected c++ class
151 def update_forces(self):
152 self.check_initialization();
154 # set the forces
155 self.cpp_integrator.removeForceComputes();
156 for f in globals.forces:
157 if f.cpp_force is None:
158 globals.msg.error('Bug in hoomd_script: cpp_force not set, please report\n');
159 raise RuntimeError('Error updating forces');
161 if f.log or f.enabled:
162 f.update_coeffs();
164 if f.enabled:
165 self.cpp_integrator.addForceCompute(f.cpp_force);
167 # set the constraint forces
168 for f in globals.constraint_forces:
169 if f.cpp_force is None:
170 globals.msg.error('Bug in hoomd_script: cpp_force not set, please report\n');
171 raise RuntimeError('Error updating forces');
173 if f.enabled:
174 self.cpp_integrator.addForceConstraint(f.cpp_force);
177 ## \internal
178 # \brief Updates the integration methods in the reflected c++ class
179 def update_methods(self):
180 self.check_initialization();
182 # if we support methods, add them all to the list
183 if self.supports_methods:
184 self.cpp_integrator.removeAllIntegrationMethods();
186 if len(globals.integration_methods) == 0:
187 globals.msg.error('This integrator requires that one or more integration methods be specified.\n');
188 raise RuntimeError('Error initializing integrator methods');
190 for m in globals.integration_methods:
191 self.cpp_integrator.addIntegrationMethod(m.cpp_method);
193 else:
194 if len(globals.integration_methods) > 0:
195 globals.msg.error("This integrator does not support the use of integration methods,\n");
196 globals.msg.error("but some have been specified in the script. Remove them or use\n");
197 globals.msg.error("a different integrator.\n");
198 raise RuntimeError('Error initializing integrator methods');
200 ## \internal
201 # \brief Counts the number of degrees of freedom and updates each compute.thermo specified
202 def update_thermos(self):
203 self.check_initialization();
205 for t in globals.thermos:
206 ndof = self.cpp_integrator.getNDOF(t.group.cpp_group);
207 t.cpp_compute.setNDOF(ndof);
209 ## \internal
210 # \brief Base class for integration methods
212 # An integration_method in hoomd_script reflects an IntegrationMethod in c++. It is responsible for all high-level
213 # management that happens behind the scenes for hoomd_script writers. 1) The instance of the c++ integration method
214 # itself is tracked and added to the integrator and 2) methods are provided for disabling the integration method from
215 # being active for the next run()
217 # The design of integration_method exactly mirrors that of _force for consistency
218 class _integration_method:
219 ## \internal
220 # \brief Constructs the integration_method
222 # Initializes the cpp_method to None.
223 def __init__(self):
224 # check if initialization has occured
225 if not init.is_initialized():
226 globals.msg.error("Cannot create an integration method before initialization\n");
227 raise RuntimeError('Error creating integration method');
229 self.cpp_method = None;
231 self.enabled = True;
232 globals.integration_methods.append(self);
234 ## \var enabled
235 # \internal
236 # \brief True if the integration method is enabled
238 ## \var cpp_method
239 # \internal
240 # \brief Stores the C++ side IntegrationMethod managed by this class
242 ## \internal
243 # \brief Checks that proper initialization has completed
244 def check_initialization(self):
245 # check that we have been initialized properly
246 if self.cpp_method is None:
247 globals.msg.error('Bug in hoomd_script: cpp_method not set, please report\n');
248 raise RuntimeError();
250 ## Disables the integration method
252 # \b Examples:
253 # \code
254 # method.disable()
255 # \endcode
257 # Executing the disable command will remove the integration method from the simulation.Any run() command executed
258 # after disabling an integration method will not apply the integration method to the particles during the
259 # simulation. A disabled integration method can be re-enabled with enable()
261 # To use this command, you must have saved the force in a variable, as
262 # shown in this example:
263 # \code
264 # method = integrate.some_method()
265 # # ... later in the script
266 # method.disable()
267 # \endcode
268 def disable(self):
269 util.print_status_line();
270 self.check_initialization()
272 # check if we are already disabled
273 if not self.enabled:
274 globals.msg.warning("Ignoring command to disable an integration method that is already disabled");
275 return;
277 self.enabled = False;
278 globals.integration_methods.remove(self);
280 ## Enables the integration method
282 # \b Examples:
283 # \code
284 # method.enable()
285 # \endcode
287 # See disable() for a detailed description.
288 def enable(self):
289 util.print_status_line();
290 self.check_initialization();
292 # check if we are already disabled
293 if self.enabled:
294 globals.msg.warning("Ignoring command to enable an integration method that is already enabled");
295 return;
297 self.enabled = True;
298 globals.integration_methods.append(self);
300 ## Enables a variety of standard integration methods
302 # integrate.mode_standard performs a standard time step integration technique to move the system forward. At each time
303 # step, all of the specified forces are evaluated and used in moving the system forward to the next step.
305 # By itself, integrate.mode_standard does nothing. You must specify one or more integration methods to apply to the
306 # system. Each integration method can be applied to only a specific group of particles enabling advanced simulation
307 # techniques.
309 # The following commands can be used to specify the integration methods used by integrate.mode_standard.
310 # - integrate.bdnvt
311 # - integrate.bdnvt_rigid
312 # - integrate.nve
313 # - integrate.nve_rigid
314 # - integrate.nvt
315 # - integrate.nvt_rigid
316 # - integrate.npt
317 # - integrate.nph
319 # There can only be one integration mode active at a time. If there are more than one integrate.mode_* commands in
320 # a hoomd script, only the most recent before a given run() will take effect.
322 # \MPI_SUPPORTED
323 class mode_standard(_integrator):
324 ## Specifies the standard integration mode
325 # \param dt Each time step of the simulation run() will advance the real time of the system forward by \a dt (in time units)
327 # \b Examples:
328 # \code
329 # integrate.mode_standard(dt=0.005)
330 # integrator_mode = integrate.mode_standard(dt=0.001)
331 # \endcode
332 def __init__(self, dt):
333 util.print_status_line();
335 # initialize base class
336 _integrator.__init__(self);
338 # initialize the reflected c++ class
339 self.cpp_integrator = hoomd.IntegratorTwoStep(globals.system_definition, dt);
340 self.supports_methods = True;
342 globals.system.setIntegrator(self.cpp_integrator);
344 ## Changes parameters of an existing integration mode
345 # \param dt New time step delta (if set) (in time units)
347 # To change the parameters of an existing integration mode, you must save it in a variable when it is
348 # specified, like so:
349 # \code
350 # integrator_mode = integrate.mode_standard(dt=5e-3)
351 # \endcode
353 # \b Examples:
354 # \code
355 # integrator_mode.set_params(dt=0.007)
356 # \endcode
357 def set_params(self, dt=None):
358 util.print_status_line();
359 self.check_initialization();
361 # change the parameters
362 if dt is not None:
363 self.cpp_integrator.setDeltaT(dt);
365 ## NVT Integration via the Nosé-Hoover thermostat
367 # integrate.nvt performs constant volume, constant temperature simulations using the Nosé-Hoover thermostat.
369 # There are two implementations of NVT in hoomd:
370 # * The MTK equations are described in Refs. \cite Martyna1994 \cite Martyna1996.
371 # * The other mode is Equation 13 in ref. \cite Bond1999.
373 # MTK exhibits superior time stability and accuracy, it is the default. The other mode is deprecated and will be
374 # removed in a future version of HOOMD-blue. It is kept now for backwards compatibility.
376 # integrate.nvt is an integration method. It must be used in concert with an integration mode. It can be used while
377 # the following modes are active:
378 # - integrate.mode_standard
380 # integrate.nvt uses the proper number of degrees of freedom to compute the temperature of the system in both
381 # 2 and 3 dimensional systems, as long as the number of dimensions is set before the integrate.nvt command
382 # is specified.
383 # \MPI_SUPPORTED
384 class nvt(_integration_method):
385 ## Specifies the NVT integration method
386 # \param group Group of particles on which to apply this method.
387 # \param T Temperature set point for the Nosé-Hoover thermostat. (in energy units)
388 # \param tau Coupling constant for the Nosé-Hoover thermostat. (in time units)
389 # \param mtk If *true* (default), use the time-reversible and measure-preserving Martyna-Tobias-Klein (MTK) update equations
391 # \f$ \tau \f$ is related to the Nosé mass \f$ Q \f$ by
392 # \f[ \tau = \sqrt{\frac{Q}{g k_B T_0}} \f] where \f$ g \f$ is the number of degrees of freedom,
393 # and \f$ k_B T_0 \f$ is the set point (\a T above).
395 # \a T can be a variant type, allowing for temperature ramps in simulation runs.
397 # Internally, a compute.thermo is automatically specified and associated with \a group.
399 # \b Examples:
400 # \code
401 # all = group.all()
402 # integrate.nvt(group=all, T=1.0, tau=0.5)
403 # integrator = integrate.nvt(group=all, tau=1.0, T=0.65)
404 # integrator = integrate.nvt(group=all, tau=1.0, T=0.65, mtk=False)
405 # typeA = group.type('A')
406 # integrator = integrate.nvt(group=typeA, tau=1.0, T=variant.linear_interp([(0, 4.0), (1e6, 1.0)]))
407 # \endcode
408 def __init__(self, group, T, tau, mtk=True):
409 util.print_status_line();
411 # initialize base class
412 _integration_method.__init__(self);
414 # setup the variant inputs
415 T = variant._setup_variant_input(T);
417 # create the compute thermo
418 # as an optimization, NVT (without MTK) on the GPU uses the thermo is a way that produces incorrect values for the pressure
419 # if we are given the overall group_all, create a new group so that the invalid pressure is not passed to
420 # analyze.log
421 if group is globals.group_all and not mtk:
422 group_copy = copy.copy(group);
423 group_copy.name = "__nvt_all";
424 util._disable_status_lines = True;
425 thermo = compute.thermo(group_copy);
426 util._disable_status_lines = False;
427 else:
428 thermo = compute._get_unique_thermo(group=group);
430 # setup suffix
431 suffix = '_' + group.name;
433 # initialize the reflected c++ class
434 if mtk is False:
435 if not globals.exec_conf.isCUDAEnabled():
436 self.cpp_method = hoomd.TwoStepNVT(globals.system_definition, group.cpp_group, thermo.cpp_compute, tau, T.cpp_variant, suffix);
437 else:
438 self.cpp_method = hoomd.TwoStepNVTGPU(globals.system_definition, group.cpp_group, thermo.cpp_compute, tau, T.cpp_variant, suffix);
439 else:
440 if not globals.exec_conf.isCUDAEnabled():
441 self.cpp_method = hoomd.TwoStepNVTMTK(globals.system_definition, group.cpp_group, thermo.cpp_compute, tau, T.cpp_variant, suffix);
442 else:
443 self.cpp_method = hoomd.TwoStepNVTMTKGPU(globals.system_definition, group.cpp_group, thermo.cpp_compute, tau, T.cpp_variant, suffix);
446 self.cpp_method.validateGroup()
448 ## Changes parameters of an existing integrator
449 # \param T New temperature (if set) (in energy units)
450 # \param tau New coupling constant (if set) (in time units)
452 # To change the parameters of an existing integrator, you must save it in a variable when it is
453 # specified, like so:
454 # \code
455 # integrator = integrate.nvt(group=all, tau=1.0, T=0.65)
456 # \endcode
458 # \b Examples:
459 # \code
460 # integrator.set_params(tau=0.6)
461 # integrator.set_params(tau=0.7, T=2.0)
462 # \endcode
463 def set_params(self, T=None, tau=None):
464 util.print_status_line();
465 self.check_initialization();
467 # change the parameters
468 if T is not None:
469 # setup the variant inputs
470 T = variant._setup_variant_input(T);
471 self.cpp_method.setT(T.cpp_variant);
472 if tau is not None:
473 self.cpp_method.setTau(tau);
475 ## NPT Integration via MTK barostat-thermostat with triclinic unit cell
477 # integrate.npt performs constant pressure, constant temperature simulations, allowing for a fully deformable
478 # simulation box
480 # The integration method is based on the rigorous Martyna-Tobias-Klein equations of motion for NPT.
481 # For optimal stability, the update equations leave the phase-space meeasure invariant and are manifestly
482 # time-reversible.
484 # By default, integrate.npt performs integration in a cubic box under hydrostatic pressure by simultaneously
485 # rescaling the lengths \a Lx, \a Ly and \a Lz of the simulation box.
487 # integrate.npt can also perform more advanced integration modes. The integration mode
488 # is specified by a set of \a couplings and by specifying the box degrees of freedom that are put under
489 # barostat control.
491 # \a Couplings define which diagonal elements of the pressure tensor \f$ P_{\alpha,\beta} \f$
492 # should be averaged over, so that the corresponding box lengths are rescaled by the same amount.
494 # Valid \a couplings are:<br>
495 # - \b none (all box lengths are updated independently)
496 # - \b xy (\a Lx and \a Ly are coupled)
497 # - \b xz (\a Lx and \a Lz are coupled)
498 # - \b yz (\a Ly and \a Lz are coupled)
499 # - \b xyz (\a Lx and \a Ly and \a Lz are coupled)
501 # The default coupling is \b xyz, i.e. the ratios between all box lengths stay constant.
503 # <em>Degrees of freedom</em> of the box specify which lengths and tilt factors of the box should be updated,
504 # and how particle coordinates and velocities should be rescaled.
506 # Valid keywords for degrees of freedom are:
507 # - \b x (the box length Lx is updated)
508 # - \b y (the box length Ly is updated)
509 # - \b z (the box length Lz is updated)
510 # - \b xy (the tilt factor xy is updated)
511 # - \b xz (the tilt factor xz is updated)
512 # - \b yz (the tilt factor yz is updated)
513 # - \b all (all elements are updated, equivalent to \b x, \b y, \b z, \b xy, \b xz, and \b yz together)
515 # Any of the six keywords can be combined together. By default, the \b x, \b y, and \b z degrees of freedom
516 # are updated.
518 # \note If any of the diagonal \a x, \a y, \a z degrees of freedom is not being integrated, pressure tensor components
519 # along that direction are not considered for the remaining degrees of freedom.
521 # For example:
522 # - Specifying \b xyz copulings and \b x, \b y, and \b z degrees of freedom amounts to \a cubic symmetry (default)
523 # - Specifying \b xy couplings and \b x, \b y, and \b z degrees of freedom amounts to \a tetragonal symmetry.
524 # - Specifing no couplings and \b all degrees of freedom amounts to a fully deformable \a triclinic unit cell
526 # integrate.npt is an integration method. It must be used in concert with an integration mode. It can be used while
527 # the following modes are active:
528 # - integrate.mode_standard
530 # integrate.npt uses the proper number of degrees of freedom to compute the temperature and pressure of the system in
531 # both 2 and 3 dimensional systems, as long as the number of dimensions is set before the integrate.npt command
532 # is specified.
534 # For the MTK equations of motion, see:
535 # \cite Martyna1994
536 # \cite Tuckerman2006
537 # \cite Yu2010
538 # Glaser et. al (2013), to be published
539 # \MPI_SUPPORTED
540 class npt(_integration_method):
541 ## Specifies the NPT integrator
542 # \param group Group of particles on which to apply this method.
543 # \param T Temperature set point for the thermostat, not needed if \b nph=True (in energy units)
544 # \param P Pressure set point for the barostat (in pressure units)
545 # \param tau Coupling constant for the thermostat, not needed if \a nph=True (in time units)
546 # \param tauP Coupling constant for the barostat (in time units)
547 # \param couple Couplings of diagonal elements of the stress tensor, can be \b "none", \b "xy", \b "xz",\b "yz", or \b "xyz" (default)
548 # \param x if \b True, rescale \a Lx and x component of particle coordinates and velocities
549 # \param y if \b True, rescale \a Ly and y component of particle coordinates and velocities
550 # \param z if \b True, rescale \a Lz and z component of particle coordinates and velocities
551 # \param xy if \b True, rescale \a xy tilt factor and x and y components of particle coordinates and velocities
552 # \param xz if \b True, rescale \a xz tilt factor and x and z components of particle coordinates and velocities
553 # \param yz if \b True, rescale \a yz tilt factor and y and z components of particle coordinates and velocities
554 # \param all if \b True, rescale all lengths and tilt factors and components of particle coordinates and velocities
555 # \param nph if \b True, integrate without a thermostat, i.e. in the NPH ensemble
556 # \param rescale_all if \b True, rescale all particles, not only those in the group
558 # Both \a T and \a P can be variant types, allowing for temperature/pressure ramps in simulation runs.
560 # \f$ \tau \f$ is related to the Nos&eacute; mass \f$ Q \f$ by
561 # \f[ \tau = \sqrt{\frac{Q}{g k_B T_0}} \f] where \f$ g \f$ is the number of degrees of freedom,
562 # and \f$ k_B T_0 \f$ is the set point (\a T above).
564 # Internally, a compute.thermo is automatically specified and associated with \a group.
566 # \b Examples:
567 # \code
568 # integrate.npt(group=all, T=1.0, tau=0.5, tauP=1.0, P=2.0)
569 # integrator = integrate.npt(group=all, tau=1.0, dt=5e-3, T=0.65, tauP = 1.2, P=2.0)
570 # # orthorhombic symmetry
571 # integrator = integrate.npt(group=all, tau=1.0, dt=5e-3, T=0.65, tauP = 1.2, P=2.0, couple="none")
572 # # tetragonal symmetry
573 # integrator = integrate.npt(group=all, tau=1.0, dt=5e-3, T=0.65, tauP = 1.2, P=2.0, couple="xy")
574 # # triclinic symmetry
575 # integrator = integrate.npt(group=all, tau=1.0, dt=5e-3, T=0.65, tauP = 1.2, P=2.0, couple="none", all=True)
576 # \endcode
577 def __init__(self, group, P, tauP, couple="xyz", x=True, y=True, z=True, xy=False, xz=False, yz=False, all=False, nph=False, T=None, tau=None, rescale_all=None):
578 util.print_status_line();
580 # check the input
581 if (T is None or tau is None):
582 if nph is False:
583 globals.msg.error("integrate.npt: Need temperature T and thermostat time scale tau.\n");
584 raise RuntimeError("Error setting up NPT integration.");
585 else:
586 # use dummy values
587 T=1.0
588 tau=1.0
590 # initialize base class
591 _integration_method.__init__(self);
593 # setup the variant inputs
594 T = variant._setup_variant_input(T);
595 P = variant._setup_variant_input(P);
597 # create the compute thermo
598 thermo_group = compute._get_unique_thermo(group=group);
599 thermo_all = compute._get_unique_thermo(group=globals.group_all);
601 # need to know if we are running 2D simulations
602 twod = (globals.system_definition.getNDimensions() == 2);
603 if twod:
604 globals.msg.notice(2, "When running in 2D, z couplings and degrees of freedom are silently ignored.\n");
606 # initialize the reflected c++ class
607 if twod:
608 # silently ignore any couplings that involve z
609 if couple == "none":
610 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_none
611 elif couple == "xy":
612 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_xy
613 elif couple == "xz":
614 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_none
615 elif couple == "yz":
616 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_none
617 elif couple == "xyz":
618 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_xy
619 else:
620 globals.msg.error("Invalid coupling mode\n");
621 raise RuntimeError("Error setting up NPT integration.");
622 else:
623 if couple == "none":
624 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_none
625 elif couple == "xy":
626 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_xy
627 elif couple == "xz":
628 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_xz
629 elif couple == "yz":
630 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_yz
631 elif couple == "xyz":
632 cpp_couple = hoomd.TwoStepNPTMTK.couplingMode.couple_xyz
633 else:
634 globals.msg.error("Invalid coupling mode\n");
635 raise RuntimeError("Error setting up NPT integration.");
637 # set degrees of freedom flags
638 # silently ignore z related degrees of freedom when running in 2d
639 flags = 0;
640 if x or all:
641 flags |= hoomd.TwoStepNPTMTK.baroFlags.baro_x
642 if y or all:
643 flags |= hoomd.TwoStepNPTMTK.baroFlags.baro_y
644 if (z or all) and not twod:
645 flags |= hoomd.TwoStepNPTMTK.baroFlags.baro_z
646 if xy or all:
647 flags |= hoomd.TwoStepNPTMTK.baroFlags.baro_xy
648 if (xz or all) and not twod:
649 flags |= hoomd.TwoStepNPTMTK.baroFlags.baro_xz
650 if (yz or all) and not twod:
651 flags |= hoomd.TwoStepNPTMTK.baroFlags.baro_yz
653 if not globals.exec_conf.isCUDAEnabled():
654 self.cpp_method = hoomd.TwoStepNPTMTK(globals.system_definition, group.cpp_group, thermo_group.cpp_compute, tau, tauP, T.cpp_variant, P.cpp_variant, cpp_couple, flags, nph);
655 else:
656 self.cpp_method = hoomd.TwoStepNPTMTKGPU(globals.system_definition, group.cpp_group, thermo_group.cpp_compute, tau, tauP, T.cpp_variant, P.cpp_variant, cpp_couple, flags, nph);
658 if rescale_all is not None:
659 self.cpp_method.setRescaleAll(rescale_all)
661 self.cpp_method.validateGroup()
663 ## Changes parameters of an existing integrator
664 # \param T New temperature (if set) (in energy units)
665 # \param tau New coupling constant (if set) (in time units)
666 # \param P New pressure (if set) (in pressure units)
667 # \param tauP New barostat coupling constant (if set) (in time units)
668 # \param rescale_all if \b True, rescale all particles, not only those in the group
670 # To change the parameters of an existing integrator, you must save it in a variable when it is
671 # specified, like so:
672 # \code
673 # integrator = integrate.npt(tau=1.0, T=0.65)
674 # \endcode
676 # \b Examples:
677 # \code
678 # integrator.set_params(tau=0.6)
679 # integrator.set_params(dt=3e-3, T=2.0, P=1.0)
680 # \endcode
681 def set_params(self, T=None, tau=None, P=None, tauP=None, rescale_all=None):
682 util.print_status_line();
683 self.check_initialization();
685 # change the parameters
686 if T is not None:
687 # setup the variant inputs
688 T = variant._setup_variant_input(T);
689 self.cpp_method.setT(T.cpp_variant);
690 if tau is not None:
691 self.cpp_method.setTau(tau);
692 if P is not None:
693 # setup the variant inputs
694 P = variant._setup_variant_input(P);
695 self.cpp_method.setP(P.cpp_variant);
696 if tauP is not None:
697 self.cpp_method.setTauP(tauP);
698 if rescale_all is not None:
699 self.cpp_method.setRescaleAll(rescale_all)
702 ## NPH Integration via MTK barostat-thermostat with triclinic unit cell
704 # integrate.nph performs constant pressure (NPH) simulations using a Martyna-Tobias-Klein barostat, an
705 # explicitly reversible and measure-preserving integration scheme. It allows for fully deformable simulation
706 # cells and uses the same underying integrator as integrate.npt (with \b nph=True).
708 # The available options are identical to those of integrate.npt, except that *T* cannot be specified.
709 # For further information, refer to the documentation of integrate.npt
711 # \note A time scale \b tau_p for the relaxation of the barostat is required. This is defined as the
712 # relaxation time the barostat would have at an average temperature \f$ T_0 =1 \f$, and it
713 # is related to the internally used (Andersen) Barostat mass \f$W\f$ via
714 # \f$ W=d N T_0 \tau_p^2 \f$, where \f$ d \f$ is the dimensionsality and \f$ N \f$ the number
715 # of particles.
717 # integrate.nph is an integration method. It must be used in concert with an integration mode. It can be used while
718 # the following modes are active:
719 # - integrate.mode_standard
721 # \sa integrate.npt
722 # \MPI_SUPPORTED
723 class nph(npt):
724 ## Specifies the NPH integrator
725 # \param params Parameters used for the underlying integrate.npt (for documentation, see there)
727 # \b Examples:
728 # \code
729 # # Triclinic unit cell
730 # nph=integrate.nph(group=all, P=2.0, tau_p=1.0, couple="none", all=True)
731 # # Cubic unit cell
732 # nph = integrate.nph(group=all, P=2.0, tau_p=1.0)
733 # \endcode
734 def __init__(self, **params):
735 util.print_status_line();
737 # initialize base class
738 util._disable_status_lines = True;
739 npt.__init__(self, nph=True, T=1.0, **params);
740 util._disable_status_lines = False;
742 ## NVE Integration via Velocity-Verlet
744 # integrate.nve performs constant volume, constant energy simulations using the standard
745 # Velocity-Verlet method. For poor initial conditions that include overlapping atoms, a
746 # limit can be specified to the movement a particle is allowed to make in one time step.
747 # After a few thousand time steps with the limit set, the system should be in a safe state
748 # to continue with unconstrained integration.
750 # Another use-case for integrate.nve is to fix the velocity of a certain group of particles. This can be achieved by
751 # setting the velocity of those particles in the initial condition and setting the \a zero_force option to True
752 # for that group. A True value for \a zero_force causes integrate.nve to ignore any net force on each particle and
753 # integrate them forward in time with a constant velocity.
755 # \note With an active limit, Newton's third law is effectively \b not obeyed and the system
756 # can gain linear momentum. Activate the update.zero_momentum updater during the limited nve
757 # run to prevent this.
759 # integrate.nve is an integration method. It must be used in concert with an integration mode. It can be used while
760 # the following modes are active:
761 # - integrate.mode_standard
762 # \MPI_SUPPORTED
763 class nve(_integration_method):
764 ## Specifies the NVE integration method
765 # \param group Group of particles on which to apply this method.
766 # \param limit (optional) Enforce that no particle moves more than a distance of \a limit in a single time step
767 # \param zero_force When set to true, particles in the \a group are integrated forward in time with constant
768 # velocity and any net force on them is ignored.
770 # Internally, a compute.thermo is automatically specified and associated with \a group.
772 # \b Examples:
773 # \code
774 # all = group.all()
775 # integrate.nve(group=all)
776 # integrator = integrate.nve(group=all)
777 # typeA = group.type('A')
778 # integrate.nve(group=typeA, limit=0.01)
779 # integrate.nve(group=typeA, zero_force=True)
780 # \endcode
781 def __init__(self, group, limit=None, zero_force=False):
782 util.print_status_line();
784 # initialize base class
785 _integration_method.__init__(self);
787 # create the compute thermo
788 compute._get_unique_thermo(group=group);
790 # initialize the reflected c++ class
791 if not globals.exec_conf.isCUDAEnabled():
792 self.cpp_method = hoomd.TwoStepNVE(globals.system_definition, group.cpp_group, False);
793 else:
794 self.cpp_method = hoomd.TwoStepNVEGPU(globals.system_definition, group.cpp_group);
796 # set the limit
797 if limit is not None:
798 self.cpp_method.setLimit(limit);
800 self.cpp_method.setZeroForce(zero_force);
802 self.cpp_method.validateGroup()
804 ## Changes parameters of an existing integrator
805 # \param limit (if set) New limit value to set. Removes the limit if limit is False
806 # \param zero_force (if set) New value for the zero force option
808 # To change the parameters of an existing integrator, you must save it in a variable when it is
809 # specified, like so:
810 # \code
811 # integrator = integrate.nve(group=all)
812 # \endcode
814 # \b Examples:
815 # \code
816 # integrator.set_params(limit=0.01)
817 # integrator.set_params(limit=False)
818 # \endcode
819 def set_params(self, limit=None, zero_force=None):
820 util.print_status_line();
821 self.check_initialization();
823 # change the parameters
824 if limit is not None:
825 if limit == False:
826 self.cpp_method.removeLimit();
827 else:
828 self.cpp_method.setLimit(limit);
830 if zero_force is not None:
831 self.cpp_method.setZeroForce(zero_force);
833 ## NVT integration via Brownian dynamics
835 # integrate.bdnvt performs constant volume, fixed average temperature simulation based on a
836 # NVE simulation with added damping and stochastic heat bath forces.
838 # The total added %force \f$ \vec{F}\f$ is
839 # \f[ \vec{F} = -\gamma \cdot \vec{v} + \vec{F}_{\mathrm{rand}} \f]
840 # where \f$ \vec{v} \f$ is the particle's velocity and \f$ \vec{F}_{\mathrm{rand}} \f$
841 # is a random force with magnitude chosen via the fluctuation-dissipation theorem
842 # to be consistent with the specified drag (\a gamma) and temperature (\a T).
844 # For poor initial conditions that include overlapping atoms, a
845 # limit can be specified to the movement a particle is allowed to make in one time step.
846 # After a few thousand time steps with the limit set, the system should be in a safe state
847 # to continue with unconstrained integration.
849 # \note With an active limit, Newton's third law is effectively \b not obeyed and the system
850 # can gain linear momentum. Activate the update.zero_momentum updater during the limited bdnvt
851 # run to prevent this.
853 # integrate.bdnvt is an integration method. It must be used in concert with an integration mode. It can be used while
854 # the following modes are active:
855 # - integrate.mode_standard
857 # integrate.bdnvt uses the proper number of degrees of freedom to compute the temperature of the system in both
858 # 2 and 3 dimensional systems, as long as the number of dimensions is set before the integrate.bdnvt command
859 # is specified.
860 # \MPI_SUPPORTED
861 class bdnvt(_integration_method):
862 ## Specifies the BD NVT integrator
863 # \param group Group of particles on which to apply this method.
864 # \param T Temperature of the simulation (in energy units)
865 # \param seed Random seed to use for the run. Simulations that are identical, except for the seed, will follow
866 # different trajectories.
867 # \param gamma_diam If True, then then gamma for each particle will be assigned to its diameter. If False (the
868 # default), gammas are assigned per particle type via set_gamma().
869 # \param limit (optional) Enforce that no particle moves more than a distance of \a limit in a single time step
870 # \param tally (optional) If true, the energy exchange between the bd thermal reservoir and the particles is
871 # tracked. Total energy conservation can then be monitored by adding
872 # \b bdnvt_reservoir_energy_<i>groupname</i> to the logged quantities.
874 # \a T can be a variant type, allowing for temperature ramps in simulation runs.
876 # Internally, a compute.thermo is automatically specified and associated with \a group.
878 # \warning If starting from a restart binary file, the energy of the reservoir will be reset to zero.
879 # \b Examples:
880 # \code
881 # all = group.all();
882 # integrate.bdnvt(group=all, T=1.0, seed=5)
883 # integrator = integrate.bdnvt(group=all, T=1.0, seed=100)
884 # integrate.bdnvt(group=all, T=1.0, limit=0.01, gamma_diam=1, tally=True)
885 # typeA = group.type('A');
886 # integrate.bdnvt(group=typeA, T=variant.linear_interp([(0, 4.0), (1e6, 1.0)]))
887 # \endcode
888 def __init__(self, group, T, seed=0, gamma_diam=False, limit=None, tally=False):
889 util.print_status_line();
891 # initialize base class
892 _integration_method.__init__(self);
894 # setup the variant inputs
895 T = variant._setup_variant_input(T);
897 # create the compute thermo
898 compute._get_unique_thermo(group=group);
900 # setup suffix
901 suffix = '_' + group.name;
903 # initialize the reflected c++ class
904 if not globals.exec_conf.isCUDAEnabled():
905 self.cpp_method = hoomd.TwoStepBDNVT(globals.system_definition, group.cpp_group, T.cpp_variant, seed, gamma_diam, suffix);
906 else:
907 self.cpp_method = hoomd.TwoStepBDNVTGPU(globals.system_definition, group.cpp_group, T.cpp_variant, seed, gamma_diam, suffix);
909 self.cpp_method.setTally(tally);
911 # set the limit
912 if limit is not None:
913 self.cpp_method.setLimit(limit);
915 self.cpp_method.validateGroup()
917 ## Changes parameters of an existing integrator
918 # \param T New temperature (if set) (in energy units)
919 # \param tally (optional) If true, the energy exchange between the bd thermal reservoir and the particles is
920 # tracked. Total energy conservation can then be monitored by adding
921 # \b bdnvt_reservoir_energy_<i>groupname</i> to the logged quantities.
923 # To change the parameters of an existing integrator, you must save it in a variable when it is
924 # specified, like so:
925 # \code
926 # integrator = integrate.bdnvt(group=all, T=1.0)
927 # \endcode
929 # \b Examples:
930 # \code
931 # integrator.set_params(T=2.0)
932 # integrator.set_params(tally=False)
933 # \endcode
934 def set_params(self, T=None, tally=None):
935 util.print_status_line();
936 self.check_initialization();
938 # change the parameters
939 if T is not None:
940 # setup the variant inputs
941 T = variant._setup_variant_input(T);
942 self.cpp_method.setT(T.cpp_variant);
944 if tally is not None:
945 self.cpp_method.setTally(tally);
947 ## Sets gamma parameter for a particle type
948 # \param a Particle type
949 # \param gamma \f$ \gamma \f$ for particle type \a (in units of force/velocity)
951 # set_gamma() sets the coefficient \f$ \gamma \f$ for a single particle type, identified
952 # by name.
954 # The gamma parameter determines how strongly a particular particle is coupled to
955 # the stochastic bath. The higher the gamma, the more strongly coupled: see
956 # integrate.bdnvt.
958 # If gamma is not set for any particle type, it will automatically default to 1.0.
959 # It is not an error to specify gammas for particle types that do not exist in the simulation.
960 # This can be useful in defining a single simulation script for many different types of particles
961 # even when some simulations only include a subset.
963 # \b Examples:
964 # \code
965 # bd.set_gamma('A', gamma=2.0)
966 # \endcode
968 def set_gamma(self, a, gamma):
969 util.print_status_line();
970 self.check_initialization();
972 ntypes = globals.system_definition.getParticleData().getNTypes();
973 type_list = [];
974 for i in range(0,ntypes):
975 type_list.append(globals.system_definition.getParticleData().getNameByType(i));
977 # change the parameters
978 for i in range(0,ntypes):
979 if a == type_list[i]:
980 self.cpp_method.setGamma(i,gamma);
983 ## NVE Integration for rigid bodies
985 # integrate.nve_rigid performs constant volume, constant energy simulations on rigid bodies
986 # The integration scheme is implemented from \cite Miller2002 .
988 # Reference \cite Nguyen2011 describes the rigid body implementation details in HOOMD-blue. Cite it
989 # if you utilize rigid body functionality in your work.
991 # integrate.nve_rigid \b only operates on particles that belong to rigid bodies.
993 # integrate.nve_rigid is an integration method. It must be used in concert with an integration mode. It can be used while
994 # the following modes are active:
995 # - integrate.mode_standard
996 # \MPI_NOT_SUPPORTED
997 class nve_rigid(_integration_method):
998 ## Specifies the NVE integration method for rigid bodies
999 # \param group Group of particles on which to apply this method.
1001 # \b Examples:
1002 # \code
1003 # rigid = group.rigid()
1004 # integrate.nve_rigid(group=rigid)
1005 # \endcode
1006 def __init__(self, group):
1007 util.print_status_line();
1009 # Error out in MPI simulations
1010 if (hoomd.is_MPI_available()):
1011 if globals.system_definition.getParticleData().getDomainDecomposition():
1012 globals.msg.error("integrate.nve_rigid not supported in multi-processor simulations.\n\n")
1013 raise RuntimeError("Error setting up integration method.")
1015 # initialize base class
1016 _integration_method.__init__(self);
1018 # initialize the reflected c++ class
1019 if not globals.exec_conf.isCUDAEnabled():
1020 self.cpp_method = hoomd.TwoStepNVERigid(globals.system_definition, group.cpp_group);
1021 else:
1022 self.cpp_method = hoomd.TwoStepNVERigidGPU(globals.system_definition, group.cpp_group);
1024 self.cpp_method.validateGroup()
1026 ## NVT Integration for rigid bodies
1028 # integrate.nvt_rigid performs constant volume, constant temperature simulations of the rigid bodies in the system.
1029 # The integration scheme is implemented from \cite Miller2002 and \cite Kamberaj2005 .
1031 # Reference \cite Nguyen2011 describes the rigid body implementation details in HOOMD-blue. Cite it
1032 # if you utilize rigid body functionality in your work.
1034 # integrate.nvt_rigid \b only operates on particles that belong to rigid bodies.
1036 # integrate.nvt_rigid is an integration method. It must be used in concert with an integration mode. It can be used while
1037 # the following modes are active:
1038 # - integrate.mode_standard
1039 # \MPI_NOT_SUPPORTED
1040 class nvt_rigid(_integration_method):
1041 ## Specifies the NVT integration method for rigid bodies
1042 # \param group Group of particles on which to apply this method.
1043 # \param T Temperature set point for the thermostat (in energy units)
1044 # \param tau Time constant for the thermostat (in time units)
1046 # \a T can be a variant type, allowing for temperature ramps in simulation runs.
1048 # \b Examples:
1049 # \code
1050 # rigid = group.rigid()
1051 # integrate.nvt_rigid(group=all, T=1.0, tau=10.0)
1052 # integrator = integrate.nvt_rigid(group=all, tau=5.0, T=1.0)
1053 # \endcode
1054 def __init__(self, group, T, tau):
1055 util.print_status_line();
1057 # Error out in MPI simulations
1058 if (hoomd.is_MPI_available()):
1059 if globals.system_definition.getParticleData().getDomainDecomposition():
1060 globals.msg.error("integrate.nvt_rigid not supported in multi-processor simulations.\n\n")
1061 raise RuntimeError("Error setting up integration method.")
1063 # initialize base class
1064 _integration_method.__init__(self);
1066 # setup the variant inputs
1067 T = variant._setup_variant_input(T);
1069 # create the compute thermo
1070 thermo = compute._get_unique_thermo(group=group);
1072 # setup suffix
1073 suffix = '_' + group.name;
1075 # initialize the reflected c++ class
1076 if not globals.exec_conf.isCUDAEnabled():
1077 self.cpp_method = hoomd.TwoStepNVTRigid(globals.system_definition, group.cpp_group, thermo.cpp_compute, T.cpp_variant, tau, suffix);
1078 else:
1079 self.cpp_method = hoomd.TwoStepNVTRigidGPU(globals.system_definition, group.cpp_group, thermo.cpp_compute, T.cpp_variant, tau, suffix);
1081 self.cpp_method.validateGroup()
1083 ## Changes parameters of an existing integrator
1084 # \param T New temperature (if set) (in energy units)
1085 # \param tau New coupling constant (if set) (in time units)
1087 # To change the parameters of an existing integrator, you must save it in a variable when it is
1088 # specified, like so:
1089 # \code
1090 # integrator = integrate.nvt_rigid(group=rigid, T=0.65)
1091 # \endcode
1093 # \b Examples:
1094 # \code
1095 # integrator.set_params(T=2.0, tau=10.0)
1096 # \endcode
1097 def set_params(self, T=None, tau=None):
1098 util.print_status_line();
1099 self.check_initialization();
1101 # change the parameters
1102 if T is not None:
1103 # setup the variant inputs
1104 T = variant._setup_variant_input(T);
1105 self.cpp_method.setT(T.cpp_variant);
1106 if tau is not None:
1107 self.cpp_method.setTau(tau);
1109 ## NVT integration via Brownian dynamics for rigid bodies
1111 # integrate.bdnvt_rigid performs constant volume, constant temperature simulation based on a
1112 # NVE simulation with added damping and stochastic heat bath forces. The NVE integration scheme
1113 # is implemented from ref \cite Miller2002.
1115 # Reference \cite Nguyen2011 describes the rigid body implementation details in HOOMD-blue. Cite it
1116 # if you utilize rigid body functionality in your work.
1118 # The total added %force \f$ \vec{F}\f$ <strong>applied to each constiuent particle</strong> is
1119 # \f[ \vec{F} = -\gamma \cdot \vec{v} + \vec{F}_{\mathrm{rand}} \f]
1120 # where \f$ \vec{v} \f$ is the particle's velocity and \f$ \vec{F}_{\mathrm{rand}} \f$
1121 # is a random force with magnitude chosen via the fluctuation-dissipation theorem
1122 # to be consistent with the specified drag (\a gamma) and temperature (\a T).
1124 # integrate.bdnvt_rigid \b only operates on particles that belong to rigid bodies.
1126 # integrate.bdnvt_rigid is an integration method. It must be used in concert with an integration mode. It can be used while
1127 # the following modes are active:
1128 # - integrate.mode_standard
1129 # \MPI_NOT_SUPPORTED
1130 class bdnvt_rigid(_integration_method):
1131 ## Specifies the BD NVT integrator for rigid bodies
1132 # \param group Group of particles on which to apply this method.
1133 # \param T Temperature of the simulation \a T (in energy units)
1134 # \param seed Random seed to use for the run. Simulations that are identical, except for the seed, will follow
1135 # different trajectories.
1136 # \param gamma_diam If True, then then gamma for each particle will be assigned to its diameter. If False (the
1137 # default), gammas are assigned per particle type via set_gamma().
1139 # \a T can be a variant type, allowing for temperature ramps in simulation runs.
1141 # \b Examples:
1142 # \code
1143 # rigid = group.rigid();
1144 # integrate.bdnvt_rigid(group=rigid, T=1.0, seed=5)
1145 # integrator = integrate.bdnvt_rigid(group=all, T=1.0, seed=100)
1146 # integrate.bdnvt_rigid(group=all, T=1.0, gamma_diam=True)
1147 # \endcode
1148 def __init__(self, group, T, seed=0, gamma_diam=False):
1149 util.print_status_line();
1151 # Error out in MPI simulations
1152 if (hoomd.is_MPI_available()):
1153 if globals.system_definition.getParticleData().getDomainDecomposition():
1154 globals.msg.error("integrate.bdnvt_rigid not supported in multi-processor simulations.\n\n")
1155 raise RuntimeError("Error setting up integration method.")
1157 # initialize base class
1158 _integration_method.__init__(self);
1160 # setup the variant inputs
1161 T = variant._setup_variant_input(T);
1163 # initialize the reflected c++ class
1164 if not globals.exec_conf.isCUDAEnabled():
1165 self.cpp_method = hoomd.TwoStepBDNVTRigid(globals.system_definition, group.cpp_group, T.cpp_variant, seed, gamma_diam);
1166 else:
1167 self.cpp_method = hoomd.TwoStepBDNVTRigidGPU(globals.system_definition, group.cpp_group, T.cpp_variant, seed, gamma_diam);
1169 self.cpp_method.validateGroup()
1171 ## Changes parameters of an existing integrator
1172 # \param T New temperature (if set) (in energy units)
1174 # To change the parameters of an existing integrator, you must save it in a variable when it is
1175 # specified, like so:
1176 # \code
1177 # integrator = integrate.bdnvt_rigid(group=rigid, T=1.0)
1178 # \endcode
1180 # \b Examples:
1181 # \code
1182 # integrator.set_params(T=2.0)
1183 # \endcode
1184 def set_params(self, T=None):
1185 util.print_status_line();
1186 self.check_initialization();
1188 # change the parameters
1189 if T is not None:
1190 # setup the variant inputs
1191 T = variant._setup_variant_input(T);
1192 self.cpp_method.setT(T.cpp_variant);
1194 ## Sets gamma parameter for a particle type
1195 # \param a Particle type
1196 # \param gamma \f$ \gamma \f$ for particle type (see below for examples) (in units of force/velocity)
1198 # set_gamma() sets the coefficient \f$ \gamma \f$ for a single particle type, identified
1199 # by name.
1201 # The gamma parameter determines how strongly a particular particle is coupled to
1202 # the stochastic bath. The higher the gamma, the more strongly coupled: see
1203 # integrate.bdnvt_rigid.
1205 # If gamma is not set for any particle type, it will automatically default to 1.0.
1206 # It is not an error to specify gammas for particle types that do not exist in the simulation.
1207 # This can be useful in defining a single simulation script for many different types of particles
1208 # even when some simulations only include a subset.
1210 # \b Examples:
1211 # \code
1212 # bd.set_gamma('A', gamma=2.0)
1213 # \endcode
1215 def set_gamma(self, a, gamma):
1216 util.print_status_line();
1217 self.check_initialization();
1219 ntypes = globals.system_definition.getParticleData().getNTypes();
1220 type_list = [];
1221 for i in range(0,ntypes):
1222 type_list.append(globals.system_definition.getParticleData().getNameByType(i));
1224 # change the parameters
1225 for i in range(0,ntypes):
1226 if a == type_list[i]:
1227 self.cpp_method.setGamma(i,gamma);
1229 ## NPT Integration for rigid bodies
1231 # integrate.npt_rigid performs constant pressure, constant temperature simulations of the rigid bodies in the system.
1232 # The integration scheme is implemented from \cite Miller2002 and \cite Kamberaj2005 .
1234 # Reference \cite Nguyen2011 describes the rigid body implementation details in HOOMD-blue. Cite it
1235 # if you utilize rigid body functionality in your work.
1237 # integrate.npt_rigid \b only operates on particles that belong to rigid bodies.
1239 # integrate.npt_rigid is an integration method. It must be used in concert with an integration mode. It can be used while
1240 # the following modes are active:
1241 # - integrate.mode_standard
1242 # \MPI_NOT_SUPPORTED
1243 class npt_rigid(_integration_method):
1244 ## Specifies the NVT integration method for rigid bodies
1245 # \param group Group of particles on which to apply this method.
1246 # \param tau Time constant for the thermostat (in time units)
1247 # \param tauP Time constatnt for the barostat (in time units)
1248 # \param T Temperature set point for the thermostat (in energy units)
1249 # \param P Pressure set point for the barostat (in pressure units)
1251 # \a T (and P) can be a variant type, allowing for temperature (and pressure) ramps in simulation runs.
1253 # \b Examples:
1254 # \code
1255 # rigid = group.rigid()
1256 # integrate.npt_rigid(group=all, T=1.0, tau=10.0, P=1.0, tauP=1.0)
1258 # \endcode
1259 def __init__(self, group, T, tau, P, tauP):
1260 util.print_status_line();
1262 # Error out in MPI simulations
1263 if (hoomd.is_MPI_available()):
1264 if globals.system_definition.getParticleData().getDomainDecomposition():
1265 globals.msg.error("integrate.npt_rigid not supported in multi-processor simulations.\n\n")
1266 raise RuntimeError("Error setting up integration method.")
1268 # initialize base class
1269 _integration_method.__init__(self);
1271 # setup the variant inputs
1272 T = variant._setup_variant_input(T);
1273 P = variant._setup_variant_input(P);
1275 # create the compute thermo
1276 thermo_group = compute._get_unique_thermo(group=group);
1277 thermo_all = compute._get_unique_thermo(group=globals.group_all);
1279 # initialize the reflected c++ class
1280 if not globals.exec_conf.isCUDAEnabled():
1281 self.cpp_method = hoomd.TwoStepNPTRigid(globals.system_definition, group.cpp_group, thermo_group.cpp_compute, thermo_all.cpp_compute, tau, tauP, T.cpp_variant, P.cpp_variant);
1282 else:
1283 self.cpp_method = hoomd.TwoStepNPTRigidGPU(globals.system_definition, group.cpp_group, thermo_group.cpp_compute, thermo_all.cpp_compute, tau, tauP, T.cpp_variant, P.cpp_variant);
1285 self.cpp_method.validateGroup()
1287 ## Changes parameters of an existing integrator
1288 # \param T New temperature (if set) (in energy units)
1289 # \param tau New coupling constant (if set) (in time units)
1290 # \param P New pressure (if set) (in pressure units)
1291 # \param tauP New coupling constant (if set) (in time units)
1293 # To change the parameters of an existing integrator, you must save it in a variable when it is
1294 # specified, like so:
1295 # \code
1296 # integrator = integrate.npt_rigid(group=rigid, T=0.65, P=1.0)
1297 # \endcode
1299 # \b Examples:
1300 # \code
1301 # integrator.set_params(T=2.0, tau=10.0, P=1.5)
1302 # \endcode
1303 def set_params(self, T=None, tau=None, P=None, tauP=None):
1304 util.print_status_line();
1305 self.check_initialization();
1307 # change the parameters
1308 if T is not None:
1309 # setup the variant inputs
1310 T = variant._setup_variant_input(T);
1311 self.cpp_method.setT(T.cpp_variant);
1312 if tau is not None:
1313 self.cpp_method.setTau(tau);
1314 if P is not None:
1315 # setup the variant inputs
1316 P = variant._setup_variant_input(P);
1317 self.cpp_method.setP(P.cpp_variant);
1318 if tauP is not None:
1319 self.cpp_method.setTauP(tauP);
1321 ## NPH Integration for rigid bodies
1323 # integrate.nph_rigid performs constant pressure, constant enthalpy simulations of the rigid bodies in the system.
1324 # The integration scheme is implemented from \cite Miller2002 and \cite Kamberaj2005 .
1326 # Reference \cite Nguyen2011 describes the rigid body implementation details in HOOMD-blue. Cite it
1327 # if you utilize rigid body functionality in your work.
1329 # integrate.nph_rigid \b only operates on particles that belong to rigid bodies.
1331 # integrate.nph_rigid is an integration method. It must be used in concert with an integration mode. It can be used while
1332 # the following modes are active:
1333 # - integrate.mode_standard
1334 # \MPI_NOT_SUPPORTED
1335 class nph_rigid(_integration_method):
1336 ## Specifies the NPH integration method for rigid bodies
1337 # \param group Group of particles on which to apply this method.
1338 # \param tauP Time constatnt for the barostat (in time units)
1339 # \param P Pressure set point for the barostat (in pressure units)
1341 # \a P can be a variant type, allowing for pressure ramping in simulation runs.
1343 # \b Examples:
1344 # \code
1345 # rigid = group.rigid()
1346 # integrate.nph_rigid(group=all, P=1.0, tauP=1.0)
1348 # \endcode
1349 def __init__(self, group, P, tauP):
1350 util.print_status_line();
1352 # Error out in MPI simulations
1353 if (hoomd.is_MPI_available()):
1354 if globals.system_definition.getParticleData().getDomainDecomposition():
1355 globals.msg.error("integrate.nph_rigid is not supported in multi-processor simulations.\n\n")
1356 raise RuntimeError("Error setting up integration method.")
1358 # initialize base class
1359 _integration_method.__init__(self);
1361 # setup the variant inputs
1362 P = variant._setup_variant_input(P);
1364 # create the compute thermo
1365 thermo_group = compute._get_unique_thermo(group=group);
1366 thermo_all = compute._get_unique_thermo(group=globals.group_all);
1368 # initialize the reflected c++ class
1369 if not globals.exec_conf.isCUDAEnabled():
1370 self.cpp_method = hoomd.TwoStepNPHRigid(globals.system_definition, group.cpp_group, thermo_group.cpp_compute, thermo_all.cpp_compute, tauP, P.cpp_variant);
1371 else:
1372 self.cpp_method = hoomd.TwoStepNPHRigidGPU(globals.system_definition, group.cpp_group, thermo_group.cpp_compute, thermo_all.cpp_compute, tauP, P.cpp_variant);
1374 self.cpp_method.validateGroup()
1376 ## Changes parameters of an existing integrator
1377 # \param P New pressure (if set) (in pressure units)
1378 # \param tauP New coupling constant (if set) (in time units)
1380 # To change the parameters of an existing integrator, you must save it in a variable when it is
1381 # specified, like so:
1382 # \code
1383 # integrator = integrate.nph_rigid(group=rigid, P=1.0)
1384 # \endcode
1386 # \b Examples:
1387 # \code
1388 # integrator.set_params(P=1.5, tauP=1.0)
1389 # \endcode
1390 def set_params(self, P=None, tauP=None):
1391 util.print_status_line();
1392 self.check_initialization();
1394 # change the parameters
1395 if P is not None:
1396 # setup the variant inputs
1397 P = variant._setup_variant_input(P);
1398 self.cpp_method.setP(P.cpp_variant);
1399 if tauP is not None:
1400 self.cpp_method.setTauP(tauP);
1402 ## Energy Minimizer (FIRE)
1404 # integrate.mode_minimize_fire uses the Fast Inertial Relaxation Engine (FIRE) algorithm to minimize the energy
1405 # for a group of particles while keeping all other particles fixed. This method is published in
1406 # Bitzek, et al, PRL, 2006.
1408 # At each time step,\f$\Delta t \f$, the algorithm uses the NVE Integrator to generate a x, v, and F, and then adjusts
1409 # v according to \f[ \vec{v} = (1-\alpha)\vec{v} + \alpha \hat{F}|\vec{v}| \f] where \f$ \alpha \f$ and \f$\Delta t \f$
1410 # are dynamically adaptive quantities. While a current search has been lowering the energy of system for more than
1411 # \f$N_{min}\f$ steps, \f$ \alpha \f$ is decreased by \f$ \alpha \rightarrow \alpha f_{alpha} \f$ and
1412 # \f$\Delta t \f$ is increased by \f$ \Delta t \rightarrow max(\Delta t * f_{inc}, \Delta t_{max}) \f$.
1413 # If the energy of the system increases (or stays the same), the velocity of the particles is set to 0,
1414 # \f$ \alpha \rightarrow \alpha_{start}\f$ and
1415 # \f$ \Delta t \rightarrow \Delta t * f_{dec} \f$. Convergence is determined by both the force per particle or the
1416 # change in energy per particle dropping below \a ftol and \a Etol, respectively or,
1418 # \f[ \frac{\sum |F|}{N*\sqrt{N_{dof}}} <ftol \;\; and \;\; \Delta \frac{\sum |E|}{N} < Etol \f]
1419 # where N is the number of particles the minimization is acting over (i.e. the group size). Either of the two criterion can be effectively turned off by setting the tolerance to a large number.
1421 # If the minimization is acted over a subset of all the particles in the system, the "other" particles will be kept
1422 # frozen but will still interact with the particles being moved.
1424 # \b Example:
1425 # \code
1426 # fire=integrate.mode_minimize_fire( group=group.all(), dt=0.05, ftol=1e-2, Etol=1e-7)
1427 # while not(fire.has_converged()):
1428 # xml = dump.xml(filename="dump",period=1)
1429 # run(100)
1430 # \endcode
1432 # \note As a default setting, the algorithm will start with a \f$ \Delta t = \frac{1}{10} \Delta t_{max} \f$ and
1433 # attempts at least 10 search steps. In practice, it was found that this prevents the simulation from making too
1434 # aggressive a first step, but also from quitting before having found a good search direction. The minimum number of
1435 # attempts can be set by the user.
1437 # \warning All other integration methods must be disabled before using the FIRE energy minimizer.
1438 # \MPI_NOT_SUPPORTED
1439 class mode_minimize_fire(_integrator):
1440 ## Specifies the FIRE energy minimizer.
1441 # \param group Particle group to be applied FIRE
1442 # \param group Group of particles on which to apply this method.
1443 # \param dt This is the maximum step size the minimizer is permitted to use. Consider the stability of the system when setting. (in time units)
1444 # \param Nmin Number of steps energy change is negative before allowing \f$ \alpha \f$ and \f$ \Delta t \f$ to adapt.
1445 # - <i>optional</i>: defaults to 5
1446 # \param finc Factor to increase \f$ \Delta t \f$ by
1447 # - <i>optional</i>: defaults to 1.1
1448 # \param fdec Factor to decrease \f$ \Delta t \f$ by
1449 # - <i>optional</i>: defaults to 0.5
1450 # \param alpha_start Initial (and maximum) \f$ \alpha \f$
1451 # - <i>optional</i>: defaults to 0.1
1452 # \param falpha Factor to decrease \f$ \alpha t \f$ by
1453 # - <i>optional</i>: defaults to 0.99
1454 # \param ftol force convergence criteria (in force units)
1455 # - <i>optional</i>: defaults to 1e-1
1456 # \param Etol energy convergence criteria (in energy units)
1457 # - <i>optional</i>: defaults to 1e-5
1458 # \param min_steps A minimum number of attempts before convergence criteria are considered
1459 # - <i>optional</i>: defaults to 10
1460 def __init__(self, group, dt, Nmin=None, finc=None, fdec=None, alpha_start=None, falpha=None, ftol = None, Etol= None, min_steps=None):
1461 util.print_status_line();
1463 # Error out in MPI simulations
1464 if (hoomd.is_MPI_available()):
1465 if globals.system_definition.getParticleData().getDomainDecomposition():
1466 globals.msg.error("mode_minimize_fire is not supported in multi-processor simulations.\n\n")
1467 raise RuntimeError("Error setting up integration mode.")
1469 # initialize base class
1470 _integrator.__init__(self);
1472 # initialize the reflected c++ class
1473 if not globals.exec_conf.isCUDAEnabled():
1474 self.cpp_integrator = hoomd.FIREEnergyMinimizer(globals.system_definition, group.cpp_group, dt);
1475 else:
1476 self.cpp_integrator = hoomd.FIREEnergyMinimizerGPU(globals.system_definition, group.cpp_group, dt);
1478 self.supports_methods = False;
1480 globals.system.setIntegrator(self.cpp_integrator);
1482 # change the set parameters if not None
1483 if not(Nmin is None):
1484 self.cpp_integrator.setNmin(Nmin);
1485 if not(finc is None):
1486 self.cpp_integrator.setFinc(finc);
1487 if not(fdec is None):
1488 self.cpp_integrator.setFdec(fdec);
1489 if not(alpha_start is None):
1490 self.cpp_integrator.setAlphaStart(alpha_start);
1491 if not(falpha is None):
1492 self.cpp_integrator.setFalpha(falpha);
1493 if not(ftol is None):
1494 self.cpp_integrator.setFtol(ftol);
1495 if not(Etol is None):
1496 self.cpp_integrator.setEtol(Etol);
1497 if not(min_steps is None):
1498 self.cpp_integrator.setMinSteps(min_steps);
1500 ## Asks if Energy Minimizer has converged
1502 def has_converged(self):
1503 self.check_initialization();
1504 return self.cpp_integrator.hasConverged()
1506 ## Energy Minimizer RIGID (FIRE)
1508 # integrate.energyminimizer_FIRE uses the Fast Inertial Relaxation Engine (FIRE) algorithm to minimize the energy
1509 # for a group of particles while keeping all other particles fixed.
1511 # For the time being, energy minimization will be handled separately for rigid and non-rigid bodies
1513 # \MPI_NOT_SUPPORTED
1514 class mode_minimize_rigid_fire(_integrator):
1515 ## Specifies the FIRE energy minimizer.
1517 # \param group Group of particles in rigid bodies
1518 # \param dt This is the maximum timestep the minimizer is permitted to use. Consider the stability of the system when setting. (in time units)
1519 # \param Nmin Number of steps energy change is negative before allowing \f$ \alpha \f$ and \f$ \Delta t \f$ to adapt.
1520 # - <i>optional</i>: defaults to 5
1521 # \param finc Factor to increase \f$ \Delta t \f$ by
1522 # - <i>optional</i>: defaults to 1.1
1523 # \param fdec Factor to decrease \f$ \Delta t \f$ by
1524 # - <i>optional</i>: defaults to 0.5
1525 # \param alpha_start Initial (and maximum) \f$ \alpha \f$
1526 # - <i>optional</i>: defaults to 0.1
1527 # \param falpha Factor to decrease \f$ \alpha t \f$ by
1528 # - <i>optional</i>: defaults to 0.99
1529 # \param ftol force convergence criteria
1530 # - <i>optional</i>: defaults to 1e-1
1531 # \param wtol torque convergence criteria
1532 # - <i>optional</i>: defaults to 1e-1
1533 # \param Etol energy convergence criteria
1534 # - <i>optional</i>: defaults to 1e-5
1535 def __init__(self, group, dt, Nmin=None, finc=None, fdec=None, alpha_start=None, falpha=None, ftol = None, wtol=None, Etol= None):
1536 util.print_status_line();
1538 # initialize base class
1539 _integrator.__init__(self);
1541 # initialize the reflected c++ class
1542 if not globals.exec_conf.isCUDAEnabled():
1543 self.cpp_integrator = hoomd.FIREEnergyMinimizerRigid(globals.system_definition, group.cpp_group, dt);
1544 else:
1545 self.cpp_integrator = hoomd.FIREEnergyMinimizerRigidGPU(globals.system_definition, group.cpp_group, dt);
1547 self.supports_methods = False;
1549 globals.system.setIntegrator(self.cpp_integrator);
1551 # change the set parameters if not None
1552 if not(Nmin is None):
1553 self.cpp_integrator.setNmin(Nmin);
1554 if not(finc is None):
1555 self.cpp_integrator.setFinc(finc);
1556 if not(fdec is None):
1557 self.cpp_integrator.setFdec(fdec);
1558 if not(alpha_start is None):
1559 self.cpp_integrator.setAlphaStart(alpha_start);
1560 if not(falpha is None):
1561 self.cpp_integrator.setFalpha(falpha);
1562 if not(ftol is None):
1563 self.cpp_integrator.setFtol(ftol);
1564 if not(wtol is None):
1565 self.cpp_integrator.setWtol(wtol);
1566 if not(Etol is None):
1567 self.cpp_integrator.setEtol(Etol);
1569 ## Asks if Energy Minimizer has converged
1571 def has_converged(self):
1572 self.check_initialization();
1573 return self.cpp_integrator.hasConverged()
1575 ## Applies the Berendsen thermostat.
1577 # integrate.berendsen rescales the velocities of all particles on each time step. The rescaling is performed so that
1578 # the difference in the current temperature from the set point decays exponentially \cite Berendsen1984
1579 # \f[
1580 # \frac{dT_\mathrm{cur}}{dt} = \frac{T - T_\mathrm{cur}}{\tau}
1581 # \f]
1583 # \MPI_NOT_SUPPORTED
1584 class berendsen(_integration_method):
1585 ## Initialize the Berendsen thermostat.
1586 # \param group Group to which the Berendsen thermostat will be applied.
1587 # \param T Temperature of thermostat. (in energy units)
1588 # \param tau Time constant of thermostat. (in time units)
1590 def __init__(self, group, T, tau):
1591 util.print_status_line();
1593 # Error out in MPI simulations
1594 if (hoomd.is_MPI_available()):
1595 if globals.system_definition.getParticleData().getDomainDecomposition():
1596 globals.msg.error("integrate.berendsen is not supported in multi-processor simulations.\n\n")
1597 raise RuntimeError("Error setting up integration method.")
1599 # initialize base class
1600 _integration_method.__init__(self);
1602 # setup the variant inputs
1603 T = variant._setup_variant_input(T);
1605 # create the compute thermo
1606 thermo = compute._get_unique_thermo(group = group);
1608 # initialize the reflected c++ class
1609 if not globals.exec_conf.isCUDAEnabled():
1610 self.cpp_method = hoomd.TwoStepBerendsen(globals.system_definition,
1611 group.cpp_group,
1612 thermo.cpp_compute,
1613 tau,
1614 T.cpp_variant);
1615 else:
1616 self.cpp_method = hoomd.TwoStepBerendsenGPU(globals.system_definition,
1617 group.cpp_group,
1618 thermo.cpp_compute,
1619 tau,
1620 T.cpp_variant);