Changeset 32e3c9b in sasmodels for sasmodels/kernel_iq.c
- Timestamp:
- Jul 21, 2016 2:08:04 PM (8 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- b966a96
- Parents:
- 42356c8
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/kernel_iq.c
ra738209 r32e3c9b 33 33 #endif 34 34 35 #ifdef MAGNETIC 36 const int32_t magnetic[] = { MAGNETIC_PARS }; 37 #endif 38 39 #ifdef MAGNETIC 40 // Return value restricted between low and high 41 static double clip(double value, double low, double high) 42 { 43 return (value < low ? low : (value > high ? high : value)); 44 } 45 46 // Compute spin cross sections given in_spin and out_spin 47 // To convert spin cross sections to sld b: 48 // uu * (sld - m_sigma_x); 49 // dd * (sld + m_sigma_x); 50 // ud * (m_sigma_y + 1j*m_sigma_z); 51 // du * (m_sigma_y - 1j*m_sigma_z); 52 static void spins(double in_spin, double out_spin, 53 double *uu, double *dd, double *ud, double *du) 54 { 55 in_spin = clip(in_spin, 0.0, 1.0); 56 out_spin = clip(out_spin, 0.0, 1.0); 57 *uu = sqrt(sqrt(in_spin * out_spin)); 58 *dd = sqrt(sqrt((1.0-in_spin) * (1.0-out_spin))); 59 *ud = sqrt(sqrt(in_spin * (1.0-out_spin))); 60 *du = sqrt(sqrt((1.0-in_spin) * out_spin)); 61 } 62 63 // Convert polar to rectangular coordinates. 64 static void polrec(double r, double theta, double phi, 65 double *x, double *y, double *z) 66 { 67 double cos_theta, sin_theta, cos_phi, sin_phi; 68 SINCOS(theta*M_PI_180, sin_theta, cos_theta); 69 SINCOS(phi*M_PI_180, sin_phi, cos_phi); 70 *x = r * cos_theta * cos_phi; 71 *y = r * sin_theta; 72 *z = -r * cos_theta * sin_phi; 73 } 74 #endif 35 75 36 76 kernel … … 40 80 const int32_t pd_stop, // where we are stopping in the polydispersity loop 41 81 global const ProblemDetails *details, 42 global const double *values, 82 // global const // TODO: make it const again! 83 double *values, 43 84 global const double *q, // nq q values, with padding to boundary 44 85 global double *result, // nq+3 return values, again with padding … … 52 93 53 94 // Fill in the initial variables 95 // values[0] is scale 96 // values[1] is background 54 97 #ifdef USE_OPENMP 55 98 #pragma omp parallel for … … 58 101 pvec[k] = values[k+2]; 59 102 } 103 #ifdef MAGNETIC 104 const double up_frac_i = values[NPARS+2]; 105 const double up_frac_f = values[NPARS+3]; 106 const double up_angle = values[NPARS+4]; 107 #define MX(_k) (values[NPARS+5+3*_k]) 108 #define MY(_k) (values[NPARS+6+3*_k]) 109 #define MZ(_k) (values[NPARS+7+3*_k]) 110 111 // TODO: precompute this on the python side 112 // Convert polar to rectangular coordinates in place. 113 if (pd_start == 0) { // Update in place; only do this for the first hunk! 114 //printf("spin: %g %g %g\n", up_frac_i, up_frac_f, up_angle); 115 for (int mag=0; mag < NUM_MAGNETIC; mag++) { 116 //printf("mag %d: %g %g %g\n", mag, MX(mag), MY(mag), MZ(mag)); 117 polrec(MX(mag), MY(mag), MZ(mag), &MX(mag), &MY(mag), &MZ(mag)); 118 //printf(" ==>: %g %g %g\n", MX(mag), MY(mag), MZ(mag)); 119 } 120 } 121 // Interpret polarization cross section. 122 double uu, dd, ud, du; 123 double cos_mspin, sin_mspin; 124 spins(up_frac_i, up_frac_f, &uu, &dd, &ud, &du); 125 SINCOS(-up_angle*M_PI_180, sin_mspin, cos_mspin); 126 #endif 60 127 61 128 // Monodisperse computation … … 74 141 #endif 75 142 for (int q_index=0; q_index < nq; q_index++) { 143 #ifdef MAGNETIC 144 const double qx = q[2*q_index]; 145 const double qy = q[2*q_index+1]; 146 const double qsq = qx*qx + qy*qy; 147 148 // Constant across orientation, polydispersity for given qx, qy 149 double px, py, pz; 150 if (qsq > 1e-16) { 151 px = (qy*cos_mspin + qx*sin_mspin)/qsq; 152 py = (qy*sin_mspin - qx*cos_mspin)/qsq; 153 pz = 1.0; 154 } else { 155 px = py = pz = 0.0; 156 } 157 158 double scattering = 0.0; 159 if (uu > 1e-8) { 160 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 161 const double perp = (qy*MX(mag) - qx*MY(mag)); 162 pvec[magnetic[mag]] = (values[magnetic[mag]+2] - perp*px)*uu; 163 } 164 scattering += CALL_IQ(q, q_index, local_values); 165 } 166 if (dd > 1e-8){ 167 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 168 const double perp = (qy*MX(mag) - qx*MY(mag)); 169 pvec[magnetic[mag]] = (values[magnetic[mag]+2] + perp*px)*dd; 170 } 171 scattering += CALL_IQ(q, q_index, local_values); 172 } 173 if (ud > 1e-8){ 174 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 175 const double perp = (qy*MX(mag) - qx*MY(mag)); 176 pvec[magnetic[mag]] = perp*py*ud; 177 } 178 scattering += CALL_IQ(q, q_index, local_values); 179 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 180 pvec[magnetic[mag]] = MZ(mag)*pz*ud; 181 } 182 scattering += CALL_IQ(q, q_index, local_values); 183 } 184 if (du > 1e-8) { 185 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 186 const double perp = (qy*MX(mag) - qx*MY(mag)); 187 pvec[magnetic[mag]] = perp*py*du; 188 } 189 scattering += CALL_IQ(q, q_index, local_values); 190 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 191 pvec[magnetic[mag]] = -MZ(mag)*pz*du; 192 } 193 scattering += CALL_IQ(q, q_index, local_values); 194 } 195 #else 76 196 double scattering = CALL_IQ(q, q_index, local_values); 197 #endif 77 198 result[q_index] = (norm>0. ? scale*scattering/norm + background : background); 78 199 } … … 82 203 #if MAX_PD > 0 83 204 205 #if MAGNETIC 206 const double *pd_value = values+2+NPARS+3+3*NUM_MAGNETIC; 207 #else 84 208 const double *pd_value = values+2+NPARS; 209 #endif 85 210 const double *pd_weight = pd_value+details->pd_sum; 86 211 … … 164 289 #endif 165 290 for (int q_index=0; q_index < nq; q_index++) { 166 const double scattering = CALL_IQ(q, q_index, local_values); 291 #ifdef MAGNETIC 292 const double qx = q[2*q_index]; 293 const double qy = q[2*q_index+1]; 294 const double qsq = qx*qx + qy*qy; 295 296 // Constant across orientation, polydispersity for given qx, qy 297 double px, py, pz; 298 if (qsq > 1e-16) { 299 px = (qy*cos_mspin + qx*sin_mspin)/qsq; 300 py = (qy*sin_mspin - qx*cos_mspin)/qsq; 301 pz = 1.0; 302 } else { 303 px = py = pz = 0.0; 304 } 305 306 double scattering = 0.0; 307 if (uu > 1e-8) { 308 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 309 const double perp = (qy*MX(mag) - qx*MY(mag)); 310 pvec[magnetic[mag]] = (values[magnetic[mag]+2] - perp*px)*uu; 311 } 312 scattering += CALL_IQ(q, q_index, local_values); 313 } 314 if (dd > 1e-8){ 315 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 316 const double perp = (qy*MX(mag) - qx*MY(mag)); 317 pvec[magnetic[mag]] = (values[magnetic[mag]+2] + perp*px)*dd; 318 } 319 scattering += CALL_IQ(q, q_index, local_values); 320 } 321 if (ud > 1e-8){ 322 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 323 const double perp = (qy*MX(mag) - qx*MY(mag)); 324 pvec[magnetic[mag]] = perp*py*ud; 325 } 326 scattering += CALL_IQ(q, q_index, local_values); 327 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 328 pvec[magnetic[mag]] = MZ(mag)*pz*ud; 329 } 330 scattering += CALL_IQ(q, q_index, local_values); 331 } 332 if (du > 1e-8) { 333 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 334 const double perp = (qy*MX(mag) - qx*MY(mag)); 335 pvec[magnetic[mag]] = perp*py*du; 336 } 337 scattering += CALL_IQ(q, q_index, local_values); 338 for (int mag=0; mag<NUM_MAGNETIC; mag++) { 339 pvec[magnetic[mag]] = -MZ(mag)*pz*du; 340 } 341 scattering += CALL_IQ(q, q_index, local_values); 342 } 343 #else 344 double scattering = CALL_IQ(q, q_index, local_values); 345 #endif 167 346 result[q_index] += weight*scattering; 168 347 }
Note: See TracChangeset
for help on using the changeset viewer.