Commit 8d8c3ebd609c8bc1175c0ce9ff1c92b558529b51
0 parents
initial commit transferring bimsym to bimsim
Showing
4 changed files
with
520 additions
and
0 deletions
Show diff stats
1 | +++ a/CMakeLists.txt | |
1 | +#Specify the version being used aswell as the language | |
2 | +cmake_minimum_required(VERSION 2.8) | |
3 | +#Name your project here | |
4 | +project(bimsym) | |
5 | + | |
6 | + | |
7 | + | |
8 | +#set the module directory | |
9 | +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") | |
10 | + | |
11 | +#set up CUDA | |
12 | +find_package(CUDA) | |
13 | + | |
14 | +#find OpenCV | |
15 | +find_package(OpenCV REQUIRED ) | |
16 | + | |
17 | +find_package(Boost REQUIRED) | |
18 | + | |
19 | +#find the STIM library | |
20 | +find_package(STIM) | |
21 | + | |
22 | +#build the executable in the binary directory on MS Visual Studio | |
23 | +if ( MSVC ) | |
24 | + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${OUTPUT_DIRECTORY}") | |
25 | + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${OUTPUT_DIRECTORY}") | |
26 | +endif ( MSVC ) | |
27 | + | |
28 | +#set the include directories | |
29 | +include_directories( | |
30 | + ${CMAKE_CURRENT_BINARY_DIR} | |
31 | + ${CMAKE_CURRENT_SOURCE_DIR} | |
32 | + ${STIM_INCLUDE_DIRS} | |
33 | + ${Boost_INCLUDE_DIRS} | |
34 | +) | |
35 | + | |
36 | +#SET(CUDA_NVCC_FLAGS_RELEASE ${CUDA_NVCC_FLAGS};/maxregcount=60) | |
37 | + | |
38 | +#create an executable | |
39 | +cuda_add_executable(bimsym | |
40 | + bimsym.cu | |
41 | + sources.h | |
42 | +) | |
43 | + | |
44 | +#set the link libraries | |
45 | +target_link_libraries(bimsym | |
46 | + ${CUDA_cufft_LIBRARY} | |
47 | + ${CUDA_cublas_LIBRARY} | |
48 | + ${OpenCV_LIBS} | |
49 | + ) | |
50 | + | |
51 | + | |
52 | + | ... | ... |
1 | +++ a/bimsym.cu | |
1 | +#define CUDA_FOUND | |
2 | +#define USING_OPENCV | |
3 | + | |
4 | +#include <iostream> | |
5 | + | |
6 | +#include <stim/visualization/colormap.h> | |
7 | + | |
8 | +#include <stim/parser/arguments.h> | |
9 | +#include <stim/math/vec3.h> | |
10 | +#include <stim/optics/scalarbeam.h> | |
11 | +#include <stim/optics/scalarmie.h> | |
12 | +#include <stim/parser/filename.h> | |
13 | +#include <stim/ui/progressbar.h> | |
14 | +#include <stim/parser/table.h> | |
15 | + | |
16 | +#include <stim/cuda/cudatools.h> | |
17 | + | |
18 | +#include <sources.h> //default source types | |
19 | + | |
20 | +#include <chrono> | |
21 | +#include <thread> | |
22 | + | |
23 | +//field parameters | |
24 | +size_t g_R_nf; //near-field resolution along X and Y | |
25 | +double g_S_nf; //size of the near field simulation | |
26 | +double g_Z_nf; //z position of the field slice | |
27 | +std::vector<stim::vec3<float>> g_sources; //point source position list | |
28 | + | |
29 | +bool use_cuda = true; | |
30 | +int cuda_device; | |
31 | +int cuda_major = 3; | |
32 | +int cuda_minor = 0; | |
33 | +bool use_backprop = true; | |
34 | + | |
35 | +//incident beam parameters | |
36 | +double g_NA_cond[2]; //condenser numerical aperture, [internal, external] | |
37 | +double g_lambda; //incident wavelength | |
38 | +size_t g_Nl; //number of orders used to calculate the incident field | |
39 | +double g_A; //amplitude of the incident field | |
40 | + | |
41 | +//scattering parameters | |
42 | +stim::scalarcluster<float> spheres; | |
43 | +//std::vector<double> g_radius(1); //radius of the scattering sphere | |
44 | +//std::vector< stim::complex<double> > g_n(1); //refractive index of the scattering sphere | |
45 | +size_t g_MC; //number of monte-carlo samples used to calculate the scattered field | |
46 | +//std::vector< stim::vec3<float> > g_c(1); //center of the sphere | |
47 | + | |
48 | +//far field parameters | |
49 | +double g_NA_obj[2]; //objective numerical aperture | |
50 | +size_t g_padding; //padding applied to the near-field calculation in order to improve the quality of the band-pass | |
51 | +double g_backprop = 0; //number of units that the field has to be backpropagated by in order to approximate a near-field slice passing through a sphere | |
52 | +size_t g_R_ff; //number of samples along X and Y in the far field image | |
53 | +double g_S_ff; //size (in units) of the far field image | |
54 | +double g_Z_ff; //position of the near-field plane projected into the far field (position of the back-propagated plane) | |
55 | + | |
56 | +//debugging | |
57 | +bool g_debug_images = false; | |
58 | +bool g_verbose = false; | |
59 | + | |
60 | +stim::filename outfile("out.bmp"); //output file name | |
61 | + | |
62 | +stim::arglist args; //input arguments | |
63 | + | |
64 | +template<typename T> | |
65 | +__global__ void cuda_absorbance(T* out, T* I, T* I0, size_t N){ | |
66 | + | |
67 | + size_t i = blockIdx.x * blockDim.x + threadIdx.x; | |
68 | + | |
69 | + if(i >= N) return; | |
70 | + | |
71 | + out[i] = -log10(I[i] / I0[i]); | |
72 | +} | |
73 | + | |
74 | +/// Crops a 2D image composed of elements of type T | |
75 | +/// @param dest is a device pointer to memory of size dx*dy that will store the cropped image | |
76 | +/// @param src is a device pointer to memory of size sx*sy that stores the original image | |
77 | +/// @param sx is the size of the source image along x | |
78 | +/// @param sy is the size of the source image along y | |
79 | +/// @param x is the x-coordinate of the start position of the cropped region within the source image | |
80 | +/// @param y is the y-coordinate of the start position of the cropped region within the source image | |
81 | +/// @param dx is the size of the destination image along x | |
82 | +/// @param dy is the size of the destination image along y | |
83 | +template<typename T> | |
84 | +void gpu_absorbance(T* A, T* I, T* I0, size_t N){ | |
85 | + int threads = stim::maxThreadsPerBlock(); //get the maximum number of threads per block for the CUDA device | |
86 | + | |
87 | + dim3 blocks( N / threads + 1 ); //calculate the optimal number of blocks | |
88 | + cuda_absorbance<T> <<< blocks, threads >>>(A, I, I0, N); | |
89 | +} | |
90 | + | |
91 | +//function to display a progress bar | |
92 | +void progressbar_thread(double* e){ | |
93 | + | |
94 | + unsigned int p = 0; | |
95 | + while(p != 100){ | |
96 | + if(*e > p){ | |
97 | + p = (unsigned int)(*e); | |
98 | + rtsProgressBar(p); | |
99 | + } | |
100 | + } | |
101 | + std::cout<<std::endl; //put a newline after the completed progress bar | |
102 | +} | |
103 | + | |
104 | +void advertise(){ | |
105 | + //output advertisement | |
106 | + std::cout<<std::endl<<std::endl; | |
107 | + std::cout<<"========================================================================="<<std::endl; | |
108 | + | |
109 | + std::cout<<"========================================================================="<<std::endl<<std::endl; | |
110 | + | |
111 | + std::cout<<std::endl<<std::endl; | |
112 | + | |
113 | + std::cout<<args.str(); | |
114 | +} | |
115 | + | |
116 | +void set_arguments(int argc, char* argv[]){ | |
117 | + args.add("help", "prints this help text"); | |
118 | + | |
119 | + args.section("Field Slice Parameters"); | |
120 | + args.add("res", "field resolution (number of samples along X and Y)", "256", "nonzero positive integer"); | |
121 | + args.add("size", "size of the calculated field", "10", "nonzero positive value"); | |
122 | + args.add("z", "position of the field slice along the z axis", "0", "any real value"); | |
123 | + | |
124 | + args.section("Incoherent Sources"); | |
125 | + args.add("simage", "image of the source at the focal plane (z=0)", "", "any standard image format"); | |
126 | + args.add("sgrid", "grid of n x n point sources", "", "n"); | |
127 | + | |
128 | + args.section("Incident Field Parameters"); | |
129 | + args.add("f", "position of a single focal point", "0 0", "x y position (z = 0)"); | |
130 | + args.add("condenser", "condenser numerical aperture (NA) and center obscuration", "1", "'sin(a1)' or 'sin(a1) sin(a0)', where a0 = center obscuration"); | |
131 | + args.add("lambda", "incident wavelength", "1", "any real positive value"); | |
132 | + args.add("wavenumber", "incident wavelength specified in cm^(-1)", "", "any real positive value, sets all units to microns"); | |
133 | + args.add("order", "order used to calculate the incident field", "20", "any nonzero integer"); | |
134 | + | |
135 | + args.section("Mie Scattering Parameters"); | |
136 | + args.add("c", "center of the scattering sphere", "0 0 0", "any real 3D coordinate"); | |
137 | + args.add("radius", "radius of the scattering sphere", "0.5", "any real positive value"); | |
138 | + args.add("n", "complex refractive index of the scattering sphere", "1.4 0.1", "[r] or [r i]"); | |
139 | + args.add("samples", "number of Monte-Carlo samples used to calculate the scattered field", "1000", "any real positive integer"); | |
140 | + args.add("spheres", "specify a file defining several spheres", "", "(1/line: radius, real RI, imag RI, x, y, z)"); | |
141 | + | |
142 | + args.section("Far Field Parameters"); | |
143 | + args.add("objective", "objective numerical aperture (NA) and center obscuration", "1", "'sin(b1)' or 'sin(b1) sin(b0)', where b0 = center obscuration"); | |
144 | + args.add("padding", "padding for the near field calculation (improves far-field calculation)", "1", "any real positive integer"); | |
145 | + args.add("nobackprop", "don't use back-propagation to deal with sphere intersections"); | |
146 | + | |
147 | + args.section("Debugging"); | |
148 | + args.add("cuda", "CUDA device ID of device to use (-1 disables CUDA)", "0", "integer value"); | |
149 | + args.add("debug", "outputs a debug image at several important intermediate steps of the Mie scattering calculation"); | |
150 | + args.add("verbose", "outputs additional information regarding the Mie calculations as they are performed"); | |
151 | + args.parse(argc, argv); | |
152 | + | |
153 | + if(args["help"].is_set()){ | |
154 | + advertise(); | |
155 | + exit(1); | |
156 | + } | |
157 | +} | |
158 | + | |
159 | +void output_simulation(){ | |
160 | + std::cout<<"far field slice-------"<<std::endl; | |
161 | + std::cout<<"R: "<<g_R_ff<<" x "<<g_R_ff<<" pixels"<<std::endl; | |
162 | + std::cout<<"S: "<<g_S_ff<<" x "<<g_S_ff<<" units"<<std::endl; | |
163 | + std::cout<<"Z: "<<g_Z_ff<<" units"<<std::endl; | |
164 | + | |
165 | + std::cout<<"objective NA: "<<g_NA_obj[1]; | |
166 | + if(g_NA_obj[0] != 0) std::cout<<" (internal = "<<g_NA_obj[0]<<")"; | |
167 | + std::cout<<std::endl; | |
168 | + std::cout<<"padding: "<<g_padding<<std::endl; | |
169 | + std::cout<<"backprop: "<<g_backprop<<" units"<<std::endl; | |
170 | + std::cout<<std::endl; | |
171 | + | |
172 | + std::cout<<"near field slice------"<<std::endl; | |
173 | + std::cout<<"R: "<<g_R_nf<<" x "<<g_R_nf<<" pixels"<<std::endl; | |
174 | + std::cout<<"S: "<<g_S_nf<<" x "<<g_S_nf<<" units"<<std::endl; | |
175 | + std::cout<<"Z: "<<g_Z_nf<<" units"<<std::endl; | |
176 | + std::cout<<std::endl; | |
177 | + | |
178 | + std::cout<<"incident field--------"<<std::endl; | |
179 | + std::cout<<"condenser NA: "<<g_NA_cond[1]; | |
180 | + if(g_NA_cond[0] != 0) std::cout<<" (internal = "<<g_NA_cond[0]<<")"; | |
181 | + std::cout<<std::endl; | |
182 | + std::cout<<"wavelength: "<<g_lambda<<" units"<<std::endl; | |
183 | + std::cout<<"order: "<<g_Nl<<std::endl; | |
184 | + std::cout << "# sources: " << g_sources.size()<<" "; | |
185 | + if (g_sources.size() == 1) | |
186 | + std::cout << g_sources[0].str(); | |
187 | + std::cout << std::endl; | |
188 | + std::cout<<std::endl; | |
189 | + | |
190 | + std::cout<<"mie scattering-------"<<std::endl; | |
191 | + if (spheres.size() == 1) { | |
192 | + std::cout << "center: " << spheres[0].c << " units" << std::endl; | |
193 | + std::cout << "radius: " << spheres[0].radius << " units" << std::endl; | |
194 | + std::cout << "ref. index: " << spheres[0].n << std::endl; | |
195 | + } | |
196 | + else { | |
197 | + for (size_t si = 0; si < spheres.size(); si++) { | |
198 | + std::cout << "sphere [" << si << "]: r = " << spheres[si].radius << " n = " << spheres[si].n << " c = " << spheres[si].c << std::endl; | |
199 | + } | |
200 | + } | |
201 | + std::cout << "MC samples: " << g_MC << std::endl; | |
202 | + std::cout<<std::endl; | |
203 | +} | |
204 | + | |
205 | +void load_spheres(std::string filename) { | |
206 | + stim::table t; | |
207 | + t.read_ascii(filename, ' '); | |
208 | + | |
209 | + std::cout << t.str() << std::endl; | |
210 | + size_t ns = t.rows(); | |
211 | + spheres.resize(ns); | |
212 | + | |
213 | + std::vector< std::vector< double > > s = t.get_vector< double >(); | |
214 | + | |
215 | + | |
216 | + for (size_t si = 0; si < ns; si++) { //for each sphere in the file | |
217 | + spheres[si] = stim::scalarmie<float>(s[si][0], //generate a corresponding scalar mie object in the cluster | |
218 | + stim::complex<float>(s[si][1], s[si][2]), | |
219 | + stim::vec3<float>(s[si][3], s[si][4], s[si][5])); | |
220 | + } | |
221 | +} | |
222 | + | |
223 | +void set_simulation(){ | |
224 | + | |
225 | + if(args.nargs() > 0) outfile = args.arg(0); //the first argument is the filename (if any) | |
226 | + | |
227 | + if (args["cuda"].as_int() == -1) use_cuda = false; | |
228 | + if (use_cuda) cuda_device = args["cuda"].as_int(); | |
229 | + if (!stim::testDevice(cuda_device, cuda_major, cuda_minor)) { //make sure the device supports the necessary compute capability | |
230 | + std::cout << "ERROR: CUDA device doesn't support compute capability " << cuda_major << "." << cuda_minor << std::endl; | |
231 | + exit(1); | |
232 | + } | |
233 | + if(args["debug"].is_set()) g_debug_images = true; //set debug flags | |
234 | + if(args["verbose"].is_set()) g_verbose = true; | |
235 | + | |
236 | + //set the condenser NA | |
237 | + g_NA_cond[1] = args["condenser"].as_float(0); //set the external condenser NA | |
238 | + if(args["condenser"].nargs() == 2) g_NA_cond[0] = args["condenser"].as_float(1); //if the internal NA is specified, use it | |
239 | + else g_NA_cond[0] = 0; //otherwise set the internal NA to zero | |
240 | + | |
241 | + //set the incident wavelength | |
242 | + if(args["wavenumber"].is_set()) //if the wavelength is given in terms of wavenumber | |
243 | + g_lambda = 10000.0 / args["wavenumber"].as_float(0); //convert to wavelength (assume microns) | |
244 | + else | |
245 | + g_lambda = args["lambda"].as_float(0); //otherwise assume the wavelength is specified in microns | |
246 | + | |
247 | + g_Nl = args["order"].as_int(0); //set the incident field order | |
248 | + | |
249 | + //set the mie scattering parameters | |
250 | + g_MC = args["samples"].as_int(); //get the number of monte-carlo samples | |
251 | + if (args["spheres"]) { | |
252 | + load_spheres(args["spheres"].as_string()); | |
253 | + } | |
254 | + else { //otherwise store the sphere specified at the command line | |
255 | + float radius = args["radius"].as_float(0); //set the radius of the sphere | |
256 | + stim::complex<float> n; | |
257 | + n.real(args["n"].as_float(0)); //set the real part of the refractive index | |
258 | + if (args["n"].nargs() == 2) //if an imaginary part is specified | |
259 | + n.imag(args["n"].as_float(1)); //set the imaginary part | |
260 | + else n.imag(0); //otherwise assume the imaginary part is zero | |
261 | + stim::vec3<float> c = stim::vec3<float>(args["c"].as_float(0), args["c"].as_float(1), args["c"].as_float(2)); | |
262 | + spheres.resize(1); | |
263 | + spheres[0] = stim::scalarmie<float>(radius, n, c); | |
264 | + } | |
265 | + | |
266 | + g_padding = args["padding"].as_int(); //get the near field padding factor | |
267 | + g_R_ff = args["res"].as_int(0); | |
268 | + g_R_nf = g_R_ff * (2 * g_padding + 1); //set the field resolution to the first resolution argument | |
269 | + g_S_ff = args["size"].as_int(0); | |
270 | + g_S_nf = g_S_ff * (2 * g_padding + 1); //get the size of the field slice (assume square at first) | |
271 | + g_Z_ff = args["z"].as_float(); //get the z-axis position for the desired far-field image | |
272 | + | |
273 | + if (args["nobackprop"]) use_backprop = false; | |
274 | + if(use_backprop && (abs(g_Z_ff) < spheres[0].radius)){ //if the near field slice is cutting through the sphere | |
275 | + g_backprop = g_Z_ff - spheres[0].radius; //calculate the number of units that the field has to be back-propagated | |
276 | + g_Z_nf = spheres[0].radius; | |
277 | + } | |
278 | + else { | |
279 | + g_Z_nf = g_Z_ff; | |
280 | + } | |
281 | + | |
282 | + g_NA_obj[1] = args["objective"].as_float(0); //set the external condenser NA | |
283 | + if(args["objective"].nargs() == 2) g_NA_obj[0] = args["objective"].as_float(1); //if the internal NA is specified, use it | |
284 | + else g_NA_obj[0] = 0; //otherwise set the internal NA to zero | |
285 | + | |
286 | + if (args["simage"].is_set()) //if a source image is provided | |
287 | + g_sources = simage<float>(g_S_ff, args["simage"].as_string()); //convert the image to a list of sources | |
288 | + else if (args["sgrid"]) { | |
289 | + if (args["sgrid"].nargs() == 1) | |
290 | + g_sources = sgrid<float>(g_S_ff, args["sgrid"].as_int()); | |
291 | + else | |
292 | + g_sources = sgrid<float>(g_S_ff, args["sgrid"].as_int(0), args["sgrid"].as_int(1)); | |
293 | + } | |
294 | + else | |
295 | + g_sources.push_back( stim::vec3<float>(args["f"].as_float(0), args["f"].as_float(1), 0) ); //otherwise just put a single point source at the origin | |
296 | +} | |
297 | + | |
298 | +int main(int argc, char* argv[]){ | |
299 | + set_arguments(argc, argv); //set the input arguments | |
300 | + set_simulation(); //set all simulation parameters | |
301 | + | |
302 | + if(g_verbose) output_simulation(); //output all simulation parameters | |
303 | + | |
304 | + stim::vec3<float> d(0, 0, 1); //beam direction | |
305 | + | |
306 | + size_t I_bytes = sizeof(float) * g_R_ff * g_R_ff; //number of bytes in the final intensity images | |
307 | + | |
308 | + //background intensity image | |
309 | + float* I0; //allocate space for the background intensity image | |
310 | + float* I; | |
311 | + | |
312 | + stim::scalarfield<float> E0(g_R_nf, g_R_nf, (float)g_S_nf, (float)g_Z_nf + (float)g_backprop); //incident nearfield | |
313 | + stim::scalarfield<float> E(g_R_nf, g_R_nf, (float)g_S_nf, (float)g_Z_nf); //create the scattered field | |
314 | + stim::scalarfield<float> Eff(g_R_ff, g_R_ff, (float)g_S_ff, (float)g_Z_ff); //create the far field | |
315 | + | |
316 | + float* X = (float*) malloc( E0.size() * sizeof(float) ); | |
317 | + float* Y = (float*) malloc( E0.size() * sizeof(float) ); | |
318 | + float* Z = (float*) malloc( E0.size() * sizeof(float) ); | |
319 | + E.meshgrid(X, Y, Z, stim::CPUmem); //create a meshgrid for the scattering plane (different from E0 b/c we can't propagate the internal field) | |
320 | + | |
321 | + | |
322 | + E0.meshgrid(); //create meshgrids in the field object for field calculations | |
323 | + E.meshgrid(); | |
324 | + | |
325 | + if (use_cuda) { | |
326 | + cudaSetDevice(cuda_device); | |
327 | + HANDLE_ERROR(cudaMalloc(&I0, I_bytes)); | |
328 | + HANDLE_ERROR(cudaMemset(I0, 0, I_bytes)); //create an array to store the image intensity | |
329 | + HANDLE_ERROR(cudaMalloc(&I, I_bytes)); | |
330 | + HANDLE_ERROR(cudaMemset(I, 0, I_bytes)); | |
331 | + E0.to_gpu(); | |
332 | + E.to_gpu(); | |
333 | + } | |
334 | + else { | |
335 | + I0 = (float*)calloc(I_bytes, 1); | |
336 | + I = (float*)calloc(I_bytes, 1); | |
337 | + } | |
338 | + | |
339 | + std::chrono::high_resolution_clock::time_point t_begin = std::chrono::high_resolution_clock::now(); | |
340 | + double P = 0; | |
341 | + std::thread t1(progressbar_thread, &P); //start the progress bar thread | |
342 | + for(size_t s = 0; s < g_sources.size(); s++){ | |
343 | + stim::scalarbeam<float> beam((float)g_lambda, 1, g_sources[s], d, (float)g_NA_cond[1], (float)g_NA_cond[0]); //create a focused beam | |
344 | + | |
345 | + beam.eval(E0, g_Nl); //evaluate the incident field | |
346 | + | |
347 | + if(g_debug_images && s == 0){ | |
348 | + stim::filename incident_file = outfile.prefix(outfile.prefix() + "_0_nfi"); | |
349 | + E0.image(incident_file.str(), stim::complexMag); | |
350 | + } | |
351 | + E0.crop(g_padding, Eff); | |
352 | + Eff.intensity(I0); | |
353 | + | |
354 | + spheres.eval(E, beam, g_Nl, g_MC); | |
355 | + | |
356 | + if(g_debug_images && s == 0){ | |
357 | + stim::filename nf_file = outfile.prefix(outfile.prefix() + "_1_nfs"); | |
358 | + E.image(nf_file.str(), stim::complexMag); | |
359 | + } | |
360 | + | |
361 | + E.propagate(g_backprop, stim::TAU / g_lambda); //propagate the field back to the origin | |
362 | + | |
363 | + if(g_debug_images && s == 0){ | |
364 | + stim::filename propagate_file = outfile.prefix(outfile.prefix()+"_2_nfprop"); | |
365 | + E.image(propagate_file.str(), stim::complexMag); | |
366 | + } | |
367 | + | |
368 | + E.crop(g_padding, Eff); //crop out the far field slice | |
369 | + Eff.intensity(I); //calculate the far field intensity and add it to the single-beam image | |
370 | + | |
371 | + if(g_debug_images && s == 0){ | |
372 | + stim::filename cropped_file = outfile.prefix(outfile.prefix() + "_3_cropped"); | |
373 | + Eff.image(cropped_file.str(), stim::complexMag); | |
374 | + } | |
375 | + P = (double)(s + 1) / (double)g_sources.size() * 100; | |
376 | + | |
377 | + } | |
378 | + t1.join(); | |
379 | + | |
380 | + std::chrono::high_resolution_clock::time_point t_end = std::chrono::high_resolution_clock::now(); | |
381 | + std::chrono::duration<double> t_total = (t_end - t_begin); | |
382 | + std::cout<<"Time: "<<t_total.count()<<" s"<<std::endl; | |
383 | + | |
384 | + //save the near-field image | |
385 | + if (g_debug_images) { | |
386 | + stim::filename nearfield_real_file = outfile.prefix(outfile.prefix() + "_3_detector_real"); | |
387 | + E.image(nearfield_real_file.str(), stim::complexReal); | |
388 | + stim::filename nearfield_imag_file = outfile.prefix(outfile.prefix() + "_3_detector_imag"); | |
389 | + E.image(nearfield_imag_file.str(), stim::complexImaginary); | |
390 | + } | |
391 | + | |
392 | + //save the background and single-beam images | |
393 | + stim::filename background_file = outfile.prefix(outfile.prefix() + "background"); | |
394 | + stim::filename intensity_file = outfile.prefix(outfile.prefix() + "intensity"); | |
395 | + | |
396 | + if (use_cuda) { | |
397 | + stim::gpu2image<float>(I0, background_file.str(), g_R_ff, g_R_ff, stim::cmBrewer); | |
398 | + stim::gpu2image<float>(I, intensity_file.str(), g_R_ff, g_R_ff, stim::cmBrewer); | |
399 | + } | |
400 | + else { | |
401 | + stim::cpu2image<float>(I0, background_file.str(), g_R_ff, g_R_ff, stim::cmBrewer); | |
402 | + stim::cpu2image<float>(I, intensity_file.str(), g_R_ff, g_R_ff, stim::cmBrewer); | |
403 | + } | |
404 | + | |
405 | + | |
406 | + float* A; | |
407 | + HANDLE_ERROR( cudaMalloc(&A, sizeof(float) * g_R_ff * g_R_ff) ); | |
408 | + gpu_absorbance(A, I, I0, g_R_ff * g_R_ff); | |
409 | + stim::filename absorbance_file = outfile.prefix(outfile.prefix() + "absorbance"); | |
410 | + stim::gpu2image<float>(A, absorbance_file.str(), g_R_ff, g_R_ff, stim::cmBrewer); | |
411 | +} | |
0 | 412 | \ No newline at end of file | ... | ... |
1 | +++ a/sources.h | |
1 | +template<typename T> | |
2 | +std::vector< stim::vec3<T> > simage(T size, std::string imagefile) { | |
3 | + std::vector< stim::vec3<T> > sources; | |
4 | + | |
5 | + stim::image<unsigned char> src(imagefile); | |
6 | + | |
7 | + float xmin = -size / 2; | |
8 | + float ymin = -size / 2; | |
9 | + | |
10 | + size_t xi, yi; | |
11 | + float xa, ya; | |
12 | + for (yi = 0; yi < src.height(); yi++) { | |
13 | + for (xi = 0; xi < src.width(); xi++) { | |
14 | + if (src(xi, yi)) { | |
15 | + xa = (float)xi / (float)(src.width() - 1); | |
16 | + ya = (float)yi / (float)(src.height() - 1); | |
17 | + | |
18 | + sources.push_back(stim::vec3<float>(xa * size + xmin, ya * size + ymin, 0)); | |
19 | + | |
20 | + } | |
21 | + } | |
22 | + } | |
23 | + | |
24 | + return sources; | |
25 | +} | |
26 | + | |
27 | +template<typename T> | |
28 | +std::vector< stim::vec3<T> > sgrid(T size, unsigned int n, unsigned int m = 0) { | |
29 | + std::vector< stim::vec3<T> > sources; | |
30 | + | |
31 | + if (m == 0) m = n; | |
32 | + | |
33 | + float xmin = -size / 2 + size/(n + 1); | |
34 | + float ymin = -size / 2 + size/(m + 1); | |
35 | + | |
36 | + size_t xi, yi; | |
37 | + float xa, ya; | |
38 | + for (yi = 0; yi < m; yi++) { | |
39 | + for (xi = 0; xi < n; xi++) { | |
40 | + xa = (float)xi / (float)(n + 1); | |
41 | + ya = (float)yi / (float)(m + 1); | |
42 | + | |
43 | + sources.push_back(stim::vec3<float>(xa * size + xmin, ya * size + ymin, 0)); | |
44 | + } | |
45 | + } | |
46 | + | |
47 | + return sources; | |
48 | +} | |
0 | 49 | \ No newline at end of file | ... | ... |