Commit 396a5f1225210b5c52e5b6df9c9d96e7f63176e5

Authored by David Mayerich
1 parent 4a9d9281

added custom code for dealing with command-line arguments

CMakeLists.txt
... ... @@ -12,10 +12,10 @@ set(CMAKE_AUTOMOC ON)
12 12 set(CMAKE_INCLUDE_CURRENT_DIR ON)
13 13  
14 14 #find BOOST
15   -set(Boost_USE_STATIC_LIBS ON)
16   -set(Boost_USE_MULTITHREADED ON)
17   -set(Boost_USE_STATIC_RUNTIME OFF)
18   -find_package( Boost 1.46.0 COMPONENTS program_options )
  15 +#set(Boost_USE_STATIC_LIBS ON)
  16 +#set(Boost_USE_MULTITHREADED ON)
  17 +#set(Boost_USE_STATIC_RUNTIME OFF)
  18 +#find_package( Boost 1.46.0 COMPONENTS program_options )
19 19  
20 20 #find the Qt5
21 21 find_package(Qt5Widgets REQUIRED)
... ... @@ -28,7 +28,7 @@ include_directories(${QT_INCLUDE_DIRECTORY})
28 28 find_package(CUDA)
29 29  
30 30 #ask the user for the RTS location
31   -find_package(RTS REQUIRED)
  31 +#find_package(RTS REQUIRED)
