Beispiel #1
0
 def __init__(self,
              max_analytic_order=0,
              property=Energy,
              deltas=None,
              details=None,
              run_now=False,
              queue=None,
              robustness=2,
              **kwargs):
     kwargs.update(property=property)
     super(FiniteDifferenceForceField, self).__init__(**kwargs)
     self.robustness = robustness
     self.max_analytic_order = max_analytic_order
     self.filled_for_order = [False] * self.max_order
     if max_analytic_order > 1:
         raise NotImplementedError
     elif max_analytic_order > 0:
         if isinstance(self.representation, CartesianRepresentation):
             self.computed_property = PropertyDerivative(
                 property,
                 representation=self.representation,
                 order=max_analytic_order)
             self.computed_property = self.computed_property.in_units(
                 self.property_units /
                 self.representation.units**self.max_analytic_order)
         else:
             # TODO figure out why I need to do finite difference of cartesian gradients and then convert to get the correct answer (rather than finite difference of internal coordinate gradients)
             self.computed_property = PropertyDerivative(
                 property,
                 representation=self.representation.molecule.
                 cartesian_representation,
                 order=max_analytic_order)
             self.computed_property = self.computed_property.in_units(
                 self.property_units /
                 (self.representation.molecule.cartesian_representation.
                  units**self.max_analytic_order))
     else:
         self.computed_property = property.in_units(self.property_units)
     self.displacement_manager = DisplacementManager(
         self.representation,
         differentiable=self.computed_property,
         deltas=deltas,
         details=details)
     if queue is not None:
         self.computation_queue = queue
         queue.enqueue(*self.needed_computations)
         if run_now:
             queue.run()
             self.fill()
     elif run_now:
         self.fill()
Beispiel #2
0
 def __init__(self,
         max_analytic_order=0,
         property=Energy,
         deltas=None,
         details=None,
         run_now=False,
         queue=None,
         robustness=2,
         **kwargs):
     kwargs.update(property=property)
     super(FiniteDifferenceForceField, self).__init__(**kwargs)
     self.robustness = robustness
     self.max_analytic_order = max_analytic_order
     self.filled_for_order = [False] * self.max_order
     if max_analytic_order > 1:
         raise NotImplementedError
     elif max_analytic_order > 0:
         if isinstance(self.representation, CartesianRepresentation):
             self.computed_property = PropertyDerivative(
                 property,
                 representation=self.representation,
                 order=max_analytic_order
             )
             self.computed_property = self.computed_property.in_units(
                 self.property_units / self.representation.units**self.max_analytic_order
             )
         else:
             # TODO figure out why I need to do finite difference of cartesian gradients and then convert to get the correct answer (rather than finite difference of internal coordinate gradients)
             self.computed_property = PropertyDerivative(
                 property,
                 representation=self.representation.molecule.cartesian_representation,
                 order=max_analytic_order
             )
             self.computed_property = self.computed_property.in_units(
                 self.property_units / (
                     self.representation.molecule.cartesian_representation.units**self.max_analytic_order
                 )
             )
     else:
         self.computed_property = property.in_units(self.property_units)
     self.displacement_manager = DisplacementManager(
         self.representation,
         differentiable=self.computed_property,
         deltas=deltas,
         details=details
     )
     if queue is not None:
         self.computation_queue = queue
         queue.enqueue(*self.needed_computations)
         if run_now:
             queue.run()
             self.fill()
     elif run_now:
         self.fill()
