1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for the pseudo-ellipse frame order model."""
24
25
26 import dep_check
27
28
29 from math import cos, pi, sin, sqrt
30 from numpy import sinc
31 if dep_check.scipy_module:
32 from scipy.integrate import quad, tplquad
33
34
35 from lib.geometry.pec import pec
36 from lib.frame_order.matrix_ops import pcs_pivot_motion_full, pcs_pivot_motion_full_qrint, rotate_daeg
37
38
40 """Generate the 1st degree Frame Order matrix for the pseudo-ellipse.
41
42 @param matrix: The Frame Order matrix, 1st degree to be populated.
43 @type matrix: numpy 3D, rank-2 array
44 @param theta_x: The cone opening angle along x.
45 @type theta_x: float
46 @param theta_y: The cone opening angle along y.
47 @type theta_y: float
48 @param sigma_max: The maximum torsion angle.
49 @type sigma_max: float
50 """
51
52
53 fact = 1.0 / (2.0 * sigma_max * pec(theta_x, theta_y))
54
55
56 matrix[0, 0] = fact * quad(part_int_daeg1_pseudo_ellipse_xx, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]
57 matrix[1, 1] = fact * quad(part_int_daeg1_pseudo_ellipse_yy, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]
58 matrix[2, 2] = fact * quad(part_int_daeg1_pseudo_ellipse_zz, -pi, pi, args=(theta_x, theta_y, sigma_max), full_output=1)[0]
59
60
62 """Generate the 2nd degree Frame Order matrix for the pseudo-ellipse.
63
64 @param matrix: The Frame Order matrix, 2nd degree to be populated.
65 @type matrix: numpy 9D, rank-2 array
66 @param Rx2_eigen: The Kronecker product of the eigenframe rotation matrix with itself.
67 @type Rx2_eigen: numpy 9D, rank-2 array
68 @param theta_x: The cone opening angle along x.
69 @type theta_x: float
70 @param theta_y: The cone opening angle along y.
71 @type theta_y: float
72 @param sigma_max: The maximum torsion angle.
73 @type sigma_max: float
74 """
75
76
77 fact = 12.0 * pec(theta_x, theta_y)
78
79
80 if fact == 0.0:
81 fact = 1e100
82 else:
83 fact = 1.0 / fact
84
85
86 if sigma_max == 0.0:
87 fact2 = 1e100
88 else:
89 fact2 = fact / (2.0 * sigma_max)
90
91
92 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])
93 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])
94 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])
95 matrix[3, 3] = matrix[1, 1]
96 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])
97 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])
98 matrix[6, 6] = matrix[2, 2]
99 matrix[7, 7] = matrix[5, 5]
100 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])
101
102
103 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])
104 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])
105 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])
106 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])
107 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])
108 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])
109
110
111 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])
112 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])
113 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])
114
115
116 return rotate_daeg(matrix, Rx2_eigen)
117
118
120 """The theta-sigma partial integral of the 1st degree Frame Order matrix element xx for the pseudo-ellipse.
121
122 @param phi: The azimuthal tilt-torsion angle.
123 @type phi: float
124 @param x: The cone opening angle along x.
125 @type x: float
126 @param y: The cone opening angle along y.
127 @type y: float
128 @param smax: The maximum torsion angle.
129 @type smax: float
130 @return: The theta-sigma partial integral.
131 @rtype: float
132 """
133
134
135 tmax = tmax_pseudo_ellipse(phi, x, y)
136
137
138 return sin(smax) * (2 * (1 - cos(tmax)) * sin(phi)**2 + cos(phi)**2 * sin(tmax)**2)
139
140
142 """The theta-sigma partial integral of the 1st degree Frame Order matrix element yy for the pseudo-ellipse.
143
144 @param phi: The azimuthal tilt-torsion angle.
145 @type phi: float
146 @param x: The cone opening angle along x.
147 @type x: float
148 @param y: The cone opening angle along y.
149 @type y: float
150 @param smax: The maximum torsion angle.
151 @type smax: float
152 @return: The theta-sigma partial integral.
153 @rtype: float
154 """
155
156
157 tmax = tmax_pseudo_ellipse(phi, x, y)
158
159
160 return sin(smax) * (2.0 * cos(phi)**2 * (1.0 - cos(tmax)) + sin(phi)**2 * sin(tmax)**2)
161
162
164 """The theta-sigma partial integral of the 1st degree Frame Order matrix element zz for the pseudo-ellipse.
165
166 @param phi: The azimuthal tilt-torsion angle.
167 @type phi: float
168 @param x: The cone opening angle along x.
169 @type x: float
170 @param y: The cone opening angle along y.
171 @type y: float
172 @param smax: The maximum torsion angle.
173 @type smax: float
174 @return: The theta-sigma partial integral.
175 @rtype: float
176 """
177
178
179 tmax = tmax_pseudo_ellipse(phi, x, y)
180
181
182 return smax * sin(tmax)**2
183
184
186 """The theta-sigma partial integral of the 2nd degree Frame Order matrix element 11 for the pseudo-ellipse.
187
188 @param phi: The azimuthal tilt-torsion angle.
189 @type phi: float
190 @param x: The cone opening angle along x.
191 @type x: float
192 @param y: The cone opening angle along y.
193 @type y: float
194 @param smax: The maximum torsion angle.
195 @type smax: float
196 @return: The theta-sigma partial integral.
197 @rtype: float
198 """
199
200
201 tmax = tmax_pseudo_ellipse(phi, x, y)
202
203
204 cos_tmax = cos(tmax)
205 sin_tmax2 = sin(tmax)**2
206 cos_phi2 = cos(phi)**2
207
208
209 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))
210 b = 2.0*cos_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax
211
212
213 return a + b
214
215
217 """The theta-sigma partial integral of the 2nd degree Frame Order matrix element 22 for the pseudo-ellipse.
218
219 @param phi: The azimuthal tilt-torsion angle.
220 @type phi: float
221 @param x: The cone opening angle along x.
222 @type x: float
223 @param y: The cone opening angle along y.
224 @type y: float
225 @param smax: The maximum torsion angle.
226 @type smax: float
227 @return: The theta-sigma partial integral.
228 @rtype: float
229 """
230
231
232 tmax = tmax_pseudo_ellipse(phi, x, y)
233
234
235 cos_tmax = cos(tmax)
236 sin_tmax2 = sin(tmax)**2
237 cos_phi2 = cos(phi)**2
238 sin_phi2 = sin(phi)**2
239
240
241 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))
242 b = 2.0*cos_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax
243
244
245 return a + b
246
247
249 """The theta-sigma partial integral of the 2nd degree Frame Order matrix element 33 for the pseudo-ellipse.
250
251 @param phi: The azimuthal tilt-torsion angle.
252 @type phi: float
253 @param x: The cone opening angle along x.
254 @type x: float
255 @param y: The cone opening angle along y.
256 @type y: float
257 @param smax: The maximum torsion angle.
258 @type smax: float
259 @return: The theta-sigma partial integral.
260 @rtype: float
261 """
262
263
264 tmax = tmax_pseudo_ellipse(phi, x, y)
265
266
267 return cos(tmax) * cos(phi)**2 * (sin(tmax)**2 + 2.0)
268
269
271 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
272
273 @param phi: The azimuthal tilt-torsion angle.
274 @type phi: float
275 @param x: The cone opening angle along x.
276 @type x: float
277 @param y: The cone opening angle along y.
278 @type y: float
279 @param smax: The maximum torsion angle.
280 @type smax: float
281 @return: The theta-sigma partial integral.
282 @rtype: float
283 """
284
285
286 tmax = tmax_pseudo_ellipse(phi, x, y)
287
288
289 cos_tmax = cos(tmax)
290 cos_phi2 = cos(phi)**2
291 sin_phi2 = sin(phi)**2
292
293
294 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
295
296
297 return a
298
299
301 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
302
303 @param phi: The azimuthal tilt-torsion angle.
304 @type phi: float
305 @param x: The cone opening angle along x.
306 @type x: float
307 @param y: The cone opening angle along y.
308 @type y: float
309 @param smax: The maximum torsion angle.
310 @type smax: float
311 @return: The theta-sigma partial integral.
312 @rtype: float
313 """
314
315
316 tmax = tmax_pseudo_ellipse(phi, x, y)
317
318
319 cos_tmax = cos(tmax)
320 sin_tmax2 = sin(tmax)**2
321 sinc_2smax = sinc(2.0*smax/pi)
322 cos_sin_phi2 = cos(phi)**2*sin(phi)**2
323
324
325 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
326
327
329 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
330
331 @param phi: The azimuthal tilt-torsion angle.
332 @type phi: float
333 @param x: The cone opening angle along x.
334 @type x: float
335 @param y: The cone opening angle along y.
336 @type y: float
337 @param smax: The maximum torsion angle.
338 @type smax: float
339 @return: The theta-sigma partial integral.
340 @rtype: float
341 """
342
343
344 tmax = tmax_pseudo_ellipse(phi, x, y)
345
346
347 cos_tmax = cos(tmax)
348 cos_phi2 = cos(phi)**2
349
350
351 a = 2.0*cos_phi2*cos_tmax**3 + 3.0*(1.0 - cos_phi2)*cos_tmax**2
352
353
354 return a
355
356
358 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
359
360 @param phi: The azimuthal tilt-torsion angle.
361 @type phi: float
362 @param x: The cone opening angle along x.
363 @type x: float
364 @param y: The cone opening angle along y.
365 @type y: float
366 @param smax: The maximum torsion angle.
367 @type smax: float
368 @return: The theta-sigma partial integral.
369 @rtype: float
370 """
371
372
373 tmax = tmax_pseudo_ellipse(phi, x, y)
374
375
376 return cos(phi)**2 * (cos(tmax)**3 - 3.0*cos(tmax))
377
378
380 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
381
382 @param phi: The azimuthal tilt-torsion angle.
383 @type phi: float
384 @param x: The cone opening angle along x.
385 @type x: float
386 @param y: The cone opening angle along y.
387 @type y: float
388 @param smax: The maximum torsion angle.
389 @type smax: float
390 @return: The theta-sigma partial integral.
391 @rtype: float
392 """
393
394
395 tmax = tmax_pseudo_ellipse(phi, x, y)
396
397
398 cos_tmax = cos(tmax)
399 sin_tmax2 = sin(tmax)**2
400 cos_phi2 = cos(phi)**2
401 sin_phi2 = sin(phi)**2
402
403
404 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))
405 b = 2.0*sin_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax
406
407
408 return a + b
409
410
412 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
413
414 @param phi: The azimuthal tilt-torsion angle.
415 @type phi: float
416 @param x: The cone opening angle along x.
417 @type x: float
418 @param y: The cone opening angle along y.
419 @type y: float
420 @param smax: The maximum torsion angle.
421 @type smax: float
422 @return: The theta-sigma partial integral.
423 @rtype: float
424 """
425
426
427 tmax = tmax_pseudo_ellipse(phi, x, y)
428
429
430 cos_tmax = cos(tmax)
431 sin_tmax2 = sin(tmax)**2
432 cos_phi2 = cos(phi)**2
433 sin_phi2 = sin(phi)**2
434
435
436 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))
437 b = 2.0*sin_phi2*cos_tmax*(sin_tmax2 + 2.0) - 6.0*cos_tmax
438
439
440 return a + b
441
442
444 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
445
446 @param phi: The azimuthal tilt-torsion angle.
447 @type phi: float
448 @param x: The cone opening angle along x.
449 @type x: float
450 @param y: The cone opening angle along y.
451 @type y: float
452 @param smax: The maximum torsion angle.
453 @type smax: float
454 @return: The theta-sigma partial integral.
455 @rtype: float
456 """
457
458
459 tmax = tmax_pseudo_ellipse(phi, x, y)
460
461
462 return cos(tmax) * sin(phi)**2 * (sin(tmax)**2 + 2.0)
463
464
466 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
467
468 @param phi: The azimuthal tilt-torsion angle.
469 @type phi: float
470 @param x: The cone opening angle along x.
471 @type x: float
472 @param y: The cone opening angle along y.
473 @type y: float
474 @param smax: The maximum torsion angle.
475 @type smax: float
476 @return: The theta-sigma partial integral.
477 @rtype: float
478 """
479
480
481 tmax = tmax_pseudo_ellipse(phi, x, y)
482
483
484 cos_tmax = cos(tmax)
485 sin_phi2 = sin(phi)**2
486
487
488 return 2.0*sin_phi2*cos_tmax**3 + 3.0*(1.0 - sin_phi2)*cos_tmax**2
489
490
492 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
493
494 @param phi: The azimuthal tilt-torsion angle.
495 @type phi: float
496 @param x: The cone opening angle along x.
497 @type x: float
498 @param y: The cone opening angle along y.
499 @type y: float
500 @param smax: The maximum torsion angle.
501 @type smax: float
502 @return: The theta-sigma partial integral.
503 @rtype: float
504 """
505
506
507 tmax = tmax_pseudo_ellipse(phi, x, y)
508
509
510 return sin(phi)**2 * (cos(tmax)**3 - 3.0*cos(tmax))
511
512
514 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
515
516 @param phi: The azimuthal tilt-torsion angle.
517 @type phi: float
518 @param x: The cone opening angle along x.
519 @type x: float
520 @param y: The cone opening angle along y.
521 @type y: float
522 @param smax: The maximum torsion angle.
523 @type smax: float
524 @return: The theta-sigma partial integral.
525 @rtype: float
526 """
527
528
529 tmax = tmax_pseudo_ellipse(phi, x, y)
530
531
532 cos_tmax = cos(tmax)
533 sin_tmax2 = sin(tmax)**2
534 cos_phi2 = cos(phi)**2
535
536
537 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
538
539
541 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
542
543 @param phi: The azimuthal tilt-torsion angle.
544 @type phi: float
545 @param x: The cone opening angle along x.
546 @type x: float
547 @param y: The cone opening angle along y.
548 @type y: float
549 @param smax: The maximum torsion angle.
550 @type smax: float
551 @return: The theta-sigma partial integral.
552 @rtype: float
553 """
554
555
556 tmax = tmax_pseudo_ellipse(phi, x, y)
557
558
559 cos_tmax = cos(tmax)
560 sin_tmax2 = sin(tmax)**2
561 cos_phi2 = cos(phi)**2
562
563
564 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
565
566
568 """The theta-sigma partial integral of the 2nd degree Frame Order matrix for the pseudo-ellipse.
569
570 @param phi: The azimuthal tilt-torsion angle.
571 @type phi: float
572 @param x: The cone opening angle along x.
573 @type x: float
574 @param y: The cone opening angle along y.
575 @type y: float
576 @param smax: The maximum torsion angle.
577 @type smax: float
578 @return: The theta-sigma partial integral.
579 @rtype: float
580 """
581
582
583 tmax = tmax_pseudo_ellipse(phi, x, y)
584
585
586 return cos(tmax)**3
587
588
589 -def pcs_numeric_int_pseudo_ellipse(theta_x=None, theta_y=None, sigma_max=None, c=None, r_pivot_atom=None, r_ln_pivot=None, A=None, R_eigen=None, RT_eigen=None, Ri_prime=None):
590 """Determine the averaged PCS value via numerical integration.
591
592 @keyword theta_x: The x-axis half cone angle.
593 @type theta_x: float
594 @keyword theta_y: The y-axis half cone angle.
595 @type theta_y: float
596 @keyword sigma_max: The maximum torsion angle.
597 @type sigma_max: float
598 @keyword c: The PCS constant (without the interatomic distance and in Angstrom units).
599 @type c: float
600 @keyword r_pivot_atom: The pivot point to atom vector.
601 @type r_pivot_atom: numpy rank-1, 3D array
602 @keyword r_ln_pivot: The lanthanide position to pivot point vector.
603 @type r_ln_pivot: numpy rank-1, 3D array
604 @keyword A: The full alignment tensor of the non-moving domain.
605 @type A: numpy rank-2, 3D array
606 @keyword R_eigen: The eigenframe rotation matrix.
607 @type R_eigen: numpy rank-2, 3D array
608 @keyword RT_eigen: The transpose of the eigenframe rotation matrix (for faster calculations).
609 @type RT_eigen: numpy rank-2, 3D array
610 @keyword Ri_prime: The empty rotation matrix for the in-frame isotropic cone motion, used to calculate the PCS for each state i in the numerical integration.
611 @type Ri_prime: numpy rank-2, 3D array
612 @return: The averaged PCS value.
613 @rtype: float
614 """
615
616 def pseudo_ellipse(theta, phi):
617 """The pseudo-ellipse wrapper formula."""
618
619 return tmax_pseudo_ellipse(phi, theta_x, theta_y)
620
621
622 result = tplquad(pcs_pivot_motion_full, -sigma_max, sigma_max, lambda phi: -pi, lambda phi: pi, lambda theta, phi: 0.0, pseudo_ellipse, args=(r_pivot_atom, r_ln_pivot, A, R_eigen, RT_eigen, Ri_prime))
623
624
625 SA = 2.0 * sigma_max * pec(theta_x, theta_y)
626
627
628 return c * result[0] / SA
629
630
632 """The pseudo-ellipse tilt-torsion polar angle.
633
634 @param phi: The azimuthal tilt-torsion angle.
635 @type phi: float
636 @param theta_x: The cone opening angle along x.
637 @type theta_x: float
638 @param theta_y: The cone opening angle along y.
639 @type theta_y: float
640 @return: The theta max angle for the given phi angle.
641 @rtype: float
642 """
643
644
645 if theta_x == 0.0:
646 return 0.0
647 elif theta_y == 0.0:
648 return 0.0
649
650
651 return theta_x * theta_y / sqrt((cos(phi)*theta_y)**2 + (sin(phi)*theta_x)**2)
652
653
654 -def pcs_numeric_int_pseudo_ellipse_qrint(points=None, theta_x=None, theta_y=None, sigma_max=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, error_flag=False):
655 """Determine the averaged PCS value via numerical integration.
656
657 @keyword points: The Sobol points in the torsion-tilt angle space.
658 @type points: numpy rank-2, 3D array
659 @keyword theta_x: The x-axis half cone angle.
660 @type theta_x: float
661 @keyword theta_y: The y-axis half cone angle.
662 @type theta_y: float
663 @keyword sigma_max: The maximum torsion angle.
664 @type sigma_max: float
665 @keyword c: The PCS constant (without the interatomic distance and in Angstrom units).
666 @type c: float
667 @keyword full_in_ref_frame: An array of flags specifying if the tensor in the reference frame is the full or reduced tensor.
668 @type full_in_ref_frame: numpy rank-1 array
669 @keyword r_pivot_atom: The pivot point to atom vector.
670 @type r_pivot_atom: numpy rank-1, 3D array
671 @keyword r_pivot_atom_rev: The reversed pivot point to atom vector.
672 @type r_pivot_atom_rev: numpy rank-2, 3D array
673 @keyword r_ln_pivot: The lanthanide position to pivot point vector.
674 @type r_ln_pivot: numpy rank-1, 3D array
675 @keyword A: The full alignment tensor of the non-moving domain.
676 @type A: numpy rank-2, 3D array
677 @keyword R_eigen: The eigenframe rotation matrix.
678 @type R_eigen: numpy rank-2, 3D array
679 @keyword RT_eigen: The transpose of the eigenframe rotation matrix (for faster calculations).
680 @type RT_eigen: numpy rank-2, 3D array
681 @keyword Ri_prime: The empty rotation matrix for the in-frame isotropic cone motion, used to calculate the PCS for each state i in the numerical integration.
682 @type Ri_prime: numpy rank-2, 3D array
683 @keyword pcs_theta: The storage structure for the back-calculated PCS values.
684 @type pcs_theta: numpy rank-2 array
685 @keyword pcs_theta_err: The storage structure for the back-calculated PCS errors.
686 @type pcs_theta_err: numpy rank-2 array
687 @keyword missing_pcs: A structure used to indicate which PCS values are missing.
688 @type missing_pcs: numpy rank-2 array
689 @keyword error_flag: A flag which if True will cause the PCS errors to be estimated and stored in pcs_theta_err.
690 @type error_flag: bool
691 """
692
693
694
695 for i in range(len(pcs_theta)):
696 for j in range(len(pcs_theta[i])):
697 pcs_theta[i, j] = 0.0
698 pcs_theta_err[i, j] = 0.0
699
700
701 num = 0
702 for i in range(len(points)):
703
704 theta, phi, sigma = points[i]
705
706
707 theta_max = tmax_pseudo_ellipse(phi, theta_x, theta_y)
708
709
710 if theta > theta_max:
711 continue
712 if sigma > sigma_max or sigma < -sigma_max:
713 continue
714
715
716 pcs_pivot_motion_full_qrint(theta_i=theta, phi_i=phi, sigma_i=sigma, 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, R_eigen=R_eigen, RT_eigen=RT_eigen, Ri_prime=Ri_prime, pcs_theta=pcs_theta, pcs_theta_err=pcs_theta_err, missing_pcs=missing_pcs)
717
718
719 num += 1
720
721
722 for i in range(len(pcs_theta)):
723 for j in range(len(pcs_theta[i])):
724
725 pcs_theta[i, j] = c[i] * pcs_theta[i, j] / float(num)
726
727
728 if error_flag:
729 pcs_theta_err[i, j] = abs(pcs_theta_err[i, j] / float(num) - pcs_theta[i, j]**2) / float(num)
730 pcs_theta_err[i, j] = c[i] * sqrt(pcs_theta_err[i, j])
731 print("%8.3f +/- %-8.3f" % (pcs_theta[i, j]*1e6, pcs_theta_err[i, j]*1e6))
732