Package maths_fns :: Module frame_order_matrix_ops
[hide private]
[frames] | no frames]

Source Code for Module maths_fns.frame_order_matrix_ops

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2009-2011 Edward d'Auvergne                                   # 
   4  #                                                                             # 
   5  # This file is part of the program relax.                                     # 
   6  #                                                                             # 
   7  # relax is free software; you can redistribute it and/or modify               # 
   8  # it under the terms of the GNU General Public License as published by        # 
   9  # the Free Software Foundation; either version 2 of the License, or           # 
  10  # (at your option) any later version.                                         # 
  11  #                                                                             # 
  12  # relax is distributed in the hope that it will be useful,                    # 
  13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
  14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
  15  # GNU General Public License for more details.                                # 
  16  #                                                                             # 
  17  # You should have received a copy of the GNU General Public License           # 
  18  # along with relax; if not, write to the Free Software                        # 
  19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
  20  #                                                                             # 
  21  ############################################################################### 
  22   
  23  # Module docstring. 
  24  """Module for the handling of Frame Order.""" 
  25   
  26  # Dependency check module. 
  27  import dep_check 
  28   
  29  # Python module imports. 
  30  from math import cos, pi, sin, sqrt 
  31  from numpy import cross, dot, sinc, transpose 
  32  from numpy.linalg import norm 
  33  if dep_check.scipy_module: 
  34      from scipy.integrate import quad 
  35   
  36  # relax module imports. 
  37  from float import isNaN 
  38  from maths_fns import order_parameters 
  39  from maths_fns.coord_transform import spherical_to_cartesian 
  40  from maths_fns.kronecker_product import kron_prod, transpose_23 
  41  from maths_fns.pseudo_ellipse import pec 
  42  from maths_fns.rotation_matrix import euler_to_R_zyz, two_vect_to_R 
  43   
  44   