32 32  
33 33 #set the include directories
34 34 include_directories(
... ... @@ -37,8 +37,9 @@ include_directories(
37 37 ${Qt5Core_INCLUDE_DIRS}
38 38 ${Qt5Gui_INCLUDE_DIRS}
39 39 # ${Qt5OpenGL_INCLUDE_DIRS}
40   - ${RTS_INCLUDE_DIR}
41   - ${Boost_INCLUDE_DIR}
  40 +# ${RTS_INCLUDE_DIR}
  41 +# ${Boost_INCLUDE_DIR}
  42 + ${CMAKE_CURRENT_SOURCE_DIR}
42 43 )
43 44  
44 45 #build position independent code for Qt (-fPIC)
... ... @@ -55,6 +56,9 @@ file(GLOB SRC_H "*.h")
55 56 file(GLOB SRC_UI "*.ui")
56 57 file(GLOB SRC_CU "*.cu")
57 58  
  59 +#assign RTS source files
  60 +file(GLOB SRC_RTS "rts/source/*.cpp")
  61 +
58 62 #determine which source files have to be moc'd
59 63 Qt5_wrap_cpp(UI_MOC ${SRC_H})
60 64 Qt5_wrap_ui(UI_H ${SRC_UI})
... ... @@ -70,6 +74,7 @@ cuda_add_executable(bimsim
70 74 ${UI_H}
71 75 ${SRC_UI}
72 76 ${SRC_CU}
  77 + ${SRC_RTS}
73 78 )
74 79  
75 80 #specify which qt5 modules to use
... ... @@ -83,7 +88,7 @@ target_link_libraries(bimsim
83 88 # ${Qt5OpenGL_LIBRARIES}
84 89 ${CUDA_cufft_LIBRARY}
85 90 ${CUDA_cublas_LIBRARY}
86   - ${Boost_LIBRARIES}
  91 +# ${Boost_LIBRARIES}
87 92 )
88 93  
89 94  
... ...
dataTypes.h
... ... @@ -14,10 +14,10 @@ typedef double ptype;
14 14 #define BLOCK 256
15 15 #define SQRT_BLOCK 16
16 16  
17   -#define PI 3.14159
  17 +#define PI 3.14159f
18 18  
19 19 //a very small number
20   -#define EPSILON 0.00001
  20 +#define EPSILON 0.00001f
21 21  
22 22 //CUDA hybrid code - complex class should run on both the CPU and GPU
23 23  
... ...
defaults.h
... ... @@ -8,22 +8,26 @@
8 8 #define DEFAULT_SPHERE_A 1
9 9  
10 10 //default near field parameters
11   -#define DEFAULT_LAMBDA 1
12   -#define DEFAULT_AMPLITUDE 1
  11 +#define DEFAULT_LAMBDA "1"
  12 +#define DEFAULT_AMPLITUDE "1"
  13 +#define DEFAULT_MATERIAL "1.4 0.05"
13 14 #define DEFAULT_N 1.4
14 15 #define DEFAULT_K 0.5
15   -#define DEFAULT_FOCUS_X 0
16   -#define DEFAULT_FOCUS_Y 0
17   -#define DEFAULT_FOCUS_Z 0
  16 +#define DEFAULT_FOCUS "0 0 0"
  17 +//#define DEFAULT_FOCUS_X "0"
  18 +//#define DEFAULT_FOCUS_Y "0"
  19 +//#define DEFAULT_FOCUS_Z "0"
18 20 //#define DEFAULT_INCIDENT_ORDER 20
19 21 #define DEFAULT_STABILITY_PARM 1.4
20 22  
21 23 //optics
22   -#define DEFAULT_CONDENSER_MIN 0
23   -#define DEFAULT_CONDENSER_MAX 1
  24 +//#define DEFAULT_CONDENSER_MIN "0.0"
  25 +//#define DEFAULT_CONDENSER_MAX "1.0"
  26 +#define DEFAULT_CONDENSER "0 1"
24 27  
25   -#define DEFAULT_OBJECTIVE_MIN 0
26   -#define DEFAULT_OBJECTIVE_MAX 1
  28 +//#define DEFAULT_OBJECTIVE_MIN "0"
  29 +//#define DEFAULT_OBJECTIVE_MAX "1"
  30 +#define DEFAULT_OBJECTIVE "0 1"
27 31  
28 32 //incident light direction
29 33 #define DEFAULT_K_THETA 0
... ... @@ -35,15 +39,17 @@
35 39 #define DEFAULT_APPEND false
36 40 //#define DEFAULT_OUTPUT_POINT fileoutStruct::imageObjective
37 41  
38   -
  42 +#define DEFAULT_PLANE_MIN "-5 0 -5"
39 43 #define DEFAULT_PLANE_MIN_X -5
40 44 #define DEFAULT_PLANE_MIN_Y 0
41 45 #define DEFAULT_PLANE_MIN_Z -5
42 46  
  47 +#define DEFAULT_PLANE_MAX "5 0 5"
43 48 #define DEFAULT_PLANE_MAX_X 5
44 49 #define DEFAULT_PLANE_MAX_Y 0
45 50 #define DEFAULT_PLANE_MAX_Z 5
46 51  
  52 +#define DEFAULT_PLANE_NORM "0 1 0"
47 53 #define DEFAULT_PLANE_NORM_X 0
48 54 #define DEFAULT_PLANE_NORM_Y 1
49 55 #define DEFAULT_PLANE_NORM_Z 0
... ... @@ -67,16 +73,16 @@
67 73 */
68 74  
69 75  
70   -#define DEFAULT_FIELD_ORDER 10
  76 +#define DEFAULT_FIELD_ORDER "10"
71 77  
72   -#define DEFAULT_SAMPLES 400
  78 +#define DEFAULT_SAMPLES "400"
73 79  
74   -#define DEFAULT_SLICE_RES 256
  80 +#define DEFAULT_SLICE_RES "256"
75 81  
76 82 #define DEFAULT_SPHERE_THETA_R 1000
77 83  
78   -#define DEFAULT_PADDING 1
79   -#define DEFAULT_SUPERSAMPLE 1
  84 +#define DEFAULT_PADDING "1"
  85 +#define DEFAULT_SUPERSAMPLE "1"
80 86  
81 87 #define DEFAULT_INTENSITY_FILE "out_i.bmp"
82 88 #define DEFAULT_TRANSMITTANCE_FILE ""
... ...
main.cpp
... ... @@ -12,7 +12,9 @@ microscopeStruct* SCOPE;
12 12 #include "fieldslice.h"
13 13  
14 14 #include "fileout.h"
15   -#include "options.h"
  15 +//#include "options.h"
  16 +#include "arguments.h"
  17 +#include "rts/tools/arguments.h"
16 18 #include "montecarlo.h"
17 19 #include "rts/math/point.h"
18 20 #include "rts/math/spherical_bessel.h"
... ... @@ -29,28 +31,42 @@ microscopeStruct* SCOPE;
29 31 #include "qtMainDialog.h"
30 32 bool gui = false;
31 33  
  34 +#ifdef _WIN32
  35 +bool ansi = false;
  36 +#else
  37 +bool ansi = true;
  38 +#endif
  39 +
32 40 fileoutStruct gFileOut;
33 41 bool verbose = false;
34 42 using namespace std;
35 43  
36   -int cbessjyva(double v,complex<double> z,double &vm,complex<double>*cjv,
  44 +int cbessjyva(double v,complex<double> z,double &vm,complex<double>*cjv,
37 45 complex<double>*cyv,complex<double>*cjvp,complex<double>*cyvp);
38 46  
39 47 int main(int argc, char *argv[])
40 48 {
  49 + //arguments test
  50 + rts::arglist args;
  51 + SetArguments(args);
41 52  
42   - //benchtest planewave class
43   - rts::vector<ptype, 3> k(1, 0, 0);
44   - rts::vector<ptype, 3> E(2, 2, 0);
45   - planewave<ptype> P(k, E);
46   -
47   - std::cout<<P<<std::endl;
48   -
49   - exit(1);
  53 + //parse the input arguments
  54 + args.parse(argc, argv);
50 55  
51 56 SCOPE = new microscopeStruct();
52   -
53   - LoadParameters(argc, argv);
  57 +
  58 + //load the user specified parameters into the simulation
  59 + LoadParameters(args);
  60 +
  61 + //activate ansi output if specified
  62 + args.set_ansi(ansi);
  63 +
  64 + //display help and exit
  65 + if(args("help"))
  66 + {
  67 + cout<<args.toStr()<<endl;
  68 + exit(1);
  69 + }
54 70  
55 71 //initialize GPU memory for fields
56 72 SCOPE->init();
... ...
nearfield.h
... ... @@ -8,7 +8,7 @@
8 8 #include "sphere.h"
9 9 #include <vector>
10 10  
11   -#define EPSILON_FLOAT 0.000001
  11 +#define EPSILON_FLOAT 0.000001f
12 12  
13 13 //This structure stores values relevant to creating the near field
14 14 struct nearfieldStruct
... ... @@ -29,7 +29,7 @@ struct nearfieldStruct
29 29 bsVector k; //cartesian coordinates, normalized
30 30 bsPoint focus;
31 31  
32   - //slice position and orientation in world space
  32 + //slice position and orientation in world space
33 33 rts::quad<ptype, 3> pos;
34 34  
35 35 //slices for the focused field
... ...
nfScalarUf.cu
... ... @@ -3,8 +3,8 @@
3 3 #include "rts/math/legendre.h"
4 4 #include <stdlib.h>
5 5 #include "rts/cuda/error.h"
6   -#include "rts/cuda/timer.h"
7   -
  6 +#include "rts/cuda/timer.h"
  7 +
8 8 //Incident field for a single plane wave
9 9 __global__ void gpuScalarUfp(bsComplex* Uf, bsVector k, ptype kmag, bsPoint f, ptype A, bsRect ABCD, int uR, int vR)
10 10 {
... ... @@ -33,15 +33,15 @@ __global__ void gpuScalarUfp(bsComplex* Uf, bsVector k, ptype kmag, bsPoint f, p
33 33 //get the rtsPoint in world space and then the r vector
34 34 bsPoint p = ABCD(u, v);
35 35 bsVector r = p - f;
36   - //ptype d = r.len();
37   -
38   - ptype k_dot_r = kmag * k.dot(r);
39   - bsComplex d(0, k_dot_r);
40   -
  36 + //ptype d = r.len();
  37 +
  38 + ptype k_dot_r = kmag * k.dot(r);
  39 + bsComplex d(0, k_dot_r);
  40 +
41 41 Uf[i] = exp(d) * A;
42 42  
43 43 }
44   -
  44 +
45 45 //Incident field for a focused point source
46 46 __global__ void gpuScalarUf(bsComplex* Uf, bsVector k, ptype kmag, bsPoint f, ptype A, bsRect ABCD, int uR, int vR, ptype cosAlpha, ptype cosBeta, int nl, ptype j_conv = 1.4)
47 47 {
... ... @@ -70,11 +70,11 @@ __global__ void gpuScalarUf(bsComplex* Uf, bsVector k, ptype kmag, bsPoint f, pt
70 70 //get the rtsPoint in world space and then the r vector
71 71 bsPoint p = ABCD(u, v);
72 72 bsVector r = p - f;
73   - ptype d = r.len();
74   - if(d < EPSILON_FLOAT)
75   - {
76   - Uf[i] = A * 2 * PI * (cosAlpha - cosBeta);
77   - return;
  73 + ptype d = r.len();
  74 + if(d < EPSILON_FLOAT)
  75 + {
  76 + Uf[i] = A * 2 * PI * (cosAlpha - cosBeta);
  77 + return;
78 78 }
79 79  
80 80 //get info for the light direction and frequency
... ... @@ -94,10 +94,10 @@ __global__ void gpuScalarUf(bsComplex* Uf, bsVector k, ptype kmag, bsPoint f, pt
94 94 ptype P[2];
95 95 //get the angle between k and r (light direction and position vector)
96 96 ptype cosTheta;
97   - cosTheta = k.dot(r);
98   -
99   - //deal with the degenerate case where r == 0
100   - //if(isnan(cosTheta))
  97 + cosTheta = k.dot(r);
  98 +
  99 + //deal with the degenerate case where r == 0
  100 + //if(isnan(cosTheta))
101 101 // cosTheta = 0;
102 102 rts::init_legendre<ptype>(cosTheta, P[0], P[1]);
103 103  
... ... @@ -162,12 +162,12 @@ __global__ void gpuScalarUf(bsComplex* Uf, bsVector k, ptype kmag, bsPoint f, pt
162 162  
163 163 void nearfieldStruct::scalarUf()
164 164 {
165   -
166   - gpuStartTimer();
  165 +
  166 + gpuStartTimer();
167 167  
168 168 //create one thread for each pixel of the field slice
169 169 dim3 dimBlock(SQRT_BLOCK, SQRT_BLOCK);
170   - dim3 dimGrid((Uf.R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (Uf.R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK);
  170 + dim3 dimGrid((Uf.R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (Uf.R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK);
171 171  
172 172 //if we are computing a plane wave, call the gpuScalarUfp function
173 173 if(planeWave)
... ... @@ -176,15 +176,15 @@ void nearfieldStruct::scalarUf()
176 176 }
177 177 //otherwise compute the condenser info and create a focused field
178 178 else
179   - {
180   - //pre-compute the cosine of the obscuration and objective angles
181   - //cout<<"Condenser angle in: "<<asin(condenser[0])<<std::endl;
182   - //cout<<"Condenser angle out: "<<asin(condenser[1])<<std::endl;
183   - ptype cosAlpha = cos(asin(condenser[0]));
  179 + {
  180 + //pre-compute the cosine of the obscuration and objective angles
  181 + //cout<<"Condenser angle in: "<<asin(condenser[0])<<std::endl;
  182 + //cout<<"Condenser angle out: "<<asin(condenser[1])<<std::endl;
  183 + ptype cosAlpha = cos(asin(condenser[0]));
184 184 ptype cosBeta = cos(asin(condenser[1]));
185 185 //compute the scalar Uf field (this will be in the x_hat channel of Uf)
186 186 gpuScalarUf<<<dimGrid, dimBlock>>>(Uf.x_hat, k, 2 * PI / lambda, focus, A, pos, Uf.R[0], Uf.R[1], cosAlpha, cosBeta, m);
187   - }
188   -
189   - t_Uf = gpuStopTimer();
190   -}
  187 + }
  188 +
  189 + t_Uf = gpuStopTimer();
  190 +}
... ...
nfScalarUfLut.cu
1 1 #include "nearfield.h"
2 2  
3 3 #include "rts/math/legendre.h"
4   -#include "rts/cuda/error.h"
  4 +#include "rts/cuda/error.h"
5 5 #include "rts/cuda/timer.h"
6 6  
7 7 texture<float, cudaTextureType2D> texJ;
... ... @@ -25,100 +25,100 @@ __global__ void gpuScalarUfLut(bsComplex* Uf, bsRect ABCD, int uR, int vR, bsPoi
25 25  
26 26 */
27 27  
28   - //get the current coordinate in the plane slice
29   - int iu = blockIdx.x * blockDim.x + threadIdx.x;
30   - int iv = blockIdx.y * blockDim.y + threadIdx.y;
31   -
32   - //make sure that the thread indices are in-bounds
33   - if(iu >= uR || iv >= vR) return;
34   -
35   - //compute the index (easier access to the scalar field array)
36   - int i = iv*uR + iu;
37   -
38   - //compute the parameters for u and v
39   - ptype u = (ptype)iu / (uR);
40   - ptype v = (ptype)iv / (vR);
41   -
42   -
43   -
44   - //get the rtsPoint in world space and then the r vector
45   - bsPoint p = ABCD(u, v);
46   - bsVector r = p - f;
  28 + //get the current coordinate in the plane slice
  29 + int iu = blockIdx.x * blockDim.x + threadIdx.x;
  30 + int iv = blockIdx.y * blockDim.y + threadIdx.y;
  31 +
  32 + //make sure that the thread indices are in-bounds
  33 + if(iu >= uR || iv >= vR) return;
  34 +
  35 + //compute the index (easier access to the scalar field array)
  36 + int i = iv*uR + iu;
  37 +
  38 + //compute the parameters for u and v
  39 + ptype u = (ptype)iu / (uR);
  40 + ptype v = (ptype)iv / (vR);
  41 +
  42 +
  43 +
  44 + //get the rtsPoint in world space and then the r vector
  45 + bsPoint p = ABCD(u, v);
  46 + bsVector r = p - f;
47 47 ptype d = r.len();
48 48  
49 49 if(d == 0)
50 50 {
51 51 Uf[i] = A * 2 * PI * (cosAlpha - cosBeta);
52 52 return;
53   - }
54   -
55   - //get info for the light direction and frequency
56   - r = r.norm();
57   -
58   - //compute the imaginary factor i^l
59   - bsComplex im = bsComplex(0, 1);
60   - bsComplex il = bsComplex(1, 0);
61   -
62   - //Legendre functions are computed dynamically to save memory
63   - //initialize the Legendre functions
64   -
65   - ptype P[2];
66   - //get the angle between k and r (light direction and position vector)
67   - ptype cosTheta;
  53 + }
  54 +
  55 + //get info for the light direction and frequency
  56 + r = r.norm();
  57 +
  58 + //compute the imaginary factor i^l
  59 + bsComplex im = bsComplex(0, 1);
  60 + bsComplex il = bsComplex(1, 0);
  61 +
  62 + //Legendre functions are computed dynamically to save memory
  63 + //initialize the Legendre functions
  64 +
  65 + ptype P[2];
  66 + //get the angle between k and r (light direction and position vector)
  67 + ptype cosTheta;
68 68 cosTheta = k.dot(r);
69 69  
70   - rts::init_legendre<ptype>(cosTheta, P[0], P[1]);
71   -
72   - //initialize legendre functions for the cassegrain angles
73   - ptype Palpha[3];
74   - rts::init_legendre<ptype>(cosAlpha, Palpha[0], Palpha[1]);
75   - Palpha[2] = 1;
76   -
77   - ptype Pbeta[3];
78   - rts::init_legendre<ptype>(cosBeta, Pbeta[0], Pbeta[1]);
79   - Pbeta[2] = 1;
80   -
81   - //for each order l
82   - bsComplex sumUf(0.0, 0.0);
83   - ptype jl = 0.0;
  70 + rts::init_legendre<ptype>(cosTheta, P[0], P[1]);
  71 +
  72 + //initialize legendre functions for the cassegrain angles
  73 + ptype Palpha[3];
  74 + rts::init_legendre<ptype>(cosAlpha, Palpha[0], Palpha[1]);
  75 + Palpha[2] = 1;
  76 +
  77 + ptype Pbeta[3];
  78 + rts::init_legendre<ptype>(cosBeta, Pbeta[0], Pbeta[1]);
  79 + Pbeta[2] = 1;
  80 +
  81 + //for each order l
  82 + bsComplex sumUf(0, 0);
  83 + ptype jl = 0;
84 84 ptype Pl;
85   - ptype di = ( (d - dmin)/(dmax - dmin) ) * (dR - 1);
86   - for(int l = 0; l<=nl; l++)
87   - {
88   - jl = tex2D(texJ, l + 0.5, di + 0.5);
89   - if(l==0)
90   - Pl = P[0];
91   - else if(l==1)
92   - {
93   - Pl = P[1];
94   -
95   - //adjust the cassegrain Legendre function
96   - Palpha[2] = Palpha[0];
97   - rts::shift_legendre<ptype>(l+1, cosAlpha, Palpha[0], Palpha[1]);
98   - Pbeta[2] = Pbeta[0];
99   - rts::shift_legendre<ptype>(l+1, cosBeta, Pbeta[0], Pbeta[1]);
100   - }
101   - else
102   - {
103   - rts::shift_legendre<ptype>(l, cosTheta, P[0], P[1]);
104   -
105   - Pl = P[1];
106   -
107   - //adjust the cassegrain outer Legendre function
108   - Palpha[2] = Palpha[0];
109   - rts::shift_legendre<ptype>(l+1, cosAlpha, Palpha[0], Palpha[1]);
110   - Pbeta[2] = Pbeta[0];
111   - rts::shift_legendre<ptype>(l+1, cosBeta, Pbeta[0], Pbeta[1]);
112   - }
113   -
  85 + ptype di = ( (d - dmin)/(dmax - dmin) ) * (dR - 1);
  86 + for(int l = 0; l<=nl; l++)
  87 + {
  88 + jl = tex2D(texJ, l + 0.5f, di + 0.5f);
  89 + if(l==0)
  90 + Pl = P[0];
  91 + else if(l==1)
  92 + {
  93 + Pl = P[1];
  94 +
  95 + //adjust the cassegrain Legendre function
  96 + Palpha[2] = Palpha[0];
  97 + rts::shift_legendre<ptype>(l+1, cosAlpha, Palpha[0], Palpha[1]);
  98 + Pbeta[2] = Pbeta[0];
  99 + rts::shift_legendre<ptype>(l+1, cosBeta, Pbeta[0], Pbeta[1]);
  100 + }
  101 + else
  102 + {
  103 + rts::shift_legendre<ptype>(l, cosTheta, P[0], P[1]);
  104 +
  105 + Pl = P[1];
  106 +
  107 + //adjust the cassegrain outer Legendre function
  108 + Palpha[2] = Palpha[0];
  109 + rts::shift_legendre<ptype>(l+1, cosAlpha, Palpha[0], Palpha[1]);
  110 + Pbeta[2] = Pbeta[0];
  111 + rts::shift_legendre<ptype>(l+1, cosBeta, Pbeta[0], Pbeta[1]);
  112 + }
  113 +
114 114 sumUf += il * jl * Pl * (Palpha[1] - Palpha[2] - Pbeta[1] + Pbeta[2]);
115 115 //sumUf += jl;
116   -
117   - il *= im;
118   - }
119   -
  116 +
  117 + il *= im;
  118 + }
  119 +
120 120 Uf[i] = sumUf * 2 * PI * A;
121   - //Uf[i] = u;
  121 + //Uf[i] = u;
122 122 //return;
123 123 }
124 124  
... ... @@ -159,23 +159,23 @@ void nearfieldStruct::scalarUfLut()
159 159 HANDLE_ERROR( cudaMemcpy2DToArray(arrayJ, 0, 0, j, (m+1)*sizeof(float), (m+1)*sizeof(float), dR, cudaMemcpyHostToDevice));
160 160  
161 161 //----------------Compute the focused field
162   - //create one thread for each pixel of the field slice
163   - dim3 dimBlock(SQRT_BLOCK, SQRT_BLOCK);
  162 + //create one thread for each pixel of the field slice
  163 + dim3 dimBlock(SQRT_BLOCK, SQRT_BLOCK);
164 164 dim3 dimGrid((Uf.R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (Uf.R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK);
165   -
166   - //if we are computing a plane wave, call the gpuScalarUfp function
167   - if(planeWave)
168   - {
169   - gpuScalarUfp<<<dimGrid, dimBlock>>>(Uf.x_hat, k, 2 * PI / lambda, focus, A, pos, Uf.R[0], Uf.R[1]);
170   - }
171   - //otherwise compute the condenser info and create a focused field
172   - else
  165 +
  166 + //if we are computing a plane wave, call the gpuScalarUfp function
  167 + if(planeWave)
  168 + {
  169 + gpuScalarUfp<<<dimGrid, dimBlock>>>(Uf.x_hat, k, 2 * PI / lambda, focus, A, pos, Uf.R[0], Uf.R[1]);
  170 + }
  171 + //otherwise compute the condenser info and create a focused field
  172 + else
173 173 {
174 174 //pre-compute the cosine of the obscuration and objective angles
175 175 ptype cosAlpha = cos(asin(condenser[0]));
176   - ptype cosBeta = cos(asin(condenser[1]));
177   - //compute the scalar Uf field (this will be in the x_hat channel of Uf)
178   - gpuScalarUfLut<<<dimGrid, dimBlock>>>(Uf.x_hat, pos, Uf.R[0], Uf.R[1], focus, k, A, cosAlpha, cosBeta, m, d_min, d_max, dR);
  176 + ptype cosBeta = cos(asin(condenser[1]));
  177 + //compute the scalar Uf field (this will be in the x_hat channel of Uf)
  178 + gpuScalarUfLut<<<dimGrid, dimBlock>>>(Uf.x_hat, pos, Uf.R[0], Uf.R[1], focus, k, A, cosAlpha, cosBeta, m, d_min, d_max, dR);
179 179 }
180 180  
181 181  
... ...
nfScalarUpLut.cu
... ... @@ -3,30 +3,30 @@
3 3 #include "rts/math/legendre.h"
4 4 #include <stdlib.h>
5 5 #include "rts/cuda/error.h"
6   -#include "rts/cuda/timer.h"
7   -
8   -texture<float2, cudaTextureType2D> texUsp;
9   -texture<float2, cudaTextureType2D> texUip;
10   -
  6 +#include "rts/cuda/timer.h"
  7 +
  8 +texture<float2, cudaTextureType2D> texUsp;
  9 +texture<float2, cudaTextureType2D> texUip;
  10 +
11 11 __global__ void gpuScalarUpLut(bsComplex* Us, bsVector* k, int nk, ptype kmag, ptype a, ptype dmin, ptype dmax, bsPoint f, bsPoint ps, ptype A, bsRect ABCD, int uR, int vR, int dR, int aR, int thetaR)
12   -{
13   - /*This function uses Monte-Carlo integration to sample a texture-based LUT describing the scattered field
14   - produced by a plane wave through a sphere. The MC sampling is used to approximate a focused field.
15   -
16   - Us = final scattered field
17   - k = list of incoming plane waves (Monte-Carlo samples)
18   - nk = number of incoming MC samples
19   - kmag= magnitude of the incoming field 2pi/lambda
20   - dmin= minimum distance of the Usp texture
21   - dmax= maximum distance of the Usp texture
22   - f = position of the focus
23   - ps = position of the sphere
24   - A = total amplitude of the incident field arriving at the focal spot
25   - ABCD= rectangle representing the field slice
26   - uR = resolution of the field slice in the u direction
27   - vR = resolution of the field slice in the v direction
28   - dR = resolution of the Usp texture in the d direction
29   - thetaR= resolution of the Usp texture in the theta direction
  12 +{
  13 + /*This function uses Monte-Carlo integration to sample a texture-based LUT describing the scattered field
  14 + produced by a plane wave through a sphere. The MC sampling is used to approximate a focused field.
  15 +
  16 + Us = final scattered field
  17 + k = list of incoming plane waves (Monte-Carlo samples)
  18 + nk = number of incoming MC samples
  19 + kmag= magnitude of the incoming field 2pi/lambda
  20 + dmin= minimum distance of the Usp texture
  21 + dmax= maximum distance of the Usp texture
  22 + f = position of the focus
  23 + ps = position of the sphere
  24 + A = total amplitude of the incident field arriving at the focal spot
  25 + ABCD= rectangle representing the field slice
  26 + uR = resolution of the field slice in the u direction
  27 + vR = resolution of the field slice in the v direction
  28 + dR = resolution of the Usp texture in the d direction
  29 + thetaR= resolution of the Usp texture in the theta direction
30 30 */
31 31  
32 32 //get the current coordinate in the plane slice
... ... @@ -46,47 +46,47 @@ __global__ void gpuScalarUpLut(bsComplex* Us, bsVector* k, int nk, ptype kmag, p
46 46 //get the rtsPoint in world space and then the r vector
47 47 bsPoint p = ABCD(u, v);
48 48 bsVector r = p - ps;
49   - ptype d = r.len();
50   - float di = ( (d - max(a, dmin))/(dmax - max(a, dmin)) ) * (dR - 1);
51   - float ai = ( (d - dmin)/(a - dmin)) * (aR - 1);
52   -
53   - bsComplex sumUs(0, 0);
54   - //for each plane wave in the wave list
55   - for(int iw = 0; iw < nk; iw++)
56   - {
57   - //normalize the direction vectors and find their inner product
58   - r = r.norm();
59   - ptype cos_theta = k[iw].dot(r);
60   - if(cos_theta < -1)
61   - cos_theta = -1;
62   - if(cos_theta > 1)
63   - cos_theta = 1;
64   - float thetai = ( acos(cos_theta) / PI ) * (thetaR - 1);
65   -
66   - //compute the phase factor for spheres that are not at the origin
67   - bsVector c = ps - f;
68   - bsComplex phase = exp(bsComplex(0, kmag * k[iw].dot(c)));
69   -
70   - //compute the internal field if we are inside a sphere
  49 + ptype d = r.len();
  50 + float di = ( (d - max(a, dmin))/(dmax - max(a, dmin)) ) * (dR - 1);
  51 + float ai = ( (d - dmin)/(a - dmin)) * (aR - 1);
  52 +
  53 + bsComplex sumUs(0, 0);
  54 + //for each plane wave in the wave list
  55 + for(int iw = 0; iw < nk; iw++)
  56 + {
  57 + //normalize the direction vectors and find their inner product
  58 + r = r.norm();
  59 + ptype cos_theta = k[iw].dot(r);
  60 + if(cos_theta < -1)
  61 + cos_theta = -1;
  62 + if(cos_theta > 1)
  63 + cos_theta = 1;
  64 + float thetai = ( acos(cos_theta) / PI ) * (thetaR - 1);
  65 +
  66 + //compute the phase factor for spheres that are not at the origin
  67 + bsVector c = ps - f;
  68 + bsComplex phase = exp(bsComplex(0, kmag * k[iw].dot(c)));
  69 +
  70 + //compute the internal field if we are inside a sphere
71 71 if(d < a)
72 72 {
73   - float2 Uip = tex2D(texUip, ai + 0.5, thetai + 0.5);
74   - sumUs += (1.0/nk) * A * phase * bsComplex(Uip.x, Uip.y);
75   - }
76   - //otherwise compute the scattered field
77   - else
78   - {
79   - float2 Usp = tex2D(texUsp, di + 0.5, thetai + 0.5);
80   - sumUs += (1.0/nk) * A * phase * bsComplex(Usp.x, Usp.y);
81   - }
82   -
83   - }
84   -
85   - Us[i] += sumUs;
86   -}
87   -
88   -void nearfieldStruct::scalarUpLut()
89   -{
  73 + float2 Uip = tex2D(texUip, ai + 0.5f, thetai + 0.5f);
  74 + sumUs += (1.0f/nk) * A * phase * bsComplex(Uip.x, Uip.y);
  75 + }
  76 + //otherwise compute the scattered field
  77 + else
  78 + {
  79 + float2 Usp = tex2D(texUsp, di + 0.5f, thetai + 0.5f);
  80 + sumUs += (1.0f/nk) * A * phase * bsComplex(Usp.x, Usp.y);
  81 + }
  82 +
  83 + }
  84 +
  85 + Us[i] += sumUs;
  86 +}
  87 +
  88 +void nearfieldStruct::scalarUpLut()
  89 +{
90 90 //get the number of spheres
91 91 int nSpheres = sVector.size();
92 92  
... ... @@ -103,90 +103,90 @@ void nearfieldStruct::scalarUpLut()
103 103 //create one thread for each pixel of the field slice
104 104 dim3 dimBlock(SQRT_BLOCK, SQRT_BLOCK);
105 105 dim3 dimGrid((U.R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (U.R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK);
106   -
107   - //copy Monte-Carlo samples to the GPU and determine the incident amplitude (plane-wave specific stuff)
108   - bsVector* gpuk;
109   - int nWaves;
110   - ptype subA;
111   - if(planeWave)
112   - {
113   - nWaves = 1;
114   - HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) ) );
115   - HANDLE_ERROR(cudaMemcpy( gpuk, &k, sizeof(bsVector), cudaMemcpyHostToDevice));
116   - subA = A;
117   - }
118   - else
119   - {
120   - nWaves = inWaves.size();
121   - HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) * nWaves ) );
122   - HANDLE_ERROR(cudaMemcpy( gpuk, &inWaves[0], sizeof(bsVector) * nWaves, cudaMemcpyHostToDevice));
123   - //compute the amplitude that makes it through the condenser
124   - subA = 2 * PI * A * ( (1 - cos(asin(condenser[1]))) - (1 - cos(asin(condenser[0]))) );
125   - }
  106 +
  107 + //copy Monte-Carlo samples to the GPU and determine the incident amplitude (plane-wave specific stuff)
  108 + bsVector* gpuk;
  109 + int nWaves;
  110 + ptype subA;
  111 + if(planeWave)
  112 + {
  113 + nWaves = 1;
  114 + HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) ) );
  115 + HANDLE_ERROR(cudaMemcpy( gpuk, &k, sizeof(bsVector), cudaMemcpyHostToDevice));
  116 + subA = A;
  117 + }
  118 + else
  119 + {
  120 + nWaves = inWaves.size();
  121 + HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) * nWaves ) );
  122 + HANDLE_ERROR(cudaMemcpy( gpuk, &inWaves[0], sizeof(bsVector) * nWaves, cudaMemcpyHostToDevice));
  123 + //compute the amplitude that makes it through the condenser
  124 + subA = 2 * PI * A * ( (1 - cos(asin(condenser[1]))) - (1 - cos(asin(condenser[0]))) );
  125 + }
126 126  
127 127 //for each sphere
128 128 for(int s = 0; s<nSpheres; s++)
129   - {
130   - //get the current sphere
131   - //sphere S = sVector[s];
132   -
133   - //allocate space for the Usp and Uip textures
134   - //allocate the cuda array
135   - cudaArray* arrayUsp;
136   - cudaArray* arrayUip;
137   - cudaChannelFormatDesc channelDescUsp =
138   - cudaCreateChannelDesc(32, 32, 0, 0, cudaChannelFormatKindFloat);
139   - cudaChannelFormatDesc channelDescUip =
140   - cudaCreateChannelDesc(32, 32, 0, 0, cudaChannelFormatKindFloat);
141   - int dR = sVector[s].Usp.R[0];
142   - int thetaR = sVector[s].Usp.R[1];
143   - int aR = sVector[s].Uip.R[0];
144   - HANDLE_ERROR(cudaMallocArray(&arrayUsp, &channelDescUsp, dR, thetaR));
145   - HANDLE_ERROR(cudaMallocArray(&arrayUip, &channelDescUip, aR, thetaR));
146   -
147   - texUsp.addressMode[0] = cudaAddressModeMirror;
148   - texUsp.addressMode[1] = cudaAddressModeMirror;
149   - texUsp.filterMode = cudaFilterModeLinear;
150   - texUsp.normalized = false;
151   -
152   - texUip.addressMode[0] = cudaAddressModeMirror;
153   - texUip.addressMode[1] = cudaAddressModeMirror;
154   - texUip.filterMode = cudaFilterModeLinear;
155   - texUip.normalized = false;
156   - HANDLE_ERROR(cudaBindTextureToArray(texUsp, arrayUsp, channelDescUsp));
157   - HANDLE_ERROR(cudaBindTextureToArray(texUip, arrayUip, channelDescUip));
158   -
159   - //copy the LUT to the Usp texture
160   - HANDLE_ERROR( cudaMemcpy2DToArray(arrayUsp, 0, 0, sVector[s].Usp.x_hat, dR*sizeof(float2), dR*sizeof(float2), thetaR, cudaMemcpyDeviceToDevice));
161   - HANDLE_ERROR( cudaMemcpy2DToArray(arrayUip, 0, 0, sVector[s].Uip.x_hat, aR*sizeof(float2), aR*sizeof(float2), thetaR, cudaMemcpyDeviceToDevice));
162   -
  129 + {
  130 + //get the current sphere
  131 + //sphere S = sVector[s];
  132 +
  133 + //allocate space for the Usp and Uip textures
  134 + //allocate the cuda array
  135 + cudaArray* arrayUsp;
  136 + cudaArray* arrayUip;
  137 + cudaChannelFormatDesc channelDescUsp =
  138 + cudaCreateChannelDesc(32, 32, 0, 0, cudaChannelFormatKindFloat);
  139 + cudaChannelFormatDesc channelDescUip =
  140 + cudaCreateChannelDesc(32, 32, 0, 0, cudaChannelFormatKindFloat);
  141 + int dR = sVector[s].Usp.R[0];
  142 + int thetaR = sVector[s].Usp.R[1];
  143 + int aR = sVector[s].Uip.R[0];
  144 + HANDLE_ERROR(cudaMallocArray(&arrayUsp, &channelDescUsp, dR, thetaR));
  145 + HANDLE_ERROR(cudaMallocArray(&arrayUip, &channelDescUip, aR, thetaR));
  146 +
  147 + texUsp.addressMode[0] = cudaAddressModeMirror;
  148 + texUsp.addressMode[1] = cudaAddressModeMirror;
  149 + texUsp.filterMode = cudaFilterModeLinear;
  150 + texUsp.normalized = false;
  151 +
  152 + texUip.addressMode[0] = cudaAddressModeMirror;
  153 + texUip.addressMode[1] = cudaAddressModeMirror;
  154 + texUip.filterMode = cudaFilterModeLinear;
  155 + texUip.normalized = false;
  156 + HANDLE_ERROR(cudaBindTextureToArray(texUsp, arrayUsp, channelDescUsp));
  157 + HANDLE_ERROR(cudaBindTextureToArray(texUip, arrayUip, channelDescUip));
  158 +
  159 + //copy the LUT to the Usp texture
  160 + HANDLE_ERROR( cudaMemcpy2DToArray(arrayUsp, 0, 0, sVector[s].Usp.x_hat, dR*sizeof(float2), dR*sizeof(float2), thetaR, cudaMemcpyDeviceToDevice));
  161 + HANDLE_ERROR( cudaMemcpy2DToArray(arrayUip, 0, 0, sVector[s].Uip.x_hat, aR*sizeof(float2), aR*sizeof(float2), thetaR, cudaMemcpyDeviceToDevice));
  162 +
163 163 gpuScalarUpLut<<<dimGrid, dimBlock>>>(U.x_hat,
164   - gpuk,
  164 + gpuk,
165 165 nWaves,
166   - 2 * PI / lambda,
167   - sVector[s].a,
168   - sVector[s].d_min,
  166 + 2 * PI / lambda,
  167 + sVector[s].a,
  168 + sVector[s].d_min,
169 169 sVector[s].d_max,
170 170 focus,
171   - sVector[s].p,
172   - subA,
  171 + sVector[s].p,
  172 + subA,
173 173 pos,
174 174 U.R[0],
175   - U.R[1],
176   - dR,
177   - aR,
178   - thetaR);
179   -
180   - cudaFreeArray(arrayUsp);
181   - cudaFreeArray(arrayUip);
182   -
183   - }
184   -
  175 + U.R[1],
  176 + dR,
  177 + aR,
  178 + thetaR);
  179 +
  180 + cudaFreeArray(arrayUsp);
  181 + cudaFreeArray(arrayUip);
  182 +
  183 + }
  184 +
185 185  
186 186 //store the time to compute the scattered field
187   - t_Us = gpuStopTimer();
188   -
189   - //free monte-carlo samples
190   - cudaFree(gpuk);
191   -
192   -}
  187 + t_Us = gpuStopTimer();
  188 +
  189 + //free monte-carlo samples
  190 + cudaFree(gpuk);
  191 +
  192 +}
