/mc_func_Berrocal.m

http://github.com/gallamine/Photonator · Objective C · 249 lines · 219 code · 30 blank · 0 comment · 26 complexity · ea7e5e033ce090ef6a793b1193e4dfeb MD5 · raw file

  1. % set up an array for the photons,
  2. % x, y, z, mu_x, mu_y, mu_z, weight, received
  3. % 0, 0, 0, 0 , 0 , 1 , 1 , 1 - initial values
  4. % 1, 2, 3, 4 , 5 , 6 , 7 , 8 - Position
  5. % photon(:,1) == X POSITION
  6. % photon(:,2) == Y POSITION
  7. % photon(:,3) == Z POSITION
  8. % photon(:,4) == ux
  9. % photon(:,5) == uy
  10. % photon(:,6) == uz
  11. % photon(:,7) == WEIGHT
  12. % photon(:,8) == RECEIVED? 1 = No, 0 = Yes (detected), -1 = terminated
  13. % index from origin, 0 theta (angle between x and z), 0 phi (angle between
  14. % x and y) along x-axis
  15. % V5 - change scattering equations. Change direction of propogation to
  16. % z-axis.
  17. % V6 - Lots of changes:
  18. % - Added size limits to the simulation. Photons terminate when
  19. % encountering boundaris
  20. % - Added unlimited scattering. Scattering is dependant on minimum weight
  21. % - added rouletting to remove photons of low weight
  22. % - added window effects to the receiver
  23. % - changed events to be based on 'c', not 'b'
  24. % - changed how weights are calculated/updated
  25. function [total_time,total_rec_power,total_rec_packets,rec_loc_final,total_rec_dist,rec_weights] = ...
  26. mc_func_Berrocal(num_photons,scattering_events,c,a,receiver_z,...
  27. cdf_scatter,angle,init_angle,init_angle2,diverg)
  28. useLimits = 'true';
  29. if strcmp(useLimits,'true')
  30. xLimMax = 0.005000;
  31. xLimMin = -0.005;
  32. yLimMax = 0.005;
  33. yLimMin = -0.005;
  34. zLimMax = 0.01;
  35. zLimMin = -0.005;
  36. end
  37. photon = zeros(num_photons,8);
  38. photon(:,7) = ones(num_photons,1); % set weights to one
  39. photon(:,8) = ones(num_photons,1); % set all active
  40. totaldist = zeros(num_photons,1); % record total distance traveled by each photon
  41. rec_dist = zeros(num_photons,1); % total distance photon traveld at point of reception
  42. rec_loc = zeros(num_photons,4); % location of the received photon on the z,y rec. plane
  43. total_rec_packets = 0; % Total number of packets to cross detector
  44. total_rec_power = 0; % Total power to cross detector
  45. prob_of_survival = ((c-a)/c); % b/c
  46. rouletteConst = 10; % 1/rouletteConst determines the probability of a low power photon surviving
  47. rouletteConst_inv = 1/rouletteConst;
  48. inv_c = 1/c;
  49. inv_b = 1/(c-a);
  50. min_power = 1e-4; % minimum power value for photons before they are terminated by rouletting
  51. max_uz = 0.99999;
  52. tic;
  53. %
  54. % theta = diverg.*rand(1,num_photons); % uniform rand. dist over divergence ang.
  55. % phi = (2*pi).*rand(1,num_photons); % uniform rand. dist over azmuthal angles
  56. %
  57. % beta = init_angle; % direction the transmitter is pointing (zenith)
  58. % alpha = init_angle2; % direction the transmitter is pointing (azmuth)
  59. [x,y] = startingDistribution(num_photons); % Assuming a square end size
  60. %point down z-axis
  61. photon(:,1) = x.*xLimMax; % x position
  62. photon(:,2) = y.*yLimMax; % y position
  63. photon(:,6) = ones(num_photons,1); % z - 1
  64. % photon(:,1) = xLimMax; % x position
  65. % photon(:,2) = y.*yLimMax; % y position
  66. % photon(:,3) = x.*xLimMax; % z position
  67. % photon(:,4) = -1.*ones(num_photons,1); % x - 1
  68. photonsRemaining = num_photons; % count down for each photon received/terminated
  69. clear theta phi z beta alpha
  70. % for j = 1:scattering_events
  71. while photonsRemaining > 0 % which is faster? create random values on the fly?? <- check
  72. rand_array = rand(num_photons,3); % generate a matrix for each photon with rand propogation, roll, and pitch
  73. rand_array(:,3) = rand_array(:,3).*2.*pi; % Uniformly distributed over (0,2Pi)
  74. % iterate over every single photon to calculate new position and
  75. % whether it was received or not.
  76. for i = 1:num_photons
  77. % if photon hasn't been received
  78. if (photon(i,8) == 1)
  79. r = -inv_c*log(rand_array(i,1)); % randomly generate optical path length
  80. %Generate scattering angle from beam spread function
  81. minIndex = 2;
  82. maxIndex = length(cdf_scatter);
  83. midIndex = minIndex + ceil((maxIndex - minIndex)/2);
  84. while rand_array(i,2) ~= cdf_scatter(midIndex) && maxIndex >= minIndex % changed > to >=
  85. midIndex = minIndex + ceil((maxIndex - minIndex)/2);
  86. if rand_array(i,2) > cdf_scatter(midIndex)
  87. minIndex = midIndex + 1;
  88. elseif rand_array(i,2) < cdf_scatter(midIndex)
  89. maxIndex = midIndex - 1;
  90. end
  91. end
  92. midIndex = minIndex + ceil((maxIndex - minIndex)/2);
  93. k = midIndex;
  94. theta = angle(k-1) + (rand_array(i,2) - cdf_scatter(k-1))*(angle(k) - angle(k-1))/(cdf_scatter(k) - cdf_scatter(k-1)); % Linear interpolation from "angle" vector
  95. phi = rand_array(i,3); % Phi is uniformly distributed over 0-2pi
  96. % find new position increment based on PREVIOUS direction vectors (ux,uy,uz). This
  97. % takes care of the initial condition problem where photons
  98. % were scattered immediately on the first iteration.
  99. x_step = r*photon(i,4); % x step size
  100. y_step = r*photon(i,5); % y step size
  101. z_step = r*photon(i,6); % z step size
  102. % if the photon moves past the receiver plane
  103. if ((photon(i,3) + z_step) >= receiver_z)
  104. if photon(i,6) ~= 0 % If the photon has a z-component, mu_z != 0
  105. % z distance to receiver plane
  106. z_dist_rec_intersection = receiver_z - photon(i,3); % Zrec - Zphoton
  107. % y distance to receiver plane
  108. y_dist_rec_intersection = z_dist_rec_intersection*photon(i,5)/photon(i,6);
  109. % x distance to receiver plane
  110. x_dist_rec_intersection = z_dist_rec_intersection*photon(i,4)/photon(i,6);
  111. else
  112. disp('how can the photon cross the receiver plane when it"s pointing straight up??? Z distance step:');
  113. disp(z_step);
  114. disp('Z position:');
  115. disp(photon(i,3));
  116. end
  117. % euclidian distance to the reciever plane
  118. dist_to_rec = z_dist_rec_intersection / photon(i,6); % z / mu_z
  119. rec_loc(i,1) = photon(i,1) + x_dist_rec_intersection; % x-axis location of reception
  120. rec_loc(i,2) = photon(i,2) + y_dist_rec_intersection; % y-axis location of reception
  121. rec_loc(i,3) = photon(i,4); % incident angle (mu_x)
  122. rec_loc(i,4) = photon(i,5); % for statistics, should be uniform (mu_y)
  123. rec_loc(i,5) = photon(i,6); % for statistics, should be uniform (mu_z)
  124. total_rec_packets = total_rec_packets + 1;
  125. total_rec_power = total_rec_power + photon(i,7); % total power at the receiver plane (sum of received photons)
  126. rec_dist(i) = totaldist(i)+ dist_to_rec; % individual photon's distance traveled.
  127. photon(i,8) = 0; % mark photon as received
  128. photonsRemaining = photonsRemaining - 1; % decrement number of outstanding photons
  129. % update the total distance the photon has traveled
  130. totaldist(i) = totaldist(i) + dist_to_rec;
  131. else % if the photon didn't move into the detector, reduce its power & move it
  132. photon(i,1) = photon(i,1) + x_step; % move to new x position
  133. photon(i,2) = photon(i,2) + y_step; % move to new y position
  134. photon(i,3) = photon(i,3) + z_step; % move to new z position
  135. if ((photon(i,1) > xLimMax) || (photon(i,1) < xLimMin) || (photon(i,2) > yLimMax) || (photon(i,2) < yLimMin) || (photon(i,3) < zLimMin))
  136. photon(i,8) = -1; % mark as terminated
  137. photonsRemaining = photonsRemaining - 1; % decrement outstanding photons
  138. else % if the photon is still in the boundaries
  139. photon(i,7) = photon(i,7)*prob_of_survival; % reduce weight
  140. if photon(i,7) < min_power
  141. if rand() > (rouletteConst_inv) % if the photon is randomly chosen to be terminated ...
  142. photon(i,8) = -1; % -1 indicates a photon was terminated, but not received
  143. photonsRemaining = photonsRemaining - 1; % decrement outstanding photons
  144. else % ... otherwise the photon gets the energey of terminated photons
  145. photon(i,7) = photon(i,7)*rouletteConst; % shift power of terminated photons to new photon
  146. end
  147. end
  148. if abs(photon(i,6)) > max_uz % if uz ~ 1
  149. photon(i,4) = sin(theta)*cos(phi);
  150. photon(i,5) = sin(theta)*sin(phi);
  151. photon(i,6) = sign(photon(i,6))*cos(theta);
  152. %disp('mu_z near 1')
  153. else
  154. sqrt_uz = sqrt(1 - photon(i,6)^2);
  155. old_ux = photon(i,4);
  156. old_uy = photon(i,5);
  157. old_uz = photon(i,6);
  158. photon(i,4) = (sin(theta)/sqrt_uz)*(old_ux*old_uz*cos(phi) - old_uy*sin(phi)) + old_ux*cos(theta); % ux
  159. photon(i,5) = (sin(theta)/sqrt_uz)*(old_uy*old_uz*cos(phi) + old_ux*sin(phi)) + old_uy*cos(theta); % uy
  160. photon(i,6) = (-sin(theta)*cos(phi))*sqrt_uz + old_uz*cos(theta); % uz
  161. %disp('mu_z less than 1')
  162. end
  163. end
  164. % update the total distance the photon has traveled
  165. totaldist(i) = totaldist(i) + r;
  166. end
  167. end
  168. end
  169. end
  170. total_time = toc;
  171. % Do this after the loop above, so we can allocate the array once (instead
  172. % of growing dynamically as we receive individual photons - SLOW)
  173. rec_loc_final = ones(total_rec_packets,5);
  174. j = 1;
  175. for i = 1:num_photons % iterate over all photons
  176. if (photon(i,8) == 0) % if the photon was received
  177. rec_loc_final(j,:) = rec_loc(i,:); % record the receive location and angles
  178. j = j +1; % increment the number of received photons
  179. end
  180. end
  181. if ((j-1) ~= total_rec_packets)
  182. disp('Error! Total received photons doesnt equal j iterator. ');
  183. disp(sprintf('j = %d and total_rec_packets = %d',j, total_rec_packets));
  184. end
  185. j = 1;
  186. total_rec_dist = zeros(total_rec_packets,1);
  187. rec_weights = zeros(total_rec_packets,1);
  188. total_rec_power = 0;
  189. for i = 1:num_photons
  190. if (photon(i,8) == 0)
  191. total_rec_dist(j) = rec_dist(i); % store the distance traveled by each photon
  192. rec_weights(j) = photon(i,7); % store the weights of received photons
  193. j = j + 1;
  194. end
  195. end
  196. if ((j-1) ~= total_rec_packets)
  197. disp('Error! Total received distances doesnt equal j iterator');
  198. disp(sprintf('j = %d and total_rec_packets = %d',j, total_rec_packets));
  199. end