Author: bugman Date: Wed Jun 18 15:38:33 2014 New Revision: 24090 URL: http://svn.gna.org/viewcvs/relax?rev=24090&view=rev Log: Support for the 3 vector system for double motions has been added to the frame order analysis. This is used for the quasi-random Sobol' numeric integration of the PCS. The lanthanide to atom vector is the sum of three parts: the 1st pivot to atom vector rotated by the 1st mode of motion; the 2nd pivot to 1st pivot vector rotated by the 2nd mode of motion (together with the rotated 1st pivot to atom vectors); and the lanthanide to second pivot vector. All these vectors are passed into the lib.frame_order.double_rotor.pcs_numeric_int_double_rotor() function, which passes them to the pcs_pivot_motion_double_rotor() function where they are rotated and reconstructed into the Ln3+ to atom vectors. Modified: branches/frame_order_cleanup/lib/frame_order/double_rotor.py branches/frame_order_cleanup/target_functions/frame_order.py Modified: branches/frame_order_cleanup/lib/frame_order/double_rotor.py URL: http://svn.gna.org/viewcvs/relax/branches/frame_order_cleanup/lib/frame_order/double_rotor.py?rev=24090&r1=24089&r2=24090&view=diff ============================================================================== --- branches/frame_order_cleanup/lib/frame_order/double_rotor.py (original) +++ branches/frame_order_cleanup/lib/frame_order/double_rotor.py Wed Jun 18 15:38:33 2014 @@ -24,7 +24,7 @@ # Python module imports. from math import pi, sqrt -from numpy import divide, dot, inner, multiply, sinc, swapaxes, tensordot, transpose +from numpy import add, divide, dot, inner, multiply, sinc, swapaxes, tensordot, transpose from numpy.linalg import norm # relax module imports. @@ -75,7 +75,7 @@ return rotate_daeg(matrix, Rx2_eigen) -def pcs_numeric_int_double_rotor(points=None, sigma_max=None, sigma_max_2=None, c=None, full_in_ref_frame=None, r_pivot_atom=None, r_pivot_atom_rev=None, r_ln_pivot=None, A=None, R_eigen=None, RT_eigen=None, Ri_prime=None, pcs_theta=None, pcs_theta_err=None, missing_pcs=None): +def pcs_numeric_int_double_rotor(points=None, sigma_max=None, sigma_max_2=None, c=None, full_in_ref_frame=None, r_pivot_atom=None, r_pivot_atom_rev=None, r_ln_pivot=None, r_inter_pivot=None, A=None, R_eigen=None, RT_eigen=None, Ri_prime=None, pcs_theta=None, pcs_theta_err=None, missing_pcs=None): """The averaged PCS value via numerical integration for the double rotor frame order model. @keyword points: The Sobol points in the torsion-tilt angle space. @@ -94,6 +94,8 @@ @type r_pivot_atom_rev: numpy rank-2, 3D array @keyword r_ln_pivot: The lanthanide position to pivot point vector. @type r_ln_pivot: numpy rank-2, 3D array + @keyword r_inter_pivot: The vector between the two pivots. + @type r_inter_pivot: numpy rank-1, 3D array @keyword A: The full alignment tensor of the non-moving domain. @type A: numpy rank-2, 3D array @keyword R_eigen: The eigenframe rotation matrix. @@ -129,7 +131,7 @@ continue # Calculate the PCSs for this state. - pcs_pivot_motion_double_rotor(full_in_ref_frame=full_in_ref_frame, r_pivot_atom=r_pivot_atom, r_pivot_atom_rev=r_pivot_atom_rev, r_ln_pivot=r_ln_pivot, A=A, Ri=Ri[i], pcs_theta=pcs_theta, pcs_theta_err=pcs_theta_err, missing_pcs=missing_pcs) + pcs_pivot_motion_double_rotor(full_in_ref_frame=full_in_ref_frame, r_pivot_atom=r_pivot_atom, r_pivot_atom_rev=r_pivot_atom_rev, r_ln_pivot=r_ln_pivot, r_inter_pivot=r_inter_pivot, A=A, Ri=Ri[i], Ri2=Ri[i], pcs_theta=pcs_theta, pcs_theta_err=pcs_theta_err, missing_pcs=missing_pcs) # Increment the number of points. num += 1 @@ -142,7 +144,7 @@ Ri = swapaxes(Ri, 0, 1) # Calculate the PCSs for this state. - pcs_pivot_motion_double_rotor(full_in_ref_frame=full_in_ref_frame, r_pivot_atom=r_pivot_atom, r_pivot_atom_rev=r_pivot_atom_rev, r_ln_pivot=r_ln_pivot, A=A, Ri=Ri, pcs_theta=pcs_theta, pcs_theta_err=pcs_theta_err, missing_pcs=missing_pcs) + pcs_pivot_motion_double_rotor(full_in_ref_frame=full_in_ref_frame, r_pivot_atom=r_pivot_atom, r_pivot_atom_rev=r_pivot_atom_rev, r_ln_pivot=r_ln_pivot, r_inter_pivot=r_inter_pivot, A=A, Ri=Ri, Ri2=Ri, pcs_theta=pcs_theta, pcs_theta_err=pcs_theta_err, missing_pcs=missing_pcs) # Multiply the constant. multiply(c, pcs_theta, pcs_theta) @@ -153,7 +155,7 @@ divide(pcs_theta, float(num), pcs_theta) -def pcs_pivot_motion_double_rotor(full_in_ref_frame=None, r_pivot_atom=None, r_pivot_atom_rev=None, r_ln_pivot=None, A=None, Ri=None, pcs_theta=None, pcs_theta_err=None, missing_pcs=None): +def pcs_pivot_motion_double_rotor(full_in_ref_frame=None, r_pivot_atom=None, r_pivot_atom_rev=None, r_ln_pivot=None, r_inter_pivot=None, A=None, Ri=None, Ri2=None, pcs_theta=None, pcs_theta_err=None, missing_pcs=None): """Calculate the PCS value after a pivoted motion for the double rotor model. @keyword full_in_ref_frame: An array of flags specifying if the tensor in the reference frame is the full or reduced tensor. @@ -164,10 +166,14 @@ @type r_pivot_atom_rev: numpy rank-2, 3D array @keyword r_ln_pivot: The lanthanide position to pivot point vector. @type r_ln_pivot: numpy rank-2, 3D array + @keyword r_inter_pivot: The vector between the two pivots. + @type r_inter_pivot: numpy rank-1, 3D array @keyword A: The full alignment tensor of the non-moving domain. @type A: numpy rank-2, 3D array - @keyword Ri: The frame-shifted, pre-calculated rotation matrix for state i. + @keyword Ri: The frame-shifted, pre-calculated rotation matrix for state i for the first mode of motion. @type Ri: numpy rank-2, 3D array + @keyword Ri2: The frame-shifted, pre-calculated rotation matrix for state i for the second mode of motion. + @type Ri2: numpy rank-2, 3D array @keyword pcs_theta: The storage structure for the back-calculated PCS values. @type pcs_theta: numpy rank-2 array @keyword pcs_theta_err: The storage structure for the back-calculated PCS errors. @@ -176,15 +182,27 @@ @type missing_pcs: numpy rank-2 array """ - # Pre-calculate all the new vectors. + # Rotate the first pivot to atomic position vectors. rot_vect = dot(r_pivot_atom, Ri) + r_ln_pivot + + # Add the inter-pivot vector to obtain the 2nd pivot to atomic position vectors. + add(r_inter_pivot, rot_vect, rot_vect) + + # Rotate the 2nd pivot to atomic position vectors. + rot_vect = dot(rot_vect, Ri2) + + # Add the lanthanide to pivot vector. + add(rot_vect, r_ln_pivot, rot_vect) # The vector length (to the 5th power). length = 1.0 / norm(rot_vect, axis=1)**5 # The reverse vectors and lengths. if min(full_in_ref_frame) == 0: - rot_vect_rev = dot(r_pivot_atom_rev, Ri) + r_ln_pivot + rot_vect_rev = dot(r_pivot_atom_rev, Ri) + add(r_inter_pivot, rot_vect_rev, rot_vect_rev) + rot_vect_rev = dot(rot_vect_rev, Ri2) + add(rot_vect_rev, r_ln_pivot, rot_vect_rev) length_rev = 1.0 / norm(rot_vect_rev, axis=1)**5 # Loop over the atoms. Modified: branches/frame_order_cleanup/target_functions/frame_order.py URL: http://svn.gna.org/viewcvs/relax/branches/frame_order_cleanup/target_functions/frame_order.py?rev=24090&r1=24089&r2=24090&view=diff ============================================================================== --- branches/frame_order_cleanup/target_functions/frame_order.py (original) +++ branches/frame_order_cleanup/target_functions/frame_order.py Wed Jun 18 15:38:33 2014 @@ -431,7 +431,7 @@ # PCS via numerical integration. if self.pcs_flag: # Numerical integration of the PCSs. - pcs_numeric_int_double_rotor(points=self.sobol_angles, sigma_max=sigma_max, sigma_max_2=sigma_max_2, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs) + pcs_numeric_int_double_rotor(points=self.sobol_angles, sigma_max=sigma_max, sigma_max_2=sigma_max_2, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, r_inter_pivot=self.r_inter_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs) # Calculate and sum the single alignment chi-squared value (for the PCS). for align_index in range(self.num_align): @@ -1164,6 +1164,10 @@ add(self.r_pivot_atom_rev, self.ave_pos_pivot, self.r_pivot_atom_rev) add(self.r_pivot_atom_rev, self._translation_vector, self.r_pivot_atom_rev) subtract(self.r_pivot_atom_rev, pivot, self.r_pivot_atom_rev) + + # Calculate the inter-pivot vector for the double motion models. + if pivot2 != None: + self.r_inter_pivot = pivot - pivot2 def create_sobol_data(self, n=10000, dims=None):