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