@@ -146,6 +146,7 @@ DECLARE
146146 int solution;
147147 int min_solution;
148148 int ignore_closest;
149+ int ignore_surface_index;
149150 int min_volume;
150151 int time_found;
151152 double intersection_time;
@@ -931,11 +932,11 @@ exit(-1);
931932
932933 intersection_time_table.n_elements = (int*) malloc(intersection_time_table.num_volumes * sizeof(int));
933934 intersection_time_table.calculated = (int*) malloc(intersection_time_table.num_volumes * sizeof(int));
934- intersection_time_table.intersection_times = (double**) malloc(intersection_time_table.num_volumes * sizeof(double));
935- intersection_time_table.normal_vector_x = (double**) malloc(intersection_time_table.num_volumes * sizeof(double));
936- intersection_time_table.normal_vector_y = (double**) malloc(intersection_time_table.num_volumes * sizeof(double));
937- intersection_time_table.normal_vector_z = (double**) malloc(intersection_time_table.num_volumes * sizeof(double));
938- intersection_time_table.surface_index = (int**) malloc(intersection_time_table.num_volumes * sizeof(int));
935+ intersection_time_table.intersection_times = (double**) malloc(intersection_time_table.num_volumes * sizeof(double* ));
936+ intersection_time_table.normal_vector_x = (double**) malloc(intersection_time_table.num_volumes * sizeof(double* ));
937+ intersection_time_table.normal_vector_y = (double**) malloc(intersection_time_table.num_volumes * sizeof(double* ));
938+ intersection_time_table.normal_vector_z = (double**) malloc(intersection_time_table.num_volumes * sizeof(double* ));
939+ intersection_time_table.surface_index = (int**) malloc(intersection_time_table.num_volumes * sizeof(int* ));
939940
940941 for (iterator = 0;iterator < intersection_time_table.num_volumes;iterator++){
941942 if (strcmp(Volumes[iterator]->geometry.shape, "mesh") == 0) {
@@ -950,13 +951,20 @@ exit(-1);
950951 intersection_time_table.intersection_times[0] = NULL;
951952 }
952953 else {
954+ printf("allocating memory for volume %d \n", iterator);
953955 intersection_time_table.intersection_times[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double));
954956 intersection_time_table.normal_vector_x[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double));
955957 intersection_time_table.normal_vector_y[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double));
956958 intersection_time_table.normal_vector_z[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double));
957959 intersection_time_table.surface_index[iterator] = (int*) malloc(intersection_time_table.n_elements[iterator]*sizeof(int));
960+
958961 for (solutions = 0;solutions < intersection_time_table.n_elements[iterator];solutions++) {
959962 intersection_time_table.intersection_times[iterator][solutions] = -1.0;
963+ intersection_time_table.normal_vector_x[iterator][solutions] = -1.0;
964+ intersection_time_table.normal_vector_y[iterator][solutions] = -1.0;
965+ intersection_time_table.normal_vector_z[iterator][solutions] = -1.0;
966+ intersection_time_table.surface_index[iterator][solutions] = -1;
967+
960968 }
961969 }
962970 }
@@ -1156,7 +1164,11 @@ TRACE
11561164 printf("running intersection for intersect_list with *check = %d \n",*check);
11571165 #endif
11581166 // Calculate intersections using intersect function imbedded in the relevant volume structure using parameters that are also imbedded in the structure.
1159-
1167+ #ifdef Union_trace_verbal_setting
1168+ printf("surface_index[*check][0] = %d, surface_index[*check][1] = %d\n",
1169+ intersection_time_table.surface_index[*check][0],
1170+ intersection_time_table.surface_index[*check][1]);
1171+ #endif
11601172 // GPU Flexible intersect_function call
11611173 geometry_output = intersect_function(intersection_time_table.intersection_times[*check],
11621174 intersection_time_table.normal_vector_x[*check],
@@ -1166,6 +1178,10 @@ TRACE
11661178 number_of_solutions, r_start, v, &Volumes[*check]->geometry);
11671179
11681180 intersection_time_table.calculated[*check] = 1;
1181+ #ifdef Union_trace_verbal_setting
1182+ printf("finished running intersection for intersect_list with *check = %d \n",*check);
1183+ print_intersection_table(&intersection_time_table);
1184+ #endif
11691185 }
11701186 }
11711187
@@ -1272,11 +1288,13 @@ TRACE
12721288 #endif
12731289
12741290 // For the closest intersection to volume with index ignore_closest, the scattering with the shortest absolute time should be ignored
1275- if (ignore_closest != -1 ) {
1291+ if (ignore_closest > 0 ) {
12761292 min_intersection_time = 1E9;
12771293 min_solution = -1;
1278- for (solution = 0;solution<intersection_time_table.n_elements[ignore_closest];solution++) {
1279- if (fabs(intersection_time_table.intersection_times[ignore_closest][solution]) < min_intersection_time) {
1294+ for (solution = 0; solution<intersection_time_table.n_elements[ignore_closest]; solution++) {
1295+ // For a solution to be removed, it must have the same surface index as the ignored surface interaction point
1296+ if (intersection_time_table.surface_index[ignore_closest][solution] == ignore_surface_index && fabs(intersection_time_table.intersection_times[ignore_closest][solution]) < min_intersection_time) {
1297+ // if (fabs(intersection_time_table.intersection_times[ignore_closest][solution]) < min_intersection_time) {
12801298 min_intersection_time = fabs(intersection_time_table.intersection_times[ignore_closest][solution]);
12811299 min_solution = solution;
12821300 }
@@ -1295,15 +1313,16 @@ TRACE
12951313 // Loops are eqvialent to the 3 intersection calculation loops already completed
12961314
12971315 // First loop for checking intersect_check_list
1316+
12981317 #ifdef Union_trace_verbal_setting
1299- min_intersection_time=0;
13001318 printf("Incoming value of MIN_intersection_time=%g\n",min_intersection_time);
13011319 #endif
1320+ min_intersection_time=0;
13021321 time_found = 0;
13031322 for (start=check=Volumes[current_volume]->geometry.intersect_check_list.elements;check-start<Volumes[current_volume]->geometry.intersect_check_list.num_elements;check++) {
13041323 for (solution = 0;solution<intersection_time_table.n_elements[*check];solution++) {
13051324 if (time_found) {
1306- if ((intersection_time = intersection_time_table.intersection_times[*check][solution]) > time_propagated_without_scattering && intersection_time < min_intersection_time) {
1325+ if ((intersection_time = intersection_time_table.intersection_times[*check][solution]) > time_propagated_without_scattering && intersection_time < min_intersection_time) {
13071326 min_intersection_time = intersection_time;min_solution = solution;min_volume = *check;
13081327 #ifdef Union_trace_verbal_setting
13091328 printf("found A at %i x %i\n",*check,solution);
@@ -2046,7 +2065,6 @@ TRACE
20462065 //double par[] = {0.99, Volumes[current_volume]->p_physics->refraction_Qc, 6.0, 1.0, 1.0/300.0};
20472066 double reflectivity;
20482067
2049-
20502068 int p_reflect = 1;
20512069 int p_refract = 1;
20522070
@@ -2058,36 +2076,41 @@ TRACE
20582076 Coords I = coords_scale(V, 1/v_length); // normalised ray = v/|v|
20592077
20602078 // compute reflectivity
2079+ double qc;
20612080 double q_normal = fabs(2*coords_sp(V, N)*V2Q);
2081+ double q_qc_quadratic_diff;
2082+ int use_fresnel;
20622083
2084+ use_fresnel = 1;
20632085
20642086
2065- /*
2066- // Reflectivity calculation
2067-
2068- if (n2/n1 < 1)
2069- // qc exists
2070- qc = 2*k*sin(arccos(n2/n1));
2071- if (q < qc)
2072- reflectivity = 1.0
2073- else
2074- //fresnells law
2075- else:
2076- fresnells law
2077-
2078-
2079- */
2080-
20812087 /* Reflectivity (see component Guide). */
2082- // todo: use reflectivity
20832088 //StdReflecFunc(q_normal, par, &reflectivity);
20842089
2085- // test
2086- if (q_normal < 0.5)
2087- reflectivity = 0.9;
2088- else
2089- reflectivity = 0.0;
2090-
2090+ // Reflectivity calculation
2091+ if (n2/n1 < 1) {
2092+ // qc exists
2093+ qc = 4.0*PI*sin(acos(n2/n1))/lambda;
2094+ if (q_normal < qc) {
2095+ reflectivity = 1.0;
2096+ use_fresnel = 0;
2097+ }
2098+ // NEUTRON REFLECTION: PRINCIPLES AND EXAMPLES OF APPLICATIONS: Robert Cubitt and Giovanna Fragneto
2099+ //q_qc_quadratic_diff = sqrt(q_normal*q_normal - qc*qc)
2100+ //reflectivity = pow((q_normal - q_qc_quadratic_diff)/(q_normal + q_qc_quadratic_diff), 2);
2101+ }
2102+
2103+ if (use_fresnel) {
2104+ // Fresnel law for both n1 > n2 and n1 < n2
2105+ double term1, term2, R_perp, R_parallel;
2106+ term1 = n1 * sqrt(1.0 - pow(lambda * q_normal / (4.0 * PI * n1), 2));
2107+ term2 = n2 * sqrt(1.0 - pow(lambda * q_normal / (4.0 * PI * n2), 2));
2108+ R_perp = ((term1 - term2) / (term1 + term2))*((term1 - term2) / (term1 + term2));
2109+ R_parallel = ((term2 - term1) / (term2 + term1))*((term2 - term1) / (term2 + term1));
2110+ reflectivity = 0.5*(R_perp + R_parallel); // Unpolarized neutrons
2111+ }
2112+
2113+
20912114 double theta1, theta2;
20922115 // theta1: incident angle to the surface normal
20932116 double cos_theta1 = -coords_sp(N,I); // cos(theta1) = -N.I
@@ -2105,46 +2128,33 @@ TRACE
21052128 Coords V_reflect = coords_scale(I_reflect, v_length);
21062129
21072130 // compute refracted angle theta2...
2108- double sqr_cos_theta2 = 1-(n1/n2)*(n1/n2)*(1-cos_theta1*cos_theta1);
2131+ double sqr_cos_theta2 = 1-(n1/n2)*(n1/n2)*(1.0 -cos_theta1*cos_theta1);
21092132
21102133 // now choose which one to use, and compute outgoing velocity
2111- if (0 < sqr_cos_theta2 && sqr_cos_theta2 < 1) {
2134+ if (0 < sqr_cos_theta2 && sqr_cos_theta2 < 1.0 ) {
21122135 // refraction is possible
21132136
21142137 // theta2: refracted angle to the surface normal
21152138 double cos_theta2= sqrt(sqr_cos_theta2);
21162139
21172140 // select reflection (or refraction) from Monte-Carlo choice with probability R
21182141 // in this case we expect R to be small (q > Qc)
2119- if (p_reflect && 0 < reflectivity && reflectivity < 1 && rand01() < reflectivity) {
2120-
2121- // Propagate forward backwards before reflection to ensure neutron is in right volume
2122- /*
2123- x -= 1E-5*nx;
2124- y -= 1E-5*ny;
2125- z -= 1E-5*nz;
2126- */
2142+ if (p_reflect && 0.0 < reflectivity && reflectivity < 1.0 && rand01() < reflectivity) {
21272143
21282144 // choose reflection from MC
21292145 theta2 = theta1;
21302146 coords_get(V_reflect, &vx, &vy, &vz);
21312147
2132- if (current_volume == min_volume) {
2133- //excluded_volume = min_volume;
2134- ignore_closest = min_volume;
2135- } else {
2136- ignore_closest = min_volume;
2137- }
21382148 current_volume = previous_volume; // Reflected, stays in current volume
21392149
21402150 // Update velocity in all ways used in master
21412151 v[0] = vx; v[1] = vy; v[2] = vz;
21422152 v_length = sqrt(vx*vx + vy*vy + vz*vz);
21432153 k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz;
21442154 ray_velocity = coords_set(vx, vy, vz);
2145-
2146- //r[0] = x; r[1] = y; r[2] = z ;
2147- //ray_position = coords_set(x,y,z) ;
2155+
2156+ ignore_closest = min_volume ;
2157+ ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution] ;
21482158
21492159 // Since velocity is updated, we need to clear the intersection time table
21502160 clear_intersection_table(&intersection_time_table);
@@ -2168,29 +2178,21 @@ TRACE
21682178
21692179 coords_get(V_refract, &vx, &vy, &vz);
21702180
2171-
2172- // Reflected can ignore some intersections in next geometry iteration
2173- if (previous_volume == min_volume) {
2174- //excluded_volume = min_volume;
2175- ignore_closest = min_volume;
2176- } else {
2177- ignore_closest = min_volume;
2178- }
2179-
2180- ignore_closest = min_volume; // Ignore closest intersection in next geometry iteration
2181+
21812182
21822183 // Update velocity in all ways used in master
21832184 v[0] = vx; v[1] = vy; v[2] = vz;
21842185 v_length = sqrt(vx*vx + vy*vy + vz*vz);
21852186 k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz;
21862187 ray_velocity = coords_set(vx, vy, vz);
21872188
2188- //r[0] = x; r[1] = y; r[2] = z;
2189- //ray_position = coords_set(x,y,z);
2190-
2189+ // Reflected can ignore some intersections in next geometry iteration
2190+ ignore_closest = min_volume; // Ignore closest intersection in next geometry iteration
2191+ ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution];
2192+
21912193 // Since velocity is updated, we need to clear the intersection time table
21922194 clear_intersection_table(&intersection_time_table);
2193-
2195+
21942196 // Reset origin point for ray
21952197 r_start[0] = x; r_start[1] = y; r_start[2] = z;
21962198 time_propagated_without_scattering = 0.0;
@@ -2206,24 +2208,11 @@ TRACE
22062208 } else if (p_reflect) {
22072209 // only reflection: below total reflection
22082210
2209- // Propagate forward backwards before reflection to ensure neutron is in right volume
2210- /*
2211- x -= 1E-5*nx;
2212- y -= 1E-5*ny;
2213- z -= 1E-5*nz;
2214- */
2215-
22162211 theta2 = theta1;
22172212 if (0 < reflectivity && reflectivity < 1) p *= reflectivity; // should be R0
22182213 coords_get(V_reflect, &vx, &vy, &vz);
22192214
2220- // Reflected can ignore some intersections in next geometry iteration
2221- if (current_volume == min_volume) {
2222- //excluded_volume = min_volume;
2223- ignore_closest = min_volume;
2224- } else {
2225- ignore_closest = min_volume;
2226- }
2215+
22272216 current_volume = previous_volume; // Reflected, stays in current volume
22282217
22292218 // Update velocity in all ways used in master
@@ -2234,7 +2223,10 @@ TRACE
22342223
22352224 //r[0] = x; r[1] = y; r[2] = z;
22362225 //ray_position = coords_set(x,y,z);
2237-
2226+
2227+ // Reflected can ignore some intersections in next geometry iteration
2228+ ignore_closest = min_volume;
2229+ ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution];
22382230 // Since velocity is updated, we need to clear the intersection time table
22392231 clear_intersection_table(&intersection_time_table);
22402232
0 commit comments