Skip to content

Commit 4debabd

Browse files
Started work on proper system for surface effects.
Refraction will be a special case always present (if information given), and general surface effects to follow. Work in progress, not yet functional.
1 parent ea9469e commit 4debabd

3 files changed

Lines changed: 488 additions & 45 deletions

File tree

mcstas-comps/share/union-lib.c

Lines changed: 98 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ int num_volumes;
4141
int *calculated;
4242
int *n_elements;
4343
double **intersection_times;
44+
double **normal_vector_x;
45+
double **normal_vector_y;
46+
double **normal_vector_z;
47+
int **surface_index;
4448
};
4549

4650
struct line_segment{
47-
//struct position point1;
48-
//struct position point2;
4951
Coords point1;
5052
Coords point2;
5153
int number_of_dashes;
@@ -75,12 +77,6 @@ struct line_segment *lines;
7577
#pragma acc shape(lines[0:number_of_lines]) init_needed(number_of_lines)
7678
};
7779

78-
// 2D lists not needed anyway
79-
// struct pointer_to_2d_int_list {
80-
// int n_lists;
81-
// struct pointer_to_1d_int_list *lists;
82-
// }
83-
8480
// Todo: see if the union geometry_parameter_union and other geometry structs can be here
8581
union geometry_parameter_union{
8682
struct sphere_storage *p_sphere_storage;
@@ -405,8 +401,8 @@ struct pointer_to_1d_int_list focus_array_indices; // Add 1D integer array with
405401

406402

407403
// intersect_function takes position/velocity of ray and parameters, returns time list
408-
int (*intersect_function)(double*,int*,double*,double*,struct geometry_struct*);
409-
// t_array,n_ar,r ,v
404+
int (*intersect_function)(double*, double*, double*, double*, int*, int*,double*,double*,struct geometry_struct*);
405+
// t_array, nx array, ny array, nz array, surface_index array, n arary, r ,v
410406

411407
// within_function that checks if the ray origin is within this volume
412408
int (*within_function)(Coords,struct geometry_struct*);
@@ -456,6 +452,12 @@ double my_a;
456452
int number_of_processes;
457453
// pointer to array of pointers to physics_sub structures that each describe a scattering process
458454
struct scattering_process_struct *p_scattering_array;
455+
456+
// refraction related
457+
int has_refraction_info;
458+
double refraction_rho;
459+
double refraction_bc;
460+
double refraction_Qc;
459461
};
460462

