source: sasview/src/sas/sascalc/calculator/c_extensions/libfunc.c @ b36e7c7

magnetic_scatt
Last change on this file since b36e7c7 was b36e7c7, checked in by dirk, 5 years ago

clean up obsolete? code of magnetic scattering calculation. Addresses #1086.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1// by jcho
2
3#include <math.h>
4
5#include "libfunc.h"
6
7#include <stdio.h>
8
9
10
11//used in Si func
12
13int factorial(int i) {
14
15        int k, j;
16        if (i<2){
17                return 1;
18        }
19
20        k=1;
21
22        for(j=1;j<i;j++) {
23                k=k*(j+1);
24        }
25
26        return k;
27
28}
29
30
31
32// Used in pearl nec model
33
34// Sine integral function: approximated within 1%!!!
35
36// integral of sin(x)/x up to namx term nmax=6 looks the best.
37
38double Si(double x)
39
40{
41        int i;
42        int nmax=6;
43        double out;
44        long double power;
45        double pi = 4.0*atan(1.0);
46
47        if (x >= pi*6.2/4.0){
48                double out_sin = 0.0;
49                double out_cos = 0.0;
50                out = pi/2.0;
51
52                for (i=0; i<nmax-2; i+=1) {
53                        out_cos += pow(-1.0, i) * (double)factorial(2*i) / pow(x, 2*i+1);
54                        out_sin += pow(-1.0, i) * (double)factorial(2*i+1) / pow(x, 2*i+2);
55                }
56
57                out -= cos(x) * out_cos;
58                out -= sin(x) * out_sin;
59                return out;
60        }
61
62        out = 0.0;
63
64        for (i=0; i<nmax; i+=1) {
65                if (i==0) {
66                        out += x;
67                        continue;
68                }
69
70                power = pow(x,(2 * i + 1));
71                out += (double)pow(-1, i) * power / ((2.0 * (double)i + 1.0) * (double)factorial(2 * i + 1));
72
73                //printf ("Si=%g %g %d\n", x, out, i);
74        }
75
76        return out;
77}
78
79
80
81double sinc(double x)
82{
83  if (x==0.0){
84    return 1.0;
85  }
86  return sin(x)/x;
87}
88
89//The code calculating magnetic sld below seems to be not used.
90//Keeping it in order to check if it is not breaking anything.
91// calculate magnetic sld and return total sld
92// bn : contrast (not just sld of the layer)
93// m0: max mag of M; mtheta: angle from x-z plane;
94// mphi: angle (anti-clock-wise)of x-z projection(M) from x axis
95// spinfraci: the fraction of UP among UP+Down (before sample)
96// spinfracf: the fraction of UP among UP+Down (after sample and before detector)
97// spintheta: angle (anti-clock-wise) between neutron spin(up) and x axis
98// Note: all angles are in degrees.
99// void cal_msld(polar_sld *p_sld, int isangle, double qx, double qy, double bn,
100//                              double m01, double mtheta1, double mphi1,
101//                              double spinfraci, double spinfracf, double spintheta)
102// {
103//      //locals
104//      double q_x = qx;
105//      double q_y = qy;
106//      double sld = bn;
107//      int is_angle = isangle;
108//      double pi = 4.0*atan(1.0);
109//      double s_theta = spintheta * pi/180.0;
110//      double m_max = m01;
111//      double m_phi = mphi1;
112//      double m_theta = mtheta1;
113//      double in_spin = spinfraci;
114//      double out_spin = spinfracf;
115//
116//      double m_perp = 0.0;
117//      double m_perp_z = 0.0;
118//      double m_perp_y = 0.0;
119//      double m_perp_x = 0.0;
120//      double m_sigma_x = 0.0;
121//      double m_sigma_z = 0.0;
122//      double m_sigma_y = 0.0;
123//      //double b_m = 0.0;
124//      double q_angle = 0.0;
125//      double mx = 0.0;
126//      double my = 0.0;
127//      double mz = 0.0;
128//      double uu = sld;
129//      double dd = sld;
130//      double re_ud = 0.0;
131//      double im_ud = 0.0;
132//      double re_du = 0.0;
133//      double im_du = 0.0;
134//
135//      //No mag means no further calculation
136//      if (isangle>0) {
137//              if (m_max < 1.0e-32){
138//                      uu = sqrt((1+in_spin)/2 * (1+out_spin)/2) * uu;
139//                      dd = sqrt((1.0 - in_spin)/2 * (1.0 - out_spin)/2) * dd;
140//              }
141//      }
142//      else if (fabs(m_max)< 1.0e-32 && fabs(m_phi)< 1.0e-32 && fabs(m_theta)< 1.0e-32){
143//                      uu = sqrt((1+in_spin)/2 * (1+out_spin)/2) * uu;
144//                      dd = sqrt((1.0 - in_spin)/2 * (1.0 - out_spin)/2) * dd;
145//      } else {
146//
147//              //These are needed because of the precision of inputs
148//              if (in_spin < 0.0) in_spin = 0.0;
149//              if (in_spin > 1.0) in_spin = 1.0;
150//              if (out_spin < 0.0) out_spin = 0.0;
151//              if (out_spin > 1.0) out_spin = 1.0;
152//
153//              if (q_x == 0.0) q_angle = pi / 2.0;
154//              else q_angle = atan(q_y/q_x);
155//              if (q_y < 0.0 && q_x < 0.0) q_angle -= pi;
156//              else if (q_y > 0.0 && q_x < 0.0) q_angle += pi;
157//
158//              q_angle = pi/2.0 - q_angle;
159//              if (q_angle > pi) q_angle -= 2.0 * pi;
160//              else if (q_angle < -pi) q_angle += 2.0 * pi;
161//
162//              if (fabs(q_x) < 1.0e-16 && fabs(q_y) < 1.0e-16){
163//                      m_perp = 0.0;
164//                      }
165//              else {
166//                      m_perp = m_max;
167//                      }
168//              if (is_angle > 0){
169//                      m_phi *= pi/180.0;
170//                      m_theta *= pi/180.0;
171//                      mx = m_perp * cos(m_theta) * cos(m_phi);
172//                      my = m_perp * sin(m_theta);
173//                      mz = -(m_perp * cos(m_theta) * sin(m_phi));
174//              }
175//              else{
176//                      mx = m_perp;
177//                      my = m_phi;
178//                      mz = m_theta;
179//              }
180//              //ToDo: simplify these steps
181//              // m_perp1 -m_perp2
182//              m_perp_x = (mx) *  cos(q_angle);
183//              m_perp_x -= (my) * sin(q_angle);
184//              m_perp_y = m_perp_x;
185//              m_perp_x *= cos(-q_angle);
186//              m_perp_y *= sin(-q_angle);
187//              m_perp_z = mz;
188//
189//              m_sigma_x = (m_perp_x * cos(-s_theta) - m_perp_y * sin(-s_theta));
190//              m_sigma_y = (m_perp_x * sin(-s_theta) + m_perp_y * cos(-s_theta));
191//              m_sigma_z = (m_perp_z);
192//
193//              //Find b
194//              uu -= m_sigma_x;
195//              dd += m_sigma_x;
196//              re_ud = m_sigma_y;
197//              re_du = m_sigma_y;
198//              im_ud = m_sigma_z;
199//              im_du = -m_sigma_z;
200//
201//              uu = sqrt((1+in_spin) * (1 + out_spin)) * uu;
202//              dd = sqrt((1.0 - in_spin) * (1.0 - out_spin)) * dd;
203//
204//              re_ud = sqrt(in_spin * (1.0 - out_spin)) * re_ud;
205//              im_ud = sqrt(in_spin * (1.0 - out_spin)) * im_ud;
206//              re_du = sqrt((1.0 - in_spin) * out_spin) * re_du;
207//              im_du = sqrt((1.0 - in_spin) * out_spin) * im_du;
208//      }
209//      p_sld->uu = uu;
210//      p_sld->dd = dd;
211//      p_sld->re_ud = re_ud;
212//      p_sld->im_ud = im_ud;
213//      p_sld->re_du = re_du;
214//      p_sld->im_du = im_du;
215// }
216
217
218/** Modifications below by kieranrcampbell@gmail.com
219    Institut Laue-Langevin, July 2012
220**/
221
222/**
223Wojtek's comment Mar 22 2016: The remaing code can mostly likely be deleated
224Keeping it in order to check if it is not breaking anything
225**/
226
227/*
228#define ITMAX 100
229#define EPS 3.0e-7
230#define FPMIN 1.0e-30
231
232void gser(float *gamser, float a, float x, float *gln) {
233  int n;
234  float sum,del,ap;
235
236  *gln = lgamma(a);
237  if(x <= 0.0) {
238    if (x < 0.0) printf("Error: x less than 0 in routine gser");
239    *gamser = 0.0;
240    return;
241  } else {
242    ap = a;
243    del = sum = 1.0/a;
244
245    for(n=1;n<=ITMAX;n++) {
246      ++ap;
247      del *= x/ap;
248      sum += del;
249      if(fabs(del) < fabs(sum)*EPS) {
250        *gamser = sum * exp(-x + a * log(x) - (*gln));
251        return;
252      }
253    }
254    printf("a too large, ITMAX too small in routine gser");
255    return;
256
257  }
258
259}
260*/
261/**
262   Implements the incomplete gamma function Q(a,x) evaluated by its continued fraction
263   representation
264**/
265/*
266void gcf(float *gammcf, float a, float x, float *gln) {
267  int i;
268  float an,b,c,d,del,h;
269
270  *gln = lgamma(a);
271  b = x+1.0-a;
272  c = 1.0/FPMIN;
273  d = 1.0/b;
274  h=d;
275  for (i=1;i <= ITMAX; i++) {
276    an = -i*(i-a);
277    b += 2.0;
278    d = an*d + b;
279    if (fabs(d) < FPMIN) d = FPMIN;
280    c = b+an/c;
281    if (fabs(c) < FPMIN) c = FPMIN;
282    d = 1.0/d;
283    del = d*c;
284    h += del;
285    if (fabs(del-1.0) < EPS) break;
286  }
287  if (i > ITMAX) printf("a too large, ITMAX too small in gcf");
288  *gammcf = exp(-x+a*log(x)-(*gln))*h;
289  return;
290}
291*/
292/**
293   Represents incomplete error function, P(a,x)
294**/
295/*
296float gammp(float a, float x) {
297  float gamser,gammcf,gln;
298  if(x < 0.0 || a <= 0.0) printf("Invalid arguments in routine gammp");
299  if (x < (a+1.0)) {
300    gser(&gamser,a,x,&gln);
301    return gamser;
302  } else {
303    gcf(&gammcf,a,x,&gln);
304    return 1.0 - gammcf;
305  }
306}
307*/
308/**
309    Implementation of the error function, erf(x)
310**/
311/*
312float erff(float x) {
313  return x < 0.0 ? -gammp(0.5,x*x) : gammp(0.5,x*x);
314}
315*/
Note: See TracBrowser for help on using the repository browser.