... ...
nfScalarUs.cu
... ... @@ -7,47 +7,47 @@
7 7  
8 8 __device__ bsComplex calc_Us(ptype kd, ptype cos_theta, int Nl, bsComplex* B)
9 9 {
10   - //initialize the spherical Bessel functions
11   - ptype j[2];
12   - rts::init_sbesselj<ptype>(kd, j);
13   - ptype y[2];
14   - rts::init_sbessely<ptype>(kd, y);
15   -
16   - //initialize the Legendre polynomial
17   - ptype P[2];
18   - rts::init_legendre<ptype>(cos_theta, P[0], P[1]);
19   -
20   - //initialize the spherical Hankel function
21   - bsComplex h((ptype)0, (ptype)0);
22   -
23   - //initialize the result
24   - bsComplex Us((ptype)0, (ptype)0);
25   -
26   - //for each order up to Nl
27   - for(int l=0; l<=Nl; l++)
28   - {
29   - if(l == 0)
30   - {
31   - h.r = j[0];
32   - h.i = y[0];
33   - Us += B[0] * h * P[0];
34   - }
35   - else
36   - {
37   - //shift the bessel functions and legendre polynomials
38   - if(l > 1)
39   - {
40   - rts::shift_legendre<ptype>(l, cos_theta, P[0], P[1]);
41   - rts::shift_sbesselj<ptype>(l, kd, j);
42   - rts::shift_sbessely<ptype>(l, kd, y);
43   - }
44   -
45   - h.r = j[1];
46   - h.i = y[1];
47   - Us += B[l] * h * P[1];
48   -
49   -
50   - }
  10 + //initialize the spherical Bessel functions
  11 + ptype j[2];
  12 + rts::init_sbesselj<ptype>(kd, j);
  13 + ptype y[2];
  14 + rts::init_sbessely<ptype>(kd, y);
  15 +
  16 + //initialize the Legendre polynomial
  17 + ptype P[2];
  18 + rts::init_legendre<ptype>(cos_theta, P[0], P[1]);
  19 +
  20 + //initialize the spherical Hankel function
  21 + bsComplex h((ptype)0, (ptype)0);
  22 +
  23 + //initialize the result
  24 + bsComplex Us((ptype)0, (ptype)0);
  25 +
  26 + //for each order up to Nl
  27 + for(int l=0; l<=Nl; l++)
  28 + {
  29 + if(l == 0)
  30 + {
  31 + h.r = j[0];
  32 + h.i = y[0];
  33 + Us += B[0] * h * P[0];
  34 + }
  35 + else
  36 + {
  37 + //shift the bessel functions and legendre polynomials
  38 + if(l > 1)
  39 + {
  40 + rts::shift_legendre<ptype>(l, cos_theta, P[0], P[1]);
  41 + rts::shift_sbesselj<ptype>(l, kd, j);
  42 + rts::shift_sbessely<ptype>(l, kd, y);
  43 + }
  44 +
  45 + h.r = j[1];
  46 + h.i = y[1];
  47 + Us += B[l] * h * P[1];
  48 +
  49 +
  50 + }
51 51 }
52 52 return Us;
53 53 }
... ... @@ -59,41 +59,41 @@ __device__ bsComplex calc_Ui(bsComplex knd, ptype cos_theta, int Nl, bsComplex*
59 59 bsComplex Ui((ptype)0, (ptype)0);
60 60  
61 61 //deal with rtsPoints near zero
62   - if(real(knd) < EPSILON_FLOAT)
63   - {
64   - //for(int l=0; l<Nl; l++)
65   - Ui = A[0];
66   - return Ui;
  62 + if(real(knd) < EPSILON_FLOAT)
  63 + {
  64 + //for(int l=0; l<Nl; l++)
  65 + Ui = A[0];
  66 + return Ui;
67 67 }
68 68  
69   - //initialize the spherical Bessel functions
70   - bsComplex j[2];
71   - rts::init_sbesselj<bsComplex>(knd, j);
72   -
73   - //initialize the Legendre polynomial
74   - ptype P[2];
75   - rts::init_legendre<ptype>(cos_theta, P[0], P[1]);
76   -
77   - //for each order up to Nl
78   - for(int l=0; l<=Nl; l++)
79   - {
80   - if(l == 0)
81   - {
82   - Ui += A[0] * j[0] * P[0];
83   - }
84   - else
85   - {
86   - //shift the bessel functions and legendre polynomials
87   - if(l > 1)
88   - {
89   - rts::shift_legendre<ptype>(l, cos_theta, P[0], P[1]);
90   - rts::shift_sbesselj<bsComplex>(l, knd, j);
91   - }
92   -
93   - Ui += A[l] * j[1] * P[1];
94   -
95   -
96   - }
  69 + //initialize the spherical Bessel functions
  70 + bsComplex j[2];
  71 + rts::init_sbesselj<bsComplex>(knd, j);
  72 +
  73 + //initialize the Legendre polynomial
  74 + ptype P[2];
  75 + rts::init_legendre<ptype>(cos_theta, P[0], P[1]);
  76 +
  77 + //for each order up to Nl
  78 + for(int l=0; l<=Nl; l++)
  79 + {
  80 + if(l == 0)
  81 + {
  82 + Ui += A[0] * j[0] * P[0];
  83 + }
  84 + else
  85 + {
  86 + //shift the bessel functions and legendre polynomials
  87 + if(l > 1)
  88 + {
  89 + rts::shift_legendre<ptype>(l, cos_theta, P[0], P[1]);
  90 + rts::shift_sbesselj<bsComplex>(l, knd, j);
  91 + }
  92 +
  93 + Ui += A[l] * j[1] * P[1];
  94 +
  95 +
  96 + }
97 97 }
98 98 return Ui;
99 99 }
... ... @@ -118,39 +118,39 @@ __global__ void gpuScalarUsp(bsComplex* Us, bsVector* k, int nk, ptype kmag, bsP
118 118 //get the rtsPoint in world space and then the r vector
119 119 bsPoint p = ABCD(u, v);
120 120 bsVector r = p - ps;
121   - ptype d = r.len();
122   -
123   - bsComplex sumUs(0, 0);
124   - //for each plane wave in the wave list
125   - for(int iw = 0; iw < nk; iw++)
126   - {
127   - //normalize the direction vectors and find their inner product
128   - r = r.norm();
129   - ptype cos_theta = k[iw].dot(r);
130   -
131   - //compute the phase factor for spheres that are not at the origin
132   - bsVector c = ps - f;
133   - bsComplex phase = exp(bsComplex(0, kmag * k[iw].dot(c)));
134   -
135   - //compute the internal field if we are inside a sphere
  121 + ptype d = r.len();
  122 +
  123 + bsComplex sumUs(0, 0);
  124 + //for each plane wave in the wave list
  125 + for(int iw = 0; iw < nk; iw++)
  126 + {
  127 + //normalize the direction vectors and find their inner product
  128 + r = r.norm();
  129 + ptype cos_theta = k[iw].dot(r);
  130 +
  131 + //compute the phase factor for spheres that are not at the origin
  132 + bsVector c = ps - f;
  133 + bsComplex phase = exp(bsComplex(0, kmag * k[iw].dot(c)));
  134 +
  135 + //compute the internal field if we are inside a sphere
136 136 if(d <= a)
137 137 {
138 138 bsComplex knd = kmag * d * n;
139   - sumUs += (1.0/nk) * A * phase * calc_Ui(knd, cos_theta, Nl, Alpha);
140   - }
141   - //otherwise compute the scattered field
142   - else
143   - {
144   - //compute the argument for the spherical Hankel function
145   - ptype kd = kmag * d;
146   - sumUs += (1.0/nk) * A * phase * calc_Us(kd, cos_theta, Nl, Beta);
147   - }
148   -
149   - }
150   -
151   - Us[i] += sumUs;
152   -
153   -
  139 + sumUs += (1.0f/nk) * A * phase * calc_Ui(knd, cos_theta, Nl, Alpha);
  140 + }
  141 + //otherwise compute the scattered field
  142 + else
  143 + {
  144 + //compute the argument for the spherical Hankel function
  145 + ptype kd = kmag * d;
  146 + sumUs += (1.0f/nk) * A * phase * calc_Us(kd, cos_theta, Nl, Beta);
  147 + }
  148 +
  149 + }
  150 +
  151 + Us[i] += sumUs;
  152 +
  153 +
154 154 }
155 155  
156 156 void nearfieldStruct::scalarUs()
... ... @@ -190,17 +190,17 @@ void nearfieldStruct::scalarUs()
190 190 HANDLE_ERROR(cudaMemcpy(gpuB, &sVector[s].B[0], (Nl+1) * sizeof(bsComplex), cudaMemcpyHostToDevice));
191 191 HANDLE_ERROR(cudaMemcpy(gpuA, &sVector[s].A[0], (Nl+1) * sizeof(bsComplex), cudaMemcpyHostToDevice));
192 192  
193   - //if we are computing a plane wave, call the gpuScalarUfp function
194   - sphere S = sVector[s];
195   - bsVector* gpuk;
  193 + //if we are computing a plane wave, call the gpuScalarUfp function
  194 + sphere S = sVector[s];
  195 + bsVector* gpuk;
196 196  
197 197 if(planeWave)
198   - {
199   - //if this is a single plane wave, assume it goes along direction k (copy the k vector to the GPU)
200   - HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) ));
  198 + {
  199 + //if this is a single plane wave, assume it goes along direction k (copy the k vector to the GPU)
  200 + HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) ));