Beispiel #3
0
class FiniteDifferenceForceField(ForceField):
    """
    """

    ##############
    # Attributes #
    ##############

    displacement_manager = None
    filled_for_order = None
    computed_property = None
    max_analytic_order = None
    robustness = None
    computation_queue = None

    ######################
    # Private Attributes #
    ######################

    _unit_dict = None

    ##################
    # Initialization #
    ##################

    def __init__(self,
            max_analytic_order=0,
            property=Energy,
            deltas=None,
            details=None,
            run_now=False,
            queue=None,
            robustness=2,
            **kwargs):
        kwargs.update(property=property)
        super(FiniteDifferenceForceField, self).__init__(**kwargs)
        self.robustness = robustness
        self.max_analytic_order = max_analytic_order
        self.filled_for_order = [False] * self.max_order
        if max_analytic_order > 1:
            raise NotImplementedError
        elif max_analytic_order > 0:
            if isinstance(self.representation, CartesianRepresentation):
                self.computed_property = PropertyDerivative(
                    property,
                    representation=self.representation,
                    order=max_analytic_order
                )
                self.computed_property = self.computed_property.in_units(
                    self.property_units / self.representation.units**self.max_analytic_order
                )
            else:
                # TODO figure out why I need to do finite difference of cartesian gradients and then convert to get the correct answer (rather than finite difference of internal coordinate gradients)
                self.computed_property = PropertyDerivative(
                    property,
                    representation=self.representation.molecule.cartesian_representation,
                    order=max_analytic_order
                )
                self.computed_property = self.computed_property.in_units(
                    self.property_units / (
                        self.representation.molecule.cartesian_representation.units**self.max_analytic_order
                    )
                )
        else:
            self.computed_property = property.in_units(self.property_units)
        self.displacement_manager = DisplacementManager(
            self.representation,
            differentiable=self.computed_property,
            deltas=deltas,
            details=details
        )
        if queue is not None:
            self.computation_queue = queue
            queue.enqueue(*self.needed_computations)
            if run_now:
                queue.run()
                self.fill()
        elif run_now:
            self.fill()

    ##############
    # Properties #
    ##############

    @property
    def all_computations(self):
        all_comps = set()
        for order in xrange(self.max_analytic_order+1, self.max_order+1):
            for coords in symmetric_product(self.representation, order-self.max_analytic_order):
                fd = FiniteDifferenceDerivative(
                    self.displacement_manager,
                    *coords,
                    target_robustness=self.robustness
                )
                for incs in fd.needed_increments:
                    increments = [0] * len(self.representation)
                    for coord, inc in zip(fd.variables, incs):
                        increments[coord.index] = inc
                    dmol = self.displacement_manager.displacement_for(tuple(increments)).displaced_molecule
                    comp = dmol.get_computation_for_property(
                        self.computed_property,
                        self.displacement_manager.details
                    )
                    if comp not in all_comps:
                        all_comps.add(comp)
        if self.max_analytic_order == 1:
            comp = self.base_molecule.get_computation_for_property(
                self.computed_property,
                self.displacement_manager.details
            )
            if comp not in all_comps:
                all_comps.add(comp)
        elif self.max_analytic_order > 2:
            # TODO figure out how many analytic computations need to be done
            raise NotImplementedError
        return list(all_comps)

    @property
    def needed_computations(self):
        return [c for c in self.all_computations if not c.completed]


    ###########
    # Methods #
    ###########

    def fill(self):
        if self.computation_queue is not None and not self.computation_queue.is_finished():
            self.computation_queue.run()
        for n in xrange(self.max_order):
            self.fill_order(self.max_order - n)

    def fill_order(self, order):
        if self.filled_for_order[order-1]:
            return
        #----------------------------------------#
        tens = self.tensors[order]
        if order <= self.max_analytic_order:
            #TODO this will need to be significantly modified for hessians and higher, since the transformation to interal coordinates requires all lower derivatives as well...
            tens[...] = self.base_molecule.get_property(
                PropertyDerivative(self.molecular_property, order) if order > 0 else self.molecular_property,
                details=self.displacement_manager.details
            ).value.in_representation(self.representation)
        #----------------------------------------#
        else:
            for f_coords in symmetric_product(self.representation, order-self.max_analytic_order):
                if self.max_analytic_order == 0 or isinstance(self.representation, CartesianRepresentation):
                    spread_val = FiniteDifferenceDerivative(
                        self.displacement_manager,
                        *f_coords,
                        target_robustness=self.robustness
                    ).value
                else:
                    spread_val = RepresentationDependentTensor(
                        FiniteDifferenceDerivative(
                            self.displacement_manager,
                            *f_coords,
                            target_robustness=self.robustness
                        ).value,
                        representation=self.representation.molecule.cartesian_representation
                    )
                    spread_val = spread_val.in_representation(self.representation)
                for perm in permutations(f_coords):
                    tens[perm] = spread_val
        #----------------------------------------#
        self.filled_for_order[order-1] = True

    @typechecked(order=int)
    def for_order(self, order):
        if order <= self.max_order and not self.filled_for_order[order-1]:
            raise ValueError("Order {} tensor of ForceField instance not yet computed.".format(
                order
            ))
        else:
            return super(FiniteDifferenceForceField, self).for_order(order)
