[e6f1410] | 1 | r""" |
---|
| 2 | Show numerical precision of $2 J_1(x)/x$. |
---|
| 3 | """ |
---|
[95ce773] | 4 | import sys; sys.path.insert(0, '..') |
---|
[e6f1410] | 5 | |
---|
| 6 | import numpy as np |
---|
[95ce773] | 7 | try: |
---|
| 8 | from mpmath import mp |
---|
| 9 | except: |
---|
| 10 | # CRUFT: mpmath split out into its own package |
---|
| 11 | from sympy.mpmath import mp |
---|
[e6f1410] | 12 | #import matplotlib; matplotlib.use('TkAgg') |
---|
| 13 | import pylab |
---|
| 14 | |
---|
| 15 | |
---|
[cbd37a7] | 16 | SHOW_DIFF = True # True if show diff rather than function value |
---|
| 17 | #SHOW_DIFF = False # True if show diff rather than function value |
---|
[e6f1410] | 18 | LINEAR_X = False # True if q is linearly spaced instead of log spaced |
---|
[cbd37a7] | 19 | #LINEAR_X = True # True if q is linearly spaced instead of log spaced |
---|
| 20 | FUNCTION = "2*J1(x)/x" |
---|
[e6f1410] | 21 | |
---|
[cbd37a7] | 22 | def mp_fn(vec, bits=500): |
---|
[e6f1410] | 23 | """ |
---|
| 24 | Direct calculation using sympy multiprecision library. |
---|
| 25 | """ |
---|
[0a6da3c] | 26 | with mp.workprec(bits): |
---|
[cbd37a7] | 27 | return [_mp_fn(mp.mpf(x)) for x in vec] |
---|
[e6f1410] | 28 | |
---|
[cbd37a7] | 29 | def _mp_fn(x): |
---|
[e6f1410] | 30 | """ |
---|
[cbd37a7] | 31 | Actual function that gets evaluated. The caller just vectorizes. |
---|
[e6f1410] | 32 | """ |
---|
| 33 | return mp.mpf(2)*mp.j1(x)/x |
---|
| 34 | |
---|
[cbd37a7] | 35 | def np_fn(x, dtype): |
---|
[e6f1410] | 36 | """ |
---|
| 37 | Direct calculation using scipy. |
---|
| 38 | """ |
---|
[0a6da3c] | 39 | from scipy.special import j1 as J1 |
---|
[e6f1410] | 40 | x = np.asarray(x, dtype) |
---|
[0a6da3c] | 41 | return np.asarray(2, dtype)*J1(x)/x |
---|
[e6f1410] | 42 | |
---|
[cbd37a7] | 43 | def sasmodels_fn(x, dtype, platform='ocl'): |
---|
[e6f1410] | 44 | """ |
---|
| 45 | Calculation using pade approximant. |
---|
| 46 | """ |
---|
[cbd37a7] | 47 | from sasmodels import core, data, direct_model |
---|
| 48 | model = core.load_model('bessel', dtype=dtype) |
---|
| 49 | calculator = direct_model.DirectModel(data.empty_data1D(x), model) |
---|
| 50 | return calculator(background=0) |
---|
[0a6da3c] | 51 | |
---|
[e6f1410] | 52 | def plotdiff(x, target, actual, label): |
---|
| 53 | """ |
---|
| 54 | Plot the computed value. |
---|
| 55 | |
---|
| 56 | Use relative error if SHOW_DIFF, otherwise just plot the value directly. |
---|
| 57 | """ |
---|
| 58 | if SHOW_DIFF: |
---|
[cbd37a7] | 59 | err = abs((target-actual)/target) |
---|
| 60 | #err = np.clip(err, 0, 1) |
---|
[e6f1410] | 61 | pylab.loglog(x, err, '-', label=label) |
---|
| 62 | else: |
---|
| 63 | limits = np.min(target), np.max(target) |
---|
| 64 | pylab.semilogx(x, np.clip(actual,*limits), '-', label=label) |
---|
| 65 | |
---|
[cbd37a7] | 66 | def compare(x, precision, target): |
---|
[e6f1410] | 67 | r""" |
---|
| 68 | Compare the different computation methods using the given precision. |
---|
| 69 | """ |
---|
[cbd37a7] | 70 | #plotdiff(x, target, mp_fn(x, 11), 'mp 11 bits') |
---|
| 71 | plotdiff(x, target, np_fn(x, precision), 'numpy '+precision) |
---|
| 72 | plotdiff(x, target, sasmodels_fn(x, precision, 0), 'sasmodels '+precision) |
---|
[e6f1410] | 73 | pylab.xlabel("qr (1/Ang)") |
---|
| 74 | if SHOW_DIFF: |
---|
| 75 | pylab.ylabel("relative error") |
---|
| 76 | else: |
---|
[cbd37a7] | 77 | pylab.ylabel(FUNCTION) |
---|
[e6f1410] | 78 | pylab.semilogx(x, target, '-', label="true value") |
---|
| 79 | if LINEAR_X: |
---|
| 80 | pylab.xscale('linear') |
---|
| 81 | |
---|
| 82 | def main(): |
---|
| 83 | r""" |
---|
| 84 | Compare accuracy of different methods for computing $3 j_1(x)/x$. |
---|
| 85 | :return: |
---|
| 86 | """ |
---|
| 87 | if LINEAR_X: |
---|
| 88 | qr = np.linspace(1,1000,2000) |
---|
| 89 | else: |
---|
| 90 | qr = np.logspace(-3,5,400) |
---|
[cbd37a7] | 91 | target = np.asarray(mp_fn(qr), 'double') |
---|
[e6f1410] | 92 | pylab.subplot(121) |
---|
[cbd37a7] | 93 | compare(qr, 'single', target) |
---|
[e6f1410] | 94 | pylab.legend(loc='best') |
---|
| 95 | pylab.subplot(122) |
---|
[cbd37a7] | 96 | compare(qr, 'double', target) |
---|
[e6f1410] | 97 | pylab.legend(loc='best') |
---|
[cbd37a7] | 98 | pylab.suptitle(FUNCTION) |
---|
[e6f1410] | 99 | |
---|
| 100 | if __name__ == "__main__": |
---|
[0a6da3c] | 101 | #print "\n".join(str(x) for x in mp_J1c([1e-6,1e-5,1e-4,1e-3])) |
---|
[e6f1410] | 102 | main() |
---|
| 103 | pylab.show() |
---|