source: sasview/src/sas/sascalc/calculator/c_extensions/sld2i.c @ 0d72cac

ESS_GUIESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 0d72cac was b8080e1, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

cherry picking sascalc changes from master SASVIEW-996
minor unit test fixes

  • Property mode set to 100755
File size: 6.2 KB
RevLine 
[9e531f2]1/**
2Computes the (magnetic) scattering form sld (n and m) profile
3 */
4#include <stdio.h>
5#include <math.h>
[3010f68]6#include "sld2i.h"
7#include "libfunc.h"
8#include "librefl.h"
[9e531f2]9/**
10 * Constructor for GenI
11 *
12 * binning
13 * //@param qx: array of Qx values
14 * //@param qy: array of Qy values
15 * //@param qz: array of Qz values
16 * @param x: array of x values
17 * @param y: array of y values
18 * @param z: array of z values
19 * @param sldn: array of sld n
20 * @param mx: array of sld mx
21 * @param my: array of sld my
22 * @param mz: array of sld mz
23 * @param in_spin: ratio of up spin in Iin
24 * @param out_spin: ratio of up spin in Iout
25 * @param s_theta: angle (from x-axis) of the up spin in degree
26 */
[b8080e1]27void initGenI(GenI* this, int is_avg, int npix, double* x, double* y, double* z, double* sldn,
[9e531f2]28                        double* mx, double* my, double* mz, double* voli,
29                        double in_spin, double out_spin,
30                        double s_theta) {
[b8080e1]31        this->is_avg = is_avg;
[9e531f2]32        this->n_pix = npix;
33        this->x_val = x;
34        this->y_val = y;
35        this->z_val = z;
36        this->sldn_val = sldn;
37        this->mx_val = mx;
38        this->my_val = my;
39        this->mz_val = mz;
40        this->vol_pix = voli;
41        this->inspin = in_spin;
42        this->outspin = out_spin;
43        this->stheta = s_theta;
[3010f68]44}
[9e531f2]45
46/**
47 * Compute 2D anisotropic
48 */
[3010f68]49void genicomXY(GenI* this, int npoints, double *qx, double *qy, double *I_out){
50        //npoints is given negative for angular averaging
[9e531f2]51        // Assumes that q doesn't have qz component and sld_n is all real
52        //double q = 0.0;
53        //double Pi = 4.0*atan(1.0);
54        polar_sld b_sld;
55        double qr = 0.0;
[f54e82cf]56        Cplx iqr;
57        Cplx ephase;
58        Cplx comp_sld;
[9e531f2]59
[f54e82cf]60        Cplx sumj_uu;
61        Cplx sumj_ud;
62        Cplx sumj_du;
63        Cplx sumj_dd;
64        Cplx temp_fi;
65
[9e531f2]66        double count = 0.0;
[b8080e1]67        int i, j;
[9e531f2]68
[f54e82cf]69        cassign(&iqr, 0.0, 0.0);
70        cassign(&ephase, 0.0, 0.0);
71        cassign(&comp_sld, 0.0, 0.0);
72
[9e531f2]73        //Assume that pixel volumes are given in vol_pix in A^3 unit
74        //int x_size = 0; //in Ang
75        //int y_size = 0; //in Ang
76        //int z_size = 0; //in Ang
[3010f68]77
[9e531f2]78        // Loop over q-values and multiply apply matrix
[b8080e1]79
80        //printf("npoints: %d, npix: %d\n", npoints, this->n_pix);
[e6f2009]81        for(i=0; i<npoints; i++){
[9e531f2]82                //I_out[i] = 0.0;
[f54e82cf]83                cassign(&sumj_uu, 0.0, 0.0);
84                cassign(&sumj_ud, 0.0, 0.0);
85                cassign(&sumj_du, 0.0, 0.0);
86                cassign(&sumj_dd, 0.0, 0.0);
87                //printf("i: %d\n", i);
[9e531f2]88                //q = sqrt(qx[i]*qx[i] + qy[i]*qy[i]); // + qz[i]*qz[i]);
[b8080e1]89
[e6f2009]90                for(j=0; j<this->n_pix; j++){
[3010f68]91                        if (this->sldn_val[j]!=0.0
92                                ||this->mx_val[j]!=0.0
93                                ||this->my_val[j]!=0.0
94                                ||this->mz_val[j]!=0.0)
95                        {
[f54e82cf]96                            // printf("i,j: %d,%d\n", i,j);
[9e531f2]97                                //anisotropic
[f54e82cf]98                                cassign(&temp_fi, 0.0, 0.0);
99                                cal_msld(&b_sld, 0, qx[i], qy[i], this->sldn_val[j],
[3010f68]100                                                         this->mx_val[j], this->my_val[j], this->mz_val[j],
101                                                         this->inspin, this->outspin, this->stheta);
102                                qr = (qx[i]*this->x_val[j] + qy[i]*this->y_val[j]);
[f54e82cf]103                                cassign(&iqr, 0.0, qr);
104                                cplx_exp(&ephase, iqr);
[3010f68]105
[9e531f2]106                                //Let's multiply pixel(atomic) volume here
[f54e82cf]107                                rcmult(&ephase, this->vol_pix[j], ephase);
[9e531f2]108                                //up_up
[3010f68]109                                if (this->inspin > 0.0 && this->outspin > 0.0){
[f54e82cf]110                                        cassign(&comp_sld, b_sld.uu, 0.0);
111                                        cplx_mult(&temp_fi, comp_sld, ephase);
112                                        cplx_add(&sumj_uu, sumj_uu, temp_fi);
[9e531f2]113                                }
114                                //down_down
[3010f68]115                                if (this->inspin < 1.0 && this->outspin < 1.0){
[f54e82cf]116                                        cassign(&comp_sld, b_sld.dd, 0.0);
117                                        cplx_mult(&temp_fi, comp_sld, ephase);
118                                        cplx_add(&sumj_dd, sumj_dd, temp_fi);
[9e531f2]119                                }
120                                //up_down
[3010f68]121                                if (this->inspin > 0.0 && this->outspin < 1.0){
[f54e82cf]122                                        cassign(&comp_sld, b_sld.re_ud, b_sld.im_ud);
123                                        cplx_mult(&temp_fi, comp_sld, ephase);
124                                        cplx_add(&sumj_ud, sumj_ud, temp_fi);
[9e531f2]125                                }
126                                //down_up
[3010f68]127                                if (this->inspin < 1.0 && this->outspin > 0.0){
[f54e82cf]128                                        cassign(&comp_sld, b_sld.re_du, b_sld.im_du);
129                                        cplx_mult(&temp_fi, comp_sld, ephase);
130                                        cplx_add(&sumj_du, sumj_du, temp_fi);
[9e531f2]131                                }
132
133                                if (i == 0){
[3010f68]134                                        count += this->vol_pix[j];
[9e531f2]135                                }
136                        }
137                }
138                //printf("aa%d=%g %g %d\n", i, (sumj_uu.re*sumj_uu.re + sumj_uu.im*sumj_uu.im), (sumj_dd.re*sumj_dd.re + sumj_dd.im*sumj_dd.im), count);
139
140                I_out[i] = (sumj_uu.re*sumj_uu.re + sumj_uu.im*sumj_uu.im);
141                I_out[i] += (sumj_ud.re*sumj_ud.re + sumj_ud.im*sumj_ud.im);
142                I_out[i] += (sumj_du.re*sumj_du.re + sumj_du.im*sumj_du.im);
143                I_out[i] += (sumj_dd.re*sumj_dd.re + sumj_dd.im*sumj_dd.im);
144
145                I_out[i] *= (1.0E+8 / count); //in cm (unit) / number; //to be multiplied by vol_pix
146        }
[b8080e1]147        //printf("count = %d %g %g %g %g\n", count, this->sldn_val[0],this->mx_val[0], this->my_val[0], this->mz_val[0]);
[9e531f2]148}
149/**
150 * Compute 1D isotropic
151 * Isotropic: Assumes all slds are real (no magnetic)
152 * Also assumes there is no polarization: No dependency on spin
153 */
[3010f68]154void genicom(GenI* this, int npoints, double *q, double *I_out){
155        //npoints is given negative for angular averaging
[9e531f2]156        // Assumes that q doesn't have qz component and sld_n is all real
157        //double Pi = 4.0*atan(1.0);
158        double qr = 0.0;
159        double sumj;
160        double sld_j = 0.0;
161        double count = 0.0;
[b8080e1]162        int i, j, k;
163
[9e531f2]164        //Assume that pixel volumes are given in vol_pix in A^3 unit
165        // Loop over q-values and multiply apply matrix
[e6f2009]166        for(i=0; i<npoints; i++){
[3010f68]167                sumj =0.0;
[b8080e1]168                for(j=0; j<this->n_pix; j++){
[9e531f2]169                        //Isotropic: Assumes all slds are real (no magnetic)
170                        //Also assumes there is no polarization: No dependency on spin
[b8080e1]171                        if (this->is_avg == 1){
[9e531f2]172                                // approximation for a spherical symmetric particle
[3010f68]173                                qr = sqrt(this->x_val[j]*this->x_val[j]+this->y_val[j]*this->y_val[j]+this->z_val[j]*this->z_val[j])*q[i];
[9e531f2]174                                if (qr > 0.0){
175                                        qr = sin(qr) / qr;
[3010f68]176                                        sumj += this->sldn_val[j] * this->vol_pix[j] * qr;
[9e531f2]177                                }
178                                else{
[3010f68]179                                        sumj += this->sldn_val[j] * this->vol_pix[j];
[9e531f2]180                                }
181                        }
182                        else{
183                                //full calculation
184                                //pragma omp parallel for
[b8080e1]185                                for(k=0; k<this->n_pix; k++){
[3010f68]186                                        sld_j =  this->sldn_val[j] * this->sldn_val[k] * this->vol_pix[j] * this->vol_pix[k];
187                                        qr = (this->x_val[j]-this->x_val[k])*(this->x_val[j]-this->x_val[k])+
188                                                      (this->y_val[j]-this->y_val[k])*(this->y_val[j]-this->y_val[k])+
189                                                      (this->z_val[j]-this->z_val[k])*(this->z_val[j]-this->z_val[k]);
[9e531f2]190                                        qr = sqrt(qr) * q[i];
191                                        if (qr > 0.0){
192                                                sumj += sld_j*sin(qr)/qr;
193                                        }
194                                        else{
195                                                sumj += sld_j;
196                                        }
197                                }
198                        }
199                        if (i == 0){
[3010f68]200                                count += this->vol_pix[j];
[9e531f2]201                        }
202                }
203                I_out[i] = sumj;
[b8080e1]204                if (this->is_avg == 1) {
[9e531f2]205                        I_out[i] *= sumj;
206                }
207                I_out[i] *= (1.0E+8 / count); //in cm (unit) / number; //to be multiplied by vol_pix
208        }
[b8080e1]209        //printf("count = %d %g %g %g %g\n", count, sldn_val[0],mx_val[0], my_val[0], mz_val[0]);
[9e531f2]210}
Note: See TracBrowser for help on using the repository browser.