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
def assertHasValidBVector(self, coord, robustness=8, places=9): fdiffs = [ FiniteDifferenceDerivative(coord, c, robustness=robustness) for c in coord.variables ] values = [float(f.value) for f in fdiffs] self.assertSequenceAlmostEqual(values, coord.b_vector, places=places)
def assertOkayFdiffDerivative(self, poly, vars, places=4, robustness=2, forward=False): """ Assert almost equal with significant figures rather than digits after the decimal """ df = FiniteDifferenceDerivative(poly, *tuple(vars), robustness=robustness, forward=forward).value exp = poly.actual_derivative(*tuple(vars)) if abs(exp) > 0: div = 10.0**float(math.ceil(math.log(abs(exp), 10.0))) ract = round(df / div, places) rexp = round(exp / div, places) else: ract = round(df, places) rexp = round(exp, places) tmp = self.longMessage self.longMessage = True try: #("%"+str(places+1)+"f") % rexp, ("%"+str(places+1)+"f") % ract, self.assertAlmostEqual( ract, rexp, places, msg="\nfor derivative {} with robustness {} of function:\n{}". format(vars, robustness, indented(str(poly)))) finally: self.longMessage = tmp
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)
def test_one_var_huge(self): FiniteDifferenceDerivative.precompute_single_variable(3, 60) terms = [] for exp in range(1, 45): terms.append('{}x^{}'.format(45 - exp, exp)) p = Polynomial(' + '.join(terms), [1.25]) #self.assertOkayFdiffDerivative(p, 'x', robustness=2, places=2) #self.assertOkayFdiffDerivative(p, 'x', robustness=4, places=3) #for rob in range(6, 12, 2): # self.assertOkayFdiffDerivative(p, 'x', robustness=rob, places=6) #for rob in range(12, 58, 2): # self.assertOkayFdiffDerivative(p, 'x', robustness=rob, places=10) self.assertOkayFdiffDerivative(p, 'xx', robustness=2, places=2) self.assertOkayFdiffDerivative(p, 'xx', robustness=4, places=3) for rob in range(6, 12, 1): self.assertOkayFdiffDerivative(p, 'xx', robustness=rob, places=6) for rob in range(12, 58, 1): self.assertOkayFdiffDerivative(p, 'xx', robustness=rob, places=10) for rob in range(6, 12, 2): self.assertOkayFdiffDerivative(p, 'xxx', robustness=rob, places=6) for rob in range(12, 58, 2): self.assertOkayFdiffDerivative(p, 'xxx', robustness=rob, places=10)
def test_one_var_huge(self): FiniteDifferenceDerivative.precompute_single_variable(3, 60) terms = [] for exp in range(1, 45): terms.append('{}x^{}'.format(45-exp,exp)) p = Polynomial(' + '.join(terms), [1.25]) #self.assertOkayFdiffDerivative(p, 'x', robustness=2, places=2) #self.assertOkayFdiffDerivative(p, 'x', robustness=4, places=3) #for rob in range(6, 12, 2): # self.assertOkayFdiffDerivative(p, 'x', robustness=rob, places=6) #for rob in range(12, 58, 2): # self.assertOkayFdiffDerivative(p, 'x', robustness=rob, places=10) self.assertOkayFdiffDerivative(p, 'xx', robustness=2, places=2) self.assertOkayFdiffDerivative(p, 'xx', robustness=4, places=3) for rob in range(6, 12, 1): self.assertOkayFdiffDerivative(p, 'xx', robustness=rob, places=6) for rob in range(12, 58, 1): self.assertOkayFdiffDerivative(p, 'xx', robustness=rob, places=10) for rob in range(6, 12, 2): self.assertOkayFdiffDerivative(p, 'xxx', robustness=rob, places=6) for rob in range(12, 58, 2): self.assertOkayFdiffDerivative(p, 'xxx', robustness=rob, places=10)
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
def get_b_tensor_entry(self, internal_coord, cart_coords): fdiff_key = (internal_coord, cart_coords) fdiff = self.fdiff_instances.get(fdiff_key, None) if fdiff is None: fdiff = FiniteDifferenceDerivative( #--------------# # function = internal_coord, #--------------# # *variables = cart_coords[0], #--------------# value_function=partial( self.value_for_coords_and_displacements, internal_coord=internal_coord, cart_coords=cart_coords[1:]), forward=self.forward, delta=self.delta, robustness=self.robustness ) self.fdiff_instances[fdiff_key] = fdiff ret_val = fdiff.value return ret_val
def test_one_var(self): p = Polynomial('3x^2 + 2x + 1', [5.5]) f = FiniteDifferenceDerivative(p, 'x') self.assertAlmostEqual(f.value, p.actual_derivative('x'))