45 -def compile_1st_matrix_pseudo_ellipse(matrix, theta_x, theta_y, sigma_max):
46 """Generate the 1st degree Frame Order matrix for the pseudo-ellipse. 47 48 @param matrix: The Frame Order matrix, 1st degree to be populated. 49 @type matrix: numpy 3D, rank-2 array 50 @param theta_x: The cone opening angle along x. 51 @type theta_x: float 52 @param theta_y: The cone opening angle along y. 53 @type theta_y: float 54 @param sigma_max: The maximum torsion angle. 55 @type sigma_max: float 56 """ 57 58 # The surface area normalisation factor. 59 fact = 1.0 / (2.0 * sigma_max * pec(theta_x, theta_y)) 60 61 # Numerical integration of phi of each element. 62 matrix[0, 0] = fact * quad(part_int_daeg1_pseudo_ellipse_xx, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0] 63 matrix[1, 1] = fact * quad(part_int_daeg1_pseudo_ellipse_yy, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0] 64 matrix[2, 2] = fact * quad(part_int_daeg1_pseudo_ellipse_zz, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]
65 66
67 -def compile_2nd_matrix_free_rotor(matrix, R, z_axis, axis, theta_axis, phi_axis):
68 """Generate the rotated 2nd degree Frame Order matrix for the free rotor model. 69 70 The rotor axis is assumed to be parallel to the z-axis in the eigenframe. 71 72 73 @param matrix: The Frame Order matrix, 2nd degree to be populated. 74 @type matrix: numpy 9D, rank-2 array 75 @param R: The rotation matrix to be populated. 76 @type R: numpy 3D, rank-2 array 77 @param z_axis: The molecular frame z-axis from which the rotor axis is rotated from. 78 @type z_axis: numpy 3D, rank-1 array 79 @param axis: The storage structure for the axis. 80 @type axis: numpy 3D, rank-1 array 81 @param theta_axis: The axis polar angle. 82 @type theta_axis: float 83 @param phi_axis: The axis azimuthal angle. 84 @type phi_axis: float 85 """ 86 87 # Zeros. 88 for i in range(9): 89 for j in range(9): 90 matrix[i, j] = 0.0 91 92 # Diagonal. 93 matrix[0, 0] = 0.5 94 matrix[1, 1] = 0.5 95 matrix[3, 3] = 0.5 96 matrix[4, 4] = 0.5 97 matrix[8, 8] = 1 98 99 # Off diagonal set 1. 100 matrix[0, 4] = matrix[4, 0] = 0.5 101 102 # Off diagonal set 2. 103 matrix[1, 3] = matrix[3, 1] = -0.5 104 105 # Generate the cone axis from the spherical angles. 106 spherical_to_cartesian([1.0, theta_axis, phi_axis], axis) 107 108 # Average position rotation. 109 two_vect_to_R(z_axis, axis, R) 110 111 # Rotate and return the frame order matrix. 112 return rotate_daeg(matrix, R)
113 114
115 -def compile_2nd_matrix_iso_cone(matrix, R, eigen_alpha, eigen_beta, eigen_gamma, cone_theta, sigma_max):
116 """Generate the rotated 2nd degree Frame Order matrix for the isotropic cone. 117 118 The cone axis is assumed to be parallel to the z-axis in the eigenframe. 119 120 @param matrix: The Frame Order matrix, 2nd degree to be populated. 121 @type matrix: numpy 9D, rank-2 array 122 @param R: The rotation matrix to be populated. 123 @type R: numpy 3D, rank-2 array 124 @param eigen_alpha: The eigenframe rotation alpha Euler angle. 125 @type eigen_alpha: float 126 @param eigen_beta: The eigenframe rotation beta Euler angle. 127 @type eigen_beta: float 128 @param eigen_gamma: The eigenframe rotation gamma Euler angle. 129 @type eigen_gamma: float 130 @param cone_theta: The cone opening angle. 131 @type cone_theta: float 132 @param sigma_max: The maximum torsion angle. 133 @type sigma_max: float 134 """ 135 136 # Populate the Frame Order matrix in the eigenframe. 137 populate_2nd_eigenframe_iso_cone(matrix, cone_theta, sigma_max) 138 139 # Average position rotation. 140 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, R) 141 142 # Rotate and return the frame order matrix. 143 return rotate_daeg(matrix, R)
144 145
146 -def compile_2nd_matrix_iso_cone_free_rotor(matrix, R, z_axis, cone_axis, theta_axis, phi_axis, s1):
147 """Generate the rotated 2nd degree Frame Order matrix for the free rotor isotropic cone. 148 149 The cone axis is assumed to be parallel to the z-axis in the eigenframe. In this model, the three order parameters are defined as:: 150 151 S1 = S2, 152 S3 = 0 153 154 155 @param matrix: The Frame Order matrix, 2nd degree to be populated. 156 @type matrix: numpy 9D, rank-2 array 157 @param R: The rotation matrix to be populated. 158 @type R: numpy 3D, rank-2 array 159 @param z_axis: The molecular frame z-axis from which the cone axis is rotated from. 160 @type z_axis: numpy 3D, rank-1 array 161 @param cone_axis: The storage structure for the cone axis. 162 @type cone_axis: numpy 3D, rank-1 array 163 @param theta_axis: The cone axis polar angle. 164 @type theta_axis: float 165 @param phi_axis: The cone axis azimuthal angle. 166 @type phi_axis: float 167 @param s1: The cone order parameter. 168 @type s1: float 169 """ 170 171 # Generate the cone axis from the spherical angles. 172 spherical_to_cartesian([1.0, theta_axis, phi_axis], cone_axis) 173 174 # Populate the Frame Order matrix in the eigenframe. 175 populate_2nd_eigenframe_iso_cone_free_rotor(matrix, s1) 176 177 # Average position rotation. 178 two_vect_to_R(z_axis, cone_axis, R) 179 180 # Rotate and return the frame order matrix. 181 return rotate_daeg(matrix, R)
182 183
184 -def compile_2nd_matrix_iso_cone_torsionless(matrix, R, z_axis, cone_axis, theta_axis, phi_axis, cone_theta):
185 """Generate the rotated 2nd degree Frame Order matrix for the torsionless isotropic cone. 186 187 The cone axis is assumed to be parallel to the z-axis in the eigenframe. 188 189 190 @param matrix: The Frame Order matrix, 2nd degree to be populated. 191 @type matrix: numpy 9D, rank-2 array 192 @param R: The rotation matrix to be populated. 193 @type R: numpy 3D, rank-2 array 194 @param z_axis: The molecular frame z-axis from which the cone axis is rotated from. 195 @type z_axis: numpy 3D, rank-1 array 196 @param cone_axis: The storage structure for the cone axis. 197 @type cone_axis: numpy 3D, rank-1 array 198 @param theta_axis: The cone axis polar angle. 199 @type theta_axis: float 200 @param phi_axis: The cone axis azimuthal angle. 201 @type phi_axis: float 202 @param cone_theta: The cone opening angle. 203 @type cone_theta: float 204 """ 205 206 # Zeros. 207 for i in range(9): 208 for j in range(9): 209 matrix[i, j] = 0.0 210 211 # Repetitive trig calculations. 212 cos_tmax = cos(cone_theta) 213 cos_tmax2 = cos_tmax**2 214 215 # Diagonal. 216 matrix[0, 0] = (3.0*cos_tmax2 + 6.0*cos_tmax + 15.0) / 24.0 217 matrix[1, 1] = (cos_tmax2 + 10.0*cos_tmax + 13.0) / 24.0 218 matrix[2, 2] = (4.0*cos_tmax2 + 10.0*cos_tmax + 10.0) / 24.0 219 matrix[3, 3] = matrix[1, 1] 220 matrix[4, 4] = matrix[0, 0] 221 matrix[5, 5] = matrix[2, 2] 222 matrix[6, 6] = matrix[2, 2] 223 matrix[7, 7] = matrix[2, 2] 224 matrix[8, 8] = (cos_tmax2 + cos_tmax + 1.0) / 3.0 225 226 # Off diagonal set 1. 227 matrix[0, 4] = matrix[4, 0] = (cos_tmax2 - 2.0*cos_tmax + 1.0) / 24.0 228 matrix[0, 8] = matrix[8, 0] = -(cos_tmax2 + cos_tmax - 2.0) / 6.0 229 matrix[4, 8] = matrix[8, 4] = matrix[0, 8] 230 231 # Off diagonal set 2. 232 matrix[1, 3] = matrix[3, 1] = matrix[0, 4] 233 matrix[2, 6] = matrix[6, 2] = -matrix[0, 8] 234 matrix[5, 7] = matrix[7, 5] = -matrix[0, 8] 235 236 # Generate the cone axis from the spherical angles. 237 spherical_to_cartesian([1.0, theta_axis, phi_axis], cone_axis) 238 239 # Average position rotation. 240 two_vect_to_R(z_axis, cone_axis, R) 241 242 # Rotate and return the frame order matrix. 243 return rotate_daeg(matrix, R)
244 245
246 -def compile_2nd_matrix_pseudo_ellipse(matrix, R, eigen_alpha, eigen_beta, eigen_gamma, theta_x, theta_y, sigma_max):
247 """Generate the 2nd degree Frame Order matrix for the pseudo-ellipse. 248 249 @param matrix: The Frame Order matrix, 2nd degree to be populated. 250 @type matrix: numpy 9D, rank-2 array 251 @param R: The rotation matrix to be populated. 252 @type R: numpy 3D, rank-2 array 253 @param eigen_alpha: The eigenframe rotation alpha Euler angle. 254 @type eigen_alpha: float 255 @param eigen_beta: The eigenframe rotation beta Euler angle. 256 @type eigen_beta: float 257 @param eigen_gamma: The eigenframe rotation gamma Euler angle. 258 @type eigen_gamma: float 259 @param theta_x: The cone opening angle along x. 260 @type theta_x: float 261 @param theta_y: The cone opening angle along y. 262 @type theta_y: float 263 @param sigma_max: The maximum torsion angle. 264 @type sigma_max: float 265 """ 266 267 # The surface area normalisation factor. 268 fact = 12.0 * pec(theta_x, theta_y) 269 270 # Invert. 271 if fact == 0.0: 272 fact = 1e100 273 else: 274 fact = 1.0 / fact 275 276 # Sigma_max part. 277 if sigma_max == 0.0: 278 fact2 = 1e100 279 else: 280 fact2 = fact / (2.0 * sigma_max) 281 282 # Diagonal. 283 matrix[0, 0] = fact * (4.0*pi*(sinc(2.0*sigma_max/pi) + 2.0) + quad(part_int_daeg2_pseudo_ellipse_00, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 284 matrix[1, 1] = fact * (4.0*pi*sinc(2.0*sigma_max/pi) + quad(part_int_daeg2_pseudo_ellipse_11, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 285 matrix[2, 2] = fact * 2.0*sinc(sigma_max/pi) * (5.0*pi - quad(part_int_daeg2_pseudo_ellipse_22, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 286 matrix[3, 3] = matrix[1, 1] 287 matrix[4, 4] = fact * (4.0*pi*(sinc(2.0*sigma_max/pi) + 2.0) + quad(part_int_daeg2_pseudo_ellipse_44, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 288 matrix[5, 5] = fact * 2.0*sinc(sigma_max/pi) * (5.0*pi - quad(part_int_daeg2_pseudo_ellipse_55, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 289 matrix[6, 6] = matrix[2, 2] 290 matrix[7, 7] = matrix[5, 5] 291 matrix[8, 8] = 4.0 * fact * (2.0*pi - quad(part_int_daeg2_pseudo_ellipse_88, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 292 293 # Off diagonal set 1. 294 matrix[0, 4] = fact * (4.0*pi*(2.0 - sinc(2.0*sigma_max/pi)) + quad(part_int_daeg2_pseudo_ellipse_04, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 295 matrix[4, 0] = fact * (4.0*pi*(2.0 - sinc(2.0*sigma_max/pi)) + quad(part_int_daeg2_pseudo_ellipse_40, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 296 matrix[0, 8] = 4.0 * fact * (2.0*pi - quad(part_int_daeg2_pseudo_ellipse_08, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 297 matrix[8, 0] = fact * (8.0*pi + quad(part_int_daeg2_pseudo_ellipse_80, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 298 matrix[4, 8] = 4.0 * fact * (2.0*pi - quad(part_int_daeg2_pseudo_ellipse_48, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 299 matrix[8, 4] = fact * (8.0*pi - quad(part_int_daeg2_pseudo_ellipse_84, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 300 301 # Off diagonal set 2. 302 matrix[1, 3] = matrix[3, 1] = fact * (4.0*pi*sinc(2.0*sigma_max/pi) + quad(part_int_daeg2_pseudo_ellipse_13, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 303 matrix[2, 6] = matrix[6, 2] = -fact * 4.0 * sinc(sigma_max/pi) * (2.0*pi + quad(part_int_daeg2_pseudo_ellipse_26, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 304 matrix[5, 7] = matrix[7, 5] = -fact * 4.0 * sinc(sigma_max/pi) * (2.0*pi + quad(part_int_daeg2_pseudo_ellipse_57, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]) 305 306 # Average position rotation. 307 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, R) 308 309 # Rotate and return the frame order matrix. 310 return rotate_daeg(matrix, R)
311 312
313 -def compile_2nd_matrix_pseudo_ellipse_free_rotor(matrix, R, eigen_alpha, eigen_beta, eigen_gamma, theta_x, theta_y):
314 """Generate the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 315 316 @param matrix: The Frame Order matrix, 2nd degree to be populated. 317 @type matrix: numpy 9D, rank-2 array 318 @param R: The rotation matrix to be populated. 319 @type R: numpy 3D, rank-2 array 320 @param eigen_alpha: The eigenframe rotation alpha Euler angle. 321 @type eigen_alpha: float 322 @param eigen_beta: The eigenframe rotation beta Euler angle. 323 @type eigen_beta: float 324 @param eigen_gamma: The eigenframe rotation gamma Euler angle. 325 @type eigen_gamma: float 326 @param theta_x: The cone opening angle along x. 327 @type theta_x: float 328 @param theta_y: The cone opening angle along y. 329 @type theta_y: float 330 """ 331 332 # The surface area normalisation factor. 333 fact = 1.0 / (6.0 * pec(theta_x, theta_y)) 334 335 # Diagonal. 336 matrix[0, 0] = fact * (4.0*pi - quad(part_int_daeg2_pseudo_ellipse_free_rotor_00, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 337 matrix[1, 1] = matrix[3, 3] = fact * 3.0/2.0 * quad(part_int_daeg2_pseudo_ellipse_free_rotor_11, -pi, pi, args=(theta_x, theta_y), full_output=1)[0] 338 matrix[4, 4] = fact * (4.0*pi - quad(part_int_daeg2_pseudo_ellipse_free_rotor_44, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 339 matrix[8, 8] = fact * (4.0*pi - 2.0*quad(part_int_daeg2_pseudo_ellipse_free_rotor_88, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 340 341 # Off diagonal set 1. 342 matrix[0, 4] = matrix[0, 0] 343 matrix[4, 0] = matrix[4, 4] 344 matrix[0, 8] = fact * (4.0*pi + quad(part_int_daeg2_pseudo_ellipse_free_rotor_08, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 345 matrix[8, 0] = fact * (4.0*pi + quad(part_int_daeg2_pseudo_ellipse_free_rotor_80, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 346 matrix[4, 8] = fact * (4.0*pi + quad(part_int_daeg2_pseudo_ellipse_free_rotor_48, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 347 matrix[8, 4] = matrix[8, 0] 348 349 # Off diagonal set 2. 350 matrix[1, 3] = matrix[3, 1] = -matrix[1, 1] 351 352 # Average position rotation. 353 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, R) 354 355 # Rotate and return the frame order matrix. 356 return rotate_daeg(matrix, R)
357 358
359 -def compile_2nd_matrix_pseudo_ellipse_torsionless(matrix, R, eigen_alpha, eigen_beta, eigen_gamma, theta_x, theta_y):
360 """Generate the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 361 362 @param matrix: The Frame Order matrix, 2nd degree to be populated. 363 @type matrix: numpy 9D, rank-2 array 364 @param R: The rotation matrix to be populated. 365 @type R: numpy 3D, rank-2 array 366 @param eigen_alpha: The eigenframe rotation alpha Euler angle. 367 @type eigen_alpha: float 368 @param eigen_beta: The eigenframe rotation beta Euler angle. 369 @type eigen_beta: float 370 @param eigen_gamma: The eigenframe rotation gamma Euler angle. 371 @type eigen_gamma: float 372 @param theta_x: The cone opening angle along x. 373 @type theta_x: float 374 @param theta_y: The cone opening angle along y. 375 @type theta_y: float 376 """ 377 378 # The surface area normalisation factor. 379 fact = 1.0 / (6.0 * pec(theta_x, theta_y)) 380 381 # Diagonal. 382 matrix[0, 0] = fact * (6.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_00, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 383 matrix[1, 1] = fact * (2.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_11, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 384 matrix[2, 2] = fact * (5.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_22, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 385 matrix[3, 3] = matrix[1, 1] 386 matrix[4, 4] = fact * (6.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_44, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 387 matrix[5, 5] = fact * (5.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_55, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 388 matrix[6, 6] = matrix[2, 2] 389 matrix[7, 7] = matrix[5, 5] 390 matrix[8, 8] = fact * quad(part_int_daeg2_pseudo_ellipse_torsionless_88, -pi, pi, args=(theta_x, theta_y), full_output=1)[0] 391 392 # Off diagonal set 1. 393 matrix[0, 4] = matrix[4, 0] = fact * (2.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_04, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 394 matrix[0, 8] = matrix[8, 0] = fact * (4.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_08, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 395 matrix[4, 8] = matrix[8, 4] = fact * (4.0*pi + quad(part_int_daeg2_pseudo_ellipse_torsionless_48, -pi, pi, args=(theta_x, theta_y), full_output=1)[0]) 396 397 # Off diagonal set 2. 398 matrix[1, 3] = matrix[3, 1] = matrix[0, 4] 399 matrix[2, 6] = matrix[6, 2] = -matrix[0, 8] 400 matrix[5, 7] = matrix[7, 5] = -matrix[4, 8] 401 402 # Average position rotation. 403 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, R) 404 405 # Rotate and return the frame order matrix. 406 return rotate_daeg(matrix, R)
407 408
409 -def compile_2nd_matrix_rotor(matrix, R, z_axis, axis, theta_axis, phi_axis, smax):
410 """Generate the rotated 2nd degree Frame Order matrix for the rotor model. 411 412 The cone axis is assumed to be parallel to the z-axis in the eigenframe. 413 414 415 @param matrix: The Frame Order matrix, 2nd degree to be populated. 416 @type matrix: numpy 9D, rank-2 array 417 @param R: The rotation matrix to be populated. 418 @type R: numpy 3D, rank-2 array 419 @param z_axis: The molecular frame z-axis from which the rotor axis is rotated from. 420 @type z_axis: numpy 3D, rank-1 array 421 @param axis: The storage structure for the axis. 422 @type axis: numpy 3D, rank-1 array 423 @param theta_axis: The axis polar angle. 424 @type theta_axis: float 425 @param phi_axis: The axis azimuthal angle. 426 @type phi_axis: float 427 @param smax: The maximum torsion angle. 428 @type smax: float 429 """ 430 431 # Zeros. 432 for i in range(9): 433 for j in range(9): 434 matrix[i, j] = 0.0 435 436 # Repetitive trig calculations. 437 sinc_smax = sinc(smax/pi) 438 sinc_2smax = sinc(2.0*smax/pi) 439 440 # Diagonal. 441 matrix[0, 0] = (sinc_2smax + 1.0) / 2.0 442 matrix[1, 1] = matrix[0, 0] 443 matrix[2, 2] = sinc_smax 444 matrix[3, 3] = matrix[0, 0] 445 matrix[4, 4] = matrix[0, 0] 446 matrix[5, 5] = matrix[2, 2] 447 matrix[6, 6] = matrix[2, 2] 448 matrix[7, 7] = matrix[2, 2] 449 matrix[8, 8] = 1.0 450 451 # Off diagonal set 1. 452 matrix[0, 4] = matrix[4, 0] = -(sinc_2smax - 1.0) / 2.0 453 454 # Off diagonal set 2. 455 matrix[1, 3] = matrix[3, 1] = -matrix[0, 4] 456 457 # Generate the cone axis from the spherical angles. 458 spherical_to_cartesian([1.0, theta_axis, phi_axis], axis) 459 460 # Average position rotation. 461 two_vect_to_R(z_axis, axis, R) 462 463 # Rotate and return the frame order matrix. 464 return rotate_daeg(matrix, R)
465 466
467 -def daeg_to_rotational_superoperator(daeg, Rsuper):
468 """Convert the frame order matrix (daeg) to the rotational superoperator. 469 470 @param daeg: The second degree frame order matrix, daeg. This must be in the Kronecker product layout. 471 @type daeg: numpy 9D, rank-2 array or numpy 3D, rank-4 array 472 @param Rsuper: The rotational superoperator structure to be populated. 473 @type Rsuper: numpy 5D, rank-2 array 474 """ 475 476 # First perform the T23 transpose. 477 transpose_23(daeg) 478 479 # Convert to rank-4. 480 orig_shape = daeg.shape 481 daeg.shape = (3, 3, 3, 3) 482 483 # First column of the superoperator. 484 Rsuper[0, 0] = daeg[0, 0, 0, 0] - daeg[2, 0, 2, 0] 485 Rsuper[1, 0] = daeg[0, 1, 0, 1] - daeg[2, 1, 2, 1] 486 Rsuper[2, 0] = daeg[0, 0, 0, 1] - daeg[2, 0, 2, 1] 487 Rsuper[3, 0] = daeg[0, 0, 0, 2] - daeg[2, 0, 2, 2] 488 Rsuper[4, 0] = daeg[0, 1, 0, 2] - daeg[2, 1, 2, 2] 489 490 # Second column of the superoperator. 491 Rsuper[0, 1] = daeg[1, 0, 1, 0] - daeg[2, 0, 2, 0] 492 Rsuper[1, 1] = daeg[1, 1, 1, 1] - daeg[2, 1, 2, 1] 493 Rsuper[2, 1] = daeg[1, 0, 1, 1] - daeg[2, 0, 2, 1] 494 Rsuper[3, 1] = daeg[1, 0, 1, 2] - daeg[2, 0, 2, 2] 495 Rsuper[4, 1] = daeg[1, 1, 1, 2] - daeg[2, 1, 2, 2] 496 497 # Third column of the superoperator. 498 Rsuper[0, 2] = daeg[0, 0, 1, 0] + daeg[1, 0, 0, 0] 499 Rsuper[1, 2] = daeg[0, 1, 1, 1] + daeg[1, 1, 0, 1] 500 Rsuper[2, 2] = daeg[0, 0, 1, 1] + daeg[1, 0, 0, 1] 501 Rsuper[3, 2] = daeg[0, 0, 1, 2] + daeg[1, 0, 0, 2] 502 Rsuper[4, 2] = daeg[0, 1, 1, 2] + daeg[1, 1, 0, 2] 503 504 # Fourth column of the superoperator. 505 Rsuper[0, 3] = daeg[0, 0, 2, 0] + daeg[2, 0, 0, 0] 506 Rsuper[1, 3] = daeg[0, 1, 2, 1] + daeg[2, 1, 0, 1] 507 Rsuper[2, 3] = daeg[0, 0, 2, 1] + daeg[2, 0, 0, 1] 508 Rsuper[3, 3] = daeg[0, 0, 2, 2] + daeg[2, 0, 0, 2] 509 Rsuper[4, 3] = daeg[0, 1, 2, 2] + daeg[2, 1, 0, 2] 510 511 # Fifth column of the superoperator. 512 Rsuper[0, 4] = daeg[1, 0, 2, 0] + daeg[2, 0, 1, 0] 513 Rsuper[1, 4] = daeg[1, 1, 2, 1] + daeg[2, 1, 1, 1] 514 Rsuper[2, 4] = daeg[1, 0, 2, 1] + daeg[2, 0, 1, 1] 515 Rsuper[3, 4] = daeg[1, 0, 2, 2] + daeg[2, 0, 1, 2] 516 Rsuper[4, 4] = daeg[1, 1, 2, 2] + daeg[2, 1, 1, 2] 517 518 # Revert the shape. 519 daeg.shape = orig_shape 520 521 # Undo the T23 transpose. 522 transpose_23(daeg)
523 524
525 -def part_int_daeg1_pseudo_ellipse_xx(phi, x, y, smax):
526 """The theta-sigma partial integral of the 1st degree Frame Order matrix element xx for the pseudo-ellipse. 527 528 @param phi: The azimuthal tilt-torsion angle. 529 @type phi: float 530 @param x: The cone opening angle along x. 531 @type x: float 532 @param y: The cone opening angle along y. 533 @type y: float 534 @param smax: The maximum torsion angle. 535 @type smax: float 536 @return: The theta-sigma partial integral. 537 @rtype: float 538 """ 539 540 # Theta max. 541 tmax = tmax_pseudo_ellipse(phi, x, y) 542 543 # The theta-sigma integral. 544 return sin(smax) * (2 * (1 - cos(tmax)) * sin(phi)**2 + cos(phi)**2 * sin(tmax)**2)
545 546
547 -def part_int_daeg1_pseudo_ellipse_yy(phi, x, y, smax):
548 """The theta-sigma partial integral of the 1st degree Frame Order matrix element yy for the pseudo-ellipse. 549 550 @param phi: The azimuthal tilt-torsion angle. 551 @type phi: float 552 @param x: The cone opening angle along x. 553 @type x: float 554 @param y: The cone opening angle along y. 555 @type y: float 556 @param smax: The maximum torsion angle. 557 @type smax: float 558 @return: The theta-sigma partial integral. 559 @rtype: float 560 """ 561 562 # Theta max. 563 tmax = tmax_pseudo_ellipse(phi, x, y) 564 565 # The theta-sigma integral. 566 return sin(smax) * (2.0 * cos(phi)**2 * (1.0 - cos(tmax)) + sin(phi)**2 * sin(tmax)**2)
567 568
569 -def part_int_daeg1_pseudo_ellipse_zz(phi, x, y, smax):
570 """The theta-sigma partial integral of the 1st degree Frame Order matrix element zz for the pseudo-ellipse. 571 572 @param phi: The azimuthal tilt-torsion angle. 573 @type phi: float 574 @param x: The cone opening angle along x. 575 @type x: float 576 @param y: The cone opening angle along y. 577 @type y: float 578 @param smax: The maximum torsion angle. 579 @type smax: float 580 @return: The theta-sigma partial integral. 581 @rtype: float 582 """ 583 584 # Theta max. 585 tmax = tmax_pseudo_ellipse(phi, x, y) 586 587 # The theta-sigma integral. 588 return smax * sin(tmax)**2
589 590
591 -def part_int_daeg2_pseudo_ellipse_00(phi, x, y, smax):
592 """The theta-sigma partial integral of the 2nd degree Frame Order matrix element 11 for the pseudo-ellipse. 593 594 @param phi: The azimuthal tilt-torsion angle. 595 @type phi: float 596 @param x: The cone opening angle along x. 597 @type x: float 598 @param y: The cone opening angle along y. 599 @type y: float 600 @param smax: The maximum torsion angle. 601 @type smax: float 602 @return: The theta-sigma partial integral. 603 @rtype: float 604 """ 605 606 # Theta max. 607 tmax = tmax_pseudo_ellipse(phi, x, y) 608 609 # Repetitive trig. 610 cos_tmax = cos(tmax) 611 sin_tmax2 = sin(tmax)**2 612 cos_phi2 = cos(phi)**2 613 614 # Components. 615 a = sinc(2.0*smax/pi) * (2.0 * sin_tmax2 * cos_phi2 * ((2.0*cos_phi2 - 1.0)*cos(tmax) - 6.0*(cos_phi2 - 1.0)) - 2.0*cos_tmax * (2.0*cos_phi2*(4.0*cos_phi2 - 5.0) + 3.0)) 616 b = 2.0*cos_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax 617 618 # Return the theta-sigma integral. 619 return a + b
620 621
622 -def part_int_daeg2_pseudo_ellipse_04(phi, x, y, smax):
623 """The theta-sigma partial integral of the 2nd degree Frame Order matrix element 22 for the pseudo-ellipse. 624 625 @param phi: The azimuthal tilt-torsion angle. 626 @type phi: float 627 @param x: The cone opening angle along x. 628 @type x: float 629 @param y: The cone opening angle along y. 630 @type y: float 631 @param smax: The maximum torsion angle. 632 @type smax: float 633 @return: The theta-sigma partial integral. 634 @rtype: float 635 """ 636 637 # Theta max. 638 tmax = tmax_pseudo_ellipse(phi, x, y) 639 640 # Repetitive trig. 641 cos_tmax = cos(tmax) 642 sin_tmax2 = sin(tmax)**2 643 cos_phi2 = cos(phi)**2 644 sin_phi2 = sin(phi)**2 645 646 # Components. 647 a = sinc(2.0*smax/pi) * (2.0 * sin_tmax2 * cos_phi2 * ((2.0*sin_phi2 - 1.0)*cos(tmax) - 6.0*sin_phi2) + 2.0*cos_tmax * (2.0*cos_phi2*(4.0*cos_phi2 - 5.0) + 3.0)) 648 b = 2.0*cos_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax 649 650 # Return the theta-sigma integral. 651 return a + b
652 653
654 -def part_int_daeg2_pseudo_ellipse_08(phi, x, y, smax):
655 """The theta-sigma partial integral of the 2nd degree Frame Order matrix element 33 for the pseudo-ellipse. 656 657 @param phi: The azimuthal tilt-torsion angle. 658 @type phi: float 659 @param x: The cone opening angle along x. 660 @type x: float 661 @param y: The cone opening angle along y. 662 @type y: float 663 @param smax: The maximum torsion angle. 664 @type smax: float 665 @return: The theta-sigma partial integral. 666 @rtype: float 667 """ 668 669 # Theta max. 670 tmax = tmax_pseudo_ellipse(phi, x, y) 671 672 # The theta-sigma integral. 673 return cos(tmax) * cos(phi)**2 * (sin(tmax)**2 + 2.0)
674 675
676 -def part_int_daeg2_pseudo_ellipse_11(phi, x, y, smax):
677 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 678 679 @param phi: The azimuthal tilt-torsion angle. 680 @type phi: float 681 @param x: The cone opening angle along x. 682 @type x: float 683 @param y: The cone opening angle along y. 684 @type y: float 685 @param smax: The maximum torsion angle. 686 @type smax: float 687 @return: The theta-sigma partial integral. 688 @rtype: float 689 """ 690 691 # Theta max. 692 tmax = tmax_pseudo_ellipse(phi, x, y) 693 694 # Repetitive trig. 695 cos_tmax = cos(tmax) 696 cos_phi2 = cos(phi)**2 697 sin_phi2 = sin(phi)**2 698 699 # The integral. 700 a = sinc(2.0*smax/pi) * ((4.0*cos_phi2*((1.0 - cos_phi2)*cos_tmax + 3.0*(cos_phi2-1)) + 3.0)*sin(tmax)**2 - 16.0*cos_phi2*sin_phi2*cos_tmax) + 3.0*sin(tmax)**2 701 702 # The theta-sigma integral. 703 return a
704 705
706 -def part_int_daeg2_pseudo_ellipse_13(phi, x, y, smax):
707 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 708 709 @param phi: The azimuthal tilt-torsion angle. 710 @type phi: float 711 @param x: The cone opening angle along x. 712 @type x: float 713 @param y: The cone opening angle along y. 714 @type y: float 715 @param smax: The maximum torsion angle. 716 @type smax: float 717 @return: The theta-sigma partial integral. 718 @rtype: float 719 """ 720 721 # Theta max. 722 tmax = tmax_pseudo_ellipse(phi, x, y) 723 724 # Repetitive trig. 725 cos_tmax = cos(tmax) 726 sin_tmax2 = sin(tmax)**2 727 sinc_2smax = sinc(2.0*smax/pi) 728 cos_sin_phi2 = cos(phi)**2*sin(phi)**2 729 730 # The theta-sigma integral. 731 return sinc_2smax * (sin_tmax2 * (4*cos_sin_phi2*cos_tmax - 12*cos_sin_phi2 + 3) - 16*cos_sin_phi2*cos_tmax) - 3.0*sin_tmax2
732 733
734 -def part_int_daeg2_pseudo_ellipse_22(phi, x, y, smax):
735 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 736 737 @param phi: The azimuthal tilt-torsion angle. 738 @type phi: float 739 @param x: The cone opening angle along x. 740 @type x: float 741 @param y: The cone opening angle along y. 742 @type y: float 743 @param smax: The maximum torsion angle. 744 @type smax: float 745 @return: The theta-sigma partial integral. 746 @rtype: float 747 """ 748 749 # Theta max. 750 tmax = tmax_pseudo_ellipse(phi, x, y) 751 752 # Repetitive trig. 753 cos_tmax = cos(tmax) 754 cos_phi2 = cos(phi)**2 755 756 # Components. 757 a = 2.0*cos_phi2*cos_tmax**3 + 3.0*(1.0 - cos_phi2)*cos_tmax**2 758 759 # Return the theta-sigma integral. 760 return a
761 762
763 -def part_int_daeg2_pseudo_ellipse_26(phi, x, y, smax):
764 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 765 766 @param phi: The azimuthal tilt-torsion angle. 767 @type phi: float 768 @param x: The cone opening angle along x. 769 @type x: float 770 @param y: The cone opening angle along y. 771 @type y: float 772 @param smax: The maximum torsion angle. 773 @type smax: float 774 @return: The theta-sigma partial integral. 775 @rtype: float 776 """ 777 778 # Theta max. 779 tmax = tmax_pseudo_ellipse(phi, x, y) 780 781 # The theta-sigma integral. 782 return cos(phi)**2 * (cos(tmax)**3 - 3.0*cos(tmax))
783 784
785 -def part_int_daeg2_pseudo_ellipse_40(phi, x, y, smax):
786 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 787 788 @param phi: The azimuthal tilt-torsion angle. 789 @type phi: float 790 @param x: The cone opening angle along x. 791 @type x: float 792 @param y: The cone opening angle along y. 793 @type y: float 794 @param smax: The maximum torsion angle. 795 @type smax: float 796 @return: The theta-sigma partial integral. 797 @rtype: float 798 """ 799 800 # Theta max. 801 tmax = tmax_pseudo_ellipse(phi, x, y) 802 803 # Repetitive trig. 804 cos_tmax = cos(tmax) 805 sin_tmax2 = sin(tmax)**2 806 cos_phi2 = cos(phi)**2 807 sin_phi2 = sin(phi)**2 808 809 # Components. 810 a = sinc(2.0*smax/pi) * (2.0 * sin_tmax2 * sin_phi2 * ((2.0*cos_phi2 - 1.0)*cos(tmax) - 6.0*cos_phi2) + 2.0*cos_tmax * (2.0*sin_phi2*(4.0*sin_phi2 - 5.0) + 3.0)) 811 b = 2.0*sin_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax 812 813 # Return the theta-sigma integral. 814 return a + b
815 816
817 -def part_int_daeg2_pseudo_ellipse_44(phi, x, y, smax):
818 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 819 820 @param phi: The azimuthal tilt-torsion angle. 821 @type phi: float 822 @param x: The cone opening angle along x. 823 @type x: float 824 @param y: The cone opening angle along y. 825 @type y: float 826 @param smax: The maximum torsion angle. 827 @type smax: float 828 @return: The theta-sigma partial integral. 829 @rtype: float 830 """ 831 832 # Theta max. 833 tmax = tmax_pseudo_ellipse(phi, x, y) 834 835 # Repetitive trig. 836 cos_tmax = cos(tmax) 837 sin_tmax2 = sin(tmax)**2 838 cos_phi2 = cos(phi)**2 839 sin_phi2 = sin(phi)**2 840 841 # Components. 842 a = sinc(2.0*smax/pi) * (2.0 * sin_tmax2 * sin_phi2 * ((2.0*sin_phi2 - 1.0)*cos(tmax) + 6.0*cos_phi2) - 2.0*cos_tmax * (2.0*sin_phi2*(4.0*sin_phi2 - 5.0) + 3.0)) 843 b = 2.0*sin_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax 844 845 # Return the theta-sigma integral. 846 return a + b
847 848
849 -def part_int_daeg2_pseudo_ellipse_48(phi, x, y, smax):
850 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 851 852 @param phi: The azimuthal tilt-torsion angle. 853 @type phi: float 854 @param x: The cone opening angle along x. 855 @type x: float 856 @param y: The cone opening angle along y. 857 @type y: float 858 @param smax: The maximum torsion angle. 859 @type smax: float 860 @return: The theta-sigma partial integral. 861 @rtype: float 862 """ 863 864 # Theta max. 865 tmax = tmax_pseudo_ellipse(phi, x, y) 866 867 # The theta-sigma integral. 868 return cos(tmax) * sin(phi)**2 * (sin(tmax)**2 + 2.0)
869 870
871 -def part_int_daeg2_pseudo_ellipse_55(phi, x, y, smax):
872 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 873 874 @param phi: The azimuthal tilt-torsion angle. 875 @type phi: float 876 @param x: The cone opening angle along x. 877 @type x: float 878 @param y: The cone opening angle along y. 879 @type y: float 880 @param smax: The maximum torsion angle. 881 @type smax: float 882 @return: The theta-sigma partial integral. 883 @rtype: float 884 """ 885 886 # Theta max. 887 tmax = tmax_pseudo_ellipse(phi, x, y) 888 889 # Repetitive trig. 890 cos_tmax = cos(tmax) 891 sin_phi2 = sin(phi)**2 892 893 # Return the theta-sigma integral. 894 return 2.0*sin_phi2*cos_tmax**3 + 3.0*(1.0 - sin_phi2)*cos_tmax**2
895 896
897 -def part_int_daeg2_pseudo_ellipse_57(phi, x, y, smax):
898 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 899 900 @param phi: The azimuthal tilt-torsion angle. 901 @type phi: float 902 @param x: The cone opening angle along x. 903 @type x: float 904 @param y: The cone opening angle along y. 905 @type y: float 906 @param smax: The maximum torsion angle. 907 @type smax: float 908 @return: The theta-sigma partial integral. 909 @rtype: float 910 """ 911 912 # Theta max. 913 tmax = tmax_pseudo_ellipse(phi, x, y) 914 915 # The theta-sigma integral. 916 return sin(phi)**2 * (cos(tmax)**3 - 3.0*cos(tmax))
917 918
919 -def part_int_daeg2_pseudo_ellipse_80(phi, x, y, smax):
920 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 921 922 @param phi: The azimuthal tilt-torsion angle. 923 @type phi: float 924 @param x: The cone opening angle along x. 925 @type x: float 926 @param y: The cone opening angle along y. 927 @type y: float 928 @param smax: The maximum torsion angle. 929 @type smax: float 930 @return: The theta-sigma partial integral. 931 @rtype: float 932 """ 933 934 # Theta max. 935 tmax = tmax_pseudo_ellipse(phi, x, y) 936 937 # Repetitive trig. 938 cos_tmax = cos(tmax) 939 sin_tmax2 = sin(tmax)**2 940 cos_phi2 = cos(phi)**2 941 942 # The theta-sigma integral. 943 return sinc(2.0*smax/pi) * (2.0*(1.0 - 2.0*cos_phi2)*cos_tmax*(sin_tmax2 + 2.0)) + 2.0*cos_tmax**3 - 6.0*cos_tmax
944 945
946 -def part_int_daeg2_pseudo_ellipse_84(phi, x, y, smax):
947 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 948 949 @param phi: The azimuthal tilt-torsion angle. 950 @type phi: float 951 @param x: The cone opening angle along x. 952 @type x: float 953 @param y: The cone opening angle along y. 954 @type y: float 955 @param smax: The maximum torsion angle. 956 @type smax: float 957 @return: The theta-sigma partial integral. 958 @rtype: float 959 """ 960 961 # Theta max. 962 tmax = tmax_pseudo_ellipse(phi, x, y) 963 964 # Repetitive trig. 965 cos_tmax = cos(tmax) 966 sin_tmax2 = sin(tmax)**2 967 cos_phi2 = cos(phi)**2 968 969 # The theta-sigma integral. 970 return sinc(2.0*smax/pi) * (2.0*(1.0 - 2.0*cos_phi2)*cos_tmax*(sin_tmax2 + 2.0)) - 2.0*cos_tmax**3 + 6.0*cos_tmax
971 972
973 -def part_int_daeg2_pseudo_ellipse_88(phi, x, y, smax):
974 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse. 975 976 @param phi: The azimuthal tilt-torsion angle. 977 @type phi: float 978 @param x: The cone opening angle along x. 979 @type x: float 980 @param y: The cone opening angle along y. 981 @type y: float 982 @param smax: The maximum torsion angle. 983 @type smax: float 984 @return: The theta-sigma partial integral. 985 @rtype: float 986 """ 987 988 # Theta max. 989 tmax = tmax_pseudo_ellipse(phi, x, y) 990 991 # The theta-sigma integral. 992 return cos(tmax)**3
993 994
995 -def part_int_daeg2_pseudo_ellipse_free_rotor_00(phi, x, y):
996 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 997 998 @param phi: The azimuthal tilt-torsion angle. 999 @type phi: float 1000 @param x: The cone opening angle along x. 1001 @type x: float 1002 @param y: The cone opening angle along y. 1003 @type y: float 1004 @return: The theta-sigma partial integral. 1005 @rtype: float 1006 """ 1007 1008 # Theta max. 1009 tmax = tmax_pseudo_ellipse(phi, x, y) 1010 1011 # The theta-sigma integral. 1012 return cos(phi)**2*cos(tmax)**3 + 3.0*sin(phi)**2*cos(tmax)
1013 1014
1015 -def part_int_daeg2_pseudo_ellipse_free_rotor_08(phi, x, y):
1016 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 1017 1018 @param phi: The azimuthal tilt-torsion angle. 1019 @type phi: float 1020 @param x: The cone opening angle along x. 1021 @type x: float 1022 @param y: The cone opening angle along y. 1023 @type y: float 1024 @return: The theta-sigma partial integral. 1025 @rtype: float 1026 """ 1027 1028 # Theta max. 1029 tmax = tmax_pseudo_ellipse(phi, x, y) 1030 1031 # The theta-sigma integral. 1032 return cos(phi)**2*(2.0*cos(tmax)**3 - 6.0*cos(tmax))
1033 1034
1035 -def part_int_daeg2_pseudo_ellipse_free_rotor_11(phi, x, y):
1036 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 1037 1038 @param phi: The azimuthal tilt-torsion angle. 1039 @type phi: float 1040 @param x: The cone opening angle along x. 1041 @type x: float 1042 @param y: The cone opening angle along y. 1043 @type y: float 1044 @return: The theta-sigma partial integral. 1045 @rtype: float 1046 """ 1047 1048 # Theta max. 1049 tmax = tmax_pseudo_ellipse(phi, x, y) 1050 1051 # The theta-sigma integral. 1052 return sin(tmax)**2
1053 1054
1055 -def part_int_daeg2_pseudo_ellipse_free_rotor_44(phi, x, y):
1056 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 1057 1058 @param phi: The azimuthal tilt-torsion angle. 1059 @type phi: float 1060 @param x: The cone opening angle along x. 1061 @type x: float 1062 @param y: The cone opening angle along y. 1063 @type y: float 1064 @return: The theta-sigma partial integral. 1065 @rtype: float 1066 """ 1067 1068 # Theta max. 1069 tmax = tmax_pseudo_ellipse(phi, x, y) 1070 1071 # The theta-sigma integral. 1072 return sin(phi)**2*cos(tmax)**3 + 3*cos(phi)**2*cos(tmax)
1073 1074
1075 -def part_int_daeg2_pseudo_ellipse_free_rotor_48(phi, x, y):
1076 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 1077 1078 @param phi: The azimuthal tilt-torsion angle. 1079 @type phi: float 1080 @param x: The cone opening angle along x. 1081 @type x: float 1082 @param y: The cone opening angle along y. 1083 @type y: float 1084 @return: The theta-sigma partial integral. 1085 @rtype: float 1086 """ 1087 1088 # Theta max. 1089 tmax = tmax_pseudo_ellipse(phi, x, y) 1090 1091 # The theta-sigma integral. 1092 return sin(phi)**2*(2.0*cos(tmax)**3 - 6.0*cos(tmax))
1093 1094
1095 -def part_int_daeg2_pseudo_ellipse_free_rotor_80(phi, x, y):
1096 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 1097 1098 @param phi: The azimuthal tilt-torsion angle. 1099 @type phi: float 1100 @param x: The cone opening angle along x. 1101 @type x: float 1102 @param y: The cone opening angle along y. 1103 @type y: float 1104 @return: The theta-sigma partial integral. 1105 @rtype: float 1106 """ 1107 1108 # Theta max. 1109 tmax = tmax_pseudo_ellipse(phi, x, y) 1110 1111 # The theta-sigma integral. 1112 return cos(tmax)**3 - 3.0*cos(tmax)
1113 1114
1115 -def part_int_daeg2_pseudo_ellipse_free_rotor_88(phi, x, y):
1116 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the free rotor pseudo-ellipse. 1117 1118 @param phi: The azimuthal tilt-torsion angle. 1119 @type phi: float 1120 @param x: The cone opening angle along x. 1121 @type x: float 1122 @param y: The cone opening angle along y. 1123 @type y: float 1124 @return: The theta-sigma partial integral. 1125 @rtype: float 1126 """ 1127 1128 # Theta max. 1129 tmax = tmax_pseudo_ellipse(phi, x, y) 1130 1131 # The theta-sigma integral. 1132 return cos(tmax)**3
1133 1134
1135 -def part_int_daeg2_pseudo_ellipse_torsionless_00(phi, x, y):
1136 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1137 1138 @param phi: The azimuthal tilt-torsion angle. 1139 @type phi: float 1140 @param x: The cone opening angle along x. 1141 @type x: float 1142 @param y: The cone opening angle along y. 1143 @type y: float 1144 @return: The theta partial integral. 1145 @rtype: float 1146 """ 1147 1148 # Theta max. 1149 tmax = tmax_pseudo_ellipse(phi, x, y) 1150 1151 # The theta integral. 1152 return (2*cos(phi)**4*cos(tmax) + 6*cos(phi)**2*sin(phi)**2)*sin(tmax)**2 - (6*sin(phi)**4 + 2*cos(phi)**4)*cos(tmax)
1153 1154
1155 -def part_int_daeg2_pseudo_ellipse_torsionless_04(phi, x, y):
1156 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1157 1158 @param phi: The azimuthal tilt-torsion angle. 1159 @type phi: float 1160 @param x: The cone opening angle along x. 1161 @type x: float 1162 @param y: The cone opening angle along y. 1163 @type y: float 1164 @return: The theta partial integral. 1165 @rtype: float 1166 """ 1167 1168 # Theta max. 1169 tmax = tmax_pseudo_ellipse(phi, x, y) 1170 1171 # The theta integral. 1172 return (2*cos(phi)**2*sin(phi)**2*cos(tmax) - 6*cos(phi)**2*sin(phi)**2)*sin(tmax)**2 - 8*cos(phi)**2*sin(phi)**2*cos(tmax)
1173 1174
1175 -def part_int_daeg2_pseudo_ellipse_torsionless_08(phi, x, y):
1176 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1177 1178 @param phi: The azimuthal tilt-torsion angle. 1179 @type phi: float 1180 @param x: The cone opening angle along x. 1181 @type x: float 1182 @param y: The cone opening angle along y. 1183 @type y: float 1184 @return: The theta partial integral. 1185 @rtype: float 1186 """ 1187 1188 # Theta max. 1189 tmax = tmax_pseudo_ellipse(phi, x, y) 1190 1191 # The theta integral. 1192 return 2*cos(phi)**2*cos(tmax)**3 - 6*cos(phi)**2*cos(tmax)
1193 1194
1195 -def part_int_daeg2_pseudo_ellipse_torsionless_11(phi, x, y):
1196 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1197 1198 @param phi: The azimuthal tilt-torsion angle. 1199 @type phi: float 1200 @param x: The cone opening angle along x. 1201 @type x: float 1202 @param y: The cone opening angle along y. 1203 @type y: float 1204 @return: The theta partial integral. 1205 @rtype: float 1206 """ 1207 1208 # Theta max. 1209 tmax = tmax_pseudo_ellipse(phi, x, y) 1210 1211 # The theta integral. 1212 return (2*cos(phi)**2*sin(phi)**2*cos(tmax) + 3*sin(phi)**4 + 3*cos(phi)**4)*sin(tmax)**2 - 8*cos(phi)**2*sin(phi)**2*cos(tmax)
1213 1214
1215 -def part_int_daeg2_pseudo_ellipse_torsionless_22(phi, x, y):
1216 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1217 1218 @param phi: The azimuthal tilt-torsion angle. 1219 @type phi: float 1220 @param x: The cone opening angle along x. 1221 @type x: float 1222 @param y: The cone opening angle along y. 1223 @type y: float 1224 @return: The theta partial integral. 1225 @rtype: float 1226 """ 1227 1228 # Theta max. 1229 tmax = tmax_pseudo_ellipse(phi, x, y) 1230 1231 # The theta integral. 1232 return (2*sin(phi)**2 - 2)*cos(tmax)**3 - 3*sin(phi)**2*cos(tmax)**2
1233 1234
1235 -def part_int_daeg2_pseudo_ellipse_torsionless_44(phi, x, y):
1236 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1237 1238 @param phi: The azimuthal tilt-torsion angle. 1239 @type phi: float 1240 @param x: The cone opening angle along x. 1241 @type x: float 1242 @param y: The cone opening angle along y. 1243 @type y: float 1244 @return: The theta partial integral. 1245 @rtype: float 1246 """ 1247 1248 # Theta max. 1249 tmax = tmax_pseudo_ellipse(phi, x, y) 1250 1251 # The theta integral. 1252 return (2*sin(phi)**4*cos(tmax) + 6*cos(phi)**2*sin(phi)**2)*sin(tmax)**2 - (2*sin(phi)**4 + 6*cos(phi)**4)*cos(tmax)
1253 1254
1255 -def part_int_daeg2_pseudo_ellipse_torsionless_48(phi, x, y):
1256 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1257 1258 @param phi: The azimuthal tilt-torsion angle. 1259 @type phi: float 1260 @param x: The cone opening angle along x. 1261 @type x: float 1262 @param y: The cone opening angle along y. 1263 @type y: float 1264 @return: The theta partial integral. 1265 @rtype: float 1266 """ 1267 1268 # Theta max. 1269 tmax = tmax_pseudo_ellipse(phi, x, y) 1270 1271 # The theta integral. 1272 return 2*sin(phi)**2*cos(tmax)**3 - 6*sin(phi)**2*cos(tmax)
1273 1274
1275 -def part_int_daeg2_pseudo_ellipse_torsionless_55(phi, x, y):
1276 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1277 1278 @param phi: The azimuthal tilt-torsion angle. 1279 @type phi: float 1280 @param x: The cone opening angle along x. 1281 @type x: float 1282 @param y: The cone opening angle along y. 1283 @type y: float 1284 @return: The theta partial integral. 1285 @rtype: float 1286 """ 1287 1288 # Theta max. 1289 tmax = tmax_pseudo_ellipse(phi, x, y) 1290 1291 # The theta integral. 1292 return (2*cos(phi)**2 - 2)*cos(tmax)**3 - 3*cos(phi)**2*cos(tmax)**2
1293 1294
1295 -def part_int_daeg2_pseudo_ellipse_torsionless_88(phi, x, y):
1296 """The theta partial integral of the 2nd degree Frame Order matrix for the torsionless pseudo-ellipse. 1297 1298 @param phi: The azimuthal tilt-torsion angle. 1299 @type phi: float 1300 @param x: The cone opening angle along x. 1301 @type x: float 1302 @param y: The cone opening angle along y. 1303 @type y: float 1304 @return: The theta partial integral. 1305 @rtype: float 1306 """ 1307 1308 # Theta max. 1309 tmax = tmax_pseudo_ellipse(phi, x, y) 1310 1311 # The theta integral. 1312 return 2 - 2*cos(tmax)**3
1313 1314
1315 -def populate_1st_eigenframe_iso_cone(matrix, angle):
1316 """Populate the 1st degree Frame Order matrix in the eigenframe for an isotropic cone. 1317 1318 The cone axis is assumed to be parallel to the z-axis in the eigenframe. 1319 1320 @param matrix: The Frame Order matrix, 1st degree. 1321 @type matrix: numpy 3D, rank-2 array 1322 @param angle: The cone angle. 1323 @type angle: float 1324 """ 1325 1326 # Zeros. 1327 for i in range(3): 1328 for j in range(3): 1329 matrix[i, j] = 0.0 1330 1331 # The c33 element. 1332 matrix[2, 2] = (cos(angle) + 1.0) / 2.0
1333 1334
1335 -def populate_2nd_eigenframe_iso_cone(matrix, tmax, smax):
1336 """Populate the 2nd degree Frame Order matrix in the eigenframe for the isotropic cone. 1337 1338 The cone axis is assumed to be parallel to the z-axis in the eigenframe. 1339 1340 1341 @param matrix: The Frame Order matrix, 2nd degree. 1342 @type matrix: numpy 9D, rank-2 array 1343 @param tmax: The cone opening angle. 1344 @type tmax: float 1345 @param smax: The maximum torsion angle. 1346 @type smax: float 1347 """ 1348 1349 # Zeros. 1350 for i in range(9): 1351 for j in range(9): 1352 matrix[i, j] = 0.0 1353 1354 # Repetitive trig calculations. 1355 sinc_smax = sinc(smax/pi) 1356 sinc_2smax = sinc(2.0*smax/pi) 1357 cos_tmax = cos(tmax) 1358 cos_tmax2 = cos_tmax**2 1359 1360 # Larger factors. 1361 fact_sinc_2smax = sinc_2smax*(cos_tmax2 + 4.0*cos_tmax + 7.0) / 24.0 1362 fact_cos_tmax2 = (cos_tmax2 + cos_tmax + 4.0) / 12.0 1363 fact_cos_tmax = (cos_tmax + 1.0) / 4.0 1364 1365 # Diagonal. 1366 matrix[0, 0] = fact_sinc_2smax + fact_cos_tmax2 1367 matrix[1, 1] = fact_sinc_2smax + fact_cos_tmax 1368 matrix[2, 2] = sinc_smax * (2.0*cos_tmax2 + 5.0*cos_tmax + 5.0) / 12.0 1369 matrix[3, 3] = matrix[1, 1] 1370 matrix[4, 4] = matrix[0, 0] 1371 matrix[5, 5] = matrix[2, 2] 1372 matrix[6, 6] = matrix[2, 2] 1373 matrix[7, 7] = matrix[2, 2] 1374 matrix[8, 8] = (cos_tmax2 + cos_tmax + 1.0) / 3.0 1375 1376 # Off diagonal set 1. 1377 matrix[0, 4] = matrix[4, 0] = -fact_sinc_2smax + fact_cos_tmax2 1378 matrix[0, 8] = matrix[8, 0] = -(cos_tmax2 + cos_tmax - 2.0) / 6.0 1379 matrix[4, 8] = matrix[8, 4] = matrix[0, 8] 1380 1381 # Off diagonal set 2. 1382 matrix[1, 3] = matrix[3, 1] = fact_sinc_2smax - fact_cos_tmax 1383 matrix[2, 6] = matrix[6, 2] = sinc_smax * (cos_tmax2 + cos_tmax - 2.0) / 6.0 1384 matrix[5, 7] = matrix[7, 5] = matrix[2, 6]
1385 1386
1387 -def populate_2nd_eigenframe_iso_cone_free_rotor(matrix, s1):
1388 """Populate the 2nd degree Frame Order matrix in the eigenframe for the free rotor isotropic cone. 1389 1390 The cone axis is assumed to be parallel to the z-axis in the eigenframe. In this model, the three order parameters are defined as:: 1391 1392 S1 = S2, 1393 S3 = 0 1394 1395 This is in the Kronecker product form. 1396 1397 1398 @param matrix: The Frame Order matrix, 2nd degree. 1399 @type matrix: numpy 9D, rank-2 array 1400 @param s1: The cone order parameter. 1401 @type s1: float 1402 """ 1403 1404 # Zeros. 1405 for i in range(9): 1406 for j in range(9): 1407 matrix[i, j] = 0.0 1408 1409 # The c11^2, c22^2, c12^2, and c21^2 elements. 1410 matrix[0, 0] = matrix[4, 4] = (s1 + 2.0) / 6.0 1411 matrix[0, 4] = matrix[4, 0] = matrix[0, 0] 1412 1413 # The c33^2 element. 1414 matrix[8, 8] = (2.0*s1 + 1.0) / 3.0 1415 1416 # The c13^2, c31^2, c23^2, c32^2 elements. 1417 matrix[0, 8] = matrix[8, 0] = (1.0 - s1) / 3.0 1418 matrix[4, 8] = matrix[8, 4] = matrix[0, 8] 1419 1420 # Calculate the cone angle. 1421 theta = order_parameters.iso_cone_S_to_theta(s1) 1422 1423 # The c11.c22 and c12.c21 elements. 1424 matrix[1, 1] = matrix[3, 3] = (cos(theta) + 1.0) / 4.0 1425 matrix[1, 3] = matrix[3, 1] = -matrix[1, 1]
1426 1427
1428 -def reduce_alignment_tensor(D, A, red_tensor):
1429 """Calculate the reduction in the alignment tensor caused by the Frame Order matrix. 1430 1431 This is both the forward rotation notation and Kronecker product arrangement. 1432 1433 @param D: The Frame Order matrix, 2nd degree to be populated. 1434 @type D: numpy 9D, rank-2 array 1435 @param A: The full alignment tensor in {Axx, Ayy, Axy, Axz, Ayz} notation. 1436 @type A: numpy 5D, rank-1 array 1437 @param red_tensor: The structure in {Axx, Ayy, Axy, Axz, Ayz} notation to place the reduced 1438 alignment tensor. 1439 @type red_tensor: numpy 5D, rank-1 array 1440 """ 1441 1442 # The reduced tensor element A0. 1443 red_tensor[0] = (D[0, 0] - D[0, 8])*A[0] 1444 red_tensor[0] = red_tensor[0] + (D[0, 4] - D[0, 8])*A[1] 1445 red_tensor[0] = red_tensor[0] + (D[0, 1] + D[0, 3])*A[2] 1446 red_tensor[0] = red_tensor[0] + (D[0, 2] + D[0, 6])*A[3] 1447 red_tensor[0] = red_tensor[0] + (D[0, 5] + D[0, 7])*A[4] 1448 1449 # The reduced tensor element A1. 1450 red_tensor[1] = (D[4, 0] - D[4, 8])*A[0] 1451 red_tensor[1] = red_tensor[1] + (D[4, 4] - D[4, 8])*A[1] 1452 red_tensor[1] = red_tensor[1] + (D[4, 1] + D[4, 3])*A[2] 1453 red_tensor[1] = red_tensor[1] + (D[4, 2] + D[4, 6])*A[3] 1454 red_tensor[1] = red_tensor[1] + (D[4, 5] + D[4, 7])*A[4] 1455 1456 # The reduced tensor element A2. 1457 red_tensor[2] = (D[1, 0] - D[1, 8])*A[0] 1458 red_tensor[2] = red_tensor[2] + (D[1, 4] - D[1, 8])*A[1] 1459 red_tensor[2] = red_tensor[2] + (D[1, 1] + D[1, 3])*A[2] 1460 red_tensor[2] = red_tensor[2] + (D[1, 2] + D[1, 6])*A[3] 1461 red_tensor[2] = red_tensor[2] + (D[1, 5] + D[1, 7])*A[4] 1462 1463 # The reduced tensor element A3. 1464 red_tensor[3] = (D[2, 0] - D[2, 8])*A[0] 1465 red_tensor[3] = red_tensor[3] + (D[2, 4] - D[2, 8])*A[1] 1466 red_tensor[3] = red_tensor[3] + (D[2, 1] + D[2, 3])*A[2] 1467 red_tensor[3] = red_tensor[3] + (D[2, 2] + D[2, 6])*A[3] 1468 red_tensor[3] = red_tensor[3] + (D[2, 5] + D[2, 7])*A[4] 1469 1470 # The reduced tensor element A4. 1471 red_tensor[4] = (D[5, 0] - D[5, 8])*A[0] 1472 red_tensor[4] = red_tensor[4] + (D[5, 4] - D[5, 8])*A[1] 1473 red_tensor[4] = red_tensor[4] + (D[5, 1] + D[5, 3])*A[2] 1474 red_tensor[4] = red_tensor[4] + (D[5, 2] + D[5, 6])*A[3] 1475 red_tensor[4] = red_tensor[4] + (D[5, 5] + D[5, 7])*A[4]
1476 1477
1478 -def reduce_alignment_tensor_symmetric(D, A, red_tensor):
1479 """Calculate the reduction in the alignment tensor caused by the Frame Order matrix. 1480 1481 This is both the forward rotation notation and Kronecker product arrangement. This simplification is due to the symmetry in motion of the pseudo-elliptic and isotropic cones. All element of the frame order matrix where an index appears only once are zero. 1482 1483 @param D: The Frame Order matrix, 2nd degree to be populated. 1484 @type D: numpy 9D, rank-2 array 1485 @param A: The full alignment tensor in {Axx, Ayy, Axy, Axz, Ayz} notation. 1486 @type A: numpy 5D, rank-1 array 1487 @param red_tensor: The structure in {Axx, Ayy, Axy, Axz, Ayz} notation to place the reduced 1488 alignment tensor. 1489 @type red_tensor: numpy 5D, rank-1 array 1490 """ 1491 1492 # The reduced tensor elements. 1493 red_tensor[0] = (D[0, 0] - D[0, 8])*A[0] + (D[0, 4] - D[0, 8])*A[1] 1494 red_tensor[1] = (D[4, 0] - D[4, 8])*A[0] + (D[4, 4] - D[4, 8])*A[1] 1495 red_tensor[2] = (D[1, 1] + D[1, 3])*A[2] 1496 red_tensor[3] = (D[2, 2] + D[2, 6])*A[3] 1497 red_tensor[4] = (D[5, 5] + D[5, 7])*A[4]
1498 1499
1500 -def rotate_daeg(matrix, R):
1501 """Rotate the given frame order matrix. 1502 1503 It is assumed that the frame order matrix is in the Kronecker product form. 1504 1505 1506 @param matrix: The Frame Order matrix, 2nd degree to be populated. 1507 @type matrix: numpy 9D, rank-2 array 1508 @param R: The rotation matrix to be populated. 1509 @type R: numpy 3D, rank-2 array 1510 """ 1511 1512 # The outer product of R. 1513 R_kron = kron_prod(R, R) 1514 1515 # Rotate. 1516 matrix_rot = dot(R_kron, dot(matrix, transpose(R_kron))) 1517 1518 # Return the matrix. 1519 return matrix_rot
1520 1521
1522 -def tmax_pseudo_ellipse(phi, theta_x, theta_y):
1523 """The pseudo-ellipse tilt-torsion polar angle. 1524 1525 @param phi: The azimuthal tilt-torsion angle. 1526 @type phi: float 1527 @param theta_x: The cone opening angle along x. 1528 @type theta_x: float 1529 @param theta_y: The cone opening angle along y. 1530 @type theta_y: float 1531 @return: The theta max angle for the given phi angle. 1532 @rtype: float 1533 """ 1534 1535 # Zero points. 1536 if theta_x == 0.0: 1537 return 0.0 1538 elif theta_y == 0.0: 1539 return 0.0 1540 1541 # Return the maximum angle. 1542 return theta_x * theta_y / sqrt((cos(phi)*theta_y)**2 + (sin(phi)*theta_x)**2)
1543