예제 #1
0
 def Energy(self, coordinates3, gradients3=None):
     """Calculate the energy."""
     # . Displacements.
     v12 = coordinates3.Displacement(self.point1, self.point2)
     v32 = coordinates3.Displacement(self.point3, self.point2)
     v34 = coordinates3.Displacement(self.point3, self.point4)
     # . Get m and n.
     m = Clone(v12)
     m.Cross(v32)
     n = Clone(v32)
     n.Cross(v34)
     # . Get the sizes of m and n.
     msize = m.Norm2()
     nsize = n.Norm2()
     # . Normalize m and n.
     m.Scale(1.0 / msize)
     n.Scale(1.0 / nsize)
     # . Get the dot-product.
     dotfac = m.Dot(n)
     if dotfac > 1.0: dotfac = 1.0
     elif dotfac < -1.0: dotfac = -1.0
     # . Get the sign of the angle.
     sgnfac = 1.0
     if v12.Dot(n) < 0.0: sgnfac = -1.0
     # . Determine the dihedral.
     value = sgnfac * math.acos(dotfac) * UNITS_ANGLE_RADIANS_TO_DEGREES
     # . Get the energy.
     (f, df) = self.energyModel.Energy(value)
     # . Derivatives.
     if gradients3 is not None:
         df *= UNITS_ANGLE_RADIANS_TO_DEGREES
         # . Calculate r32.
         r32 = v32.Norm2()
         # . Calculate dedi and dedl in m and n respectively.
         m.Scale(df * r32 / msize)
         n.Scale(-df * r32 / nsize)
         # . Calculate some additional factors.
         fact12 = v12.Dot(v32) / (r32 * r32)
         fact34 = v34.Dot(v32) / (r32 * r32)
         # . Gradients for i and l.
         gradients3.Increment(self.point1, m)
         gradients3.Increment(self.point4, n)
         # . Calculate dedj and dedk in v12 and v32 respectively.
         m.CopyTo(v12)
         v12.Scale(fact12 - 1.0)
         v12.AddScaledVector3(-fact34, n)
         n.CopyTo(v32)
         v32.Scale(fact34 - 1.0)
         v32.AddScaledVector3(-fact12, m)
         # . calculate the gradients.
         gradients3.Increment(self.point2, v12)
         gradients3.Increment(self.point3, v32)
     return (f, value)
 def AddLinearConstraint ( self, constraint ):
     """Add a linear constraint."""
     if len ( constraint ) != self.nvariables: raise ValueError ( "Invalid linear constraint length." )
     # . Orthogonalize to existing constraints.
     if self.linearVectors is not None:
         constraint = Clone ( constraint )
         self.linearVectors.ProjectOutOfArray ( constraint )
     # . Check to see if the constraint is valid.
     cnorm2 = constraint.Norm2 ( )
     if cnorm2 > 1.0e-10:
         constraint.Scale ( 1.0 / cnorm2 )
         # . Allocate space for new constraints.
         ncolumns = 1
         if self.linearVectors is not None: ncolumns += self.linearVectors.columns
         newconstraints = Real2DArray.WithExtents ( len ( constraint ), ncolumns )
         # . Copy over constraints.
         if self.linearVectors is not None:
             for r in range ( self.linearVectors.rows ):
                 for c in range ( self.linearVectors.columns ):
                     newconstraints[r,c] = self.linearVectors[r,c]
         for r in range ( len ( constraint ) ): newconstraints[r,ncolumns-1] = constraint[r]
         self.linearVectors = newconstraints
         # . Determine the linear scalars.
         self.linearScalars = Real1DArray.WithExtent ( self.linearVectors.columns )
         reference          = Real1DArray.WithExtent ( self.linearVectors.rows    )
         if self.rtReference is None: self.system.coordinates3.CopyToArray ( reference )
         else:                        self.rtReference.CopyToArray ( reference )
         self.linearVectors.VectorMultiply ( reference, self.linearScalars, 1.0, 0.0, transpose = True )
         # . Reset the number of degrees of freedom.
         self.degreesOfFreedom = self.nvariables - len ( self.linearScalars )