461463
union data_transfer_union{
@@ -1723,6 +1725,7 @@ int clear_intersection_table(struct intersection_time_table_struct *intersection
17231725
};
17241726

17251727
void print_intersection_table(struct intersection_time_table_struct *intersection_time_table) {
1728+
printf("debug print\n");
17261729
int num_volumes,iterate,solutions;
17271730
int max_number_of_solutions = 0;
17281731

@@ -1915,10 +1918,16 @@ struct lines_to_draw draw_line_with_highest_priority(Coords position1,Coords pos
19151918
direction[2] = r2[2] - r1[2];
19161919
int geometry_output;
19171920

1921+
// Todo: switch to nicer intersect function call
1922+
double double_dummy;
1923+
int int_dummy;
1924+
1925+
19181926
// Find intersections
19191927
for (volume_index = 1;volume_index < number_of_volumes; volume_index++) {
19201928
if (volume_index != N) {
1921-
geometry_output = Geometries[volume_index]->intersect_function(temp_intersection,&number_of_solutions,r1,direction,Geometries[volume_index]);
1929+
geometry_output = Geometries[volume_index]->intersect_function(temp_intersection, &double_dummy, &double_dummy, &double_dummy, &int_dummy,
1930+
&number_of_solutions,r1,direction,Geometries[volume_index]);
19221931
// printf("No solutions for intersection (Volume %d) with %d \n",N,volume_index);
19231932
for (iterate=0;iterate<number_of_solutions;iterate++) {
19241933
// print_1d_double_list(intersection_list,"intersection_list");
@@ -2389,7 +2398,7 @@ int A_overlaps_B(struct geometry_struct *child, struct geometry_struct *parent)
23892398

23902399
// ------------- Functions for box ray tracing used in trace ---------------------------------
23912400
// These functions needs to be fast, as they may be used many times for each ray
2392-
int sample_box_intersect_advanced(double *t,int *num_solutions,double *r,double *v,struct geometry_struct *geometry) {
2401+
int sample_box_intersect_advanced(double *t, double *nx, double *ny, double *nz, int *surface_index, int *num_solutions,double *r,double *v,struct geometry_struct *geometry) {
23932402
// possible approaches
23942403
// rotate to a simple coordinate system by rotating the ray (easier to switch to McStas standard)
23952404

@@ -2583,7 +2592,7 @@ void box_corners_local_frame(Coords *corner_points, struct geometry_struct *geom
25832592
corner_points[7] = coords_add(corner_points[4],coords_scalar_mult(y_vector,height2));
25842593
};
25852594

2586-
int sample_box_intersect_simple(double *t,int *num_solutions,double *r,double *v,struct geometry_struct *geometry) {
2595+
int sample_box_intersect_simple(double *t, double *nx, double *ny, double *nz, int *surface_index, int *num_solutions, double *r, double *v, struct geometry_struct *geometry) {
25872596
double width = geometry->geometry_parameters.p_box_storage->x_width1;
25882597
double height = geometry->geometry_parameters.p_box_storage->y_height1;
25892598
double depth = geometry->geometry_parameters.p_box_storage->z_depth;
@@ -2598,28 +2607,75 @@ int sample_box_intersect_simple(double *t,int *num_solutions,double *r,double *v
25982607

25992608
Coords coordinates = coords_set(x_new,y_new,z_new);
26002609
Coords rotated_coordinates;
2601-
// printf("Cords coordinates = (%f,%f,%f)\n",coordinates.x,coordinates.y,coordinates.z);
2610+
//printf("Cords coordinates = (%f,%f,%f)\n",coordinates.x,coordinates.y,coordinates.z);
26022611

26032612
// Rotate the position of the neutron around the center of the cylinder
26042613
rotated_coordinates = rot_apply(geometry->transpose_rotation_matrix,coordinates);
26052614
// rotated_coordinates = rot_apply(rotation_matrix_debug,coordinates);
2606-
// printf("Cords rotated_coordinates = (%f,%f,%f)\n",rotated_coordinates.x,rotated_coordinates.y,rotated_coordinates.z);
2615+
//printf("Cords rotated_coordinates = (%f,%f,%f)\n",rotated_coordinates.x,rotated_coordinates.y,rotated_coordinates.z);
26072616

26082617
Coords velocity = coords_set(v[0],v[1],v[2]);
26092618
Coords rotated_velocity;
2610-
// printf("Cords velocity = (%f,%f,%f)\n",velocity.x,velocity.y,velocity.z);
2619+
//printf("Cords velocity = (%f,%f,%f)\n",velocity.x,velocity.y,velocity.z);
26112620

26122621
// Rotate the position of the neutron around the center of the cylinder
26132622
rotated_velocity = rot_apply(geometry->transpose_rotation_matrix,velocity);
26142623
// rotated_velocity = rot_apply(rotation_matrix_debug,velocity);
2615-
// printf("Cords rotated_velocity = (%f,%f,%f)\n",rotated_velocity.x,rotated_velocity.y,rotated_velocity.z);
2624+
//printf("Cords rotated_velocity = (%f,%f,%f)\n",rotated_velocity.x,rotated_velocity.y,rotated_velocity.z);
26162625

26172626
int output;
2618-
// Run McStas built in sphere intersect funtion (sphere centered around origin)
2627+
// Run McStas built in box intersect funtion (box centered around origin)
26192628
if ((output = box_intersect(&t[0],&t[1],rotated_coordinates.x,rotated_coordinates.y,rotated_coordinates.z,rotated_velocity.x,rotated_velocity.y,rotated_velocity.z,width,height,depth)) == 0) {
26202629
*num_solutions = 0;t[0]=-1;t[1]=-1;}
26212630
else if (t[1] != 0) *num_solutions = 2;
26222631
else {*num_solutions = 1;t[1]=-1;} // t[2] is a memory error!
2632+
2633+
// Rewritten code from refractor.comp
2634+
int index;
2635+
double x, y, z, dt;
2636+
double rotated_nx, rotated_ny, rotated_nz;
2637+
Coords normal_vector_rotated;
2638+
Coords normal_vector;
2639+
for (index=0; index<*num_solutions; index++) {
2640+
2641+
dt = t[index];
2642+
2643+
// Intersection point in box coordinate system
2644+
x = rotated_coordinates.x + dt*rotated_velocity.x;
2645+
y = rotated_coordinates.y + dt*rotated_velocity.y;
2646+
z = rotated_coordinates.z + dt*rotated_velocity.z;
2647+
2648+
// determine hit face: difference to plane is closest to 0 (in box coordinate system)
2649+
normal_vector_rotated = coords_set(trunc(2.002*x/width), trunc(2.002*y/height), trunc(2.002*z/depth));
2650+
2651+
// Set surface index
2652+
if (normal_vector_rotated.z < -0.5)
2653+
// back
2654+
surface_index[index] = 0;
2655+
else if(normal_vector_rotated.z > 0.5)
2656+
// front
2657+
surface_index[index] = 1;
2658+
else if(normal_vector_rotated.x > 0.5)
2659+
// left
2660+
surface_index[index] = 2;
2661+
else if(normal_vector_rotated.x < -0.5)
2662+
// right
2663+
surface_index[index] = 3;
2664+
else if(normal_vector_rotated.y > 0.5)
2665+
// top
2666+
surface_index[index] = 4;
2667+
else if(normal_vector_rotated.y < -0.5)
2668+
// bottom
2669+
surface_index[index] = 5;
2670+
2671+
// Rotate back to master coordinate system
2672+
normal_vector = rot_apply(geometry->rotation_matrix, normal_vector_rotated);
2673+
2674+
// Set the normal vector components
2675+
nx[index] = normal_vector.x;
2676+
ny[index] = normal_vector.y;
2677+
nz[index] = normal_vector.z;
2678+
}
26232679

26242680
return output;
26252681
};
@@ -3548,7 +3604,12 @@ int existence_of_intersection(Coords point1, Coords point2, struct geometry_stru
35483604

35493605
start_point[0] = point1.x;start_point[1] = point1.y;start_point[2] = point1.z;
35503606
vector_between_v[0] = vector_between.x;vector_between_v[1] = vector_between.y;vector_between_v[2] = vector_between.z;
3551-
geometry->intersect_function(temp_solution,&number_of_solutions,start_point,vector_between_v,geometry);
3607+
3608+
// todo: Switch to nicer intersect call
3609+
double dummy_double;
3610+
int dummy_int;
3611+
3612+
geometry->intersect_function(temp_solution, &dummy_double, &dummy_double, &dummy_double, &dummy_int, &number_of_solutions,start_point,vector_between_v,geometry);
35523613
if (number_of_solutions > 0) {
35533614
if (temp_solution[0] > 0 && temp_solution[0] < 1) return 1;
35543615
if (number_of_solutions == 2) {
@@ -5867,34 +5928,46 @@ int box_within_cone(struct geometry_struct *geometry_child,struct geometry_struc
58675928

58685929

58695930
// Flexible intersection function
5870-
int intersect_function(double *t,int *num_solutions,double *r,double *v,struct geometry_struct *geometry) {
5931+
int intersect_function(double *t, double *nx, double *ny, double *nz, int *surface_index, int *num_solutions, double *r, double *v, struct geometry_struct *geometry) {
58715932
int output = 0;
58725933
switch(geometry->eShape) {
58735934
case box:
5874-
if (geometry->geometry_parameters.p_box_storage->is_rectangle == 1)
5875-
output = sample_box_intersect_simple(t, num_solutions, r, v, geometry);
5876-
else
5877-
output = sample_box_intersect_advanced(t, num_solutions, r, v, geometry);
5935+
if (geometry->geometry_parameters.p_box_storage->is_rectangle == 1) {
5936+
output = sample_box_intersect_simple(t, nx, ny, nz, surface_index, num_solutions, r, v, geometry);
5937+
}
5938+
else {
5939+
printf("Intersection function: box advanced not updated for normals yet!");
5940+
exit(1);
5941+
output = sample_box_intersect_advanced(t, nx, ny, nz, surface_index, num_solutions, r, v, geometry);
5942+
}
58785943
break;
58795944
case sphere:
5945+
printf("Intersection function: sphere not updated for normals yet!");
5946+
exit(1);
58805947
output = sample_sphere_intersect(t, num_solutions, r, v, geometry);
58815948
break;
58825949
case cylinder:
5950+
printf("Intersection function: cylinder not updated for normals yet!");
5951+
exit(1);
58835952
output = sample_cylinder_intersect(t, num_solutions, r, v, geometry);
58845953
break;
58855954
case cone:
5955+
printf("Intersection function: cone not updated for normals yet!");
5956+
exit(1);
58865957
output = sample_cone_intersect(t, num_solutions, r, v, geometry);
58875958
break;
58885959
#ifndef OPENACC
58895960
case mesh:
5961+
printf("Intersection function: mesh not updated for normals yet!");
5962+
exit(1);
58905963
output = sample_mesh_intersect(t, num_solutions, r, v, geometry);
58915964
break;
58925965
#endif
58935966
default:
58945967
printf("Intersection function: No matching geometry found!");
58955968
break;
58965969
}
5897-
5970+
58985971
return output;
58995972
};
59005973

mcstas-comps/union/Union_make_material.comp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
* process_string: [string] Comma seperated names of physical processes
3535
* my_absorption: [1/m] Inverse penetration depth from absorption at standard energy
3636
* absorber: [0/1] Control parameter, if set to 1 the material will have no scattering processes
37+
* refraction_sigma_coh: [barn] coherent cross section of refracting material. Use negative value to indicate a negative coherent scattering length
38+
* refraction_density: [g/cm3] density of the refracting material. density < 0 means the material is outside/before the shape.
39+
* refraction_weight: [g/mol] molar mass of the refracting material
3740
* init: [string] Name of Union_init component (typically "init", default)
3841
*
3942
* CALCULATED PARAMETERS:
@@ -50,7 +53,7 @@
5053

5154
DEFINE COMPONENT Union_make_material
5255

53-
SETTING PARAMETERS(string process_string="NULL", my_absorption,absorber=0, string init="init")
56+
SETTING PARAMETERS(string process_string="NULL", my_absorption,absorber=0, refraction_density=0, refraction_sigma_coh=0, refraction_weight=0, string init="init")
5457

5558

5659
/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
@@ -134,7 +137,6 @@ int manual_linking_function(char *name, char *input_string) {
134137
/* walk through other tokens */
135138
while( token != NULL )
136139
{
137-
//printf( " %s\n", token );
138140
if (strcmp(token,name) == 0) return_integer=1;
139141

140142
token = strtok(NULL,",");
@@ -177,13 +179,6 @@ INITIALIZE
177179

178180
accepted_processes.num_elements = 0;
179181
accepted_processes.elements = NULL;
180-
181-
/*
182-
// Comma test
183-
printf("Starting comma test on string: %s \n",process_string);
184-
printf("Number of commas in string: %d \n",count_commas(process_string));
185-
exit(1);
186-
*/
187182

188183

189184
if (0 == strcmp(NAME_CURRENT_COMP,"vacuum") || 0 == strcmp(NAME_CURRENT_COMP,"Vacuum")) {
@@ -239,10 +234,29 @@ struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_
239234
this_material.my_a = my_absorption; // add the absorption to this material
240235
sprintf(this_material.name,"%s",NAME_CURRENT_COMP);
241236

237+
238+
this_material.has_refraction_info = 0;
239+
if (refraction_density != 0 || refraction_weight != 0 || refraction_sigma_coh != 0) {
240+
if (refraction_density==0 || refraction_weight<=0)
241+
exit(printf("Union_make_material: %s: FATAL: invalid material density or molar weight: density=%g weight=%g\n",
242+
NAME_CURRENT_COMP, refraction_density, refraction_weight));
243+
this_material.refraction_rho = fabs(refraction_density)*6.02214179*1e23*1e-24/refraction_weight; // per at/Angs^3
244+
245+
if (refraction_sigma_coh==0)
246+
exit(printf("Refractor: %s: FATAL: invalid material coherent cross section: sigma_coh=%g\n",
247+
NAME_CURRENT_COMP, refraction_sigma_coh));
248+
this_material.refraction_bc = sqrt(fabs(refraction_sigma_coh)*100/4/PI)*1e-5; // bound coherent scattering length
249+
if (refraction_sigma_coh<0) this_material.refraction_bc *= -1;
250+
251+
this_material.refraction_Qc = 4*sqrt(PI*this_material.refraction_rho*fabs(this_material.refraction_bc));
252+
253+
this_material.has_refraction_info = 1;
254+
}
255+
242256
// packing the information into the global_material_element, which is then included in the global_material_list.
243257
sprintf(global_material_element.name,"%s",NAME_CURRENT_COMP);
244258
global_material_element.component_index = INDEX_CURRENT_COMP;
245-
global_material_element.physics = &this_material; // Would be nicer if this material was a pointer, now we have the (small) data two places
259+
global_material_element.physics = &this_material;
246260
add_element_to_material_list(global_material_list, global_material_element);
247261

248262
%}

0 commit comments

Comments
 (0)