Example #1
0
    def __init__(self, filter, kT, tau):
        # store metadata
        param_dict = ParameterDict(filter=ParticleFilter,
                                   kT=Variant,
                                   tau=float(tau))
        param_dict.update(dict(filter=filter, kT=kT))

        # set defaults
        self._param_dict.update(param_dict)
Example #2
0
 def __init__(self, test_particle_type, num_samples):
     # store metadata
     param_dict = ParameterDict(
         test_particle_type=str,
         num_samples=int
     )
     param_dict.update(
         dict(test_particle_type=test_particle_type,
              num_samples=num_samples))
     self._param_dict.update(param_dict)
Example #3
0
    def __init__(self, filter, limit=None):

        # store metadata
        param_dict = ParameterDict(
            filter=ParticleFilter,
            limit=OnlyType(float, allow_none=True),
            zero_force=OnlyType(bool, allow_none=False),
        )
        param_dict.update(dict(filter=filter, limit=limit, zero_force=False))

        # set defaults
        self._param_dict.update(param_dict)
Example #4
0
    def __init__(self, filter, manifold_constraint, tolerance=0.000001):

        # store metadata
        param_dict = ParameterDict(
            filter=ParticleFilter,
            zero_force=OnlyTypes(bool, allow_none=False),
        )
        param_dict.update(dict(filter=filter, zero_force=False))

        # set defaults
        self._param_dict.update(param_dict)

        super().__init__(manifold_constraint, tolerance)
Example #5
0
    def __init__(self, filter, kT, tau):

        # store metadata
        param_dict = ParameterDict(filter=ParticleFilter,
                                   kT=Variant,
                                   tau=float(tau),
                                   translational_thermostat_dof=(float, float),
                                   rotational_thermostat_dof=(float, float))
        param_dict.update(
            dict(kT=kT,
                 filter=filter,
                 translational_thermostat_dof=(0, 0),
                 rotational_thermostat_dof=(0, 0)))
        # set defaults
        self._param_dict.update(param_dict)
Example #6
0
 def __getstate__(self):
     state = copy.copy(self.__dict__)
     state.pop('_comm', None)
     # This is to handle when the output specified is just stdout. By default
     # file objects like this are not picklable, so we need to handle it
     # differently. We let `None` represent stdout in the state dictionary.
     # Most other file like objects will simply fail to be pickled here.
     if self.output == stdout:
         param_dict = ParameterDict()
         param_dict.update(state['_param_dict'])
         state['_param_dict'] = param_dict
         del state['_param_dict']['output']
         state['_param_dict']['output'] = None
         return state
     else:
         return super().__getstate__()
Example #7
0
    def __init__(self,
                 logger,
                 output=stdout,
                 header_sep='.',
                 delimiter=' ',
                 pretty=True,
                 max_precision=10,
                 max_header_len=None):
        def writable(fh):
            if not fh.writable():
                raise ValueError("file-like object must be writable.")
            return fh

        param_dict = ParameterDict(header_sep=str,
                                   delimiter=str,
                                   min_column_width=int,
                                   max_header_len=OnlyTypes(int,
                                                            allow_none=True),
                                   pretty=bool,
                                   max_precision=int,
                                   output=OnlyTypes(_OutputWriter,
                                                    postprocess=writable),
                                   logger=Logger)

        param_dict.update(
            dict(header_sep=header_sep,
                 delimiter=delimiter,
                 min_column_width=max(10, max_precision + 6),
                 max_header_len=max_header_len,
                 max_precision=max_precision,
                 pretty=pretty,
                 output=output,
                 logger=logger))
        self._param_dict = param_dict

        # internal variables that are not part of the state.
        # Ensure that only scalar and potentially string are set for the logger
        if (LoggerCategories.scalar not in logger.categories
                or logger.categories & self._invalid_logger_categories !=
                LoggerCategories.NONE):
            raise ValueError(
                "Given Logger must have the scalar categories set.")

        self._cur_headers_with_width = dict()
        self._fmt = _Formatter(pretty, max_precision)
        self._comm = None
