Ticket #9556: Muon_DynamicKuboToyabe.cpp

File Muon_DynamicKuboToyabe.cpp, 5.0 KB (added by Anders Markvardsen, 6 years ago)
Line 
1//----------------------------------------------------------------------
2// Includes
3//----------------------------------------------------------------------
4#include "Muon_DynamicKuboToyabe.h"
5#include <cmath>
6
7namespace Mantid
8{
9namespace CurveFitting
10{
11
12using namespace Kernel;
13using namespace API;
14
15DECLARE_FUNCTION(Muon_DynamicKuboToyabe)
16
17void Muon_DynamicKuboToyabe::init()
18{
19  declareParameter("A", 0.2);
20  declareParameter("Delta", 0.2);
21  declareParameter("Field",0.0);
22  declareParameter("hopping rate",0.0);
23  declareParameter("endX",15);
24}
25
26//--------------------------------------------------------------------------------------------------------------------------------------
27
28double midpnt(double func(const double, const double, const double,const double),
29        const double a, const double b, const int n, const double g, const double w0) {
30// quote & modified from numerical recipe 2nd edtion (page147) 
31       
32        double x,tnm,sum,del,ddel;
33        int it,j;
34        static double s;
35
36        if (n==1) { return (s =0.5*(b-a)*func(a,g,w0,b)+func(b,g,w0,b));
37        } else {
38
39                for (it=1,j=1;j<n-1;j++) it *= 3;
40                tnm = it;
41                del = (b-a)/(3*tnm);
42                ddel=del+del;
43                x = a+0.5*del;
44                sum =0.0;
45                for (j=0;j<it;j++) {
46                        sum += func(x,g,w0,b);
47                        x += ddel;
48                        sum += func(x,g,w0,b);
49                        x += del;
50                }
51                s=(s+(b-a)*sum/tnm)/3.0;
52                return s;
53        }
54}
55
56void polint (double* xa, double* ya, const double x, double& y, double& dy) {
57        int i, m, ns = 0;
58        double den, dif, dift, ho, hp, w;
59
60        const int n = sizeof xa;
61        double c[n],d[n];
62        dif = fabs(x-xa[0]);
63        for (i=0;i<n;i++){
64                if((dift=fabs(x-xa[i]))<dif) {
65                        ns=i;
66                        dif=dift;
67                }
68                c[i]=ya[i];
69                d[i]=ya[i];
70        }
71        y=ya[ns--];
72        for (m=1;m<n;m++) {
73                for (i=0;i<n-m;i++) {
74
75                        ho=xa[i]-x;
76                        hp=xa[i+m]-x;
77                        w=c[i+1]-d[i];
78//                      if((den=ho-hp)==0.0) error message!!!; delete next line.
79                        den=ho-hp;
80                        den=w/den;
81                        d[i]=hp*den;
82                        c[i]=ho*den;
83                }
84                y += (dy=(2*(ns+1)<(n-m) ? c[ns+1] : d[ns--]));
85
86        }
87}
88
89
90double integral (double func(const double, const double, const double, const double),
91                                const double a, const double b, const double g, const double w0) {
92        const int JMAX = 14, JMAXP = JMAX+1, K=5;
93        const double EPS = 3.0e-9;  //error smaller than this value
94        int i,j;
95        double ss,dss;
96        double h[JMAXP], s[JMAX], h_t[K], s_t[K];
97       
98        h[0] = 1.0;
99        for (j=1; j<= JMAX; j++) {
100                s[j-1]=midpnt(func,a,b,j,g,w0);
101                if (j >= K) {
102                        for (i=0;i<K;i++) {
103                                h_t[i]=h[j-K+i];
104                                s_t[i]=s[j-K+i];
105                        }
106                        polint(h_t,s_t,0.0,ss,dss);
107                        if (fabs(dss) <= fabs(ss)) return ss;
108                }
109                h[j]=h[j-1]/9.0;
110        }
111        return 0.0;
112}
113
114
115//--------------------------------------------------------------------------------------------------------------------------------------
116// cast all integers into doubles
117double ZFKT (const double q)
118{
119        return((0.3333333333)+(0.6666666667)*(1.0-q)*exp(-q/2.0));
120}
121//Zero field KuboToyabe function.
122
123
124double f1(const double x, const double G, const double w0, const double b) {
125       
126        return( exp(-G*G*x*x/2)*sin(w0*x)); 
127}
128//integration function for general static KuboToyabe.
129
130double gz (const double x, const double G, const double F) 
131{
132        double w0 = 2.0*3.1415926536*0.01355342*F;
133//      double Integral = 0;
134        const double q = G*G*x*x;
135       
136        if (w0 == 0.0) {
137                return (ZFKT(q)); 
138        }
139        else {
140               
141                if (F>2.0*G) { w0 = 2*3.1415926*0.01355342*F ;} else { w0 =2*3.1415926*0.01355342*2.0*G; }
142                       
143                double p = G*G/(w0*w0);
144                double HKT = 1.0-2.0*p*(1-exp(-q/2.0)*cos(w0*x))+2.0*p*p*w0*integral(f1,0.0,x,G,w0);
145                if (F>2.0*G) {return (HKT);} 
146                else {return (ZFKT(q)+ (F/2.0/G)*(HKT-ZFKT(q)));}       
147               
148   }
149}
150
151
152
153
154
155
156void Muon_DynamicKuboToyabe::functionLocal(double* out, const double* xValues, const size_t nData)const
157{
158    const double& A = getParameter("A");
159    const double& G = abs(getParameter("Delta"));
160        const double& F = abs(getParameter("Field"));
161        const double& v = abs(getParameter("hopping rate"));
162
163
164       
165       
166       
167        //do{stepsize=stepsize/10;}while (xValues[0]<stepsize);
168        //make sure stepsize is smaller than spacing between xValues.
169       
170
171
172
173        const int n = 1000;
174        const double stepsize = abs(getParameter("endX")/n);
175        double funcG[n];
176
177        double Integral = 0.0;
178        if (v == 0.0) {
179                for (int i = 0; i < nData; i++) {
180                        out[i] = A*gz(xValues[i],G,F);
181                }
182        } 
183//      else if {
184        else {
185                for (int i = 0; i < n; i++) {
186                        if (v*i*stepsize>5.0 && v>10.0*G) {
187                                funcG[i] = funcG[i-1]*exp(-2*G*G*stepsize/v);//fast hopping approx
188                        } else {
189                                double Integral=0.0;
190                                for (int c = 1; c <= i; c++) {
191                                        Integral= gz(c*stepsize,G,F)*exp(-v*c*stepsize)*funcG[i-c]*(stepsize) + Integral; 
192                                }
193                                funcG[i] = (gz(i*stepsize,G,F)*exp(-v*i*stepsize) + v*Integral);
194                        }
195                }
196                for (int i = 0; i < nData; i++) {
197                        double a =xValues[i]/stepsize;
198                        out[i] = A*(funcG[int(a)]);
199                }
200
201   }
202}
203
204
205void Muon_DynamicKuboToyabe::functionDerivLocal(API::Jacobian* out, const double* xValues, const size_t nData)
206{
207  calNumericalDeriv(out, xValues, nData);
208}
209
210
211
212
213} // namespace CurveFitting
214} // namespace Mantid