Skip to content

Commit c30628a

Browse files
Functional refraction and reflection using physics struct created by Union_make_material
Using fresnels equations to calculate reflection probability. Now only the closest intersection solution with the same surface_index is ignored.
1 parent 4debabd commit c30628a

2 files changed

Lines changed: 89 additions & 88 deletions

File tree

mcstas-comps/share/union-lib.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,7 +1725,7 @@ int clear_intersection_table(struct intersection_time_table_struct *intersection
17251725
};
17261726

17271727
void print_intersection_table(struct intersection_time_table_struct *intersection_time_table) {
1728-
printf("debug print\n");
1728+
17291729
int num_volumes,iterate,solutions;
17301730
int max_number_of_solutions = 0;
17311731

@@ -1745,7 +1745,10 @@ void print_intersection_table(struct intersection_time_table_struct *intersectio
17451745
printf(" ");
17461746
printf("| CALCULATED |");
17471747
for (solutions = 0;solutions < max_number_of_solutions;solutions++) {
1748-
printf(" - SOLUTION %d - |",solutions);
1748+
printf(" - SOLUTION %d - |", solutions);
1749+
}
1750+
for (solutions = 0;solutions < max_number_of_solutions;solutions++) {
1751+
printf(" - SURFACE %d - |", solutions);
17491752
}
17501753

17511754
printf("\n");
@@ -1763,6 +1766,12 @@ void print_intersection_table(struct intersection_time_table_struct *intersectio
17631766
else
17641767
printf(" |");
17651768
}
1769+
for (solutions = 0;solutions < max_number_of_solutions;solutions++) {
1770+
if (intersection_time_table->n_elements[iterate] > solutions && intersection_time_table->calculated[iterate] == 1)
1771+
printf(" %1.6d |",intersection_time_table->surface_index[iterate][solutions]);
1772+
else
1773+
printf(" |");
1774+
}
17661775
printf("\n");
17671776
}
17681777
printf("------------------------------------------------------------");
@@ -2596,7 +2605,7 @@ int sample_box_intersect_simple(double *t, double *nx, double *ny, double *nz, i
25962605
double width = geometry->geometry_parameters.p_box_storage->x_width1;
25972606
double height = geometry->geometry_parameters.p_box_storage->y_height1;
25982607
double depth = geometry->geometry_parameters.p_box_storage->z_depth;
2599-
2608+
26002609
// Declare variables for the function
26012610
double x_new,y_new,z_new;
26022611

@@ -2647,7 +2656,7 @@ int sample_box_intersect_simple(double *t, double *nx, double *ny, double *nz, i
26472656

26482657
// determine hit face: difference to plane is closest to 0 (in box coordinate system)
26492658
normal_vector_rotated = coords_set(trunc(2.002*x/width), trunc(2.002*y/height), trunc(2.002*z/depth));
2650-
2659+
26512660
// Set surface index
26522661
if (normal_vector_rotated.z < -0.5)
26532662
// back
@@ -2670,7 +2679,7 @@ int sample_box_intersect_simple(double *t, double *nx, double *ny, double *nz, i
26702679

26712680
// Rotate back to master coordinate system
26722681
normal_vector = rot_apply(geometry->rotation_matrix, normal_vector_rotated);
2673-
2682+
26742683
// Set the normal vector components
26752684
nx[index] = normal_vector.x;
26762685
ny[index] = normal_vector.y;

mcstas-comps/union/Union_master.comp

Lines changed: 75 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)