Example #8
0
    def __init__(self, filter, alpha=None):

        # store metadata
        param_dict = ParameterDict(
            filter=ParticleFilter,
            alpha=OnlyTypes(float, allow_none=True),
        )
        param_dict.update(dict(alpha=alpha, filter=filter))

        # set defaults
        self._param_dict.update(param_dict)

        gamma = TypeParameter('gamma',
                              type_kind='particle_types',
                              param_dict=TypeParameterDict(1., len_keys=1))

        gamma_r = TypeParameter('gamma_r',
                                type_kind='particle_types',
                                param_dict=TypeParameterDict((1., 1., 1.),
                                                             len_keys=1))
        self._extend_typeparam([gamma, gamma_r])
Example #9
0
    def __init__(self,
                 filter,
                 kT,
                 tau,
                 S,
                 tauS,
                 couple,
                 box_dof=[True, True, True, False, False, False],
                 rescale_all=False,
                 gamma=0.0):

        # store metadata
        param_dict = ParameterDict(
            filter=ParticleFilter,
            kT=Variant,
            tau=float(tau),
            S=OnlyIf(to_type_converter((Variant, ) * 6),
                     preprocess=self._preprocess_stress),
            tauS=float(tauS),
            couple=str(couple),
            box_dof=[
                bool,
            ] * 6,
            rescale_all=bool(rescale_all),
            gamma=float(gamma),
            translational_thermostat_dof=(float, float),
            rotational_thermostat_dof=(float, float),
            barostat_dof=(float, float, float, float, float, float))
        param_dict.update(
            dict(filter=filter,
                 kT=kT,
                 S=S,
                 couple=couple,
                 box_dof=box_dof,
                 translational_thermostat_dof=(0, 0),
                 rotational_thermostat_dof=(0, 0),
                 barostat_dof=(0, 0, 0, 0, 0, 0)))

        # set defaults
        self._param_dict.update(param_dict)
Example #10
0
    def __init__(self, filter, kT, alpha=None, tally_reservoir_energy=False):

        # store metadata
        param_dict = ParameterDict(
            filter=ParticleFilter,
            kT=Variant,
            alpha=OnlyTypes(float, allow_none=True),
            tally_reservoir_energy=bool(tally_reservoir_energy),
        )
        param_dict.update(dict(kT=kT, alpha=alpha, filter=filter))
        # set defaults
        self._param_dict.update(param_dict)

        gamma = TypeParameter('gamma',
                              type_kind='particle_types',
                              param_dict=TypeParameterDict(1., len_keys=1))

        gamma_r = TypeParameter('gamma_r',
                                type_kind='particle_types',
                                param_dict=TypeParameterDict((1., 1., 1.),
                                                             len_keys=1))

        self._extend_typeparam([gamma, gamma_r])
Example #11
0
    def __init__(self, filter, kT, manifold_constraint=None, tolerance=0.000001, alpha=None):

        # store metadata
        param_dict = ParameterDict(
            filter=ParticleFilter,
            kT=Variant,
            alpha=OnlyTypes(float, allow_none=True),
            )
        param_dict.update(dict(kT=kT, alpha=alpha, filter=filter))

        #set defaults
        self._param_dict.update(param_dict)

        gamma = TypeParameter('gamma', type_kind='particle_types',
                              param_dict=TypeParameterDict(1., len_keys=1)
                              )

        gamma_r = TypeParameter('gamma_r', type_kind='particle_types',
                                param_dict=TypeParameterDict((1., 1., 1.), len_keys=1)
                                )
        self._extend_typeparam([gamma,gamma_r])

        super().__init__(manifold_constraint,tolerance)