201 201 HANDLE_ERROR(cudaMemcpy( gpuk, &k, sizeof(bsVector), cudaMemcpyHostToDevice));
202 202 gpuScalarUsp<<<dimGrid, dimBlock>>>(U.x_hat,
203   - gpuk,
  203 + gpuk,
204 204 1,
205 205 2 * PI / lambda,
206 206 focus,
... ... @@ -213,20 +213,20 @@ void nearfieldStruct::scalarUs()
213 213 A,
214 214 pos,
215 215 U.R[0],
216   - U.R[1]);
  216 + U.R[1]);
217 217 HANDLE_ERROR(cudaFree(gpuk));
218   - }
219   - //otherwise copy all of the monte-carlo samples to the GPU and compute
220   - else
221   - {
222   - HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) * inWaves.size() ));
223   - HANDLE_ERROR(cudaMemcpy( gpuk, &inWaves[0], sizeof(bsVector) * inWaves.size(), cudaMemcpyHostToDevice));
224   -
225   - //compute the amplitude that makes it through the condenser
226   - ptype subA = 2 * PI * A * ( (1 - cos(asin(condenser[1]))) - (1 - cos(asin(condenser[0]))) );
227   -
  218 + }
  219 + //otherwise copy all of the monte-carlo samples to the GPU and compute
  220 + else
  221 + {
  222 + HANDLE_ERROR(cudaMalloc( (void**)&gpuk, sizeof(bsVector) * inWaves.size() ));
  223 + HANDLE_ERROR(cudaMemcpy( gpuk, &inWaves[0], sizeof(bsVector) * inWaves.size(), cudaMemcpyHostToDevice));
  224 +
  225 + //compute the amplitude that makes it through the condenser
  226 + ptype subA = 2 * PI * A * ( (1 - cos(asin(condenser[1]))) - (1 - cos(asin(condenser[0]))) );
  227 +
228 228 gpuScalarUsp<<<dimGrid, dimBlock>>>(U.x_hat,
229   - gpuk,
  229 + gpuk,
230 230 inWaves.size(),
231 231 2 * PI / lambda,
232 232 focus,
... ... @@ -239,17 +239,17 @@ void nearfieldStruct::scalarUs()
239 239 subA,
240 240 pos,
241 241 U.R[0],
242   - U.R[1]);
243   - HANDLE_ERROR(cudaFree(gpuk));
244   -
245   -
246   - }
247   -
248   - //free memory for scattering coefficients
249   - HANDLE_ERROR(cudaFree(gpuA));
  242 + U.R[1]);
  243 + HANDLE_ERROR(cudaFree(gpuk));
  244 +
  245 +
  246 + }
  247 +
  248 + //free memory for scattering coefficients
  249 + HANDLE_ERROR(cudaFree(gpuA));
