source: sans/Analysis/branches/ajj_23APR07/XOPs/SANSAnalysis/XOP/Sphere.c @ 102

Last change on this file since 102 was 102, checked in by ajj, 16 years ago

Switched to generic library header so that the XOP code doesn't have redundant defines for internal library functions.

File size: 17.1 KB
Line 
1/*      SimpleFit.c
2
3A simplified project designed to act as a template for your curve fitting function.
4The fitting function is a simple polynomial. It works but is of no practical use.
5*/
6
7#pragma XOP_SET_STRUCT_PACKING                  // All structures are 2-byte-aligned.
8
9#include "XOPStandardHeaders.h"                 // Include ANSI headers, Mac headers, IgorXOP.h, XOP.h and XOPSupport.h
10#include "SANSAnalysis.h"
11#include "libSANSAnalysis.h"
12#include "Sphere.h"
13
14// scattering from a sphere - hardly needs to be an XOP...
15int
16SphereFormX(FitParamsPtr p)
17{
18        double *dp;                             // Pointer to double precision wave data.
19        float *fp;                              // Pointer to single precision wave data.
20        double q;               //local variables of coefficient wave
21        int hState;
22        char buf[256];
23               
24        if (p->waveHandle == NIL) {
25                SetNaN64(&p->result);
26                return NON_EXISTENT_WAVE;
27        }
28       
29        q= p->x;
30
31        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
32                case NT_FP32:
33                        fp= WaveData(p->waveHandle);
34                        SetNaN64(&p->result);
35                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
36                case NT_FP64:
37                        dp= WaveData(p->waveHandle);
38                        p->result = SphereForm(dp,q);
39                        return 0;
40                default:                                                                // We can't handle this wave data type.
41                        SetNaN64(&p->result);
42                        return REQUIRES_SP_OR_DP_WAVE;
43        }       
44        return 0;
45}
46
47
48// scattering from a monodisperse core-shell sphere - hardly needs to be an XOP...
49int
50CoreShellFormX(FitParamsPtr p)
51{
52        double *dp;                             // Pointer to double precision wave data.
53        float *fp;                              // Pointer to single precision wave data.
54        double q;               //local variables of coefficient wave
55       
56        if (p->waveHandle == NIL) {
57                SetNaN64(&p->result);
58                return NON_EXISTENT_WAVE;
59        }
60       
61        q= p->x;
62       
63        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
64                case NT_FP32:
65                        fp= WaveData(p->waveHandle);
66                        SetNaN64(&p->result);
67                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
68                case NT_FP64:
69                        dp= WaveData(p->waveHandle);
70                        p->result = CoreShellForm(dp,q);
71                        return 0;
72                default:                                                                // We can't handle this wave data type.
73                        SetNaN64(&p->result);
74                        return REQUIRES_SP_OR_DP_WAVE;
75        }       
76        return 0;
77}
78
79// scattering from a unilamellar vesicle - hardly needs to be an XOP...
80// same functional form as the core-shell sphere, but more intuitive for a vesicle
81int
82VesicleFormX(FitParamsPtr p)
83{
84        double *dp;                             // Pointer to double precision wave data.
85        float *fp;                              // Pointer to single precision wave data.
86        double q;               //local variables of coefficient wave
87       
88        if (p->waveHandle == NIL) {
89                SetNaN64(&p->result);
90                return NON_EXISTENT_WAVE;
91        }
92       
93        q= p->x;
94       
95        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
96                case NT_FP32:
97                        fp= WaveData(p->waveHandle);
98                        SetNaN64(&p->result);
99                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
100                case NT_FP64:
101                        dp= WaveData(p->waveHandle);
102                        p->result = VesicleForm(dp,q);
103                        return 0;
104                default:                                                                // We can't handle this wave data type.
105                        SetNaN64(&p->result);
106                        return REQUIRES_SP_OR_DP_WAVE;
107        }       
108        return 0;
109}
110
111
112// scattering from a core shell sphere with a (Schulz) polydisperse core and constant shell thickness
113//
114int
115PolyCoreFormX(FitParamsPtr p)
116{
117        double *dp;                             // Pointer to double precision wave data.
118        float *fp;                              // Pointer to single precision wave data.
119        double q;               //local variables of coefficient wave
120       
121        if (p->waveHandle == NIL) {
122                SetNaN64(&p->result);
123                return NON_EXISTENT_WAVE;
124        }
125       
126        q= p->x;
127       
128        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
129                case NT_FP32:
130                        fp= WaveData(p->waveHandle);
131                        SetNaN64(&p->result);
132                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
133                case NT_FP64:
134                        dp= WaveData(p->waveHandle);
135                        p->result = PolyCoreForm(dp,q);
136                        return 0;
137                default:                                                                // We can't handle this wave data type.
138                        SetNaN64(&p->result);
139                        return REQUIRES_SP_OR_DP_WAVE;
140        }       
141        return 0;
142}
143
144
145// scattering from a uniform sphere with a (Schulz) size distribution
146// structure factor effects are explicitly and correctly included.
147//
148int
149PolyHardSphereIntensityX(FitParamsPtr p)
150{
151        double *dp;                             // Pointer to double precision wave data.
152        float *fp;                              // Pointer to single precision wave data.
153        double q;               //local variables of coefficient wave
154       
155        if (p->waveHandle == NIL) {
156                SetNaN64(&p->result);
157                return NON_EXISTENT_WAVE;
158        }
159       
160        q= p->x;
161       
162        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
163                case NT_FP32:
164                        fp= WaveData(p->waveHandle);
165                        SetNaN64(&p->result);
166                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
167                case NT_FP64:
168                        dp= WaveData(p->waveHandle);
169                        p->result = PolyHardSphereIntensity(dp,q);
170                        return 0;
171                default:                                                                // We can't handle this wave data type.
172                        SetNaN64(&p->result);
173                        return REQUIRES_SP_OR_DP_WAVE;
174        }       
175        return 0;
176}
177
178// scattering from a uniform sphere with a (Schulz) size distribution, bimodal population
179// NO CROSS TERM IS ACCOUNTED FOR == DILUTE SOLUTION!!
180//
181int
182BimodalSchulzSpheresX(FitParamsPtr p)
183{
184        double *dp;                             // Pointer to double precision wave data.
185        float *fp;                              // Pointer to single precision wave data.
186        double q;               //local variables of coefficient wave
187       
188        if (p->waveHandle == NIL) {
189                SetNaN64(&p->result);
190                return NON_EXISTENT_WAVE;
191        }
192       
193        q= p->x;
194       
195        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
196                case NT_FP32:
197                        fp= WaveData(p->waveHandle);
198                        SetNaN64(&p->result);
199                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
200                case NT_FP64:
201                        dp= WaveData(p->waveHandle);
202                        p->result = BimodalSchulzSpheres(dp,q);
203                        return 0;
204                default:                                                                // We can't handle this wave data type.
205                        SetNaN64(&p->result);
206                        return REQUIRES_SP_OR_DP_WAVE;
207        }       
208        return 0;
209}
210
211
212// scattering from a uniform sphere with a (Schulz) size distribution
213//
214int
215SchulzSpheresX(FitParamsPtr p)
216{
217        double *dp;                             // Pointer to double precision wave data.
218        float *fp;                              // Pointer to single precision wave data.
219        double q;               //local variables of coefficient wave
220       
221        if (p->waveHandle == NIL) {
222                SetNaN64(&p->result);
223                return NON_EXISTENT_WAVE;
224        }
225       
226        q= p->x;
227       
228        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
229                case NT_FP32:
230                        fp= WaveData(p->waveHandle);
231                        SetNaN64(&p->result);
232                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
233                case NT_FP64:
234                        dp= WaveData(p->waveHandle);
235                        p->result = SchulzSpheres(dp,q);
236                        return 0;
237                default:                                                                // We can't handle this wave data type.
238                        SetNaN64(&p->result);
239                        return REQUIRES_SP_OR_DP_WAVE;
240        }       
241        return 0;
242}
243
244
245
246// scattering from a uniform sphere with a rectangular size distribution
247//
248int
249PolyRectSpheresX(FitParamsPtr p)
250{
251        double *dp;                             // Pointer to double precision wave data.
252        float *fp;                              // Pointer to single precision wave data.
253        double q;               //local variables of coefficient wave
254       
255        if (p->waveHandle == NIL) {
256                SetNaN64(&p->result);
257                return NON_EXISTENT_WAVE;
258        }
259       
260        q= p->x;
261       
262        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
263                case NT_FP32:
264                        fp= WaveData(p->waveHandle);
265                        SetNaN64(&p->result);
266                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
267                case NT_FP64:
268                        dp= WaveData(p->waveHandle);
269                        p->result = PolyRectSpheres(dp,q);
270                        return 0;
271                default:                                                                // We can't handle this wave data type.
272                        SetNaN64(&p->result);
273                        return REQUIRES_SP_OR_DP_WAVE;
274        }       
275        return 0;
276}
277
278
279// scattering from a uniform sphere with a Gaussian size distribution
280//
281int
282GaussPolySphereX(FitParamsPtr p)
283{
284        double *dp;                             // Pointer to double precision wave data.
285        float *fp;                              // Pointer to single precision wave data.
286        double q;               //local variables of coefficient wave
287       
288        if (p->waveHandle == NIL) {
289                SetNaN64(&p->result);
290                return NON_EXISTENT_WAVE;
291        }
292       
293        q= p->x;
294       
295        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
296                case NT_FP32:
297                        fp= WaveData(p->waveHandle);
298                        SetNaN64(&p->result);
299                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
300                case NT_FP64:
301                        dp= WaveData(p->waveHandle);
302                        p->result = GaussPolySphere(dp,q);
303                        return 0;
304                default:                                                                // We can't handle this wave data type.
305                        SetNaN64(&p->result);
306                        return REQUIRES_SP_OR_DP_WAVE;
307        }       
308        return 0;
309}
310
311
312// scattering from a uniform sphere with a LogNormal size distribution
313//
314int
315LogNormalPolySphereX(FitParamsPtr p)
316{
317        double *dp;                             // Pointer to double precision wave data.
318        float *fp;                              // Pointer to single precision wave data.
319        double q;               //local variables of coefficient wave
320       
321        if (p->waveHandle == NIL) {
322                SetNaN64(&p->result);
323                return NON_EXISTENT_WAVE;
324        }
325       
326        q= p->x;
327       
328        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
329                case NT_FP32:
330                        fp= WaveData(p->waveHandle);
331                        SetNaN64(&p->result);
332                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
333                case NT_FP64:
334                        dp= WaveData(p->waveHandle);
335                        p->result = LogNormalPolySphere(dp,q);
336                        return 0;
337                default:                                                                // We can't handle this wave data type.
338                        SetNaN64(&p->result);
339                        return REQUIRES_SP_OR_DP_WAVE;
340        }       
341        return 0;
342}
343
344
345// scattering from a core shell sphere with a (Schulz) polydisperse core and constant ratio (shell thickness)/(core radius)
346// - the polydispersity is of the WHOLE sphere
347//
348int
349PolyCoreShellRatioX(FitParamsPtr p)
350{
351        double *dp;                             // Pointer to double precision wave data.
352        float *fp;                              // Pointer to single precision wave data.
353        double q;               //local variables of coefficient wave
354       
355        if (p->waveHandle == NIL) {
356                SetNaN64(&p->result);
357                return NON_EXISTENT_WAVE;
358        }
359       
360        q= p->x;
361       
362        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
363                case NT_FP32:
364                        fp= WaveData(p->waveHandle);
365                        SetNaN64(&p->result);
366                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
367                case NT_FP64:
368                        dp= WaveData(p->waveHandle);
369                        p->result = PolyCoreShellRatio(dp,q);
370                        return 0;
371                default:                                                                // We can't handle this wave data type.
372                        SetNaN64(&p->result);
373                        return REQUIRES_SP_OR_DP_WAVE;
374        }       
375        return 0;
376}
377
378
379// scattering from a a binary population of hard spheres, 3 partial structure factors
380// are properly accounted for...
381//       Input (fitting) variables are:
382//      larger sphere radius(angstroms) = guess[0]
383//      smaller sphere radius (A) = w[1]
384//      number fraction of larger spheres = guess[2]
385//      total volume fraction of spheres = guess[3]
386//      size ratio, alpha(0<a<1) = derived
387//      SLD(A-2) of larger particle = guess[4]
388//      SLD(A-2) of smaller particle = guess[5]
389//      SLD(A-2) of the solvent = guess[6]
390//      background = guess[7]
391int
392BinaryHSX(FitParamsPtr p)
393{
394        double *dp;                             // Pointer to double precision wave data.
395        float *fp;                              // Pointer to single precision wave data.
396        double q;               //local variables of coefficient wave
397       
398        if (p->waveHandle == NIL) {
399                SetNaN64(&p->result);
400                return NON_EXISTENT_WAVE;
401        }
402       
403        q= p->x;
404       
405        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
406                case NT_FP32:
407                        fp= WaveData(p->waveHandle);
408                        SetNaN64(&p->result);
409                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
410                case NT_FP64:
411                        dp= WaveData(p->waveHandle);
412                        p->result = BinaryHS(dp,q);
413                        return 0;
414                default:                                                                // We can't handle this wave data type.
415                        SetNaN64(&p->result);
416                        return REQUIRES_SP_OR_DP_WAVE;
417        }       
418        return 0;
419}
420
421int
422BinaryHS_PSF11X(FitParamsPtr p)
423{
424        double *dp;                             // Pointer to double precision wave data.
425        float *fp;                              // Pointer to single precision wave data.
426        double q;               //local variables of coefficient wave
427       
428        if (p->waveHandle == NIL) {
429                SetNaN64(&p->result);
430                return NON_EXISTENT_WAVE;
431        }
432       
433        q= p->x;
434       
435        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
436                case NT_FP32:
437                        fp= WaveData(p->waveHandle);
438                        SetNaN64(&p->result);
439                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
440                case NT_FP64:
441                        dp= WaveData(p->waveHandle);
442                        p->result = BinaryHS_PSF11(dp,q);
443                        return 0;
444                default:                                                                // We can't handle this wave data type.
445                        SetNaN64(&p->result);
446                        return REQUIRES_SP_OR_DP_WAVE;
447        }       
448        return 0;
449}
450
451int
452BinaryHS_PSF12X(FitParamsPtr p)
453{
454        double *dp;                             // Pointer to double precision wave data.
455        float *fp;                              // Pointer to single precision wave data.
456        double q;               //local variables of coefficient wave
457       
458        if (p->waveHandle == NIL) {
459                SetNaN64(&p->result);
460                return NON_EXISTENT_WAVE;
461        }
462       
463        q= p->x;
464       
465        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
466                case NT_FP32:
467                        fp= WaveData(p->waveHandle);
468                        SetNaN64(&p->result);
469                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
470                case NT_FP64:
471                        dp= WaveData(p->waveHandle);
472                        p->result = BinaryHS_PSF12(dp,q);
473                        return 0;
474                default:                                                                // We can't handle this wave data type.
475                        SetNaN64(&p->result);
476                        return REQUIRES_SP_OR_DP_WAVE;
477        }       
478        return 0;
479}
480
481
482int
483BinaryHS_PSF22X(FitParamsPtr p)
484{
485        double *dp;                             // Pointer to double precision wave data.
486        float *fp;                              // Pointer to single precision wave data.
487        double q;               //local variables of coefficient wave
488       
489        if (p->waveHandle == NIL) {
490                SetNaN64(&p->result);
491                return NON_EXISTENT_WAVE;
492        }
493       
494        q= p->x;
495       
496        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
497                case NT_FP32:
498                        fp= WaveData(p->waveHandle);
499                        SetNaN64(&p->result);
500                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
501                case NT_FP64:
502                        dp= WaveData(p->waveHandle);
503                        p->result = BinaryHS_PSF22(dp,q);
504                        return 0;
505                default:                                                                // We can't handle this wave data type.
506                        SetNaN64(&p->result);
507                        return REQUIRES_SP_OR_DP_WAVE;
508        }       
509        return 0;
510}
511
512
513
514/*
515 // calculates the scattering from a spherical particle made up of a core (aqueous) surrounded
516 // by N spherical layers, each of which is a PAIR of shells, solvent + surfactant since there
517 //must always be a surfactant layer on the outside
518 //
519 // bragg peaks arise naturally from the periodicity of the sample
520 // resolution smeared version gives he most appropriate view of the model
521 
522        Warning:
523 The call to WaveData() below returns a pointer to the middle
524 of an unlocked Macintosh handle. In the unlikely event that your
525 calculations could cause memory to move, you should copy the coefficient
526 values to local variables or an array before such operations.
527 */
528int
529MultiShellX(FitParamsPtr p)
530{
531        double *dp;                             // Pointer to double precision wave data.
532        float *fp;                              // Pointer to single precision wave data.
533        double q;               //local variables of coefficient wave
534       
535        if (p->waveHandle == NIL) {
536                SetNaN64(&p->result);
537                return NON_EXISTENT_WAVE;
538        }
539       
540        q= p->x;
541       
542        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
543                case NT_FP32:
544                        fp= WaveData(p->waveHandle);
545                        SetNaN64(&p->result);
546                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
547                case NT_FP64:
548                        dp= WaveData(p->waveHandle);
549                        p->result = MultiShell(dp,q);
550                        return 0;
551                default:                                                                // We can't handle this wave data type.
552                        SetNaN64(&p->result);
553                        return REQUIRES_SP_OR_DP_WAVE;
554        }       
555        return 0;
556}
557
558/*
559 // calculates the scattering from a POLYDISPERSE spherical particle made up of a core (aqueous) surrounded
560 // by N spherical layers, each of which is a PAIR of shells, solvent + surfactant since there
561 //must always be a surfactant layer on the outside
562 //
563 // bragg peaks arise naturally from the periodicity of the sample
564 // resolution smeared version gives he most appropriate view of the model
565 //
566 // Polydispersity is of the total (outer) radius. This is converted into a distribution of MLV's
567 // with integer numbers of layers, with a minimum of one layer... a vesicle... depending
568 // on the parameters, the "distribution" of MLV's that is used may be truncated
569 //
570        Warning:
571 The call to WaveData() below returns a pointer to the middle
572 of an unlocked Macintosh handle. In the unlikely event that your
573 calculations could cause memory to move, you should copy the coefficient
574 values to local variables or an array before such operations.
575 */
576int
577PolyMultiShellX(FitParamsPtr p)
578{
579        double *dp;                             // Pointer to double precision wave data.
580        float *fp;                              // Pointer to single precision wave data.
581        double q;               //local variables of coefficient wave
582       
583        if (p->waveHandle == NIL) {
584                SetNaN64(&p->result);
585                return NON_EXISTENT_WAVE;
586        }
587       
588        q= p->x;
589       
590        switch(WaveType(p->waveHandle)){                        // We can handle single and double precision coefficient waves.
591                case NT_FP32:
592                        fp= WaveData(p->waveHandle);
593                        SetNaN64(&p->result);
594                        return REQUIRES_SP_OR_DP_WAVE; //not quite true, but good enough for now AJJ 4/23/07                   
595                case NT_FP64:
596                        dp= WaveData(p->waveHandle);
597                        p->result = PolyMultiShell(dp,q);
598                        return 0;
599                default:                                                                // We can't handle this wave data type.
600                        SetNaN64(&p->result);
601                        return REQUIRES_SP_OR_DP_WAVE;
602        }       
603        return 0;
604}
605
606
607#pragma XOP_RESET_STRUCT_PACKING                        // All structures are 2-byte-aligned.
608
609///////////end of XOP
610
611
Note: See TracBrowser for help on using the repository browser.