Example #12
0
class LoadBalancer(Tuner):
    r""" Adjusts the boundaries of the domain decomposition.

    Args:
        trigger (hoomd.trigger.Trigger): Select the timesteps on which to
            perform load balancing.
        x (:obj:`bool`): Balance the **x** direction when `True`.
        y (:obj:`bool`): Balance the **y** direction when `True`.
        z (:obj:`bool`): Balance the **z** direction when `True`.
        tolerance (:obj:`float`): Load imbalance tolerance.
        max_iterations (:obj:`int`): Maximum number of iterations to
            attempt in a single step.

    `LoadBalancer` adjusts the boundaries of the MPI domains to distribute
    the particle load close to evenly between them. The load imbalance is
    defined as the number of particles owned by a rank divided by the average
    number of particles per rank if the particles had a uniform distribution:

    .. math::

        I = \frac{N_i}{N / P}

    where :math:`N_i` is the number of particles on rank :math:`i`, :math:`N` is
    the total number of particles, and :math:`P` is the number of ranks.

    In order to adjust the load imbalance, `LoadBalancer` scales by the inverse
    of the imbalance factor. To reduce oscillations and communication overhead,
    it does not move a domain more than 5% of its current size in a single
    rebalancing step, and not more than half the distance to its neighbors.

    Simulations with interfaces (so that there is a particle density gradient)
    or clustering should benefit from load balancing. The potential speedup is
    roughly :math:`I-1.0`, so that if the largest imbalance is 1.4, then the
    user can expect a roughly 40% speedup in the simulation. This is of course
    an estimate that assumes that all algorithms are roughly linear in
    :math:`N`, all GPUs are fully occupied, and the simulation is limited by the
    speed of the slowest processor. It also assumes that all particles roughly
    equal. If you have a simulation where, for example, some particles have
    significantly more pair force neighbors than others, this estimate of the
    load imbalance may not produce the optimal results.

    A load balancing adjustment is only performed when the maximum load
    imbalance exceeds a *tolerance*. The ideal load balance is 1.0, so setting
    *tolerance* less than 1.0 will force an adjustment every update. The load
    balancer can attempt multiple iterations of balancing on each update, and up
    to *maxiter* attempts can be made. The optimal values of update and
    *maxiter* will depend on your simulation.

    Load balancing can be performed independently and sequentially for each
    dimension of the simulation box. A small performance increase may be
    obtained by disabling load balancing along dimensions that are known to be
    homogeneous.  For example, if there is a planar vapor-liquid interface
    normal to the :math:`z` axis, then it may be advantageous to disable
    balancing along :math:`x` and :math:`y`.

    In systems that are well-behaved, there is minimal overhead of balancing
    with a small update. However, if the system is not capable of being balanced
    (for example, due to the density distribution or minimum domain size),
    having a small update and high *maxiter* may lead to a large performance
    loss. In such systems, it is currently best to either balance infrequently
    or to balance once in a short test run and then set the decomposition
    statically in a separate initialization.

    Balancing is ignored if there is no domain decomposition available (MPI is
    not built or is running on a single rank).

    Attributes:
        trigger (hoomd.trigger.Trigger): Select the timesteps on which to
            perform load balancing.
        x (:obj:`bool`): Balance the **x** direction when `True`.
        y (:obj:`bool`): Balance the **y** direction when `True`.
        z (:obj:`bool`): Balance the **z** direction when `True`.
        tolerance (:obj:`float`): Load imbalance tolerance.
        max_iterations (:obj:`int`): Maximum number of iterations to
            attempt in a single step.
    """
    def __init__(self,
                 trigger,
                 x=True,
                 y=True,
                 z=True,
                 tolerance=1.02,
                 max_iterations=1):
        defaults = dict(x=x,
                        y=y,
                        z=z,
                        tolerance=tolerance,
                        max_iterations=max_iterations,
                        trigger=trigger)
        self._param_dict = ParameterDict(x=bool,
                                         y=bool,
                                         z=bool,
                                         max_iterations=int,
                                         tolerance=float,
                                         trigger=Trigger)
        self._param_dict.update(defaults)

    def _attach(self):
        if isinstance(self._simulation.device, hoomd.device.GPU):
            cpp_cls = getattr(_hoomd, 'LoadBalancerGPU')
        else:
            cpp_cls = getattr(_hoomd, 'LoadBalancer')
        self._cpp_obj = cpp_cls(
            self._simulation.state._cpp_sys_def,
            self._simulation._cpp_sys.getCommunicator().getDomainDecomposition(
            ), self.trigger)

        super()._attach()