1 | #include "modelCalculations.h" |
---|
2 | #include "canvas.h" |
---|
3 | #include <stdio.h> |
---|
4 | #include <stdlib.h> |
---|
5 | #include <math.h> |
---|
6 | #include <memory.h> |
---|
7 | #include <time.h> |
---|
8 | |
---|
9 | /** |
---|
10 | * Initialization function for simulation structure |
---|
11 | */ |
---|
12 | int canvas_init(CanvasParams *pars) { |
---|
13 | int i; |
---|
14 | |
---|
15 | pars->n_shapes = 0; |
---|
16 | pars->max_shapes = 3; |
---|
17 | |
---|
18 | // Allocate memory |
---|
19 | pars->shapes = (SpaceObject*) malloc(pars->max_shapes*sizeof(SpaceObject)); |
---|
20 | |
---|
21 | if(pars->shapes==NULL) { |
---|
22 | printf("canvas_init: Problem allocating memory for space objects\n"); |
---|
23 | return -1; |
---|
24 | } |
---|
25 | |
---|
26 | return 0; |
---|
27 | } |
---|
28 | |
---|
29 | int canvas_dealloc(CanvasParams *self) { |
---|
30 | int i; |
---|
31 | printf("dealloc\n"); |
---|
32 | /* |
---|
33 | //for(i=0; i<self->n_shapes; i++) { |
---|
34 | for(i=0; i<self->max_shapes; i++) { |
---|
35 | free(self->shapes[i].points); |
---|
36 | free(self->shapes[i].params); |
---|
37 | //free(self->shapes[i].generate); |
---|
38 | } |
---|
39 | */ |
---|
40 | free(self->shapes); |
---|
41 | printf("deallocated\n"); |
---|
42 | return 0; |
---|
43 | } |
---|
44 | |
---|
45 | int canvas_add(CanvasParams *self, int objectCode) { |
---|
46 | int id; |
---|
47 | id = self->n_shapes; |
---|
48 | |
---|
49 | if(objectCode==REALSPACE_SPHERE) { |
---|
50 | initSphereObject( &(self->shapes[id]) ); |
---|
51 | } |
---|
52 | |
---|
53 | self->shapes[id].layer = id; |
---|
54 | self->n_shapes++; |
---|
55 | |
---|
56 | return id; |
---|
57 | } |
---|
58 | |
---|
59 | int canvas_setParam(CanvasParams *self, int shapeID, int paramID, double value) { |
---|
60 | self->shapes[shapeID].params[paramID]=value; |
---|
61 | self->shapes[shapeID].points_available = 0; |
---|
62 | |
---|
63 | // update volume |
---|
64 | self->shapes[shapeID].volume = (*self->shapes[shapeID].getVolume)(&(self->shapes[shapeID].params)); |
---|
65 | |
---|
66 | return 0; |
---|
67 | } |
---|
68 | |
---|
69 | double canvas_intensity(CanvasParams *self, double q, double phi) { |
---|
70 | double phase, cos_term, sin_term; |
---|
71 | double qx, qy, vol; |
---|
72 | int i, j, npts; |
---|
73 | double pars[4]; |
---|
74 | |
---|
75 | double cos_shape, sin_shape; |
---|
76 | |
---|
77 | double vol_core, vol_shell, vol_sum; |
---|
78 | |
---|
79 | pars[0] = 1.0; |
---|
80 | pars[1] = 40.0; |
---|
81 | |
---|
82 | cos_term = 0.0; |
---|
83 | sin_term = 0.0; |
---|
84 | |
---|
85 | vol_sum = 0.0; |
---|
86 | |
---|
87 | vol = self->shapes[0].volume; |
---|
88 | vol_core = self->shapes[1].volume; |
---|
89 | vol_shell = vol-vol_core; |
---|
90 | |
---|
91 | npts = 0; |
---|
92 | |
---|
93 | qx = q*cos(phi); |
---|
94 | qy = q*sin(phi); |
---|
95 | |
---|
96 | for(i=0; i<self->n_shapes; i++) { |
---|
97 | if (self->shapes[i].points_available==0) { |
---|
98 | (*self->shapes[i].generate)( self->shapes[i].points, self->shapes[i].params, self->shapes[i].npts); |
---|
99 | self->shapes[i].points_available=1; |
---|
100 | } |
---|
101 | npts = 0; |
---|
102 | cos_shape = 0; |
---|
103 | sin_shape = 0; |
---|
104 | for(j=0; j<self->shapes[i].npts; j++) { |
---|
105 | |
---|
106 | if(canvas_PointAllowed(self, i, j)==1) { |
---|
107 | npts++; |
---|
108 | |
---|
109 | phase = qx*self->shapes[i].points[j].x + qy*self->shapes[i].points[j].y; |
---|
110 | //phase = 0.0; |
---|
111 | |
---|
112 | cos_shape += cos(phase); |
---|
113 | sin_shape += sin(phase); |
---|
114 | } |
---|
115 | } |
---|
116 | |
---|
117 | //printf("ID %i: cos=%g sin=%g fac=%g\n",i,cos_shape, sin_shape, self->shapes[i].volume /self->shapes[i].npts * self->shapes[i].params[2]); |
---|
118 | |
---|
119 | |
---|
120 | |
---|
121 | |
---|
122 | // TODO: must find an efficient way to get the exact volume of each SLD regions. |
---|
123 | // For instance, if a volume is completely included in another (and it has a higher layer |
---|
124 | // number, we can simply subtract the two "theoretical" volumes instead of using the |
---|
125 | // ratio of the points. |
---|
126 | |
---|
127 | // The following are the three lines we would like to write: |
---|
128 | |
---|
129 | //cos_term += cos_shape * self->shapes[i].volume /npts * self->shapes[i].params[2]; |
---|
130 | //sin_term += sin_shape * self->shapes[i].volume /npts * self->shapes[i].params[2]; |
---|
131 | //vol_sum += self->shapes[i].volume; |
---|
132 | |
---|
133 | // In that case, the volume is approx |
---|
134 | // vol = (full volume) - sum(volume parts overlapping with other objects) |
---|
135 | // That can easily be done for object completely contained by others. |
---|
136 | |
---|
137 | cos_term += cos_shape * self->shapes[i].volume /self->shapes[i].npts * self->shapes[i].params[2]; |
---|
138 | sin_term += sin_shape * self->shapes[i].volume /self->shapes[i].npts * self->shapes[i].params[2]; |
---|
139 | vol_sum += self->shapes[i].volume*npts/self->shapes[i].npts; |
---|
140 | |
---|
141 | |
---|
142 | //vol_sum += self->shapes[i].volume; |
---|
143 | |
---|
144 | // The following is more precise (but implies better investigation of the topology) |
---|
145 | /* |
---|
146 | if(i==0){ |
---|
147 | cos_term += cos_shape * vol_shell/npts * self->shapes[i].params[2]; |
---|
148 | sin_term += sin_shape * vol_shell/npts * self->shapes[i].params[2]; |
---|
149 | vol_sum += vol_shell; |
---|
150 | } else { |
---|
151 | cos_term += cos_shape * vol_core/npts * self->shapes[i].params[2]; |
---|
152 | sin_term += sin_shape * vol_core/npts * self->shapes[i].params[2]; |
---|
153 | vol_sum += vol_core; |
---|
154 | } |
---|
155 | */ |
---|
156 | } |
---|
157 | |
---|
158 | return 1.0e8*(cos_term*cos_term + sin_term*sin_term)/vol_sum; |
---|
159 | } |
---|
160 | |
---|
161 | int canvas_PointAllowed(CanvasParams *self, int object_id, int i_pt) { |
---|
162 | // Check whether space point i_pt is already covered by another object |
---|
163 | int i; |
---|
164 | |
---|
165 | for(i=0; i<self->n_shapes; i++) { |
---|
166 | // Check the object object_id is underneath |
---|
167 | if(self->shapes[object_id].layer < self->shapes[i].layer) { |
---|
168 | // Is the point overlapping, if so skip it. |
---|
169 | if(self->shapes[i].isContained(&self->shapes[object_id].points[i_pt], |
---|
170 | self->shapes[i].params) == 1) { |
---|
171 | return 0; |
---|
172 | } |
---|
173 | } |
---|
174 | } |
---|
175 | return 1; |
---|
176 | } |
---|
177 | |
---|
178 | |
---|
179 | |
---|
180 | // SPHERE object ---------------------------------------------------------------------- |
---|
181 | |
---|
182 | |
---|
183 | int initSphereObject(SpaceObject *pars) { |
---|
184 | |
---|
185 | pars->x = 0.0; |
---|
186 | pars->y = 0.0; |
---|
187 | pars->z = 0.0; |
---|
188 | |
---|
189 | pars->o1 = 0.0; |
---|
190 | pars->o2 = 0.0; |
---|
191 | pars->o3 = 0.0; |
---|
192 | |
---|
193 | /* |
---|
194 | free(pars->params); |
---|
195 | |
---|
196 | printf("allocating parameters\n"); |
---|
197 | pars->params = (double*) malloc(5*sizeof(double)); |
---|
198 | if(pars->params==NULL) { |
---|
199 | printf("initSphereObject: Problem allocating memory\n"); |
---|
200 | return -1; |
---|
201 | } |
---|
202 | */ |
---|
203 | |
---|
204 | // Scale |
---|
205 | pars->params[0] = 1.0; |
---|
206 | // Radius |
---|
207 | pars->params[1] = 40.0; |
---|
208 | // Contrast |
---|
209 | pars->params[2] = 1.0; |
---|
210 | |
---|
211 | pars->points_available = 0; |
---|
212 | |
---|
213 | pars->npts = 150000; |
---|
214 | free(pars->points); |
---|
215 | |
---|
216 | // Generation function |
---|
217 | pars->generate = &generateSphereObject; |
---|
218 | // isContained function |
---|
219 | pars->isContained = &sphere_IsContained; |
---|
220 | pars->getVolume = &sphere_getVolume; |
---|
221 | |
---|
222 | pars->volume = acos(-1.0)*4.0/3.0*pars->params[1]*pars->params[1]*pars->params[1]; |
---|
223 | |
---|
224 | pars->layer = 0; |
---|
225 | |
---|
226 | return 0; |
---|
227 | |
---|
228 | } |
---|
229 | |
---|
230 | int sphere_IsContained(SpacePoint *point, double *params) { |
---|
231 | if( sqrt(point->x*point->x + point->y*point->y + point->z*point->z) < params[1]) { |
---|
232 | return 1; |
---|
233 | } |
---|
234 | return 0; |
---|
235 | } |
---|
236 | |
---|
237 | double sphere_getVolume(double *params) { |
---|
238 | printf("radius=%g\n",params[1]); |
---|
239 | return acos(-1.0)*4.0/3.0*params[1]*params[1]*params[1]; |
---|
240 | } |
---|
241 | |
---|
242 | |
---|
243 | int generateSphereObject(SpacePoint *points, double *params, int npts) { |
---|
244 | int i, testcounter; |
---|
245 | double x, y, z; |
---|
246 | SpacePoint tmp; |
---|
247 | |
---|
248 | printf("radius=%g, npts=%i\n", params[1], npts); |
---|
249 | |
---|
250 | testcounter = 0; |
---|
251 | |
---|
252 | /* |
---|
253 | free(points); |
---|
254 | printf("allocating points\n"); |
---|
255 | points = (SpacePoint*) malloc(npts*sizeof(SpacePoint)); |
---|
256 | if(points==NULL) { |
---|
257 | printf("generateSphereObject: Problem allocating memory\n"); |
---|
258 | return -1; |
---|
259 | } |
---|
260 | */ |
---|
261 | memset(points,0,npts*sizeof(SpacePoint)); |
---|
262 | |
---|
263 | for(i=0;i<npts;i++) { |
---|
264 | // Generate in a box centered around zero |
---|
265 | x = (2.0*((double)rand())/((double)(RAND_MAX)+(double)(1))-1.0) * params[1]; |
---|
266 | y = (2.0*((double)rand())/((double)(RAND_MAX)+(double)(1))-1.0) * params[1]; |
---|
267 | z = (2.0*((double)rand())/((double)(RAND_MAX)+(double)(1))-1.0) * params[1]; |
---|
268 | |
---|
269 | // reject those that are not within the volume |
---|
270 | // if( sqrt(x*x+y*y+z*z) < params[1]) { |
---|
271 | tmp.x = x; |
---|
272 | tmp.y = y; |
---|
273 | tmp.z = z; |
---|
274 | if( sphere_IsContained(&tmp, params) == 1 ) { |
---|
275 | points[i].x = x; |
---|
276 | points[i].y = y; |
---|
277 | points[i].z = z; |
---|
278 | testcounter++; |
---|
279 | } else { |
---|
280 | i--; |
---|
281 | } |
---|
282 | } |
---|
283 | |
---|
284 | // Consistency check |
---|
285 | if(testcounter != npts) { |
---|
286 | return -1; |
---|
287 | } |
---|
288 | |
---|
289 | return testcounter; |
---|
290 | |
---|
291 | } |
---|