250 250 HANDLE_ERROR(cudaFree(gpuB));
251   - }
252   -
  251 + }
  252 +
253 253  
254 254 //store the time to compute the scattered field
255 255 t_Us = gpuStopTimer();
... ...
options.h deleted
1   -//AnyOption for command-line processing
2   -//#include "anyoption.h"
3   -
4   -#include "rts/optics/material.h"
5   -
6   -#include "nearfield.h"
7   -#include "microscope.h"
8   -#include "rts/visualization/colormap.h"
9   -#include "fileout.h"
10   -//extern nearfieldStruct* NF;
11   -extern microscopeStruct* SCOPE;
12   -extern fileoutStruct gFileOut;
13   -
14   -//default values
15   -#include "defaults.h"
16   -
17   -#include <string>
18   -#include <sstream>
19   -#include <fstream>
20   -#include <limits>
21   -using namespace std;
22   -
23   -#include <boost/program_options.hpp>
24   -namespace po = boost::program_options;
25   -
26   -extern bool verbose;
27   -extern bool gui;
28   -
29   -
30   -
31   -static void lNearfield(po::variables_map vm)
32   -{
33   - //test to see if we are running a vector field simulation
34   - bool vectorField = false;
35   - if(vm.count("vector"))
36   - vectorField = true;
37   - SCOPE->scalarSim = !vectorField;
38   -
39   - //test to see if we are simulating a plane wave
40   - bool planeWave = DEFAULT_PLANEWAVE;
41   - if(vm.count("plane-wave"))
42   - planeWave = !planeWave;
43   - SCOPE->nf.planeWave = planeWave;
44   -
45   - //get the incident field amplitude
46   - SCOPE->nf.A = vm["amplitude"].as<ptype>();
47   -
48   - //get the condenser parameters
49   - SCOPE->nf.condenser[0] = DEFAULT_CONDENSER_MIN;
50   - SCOPE->nf.condenser[1] = DEFAULT_CONDENSER_MAX;
51   -
52   - if(vm.count("condenser"))
53   - {
54   - vector<ptype> cparams = vm["condenser"].as< vector<ptype> >();
55   -
56   - if(cparams.size() == 1)
57   - SCOPE->nf.condenser[1] = cparams[0];
58   - else
59   - {
60   - SCOPE->nf.condenser[0] = cparams[0];
61   - SCOPE->nf.condenser[1] = cparams[1];
62   - }
63   - }
64   -
65   -
66   - //get the focal rtsPoint position
67   - SCOPE->nf.focus[0] = DEFAULT_FOCUS_X;
68   - SCOPE->nf.focus[1] = DEFAULT_FOCUS_Y;
69   - SCOPE->nf.focus[2] = DEFAULT_FOCUS_Z;
70   - if(vm.count("focus"))
71   - {
72   - vector<ptype> fpos = vm["focus"].as< vector<ptype> >();
73   - if(fpos.size() != 3)
74   - {
75   - cout<<"BIMSIM Error - the incident focal point is incorrectly specified; it must have three components."<<endl;
76   - exit(1);
77   - }
78   - SCOPE->nf.focus[0] = fpos[0];
79   - SCOPE->nf.focus[1] = fpos[1];
80   - SCOPE->nf.focus[2] = fpos[2];
81   - }
82   -
83   - //get the incident light direction (k-vector)
84   - bsVector spherical(1, 0, 0);
85   -
86   - //if a k-vector is specified
87   - if(vm.count("k"))
88   - {
89   - vector<ptype> kvec = vm["k"].as< vector<ptype> >();
90   - if(kvec.size() != 2)
91   - {
92   - cout<<"BIMSIM Error - k-vector is not specified correctly: it must contain two elements"<<endl;
93   - exit(1);
94   - }
95   - spherical[1] = kvec[0];
96   - spherical[2] = kvec[1];
97   - }
98   - SCOPE->nf.k = spherical.sph2cart();
99   -
100   -
101   - //incident field order
102   - SCOPE->nf.m = vm["field-order"].as<int>();
103   -
104   - //number of Monte-Carlo samples
105   - SCOPE->nf.nWaves = vm["samples"].as<int>();
106   -
107   - //random number seed for Monte-Carlo samples
108   - if(vm.count("seed"))
109   - srand(vm["seed"].as<unsigned int>());
110   -
111   -
112   -
113   -}
114   -
115   -
116   -static void loadOutputParams(po::variables_map vm)
117   -{
118   - //append simulation results to previous binary files
119   - gFileOut.append = DEFAULT_APPEND;
120   - if(vm.count("append"))
121   - gFileOut.append = true;
122   -
123   - //image parameters
124   - //component of the field to be saved
125   - std::string fieldStr;
126   - fieldStr = vm["output-type"].as<string>();
127   -
128   - if(fieldStr == "magnitude")
129   - gFileOut.field = fileoutStruct::fieldMag;
130   - else if(fieldStr == "intensity")
131   - gFileOut.field = fileoutStruct::fieldIntensity;
132   - else if(fieldStr == "polarization")
133   - gFileOut.field = fileoutStruct::fieldPolar;
134   - else if(fieldStr == "imaginary")
135   - gFileOut.field = fileoutStruct::fieldImag;
136   - else if(fieldStr == "real")
137   - gFileOut.field = fileoutStruct::fieldReal;
138   - else if(fieldStr == "angular-spectrum")
139   - gFileOut.field = fileoutStruct::fieldAngularSpectrum;
140   -
141   -
142   - //image file names
143   - gFileOut.intFile = vm["intensity"].as<string>();
144   - gFileOut.absFile = vm["absorbance"].as<string>();
145   - gFileOut.transFile = vm["transmittance"].as<string>();
146   - gFileOut.nearFile = vm["near-field"].as<string>();
147   - gFileOut.farFile = vm["far-field"].as<string>();
148   -
149   - //colormap
150   - std::string cmapStr;
151   - cmapStr = vm["colormap"].as<string>();
152   - if(cmapStr == "brewer")
153   - gFileOut.colormap = rts::cmBrewer;
154   - else if(cmapStr == "gray")
155   - gFileOut.colormap = rts::cmGrayscale;
156   - else
157   - cout<<"color-map value not recognized (using default): "<<cmapStr<<endl;
158   -}
159   -
160   -void lFlags(po::variables_map vm, po::options_description desc)
161   -{
162   - //display help and exit
163   - if(vm.count("help"))
164   - {
165   - cout<<desc<<endl;
166   - exit(1);
167   - }
168   -
169   - //flag for verbose output
170   - if(vm.count("verbose"))
171   - verbose = true;
172   -
173   - if(vm.count("recursive"))
174   - {
175   - SCOPE->nf.lut_us = false;
176   - SCOPE->nf.lut_uf = false;
177   - }
178   - else if(vm.count("recursive-us"))
179   - {
180   - SCOPE->nf.lut_us = false;
181   - }
182   - else if(vm.count("lut-uf"))
183   - {
184   - SCOPE->nf.lut_uf = true;
185   - }
186   -
187   - //gui
188   - if(vm.count("gui"))
189   - gui = true;
190   -}
191   -
192   -void lWavelength(po::variables_map vm)
193   -{
194   - //load the wavelength
195   - if(vm.count("nu"))
196   - {
197   - //wavelength is given in wavenumber - transform and flag
198   - SCOPE->nf.lambda = 10000/vm["nu"].as<ptype>();
199   - gFileOut.wavenumber = true;
200   - }
201   - //otherwise we are using lambda = wavelength
202   - else
203   - {
204   - SCOPE->nf.lambda = vm["lambda"].as<ptype>();
205   - gFileOut.wavenumber = false;
206   - }
207   -}
208   -
209   -static void lSpheres(string sphereList)
210   -{
211   - /*This function loads a list of sphere given in the string sphereList
212   - The format is:
213   - x y z a m
214   - where
215   - x, y, z = sphere position (required)
216   - a = sphere radius (required)
217   - m = material ID (optional) */
218   -
219   - std::stringstream ss(sphereList);
220   -
221   - while(!ss.eof())
222   - {
223   - //create a new sphere
224   - sphere newS;
225   -
226   - //get the sphere data
227   - ss>>newS.p[0];
228   - ss>>newS.p[1];
229   - ss>>newS.p[2];
230   - ss>>newS.a;
231   -
232   - if(ss.peek() != '\n')
233   - ss>>newS.iMaterial;
234   -
235   - //add the new sphere to the sphere vector
236   - SCOPE->nf.sVector.push_back(newS);
237   -
238   - //ignore the rest of the line
239   - ss.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
240   -
241   - //check out the next element (this should set the EOF error flag)
242   - ss.peek();
243   - }
244   -}
245   -
246   -void lSpheres(po::variables_map vm)
247   -{
248   - //if a sphere is specified at the command line
249   - if(vm.count("spheres"))
250   - {
251   - //convert the sphere to a string
252   - vector<ptype> sdesc = vm["spheres"].as< vector<ptype> >();
253   -
254   - //compute the number of spheres specified
255   - unsigned int nS;
256   - if(sdesc.size() <= 5)
257   - nS = 1;
258   - else
259   - {
260   - //if the number of parameters is divisible by 4, compute the number of spheres
261   - if(sdesc.size() % 5 == 0)
262   - nS = sdesc.size() / 5;
263   - else
264   - {
265   - cout<<"BIMSIM Error: Invalid number of sphere parameters."<<endl;
266   - exit(1);
267   - }
268   - }
269   -
270   - stringstream ss;
271   -
272   - //for each sphere
273   - for(unsigned int s=0; s<nS; s++)
274   - {
275   - //compute the number of sphere parameters
276   - unsigned int nP;
277   - if(nS == 1) nP = sdesc.size();
278   - else nP = 5;
279   -
280   - //store each parameter as a string
281   - for(unsigned int i=0; i<nP; i++)
282   - {
283   - ss<<sdesc[s*5 + i]<<" ";
284   - }
285   - ss<<endl;
286   - }
287   -
288   -
289   -
290   - //convert the string to a sphere list
291   - lSpheres(ss.str());
292   - }
293   -
294   - //if a files are specified
295   - if(vm.count("sphere-file"))
296   - {
297   -
298   - vector<string> filenames = vm["sphere-file"].as< vector<string> >();
299   - //load each file
300   - for(unsigned int iS=0; iS<filenames.size(); iS++)
301   - {
302   - //load the file into a string
303   - std::ifstream ifs(filenames[iS].c_str());
304   -
305   - if(!ifs)
306   - {
307   - cout<<"Error loading sphere file."<<endl;
308   - exit(1);
309   - }
310   -
311   - std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
312   -
313   - //load the list of spheres from a string
314   - lSpheres(instr);
315   - }
316   - }
317   -
318   - //make sure the appropriate materials are loaded
319   - unsigned int nS = SCOPE->nf.sVector.size();
320   -
321   - //for each sphere
322   - for(unsigned int s = 0; s<nS; s++)
323   - {
324   - //make sure the corresponding material exists
325   - if(SCOPE->nf.sVector[s].iMaterial + 1 > SCOPE->nf.mVector.size())
326   - {
327   - //otherwise output an error
328   - cout<<"BIMSIM Error - A material is not loaded for sphere "<<s+1<<"."<<endl;
329   - cout<<"Material requested: "<<SCOPE->nf.sVector[s].iMaterial + 1<<endl;
330   - cout<<"Number of materials: "<<SCOPE->nf.mVector.size()<<endl;
331   - exit(1);
332   - }
333   - }
334   -}
335   -
336   -static void lMaterials(po::variables_map vm)
337   -{
338   - //if materials are specified at the command line
339   - if(vm.count("materials"))
340   - {
341   - vector<ptype> matVec = vm["materials"].as< vector<ptype> >();
342   - if(matVec.size() == 1)
343   - {
344   - rts::material<ptype> newM(SCOPE->nf.lambda, matVec[0], 0);
345   - SCOPE->nf.mVector.push_back(newM);
346   - }
347   - else if(matVec.size() %2 != 0)
348   - {
349   - cout<<"BIMSim Error: materials must be specified in n, k pairs"<<endl;
350   - exit(1);
351   - }
352   - else
353   - {
354   - for(unsigned int i=0; i<matVec.size(); i+=2)
355   - {
356   - rts::material<ptype> newM(SCOPE->nf.lambda, matVec[i], matVec[i+1]);
357   - SCOPE->nf.mVector.push_back(newM);
358   - }
359   - }
360   - }
361   -
362   - //if file names are specified, load the materials
363   - if(vm.count("material-file"))
364   - {
365   - vector<string> filenames = vm["material-file"].as< vector<string> >();
366   - for(unsigned int i=0; i<filenames.size(); i++)
367   - {
368   - //load the file into a string
369   - //std::ifstream ifs(filenames[i].c_str());
370   -
371   - //std::string instr((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
372   -
373   - //load the list of spheres from a string
374   - rts::material<ptype> newM(filenames[i].c_str());
375   - //newM.fromStr(instr, "");
376   - SCOPE->nf.mVector.push_back(newM);
377   - }
378   - }
379   -
380   -}
381   -
382   -static void lOptics(po::variables_map vm)
383   -{
384   - SCOPE->objective[0] = DEFAULT_OBJECTIVE_MIN;
385   - SCOPE->objective[1] = DEFAULT_OBJECTIVE_MAX;
386   - if(vm.count("objective"))
387   - {
388   - vector<ptype> oparams = vm["objective"].as< vector<ptype> >();
389   -
390   - if(oparams.size() == 1)
391   - SCOPE->objective[1] = oparams[0];
392   - else
393   - {
394   - SCOPE->objective[0] = oparams[0];
395   - SCOPE->objective[1] = oparams[1];
396   - }
397   - }
398   -}
399   -
400   -static void lImagePlane(po::variables_map vm)
401   -{
402   - bsPoint pMin(DEFAULT_PLANE_MIN_X, DEFAULT_PLANE_MIN_Y, DEFAULT_PLANE_MIN_Z);
403   - bsPoint pMax(DEFAULT_PLANE_MAX_X, DEFAULT_PLANE_MAX_Y, DEFAULT_PLANE_MAX_Z);
404   - bsVector normal(DEFAULT_PLANE_NORM_X, DEFAULT_PLANE_NORM_Y, DEFAULT_PLANE_NORM_Z);
405   -
406   - //set the default values for the slice position and orientation
407   - if(vm.count("plane-lower-left") && vm.count("plane-upper-right") && vm.count("plane-normal"))
408   - {
409   - vector<ptype> ll = vm["plane-lower-left"].as< vector<ptype> >();
410   - if(ll.size() != 3)
411   - {
412   - cout<<"BIMSIM Error - The lower-left corner of the image plane is incorrectly specified."<<endl;
413   - exit(1);
414   - }
415   -
416   - vector<ptype> ur = vm["plane-lower-left"].as< vector<ptype> >();
417   - if(ur.size() != 3)
418   - {
419   - cout<<"BIMSIM Error - The upper-right corner of the image plane is incorrectly specified."<<endl;
420   - exit(1);
421   - }
422   -
423   - vector<ptype> norm = vm["plane-lower-left"].as< vector<ptype> >();
424   - if(norm.size() != 3)
425   - {
426   - cout<<"BIMSIM Error - The normal of the image plane is incorrectly specified."<<endl;
427   - exit(1);
428   - }
429   -
430   - pMin = bsPoint(ll[0], ll[1], ll[2]);
431   - pMax = bsPoint(ur[0], ur[1], ur[2]);
432   - normal = bsVector(norm[0], norm[1], norm[2]);
433   - }
434   - else if(vm.count("xy"))
435   - {
436   - //default plane size in microns
437   - ptype s = DEFAULT_PLANE_SIZE;
438   - ptype pos = DEFAULT_PLANE_POSITION;
439   -
440   - vector<ptype> xy = vm["xy"].as< vector<ptype> >();
441   - if(xy.size() >= 1)
442   - s = xy[0];
443   - if(xy.size() >= 2)
444   - pos = xy[1];
445   -
446   - //calculate the plane corners and normal based on the size and position
447   - pMin = bsPoint(-s/2, -s/2, pos);
448   - pMax = bsPoint(s/2, s/2, pos);
449   - normal = bsVector(0, 0, 1);
450   - }
451   - else if(vm.count("xz"))
452   - {
453   - //default plane size in microns
454   - ptype size = DEFAULT_PLANE_SIZE;
455   - ptype pos = DEFAULT_PLANE_POSITION;
456   -
457   - vector<ptype> xz = vm["xz"].as< vector<ptype> >();
458   - if(xz.size() >= 1)
459   - size = xz[0];
460   - if(xz.size() >= 2)
461   - pos = xz[1];
462   -
463   - //calculate the plane corners and normal based on the size and position
464   - pMin = bsPoint(-size/2, pos, -size/2);
465   - pMax = bsPoint(size/2, pos, size/2);
466   - normal = bsVector(0, -1, 0);
467   - }
468   - else if(vm.count("yz"))
469   - {
470   - //default plane size in microns
471   - ptype size = DEFAULT_PLANE_SIZE;
472   - ptype pos = DEFAULT_PLANE_POSITION;
473   -
474   - vector<ptype> yz = vm["yz"].as< vector<ptype> >();
475   - if(yz.size() >= 1)
476   - size = yz[0];
477   - if(yz.size() >= 2)
478   - pos = yz[1];
479   -
480   - //calculate the plane corners and normal based on the size and position
481   - pMin = bsPoint(pos, -size/2, -size/2);
482   - pMax = bsPoint(pos, size/2, size/2);
483   - normal = bsVector(1, 0, 0);
484   - }
485   - SCOPE->setPos(pMin, pMax, normal);
486   -
487   - //resolution
488   - SCOPE->setRes(vm["resolution"].as<unsigned int>(),
489   - vm["resolution"].as<unsigned int>(),
490   - vm["padding"].as<unsigned int>(),
491   - vm["supersample"].as<unsigned int>());
492   -
493   -
494   -
495   -
496   -
497   - SCOPE->setNearfield();
498   -}
499   -
500   -static void OutputOptions()
501   -{
502   - cout<<SCOPE->toStr();
503   -
504   - cout<<"# of source points: "<<SCOPE->focalPoints.size()<<endl;
505   -
506   -}
507   -
508   -vector<ptype> test;
509   -static void SetOptions(po::options_description &desc)
510   -{
511   - desc.add_options()
512   - ("help", "prints this help")
513   - ("gui", "run using the Qt GUI")
514   - ("verbose", "verbose output\n\nOutput Parameters\n--------------------------")
515   -
516   - ("vector", "run a vector field simulation")
517   - ("intensity", po::value<string>()->default_value(DEFAULT_INTENSITY_FILE), "output measured intensity (filename)")
518   - ("absorbance", po::value<string>()->default_value(DEFAULT_ABSORBANCE_FILE), "output measured absorbance (filename)")
519   - ("transmittance", po::value<string>()->default_value(DEFAULT_TRANSMITTANCE_FILE), "output measured transmittance (filename)")
520   - ("far-field", po::value<string>()->default_value(DEFAULT_FAR_FILE), "output far-field at detector (filename)")
521   - ("near-field", po::value<string>()->default_value(DEFAULT_NEAR_FILE), "output field at focal plane (filename)")
522   - ("extended-source", po::value<string>()->default_value(DEFAULT_EXTENDED_SOURCE), "image of source at focus (filename)")
523   - ("output-type", po::value<string>()->default_value(DEFAULT_FIELD_TYPE), "output field value:\n magnitude, polarization, real, imaginary, angular-spectrum")
524   - ("colormap", po::value<string>()->default_value(DEFAULT_COLORMAP), "colormap: gray, brewer")
525   - ("append", "append result to an existing file\n (binary files only)\n\nSphere Parameters\n--------------------------")
526   -
527   - ("spheres", po::value< vector<ptype> >()->multitoken(), "sphere position: x y z a m")
528   - ("sphere-file", po::value< vector<string> >()->multitoken(), "sphere file:\n [x y z radius material]")
529   - ("materials", po::value< vector<ptype> >()->multitoken(), "refractive indices as n, k pairs:\n ex. -m n0 k0 n1 k1 n2 k2")
530   - ("material-file", po::value< vector<string> >()->multitoken(), "material file:\n [lambda n k]\n\nOptics\n--------------------------")
531   -
532   - ("lambda", po::value<ptype>()->default_value(DEFAULT_LAMBDA), "incident wavelength")
533   - ("nu", po::value<ptype>(), "incident frequency (in cm^-1)\n(if specified, lambda is ignored)")
534   - ("k", po::value< vector<ptype> >()->multitoken(), "k-vector direction: -k theta phi\n theta = [0 2*pi], phi = [0 pi]")
535   - ("amplitude", po::value<ptype>()->default_value(DEFAULT_AMPLITUDE), "incident field amplitude")
536   - ("condenser", po::value< vector<ptype> >()->multitoken(), "condenser numerical aperature\nA pair of values can be used to specify an inner obscuration: -c NAin NAout")
537   - ("objective", po::value< vector<ptype> >()->multitoken(), "objective numerical aperature\nA pair of values can be used to specify an inner obscuration: -c NAin NAout")
538   - ("focus", po::value< vector<ptype> >()->multitoken(), "focal position for the incident point source\n (default = --focus 0 0 0)")
539   - ("plane-wave", "simulates an incident plane wave\n\n\nImaging Parameters\n--------------------------")
540   -
541   - ("resolution", po::value<unsigned int>()->default_value(DEFAULT_SLICE_RES), "resolution of the detector")
542   - ("plane-lower-left", po::value< vector<ptype> >()->multitoken(), "lower-left position of the image plane")
543   - ("plane-upper-right", po::value< vector<ptype> >()->multitoken(), "upper-right position of the image plane")
544   - ("plane-normal", po::value< vector<ptype> >()->multitoken(), "normal for the image plane")
545   - ("xy", po::value< vector<ptype> >()->multitoken(), "specify an x-y image plane\n (standard microscope)")
546   - ("xz", po::value< vector<ptype> >()->multitoken(), "specify a x-z image plane\n (cross-section of the focal volume)")
547   - ("yz", po::value< vector<ptype> >()->multitoken(), "specify a y-z image plane\n (cross-section of the focal volume)\n\nSampling Parameters\n--------------------------")
548   -
549   - ("samples", po::value<int>()->default_value(DEFAULT_SAMPLES), "Monte-Carlo samples used to compute Us")
550   - ("padding", po::value<unsigned int>()->default_value(DEFAULT_PADDING), "FFT padding for the objective bandpass")
551   - ("supersample", po::value<unsigned int>()->default_value(DEFAULT_SUPERSAMPLE), "super-sampling rate for the detector field")
552   - ("field-order", po::value<int>()->default_value(DEFAULT_FIELD_ORDER), "order of the incident field")
553   - ("seed", po::value<unsigned int>(), "seed for the Monte-Carlo random number generator")
554   - ("recursive", "evaluate all Bessel functions recursively\n")
555