Update MTK documentation
[hoomd-blue.git] / python-module / hoomd_script / update.py
blobc4d6d6fa9814961df371752d1dd532a6cd3d72e1
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 import hoomd;
53 from hoomd_script import globals;
54 from hoomd_script import compute;
55 from hoomd_script import util;
56 from hoomd_script import variant;
57 import sys;
58 from hoomd_script import init;
60 ## \package hoomd_script.update
61 # \brief Commands that modify the system state in some way
63 # When an updater is specified, it acts on the particle system each time step to change
64 # it in some way. See the documentation of specific updaters to find out what they do.
66 ## \internal
67 # \brief Base class for updaters
69 # An updater in hoomd_script reflects an Updater in c++. It is responsible
70 # for all high-level management that happens behind the scenes for hoomd_script
71 # writers. 1) The instance of the c++ updater itself is tracked and added to the
72 # System 2) methods are provided for disabling the updater and changing the
73 # period which the system calls it
74 class _updater:
75 ## \internal
76 # \brief Constructs the updater
78 # Initializes the cpp_updater to None.
79 # Assigns a name to the updater in updater_name;
80 def __init__(self):
81 # check if initialization has occurred
82 if not init.is_initialized():
83 globals.msg.error("Cannot create updater before initialization\n");
84 raise RuntimeError('Error creating updater');
86 self.cpp_updater = None;
88 # increment the id counter
89 id = _updater.cur_id;
90 _updater.cur_id += 1;
92 self.updater_name = "updater%d" % (id);
93 self.enabled = True;
95 ## \internal
97 # \brief Helper function to setup updater period
99 # \param period An integer or callable function period
101 # If an integer is specified, then that is set as the period for the analyzer.
102 # If a callable is passed in as a period, then a default period of 1000 is set
103 # to the integer period and the variable period is enabled
105 def setupUpdater(self, period):
106 if type(period) == type(1.0):
107 period = int(period);
109 if type(period) == type(1):
110 globals.system.addUpdater(self.cpp_updater, self.updater_name, period);
111 elif type(period) == type(lambda n: n*2):
112 globals.system.addUpdater(self.cpp_updater, self.updater_name, 1000);
113 globals.system.setUpdaterPeriodVariable(self.updater_name, period);
114 else:
115 globals.msg.error("I don't know what to do with a period of type " + str(type(period)) + "expecting an int or a function\n");
116 raise RuntimeError('Error creating updater');
118 ## \var enabled
119 # \internal
120 # \brief True if the updater is enabled
122 ## \var cpp_updater
123 # \internal
124 # \brief Stores the C++ side Updater managed by this class
126 ## \var updater_name
127 # \internal
128 # \brief The Updater's name as it is assigned to the System
130 ## \var prev_period
131 # \internal
132 # \brief Saved period retrieved when an updater is disabled: used to set the period when re-enabled
134 ## \internal
135 # \brief Checks that proper initialization has completed
136 def check_initialization(self):
137 # check that we have been initialized properly
138 if self.cpp_updater is None:
139 globals.msg.error('Bug in hoomd_script: cpp_updater not set, please report\n');
140 raise RuntimeError();
142 ## Disables the updater
144 # \b Examples:
145 # \code
146 # updater.disable()
147 # \endcode
149 # Executing the disable command will remove the updater from the system.
150 # Any run() command executed after disabling an updater will not use that
151 # updater during the simulation. A disabled updater can be re-enabled
152 # with enable()
154 # To use this command, you must have saved the updater in a variable, as
155 # shown in this example:
156 # \code
157 # updater = update.some_updater()
158 # # ... later in the script
159 # updater.disable()
160 # \endcode
161 def disable(self):
162 util.print_status_line();
163 self.check_initialization();
165 # check if we are already disabled
166 if not self.enabled:
167 globals.msg.warning("Ignoring command to disable an updater that is already disabled");
168 return;
170 self.prev_period = globals.system.getUpdaterPeriod(self.updater_name);
171 globals.system.removeUpdater(self.updater_name);
172 self.enabled = False;
174 ## Enables the updater
176 # \b Examples:
177 # \code
178 # updater.enable()
179 # \endcode
181 # See disable() for a detailed description.
182 def enable(self):
183 util.print_status_line();
184 self.check_initialization();
186 # check if we are already disabled
187 if self.enabled:
188 globals.msg.warning("Ignoring command to enable an updater that is already enabled");
189 return;
191 globals.system.addUpdater(self.cpp_updater, self.updater_name, self.prev_period);
192 self.enabled = True;
194 ## Changes the period between updater executions
196 # \param period New period to set
198 # \b Examples:
199 # \code
200 # updater.set_period(100);
201 # updater.set_period(1);
202 # \endcode
204 # While the simulation is \ref run() "running", the action of each updater
205 # is executed every \a period time steps.
207 # To use this command, you must have saved the updater in a variable, as
208 # shown in this example:
209 # \code
210 # updater = update.some_updater()
211 # # ... later in the script
212 # updater.set_period(10)
213 # \endcode
214 def set_period(self, period):
215 util.print_status_line();
217 if type(period) == type(1.0):
218 period = int(period);
220 if type(period) == type(1):
221 if self.enabled:
222 globals.system.setUpdaterPeriod(self.updater_name, period);
223 else:
224 self.prev_period = period;
225 elif type(period) == type(lambda n: n*2):
226 globals.msg.warning("A period cannot be changed to a variable one");
227 else:
228 globals.msg.warning("I don't know what to do with a period of type " + str(type(period)) + " expecting an int or a function");
230 # **************************************************************************
232 ## Sorts particles in memory to improve cache coherency
234 # Every \a period time steps, particles are reordered in memory based on
235 # a Hilbert curve. This operation is very efficient, and the reordered particles
236 # significantly improve performance of all other algorithmic steps in HOOMD.
238 # The reordering is accomplished by placing particles in spatial bins. A Hilbert curve is generated that traverses
239 # these bins and particles are reordered in memory in the same order in which
240 # they fall on the curve. The grid dimension used over the course of the simulation is held constant, and the default
241 # is chosen to be as fine as possible without utilizing too much memory. The dimension can be changed with set_params(),
242 # just be aware that the value chosen will be rounded up to the next power of 2 and that the amount of memory usage for
243 # 3D simulations grows very quickly:
244 # - \a grid=128 uses 8 MB
245 # - \a grid=256 uses 64 MB
246 # - \a grid=512 uses 512 MB
247 # - \a grid=1024 uses 4096 MB
249 # 2D simulations do not use any additional memory and default to \a grid=4096
251 # Because all simulations benefit from this process, a sorter is created by
252 # default. If you have reason to disable it or modify parameters, you
253 # can use the built-in variable \c sorter to do so after initialization. The
254 # following code example disables the sorter. The init.create_random command
255 # is just an example; sorter can be modified after any command that initializes
256 # the system.
257 # \code
258 # init.create_random(N=1000, phi_p=0.2)
259 # sorter.disable()
260 # \endcode
261 class sort(_updater):
262 ## Initialize the sorter
264 # Users should not initialize the sorter directly. One in created for you
265 # when any initialization command from init is run.
266 # The created sorter can be accessed via the built-in variable \c sorter.
268 # By default, the sorter is created with a \a grid of 256 (4096 in 2D) and
269 # an update period of 300 time steps (100 if running on the CPU).
270 # The period can be changed with set_period() and the grid width can be
271 # changed with set_params()
272 def __init__(self):
273 # initialize base class
274 _updater.__init__(self);
276 # create the c++ mirror class
277 if not globals.exec_conf.isCUDAEnabled():
278 self.cpp_updater = hoomd.SFCPackUpdater(globals.system_definition);
279 else:
280 self.cpp_updater = hoomd.SFCPackUpdaterGPU(globals.system_definition);
282 default_period = 300;
283 # change default period to 100 on the CPU
284 if not globals.exec_conf.isCUDAEnabled():
285 default_period = 100;
287 self.setupUpdater(default_period);
289 ## Change sorter parameters
291 # \param grid New grid dimension (if set)
293 # \b Examples:
294 # \code
295 # sorter.set_params(grid=128)
296 # \endcode
297 def set_params(self, grid=None):
298 util.print_status_line();
299 self.check_initialization();
301 if grid is not None:
302 self.cpp_updater.setGrid(grid);
305 ## Rescales particle velocities
307 # Every \a period time steps, particle velocities are rescaled by equal factors
308 # so that they are consistent with a given temperature in the equipartition theorem
309 # \f$\langle 1/2 m v^2 \rangle = k_B T \f$.
311 # update.rescale_temp is best coupled with the \ref integrate.nve "NVE" integrator.
312 # \MPI_SUPPORTED
313 class rescale_temp(_updater):
314 ## Initialize the rescaler
316 # \param T Temperature set point (in energy units)
317 # \param period Velocities will be rescaled every \a period time steps
319 # \a T can be a variant type, allowing for temperature ramps in simulation runs.
321 # \b Examples:
322 # \code
323 # update.rescale_temp(T=1.2)
324 # rescaler = update.rescale_temp(T=0.5)
325 # update.rescale_temp(period=100, T=1.03)
326 # update.rescale_temp(period=100, T=variant.linear_interp([(0, 4.0), (1e6, 1.0)]))
327 # \endcode
329 # \a period can be a function: see \ref variable_period_docs for details
330 def __init__(self, T, period=1):
331 util.print_status_line();
333 # initialize base class
334 _updater.__init__(self);
336 # setup the variant inputs
337 T = variant._setup_variant_input(T);
339 # create the compute thermo
340 thermo = compute._get_unique_thermo(group=globals.group_all);
342 # create the c++ mirror class
343 self.cpp_updater = hoomd.TempRescaleUpdater(globals.system_definition, thermo.cpp_compute, T.cpp_variant);
344 self.setupUpdater(period);
346 ## Change rescale_temp parameters
348 # \param T New temperature set point (in energy units)
350 # To change the parameters of an existing updater, you must have saved it when it was specified.
351 # \code
352 # rescaler = update.rescale_temp(T=0.5)
353 # \endcode
355 # \b Examples:
356 # \code
357 # rescaler.set_params(T=2.0)
358 # \endcode
359 def set_params(self, T=None):
360 util.print_status_line();
361 self.check_initialization();
363 if T is not None:
364 T = variant._setup_variant_input(T);
365 self.cpp_updater.setT(T.cpp_variant);
367 ## Zeroes system momentum
369 # Every \a period time steps, particle velocities are modified such that the total linear
370 # momentum of the system is set to zero.
372 # update.zero_momentum is intended to be used when the \ref integrate.nve "NVE" integrator has the
373 # \a limit option specified, where Newton's third law is broken and systems could gain momentum.
374 # Of course, it can be used in any script.
376 # \MPI_SUPPORTED
377 class zero_momentum(_updater):
378 ## Initialize the momentum zeroer
380 # \param period Momentum will be zeroed every \a period time steps
382 # \b Examples:
383 # \code
384 # update.zero_momentum()
385 # zeroer= update.zero_momentum(period=10)
386 # \endcode
388 # \a period can be a function: see \ref variable_period_docs for details
389 def __init__(self, period=1):
390 util.print_status_line();
392 # initialize base class
393 _updater.__init__(self);
395 # create the c++ mirror class
396 self.cpp_updater = hoomd.ZeroMomentumUpdater(globals.system_definition);
397 self.setupUpdater(period);
399 ## Enforces 2D simulation
401 # Every time step, particle velocities and accelerations are modified so that their z components are 0: forcing
402 # 2D simulations when other calculations may cause particles to drift out of the plane.
404 # Using enforce2d is only allowed when the system is specified as having only 2 dimensions. This specification can
405 # be made in the xml file read by init.read_xml() or set dynamically via the particle data access routines. Setting
406 # the number of dimensions to 2 also changes the degrees of freedom calculation for temperature calculations and forces
407 # the neighbor list to only find 2D neighbors. Doing so requires that a small, but non-zero, value be set for the z
408 # dimension of the simulation box.
410 # \MPI_SUPPORTED
411 class enforce2d(_updater):
412 ## Initialize the 2D enforcement
414 # \b Examples:
415 # \code
416 # update.enforce2d()
417 # \endcode
419 def __init__(self):
420 util.print_status_line();
421 period = 1;
423 # initialize base class
424 _updater.__init__(self);
426 # create the c++ mirror class
427 if not globals.exec_conf.isCUDAEnabled():
428 self.cpp_updater = hoomd.Enforce2DUpdater(globals.system_definition);
429 else:
430 self.cpp_updater = hoomd.Enforce2DUpdaterGPU(globals.system_definition);
431 self.setupUpdater(period);
433 ## Rescales the system box size
435 # Every \a period time steps, the system box dimensions is updated to values given by
436 # the user (in a variant). As an option, the particles can either be left in place
437 # as the box is changed or their positions can be scaled with the box.
439 # \MPI_SUPPORTED
440 class box_resize(_updater):
441 ## Initialize box size resize updater
443 # \param L (if set) box length in the x,y, and z directions as a function of time (in distance units)
444 # \param Lx (if set) box length in the x direction as a function of time (in distance units)
445 # \param Ly (if set) box length in the y direction as a function of time (in distance units)
446 # \param Lz (if set) box length in the z direction as a function of time (in distance units)
447 # \param xy (if set) X-Y tilt factor as a function of time (dimensionless)
448 # \param xz (if set) X-Z tilt factor as a function of time (dimensionless)
449 # \param yz (if set) Y-Z tilt factor as a function of time (dimensionless)
450 # \param period The box size will be updated every \a period time steps
452 # \a L, Lx, \a Ly, \a Lz, \a xy, \a xz, \a yz can either be set to a constant number or a variant may be provided.
453 # if any of the box parameters are not specified, they are set to maintain the same value in the current box.
455 # Use \a L as a shorthand to specify Lx, Ly, and Lz to the same value.
457 # By default, particle positions are rescaled with the box. To change this behavior,
458 # use set_params().
460 # If, under rescaling, tilt factors get too large, the simulation may slow down due to too many ghost atoms
461 # being communicated. update.box.resize does NOT reset the box to orthorhombic shape if this occurs (and does not
462 # move the next periodic image into the primary cell).
464 # \b Examples:
465 # \code
466 # update.box_resize(L = variant.linear_interp([(0, 20), (1e6, 50)]))
467 # box_resize = update.box_resize(L = variant.linear_interp([(0, 20), (1e6, 50)]), period = 10)
468 # update.box_resize(Lx = variant.linear_interp([(0, 20), (1e6, 50)]),
469 # Ly = variant.linear_interp([(0, 20), (1e6, 60)]),
470 # Lz = variant.linear_interp([(0, 10), (1e6, 80)]))
471 # update.box_resize(Lx = variant.linear_interp([(0, 20), (1e6, 50)]), Ly = 10, Lz = 10)
473 # # Shear the box in the xy plane using Lees-Edwards boundary conditions
474 # update.box_resize(xy = variant.linear_interp([(0,0), (1e6, 1)]))
475 # \endcode
477 # \a period can be a function: see \ref variable_period_docs for details
479 # If \a period is set to None, then the given box lengths are applied immediately and periodic updates
480 # are not performed.
482 def __init__(self, Lx = None, Ly = None, Lz = None, xy = None, xz = None, yz = None, period = 1, L = None):
483 util.print_status_line();
485 # initialize base class
486 _updater.__init__(self);
488 if L is not None:
489 Lx = L;
490 Ly = L;
491 Lz = L;
493 if Lx is None and Ly is None and Lz is None and xy is None and xz is None and yz is None:
494 globals.msg.warning("update.box_resize: Ignoring request to setup updater without parameters\n")
495 return
498 box = globals.system_definition.getParticleData().getGlobalBox();
499 # setup arguments
500 if Lx is None:
501 Lx = box.getL().x;
502 if Ly is None:
503 Ly = box.getL().y;
504 if Lz is None:
505 Lz = box.getL().z;
507 if xy is None:
508 xy = box.getTiltFactorXY();
509 if xz is None:
510 xz = box.getTiltFactorXZ();
511 if yz is None:
512 yz = box.getTiltFactorYZ();
514 Lx = variant._setup_variant_input(Lx);
515 Ly = variant._setup_variant_input(Ly);
516 Lz = variant._setup_variant_input(Lz);
518 xy = variant._setup_variant_input(xy);
519 xz = variant._setup_variant_input(xz);
520 yz = variant._setup_variant_input(yz);
522 # create the c++ mirror class
523 self.cpp_updater = hoomd.BoxResizeUpdater(globals.system_definition, Lx.cpp_variant, Ly.cpp_variant, Lz.cpp_variant,
524 xy.cpp_variant, xz.cpp_variant, yz.cpp_variant);
525 if period is None:
526 self.cpp_updater.update(globals.system.getCurrentTimeStep());
527 else:
528 self.setupUpdater(period);
530 ## Change box_resize parameters
532 # \param scale_particles Set to True to scale particles with the box. Set to False
533 # to have particles remain in place when the box is scaled.
535 # To change the parameters of an existing updater, you must have saved it when it was specified.
536 # \code
537 # box_resize = update.box_resize(Lx = variant.linear_interp([(0, 20), (1e6, 50)]), period = 10)
538 # \endcode
540 # \b Examples:
541 # \code
542 # box_resize.set_params(scale_particles = False)
543 # box_resize.set_params(scale_particles = True)
544 # \endcode
545 def set_params(self, scale_particles=None):
546 util.print_status_line();
547 self.check_initialization();
549 if scale_particles is not None:
550 self.cpp_updater.setParams(scale_particles);
552 # Global current id counter to assign updaters unique names
553 _updater.cur_id = 0;