Beispiel #4
0
class FiniteDifferenceForceField(ForceField):
    """
    """

    ##############
    # Attributes #
    ##############

    displacement_manager = None
    filled_for_order = None
    computed_property = None
    max_analytic_order = None
    robustness = None
    computation_queue = None

    ######################
    # Private Attributes #
    ######################

    _unit_dict = None

    ##################
    # Initialization #
    ##################

    def __init__(self,
                 max_analytic_order=0,
                 property=Energy,
                 deltas=None,
                 details=None,
                 run_now=False,
                 queue=None,
                 robustness=2,
                 **kwargs):
        kwargs.update(property=property)
        super(FiniteDifferenceForceField, self).__init__(**kwargs)
        self.robustness = robustness
        self.max_analytic_order = max_analytic_order
        self.filled_for_order = [False] * self.max_order
        if max_analytic_order > 1:
            raise NotImplementedError
        elif max_analytic_order > 0:
            if isinstance(self.representation, CartesianRepresentation):
                self.computed_property = PropertyDerivative(
                    property,
                    representation=self.representation,
                    order=max_analytic_order)
                self.computed_property = self.computed_property.in_units(
                    self.property_units /
                    self.representation.units**self.max_analytic_order)
            else:
                # TODO figure out why I need to do finite difference of cartesian gradients and then convert to get the correct answer (rather than finite difference of internal coordinate gradients)
                self.computed_property = PropertyDerivative(
                    property,
                    representation=self.representation.molecule.
                    cartesian_representation,
                    order=max_analytic_order)
                self.computed_property = self.computed_property.in_units(
                    self.property_units /
                    (self.representation.molecule.cartesian_representation.
                     units**self.max_analytic_order))
        else:
            self.computed_property = property.in_units(self.property_units)
        self.displacement_manager = DisplacementManager(
            self.representation,
            differentiable=self.computed_property,
            deltas=deltas,
            details=details)
        if queue is not None:
            self.computation_queue = queue
            queue.enqueue(*self.needed_computations)
            if run_now:
                queue.run()
                self.fill()
        elif run_now:
            self.fill()

    ##############
    # Properties #
    ##############

    @property
    def all_computations(self):
        all_comps = set()
        for order in xrange(self.max_analytic_order + 1, self.max_order + 1):
            for coords in symmetric_product(self.representation,
                                            order - self.max_analytic_order):
                fd = FiniteDifferenceDerivative(
                    self.displacement_manager,
                    *coords,
                    target_robustness=self.robustness)
                for incs in fd.needed_increments:
                    increments = [0] * len(self.representation)
                    for coord, inc in zip(fd.variables, incs):
                        increments[coord.index] = inc
                    dmol = self.displacement_manager.displacement_for(
                        tuple(increments)).displaced_molecule
                    comp = dmol.get_computation_for_property(
                        self.computed_property,
                        self.displacement_manager.details)
                    if comp not in all_comps:
                        all_comps.add(comp)
        if self.max_analytic_order == 1:
            comp = self.base_molecule.get_computation_for_property(
                self.computed_property, self.displacement_manager.details)
            if comp not in all_comps:
                all_comps.add(comp)
        elif self.max_analytic_order > 2:
            # TODO figure out how many analytic computations need to be done
            raise NotImplementedError
        return list(all_comps)

    @property
    def needed_computations(self):
        return [c for c in self.all_computations if not c.completed]

    ###########
    # Methods #
    ###########

    def fill(self):
        if self.computation_queue is not None and not self.computation_queue.is_finished(
        ):
            self.computation_queue.run()
        for n in xrange(self.max_order):
            self.fill_order(self.max_order - n)

    def fill_order(self, order):
        if self.filled_for_order[order - 1]:
            return
        #----------------------------------------#
        tens = self.tensors[order]
        if order <= self.max_analytic_order:
            #TODO this will need to be significantly modified for hessians and higher, since the transformation to interal coordinates requires all lower derivatives as well...
            tens[...] = self.base_molecule.get_property(
                PropertyDerivative(self.molecular_property, order)
                if order > 0 else self.molecular_property,
                details=self.displacement_manager.details
            ).value.in_representation(self.representation)
        #----------------------------------------#
        else:
            for f_coords in symmetric_product(self.representation,
                                              order - self.max_analytic_order):
                if self.max_analytic_order == 0 or isinstance(
                        self.representation, CartesianRepresentation):
                    spread_val = FiniteDifferenceDerivative(
                        self.displacement_manager,
                        *f_coords,
                        target_robustness=self.robustness).value
                else:
                    spread_val = RepresentationDependentTensor(
                        FiniteDifferenceDerivative(
                            self.displacement_manager,
                            *f_coords,
                            target_robustness=self.robustness).value,
                        representation=self.representation.molecule.
                        cartesian_representation)
                    spread_val = spread_val.in_representation(
                        self.representation)
                for perm in permutations(f_coords):
                    tens[perm] = spread_val
        #----------------------------------------#
        self.filled_for_order[order - 1] = True

    @typechecked(order=int)
    def for_order(self, order):
        if order <= self.max_order and not self.filled_for_order[order - 1]:
            raise ValueError(
                "Order {} tensor of ForceField instance not yet computed.".
                format(order))
        else:
            return super(FiniteDifferenceForceField, self).for_order(order)