From 2403c8e80428ac06967c667545309eb2c0150b86 Mon Sep 17 00:00:00 2001 From: Peter Willendrup Date: Tue, 17 Feb 2026 19:17:32 +0100 Subject: [PATCH] Apply formatter to union --- mcstas-comps/union/AF_HB_1D_process.comp | 349 +- .../union/IncoherentPhonon_process.comp | 9044 +++++++++-------- mcstas-comps/union/Incoherent_process.comp | 123 +- mcstas-comps/union/Mirror_surface.comp | 187 +- mcstas-comps/union/NCrystal_process.comp | 357 +- mcstas-comps/union/Non_process.comp | 107 +- mcstas-comps/union/PhononSimple_process.comp | 703 +- mcstas-comps/union/Powder_process.comp | 1111 +- .../union/Single_crystal_process.comp | 1541 +-- mcstas-comps/union/Template_process.comp | 121 +- mcstas-comps/union/Template_surface.comp | 182 +- mcstas-comps/union/Texture_process.comp | 4222 ++++---- .../union/Union_abs_logger_1D_space.comp | 662 +- .../Union_abs_logger_1D_space_event.comp | 707 +- .../union/Union_abs_logger_1D_space_tof.comp | 740 +- ...ion_abs_logger_1D_space_tof_to_lambda.comp | 943 +- .../union/Union_abs_logger_1D_time.comp | 551 +- .../union/Union_abs_logger_2D_space.comp | 865 +- .../union/Union_abs_logger_event.comp | 927 +- mcstas-comps/union/Union_abs_logger_nD.comp | 738 +- mcstas-comps/union/Union_box.comp | 690 +- mcstas-comps/union/Union_conditional_PSD.comp | 471 +- .../union/Union_conditional_standard.comp | 550 +- mcstas-comps/union/Union_cone.comp | 618 +- mcstas-comps/union/Union_cylinder.comp | 496 +- mcstas-comps/union/Union_init.comp | 86 +- mcstas-comps/union/Union_logger_1D.comp | 764 +- mcstas-comps/union/Union_logger_2DQ.comp | 856 +- mcstas-comps/union/Union_logger_2D_kf.comp | 860 +- .../union/Union_logger_2D_kf_time.comp | 969 +- mcstas-comps/union/Union_logger_2D_space.comp | 971 +- .../union/Union_logger_2D_space_time.comp | 1066 +- mcstas-comps/union/Union_logger_3D_space.comp | 1172 +-- mcstas-comps/union/Union_make_material.comp | 361 +- mcstas-comps/union/Union_master.comp | 4538 +++++---- mcstas-comps/union/Union_master_GPU.comp | 3359 +++--- mcstas-comps/union/Union_mesh.comp | 1769 ++-- mcstas-comps/union/Union_sphere.comp | 506 +- mcstas-comps/union/Union_stop.comp | 8 +- 39 files changed, 22771 insertions(+), 21519 deletions(-) diff --git a/mcstas-comps/union/AF_HB_1D_process.comp b/mcstas-comps/union/AF_HB_1D_process.comp index 1713041533..0e03edbd9e 100644 --- a/mcstas-comps/union/AF_HB_1D_process.comp +++ b/mcstas-comps/union/AF_HB_1D_process.comp @@ -62,267 +62,276 @@ SETTING PARAMETERS(atom_distance=1, number_density=0, unit_cell_volume=0, A_cons SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this AF_HB_1D_process component" -#endif + #ifndef Union + #error "The Union_init component must be included before this AF_HB_1D_process component" + #endif -struct physical_constants_AF_HB_1D{ + struct physical_constants_AF_HB_1D { // List of constants to be passed between functions - double a; // Scattering length - double J; // Interaction strength - double A; // Constant from Müller conjecture + double a; // Scattering length + double J; // Interaction strength + double A; // Constant from Müller conjecture double Atom_dist; // Distance between atoms double q2unit_less; double integral_pre_factor; - //double weight_factor; -}; + // double weight_factor; + }; -// Very important to add a pointer to this struct in the union-lib.c file -struct AF_HB_1D_physics_storage_struct{ + // Very important to add a pointer to this struct in the union-lib.c file + struct AF_HB_1D_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + double current_total_cross_section; double number_density_internal; struct physical_constants_AF_HB_1D physical_constants; -}; + }; -double eval_Sqw_AF_HB_1D(double q, double w, struct physical_constants_AF_HB_1D *constants) { + double + eval_Sqw_AF_HB_1D (double q, double w, struct physical_constants_AF_HB_1D* constants) { // Evaluate Sqw, here q should be in units of "rad", from normalizing with atom distance // w is here an energy transfer in meV - //printf("Sqw called with q = %f and w = %e\n",q,w); - if (w > 0.5*PI*constants->J*fabs(sin(q)) ) { - if (w < PI*constants->J*fabs(sin(0.5*q)) ) { - //return constants->A/(sqrt(w*w-0.25*PI*PI*constants->J*constants->J*fabs(sin(q))*fabs(sin(q)))); - // The result is currently returned in 1/meV. - double result = constants->A/(sqrt(w*w-0.25*PI*PI*constants->J*constants->J*fabs(sin(q))*fabs(sin(q)))); - //printf("Sqw returns = %e\n",result); + // printf("Sqw called with q = %f and w = %e\n",q,w); + if (w > 0.5 * PI * constants->J * fabs (sin (q))) { + if (w < PI * constants->J * fabs (sin (0.5 * q))) { + // return constants->A/(sqrt(w*w-0.25*PI*PI*constants->J*constants->J*fabs(sin(q))*fabs(sin(q)))); + // The result is currently returned in 1/meV. + double result = constants->A / (sqrt (w * w - 0.25 * PI * PI * constants->J * constants->J * fabs (sin (q)) * fabs (sin (q)))); + // printf("Sqw returns = %e\n",result); return result; - } else return 0; - } else return 0; -} + } else + return 0; + } else + return 0; + } -double numerical_integral_AF_HB_1D(double *k_initial,struct physical_constants_AF_HB_1D *constants) { + double + numerical_integral_AF_HB_1D (double* k_initial, struct physical_constants_AF_HB_1D* constants) { // returns cross section for this k_i - + double k_i_length; - k_i_length = sqrt(k_initial[0]*k_initial[0]+k_initial[1]*k_initial[1]+k_initial[2]*k_initial[2]); - - int theta_step,N_theta_steps=200; - double theta,theta_step_size,q_z; - + k_i_length = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); + + int theta_step, N_theta_steps = 200; + double theta, theta_step_size, q_z; + // Theta from 0 to Pi - theta_step_size = PI/N_theta_steps; - - int E_transfer_step,N_E_transfer_steps=200; - double E_transfer,E_transfer_step_size; - + theta_step_size = PI / N_theta_steps; + + int E_transfer_step, N_E_transfer_steps = 200; + double E_transfer, E_transfer_step_size; + // E_transfer [meV] // k [Å^-1] // Avoid transfering more energy than the ray have - if (PI*constants->J < k_i_length*k_i_length*K2V*K2V*VS2E) + if (PI * constants->J < k_i_length * k_i_length * K2V * K2V * VS2E) // Largest omega necessary: PI*J - E_transfer_step_size = PI*constants->J/N_E_transfer_steps; - else E_transfer_step_size = k_i_length*k_i_length*K2V*K2V*VS2E/N_E_transfer_steps; - + E_transfer_step_size = PI * constants->J / N_E_transfer_steps; + else + E_transfer_step_size = k_i_length * k_i_length * K2V * K2V * VS2E / N_E_transfer_steps; + double t_value; // length of final wavevector for certain theta/E_transfer choice. - + double integral_value = 0; - for (theta_step=0;theta_stepq2unit_less; + for (theta_step = 0; theta_step < N_theta_steps; theta_step++) { + theta = theta_step * theta_step_size; + + for (E_transfer_step = 0; E_transfer_step < N_E_transfer_steps; E_transfer_step++) { + E_transfer = E_transfer_step * E_transfer_step_size; + + t_value = sqrt (k_i_length * k_i_length - E_transfer * SE2V * V2K * SE2V * V2K); + q_z = (k_initial[2] - t_value * cos (theta)) * constants->q2unit_less; // May consider to translate q_z into first Brilluion zone, but not necessary - - integral_value += t_value*eval_Sqw_AF_HB_1D(q_z,E_transfer,constants)*sin(theta)*theta_step_size*E_transfer_step_size; + + integral_value += t_value * eval_Sqw_AF_HB_1D (q_z, E_transfer, constants) * sin (theta) * theta_step_size * E_transfer_step_size; } } - - //printf("integral_value after loop = %e\n",integral_value); - return 2*PI*constants->integral_pre_factor*integral_value/k_i_length; -} + // printf("integral_value after loop = %e\n",integral_value); + return 2 * PI * constants->integral_pre_factor * integral_value / k_i_length; + } -// Function for calculating my, the inverse penetration depth (for only this scattering process). -// The input for this function and its order may not be changed, but the names may be updated. -int AF_HB_1D_physics_my(double *my, double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function for calculating my, the inverse penetration depth (for only this scattering process). + // The input for this function and its order may not be changed, but the names may be updated. + int + AF_HB_1D_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, _class_particle* _particle) { // *k_initial is a pointer to a simple vector with 3 doubles, k[0], k[1], k[2] which describes the wavevector - struct physical_constants_AF_HB_1D *p_constants = &data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->physical_constants; - + struct physical_constants_AF_HB_1D* p_constants = &data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->physical_constants; + // Need to numerically solve integral to calculate cross section - double cross_section = numerical_integral_AF_HB_1D(k_initial,p_constants); - - //printf("Returned cross_section = %e\n",cross_section); + double cross_section = numerical_integral_AF_HB_1D (k_initial, p_constants); + + // printf("Returned cross_section = %e\n",cross_section); data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->current_total_cross_section = cross_section; - + // Number density given in units of 1E10*Å^-3, cross section in Å^2, returns 1/m. - *my = data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->number_density_internal*cross_section; - - //printf("Returned my = %e\n",*my); + *my = data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->number_density_internal * cross_section; + + // printf("Returned my = %e\n",*my); return 1; -}; + }; + + // Function that provides description of a basic scattering event. + // Do not change the + int + AF_HB_1D_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { -// Function that provides description of a basic scattering event. -// Do not change the -int AF_HB_1D_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { - // Unpack the physical constants struct - struct physical_constants_AF_HB_1D *p_constants = &data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->physical_constants; + struct physical_constants_AF_HB_1D* p_constants = &data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->physical_constants; // k_final and k_initial are passed as pointers to double vector[3] - double k_length = sqrt(k_initial[0]*k_initial[0]+k_initial[1]*k_initial[1]+k_initial[2]*k_initial[2]); + double k_length = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); Coords r_out; // choose a random direction vector in the specified focusing area double solid_angle; - focus_data->focusing_function(&r_out,&solid_angle,focus_data); - NORM(r_out.x,r_out.y,r_out.z); + focus_data->focusing_function (&r_out, &solid_angle, focus_data); + NORM (r_out.x, r_out.y, r_out.z); - // random energy transfer is now selected between 0 and PI*J // Need to ensure not transfering more energy than the ray has - + // Kim's proposal to use uniform E_transfer sampling, but will be outside of S(q,w) non-zero region often - double E_transfer,E_range,E_i = k_length*k_length*K2V*K2V*VS2E; - - if (PI*p_constants->J < E_i) - E_range = PI*p_constants->J; + double E_transfer, E_range, E_i = k_length * k_length * K2V * K2V * VS2E; + + if (PI * p_constants->J < E_i) + E_range = PI * p_constants->J; else E_range = E_i; - - E_transfer = E_range*rand01(); - - double k_f = sqrt(k_length*k_length - E_transfer*SE2V*V2K*SE2V*V2K); - - - //printf("---- E in scatter function --- \n"); - //printf("E_initial = %e \n",k_length*k_length*hbar*hbar*0.5/m_neutron); - //printf("E_initial = %e \n",k_length*k_length*K2V*K2V*VS2E); - //printf("E_initial = %e \n",E_i); - //printf("E_transfer = %e \n",E_transfer); - //printf("E_final = %e \n",k_f*k_f*K2V*K2V*VS2E); - - k_final[0] = r_out.x*k_f; k_final[1] = r_out.y*k_f; k_final[2] = r_out.z*k_f; - //printf("k_final = (%lf,%lf,%lf)\n",k_final[0],k_final[1],k_final[2]); - + + E_transfer = E_range * rand01 (); + + double k_f = sqrt (k_length * k_length - E_transfer * SE2V * V2K * SE2V * V2K); + + // printf("---- E in scatter function --- \n"); + // printf("E_initial = %e \n",k_length*k_length*hbar*hbar*0.5/m_neutron); + // printf("E_initial = %e \n",k_length*k_length*K2V*K2V*VS2E); + // printf("E_initial = %e \n",E_i); + // printf("E_transfer = %e \n",E_transfer); + // printf("E_final = %e \n",k_f*k_f*K2V*K2V*VS2E); + + k_final[0] = r_out.x * k_f; + k_final[1] = r_out.y * k_f; + k_final[2] = r_out.z * k_f; + // printf("k_final = (%lf,%lf,%lf)\n",k_final[0],k_final[1],k_final[2]); + double q[3]; q[0] = k_initial[0] - k_final[0]; q[1] = k_initial[1] - k_final[1]; q[2] = k_initial[2] - k_final[2]; - + double sqw_value; - if ((sqw_value = eval_Sqw_AF_HB_1D(p_constants->q2unit_less*q[2],E_transfer,p_constants)) > 0) { + if ((sqw_value = eval_Sqw_AF_HB_1D (p_constants->q2unit_less * q[2], E_transfer, p_constants)) > 0) { // Weight factor constants done in initialize, solid angle/ wavevector lengths and swq missing. - //printf("Scattering: Sqw(%f,%f) = %E \n",p_constants->q2unit_less*q[2],E_transfer,sqw_value); - *weight *= p_constants->integral_pre_factor*E_range*solid_angle*k_f/k_length*sqw_value/data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->current_total_cross_section; + // printf("Scattering: Sqw(%f,%f) = %E \n",p_constants->q2unit_less*q[2],E_transfer,sqw_value); + *weight *= p_constants->integral_pre_factor * E_range * solid_angle * k_f / k_length * sqw_value + / data_transfer.pointer_to_a_AF_HB_1D_physics_storage_struct->current_total_cross_section; return 1; - } else return 0; // Ray absorbed as Sqw == 0 - + } else + return 0; // Ray absorbed as Sqw == 0 + // A pointer to k_final is returned, and the wavevector will be set to k_final after a scattering event - //return 1; // return 1 is sucess, return 0 is failure, and the ray will be absorbed. - // failure should not happen, as this function will only be called when - // the cross section for the current k_initial is above zero. - + // return 1; // return 1 is sucess, return 0 is failure, and the ray will be absorbed. + // failure should not happen, as this function will only be called when + // the cross section for the current k_initial is above zero. + // There is access to the data_transfer from within the scattering function // In this case the only variable is my, but it could be read by: // double my = data_transfer.pointer_to_a_Template_physics_storage_struct->my_scattering; // One can assume that if the scattering function is running, the my fuction was // executed just before and for the same k_initial. - -}; - -// These lines help with future error correction, and tell other Union components -// that at least one process have been defined. -#ifndef PROCESS_DETECTOR - // Obsolete - //struct pointer_to_global_process_list global_process_list = {0,NULL}; - #define PROCESS_DETECTOR dummy -#endif - -#ifndef PROCESS_AF_HB_1D_DETECTOR - #define PROCESS_AF_HB_1D_DETECTOR dummy -#endif + }; + + // These lines help with future error correction, and tell other Union components + // that at least one process have been defined. + #ifndef PROCESS_DETECTOR + // Obsolete + // struct pointer_to_global_process_list global_process_list = {0,NULL}; + #define PROCESS_DETECTOR dummy + #endif + + #ifndef PROCESS_AF_HB_1D_DETECTOR + #define PROCESS_AF_HB_1D_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct AF_HB_1D_physics_storage_struct AF_HB_1D_storage; // Replace template with your own name here + // Declare for this component, to do calculations on the input / store in the transported data + struct AF_HB_1D_physics_storage_struct AF_HB_1D_storage; // Replace template with your own name here -// Variables needed in initialize of this function. -double effective_my_scattering; + // Variables needed in initialize of this function. + double effective_my_scattering; -// Needed for transport to the main component, will be the same for all processes -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Needed for transport to the main component, will be the same for all processes + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; %} INITIALIZE %{ - - if ((unit_cell_volume==0) && (number_density==0)) { - printf("ERROR in Union process AF_HB_1D named %s, set either unit_cell_volume or number_density.\n",NAME_CURRENT_COMP); - exit(1); + + if ((unit_cell_volume == 0) && (number_density == 0)) { + printf ("ERROR in Union process AF_HB_1D named %s, set either unit_cell_volume or number_density.\n", NAME_CURRENT_COMP); + exit (1); } - - if ((unit_cell_volume>0) && (number_density>0)) { - printf("ERROR in Union process AF_HB_1D named %s, only set one of unit_cell_volume or number_density.\n",NAME_CURRENT_COMP); - exit(1); + + if ((unit_cell_volume > 0) && (number_density > 0)) { + printf ("ERROR in Union process AF_HB_1D named %s, only set one of unit_cell_volume or number_density.\n", NAME_CURRENT_COMP); + exit (1); } - + if (J_interaction < 0) { - printf("ERROR in Union process AF_HB_1D named %s, exchange constant J_interaction needs to be positive (AF).\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR in Union process AF_HB_1D named %s, exchange constant J_interaction needs to be positive (AF).\n", NAME_CURRENT_COMP); + exit (1); } - - if (unit_cell_volume>0) number_density = 1/unit_cell_volume; // Unit of 1/Å^3 - + + if (unit_cell_volume > 0) + number_density = 1 / unit_cell_volume; // Unit of 1/Å^3 + // Packing factor taken into account by decreasing number density - number_density = number_density*packing_factor; - + number_density = number_density * packing_factor; + AF_HB_1D_storage.physical_constants.q2unit_less = atom_distance; - AF_HB_1D_storage.number_density_internal = number_density*1E10; // Unit conversion so n*sigma gets units of 1/m. - + AF_HB_1D_storage.number_density_internal = number_density * 1E10; // Unit conversion so n*sigma gets units of 1/m. + AF_HB_1D_storage.physical_constants.J = J_interaction; AF_HB_1D_storage.physical_constants.A = A_constant; AF_HB_1D_storage.physical_constants.Atom_dist = atom_distance; - + // prefactor 0.5 // Integral pre factors is (gyromagnetic ratio * r_0 * g)^2 // gyromagnetic ratio = -1.913 [unitless] // classical electron radius = 2.817940E-15 [m] -> Å = 2.817940E-5 [Å] // g factor for electron = 2.0023 [unitless] - - //AF_HB_1D_storage.physical_constants.integral_pre_factor = 1.832471E8*1.832471E8*2.81794E-15*2.81794E-15*2.0023*2.0023; - AF_HB_1D_storage.physical_constants.integral_pre_factor = 0.5*1.913*1.913*2.81794E-5*2.81794E-5*2.0023*2.0023; - + + // AF_HB_1D_storage.physical_constants.integral_pre_factor = 1.832471E8*1.832471E8*2.81794E-15*2.81794E-15*2.0023*2.0023; + AF_HB_1D_storage.physical_constants.integral_pre_factor = 0.5 * 1.913 * 1.913 * 2.81794E-5 * 2.81794E-5 * 2.0023 * 2.0023; + // Factor: 0.5 // Focusing area correction: done in direction choice // Energy range correction: done in code // Scattering density: 1/V0 = number_density // Constant term in diff cross section: integral_pre_factor (calculated in initialize) // 1E10 to make units of weight factor from Å to m. - - //AF_HB_1D_storage.physical_constants.weight_factor = 1E10*number_density*AF_HB_1D_storage.physical_constants.integral_pre_factor; - //AF_HB_1D_storage.physical_constants.weight_factor = AF_HB_1D_storage.physical_constants.integral_pre_factor; - - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + + // AF_HB_1D_storage.physical_constants.weight_factor = 1E10*number_density*AF_HB_1D_storage.physical_constants.integral_pre_factor; + // AF_HB_1D_storage.physical_constants.weight_factor = AF_HB_1D_storage.physical_constants.integral_pre_factor; + + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic - //This_process.non_isotropic_rot_index = -1; // Yes (powder) - This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = -1; // Yes (powder) + This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No // The type of the process must be saved in the global enum process This_process.eProcess = AF_HB_1D; @@ -333,20 +342,20 @@ INITIALIZE This_process.scattering_function = &AF_HB_1D_physics_scattering; // This will be the same for all process's, and can thus be moved to an include. - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); This_process.process_p_interact = interact_fraction; - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; - - struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list,global_process_element); + + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE %{ - // Trace should be empty, the simulation is done in Union_master + // Trace should be empty, the simulation is done in Union_master %} END diff --git a/mcstas-comps/union/IncoherentPhonon_process.comp b/mcstas-comps/union/IncoherentPhonon_process.comp index 9d73d3a482..0f3fcdd1e0 100644 --- a/mcstas-comps/union/IncoherentPhonon_process.comp +++ b/mcstas-comps/union/IncoherentPhonon_process.comp @@ -71,3597 +71,3925 @@ SETTING PARAMETERS(double T=394, double density=6.0, double M=50.94, SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this IncoherentPhonon_process component" -#endif - -#ifndef INCOHERENTPHONON -#define INCOHERENTPHONON -#define maxIter 1000 // Maximum number of iterations for sampling via the rejection method -#define KS2E 2.0721 // Energy / wave-vector^2 constant -#define kB 8.6173342e-2 // Boltzmann constant in meV/K -#define amu 1.66053892e-27 // atomic mass unit in kg -#define barn2cmsq 1.0e-24 // conversion factor from barn to cm2 -#define nFCmax 10000000 // maximum number of function calls in nunerical integration -#endif - -struct IncoherentPhonon_physics_storage_struct{ - // Variables that needs to be transfered between any of the following places: - // The initialize in this component - // The function for calculating my - // The function for calculating scattering - - // Type of computation - int nphe_exact; // number of exact phonon terms in the phonon expansion (0, 1, 2, 3) - int nphe_approx; // number of approximate (Gaussian or SP) phonon terms in the phonon expansion - int approx; // type of approximation (Gaussian: 0 or SP:1) - int mph_resum; // use multi-phonon resummation (no: 0 or yes: 1) - - // saved calculated cross sections for use in scattering - double xsTot, xs1phe, xs2phe, xs3phe, xsmph, *xs_p_phe_gauss, *xs_p_phe_sp; - - //Physical parameters - double T; // Temperature [K] - double density; // Material density [g/cm3] - double M; // Ion mass [amu] - double sigmaCoh; // Coherent cross section [barn] - double sigmaInc; // Incoherent cross section [barn] - double kBT; // Boltzmann constant times temperature [meV] - double mRat; // ratio of neutron mass to ion mass (m/M) - double XS2mu; // conversion from cross section (barn) to linear attenuation coefficient (m^-1) - - //Inelastic cross section - int nxs; // Number of kabs points at which the cross section is precomputed - double kabsmin; // Lower cut-off for neutron wave vector [1/A] - double kabsmax; // Higher cut-off for neutron wave vector [1/A] - double *kabs; // array of kabs points (of length nxs) at which the cross section is precomputed - - //Precomputed data (total cross sections) - double *xsTot_1ph; // one-phonon cross sections at the given kabs points (length nxs) - double *xsTot_2ph; // two-phonon cross sections at the given kabs points (length nxs) - double *xsTot_3ph; // three-phonon cross sections at the given kabs points (length nxs) - double **xsTot_pph_gauss; // multi-phonon cross sections at the given kabs points (length nxs), for each p - double **xsTot_pph_sp; // multi-phonon cross sections at the given kabs points (length nxs), for each p - double *xsTot_mph; // multi-phonon cross sections at the given kabs points (length nxs) - // Precomputed data (maxima of the differential cross sections, for sampling kprime) - double *dXSdx_xmax_1ph; // transfer (x) at which the cross section is maximum, at the given kabs points (length nxs) - double *dXSdx_xmax_2ph; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs) - double *dXSdx_xmax_3ph; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs) - double *dXSdx_Fmax_1ph; // maximum cross sections at the given kabs points (length nxs) - double *dXSdx_Fmax_2ph; // maximum cross sections at the given kabs points (length nxs) - double *dXSdx_Fmax_3ph; // maximum cross sections at the given kabs points (length nxs) - double **dXSdx_xmax_pph_gauss; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs), for each p - double **dXSdx_Fmax_pph_gauss; // maximum cross sections at the given kabs points (length nxs), for each p - double **dXSdx_xmax_pph_sp; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs), for each p - double **dXSdx_Fmax_pph_sp; // maximum cross sections at the given kabs points (length nxs), for each p - - int nF1; - int nF2; - int nF3; - double *u1; - double *u2; - double *u3; - double *F1; - double *F2; - double *F3; - double tolQuadratureFs; - - // phonon expansion in gaussian approximation - int nphe, npmax; - double epsilon; - double Delta, Delta2; - - // phonon expansion in saddle approximation - int ntsp_p; - double ximin_p, ximax_p; - double *xi_p; - double *tsp_p; - double *g_p; - double *d2gDg_p; - int p; // to compute differential cross sections (not for simulation) - - // multi-phonon resummation (saddle-point) - double ximin; - double ximax; - int ntsp; - double *xi; - double *tsp; - double *g; - double *d2g; - double *H; - double g0; - double d2g0; - double xi1; - double xi2; - double aH3; - double aH4; - double tolSaddlePoint; - double tolQuadratureGs; - - int np_u_mph; - double *u; - double *dXSdu_mph; - double tol_dXSdu_mph; - - double *dXSdQ2_Q2max_mph; - double *dXSdQ2_Fmax_mph; - double *Q2min; - double *Q2max; - - int np_Q2_mph; - double *Q2; - double *SQ2_mph; - - // exact time correlation function (used only for tests) - int npGs; - double *s; - double *rGs; - double *iGs; - - //Density of States - int np; // number of energy points at which the DoS is known - double *e; // array with the energy at which the DoS is known (length np) - double *Z; // array with the DoS at the energies at which it is known (length np) - double Emax; // cut-off energy for DoS (DoS vanishes above Emax) - double dosPar; // parabolic form of the DoS for E->0: DoS(E) = dosPar*E*E for E->0 - char dosfn[250]; // Path to the DoS file - - //Log file - FILE *filep; -}; - -// function declarations - -// total cross sections -void precomputations(struct IncoherentPhonon_physics_storage_struct *data); - -// double differential cross section (not used, only for test) -double dXS_dEp_dOmega(int type, double E, double Ep, double z, double *Smphon, struct IncoherentPhonon_physics_storage_struct *data); -//double dXS_dEp_dOmega(int type, double E, double Ep, double z, struct IncoherentPhonon_physics_storage_struct *data); -void compute_dXS_dEp_dOmega(struct IncoherentPhonon_physics_storage_struct *data); - -// build the final wave vector -int build_K_final(double kabs, double ct, double *ki, double *kf); - -// sampling direction in phonon expansion (same function in any approximation: approximations only deal with Fp) -double sampleDir(double x, double E, int p, struct IncoherentPhonon_physics_storage_struct *data); -double angularIntegral_p_phonon(int p, double alpha, double x); - -/////////////////////////////////////// -// exact terms in phonon expansion //// -/////////////////////////////////////// -double sampleKprime_1ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data); -double sampleKprime_2ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data); -double sampleKprime_3ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data); -int compute_dXSdx_max_1ph(int n, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax); -int compute_dXSdx_max_2ph(int n, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax); -int compute_dXSdx_max_3ph(int n, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax); -double dXSdx_1ph(double x, double E, struct IncoherentPhonon_physics_storage_struct *data); -double dXSdx_2ph(double x, double E, struct IncoherentPhonon_physics_storage_struct *data); -double dXSdx_3ph(double x, double E, struct IncoherentPhonon_physics_storage_struct *data); -double totXS_1ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data); -double totXS_2ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data); -double totXS_3ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data); -void computeFs(struct IncoherentPhonon_physics_storage_struct *data); -void computeTotalXS_exact(struct IncoherentPhonon_physics_storage_struct *data); -double F1(double u, struct IncoherentPhonon_physics_storage_struct *data); -double F2(double u, struct IncoherentPhonon_physics_storage_struct *data); -double F3(double u, struct IncoherentPhonon_physics_storage_struct *data); -double F2int(double u, double u1, struct IncoherentPhonon_physics_storage_struct *data); -double F3int(double u, double u1, double u2, struct IncoherentPhonon_physics_storage_struct *data); -double quadF2(double u, struct IncoherentPhonon_physics_storage_struct *data); -double trapezF2(double u, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct *data); -double quadF3(double u, struct IncoherentPhonon_physics_storage_struct *data); -double trapezF3(double u, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct *data); -double quadF3u2(double u, double u1, struct IncoherentPhonon_physics_storage_struct *data); -double trapezF3u2(double u, double u1, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct *data); -//////////////////////////////////////////////////// - -/////////////////////////////////// -// for exact Fps/////////////////// -double convolution(double u, int np, double *up, double *Fp, struct IncoherentPhonon_physics_storage_struct *data); -void computeFps(int pmax, struct IncoherentPhonon_physics_storage_struct *data); -////////////////////////////////// - -/////////////////////////////////////////////////////////// -// multiphonon expansion in gaussian approximation //////// -/////////////////////////////////////////////////////////// -double sampleKprime_pph_gauss(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data); -double dXSdx_pph_gauss(int p, double x, double E, struct IncoherentPhonon_physics_storage_struct *data); -double totXS_pph_gauss(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data); -void computeTotalXS_pph_gauss(struct IncoherentPhonon_physics_storage_struct *data); -int compute_dXSdx_max_pph_gauss(int n, int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax); -double Sgauss(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data); -void computeEpsilon(struct IncoherentPhonon_physics_storage_struct *data); -double epsilonInt(double u, double v, struct IncoherentPhonon_physics_storage_struct *data); -/////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////// -// multiphonon expansion in saddle approximation //////// -///////////////////////////////////////////////////////// -double sampleKprime_pph_sp(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data); -double dXSdx_pph_sp(int p, double x, double E, struct IncoherentPhonon_physics_storage_struct *data); -double totXS_pph_sp(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data); -void computeTotalXS_pph_sp(struct IncoherentPhonon_physics_storage_struct *data); -int compute_dXSdx_max_pph_sp(int n, int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax); -double Fp_sp(int p, double u, struct IncoherentPhonon_physics_storage_struct *data); -double Smp_phe(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data); -double Smp_p(double u, double Q2, int p, struct IncoherentPhonon_physics_storage_struct *data); -double Smp_p_int(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data); -void tspInterp_p(double xi, double *tsp, double *g, double *d2gDg, struct IncoherentPhonon_physics_storage_struct *data); -void computeSP_p(int ntsp, double ximin, double ximax, struct IncoherentPhonon_physics_storage_struct *data); -double saddlePoint_p(double xi, struct IncoherentPhonon_physics_storage_struct *data); -double integral_Smp_phe(double Q2, double tol, struct IncoherentPhonon_physics_storage_struct *data); -////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////// -// multi-phonon resumation saddle-point /////////// -//////////////////////////////////////////////////// -void sample_Kprime_and_Dir_mph(double kabs, double *x, double *z, struct IncoherentPhonon_physics_storage_struct *data); -double sample_u_mph(double umax, struct IncoherentPhonon_physics_storage_struct *data); -double sample_Q2_mph(double u, double Erat, struct IncoherentPhonon_physics_storage_struct *data); -double totXS_mph(double kabs, struct IncoherentPhonon_physics_storage_struct *data); -void compute_dXSdu_mph(struct IncoherentPhonon_physics_storage_struct *data); -double quad_dXSdu_mph(double u, struct IncoherentPhonon_physics_storage_struct *data); -double trapez_dXSdu_mph(double u, int n, double Q2max, struct IncoherentPhonon_physics_storage_struct *data); -double dXSdxdz_mph(double kabs, double x, double z, struct IncoherentPhonon_physics_storage_struct *data); -double dXSdx_mph(double kabs, double x, struct IncoherentPhonon_physics_storage_struct *data); -double dXSdz_mph(double kabs, double z, struct IncoherentPhonon_physics_storage_struct *data); -double SFunc(double xi, double Q2, struct IncoherentPhonon_physics_storage_struct *data); -double SFuncInterp(double xi, double Q2, struct IncoherentPhonon_physics_storage_struct *data); -void computeSaddlePointSol(int ntsp, double ximin, double ximax, struct IncoherentPhonon_physics_storage_struct *data); -void tspInterp(double xi, double *tsp, double *g, double *d2g, double *H, struct IncoherentPhonon_physics_storage_struct *data); -double saddlePoint(double xi, struct IncoherentPhonon_physics_storage_struct *data); -double Gt(double ti, struct IncoherentPhonon_physics_storage_struct *data); -double dGt(double ti, struct IncoherentPhonon_physics_storage_struct *data); -double d2Gt(double ti, struct IncoherentPhonon_physics_storage_struct *data); -double Gtint(double u, double ti, struct IncoherentPhonon_physics_storage_struct *data); -double dGtint(double u, double ti, struct IncoherentPhonon_physics_storage_struct *data); -double d2Gtint(double u, double ti, struct IncoherentPhonon_physics_storage_struct *data); -double quad_mp(double ti, struct IncoherentPhonon_physics_storage_struct *data, - double (*func)(double,double,struct IncoherentPhonon_physics_storage_struct *)); -double trapez_mp(int n, double umin, double umax, double ti, - struct IncoherentPhonon_physics_storage_struct *data, - double (*func)(double,double,struct IncoherentPhonon_physics_storage_struct *)); -void compute_dXSdQ2_max_mph(struct IncoherentPhonon_physics_storage_struct *data); -void compute_SQ2_mph(struct IncoherentPhonon_physics_storage_struct *data); -void compute_dXSdu_dXSdQ2_max_mph(struct IncoherentPhonon_physics_storage_struct *data); -void computeTotalXS_mph_resum(struct IncoherentPhonon_physics_storage_struct *data); -///////////////////////////////////////////////////// - -////////////////////////////////////// -// exact correlation function S ////// -////////////////////////////////////// -double exactS(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data); -void getExactS(double Q2, double nu1, double nu2, struct IncoherentPhonon_physics_storage_struct *data); - -void computeGs(double s, double *rGs, double *iGs, struct IncoherentPhonon_physics_storage_struct *data); -double realGsInt(double u, double s, struct IncoherentPhonon_physics_storage_struct *data); -double imagGsInt(double u, double s, struct IncoherentPhonon_physics_storage_struct *data); -/////////////////////////////////////// - -///////////////////////// -// general functions //// -///////////////////////// -double Gu(double u, struct IncoherentPhonon_physics_storage_struct *data); -double bose(double x); -double interpFunc(double u, int n, double *up, double *Fp); -double quadFunc(double x1, double x2, double v, double tol, struct IncoherentPhonon_physics_storage_struct *data, - double (*func)(double,double,struct IncoherentPhonon_physics_storage_struct *)); -double trapezFunc(int n, double umin, double umax, double v, struct IncoherentPhonon_physics_storage_struct *data, - double (*func)(double,double,struct IncoherentPhonon_physics_storage_struct *)); -///////////////////////// - -///////////////////////// -// input/output etc. //// -///////////////////////// -void readDoS(struct IncoherentPhonon_physics_storage_struct *data); -double dos(double E, struct IncoherentPhonon_physics_storage_struct *data); -///////////////////////// - -void setParams(struct IncoherentPhonon_physics_storage_struct *data, - int nphe_exact, int nphe_approx, int approx, int mph_resum, - double T, double density, double M, - double sigmaCoh, double sigmaInc, - double kabsmin, double kabsmax, int nxs, - char *dosfn, int ntsp, double ximin, double ximax, char *filelog); - -int finish(struct IncoherentPhonon_physics_storage_struct *data); - -// end function declaration - -/*******************************************************************/ - -// Function for calculating my in Incoherent phonon case -int IncoherentPhonon_physics_my(double *my, double *k_initial, - union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) -{ - struct IncoherentPhonon_physics_storage_struct *data = - data_transfer.pointer_to_a_IncoherentPhonon_physics_storage_struct; - - double kabs = sqrt(k_initial[0]*k_initial[0] + k_initial[1]*k_initial[1] + k_initial[2]*k_initial[2]); - int p; - - // exact terms in phonon expansion (at least the single phonon term) - data->xs1phe = interpFunc(kabs,data->nxs,data->kabs,data->xsTot_1ph); - data->xsTot = data->xs1phe; - if(data->nphe_exact>1) { - data->xs2phe = interpFunc(kabs,data->nxs,data->kabs,data->xsTot_2ph); - data->xsTot += data->xs2phe; - } - if(data->nphe_exact>2) { - data->xs3phe = interpFunc(kabs,data->nxs,data->kabs,data->xsTot_3ph); - data->xsTot += data->xs2phe; - } - - // approximate terms in phonon expansion (none if approx==0) - if(data->approx==1) { - // gaussian approximation - for(p=data->nphe_exact+1;p<=data->nphe_approx;p++) { - data->xs_p_phe_gauss[p] = interpFunc(kabs,data->nxs,data->kabs,data->xsTot_pph_gauss[p]); - data->xsTot += data->xs_p_phe_gauss[p]; - } - } else if(data->approx==2) { - // saddle point approximation - for(p=data->nphe_exact+1;p<=data->nphe_approx;p++) { - data->xs_p_phe_sp[p] = interpFunc(kabs,data->nxs,data->kabs,data->xsTot_pph_sp[p]); - data->xsTot += data->xs_p_phe_sp[p]; + #ifndef Union + #error "The Union_init component must be included before this IncoherentPhonon_process component" + #endif + + #ifndef INCOHERENTPHONON + #define INCOHERENTPHONON + #define maxIter 1000 // Maximum number of iterations for sampling via the rejection method + #define KS2E 2.0721 // Energy / wave-vector^2 constant + #define kB 8.6173342e-2 // Boltzmann constant in meV/K + #define amu 1.66053892e-27 // atomic mass unit in kg + #define barn2cmsq 1.0e-24 // conversion factor from barn to cm2 + #define nFCmax 10000000 // maximum number of function calls in nunerical integration + #endif + + struct IncoherentPhonon_physics_storage_struct { + // Variables that needs to be transfered between any of the following places: + // The initialize in this component + // The function for calculating my + // The function for calculating scattering + + // Type of computation + int nphe_exact; // number of exact phonon terms in the phonon expansion (0, 1, 2, 3) + int nphe_approx; // number of approximate (Gaussian or SP) phonon terms in the phonon expansion + int approx; // type of approximation (Gaussian: 0 or SP:1) + int mph_resum; // use multi-phonon resummation (no: 0 or yes: 1) + + // saved calculated cross sections for use in scattering + double xsTot, xs1phe, xs2phe, xs3phe, xsmph, *xs_p_phe_gauss, *xs_p_phe_sp; + + // Physical parameters + double T; // Temperature [K] + double density; // Material density [g/cm3] + double M; // Ion mass [amu] + double sigmaCoh; // Coherent cross section [barn] + double sigmaInc; // Incoherent cross section [barn] + double kBT; // Boltzmann constant times temperature [meV] + double mRat; // ratio of neutron mass to ion mass (m/M) + double XS2mu; // conversion from cross section (barn) to linear attenuation coefficient (m^-1) + + // Inelastic cross section + int nxs; // Number of kabs points at which the cross section is precomputed + double kabsmin; // Lower cut-off for neutron wave vector [1/A] + double kabsmax; // Higher cut-off for neutron wave vector [1/A] + double* kabs; // array of kabs points (of length nxs) at which the cross section is precomputed + + // Precomputed data (total cross sections) + double* xsTot_1ph; // one-phonon cross sections at the given kabs points (length nxs) + double* xsTot_2ph; // two-phonon cross sections at the given kabs points (length nxs) + double* xsTot_3ph; // three-phonon cross sections at the given kabs points (length nxs) + double** xsTot_pph_gauss; // multi-phonon cross sections at the given kabs points (length nxs), for each p + double** xsTot_pph_sp; // multi-phonon cross sections at the given kabs points (length nxs), for each p + double* xsTot_mph; // multi-phonon cross sections at the given kabs points (length nxs) + // Precomputed data (maxima of the differential cross sections, for sampling kprime) + double* dXSdx_xmax_1ph; // transfer (x) at which the cross section is maximum, at the given kabs points (length nxs) + double* dXSdx_xmax_2ph; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs) + double* dXSdx_xmax_3ph; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs) + double* dXSdx_Fmax_1ph; // maximum cross sections at the given kabs points (length nxs) + double* dXSdx_Fmax_2ph; // maximum cross sections at the given kabs points (length nxs) + double* dXSdx_Fmax_3ph; // maximum cross sections at the given kabs points (length nxs) + double** dXSdx_xmax_pph_gauss; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs), for each p + double** dXSdx_Fmax_pph_gauss; // maximum cross sections at the given kabs points (length nxs), for each p + double** dXSdx_xmax_pph_sp; // energy transfer (x) at which the cross section is maximum, at the given kabs points (length nxs), for each p + double** dXSdx_Fmax_pph_sp; // maximum cross sections at the given kabs points (length nxs), for each p + + int nF1; + int nF2; + int nF3; + double* u1; + double* u2; + double* u3; + double* F1; + double* F2; + double* F3; + double tolQuadratureFs; + + // phonon expansion in gaussian approximation + int nphe, npmax; + double epsilon; + double Delta, Delta2; + + // phonon expansion in saddle approximation + int ntsp_p; + double ximin_p, ximax_p; + double* xi_p; + double* tsp_p; + double* g_p; + double* d2gDg_p; + int p; // to compute differential cross sections (not for simulation) + + // multi-phonon resummation (saddle-point) + double ximin; + double ximax; + int ntsp; + double* xi; + double* tsp; + double* g; + double* d2g; + double* H; + double g0; + double d2g0; + double xi1; + double xi2; + double aH3; + double aH4; + double tolSaddlePoint; + double tolQuadratureGs; + + int np_u_mph; + double* u; + double* dXSdu_mph; + double tol_dXSdu_mph; + + double* dXSdQ2_Q2max_mph; + double* dXSdQ2_Fmax_mph; + double* Q2min; + double* Q2max; + + int np_Q2_mph; + double* Q2; + double* SQ2_mph; + + // exact time correlation function (used only for tests) + int npGs; + double* s; + double* rGs; + double* iGs; + + // Density of States + int np; // number of energy points at which the DoS is known + double* e; // array with the energy at which the DoS is known (length np) + double* Z; // array with the DoS at the energies at which it is known (length np) + double Emax; // cut-off energy for DoS (DoS vanishes above Emax) + double dosPar; // parabolic form of the DoS for E->0: DoS(E) = dosPar*E*E for E->0 + char dosfn[250]; // Path to the DoS file + + // Log file + FILE* filep; + }; + + // function declarations + + // total cross sections + void precomputations (struct IncoherentPhonon_physics_storage_struct* data); + + // double differential cross section (not used, only for test) + double dXS_dEp_dOmega (int type, double E, double Ep, double z, double* Smphon, struct IncoherentPhonon_physics_storage_struct* data); + // double dXS_dEp_dOmega(int type, double E, double Ep, double z, struct IncoherentPhonon_physics_storage_struct *data); + void compute_dXS_dEp_dOmega (struct IncoherentPhonon_physics_storage_struct* data); + + // build the final wave vector + int build_K_final (double kabs, double ct, double* ki, double* kf); + + // sampling direction in phonon expansion (same function in any approximation: approximations only deal with Fp) + double sampleDir (double x, double E, int p, struct IncoherentPhonon_physics_storage_struct* data); + double angularIntegral_p_phonon (int p, double alpha, double x); + + /////////////////////////////////////// + // exact terms in phonon expansion //// + /////////////////////////////////////// + double sampleKprime_1ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data); + double sampleKprime_2ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data); + double sampleKprime_3ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data); + int compute_dXSdx_max_1ph (int n, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax); + int compute_dXSdx_max_2ph (int n, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax); + int compute_dXSdx_max_3ph (int n, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax); + double dXSdx_1ph (double x, double E, struct IncoherentPhonon_physics_storage_struct* data); + double dXSdx_2ph (double x, double E, struct IncoherentPhonon_physics_storage_struct* data); + double dXSdx_3ph (double x, double E, struct IncoherentPhonon_physics_storage_struct* data); + double totXS_1ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data); + double totXS_2ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data); + double totXS_3ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data); + void computeFs (struct IncoherentPhonon_physics_storage_struct* data); + void computeTotalXS_exact (struct IncoherentPhonon_physics_storage_struct* data); + double F1 (double u, struct IncoherentPhonon_physics_storage_struct* data); + double F2 (double u, struct IncoherentPhonon_physics_storage_struct* data); + double F3 (double u, struct IncoherentPhonon_physics_storage_struct* data); + double F2int (double u, double u1, struct IncoherentPhonon_physics_storage_struct* data); + double F3int (double u, double u1, double u2, struct IncoherentPhonon_physics_storage_struct* data); + double quadF2 (double u, struct IncoherentPhonon_physics_storage_struct* data); + double trapezF2 (double u, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct* data); + double quadF3 (double u, struct IncoherentPhonon_physics_storage_struct* data); + double trapezF3 (double u, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct* data); + double quadF3u2 (double u, double u1, struct IncoherentPhonon_physics_storage_struct* data); + double trapezF3u2 (double u, double u1, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct* data); + //////////////////////////////////////////////////// + + /////////////////////////////////// + // for exact Fps/////////////////// + double convolution (double u, int np, double* up, double* Fp, struct IncoherentPhonon_physics_storage_struct* data); + void computeFps (int pmax, struct IncoherentPhonon_physics_storage_struct* data); + ////////////////////////////////// + + /////////////////////////////////////////////////////////// + // multiphonon expansion in gaussian approximation //////// + /////////////////////////////////////////////////////////// + double sampleKprime_pph_gauss (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data); + double dXSdx_pph_gauss (int p, double x, double E, struct IncoherentPhonon_physics_storage_struct* data); + double totXS_pph_gauss (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data); + void computeTotalXS_pph_gauss (struct IncoherentPhonon_physics_storage_struct* data); + int compute_dXSdx_max_pph_gauss (int n, int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax); + double Sgauss (double u, double Q2, struct IncoherentPhonon_physics_storage_struct* data); + void computeEpsilon (struct IncoherentPhonon_physics_storage_struct* data); + double epsilonInt (double u, double v, struct IncoherentPhonon_physics_storage_struct* data); + /////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////// + // multiphonon expansion in saddle approximation //////// + ///////////////////////////////////////////////////////// + double sampleKprime_pph_sp (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data); + double dXSdx_pph_sp (int p, double x, double E, struct IncoherentPhonon_physics_storage_struct* data); + double totXS_pph_sp (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data); + void computeTotalXS_pph_sp (struct IncoherentPhonon_physics_storage_struct* data); + int compute_dXSdx_max_pph_sp (int n, int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax); + double Fp_sp (int p, double u, struct IncoherentPhonon_physics_storage_struct* data); + double Smp_phe (double u, double Q2, struct IncoherentPhonon_physics_storage_struct* data); + double Smp_p (double u, double Q2, int p, struct IncoherentPhonon_physics_storage_struct* data); + double Smp_p_int (double u, double Q2, struct IncoherentPhonon_physics_storage_struct* data); + void tspInterp_p (double xi, double* tsp, double* g, double* d2gDg, struct IncoherentPhonon_physics_storage_struct* data); + void computeSP_p (int ntsp, double ximin, double ximax, struct IncoherentPhonon_physics_storage_struct* data); + double saddlePoint_p (double xi, struct IncoherentPhonon_physics_storage_struct* data); + double integral_Smp_phe (double Q2, double tol, struct IncoherentPhonon_physics_storage_struct* data); + ////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////// + // multi-phonon resumation saddle-point /////////// + //////////////////////////////////////////////////// + void sample_Kprime_and_Dir_mph (double kabs, double* x, double* z, struct IncoherentPhonon_physics_storage_struct* data); + double sample_u_mph (double umax, struct IncoherentPhonon_physics_storage_struct* data); + double sample_Q2_mph (double u, double Erat, struct IncoherentPhonon_physics_storage_struct* data); + double totXS_mph (double kabs, struct IncoherentPhonon_physics_storage_struct* data); + void compute_dXSdu_mph (struct IncoherentPhonon_physics_storage_struct* data); + double quad_dXSdu_mph (double u, struct IncoherentPhonon_physics_storage_struct* data); + double trapez_dXSdu_mph (double u, int n, double Q2max, struct IncoherentPhonon_physics_storage_struct* data); + double dXSdxdz_mph (double kabs, double x, double z, struct IncoherentPhonon_physics_storage_struct* data); + double dXSdx_mph (double kabs, double x, struct IncoherentPhonon_physics_storage_struct* data); + double dXSdz_mph (double kabs, double z, struct IncoherentPhonon_physics_storage_struct* data); + double SFunc (double xi, double Q2, struct IncoherentPhonon_physics_storage_struct* data); + double SFuncInterp (double xi, double Q2, struct IncoherentPhonon_physics_storage_struct* data); + void computeSaddlePointSol (int ntsp, double ximin, double ximax, struct IncoherentPhonon_physics_storage_struct* data); + void tspInterp (double xi, double* tsp, double* g, double* d2g, double* H, struct IncoherentPhonon_physics_storage_struct* data); + double saddlePoint (double xi, struct IncoherentPhonon_physics_storage_struct* data); + double Gt (double ti, struct IncoherentPhonon_physics_storage_struct* data); + double dGt (double ti, struct IncoherentPhonon_physics_storage_struct* data); + double d2Gt (double ti, struct IncoherentPhonon_physics_storage_struct* data); + double Gtint (double u, double ti, struct IncoherentPhonon_physics_storage_struct* data); + double dGtint (double u, double ti, struct IncoherentPhonon_physics_storage_struct* data); + double d2Gtint (double u, double ti, struct IncoherentPhonon_physics_storage_struct* data); + double quad_mp (double ti, struct IncoherentPhonon_physics_storage_struct* data, + double (*func) (double, double, struct IncoherentPhonon_physics_storage_struct*)); + double trapez_mp (int n, double umin, double umax, double ti, struct IncoherentPhonon_physics_storage_struct* data, + double (*func) (double, double, struct IncoherentPhonon_physics_storage_struct*)); + void compute_dXSdQ2_max_mph (struct IncoherentPhonon_physics_storage_struct* data); + void compute_SQ2_mph (struct IncoherentPhonon_physics_storage_struct* data); + void compute_dXSdu_dXSdQ2_max_mph (struct IncoherentPhonon_physics_storage_struct* data); + void computeTotalXS_mph_resum (struct IncoherentPhonon_physics_storage_struct* data); + ///////////////////////////////////////////////////// + + ////////////////////////////////////// + // exact correlation function S ////// + ////////////////////////////////////// + double exactS (double u, double Q2, struct IncoherentPhonon_physics_storage_struct* data); + void getExactS (double Q2, double nu1, double nu2, struct IncoherentPhonon_physics_storage_struct* data); + + void computeGs (double s, double* rGs, double* iGs, struct IncoherentPhonon_physics_storage_struct* data); + double realGsInt (double u, double s, struct IncoherentPhonon_physics_storage_struct* data); + double imagGsInt (double u, double s, struct IncoherentPhonon_physics_storage_struct* data); + /////////////////////////////////////// + + ///////////////////////// + // general functions //// + ///////////////////////// + double Gu (double u, struct IncoherentPhonon_physics_storage_struct* data); + double bose (double x); + double interpFunc (double u, int n, double* up, double* Fp); + double quadFunc (double x1, double x2, double v, double tol, struct IncoherentPhonon_physics_storage_struct* data, + double (*func) (double, double, struct IncoherentPhonon_physics_storage_struct*)); + double trapezFunc (int n, double umin, double umax, double v, struct IncoherentPhonon_physics_storage_struct* data, + double (*func) (double, double, struct IncoherentPhonon_physics_storage_struct*)); + ///////////////////////// + + ///////////////////////// + // input/output etc. //// + ///////////////////////// + void readDoS (struct IncoherentPhonon_physics_storage_struct* data); + double dos (double E, struct IncoherentPhonon_physics_storage_struct* data); + ///////////////////////// + + void setParams (struct IncoherentPhonon_physics_storage_struct* data, int nphe_exact, int nphe_approx, int approx, int mph_resum, double T, double density, + double M, double sigmaCoh, double sigmaInc, double kabsmin, double kabsmax, int nxs, char* dosfn, int ntsp, double ximin, double ximax, + char* filelog); + + int finish (struct IncoherentPhonon_physics_storage_struct* data); + + // end function declaration + + /*******************************************************************/ + + // Function for calculating my in Incoherent phonon case + int + IncoherentPhonon_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { + struct IncoherentPhonon_physics_storage_struct* data = data_transfer.pointer_to_a_IncoherentPhonon_physics_storage_struct; + + double kabs = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); + int p; + + // exact terms in phonon expansion (at least the single phonon term) + data->xs1phe = interpFunc (kabs, data->nxs, data->kabs, data->xsTot_1ph); + data->xsTot = data->xs1phe; + if (data->nphe_exact > 1) { + data->xs2phe = interpFunc (kabs, data->nxs, data->kabs, data->xsTot_2ph); + data->xsTot += data->xs2phe; + } + if (data->nphe_exact > 2) { + data->xs3phe = interpFunc (kabs, data->nxs, data->kabs, data->xsTot_3ph); + data->xsTot += data->xs2phe; } - } - // multi-phonon resummation (saddle-point) - if(data->mph_resum==1) { - data->xsmph = interpFunc(kabs,data->nxs,data->kabs,data->xsTot_mph); - data->xsTot += data->xsmph; - } + // approximate terms in phonon expansion (none if approx==0) + if (data->approx == 1) { + // gaussian approximation + for (p = data->nphe_exact + 1; p <= data->nphe_approx; p++) { + data->xs_p_phe_gauss[p] = interpFunc (kabs, data->nxs, data->kabs, data->xsTot_pph_gauss[p]); + data->xsTot += data->xs_p_phe_gauss[p]; + } + } else if (data->approx == 2) { + // saddle point approximation + for (p = data->nphe_exact + 1; p <= data->nphe_approx; p++) { + data->xs_p_phe_sp[p] = interpFunc (kabs, data->nxs, data->kabs, data->xsTot_pph_sp[p]); + data->xsTot += data->xs_p_phe_sp[p]; + } + } + + // multi-phonon resummation (saddle-point) + if (data->mph_resum == 1) { + data->xsmph = interpFunc (kabs, data->nxs, data->kabs, data->xsTot_mph); + data->xsTot += data->xsmph; + } + + *my = (data->XS2mu) * data->xsTot; - *my = (data->XS2mu)*data->xsTot; - - return 1; -}; - -// Function for incoherent phonon scattering event -int IncoherentPhonon_physics_scattering(double *k_final, double *k_initial, double *weight, - union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) -{ - int p, type; - double kabs, E, x, ct, rnd, accum, xstot, ki[3]; - - struct IncoherentPhonon_physics_storage_struct *data = - data_transfer.pointer_to_a_IncoherentPhonon_physics_storage_struct; - - ki[0] = k_initial[0]; - ki[1] = k_initial[1]; - ki[2] = k_initial[2]; - - kabs = sqrt(ki[0]*ki[0]+ki[1]*ki[1]+ki[2]*ki[2]); - E = KS2E*kabs*kabs; - - // there should be an extrapolation of the cross section from - // kabs=kabsmin down to kabs=0 and from kabs=kabsmax to infinity - // master component will care to ABSORB the neutron - if(kabskabsmin || kabs>data->kabsmax) { return 0; } - - // sample scattering type - xstot = data->xsTot; - - rnd = rand01(); - - // one phonon - accum = (data->xs1phe)/xstot; - if(rndfilep, - "sampleKprime_1ph returns negative: %f It seems maxIter=%d exceeded. Exiting\n",x,maxIter); - exit(1); - } - // Sample polar direction - ct = sampleDir(x,E,1,data); - if(ct<-1) { - fprintf(data->filep,"sampleDir 1ph returns < -1: %f It seems maxIter exceeded. Exiting\n",ct); - exit(1); - } - // x = kprime/k, with normalized kprime - build_K_final(x*kabs,ct,ki,k_final); - *weight = 1.0; return 1; - } + }; - if(data->nphe_exact>1) { - // two phonon exact - accum += (data->xs2phe)/xstot; - if(rndfilep, - "sampleKprime_2ph returns negative: %f It seems maxIter=%d exceeded. Exiting\n",x,maxIter); - exit(1); - } - // Sample polar direction - ct = sampleDir(x,E,2,data); - if(ct<-1) { - fprintf(data->filep,"sampleDir 2ph returns < -1: %f It seems maxIter exceeded. Exiting\n",ct); - exit(1); - } - // x = kprime/k, with normalized kprime - build_K_final(x*kabs,ct,ki,k_final); - *weight = 1.0; - return 1; - } - } + // Function for incoherent phonon scattering event + int + IncoherentPhonon_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, + struct focus_data_struct* focus_data, _class_particle* _particle) { + int p, type; + double kabs, E, x, ct, rnd, accum, xstot, ki[3]; + + struct IncoherentPhonon_physics_storage_struct* data = data_transfer.pointer_to_a_IncoherentPhonon_physics_storage_struct; + + ki[0] = k_initial[0]; + ki[1] = k_initial[1]; + ki[2] = k_initial[2]; + + kabs = sqrt (ki[0] * ki[0] + ki[1] * ki[1] + ki[2] * ki[2]); + E = KS2E * kabs * kabs; + + // there should be an extrapolation of the cross section from + // kabs=kabsmin down to kabs=0 and from kabs=kabsmax to infinity + // master component will care to ABSORB the neutron + if (kabs < data->kabsmin || kabs > data->kabsmax) { + return 0; + } - if(data->nphe_exact>2) { - // three phonon exact - accum += (data->xs3phe)/xstot; - if(rndfilep, - "sampleKprime_3ph returns negative: %f It seems maxIter=%d exceeded. Exiting\n",x,maxIter); - exit(1); + // sample scattering type + xstot = data->xsTot; + + rnd = rand01 (); + + // one phonon + accum = (data->xs1phe) / xstot; + if (rnd < accum) { + // Sample energy + type = 1; + x = sampleKprime_1ph (kabs, data); + if (x < 0) { + fprintf (data->filep, "sampleKprime_1ph returns negative: %f It seems maxIter=%d exceeded. Exiting\n", x, maxIter); + exit (1); } // Sample polar direction - ct = sampleDir(x,E,3,data); - if(ct<-1) { - fprintf(data->filep,"sampleDir 3ph returns < -1: %f It seems maxIter exceeded. Exiting\n",ct); - exit(1); + ct = sampleDir (x, E, 1, data); + if (ct < -1) { + fprintf (data->filep, "sampleDir 1ph returns < -1: %f It seems maxIter exceeded. Exiting\n", ct); + exit (1); } // x = kprime/k, with normalized kprime - build_K_final(x*kabs,ct,ki,k_final); + build_K_final (x * kabs, ct, ki, k_final); *weight = 1.0; return 1; } - } - if(data->approx==1) { - // p-phonon term gaussian approx - for(p=data->nphe_exact+1;p<=data->nphe_approx;p++) { - accum += (data->xs_p_phe_gauss)[p]/xstot; - if(rndfilep, - "sampleKprime_pph_gauss returns negative: %f It seems maxIter=%d exceeded. Exiting\n",x,maxIter); - exit(1); + if (data->nphe_exact > 1) { + // two phonon exact + accum += (data->xs2phe) / xstot; + if (rnd < accum) { + // Sample energy + type = 2; + x = sampleKprime_2ph (kabs, data); + if (x < 0) { + fprintf (data->filep, "sampleKprime_2ph returns negative: %f It seems maxIter=%d exceeded. Exiting\n", x, maxIter); + exit (1); } // Sample polar direction - ct = sampleDir(x,E,p,data); - if(ct<-1) { - fprintf(data->filep,"sampleDir p-ph gaussian returns < -1: %f It seems maxIter exceeded. Exiting\n",ct); - exit(1); + ct = sampleDir (x, E, 2, data); + if (ct < -1) { + fprintf (data->filep, "sampleDir 2ph returns < -1: %f It seems maxIter exceeded. Exiting\n", ct); + exit (1); } // x = kprime/k, with normalized kprime - build_K_final(x*kabs,ct,ki,k_final); + build_K_final (x * kabs, ct, ki, k_final); *weight = 1.0; return 1; - } - } - } else if (data->approx==2) { - // p-phonon term saddle point approx - for(p=data->nphe_exact+1;p<=data->nphe_approx;p++) { - accum += (data->xs_p_phe_sp)[p]/xstot; - if(rndfilep, - "sampleKprime_pph_sp returns negative: %f It seems maxIter=%d exceeded. Exiting\n",x,maxIter); - exit(1); + } + } + + if (data->nphe_exact > 2) { + // three phonon exact + accum += (data->xs3phe) / xstot; + if (rnd < accum) { + // Sample energy + type = 3; + x = sampleKprime_3ph (kabs, data); + if (x < 0) { + fprintf (data->filep, "sampleKprime_3ph returns negative: %f It seems maxIter=%d exceeded. Exiting\n", x, maxIter); + exit (1); } // Sample polar direction - ct = sampleDir(x,E,p,data); - if(ct<-1) { - fprintf(data->filep,"sampleDir p-ph saddle point returns < -1: %f It seems maxIter exceeded. Exiting\n",ct); - exit(1); + ct = sampleDir (x, E, 3, data); + if (ct < -1) { + fprintf (data->filep, "sampleDir 3ph returns < -1: %f It seems maxIter exceeded. Exiting\n", ct); + exit (1); } // x = kprime/k, with normalized kprime - build_K_final(x*kabs,ct,ki,k_final); + build_K_final (x * kabs, ct, ki, k_final); *weight = 1.0; return 1; } } - } - if (data->mph_resum==1) { - //multi-phonon resummation - accum += (data->xsmph)/xstot; - if(rndapprox == 1) { + // p-phonon term gaussian approx + for (p = data->nphe_exact + 1; p <= data->nphe_approx; p++) { + accum += (data->xs_p_phe_gauss)[p] / xstot; + if (rnd < accum) { + // Sample energy + type = p; + x = sampleKprime_pph_gauss (p, kabs, data); + if (x < 0) { + fprintf (data->filep, "sampleKprime_pph_gauss returns negative: %f It seems maxIter=%d exceeded. Exiting\n", x, maxIter); + exit (1); + } + // Sample polar direction + ct = sampleDir (x, E, p, data); + if (ct < -1) { + fprintf (data->filep, "sampleDir p-ph gaussian returns < -1: %f It seems maxIter exceeded. Exiting\n", ct); + exit (1); + } + // x = kprime/k, with normalized kprime + build_K_final (x * kabs, ct, ki, k_final); + *weight = 1.0; + return 1; + } + } + } else if (data->approx == 2) { + // p-phonon term saddle point approx + for (p = data->nphe_exact + 1; p <= data->nphe_approx; p++) { + accum += (data->xs_p_phe_sp)[p] / xstot; + if (rnd < accum) { + // Sample energy + type = p; + x = sampleKprime_pph_sp (p, kabs, data); + if (x < 0) { + fprintf (data->filep, "sampleKprime_pph_sp returns negative: %f It seems maxIter=%d exceeded. Exiting\n", x, maxIter); + exit (1); + } + // Sample polar direction + ct = sampleDir (x, E, p, data); + if (ct < -1) { + fprintf (data->filep, "sampleDir p-ph saddle point returns < -1: %f It seems maxIter exceeded. Exiting\n", ct); + exit (1); + } + // x = kprime/k, with normalized kprime + build_K_final (x * kabs, ct, ki, k_final); + *weight = 1.0; + return 1; + } + } } - } - // Should not be here - printf("IncoherentPhonon_physics_scattering: no scattering happnes !!\n"); - printf("rnd: %f accum: %f\n",rnd,accum); - printf("cross sections\n"); - printf("Total: %.6e\n",data->xsTot); - printf("1ph: %.6e\n",data->xs1phe); - if(data->nphe_exact>1) { printf("2ph: %.6e\n",data->xs2phe); } - if(data->nphe_exact>2) { printf("3ph: %.6e\n",data->xs3phe); } - if(data->approx==1) { - for(p=data->nphe_exact+1;p<=data->nphe_approx;p++) { - printf("%dph: %.6e\n",p,data->xs_p_phe_gauss[p]); - } - } else if(data->approx==2) { - for(p=data->nphe_exact+1;p<=data->nphe_approx;p++) { - printf("%dph: %.6e\n",p,data->xs_p_phe_sp[p]); + if (data->mph_resum == 1) { + // multi-phonon resummation + accum += (data->xsmph) / xstot; + if (rnd < accum) { + type = 0; + // Sample energy and polar direction + sample_Kprime_and_Dir_mph (kabs, &x, &ct, data); + // x = kprime/k, with normalized kprime + build_K_final (x * kabs, ct, ki, k_final); + *weight = 1.0; + return 1; + } } - } - if (data->mph_resum) { - printf("mph: %.6e\n",data->xsmph); - } - printf("Exiting ...\n"); - fflush(stdout); - exit(1); -}; - -int build_K_final(double kabs, double ct, double *ki, double *kf) -{ - double t1[3], t2[3]; - double st = sqrt(1.-ct*ct); - - // sample azimuthal direction - double phi = 2.*PI*rand01(); - double cp = cos(phi); - double sp = sin(phi); - - // build kprime (ki,t1,t2) orthonormal right handed triad - NORM(ki[0],ki[1],ki[2]); - normal_vec(&t1[0],&t1[1],&t1[2],ki[0],ki[1],ki[2]); - vec_prod(t2[0],t2[1],t2[2],ki[0],ki[1],ki[2],t1[0],t1[1],t1[2]); - - kf[0] = ct*ki[0] + st*(cp*t1[0] + sp*t2[0]); - kf[1] = ct*ki[1] + st*(cp*t1[1] + sp*t2[1]); - kf[2] = ct*ki[2] + st*(cp*t1[2] + sp*t2[2]); - - kf[0] = kabs*kf[0]; - kf[1] = kabs*kf[1]; - kf[2] = kabs*kf[2]; - - return 0; -}; - -// Start implementation of internal functions - -void precomputations(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, p, pmax; - double h = 4.13567; // planck constant in meV*ps - double dkabs, Q2, g0; - double xi, dxi, fac1, fac2, yp; - FILE *filep; - - fprintf(data->filep,"precomputations: start\n"); - fflush(data->filep); - - g0 = data->g0; - - /* - // computes and writes in file the exact Fp functions. Only for tests - pmax = 20; - computeFps(pmax,data); - fprintf(data->filep,"precomputations: Fps done\n"); - fflush(data->filep); - //exit(1); - */ - - // precompute exact phonon terms - computeFs(data); - fprintf(data->filep,"precomputations: FS done\n"); - fflush(data->filep); - computeTotalXS_exact(data); - fprintf(data->filep,"precomputations: exact total XS done\n"); - fflush(data->filep); - - // NULL pointers - data->xsTot_pph_gauss = NULL; - data->dXSdx_xmax_pph_gauss = NULL; - data->dXSdx_Fmax_pph_gauss = NULL; - data->xsTot_pph_sp = NULL; - data->dXSdx_xmax_pph_sp = NULL; - data->dXSdx_Fmax_pph_sp = NULL; - - if(data->approx==1) { - // precompute gaussian data - fprintf(data->filep,"precomputations: gaussian p-phonon done\n"); - fflush(data->filep); - computeTotalXS_pph_gauss(data); - fprintf(data->filep,"precomputations: total XS p-phonon gaussian done\n"); - fflush(data->filep); - } else if(data->approx==2) { - computeSP_p(data->ntsp_p,data->ximin_p,data->ximax_p,data); - fprintf(data->filep,"precomputations: SP p-phonon done\n"); - fflush(data->filep); - computeTotalXS_pph_sp(data); - fprintf(data->filep,"precomputations: total XS p-phonon SP done\n"); - fflush(data->filep); - } - if(data->mph_resum==1) { - computeSaddlePointSol(data->ntsp,data->ximin,data->ximax,data); - fprintf(data->filep,"precomputations: computeSaddlePointSol done\n"); - fflush(data->filep); - compute_SQ2_mph(data); - fprintf(data->filep,"precomputations: compute_SQ2_mph done\n"); - fflush(data->filep); - compute_dXSdu_dXSdQ2_max_mph(data); - fprintf(data->filep,"precomputations: compute_dXSdu_dXSdQ2_max_mph done\n"); - fflush(data->filep); - computeTotalXS_mph_resum(data); - fprintf(data->filep,"precomputations: total XS multi-phonon resummation done\n"); - fflush(data->filep); - } + // Should not be here + printf ("IncoherentPhonon_physics_scattering: no scattering happnes !!\n"); + printf ("rnd: %f accum: %f\n", rnd, accum); + printf ("cross sections\n"); + printf ("Total: %.6e\n", data->xsTot); + printf ("1ph: %.6e\n", data->xs1phe); + if (data->nphe_exact > 1) { + printf ("2ph: %.6e\n", data->xs2phe); + } + if (data->nphe_exact > 2) { + printf ("3ph: %.6e\n", data->xs3phe); + } + if (data->approx == 1) { + for (p = data->nphe_exact + 1; p <= data->nphe_approx; p++) { + printf ("%dph: %.6e\n", p, data->xs_p_phe_gauss[p]); + } + } else if (data->approx == 2) { + for (p = data->nphe_exact + 1; p <= data->nphe_approx; p++) { + printf ("%dph: %.6e\n", p, data->xs_p_phe_sp[p]); + } + } + if (data->mph_resum) { + printf ("mph: %.6e\n", data->xsmph); + } + printf ("Exiting ...\n"); + fflush (stdout); + exit (1); + }; + + int + build_K_final (double kabs, double ct, double* ki, double* kf) { + double t1[3], t2[3]; + double st = sqrt (1. - ct * ct); + + // sample azimuthal direction + double phi = 2. * PI * rand01 (); + double cp = cos (phi); + double sp = sin (phi); + + // build kprime (ki,t1,t2) orthonormal right handed triad + NORM (ki[0], ki[1], ki[2]); + normal_vec (&t1[0], &t1[1], &t1[2], ki[0], ki[1], ki[2]); + vec_prod (t2[0], t2[1], t2[2], ki[0], ki[1], ki[2], t1[0], t1[1], t1[2]); + + kf[0] = ct * ki[0] + st * (cp * t1[0] + sp * t2[0]); + kf[1] = ct * ki[1] + st * (cp * t1[1] + sp * t2[1]); + kf[2] = ct * ki[2] + st * (cp * t1[2] + sp * t2[2]); + + kf[0] = kabs * kf[0]; + kf[1] = kabs * kf[1]; + kf[2] = kabs * kf[2]; - fprintf(data->filep,"precompuations: finished\n"); - fflush(data->filep); -}; + return 0; + }; -void computeTotalXS_exact(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, nxs; - double aux, dkabs; - FILE *filep; + // Start implementation of internal functions - //exact 1-ph - filep = fopen("XS_1ph_exact.txt","r"); - if(filep != NULL) { - fprintf(data->filep,"computeTotalXS: reading XS 1-ph from file\n"); + void + precomputations (struct IncoherentPhonon_physics_storage_struct* data) { + int i, p, pmax; + double h = 4.13567; // planck constant in meV*ps + double dkabs, Q2, g0; + double xi, dxi, fac1, fac2, yp; + FILE* filep; + + fprintf (data->filep, "precomputations: start\n"); + fflush (data->filep); + + g0 = data->g0; + + /* + // computes and writes in file the exact Fp functions. Only for tests + pmax = 20; + computeFps(pmax,data); + fprintf(data->filep,"precomputations: Fps done\n"); fflush(data->filep); - fscanf(filep,"%d",&(data->nxs)); - data->kabs = (double *)malloc((data->nxs)*sizeof(double)); - data->xsTot_1ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_1ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_1ph = (double *)malloc((data->nxs)*sizeof(double)); - for(i=0;inxs;i++) { - fscanf(filep,"%lf %lf %lf %lf",(data->kabs)+i,(data->xsTot_1ph)+i, - (data->dXSdx_xmax_1ph)+i,(data->dXSdx_Fmax_1ph)+i); + //exit(1); + */ + + // precompute exact phonon terms + computeFs (data); + fprintf (data->filep, "precomputations: FS done\n"); + fflush (data->filep); + computeTotalXS_exact (data); + fprintf (data->filep, "precomputations: exact total XS done\n"); + fflush (data->filep); + + // NULL pointers + data->xsTot_pph_gauss = NULL; + data->dXSdx_xmax_pph_gauss = NULL; + data->dXSdx_Fmax_pph_gauss = NULL; + data->xsTot_pph_sp = NULL; + data->dXSdx_xmax_pph_sp = NULL; + data->dXSdx_Fmax_pph_sp = NULL; + + if (data->approx == 1) { + // precompute gaussian data + fprintf (data->filep, "precomputations: gaussian p-phonon done\n"); + fflush (data->filep); + computeTotalXS_pph_gauss (data); + fprintf (data->filep, "precomputations: total XS p-phonon gaussian done\n"); + fflush (data->filep); + } else if (data->approx == 2) { + computeSP_p (data->ntsp_p, data->ximin_p, data->ximax_p, data); + fprintf (data->filep, "precomputations: SP p-phonon done\n"); + fflush (data->filep); + computeTotalXS_pph_sp (data); + fprintf (data->filep, "precomputations: total XS p-phonon SP done\n"); + fflush (data->filep); } - fclose(filep); - } else { - data->kabs = (double *)malloc((data->nxs)*sizeof(double)); - data->xsTot_1ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_1ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_1ph = (double *)malloc((data->nxs)*sizeof(double)); - dkabs = (data->kabsmax-data->kabsmin)/(data->nxs); - fprintf(data->filep,"computeTotalXS: computing XS 1-ph exact\n"); - fflush(data->filep); - (data->kabs)[0] = data->kabsmin; - for(i=1;inxs;i++) { - (data->kabs)[i] = (data->kabs)[i-1] + dkabs; - } - //compute and write the results - filep = fopen("XS_1ph_exact.txt","w"); - fprintf(filep,"%d\n",data->nxs); - for(i=0;inxs;i++) { - (data->xsTot_1ph)[i] = totXS_1ph((data->kabs)[i],data); - compute_dXSdx_max_1ph(1000,(data->kabs)[i],data,(data->dXSdx_xmax_1ph)+i,(data->dXSdx_Fmax_1ph)+i); - fprintf(filep,"%f %.6e %.6e %.6e\n",(data->kabs)[i],(data->xsTot_1ph)[i], - (data->dXSdx_xmax_1ph)[i], (data->dXSdx_Fmax_1ph)[i]); - fflush(filep); + + if (data->mph_resum == 1) { + computeSaddlePointSol (data->ntsp, data->ximin, data->ximax, data); + fprintf (data->filep, "precomputations: computeSaddlePointSol done\n"); + fflush (data->filep); + compute_SQ2_mph (data); + fprintf (data->filep, "precomputations: compute_SQ2_mph done\n"); + fflush (data->filep); + compute_dXSdu_dXSdQ2_max_mph (data); + fprintf (data->filep, "precomputations: compute_dXSdu_dXSdQ2_max_mph done\n"); + fflush (data->filep); + computeTotalXS_mph_resum (data); + fprintf (data->filep, "precomputations: total XS multi-phonon resummation done\n"); + fflush (data->filep); } - fclose(filep); - } - if(data->nphe_exact==1) { - data->xsTot_2ph = NULL; - data->dXSdx_xmax_2ph = NULL; - data->dXSdx_Fmax_2ph = NULL; - data->xsTot_3ph = NULL; - data->dXSdx_xmax_3ph = NULL; - data->dXSdx_Fmax_3ph = NULL; - return; - } + fprintf (data->filep, "precompuations: finished\n"); + fflush (data->filep); + }; + + void + computeTotalXS_exact (struct IncoherentPhonon_physics_storage_struct* data) { + int i, nxs; + double aux, dkabs; + FILE* filep; + + // exact 1-ph + filep = fopen ("XS_1ph_exact.txt", "r"); + if (filep != NULL) { + fprintf (data->filep, "computeTotalXS: reading XS 1-ph from file\n"); + fflush (data->filep); + fscanf (filep, "%d", &(data->nxs)); + data->kabs = (double*)malloc ((data->nxs) * sizeof (double)); + data->xsTot_1ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_1ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_1ph = (double*)malloc ((data->nxs) * sizeof (double)); + for (i = 0; i < data->nxs; i++) { + fscanf (filep, "%lf %lf %lf %lf", (data->kabs) + i, (data->xsTot_1ph) + i, (data->dXSdx_xmax_1ph) + i, (data->dXSdx_Fmax_1ph) + i); + } + fclose (filep); + } else { + data->kabs = (double*)malloc ((data->nxs) * sizeof (double)); + data->xsTot_1ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_1ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_1ph = (double*)malloc ((data->nxs) * sizeof (double)); + dkabs = (data->kabsmax - data->kabsmin) / (data->nxs); + fprintf (data->filep, "computeTotalXS: computing XS 1-ph exact\n"); + fflush (data->filep); + (data->kabs)[0] = data->kabsmin; + for (i = 1; i < data->nxs; i++) { + (data->kabs)[i] = (data->kabs)[i - 1] + dkabs; + } + // compute and write the results + filep = fopen ("XS_1ph_exact.txt", "w"); + fprintf (filep, "%d\n", data->nxs); + for (i = 0; i < data->nxs; i++) { + (data->xsTot_1ph)[i] = totXS_1ph ((data->kabs)[i], data); + compute_dXSdx_max_1ph (1000, (data->kabs)[i], data, (data->dXSdx_xmax_1ph) + i, (data->dXSdx_Fmax_1ph) + i); + fprintf (filep, "%f %.6e %.6e %.6e\n", (data->kabs)[i], (data->xsTot_1ph)[i], (data->dXSdx_xmax_1ph)[i], (data->dXSdx_Fmax_1ph)[i]); + fflush (filep); + } + fclose (filep); + } - //exact 2-ph - filep = fopen("XS_2ph_exact.txt","r"); - if(filep != NULL) { - fprintf(data->filep,"computeTotalXS: reading XS 2-ph from file\n"); - fflush(data->filep); - fscanf(filep,"%d",&nxs); - if(nxs != data->nxs) { - fprintf(data->filep,"XS_2ph_exact.txt: different nxs: %d %d\n",nxs,data->nxs); - fprintf(data->filep,"Exiting...\n"); - fclose(data->filep); - printf("XS_2ph_exact.txt: different nxs: %d %d\n",nxs,data->nxs); - printf("Exiting...\n"); - fflush(stdout); - exit(1); - } - data->xsTot_2ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_2ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_2ph = (double *)malloc((data->nxs)*sizeof(double)); - for(i=0;inxs;i++) { - fscanf(filep,"%lf %lf %lf %lf",&aux,(data->xsTot_2ph)+i, - (data->dXSdx_xmax_2ph)+i,(data->dXSdx_Fmax_2ph)+i); + if (data->nphe_exact == 1) { + data->xsTot_2ph = NULL; + data->dXSdx_xmax_2ph = NULL; + data->dXSdx_Fmax_2ph = NULL; + data->xsTot_3ph = NULL; + data->dXSdx_xmax_3ph = NULL; + data->dXSdx_Fmax_3ph = NULL; + return; } - fclose(filep); - } else { - data->xsTot_2ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_2ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_2ph = (double *)malloc((data->nxs)*sizeof(double)); - fprintf(data->filep,"computeTotalXS: computing XS 2-ph exact\n"); - fflush(data->filep); - //compute and write the results - filep = fopen("XS_2ph_exact.txt","w"); - fprintf(filep,"%d\n",data->nxs); - for(i=0;inxs;i++) { - (data->xsTot_2ph)[i] = totXS_2ph((data->kabs)[i],data); - compute_dXSdx_max_2ph(1000,(data->kabs)[i],data,(data->dXSdx_xmax_2ph)+i,(data->dXSdx_Fmax_2ph)+i); - fprintf(filep,"%f %.6e %.6e %.6e\n",(data->kabs)[i],(data->xsTot_2ph)[i], - (data->dXSdx_xmax_2ph)[i], (data->dXSdx_Fmax_2ph)[i]); - fflush(filep); + + // exact 2-ph + filep = fopen ("XS_2ph_exact.txt", "r"); + if (filep != NULL) { + fprintf (data->filep, "computeTotalXS: reading XS 2-ph from file\n"); + fflush (data->filep); + fscanf (filep, "%d", &nxs); + if (nxs != data->nxs) { + fprintf (data->filep, "XS_2ph_exact.txt: different nxs: %d %d\n", nxs, data->nxs); + fprintf (data->filep, "Exiting...\n"); + fclose (data->filep); + printf ("XS_2ph_exact.txt: different nxs: %d %d\n", nxs, data->nxs); + printf ("Exiting...\n"); + fflush (stdout); + exit (1); + } + data->xsTot_2ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_2ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_2ph = (double*)malloc ((data->nxs) * sizeof (double)); + for (i = 0; i < data->nxs; i++) { + fscanf (filep, "%lf %lf %lf %lf", &aux, (data->xsTot_2ph) + i, (data->dXSdx_xmax_2ph) + i, (data->dXSdx_Fmax_2ph) + i); + } + fclose (filep); + } else { + data->xsTot_2ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_2ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_2ph = (double*)malloc ((data->nxs) * sizeof (double)); + fprintf (data->filep, "computeTotalXS: computing XS 2-ph exact\n"); + fflush (data->filep); + // compute and write the results + filep = fopen ("XS_2ph_exact.txt", "w"); + fprintf (filep, "%d\n", data->nxs); + for (i = 0; i < data->nxs; i++) { + (data->xsTot_2ph)[i] = totXS_2ph ((data->kabs)[i], data); + compute_dXSdx_max_2ph (1000, (data->kabs)[i], data, (data->dXSdx_xmax_2ph) + i, (data->dXSdx_Fmax_2ph) + i); + fprintf (filep, "%f %.6e %.6e %.6e\n", (data->kabs)[i], (data->xsTot_2ph)[i], (data->dXSdx_xmax_2ph)[i], (data->dXSdx_Fmax_2ph)[i]); + fflush (filep); + } + fclose (filep); } - fclose(filep); - } - if(data->nphe_exact==2) { - data->xsTot_3ph = NULL; - data->dXSdx_xmax_3ph = NULL; - data->dXSdx_Fmax_3ph = NULL; - return; - } + if (data->nphe_exact == 2) { + data->xsTot_3ph = NULL; + data->dXSdx_xmax_3ph = NULL; + data->dXSdx_Fmax_3ph = NULL; + return; + } - //exact 3-ph - filep = fopen("XS_3ph_exact.txt","r"); - if(filep != NULL) { - fprintf(data->filep,"computeTotalXS: reading XS 3-ph from file\n"); - fflush(data->filep); - fscanf(filep,"%d",&nxs); - if(nxs != data->nxs) { - fprintf(data->filep,"XS_3ph_exact.txt: different nxs: %d %d\n",nxs,data->nxs); - fprintf(data->filep,"Exiting...\n"); - fclose(data->filep); - printf("XS_3ph_exact.txt: different nxs: %d %d\n",nxs,data->nxs); - printf("Exiting...\n"); - fflush(stdout); - exit(1); - } - data->xsTot_3ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_3ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_3ph = (double *)malloc((data->nxs)*sizeof(double)); - for(i=0;inxs;i++) { - fscanf(filep,"%lf %lf %lf %lf",&aux,(data->xsTot_3ph)+i, - (data->dXSdx_xmax_3ph)+i,(data->dXSdx_Fmax_3ph)+i); + // exact 3-ph + filep = fopen ("XS_3ph_exact.txt", "r"); + if (filep != NULL) { + fprintf (data->filep, "computeTotalXS: reading XS 3-ph from file\n"); + fflush (data->filep); + fscanf (filep, "%d", &nxs); + if (nxs != data->nxs) { + fprintf (data->filep, "XS_3ph_exact.txt: different nxs: %d %d\n", nxs, data->nxs); + fprintf (data->filep, "Exiting...\n"); + fclose (data->filep); + printf ("XS_3ph_exact.txt: different nxs: %d %d\n", nxs, data->nxs); + printf ("Exiting...\n"); + fflush (stdout); + exit (1); + } + data->xsTot_3ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_3ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_3ph = (double*)malloc ((data->nxs) * sizeof (double)); + for (i = 0; i < data->nxs; i++) { + fscanf (filep, "%lf %lf %lf %lf", &aux, (data->xsTot_3ph) + i, (data->dXSdx_xmax_3ph) + i, (data->dXSdx_Fmax_3ph) + i); + } + fclose (filep); + } else { + data->xsTot_3ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_3ph = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_3ph = (double*)malloc ((data->nxs) * sizeof (double)); + + fprintf (data->filep, "computeTotalXS: computing XS 3-ph exact\n"); + fflush (data->filep); + + // compute and write the results + filep = fopen ("XS_3ph_exact.txt", "w"); + fprintf (filep, "%d\n", data->nxs); + for (i = 0; i < data->nxs; i++) { + (data->xsTot_3ph)[i] = totXS_3ph ((data->kabs)[i], data); + compute_dXSdx_max_3ph (1000, (data->kabs)[i], data, (data->dXSdx_xmax_3ph) + i, (data->dXSdx_Fmax_3ph) + i); + fprintf (filep, "%f %.6e %.6e %.6e\n", (data->kabs)[i], (data->xsTot_3ph)[i], (data->dXSdx_xmax_3ph)[i], (data->dXSdx_Fmax_3ph)[i]); + fflush (filep); + } + fclose (filep); } - fclose(filep); - } else { - data->xsTot_3ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_3ph = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_3ph = (double *)malloc((data->nxs)*sizeof(double)); - - fprintf(data->filep,"computeTotalXS: computing XS 3-ph exact\n"); - fflush(data->filep); - - //compute and write the results - filep = fopen("XS_3ph_exact.txt","w"); - fprintf(filep,"%d\n",data->nxs); - for(i=0;inxs;i++) { - (data->xsTot_3ph)[i] = totXS_3ph((data->kabs)[i],data); - compute_dXSdx_max_3ph(1000,(data->kabs)[i],data,(data->dXSdx_xmax_3ph)+i,(data->dXSdx_Fmax_3ph)+i); - fprintf(filep,"%f %.6e %.6e %.6e\n",(data->kabs)[i],(data->xsTot_3ph)[i], - (data->dXSdx_xmax_3ph)[i], (data->dXSdx_Fmax_3ph)[i]); - fflush(filep); + }; + + void + computeTotalXS_pph_gauss (struct IncoherentPhonon_physics_storage_struct* data) { + int i, p, pmax, pread, pr, nxs; + double aux; + FILE* filep; + + data->xsTot_pph_gauss = (double**)malloc ((data->nphe_approx + 1) * sizeof (double*)); + data->dXSdx_xmax_pph_gauss = (double**)malloc ((data->nphe_approx + 1) * sizeof (double*)); + data->dXSdx_Fmax_pph_gauss = (double**)malloc ((data->nphe_approx + 1) * sizeof (double*)); + // 0 compoent not used + data->xsTot_pph_gauss[0] = NULL; + data->dXSdx_xmax_pph_gauss[0] = NULL; + data->dXSdx_Fmax_pph_gauss[0] = NULL; + // allocate remaining + for (p = 1; p <= data->nphe_approx; p++) { + data->xsTot_pph_gauss[p] = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_pph_gauss[p] = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_pph_gauss[p] = (double*)malloc ((data->nxs) * sizeof (double)); } - fclose(filep); - } -}; - -void computeTotalXS_pph_gauss(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, p, pmax, pread, pr, nxs; - double aux; - FILE *filep; - - data->xsTot_pph_gauss = (double **)malloc((data->nphe_approx+1)*sizeof(double *)); - data->dXSdx_xmax_pph_gauss = (double **)malloc((data->nphe_approx+1)*sizeof(double *)); - data->dXSdx_Fmax_pph_gauss = (double **)malloc((data->nphe_approx+1)*sizeof(double *)); - // 0 compoent not used - data->xsTot_pph_gauss[0] = NULL; - data->dXSdx_xmax_pph_gauss[0] = NULL; - data->dXSdx_Fmax_pph_gauss[0] = NULL; - // allocate remaining - for(p=1;p<=data->nphe_approx;p++) { - data->xsTot_pph_gauss[p] = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_pph_gauss[p] = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_pph_gauss[p] = (double *)malloc((data->nxs)*sizeof(double)); - } - pread = 0; - filep = fopen("XS_pph_gauss.txt","r"); - if(filep != NULL) { - fprintf(data->filep,"computeTotalXS_pph_gauss: reading XS p-phonon gaussian from file\n"); - fflush(data->filep); - fscanf(filep,"%d %d",&pmax,&nxs); - if(nxs != data->nxs) { - fprintf(data->filep,"XS_pph_gauss.txt: different nxs: %d %d\n",nxs,data->nxs); - fprintf(data->filep,"Exiting...\n"); - fclose(data->filep); - printf("XS_pph_gauss.txt: different nxs: %d %d\n",nxs,data->nxs); - printf("Exiting...\n"); - fflush(stdout); - exit(1); - } - if(data->nphe_approx<=pmax) { pread = data->nphe_approx; } else { pread = pmax; } - for(p=1;p<=pread;p++) { - for(i=0;inxs;i++) { - fscanf(filep,"%d %lf %lf %lf %lf",&pr,&aux,(data->xsTot_pph_gauss)[p]+i, - (data->dXSdx_xmax_pph_gauss)[p]+i,(data->dXSdx_Fmax_pph_gauss)[p]+i); + pread = 0; + filep = fopen ("XS_pph_gauss.txt", "r"); + if (filep != NULL) { + fprintf (data->filep, "computeTotalXS_pph_gauss: reading XS p-phonon gaussian from file\n"); + fflush (data->filep); + fscanf (filep, "%d %d", &pmax, &nxs); + if (nxs != data->nxs) { + fprintf (data->filep, "XS_pph_gauss.txt: different nxs: %d %d\n", nxs, data->nxs); + fprintf (data->filep, "Exiting...\n"); + fclose (data->filep); + printf ("XS_pph_gauss.txt: different nxs: %d %d\n", nxs, data->nxs); + printf ("Exiting...\n"); + fflush (stdout); + exit (1); + } + if (data->nphe_approx <= pmax) { + pread = data->nphe_approx; + } else { + pread = pmax; + } + for (p = 1; p <= pread; p++) { + for (i = 0; i < data->nxs; i++) { + fscanf (filep, "%d %lf %lf %lf %lf", &pr, &aux, (data->xsTot_pph_gauss)[p] + i, (data->dXSdx_xmax_pph_gauss)[p] + i, + (data->dXSdx_Fmax_pph_gauss)[p] + i); + } + } + fclose (filep); + if (pread == data->nphe_approx) { + return; } } - fclose(filep); - if(pread == data->nphe_approx) { return; } - } - // compute what has not been read - for(p=pread+1;p<=data->nphe_approx;p++) { - for(i=0;inxs;i++) { - (data->xsTot_pph_gauss)[p][i] = totXS_pph_gauss(p,(data->kabs)[i],data); - compute_dXSdx_max_pph_gauss(1000,p,(data->kabs)[i],data, - (data->dXSdx_xmax_pph_gauss)[p]+i,(data->dXSdx_Fmax_pph_gauss)[p]+i); + // compute what has not been read + for (p = pread + 1; p <= data->nphe_approx; p++) { + for (i = 0; i < data->nxs; i++) { + (data->xsTot_pph_gauss)[p][i] = totXS_pph_gauss (p, (data->kabs)[i], data); + compute_dXSdx_max_pph_gauss (1000, p, (data->kabs)[i], data, (data->dXSdx_xmax_pph_gauss)[p] + i, (data->dXSdx_Fmax_pph_gauss)[p] + i); + } + } + // write the results + filep = fopen ("XS_pph_gauss.txt", "w"); + fprintf (filep, "%d %d\n", data->nphe_approx, data->nxs); + for (p = 1; p <= data->nphe_approx; p++) { + for (i = 0; i < data->nxs; i++) { + fprintf (filep, "%d %f %.6e %.6e %.6e\n", p, data->kabs[i], (data->xsTot_pph_gauss)[p][i], (data->dXSdx_xmax_pph_gauss)[p][i], + (data->dXSdx_Fmax_pph_gauss)[p][i]); + } + } + fclose (filep); + }; + + void + computeTotalXS_pph_sp (struct IncoherentPhonon_physics_storage_struct* data) { + int i, p, pmax, pread, pr, nxs; + double aux; + FILE* filep; + + data->xsTot_pph_sp = (double**)malloc ((data->nphe_approx + 1) * sizeof (double*)); + data->dXSdx_xmax_pph_sp = (double**)malloc ((data->nphe_approx + 1) * sizeof (double*)); + data->dXSdx_Fmax_pph_sp = (double**)malloc ((data->nphe_approx + 1) * sizeof (double*)); + data->xsTot_pph_sp[0] = NULL; + data->dXSdx_xmax_pph_sp[0] = NULL; + data->dXSdx_Fmax_pph_sp[0] = NULL; + for (p = 1; p <= data->nphe_approx; p++) { + data->xsTot_pph_sp[p] = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_xmax_pph_sp[p] = (double*)malloc ((data->nxs) * sizeof (double)); + data->dXSdx_Fmax_pph_sp[p] = (double*)malloc ((data->nxs) * sizeof (double)); } - } - //write the results - filep = fopen("XS_pph_gauss.txt","w"); - fprintf(filep,"%d %d\n",data->nphe_approx,data->nxs); - for(p=1;p<=data->nphe_approx;p++) { - for(i=0;inxs;i++) { - fprintf(filep,"%d %f %.6e %.6e %.6e\n",p,data->kabs[i],(data->xsTot_pph_gauss)[p][i], - (data->dXSdx_xmax_pph_gauss)[p][i],(data->dXSdx_Fmax_pph_gauss)[p][i]); - } - } - fclose(filep); -}; - -void computeTotalXS_pph_sp(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, p, pmax, pread, pr, nxs; - double aux; - FILE *filep; - - data->xsTot_pph_sp = (double **)malloc((data->nphe_approx+1)*sizeof(double *)); - data->dXSdx_xmax_pph_sp = (double **)malloc((data->nphe_approx+1)*sizeof(double *)); - data->dXSdx_Fmax_pph_sp = (double **)malloc((data->nphe_approx+1)*sizeof(double *)); - data->xsTot_pph_sp[0] = NULL; - data->dXSdx_xmax_pph_sp[0] = NULL; - data->dXSdx_Fmax_pph_sp[0] = NULL; - for(p=1;p<=data->nphe_approx;p++) { - data->xsTot_pph_sp[p] = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_xmax_pph_sp[p] = (double *)malloc((data->nxs)*sizeof(double)); - data->dXSdx_Fmax_pph_sp[p] = (double *)malloc((data->nxs)*sizeof(double)); - } - pread = 0; - filep = fopen("XS_pph_sp.txt","r"); - if(filep != NULL) { - fprintf(data->filep,"computeTotalXS_pph_sp: reading XS p-phonon saddle-point from file\n"); - fflush(data->filep); - fscanf(filep,"%d %d",&pmax,&nxs); - if(nxs != data->nxs) { - fprintf(data->filep,"XS_pph_sp.txt: different nxs: %d %d\n",nxs,data->nxs); - fprintf(data->filep,"Exiting...\n"); - fclose(data->filep); - printf("XS_pph_sp.txt: different nxs: %d %d\n",nxs,data->nxs); - printf("Exiting...\n"); - fflush(stdout); - exit(1); - } - if(data->nphe_approx<=pmax) { pread = data->nphe_approx; } else { pread = pmax; } - for(p=1;p<=pread;p++) { - for(i=0;inxs;i++) { - fscanf(filep,"%d %lf %lf %lf %lf",&pr,&aux,(data->xsTot_pph_sp)[p]+i, - (data->dXSdx_xmax_pph_sp)[p]+i,(data->dXSdx_Fmax_pph_sp)[p]+i); + pread = 0; + filep = fopen ("XS_pph_sp.txt", "r"); + if (filep != NULL) { + fprintf (data->filep, "computeTotalXS_pph_sp: reading XS p-phonon saddle-point from file\n"); + fflush (data->filep); + fscanf (filep, "%d %d", &pmax, &nxs); + if (nxs != data->nxs) { + fprintf (data->filep, "XS_pph_sp.txt: different nxs: %d %d\n", nxs, data->nxs); + fprintf (data->filep, "Exiting...\n"); + fclose (data->filep); + printf ("XS_pph_sp.txt: different nxs: %d %d\n", nxs, data->nxs); + printf ("Exiting...\n"); + fflush (stdout); + exit (1); + } + if (data->nphe_approx <= pmax) { + pread = data->nphe_approx; + } else { + pread = pmax; + } + for (p = 1; p <= pread; p++) { + for (i = 0; i < data->nxs; i++) { + fscanf (filep, "%d %lf %lf %lf %lf", &pr, &aux, (data->xsTot_pph_sp)[p] + i, (data->dXSdx_xmax_pph_sp)[p] + i, (data->dXSdx_Fmax_pph_sp)[p] + i); + } + } + fclose (filep); + if (pread == data->nphe_approx) { + return; } } - fclose(filep); - if(pread == data->nphe_approx) { return; } - } - // compute what is has not been read - for(p=pread+1;p<=data->nphe_approx;p++) { - for(i=0;inxs;i++) { - (data->xsTot_pph_sp)[p][i] = totXS_pph_sp(p,(data->kabs)[i],data); - compute_dXSdx_max_pph_sp(1000,p,(data->kabs)[i],data, - (data->dXSdx_xmax_pph_sp)[p]+i,(data->dXSdx_Fmax_pph_sp)[p]+i); + // compute what is has not been read + for (p = pread + 1; p <= data->nphe_approx; p++) { + for (i = 0; i < data->nxs; i++) { + (data->xsTot_pph_sp)[p][i] = totXS_pph_sp (p, (data->kabs)[i], data); + compute_dXSdx_max_pph_sp (1000, p, (data->kabs)[i], data, (data->dXSdx_xmax_pph_sp)[p] + i, (data->dXSdx_Fmax_pph_sp)[p] + i); + } } - } - //write the results - filep = fopen("XS_pph_sp.txt","w"); - fprintf(filep,"%d %d\n",data->nphe_approx,data->nxs); - for(p=1;p<=data->nphe_approx;p++) { - for(i=0;inxs;i++) { - fprintf(filep,"%d %f %.6e %.6e %.6e\n",p,data->kabs[i],(data->xsTot_pph_sp)[p][i], - (data->dXSdx_xmax_pph_sp)[p][i],(data->dXSdx_Fmax_pph_sp)[p][i]); - } - } - fclose(filep); -}; - -void computeTotalXS_mph_resum(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, nxs; - double aux; - FILE *filep; - filep = fopen("XS_mph_resum.txt","r"); - if(filep != NULL) { - fprintf(data->filep,"computeTotalXS_mph_resum: reading XS multi-phonon resum from file\n"); - fflush(data->filep); - fscanf(filep,"%d",&nxs); - if(nxs != data->nxs) { - fprintf(data->filep,"XS_mph_resum.txt: different nxs: %d %d\n",nxs,data->nxs); - fprintf(data->filep,"Exiting...\n"); - fclose(data->filep); - printf("XS_mph_resum.txt: different nxs: %d %d\n",nxs,data->nxs); - printf("Exiting...\n"); - fflush(stdout); - exit(1); - } - data->xsTot_mph = (double *)malloc((data->nxs)*sizeof(double)); - for(i=0;inxs;i++) { - fscanf(filep,"%lf %lf",&aux,(data->xsTot_mph)+i); + // write the results + filep = fopen ("XS_pph_sp.txt", "w"); + fprintf (filep, "%d %d\n", data->nphe_approx, data->nxs); + for (p = 1; p <= data->nphe_approx; p++) { + for (i = 0; i < data->nxs; i++) { + fprintf (filep, "%d %f %.6e %.6e %.6e\n", p, data->kabs[i], (data->xsTot_pph_sp)[p][i], (data->dXSdx_xmax_pph_sp)[p][i], (data->dXSdx_Fmax_pph_sp)[p][i]); + } } - fclose(filep); - } else { - data->xsTot_mph = (double *)malloc((data->nxs)*sizeof(double)); - //compute and write the results - filep = fopen("XS_mph_resum.txt","w"); - fprintf(filep,"%d\n",data->nxs); - for(i=0;inxs;i++) { - (data->xsTot_mph)[i] = totXS_mph((data->kabs)[i],data); - fprintf(filep,"%f %.6e\n",(data->kabs)[i],(data->xsTot_mph)[i]); - fflush(filep); + fclose (filep); + }; + + void + computeTotalXS_mph_resum (struct IncoherentPhonon_physics_storage_struct* data) { + int i, nxs; + double aux; + FILE* filep; + filep = fopen ("XS_mph_resum.txt", "r"); + if (filep != NULL) { + fprintf (data->filep, "computeTotalXS_mph_resum: reading XS multi-phonon resum from file\n"); + fflush (data->filep); + fscanf (filep, "%d", &nxs); + if (nxs != data->nxs) { + fprintf (data->filep, "XS_mph_resum.txt: different nxs: %d %d\n", nxs, data->nxs); + fprintf (data->filep, "Exiting...\n"); + fclose (data->filep); + printf ("XS_mph_resum.txt: different nxs: %d %d\n", nxs, data->nxs); + printf ("Exiting...\n"); + fflush (stdout); + exit (1); + } + data->xsTot_mph = (double*)malloc ((data->nxs) * sizeof (double)); + for (i = 0; i < data->nxs; i++) { + fscanf (filep, "%lf %lf", &aux, (data->xsTot_mph) + i); + } + fclose (filep); + } else { + data->xsTot_mph = (double*)malloc ((data->nxs) * sizeof (double)); + // compute and write the results + filep = fopen ("XS_mph_resum.txt", "w"); + fprintf (filep, "%d\n", data->nxs); + for (i = 0; i < data->nxs; i++) { + (data->xsTot_mph)[i] = totXS_mph ((data->kabs)[i], data); + fprintf (filep, "%f %.6e\n", (data->kabs)[i], (data->xsTot_mph)[i]); + fflush (filep); + } + fclose (filep); + } + }; + + //////////////////////////////////// + // Exact phonon expansion terms //// + //////////////////////////////////// + + double + sampleKprime_1ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/k + int i; + double x, px; + double E = KS2E * kabs * kabs; + double iErat = data->Emax / E; + double pxmax = interpFunc (kabs, data->nxs, data->kabs, data->dXSdx_Fmax_1ph); + double xmax = sqrt (1. + iErat); + double xmin, delta_x; + if (iErat < 1.0) { + xmin = sqrt (1.0 - iErat); + } else { + xmin = 0; + } + delta_x = xmax - xmin; + FILE* filep; + for (i = 0; i < maxIter; i++) { + x = xmin + delta_x * rand01 (); + px = dXSdx_1ph (x, E, data); + if (px > pxmax) { + fprintf (data->filep, "sampleKprime_1ph:\n"); + fprintf (data->filep, "x: %.6e\n", x); + fprintf (data->filep, "xmax: %.6e\n", xmax); + fprintf (data->filep, "pxmax: %.6e\n", pxmax); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "px/pxmax: %.6e\n", px / pxmax); + filep = fopen ("dXSdx_1ph.txt", "w"); + x = 0; + while (x <= xmax) { + px = dXSdx_1ph (x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + exit (1); + } + if (px / pxmax > rand01 ()) { + return x; + } + } + // What happens if maxIter is exceeded?? return negative value to control + fprintf (data->filep, "sampleKprime_1ph: maxIter exceeded\n"); + filep = fopen ("dXSdx_1ph_maxIter_exceeded.txt", "w"); + x = 0; + while (x <= xmax) { + px = dXSdx_1ph (x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + return -1; + }; + + double + sampleKprime_2ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/k + int i; + double x, px; + double E = KS2E * kabs * kabs; + double iErat = data->Emax / E; + double pxmax = interpFunc (kabs, data->nxs, data->kabs, data->dXSdx_Fmax_2ph); + double xmax = sqrt (1. + 2.0 * iErat); + double xmin, delta_x; + if (iErat < 0.5) { + xmin = sqrt (1.0 - 2.0 * iErat); + } else { + xmin = 0; + } + delta_x = xmax - xmin; + FILE* filep; + for (i = 0; i < maxIter; i++) { + x = xmin + delta_x * rand01 (); + px = dXSdx_2ph (x, E, data); + if (px > pxmax) { + fprintf (data->filep, "sampleKprime_2ph:\n"); + fprintf (data->filep, "x: %.6e\n", x); + fprintf (data->filep, "xmax: %.6e\n", xmax); + fprintf (data->filep, "pxmax: %.6e\n", pxmax); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "px/pxmax: %.6e\n", px / pxmax); + filep = fopen ("dXSdx_2ph.txt", "w"); + x = 0; + while (x <= xmax) { + px = dXSdx_2ph (x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + exit (1); + } + if (px / pxmax > rand01 ()) { + return x; + } + } + // What happens if maxIter is exceeded?? return negative value to control + filep = fopen ("dXSdx_2ph_maxIter_exceeded.txt", "w"); + x = 0; + while (x <= xmax) { + px = dXSdx_2ph (x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + return -1; + }; + + double + sampleKprime_3ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/k + int i; + double x, px; + double E = KS2E * kabs * kabs; + double iErat = data->Emax / E; + double pxmax = interpFunc (kabs, data->nxs, data->kabs, data->dXSdx_Fmax_3ph); + double xmax = sqrt (1. + 3.0 * iErat); + double xmin, delta_x; + if (iErat < 1. / 3.) { + xmin = sqrt (1.0 - 3.0 * iErat); + } else { + xmin = 0; + } + delta_x = xmax - xmin; + FILE* filep; + for (i = 0; i < maxIter; i++) { + x = xmin + delta_x * rand01 (); + px = dXSdx_3ph (x, E, data); + if (px > pxmax) { + fprintf (data->filep, "sampleKprime_3ph:\n"); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "xmax: %.6e\n", xmax); + fprintf (data->filep, "pxmax: %.6e\n", pxmax); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "px/pxmax: %.6e\n", px / pxmax); + filep = fopen ("dXSdx_3ph.txt", "w"); + x = 0; + while (x <= xmax) { + px = dXSdx_3ph (x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + exit (1); + } + if (px / pxmax > rand01 ()) { + return x; + } + } + // What happens if maxIter is exceeded?? return negative value to control + filep = fopen ("dXSdx_3ph_maxIter_exceeded.txt", "w"); + x = 0; + while (x <= xmax) { + px = dXSdx_3ph (x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + return -1; + }; + + double + sampleDir (double x, double E, int p, struct IncoherentPhonon_physics_storage_struct* data) { + // return z=cos(theta) + if (x <= 0) { + return 1; + } + int i; + double z, Q2, pz, pzmax; + double g0 = data->g0; + double fac = (E / (data->Emax)) * (data->mRat); + double Q2min = fac * pow (1 - x, 2); + double Q2max = fac * pow (1 + x, 2); + double Q2med = p / g0; + double pz1 = exp (-g0 * Q2min) * pow (Q2min, p); + double pz2 = exp (-g0 * Q2med) * pow (Q2med, p); + double pz3 = exp (-g0 * Q2max) * pow (Q2max, p); + double dQ2 = Q2max - Q2min; + + // determine the maximum + if (pz1 > pz3) { + pzmax = pz1; + } else { + pzmax = pz3; + } + if (Q2min < Q2med && Q2med < Q2max && pz2 > pzmax) { + pzmax = pz2; } - fclose(filep); - } -}; - -//////////////////////////////////// -// Exact phonon expansion terms //// -//////////////////////////////////// - -double sampleKprime_1ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - //x = kprime/k - int i; - double x, px; - double E = KS2E*kabs*kabs; - double iErat = data->Emax/E; - double pxmax = interpFunc(kabs,data->nxs,data->kabs,data->dXSdx_Fmax_1ph); - double xmax = sqrt(1. + iErat); - double xmin, delta_x; - if(iErat<1.0) { xmin = sqrt(1.0 - iErat); } else { xmin = 0; } - delta_x = xmax - xmin; - FILE *filep; - for(i=0;ipxmax) { - fprintf(data->filep,"sampleKprime_1ph:\n"); - fprintf(data->filep,"x: %.6e\n",x); - fprintf(data->filep,"xmax: %.6e\n",xmax); - fprintf(data->filep,"pxmax: %.6e\n",pxmax); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"px/pxmax: %.6e\n",px/pxmax); - filep = fopen("dXSdx_1ph.txt","w"); - x = 0; - while(x<=xmax) { - px = dXSdx_1ph(x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - exit(1); - } - if(px/pxmax>rand01()) { return x; } - } - //What happens if maxIter is exceeded?? return negative value to control - fprintf(data->filep,"sampleKprime_1ph: maxIter exceeded\n"); - filep = fopen("dXSdx_1ph_maxIter_exceeded.txt","w"); - x = 0; - while(x<=xmax) { - px = dXSdx_1ph(x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - return -1; -}; - -double sampleKprime_2ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - //x = kprime/k - int i; - double x, px; - double E = KS2E*kabs*kabs; - double iErat = data->Emax/E; - double pxmax = interpFunc(kabs,data->nxs,data->kabs,data->dXSdx_Fmax_2ph); - double xmax = sqrt(1. + 2.0*iErat); - double xmin, delta_x; - if(iErat<0.5) { xmin = sqrt(1.0 - 2.0*iErat); } else { xmin = 0; } - delta_x = xmax - xmin; - FILE *filep; - for(i=0;ipxmax) { - fprintf(data->filep,"sampleKprime_2ph:\n"); - fprintf(data->filep,"x: %.6e\n",x); - fprintf(data->filep,"xmax: %.6e\n",xmax); - fprintf(data->filep,"pxmax: %.6e\n",pxmax); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"px/pxmax: %.6e\n",px/pxmax); - filep = fopen("dXSdx_2ph.txt","w"); - x = 0; - while(x<=xmax) { - px = dXSdx_2ph(x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - exit(1); - } - if(px/pxmax>rand01()) { return x; } - } - //What happens if maxIter is exceeded?? return negative value to control - filep = fopen("dXSdx_2ph_maxIter_exceeded.txt","w"); - x = 0; - while(x<=xmax) { - px = dXSdx_2ph(x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - return -1; -}; - -double sampleKprime_3ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - //x = kprime/k - int i; - double x, px; - double E = KS2E*kabs*kabs; - double iErat = data->Emax/E; - double pxmax = interpFunc(kabs,data->nxs,data->kabs,data->dXSdx_Fmax_3ph); - double xmax = sqrt(1.+3.0*iErat); - double xmin, delta_x; - if(iErat<1./3.) { xmin = sqrt(1.0 - 3.0*iErat); } else { xmin = 0; } - delta_x = xmax - xmin; - FILE *filep; - for(i=0;ipxmax) { - fprintf(data->filep,"sampleKprime_3ph:\n"); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"xmax: %.6e\n",xmax); - fprintf(data->filep,"pxmax: %.6e\n",pxmax); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"px/pxmax: %.6e\n",px/pxmax); - filep = fopen("dXSdx_3ph.txt","w"); - x = 0; - while(x<=xmax) { - px = dXSdx_3ph(x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - exit(1); - } - if(px/pxmax>rand01()) { return x; } - } - //What happens if maxIter is exceeded?? return negative value to control - filep = fopen("dXSdx_3ph_maxIter_exceeded.txt","w"); - x = 0; - while(x<=xmax) { - px = dXSdx_3ph(x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - return -1; -}; - -double sampleDir(double x, double E, int p, struct IncoherentPhonon_physics_storage_struct *data) -{ - // return z=cos(theta) - if(x<=0) { return 1; } - int i; - double z, Q2, pz, pzmax; - double g0 = data->g0; - double fac = (E/(data->Emax))*(data->mRat); - double Q2min = fac*pow(1-x,2); - double Q2max = fac*pow(1+x,2); - double Q2med = p/g0; - double pz1 = exp(-g0*Q2min)*pow(Q2min,p); - double pz2 = exp(-g0*Q2med)*pow(Q2med,p); - double pz3 = exp(-g0*Q2max)*pow(Q2max,p); - double dQ2 = Q2max - Q2min; - - //determine the maximum - if(pz1>pz3) { pzmax = pz1; } else { pzmax = pz3; } - if(Q2minpzmax) { pzmax = pz2; } - - for(i=0;i1) { - fprintf(data->filep,"sampleDir:\n"); - fprintf(data->filep,"Q2min: %f\n",Q2min); - fprintf(data->filep,"Q2med: %f\n",Q2med); - fprintf(data->filep,"Q2max: %f\n",Q2max); - fprintf(data->filep,"Q2: %f\n",Q2); - fprintf(data->filep,"pz1: %.6e\n",pz1); - fprintf(data->filep,"pz2: %.6e\n",pz2); - fprintf(data->filep,"pz3: %.6e\n",pz3); - fprintf(data->filep,"pzmax: %.6e\n",pzmax); - fprintf(data->filep,"pz: %.6e\n",pz); - fprintf(data->filep,"pz/pzmax: %.6e\n",pz/pzmax); - exit(1); - } - if(pz/pzmax>rand01()) { return z; } - } - //What happens if maxIter is exceeded?? return -1000 to control - return -1000; -}; - -int compute_dXSdx_max_1ph(int n, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax) -{ - int i; - double x, xmax, dx, ss; - double E = KS2E*kabs*kabs; - - xmax = sqrt(1.+(data->Emax)/E); - dx = xmax/n; - - x = 0; - *xm = 0; - *xsDiffMax = dXSdx_1ph(x,E,data); - for(i=0;i(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } - } - ss = dXSdx_1ph(xmax,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = xmax; } - // refine - if(*xm>0 && *xm 1) { + fprintf (data->filep, "sampleDir:\n"); + fprintf (data->filep, "Q2min: %f\n", Q2min); + fprintf (data->filep, "Q2med: %f\n", Q2med); + fprintf (data->filep, "Q2max: %f\n", Q2max); + fprintf (data->filep, "Q2: %f\n", Q2); + fprintf (data->filep, "pz1: %.6e\n", pz1); + fprintf (data->filep, "pz2: %.6e\n", pz2); + fprintf (data->filep, "pz3: %.6e\n", pz3); + fprintf (data->filep, "pzmax: %.6e\n", pzmax); + fprintf (data->filep, "pz: %.6e\n", pz); + fprintf (data->filep, "pz/pzmax: %.6e\n", pz / pzmax); + exit (1); + } + if (pz / pzmax > rand01 ()) { + return z; + } + } + + // What happens if maxIter is exceeded?? return -1000 to control + return -1000; + }; + + int + compute_dXSdx_max_1ph (int n, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax) { + int i; + double x, xmax, dx, ss; + double E = KS2E * kabs * kabs; + + xmax = sqrt (1. + (data->Emax) / E); + dx = xmax / n; + + x = 0; + *xm = 0; + *xsDiffMax = dXSdx_1ph (x, E, data); + for (i = 0; i < n; i++) { x += dx; - ss = dXSdx_1ph(x,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } + ss = dXSdx_1ph (x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } } - } - // security - *xsDiffMax *= 1.01; - - return 0; -}; - -int compute_dXSdx_max_2ph(int n, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax) -{ - int i; - double x, xmax, dx, ss; - double E = KS2E*kabs*kabs; - - xmax = sqrt(1.+2.*(data->Emax)/E); - dx = xmax/n; - - x = 0; - *xm = 0; - *xsDiffMax = dXSdx_2ph(x,E,data); - for(i=0;i(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } - } - ss = dXSdx_2ph(xmax,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = xmax; } - // refine - if(*xm>0 && *xm (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = xmax; + } + // refine + if (*xm > 0 && *xm < xmax) { + xmax = *xm + dx; + x = *xm - dx; + dx /= 100; + *xm = x; + *xsDiffMax = dXSdx_1ph (x, E, data); + for (i = 0; i < 200; i++) { + x += dx; + ss = dXSdx_1ph (x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } + } + } + // security + *xsDiffMax *= 1.01; + + return 0; + }; + + int + compute_dXSdx_max_2ph (int n, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax) { + int i; + double x, xmax, dx, ss; + double E = KS2E * kabs * kabs; + + xmax = sqrt (1. + 2. * (data->Emax) / E); + dx = xmax / n; + + x = 0; + *xm = 0; + *xsDiffMax = dXSdx_2ph (x, E, data); + for (i = 0; i < n; i++) { x += dx; - ss = dXSdx_2ph(x,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } + ss = dXSdx_2ph (x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } } - } - // security - *xsDiffMax *= 1.01; - - return 0; -}; - -int compute_dXSdx_max_3ph(int n, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax) -{ - int i; - double x, xmax, dx, ss; - double E = KS2E*kabs*kabs; - - xmax = sqrt(1.+3.*(data->Emax)/E); - dx = xmax/n; - - x = 0; - *xm = 0; - *xsDiffMax = dXSdx_3ph(x,E,data); - for(i=0;i(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } - } - ss = dXSdx_3ph(xmax,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = xmax; } - // refine - if(*xm>0 && *xm (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = xmax; + } + // refine + if (*xm > 0 && *xm < xmax) { + xmax = *xm + dx; + x = *xm - dx; + dx /= 100; + *xm = x; + *xsDiffMax = dXSdx_2ph (x, E, data); + for (i = 0; i < 200; i++) { + x += dx; + ss = dXSdx_2ph (x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } + } + } + // security + *xsDiffMax *= 1.01; + + return 0; + }; + + int + compute_dXSdx_max_3ph (int n, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax) { + int i; + double x, xmax, dx, ss; + double E = KS2E * kabs * kabs; + + xmax = sqrt (1. + 3. * (data->Emax) / E); + dx = xmax / n; + + x = 0; + *xm = 0; + *xsDiffMax = dXSdx_3ph (x, E, data); + for (i = 0; i < n; i++) { x += dx; - ss = dXSdx_3ph(x,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } + ss = dXSdx_3ph (x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } } - } - // security - *xsDiffMax *= 1.01; - - return 0; -}; - -double dXSdx_1ph(double x, double E, struct IncoherentPhonon_physics_storage_struct *data) -{ - double Erat = E/(data->Emax); - double u = Erat*(1.0-x*x); - if(fabs(u)>1) { return 0; } - double Fp = interpFunc(u,data->nF1,data->u1,data->F1); - if(isnan(Fp)) { - fprintf(data->filep,"dXSdx_1ph: F1 not interpolated\n"); - exit(1); - } - double alpha = Erat*(data->mRat)*(data->g0); - double ang = angularIntegral_p_phonon(1,alpha,x); - return x*Fp*ang; -}; - -double dXSdx_2ph(double x, double E, struct IncoherentPhonon_physics_storage_struct *data) -{ - double Erat = E/(data->Emax); - double u = Erat*(1.0-x*x); - if(fabs(u)>2) { return 0; } - double Fp = interpFunc(u,data->nF2,data->u2,data->F2); - if(isnan(Fp)) { - fprintf(data->filep,"dXSdx_2ph: F2 not interpolated\n"); - exit(1); - } - double alpha = Erat*(data->mRat)*(data->g0); - double ang = angularIntegral_p_phonon(2,alpha,x); - return x*Fp*ang; -}; - -double dXSdx_3ph(double x, double E, struct IncoherentPhonon_physics_storage_struct *data) -{ - double Erat = E/(data->Emax); - double u = Erat*(1.0-x*x); - if(fabs(u)>3) { return 0; } - double Fp = interpFunc(u,data->nF3,data->u3,data->F3); - if(isnan(Fp)) { - fprintf(data->filep,"dXSdx_3ph: F3 not interpolated\n"); - exit(1); - } - double alpha = Erat*(data->mRat)*(data->g0); - double ang = angularIntegral_p_phonon(3,alpha,x); - return x*Fp*ang; -}; - -double angularIntegral_p_phonon(int p, double alpha, double x) -{ - int l; - double pol, term, ang; - double ym = alpha*pow(1.0-x,2); - double yp = alpha*pow(1.0+x,2); - pol = 1; - term = 1; - for(l=1;l<=p;l++) { - term *= ym/l; - pol += term; - } - ang = exp(-ym)*pol; - // - pol = 1; - term = 1; - for(l=1;l<=p;l++) { - term *= yp/l; - pol += term; - } - ang -= exp(-yp)*pol; - - return ang; -}; - -double totXS_1ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, n; - double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; - double E = KS2E*kabs*kabs; - double Erat = E/(data->Emax); - double alpha = Erat*(data->mRat)*(data->g0); - - n = 10000; - if(Erat>1.0) { xmin = sqrt(1.0 - 1.0/Erat); } else { xmin = 0; } - xmax = sqrt(1.0 + 1.0/Erat); - dx = (xmax-xmin)/n; - - x = xmin; - u = Erat*(1.0-x*x); - Fp = interpFunc(u,data->nF1,data->u1,data->F1); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_1ph: F1 not interpolated first\n"); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(1,alpha,x); - ss = 0.5*f; - for(i=1;inF1,data->u1,data->F1); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_1ph: F1 not interpolated i=%d\n",i); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(1,alpha,x); - ss += f; - } - x = xmax; - u = Erat*(1.0-x*x); - Fp = interpFunc(u,data->nF1,data->u1,data->F1); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_1ph: F1 not interpolated last\n"); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(1,alpha,x); - ss += 0.5*f; - - ss *= dx; - - ss *= (data->sigmaCoh+data->sigmaInc)/(2.*(data->mRat)*(data->g0)); - - return ss; -}; - -double totXS_2ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, n; - double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; - double E = KS2E*kabs*kabs; - double Erat = E/(data->Emax); - double alpha = Erat*(data->mRat)*(data->g0); - - n = 20000; - if(Erat>2.0) { xmin = sqrt(1.0 - 2.0/Erat); } else { xmin = 0; } - xmax = sqrt(1.0 + 2.0/Erat); - dx = (xmax-xmin)/n; - - x = xmin; - u =Erat*(1.0-x*x); - Fp = interpFunc(u,data->nF2,data->u2,data->F2); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_2ph: F2 not interpolated first\n"); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(2,alpha,x); - ss = 0.5*f; - for(i=1;inF2,data->u2,data->F2); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_2ph: F2 not interpolated i=%d\n",i); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(2,alpha,x); - ss += f; - } - x = xmax; - u =Erat*(1.0-x*x); - Fp = interpFunc(u,data->nF2,data->u2,data->F2); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_2ph: F2 not interpolated last\n"); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(2,alpha,x); - ss += 0.5*f; - - ss *= dx; - - ss *= (data->sigmaCoh+data->sigmaInc)/(2.*(data->mRat)*(data->g0)); - - return ss; -}; - -double totXS_3ph(double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, n; - double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; - double E = KS2E*kabs*kabs; - double Erat = E/(data->Emax); - double alpha = Erat*(data->mRat)*(data->g0); - - n = 30000; - if(Erat>3.0) { xmin = sqrt(1.0-3.0/Erat); } else { xmin = 0; } - xmax = sqrt(1.0 + 3.0/Erat); - dx = (xmax-xmin)/n; - - x = xmin; - u =Erat*(1.0-x*x); - Fp = interpFunc(u,data->nF3,data->u3,data->F3); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_3ph: F3 not interpolated first u=%f\n",u); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(3,alpha,x); - ss = 0.5*f; - for(i=1;inF3,data->u3,data->F3); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_3ph: F3 not interpolated i=%d\n",i); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(3,alpha,x); - ss += f; - } - x = xmax; - u =Erat*(1.0-x*x); - Fp = interpFunc(u,data->nF3,data->u3,data->F3); - if(isnan(Fp)) { - fprintf(data->filep,"totXS_3ph: F3 not interpolated last\n"); - exit(1); - } - f = x*Fp*angularIntegral_p_phonon(3,alpha,x); - ss += 0.5*f; - - ss *= dx; - - ss *= (data->sigmaCoh+data->sigmaInc)/(2.*(data->mRat)*(data->g0)); - - return ss; -}; - -void computeFs(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - double du; - FILE *filep; - - // g0 should have been computed in setParams - if(data->g0==0) { data->g0 = Gt(0,data); } - - // F1 - filep = fopen("F1.txt","r"); - if(filep!=NULL) { - fscanf(filep,"%d",&(data->nF1)); - data->u1 = (double *)malloc((data->nF1)*sizeof(double)); - data->F1 = (double *)malloc((data->nF1)*sizeof(double)); - for(i=0;inF1;i++) { - fscanf(filep,"%lf %lf",data->u1+i,data->F1+i); + ss = dXSdx_3ph (xmax, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = xmax; } - fclose(filep); - } else { - // compute - data->nF1 = 1000; - data->u1 = (double *)malloc((data->nF1+1)*sizeof(double)); - data->F1 = (double *)malloc((data->nF1+1)*sizeof(double)); - du = 2./(data->nF1); - data->nF1++; - filep = fopen("F1.txt","a"); - fprintf(filep,"%d\n",data->nF1); - for(i=0;inF1;i++) { - (data->u1)[i] = -1.0 + i*du; - //fprintf(data->filep,"F1: %d %d %f\n",i,data->nF1,(data->u1)[i]); - (data->F1)[i] = F1((data->u1)[i],data); - fprintf(filep,"%f %.6e\n",(data->u1)[i],(data->F1)[i]); - fflush(filep); + // refine + if (*xm > 0 && *xm < xmax) { + xmax = *xm + dx; + x = *xm - dx; + dx /= 100; + *xm = x; + *xsDiffMax = dXSdx_3ph (x, E, data); + for (i = 0; i < 200; i++) { + x += dx; + ss = dXSdx_3ph (x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } + } } - fclose(filep); - } + // security + *xsDiffMax *= 1.01; + + return 0; + }; + + double + dXSdx_1ph (double x, double E, struct IncoherentPhonon_physics_storage_struct* data) { + double Erat = E / (data->Emax); + double u = Erat * (1.0 - x * x); + if (fabs (u) > 1) { + return 0; + } + double Fp = interpFunc (u, data->nF1, data->u1, data->F1); + if (isnan (Fp)) { + fprintf (data->filep, "dXSdx_1ph: F1 not interpolated\n"); + exit (1); + } + double alpha = Erat * (data->mRat) * (data->g0); + double ang = angularIntegral_p_phonon (1, alpha, x); + return x * Fp * ang; + }; + + double + dXSdx_2ph (double x, double E, struct IncoherentPhonon_physics_storage_struct* data) { + double Erat = E / (data->Emax); + double u = Erat * (1.0 - x * x); + if (fabs (u) > 2) { + return 0; + } + double Fp = interpFunc (u, data->nF2, data->u2, data->F2); + if (isnan (Fp)) { + fprintf (data->filep, "dXSdx_2ph: F2 not interpolated\n"); + exit (1); + } + double alpha = Erat * (data->mRat) * (data->g0); + double ang = angularIntegral_p_phonon (2, alpha, x); + return x * Fp * ang; + }; + + double + dXSdx_3ph (double x, double E, struct IncoherentPhonon_physics_storage_struct* data) { + double Erat = E / (data->Emax); + double u = Erat * (1.0 - x * x); + if (fabs (u) > 3) { + return 0; + } + double Fp = interpFunc (u, data->nF3, data->u3, data->F3); + if (isnan (Fp)) { + fprintf (data->filep, "dXSdx_3ph: F3 not interpolated\n"); + exit (1); + } + double alpha = Erat * (data->mRat) * (data->g0); + double ang = angularIntegral_p_phonon (3, alpha, x); + return x * Fp * ang; + }; + + double + angularIntegral_p_phonon (int p, double alpha, double x) { + int l; + double pol, term, ang; + double ym = alpha * pow (1.0 - x, 2); + double yp = alpha * pow (1.0 + x, 2); + pol = 1; + term = 1; + for (l = 1; l <= p; l++) { + term *= ym / l; + pol += term; + } + ang = exp (-ym) * pol; + // + pol = 1; + term = 1; + for (l = 1; l <= p; l++) { + term *= yp / l; + pol += term; + } + ang -= exp (-yp) * pol; + + return ang; + }; + + double + totXS_1ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + int i, n; + double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; + double E = KS2E * kabs * kabs; + double Erat = E / (data->Emax); + double alpha = Erat * (data->mRat) * (data->g0); + + n = 10000; + if (Erat > 1.0) { + xmin = sqrt (1.0 - 1.0 / Erat); + } else { + xmin = 0; + } + xmax = sqrt (1.0 + 1.0 / Erat); + dx = (xmax - xmin) / n; + + x = xmin; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF1, data->u1, data->F1); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_1ph: F1 not interpolated first\n"); + exit (1); + } + f = x * Fp * angularIntegral_p_phonon (1, alpha, x); + ss = 0.5 * f; + for (i = 1; i < n; i++) { + x = xmin + i * dx; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF1, data->u1, data->F1); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_1ph: F1 not interpolated i=%d\n", i); + exit (1); + } + f = x * Fp * angularIntegral_p_phonon (1, alpha, x); + ss += f; + } + x = xmax; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF1, data->u1, data->F1); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_1ph: F1 not interpolated last\n"); + exit (1); + } + f = x * Fp * angularIntegral_p_phonon (1, alpha, x); + ss += 0.5 * f; - if(data->nphe_exact==1) { - data->nF2 = 0; - data->u2 = NULL; - data->F2 = NULL; - data->nF3 = 0; - data->u3 = NULL; - data->F3 = NULL; - return; - } + ss *= dx; + + ss *= (data->sigmaCoh + data->sigmaInc) / (2. * (data->mRat) * (data->g0)); + + return ss; + }; - // F2 - filep = fopen("F2.txt","r"); - if(filep!=NULL) { - fscanf(filep,"%d",&(data->nF2)); - data->u2 = (double *)malloc((data->nF2)*sizeof(double)); - data->F2 = (double *)malloc((data->nF2)*sizeof(double)); - for(i=0;inF2;i++) { - fscanf(filep,"%lf %lf",data->u2+i,data->F2+i); + double + totXS_2ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + int i, n; + double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; + double E = KS2E * kabs * kabs; + double Erat = E / (data->Emax); + double alpha = Erat * (data->mRat) * (data->g0); + + n = 20000; + if (Erat > 2.0) { + xmin = sqrt (1.0 - 2.0 / Erat); + } else { + xmin = 0; } - fclose(filep); - } else { - data->nF2 = 200; - data->u2 = (double *)malloc((data->nF2+1)*sizeof(double)); - data->F2 = (double *)malloc((data->nF2+1)*sizeof(double)); - du = 4./(data->nF2); - data->nF2++; - filep = fopen("F2.txt","a"); - fprintf(filep,"%d\n",data->nF2); - for(i=0;inF2;i++) { - (data->u2)[i] = -2.0 + i*du; - //fprintf(data->filep,"F2: %d %d %f\n",i,data->nF2,(data->u2)[i]); - (data->F2)[i] = F2((data->u2)[i],data); - fprintf(filep,"%f %.6e\n",(data->u2)[i],(data->F2)[i]); - fflush(filep); + xmax = sqrt (1.0 + 2.0 / Erat); + dx = (xmax - xmin) / n; + + x = xmin; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF2, data->u2, data->F2); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_2ph: F2 not interpolated first\n"); + exit (1); } - fclose(filep); - } + f = x * Fp * angularIntegral_p_phonon (2, alpha, x); + ss = 0.5 * f; + for (i = 1; i < n; i++) { + x = xmin + i * dx; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF2, data->u2, data->F2); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_2ph: F2 not interpolated i=%d\n", i); + exit (1); + } + f = x * Fp * angularIntegral_p_phonon (2, alpha, x); + ss += f; + } + x = xmax; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF2, data->u2, data->F2); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_2ph: F2 not interpolated last\n"); + exit (1); + } + f = x * Fp * angularIntegral_p_phonon (2, alpha, x); + ss += 0.5 * f; - if(data->nphe_exact==2) { - data->nF3 = 0; - data->u3 = NULL; - data->F3 = NULL; - return; - } + ss *= dx; + + ss *= (data->sigmaCoh + data->sigmaInc) / (2. * (data->mRat) * (data->g0)); + + return ss; + }; + + double + totXS_3ph (double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + int i, n; + double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; + double E = KS2E * kabs * kabs; + double Erat = E / (data->Emax); + double alpha = Erat * (data->mRat) * (data->g0); - // F3 - filep = fopen("F3.txt","r"); - if(filep!=NULL) { - fscanf(filep,"%d",&(data->nF3)); - data->u3 = (double *)malloc((data->nF3)*sizeof(double)); - data->F3 = (double *)malloc((data->nF3)*sizeof(double)); - for(i=0;inF3;i++) { - fscanf(filep,"%lf %lf",data->u3+i,data->F3+i); + n = 30000; + if (Erat > 3.0) { + xmin = sqrt (1.0 - 3.0 / Erat); + } else { + xmin = 0; } - fclose(filep); - } else { - data->nF3 = 100; - data->u3 = (double *)malloc((data->nF3+1)*sizeof(double)); - data->F3 = (double *)malloc((data->nF3+1)*sizeof(double)); - du = 6./(data->nF3); - data->nF3++; - filep = fopen("F3.txt","a"); - fprintf(filep,"%d\n",data->nF3); - for(i=0;inF3;i++) { - (data->u3)[i] = -3.0 + i*du; - //fprintf(data->filep,"F3: %d %d %f\n",i,data->nF3,(data->u3)[i]); - (data->F3)[i] = F3((data->u3)[i],data); - fprintf(filep,"%f %.6e\n",(data->u3)[i],(data->F3)[i]); - fflush(filep); + xmax = sqrt (1.0 + 3.0 / Erat); + dx = (xmax - xmin) / n; + + x = xmin; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF3, data->u3, data->F3); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_3ph: F3 not interpolated first u=%f\n", u); + exit (1); } - fclose(filep); - } -}; - -double Gu(double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - double E = u*data->Emax; - double x = E/data->kBT; - if(fabs(u)<1.0e-7) { return (data->dosPar)*(data->Emax)*(data->Emax)*(data->kBT); } // esto esta bien - return (data->Emax)*dos(E,data)*bose(x)/u; -}; - -double bose(double x) -{ - return 1.0/(exp(x)-1.0); -}; - -double F1(double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - return Gu(-u,data)/(data->g0); -}; - -double F2(double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - return quadF2(u,data); -}; - -double F3(double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - return quadF3(u,data); -}; - -double F2int(double u, double u1, struct IncoherentPhonon_physics_storage_struct *data) -{ - return Gu(u1,data)*Gu(-u-u1,data)/pow(data->g0,2); -}; - -double F3int(double u, double u1, double u2, struct IncoherentPhonon_physics_storage_struct *data) -{ - return Gu(u1,data)*Gu(u2,data)*Gu(-u-u1-u2,data)/pow(data->g0,3); -}; - -double quadF2(double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - int n; - double umin = -1.0; - double umax = 1.0; - double g1, g2; - double tol = data->tolQuadratureFs; - - n = 100; - g1 = trapezF2(u,n,umin,umax,data); - n = 200; - g2 = trapezF2(u,n,umin,umax,data); - while(nnF3, data->u3, data->F3); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_3ph: F3 not interpolated i=%d\n", i); + exit (1); + } + f = x * Fp * angularIntegral_p_phonon (3, alpha, x); + ss += f; + } + x = xmax; + u = Erat * (1.0 - x * x); + Fp = interpFunc (u, data->nF3, data->u3, data->F3); + if (isnan (Fp)) { + fprintf (data->filep, "totXS_3ph: F3 not interpolated last\n"); + exit (1); + } + f = x * Fp * angularIntegral_p_phonon (3, alpha, x); + ss += 0.5 * f; - fprintf(data->filep,"quadF2: not converged\n"); - fprintf(data->filep,"%f %d %.6e %.6e %.16e\n",u,n,g1,g2,g2-g1); - - return -sqrt(-1.0); -}; + ss *= dx; -double trapezF2(double u, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - double u1, du1, hdu1, s, f1, f2; + ss *= (data->sigmaCoh + data->sigmaInc) / (2. * (data->mRat) * (data->g0)); - if(n<=0) { - fprintf(data->filep,"trapezF2: invalid n = %d\n",n); - exit(1); - } + return ss; + }; - du1 = (umax-umin)/n; - hdu1 = 0.5*du1; - - s = 0; - u1 = umin; - f1 = F2int(u,u1,data); - for(i=1;i<=n;i++) { - u1 += du1; - f2 = F2int(u,u1,data); - s += hdu1*(f1+f2); - f1 = f2; - } + void + computeFs (struct IncoherentPhonon_physics_storage_struct* data) { + int i; + double du; + FILE* filep; - return s; -}; - -double quadF3(double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - int n; - double umin = -1.0; - double umax = 1.0; - double g1, g2; - double tol = data->tolQuadratureFs; - - n = 100; - g1 = trapezF3(u,n,umin,umax,data); - n = 200; - g2 = trapezF3(u,n,umin,umax,data); - while(ng0 == 0) { + data->g0 = Gt (0, data); + } - printf("quadF3: not converged\n"); - printf("%f %d %.6e %.6e %.16e\n",u,n,g1,g2,g2-g1); - - return -sqrt(-1.0); -}; + // F1 + filep = fopen ("F1.txt", "r"); + if (filep != NULL) { + fscanf (filep, "%d", &(data->nF1)); + data->u1 = (double*)malloc ((data->nF1) * sizeof (double)); + data->F1 = (double*)malloc ((data->nF1) * sizeof (double)); + for (i = 0; i < data->nF1; i++) { + fscanf (filep, "%lf %lf", data->u1 + i, data->F1 + i); + } + fclose (filep); + } else { + // compute + data->nF1 = 1000; + data->u1 = (double*)malloc ((data->nF1 + 1) * sizeof (double)); + data->F1 = (double*)malloc ((data->nF1 + 1) * sizeof (double)); + du = 2. / (data->nF1); + data->nF1++; + filep = fopen ("F1.txt", "a"); + fprintf (filep, "%d\n", data->nF1); + for (i = 0; i < data->nF1; i++) { + (data->u1)[i] = -1.0 + i * du; + // fprintf(data->filep,"F1: %d %d %f\n",i,data->nF1,(data->u1)[i]); + (data->F1)[i] = F1 ((data->u1)[i], data); + fprintf (filep, "%f %.6e\n", (data->u1)[i], (data->F1)[i]); + fflush (filep); + } + fclose (filep); + } -double trapezF3(double u, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - double u1, du1, hdu1, s, f1, f2; + if (data->nphe_exact == 1) { + data->nF2 = 0; + data->u2 = NULL; + data->F2 = NULL; + data->nF3 = 0; + data->u3 = NULL; + data->F3 = NULL; + return; + } - if(n<=0) { - printf("trapezF3: invalid n = %d\n",n); - exit(1); - } + // F2 + filep = fopen ("F2.txt", "r"); + if (filep != NULL) { + fscanf (filep, "%d", &(data->nF2)); + data->u2 = (double*)malloc ((data->nF2) * sizeof (double)); + data->F2 = (double*)malloc ((data->nF2) * sizeof (double)); + for (i = 0; i < data->nF2; i++) { + fscanf (filep, "%lf %lf", data->u2 + i, data->F2 + i); + } + fclose (filep); + } else { + data->nF2 = 200; + data->u2 = (double*)malloc ((data->nF2 + 1) * sizeof (double)); + data->F2 = (double*)malloc ((data->nF2 + 1) * sizeof (double)); + du = 4. / (data->nF2); + data->nF2++; + filep = fopen ("F2.txt", "a"); + fprintf (filep, "%d\n", data->nF2); + for (i = 0; i < data->nF2; i++) { + (data->u2)[i] = -2.0 + i * du; + // fprintf(data->filep,"F2: %d %d %f\n",i,data->nF2,(data->u2)[i]); + (data->F2)[i] = F2 ((data->u2)[i], data); + fprintf (filep, "%f %.6e\n", (data->u2)[i], (data->F2)[i]); + fflush (filep); + } + fclose (filep); + } - du1 = (umax-umin)/n; - hdu1 = 0.5*du1; - - s = 0; - u1 = umin; - f1 = quadF3u2(u,u1,data); - for(i=1;i<=n;i++) { - u1 += du1; - f2 = quadF3u2(u,u1,data); - s += hdu1*(f1+f2); - f1 = f2; - } + if (data->nphe_exact == 2) { + data->nF3 = 0; + data->u3 = NULL; + data->F3 = NULL; + return; + } - return s; -}; - -double quadF3u2(double u, double u1, struct IncoherentPhonon_physics_storage_struct *data) -{ - int n; - double umin = -1.0; - double umax = 1.0; - double g1, g2; - double tol = data->tolQuadratureFs; - - n = 100; - g1 = trapezF3u2(u,u1,n,umin,umax,data); - n = 200; - g2 = trapezF3u2(u,u1,n,umin,umax,data); - while(nnF3)); + data->u3 = (double*)malloc ((data->nF3) * sizeof (double)); + data->F3 = (double*)malloc ((data->nF3) * sizeof (double)); + for (i = 0; i < data->nF3; i++) { + fscanf (filep, "%lf %lf", data->u3 + i, data->F3 + i); + } + fclose (filep); + } else { + data->nF3 = 100; + data->u3 = (double*)malloc ((data->nF3 + 1) * sizeof (double)); + data->F3 = (double*)malloc ((data->nF3 + 1) * sizeof (double)); + du = 6. / (data->nF3); + data->nF3++; + filep = fopen ("F3.txt", "a"); + fprintf (filep, "%d\n", data->nF3); + for (i = 0; i < data->nF3; i++) { + (data->u3)[i] = -3.0 + i * du; + // fprintf(data->filep,"F3: %d %d %f\n",i,data->nF3,(data->u3)[i]); + (data->F3)[i] = F3 ((data->u3)[i], data); + fprintf (filep, "%f %.6e\n", (data->u3)[i], (data->F3)[i]); + fflush (filep); + } + fclose (filep); + } + }; + + double + Gu (double u, struct IncoherentPhonon_physics_storage_struct* data) { + double E = u * data->Emax; + double x = E / data->kBT; + if (fabs (u) < 1.0e-7) { + return (data->dosPar) * (data->Emax) * (data->Emax) * (data->kBT); + } // esto esta bien + return (data->Emax) * dos (E, data) * bose (x) / u; + }; + + double + bose (double x) { + return 1.0 / (exp (x) - 1.0); + }; + + double + F1 (double u, struct IncoherentPhonon_physics_storage_struct* data) { + return Gu (-u, data) / (data->g0); + }; + + double + F2 (double u, struct IncoherentPhonon_physics_storage_struct* data) { + return quadF2 (u, data); + }; + + double + F3 (double u, struct IncoherentPhonon_physics_storage_struct* data) { + return quadF3 (u, data); + }; + + double + F2int (double u, double u1, struct IncoherentPhonon_physics_storage_struct* data) { + return Gu (u1, data) * Gu (-u - u1, data) / pow (data->g0, 2); + }; + + double + F3int (double u, double u1, double u2, struct IncoherentPhonon_physics_storage_struct* data) { + return Gu (u1, data) * Gu (u2, data) * Gu (-u - u1 - u2, data) / pow (data->g0, 3); + }; + + double + quadF2 (double u, struct IncoherentPhonon_physics_storage_struct* data) { + int n; + double umin = -1.0; + double umax = 1.0; + double g1, g2; + double tol = data->tolQuadratureFs; + + n = 100; + g1 = trapezF2 (u, n, umin, umax, data); + n = 200; + g2 = trapezF2 (u, n, umin, umax, data); + while (n < nFCmax) { + if (fabs (g1 - g2) < tol) { + return g2; + } + n *= 2; + g1 = g2; + g2 = trapezF2 (u, n, umin, umax, data); + } - printf("quadF3u2: not converged\n"); - printf("%f %f %d %.6e %.6e %.16e\n",u,u1,n,g1,g2,g2-g1); - - return -sqrt(-1.0); -}; + fprintf (data->filep, "quadF2: not converged\n"); + fprintf (data->filep, "%f %d %.6e %.6e %.16e\n", u, n, g1, g2, g2 - g1); -double trapezF3u2(double u, double u1, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - double u2, du2, hdu2, s, f1, f2; + return -sqrt (-1.0); + }; - if(n<=0) { - printf("trapezF3u2: invalid n = %d\n",n); - exit(1); - } + double + trapezF2 (double u, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct* data) { + int i; + double u1, du1, hdu1, s, f1, f2; - du2 = (umax-umin)/n; - hdu2 = 0.5*du2; - - s = 0; - u2 = umin; - f1 = F3int(u,u1,u2,data); - for(i=1;i<=n;i++) { - u2 += du2; - f2 = F3int(u,u1,u2,data); - s += hdu2*(f1+f2); - f1 = f2; - } + if (n <= 0) { + fprintf (data->filep, "trapezF2: invalid n = %d\n", n); + exit (1); + } - return s; -}; - -//Exact computation of Fp (used only for tests) -void computeFps(int pmax, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, p, np1, np2; - double *u1, *Fp1, *u2, *Fp2; - double umin, umax, du; - char fn[500]; - FILE *filep; - - np1 = 1000; - u1 = (double *)malloc((np1+1)*sizeof(double)); - Fp1 = (double *)malloc((np1+1)*sizeof(double)); - umin = -1.0; - umax = 1.0; - du = (umax-umin)/np1; - for(i=0;itolQuadratureFs; + + n = 100; + g1 = trapezF3 (u, n, umin, umax, data); + n = 200; + g2 = trapezF3 (u, n, umin, umax, data); + while (n < nFCmax) { + if (fabs (g1 - g2) < tol) { + return g2; + } + n *= 2; + g1 = g2; + g2 = trapezF3 (u, n, umin, umax, data); + } - umin = up[0]; - umax = up[np-1]; + printf ("quadF3: not converged\n"); + printf ("%f %d %.6e %.6e %.16e\n", u, n, g1, g2, g2 - g1); - tol = 1.0e-6; + return -sqrt (-1.0); + }; - n = 200; - du = (umax-umin)/n; - ui = umin; - s = 0.5*du*F1(u-ui,data)*interpFunc(ui,np,up,Fp); - for(i=1;itolQuadratureFs; + + n = 100; + g1 = trapezF3u2 (u, u1, n, umin, umax, data); + n = 200; + g2 = trapezF3u2 (u, u1, n, umin, umax, data); + while (n < nFCmax) { + if (fabs (g1 - g2) < tol) { + return g2; + } + n *= 2; + g1 = g2; + g2 = trapezF3u2 (u, u1, n, umin, umax, data); + } + + printf ("quadF3u2: not converged\n"); + printf ("%f %f %d %.6e %.6e %.16e\n", u, u1, n, g1, g2, g2 - g1); + + return -sqrt (-1.0); + }; + + double + trapezF3u2 (double u, double u1, int n, double umin, double umax, struct IncoherentPhonon_physics_storage_struct* data) { + int i; + double u2, du2, hdu2, s, f1, f2; + + if (n <= 0) { + printf ("trapezF3u2: invalid n = %d\n", n); + exit (1); + } + + du2 = (umax - umin) / n; + hdu2 = 0.5 * du2; + + s = 0; + u2 = umin; + f1 = F3int (u, u1, u2, data); + for (i = 1; i <= n; i++) { + u2 += du2; + f2 = F3int (u, u1, u2, data); + s += hdu2 * (f1 + f2); + f1 = f2; + } + + return s; + }; + + // Exact computation of Fp (used only for tests) + void + computeFps (int pmax, struct IncoherentPhonon_physics_storage_struct* data) { + int i, p, np1, np2; + double *u1, *Fp1, *u2, *Fp2; + double umin, umax, du; + char fn[500]; + FILE* filep; + + np1 = 1000; + u1 = (double*)malloc ((np1 + 1) * sizeof (double)); + Fp1 = (double*)malloc ((np1 + 1) * sizeof (double)); + umin = -1.0; + umax = 1.0; + du = (umax - umin) / np1; + for (i = 0; i < np1; i++) { + u1[i] = umin + i * du; + Fp1[i] = F1 (u1[i], data); + } + u1[np1] = umax; + Fp1[np1] = F1 (u1[np1], data); + sprintf (fn, "F1_conv.txt"); + filep = fopen (fn, "w"); + fprintf (filep, "%d\n", np1 + 1); + for (i = 0; i <= np1; i++) { + fprintf (filep, "%.16e %.16e\n", u1[i], Fp1[i]); + } + fclose (filep); + + for (p = 2; p <= pmax; p++) { + np2 = p * 1000; + u2 = (double*)malloc ((np2 + 1) * sizeof (double)); + Fp2 = (double*)malloc ((np2 + 1) * sizeof (double)); + umin = -p; + umax = p; + du = (umax - umin) / np2; + sprintf (fn, "F%d_conv.txt", p); + filep = fopen (fn, "w"); + for (i = 0; i < np2; i++) { + u2[i] = umin + i * du; + Fp2[i] = convolution (u2[i], np1 + 1, u1, Fp1, data); + fprintf (filep, "%.16e %.16e\n", u2[i], Fp2[i]); + fflush (filep); + } + u2[np2] = umax; + Fp2[np2] = convolution (u2[np2], np1 + 1, u1, Fp1, data); + fprintf (filep, "%.16e %.16e\n", u2[np2], Fp2[np2]); + fflush (filep); + fclose (filep); + + free (u1); + free (Fp1); + np1 = np2; + u1 = (double*)malloc ((np1 + 1) * sizeof (double)); + Fp1 = (double*)malloc ((np1 + 1) * sizeof (double)); + fprintf (filep, "%d\n", np1 + 1); + for (i = 0; i <= np1; i++) { + u1[i] = u2[i]; + Fp1[i] = Fp2[i]; + } + free (u2); + free (Fp2); + } } - ui = umax; - s += 0.5*du*F1(u-ui,data)*interpFunc(ui,np,up,Fp); - s2 = s; - while(fabs(s2-s1)>tol) { - s1 = s2; + double + convolution (double u, int np, double* up, double* Fp, struct IncoherentPhonon_physics_storage_struct* data) { + int i, n; + double s, s1, s2, tol, umin, umax, du, ui; + + umin = up[0]; + umax = up[np - 1]; + + tol = 1.0e-6; + + n = 200; + du = (umax - umin) / n; + ui = umin; + s = 0.5 * du * F1 (u - ui, data) * interpFunc (ui, np, up, Fp); + for (i = 1; i < n; i++) { + ui += du; + s += du * F1 (u - ui, data) * interpFunc (ui, np, up, Fp); + } + ui = umax; + s += 0.5 * du * F1 (u - ui, data) * interpFunc (ui, np, up, Fp); + s1 = s; + n *= 2; - du = (umax-umin)/n; + du = (umax - umin) / n; ui = umin; - s = 0.5*du*F1(u-ui,data)*interpFunc(ui,np,up,Fp); - for(i=1;iEmax); - double iErat = 1./Erat; - double iEMrat = iErat/(data->mRat); - // rejection method - //for(i=0;inp_u_mph; - double *up = data->u; - double *xs = data->dXSdu_mph; - double umin = up[0]; - double du = (umax - umin); - - if(umax>up[np-1]) { - a1 = (pow(up[np-2],1)*(2*PI-xs[np-1])-pow(up[np-2],2)*(2*PI-xs[np-2]))/(up[np-1]-up[np-2]); - a2 = pow(up[np-2],2)*(2*PI-xs[np-2]) - a1*up[np-2]; - fmax = 2.*PI - a1/umax - a2/(umax*umax); - } else { - fmax = interpFunc(umax,np,up,xs); - } + while (fabs (s2 - s1) > tol) { + s1 = s2; + n *= 2; + du = (umax - umin) / n; + ui = umin; + s = 0.5 * du * F1 (u - ui, data) * interpFunc (ui, np, up, Fp); + for (i = 1; i < n; i++) { + ui += du; + s += du * F1 (u - ui, data) * interpFunc (ui, np, up, Fp); + } + ui = umax; + s += 0.5 * du * F1 (u - ui, data) * interpFunc (ui, np, up, Fp); + s2 = s; + } + + return s2; + } + + ///////////////////////////////////// + // Multi-phonon resummation term /// + ///////////////////////////////////// + + void + sample_Kprime_and_Dir_mph (double kabs, double* x, double* z, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/kabs + // z = cos(theta) + int i; + double u, Q2, x2; + double E = KS2E * kabs * kabs; + double Erat = E / (data->Emax); + double iErat = 1. / Erat; + double iEMrat = iErat / (data->mRat); + // rejection method + // for(i=0;inp_u_mph; + double* up = data->u; + double* xs = data->dXSdu_mph; + double umin = up[0]; + double du = (umax - umin); + + if (umax > up[np - 1]) { + a1 = (pow (up[np - 2], 1) * (2 * PI - xs[np - 1]) - pow (up[np - 2], 2) * (2 * PI - xs[np - 2])) / (up[np - 1] - up[np - 2]); + a2 = pow (up[np - 2], 2) * (2 * PI - xs[np - 2]) - a1 * up[np - 2]; + fmax = 2. * PI - a1 / umax - a2 / (umax * umax); + } else { + fmax = interpFunc (umax, np, up, xs); + } + + // rejection method + // for(i=0;i up[np - 1]) { + f = 2. * PI - a1 / u - a2 / (u * u); + } else { + f = interpFunc (u, np, up, xs); + } + if (f / fmax > rand01 ()) { + return u; + } + } + printf ("sample_u_mph: maxIter reached\n"); + printf ("sample_u_mph: %f %f %f %.6e\n", umin, umax, up[np - 1], fmax); + return -sqrt (-1.0); + }; + + double + sample_Q2_mph (double u, double Erat, struct IncoherentPhonon_physics_storage_struct* data) { + int i; + int np = data->np_u_mph; + double Q2, f, fmax, Q2m; + double x, x2, Q2min, Q2max; + double q1, q2, u1, u2; + double dQ2; + + x2 = 1.0 - u / Erat; + if (x2 < 0) { + return -sqrt (-1.0); + } + x = sqrt (x2); + // the commented lines are wrong. The conservation laws cannot be enforced here: + // the distribution would be biased + // Q2min = Erat*(data->mRat)*pow(1.0-x,2); + // Q2max = Erat*(data->mRat)*pow(1.0+x,2); + + // obtain fmax + if (u < (data->u)[0]) { + fmax = interpFunc (u, np, data->u, data->dXSdQ2_Fmax_mph); + Q2m = interpFunc (u, np, data->u, data->dXSdQ2_Q2max_mph); + fmax = (data->dXSdQ2_Fmax_mph)[data->np_u_mph - 1]; + printf ("uu[0]\n"); + } else if (u > (data->u)[np - 1]) { + u1 = (data->u)[np - 1]; + u2 = (data->u)[np - 2]; + q1 = (data->dXSdQ2_Q2max_mph)[np - 1]; + q2 = (data->dXSdQ2_Q2max_mph)[np - 2]; + Q2m = q1 + (q2 - q1) * ((u - u1) / (u2 - u1)); + Q2min = (data->Q2min)[np - 1]; + q1 = (data->Q2max)[np - 1]; + q2 = (data->Q2max)[np - 2]; + Q2max = q1 + (q2 - q1) * ((u - u1) / (u2 - u1)); + // fmax is overstimated, but it is best like this + fmax = (data->dXSdQ2_Fmax_mph)[data->np_u_mph - 1]; + } else { + fmax = interpFunc (u, np, data->u, data->dXSdQ2_Fmax_mph); + Q2m = interpFunc (u, np, data->u, data->dXSdQ2_Q2max_mph); + Q2min = interpFunc (u, np, data->u, data->Q2min); + Q2max = interpFunc (u, np, data->u, data->Q2max); + } + + if (Q2m < Q2min || Q2m > Q2max) { + // the maximum is attained at the borders + fmax = SFuncInterp (u / Q2min, Q2min, data); + if (isnan (fmax)) { + printf ("isnan Q2min\n"); + printf ("%f %f %.6e\n", u, Q2min, u / Q2min); + exit (1); + } + f = SFuncInterp (u / Q2max, Q2max, data); + if (isnan (f)) { + printf ("isnan Q2max\n"); + printf ("%f %f %.6e\n", u, Q2max, u / Q2max); + exit (1); + } + if (f > fmax) { + fmax = f; + } + } + + dQ2 = Q2max - Q2min; + + // rejection method + // for(i=0;i rand01 ()) { + return Q2; + } + } + printf ("sample_Q2_mph: maxIter reached\n"); + return -sqrt (-1.0); + }; + + void + compute_dXSdu_mph (struct IncoherentPhonon_physics_storage_struct* data) { + int i, np, np1, np2; + double u, du, umin, umax, xs, u1, u2, r; + double xsTol = data->tol_dXSdu_mph; + FILE* filep; + + fprintf (data->filep, "compute_dXSdu_mph: start\n"); + fflush (data->filep); + + // look for umin + u = -1; + xs = quad_dXSdu_mph (u, data); + while (xs > xsTol) { + u -= 1; + xs = quad_dXSdu_mph (u, data); + } + umin = u; + printf ("umin: %f\n", umin); + fflush (stdout); + // look for umax + filep = fopen ("tirar.txt", "w"); + u = 0; + xs = quad_dXSdu_mph (u, data); + while (fabs (xs - 2 * PI) > 0.01) { + u += 1; + xs = quad_dXSdu_mph (u, data); + fprintf (filep, "%f %.6e %.6e\n", u, xs, fabs (xs - 2 * PI)); + fflush (filep); + } + fclose (filep); + umax = u; + printf ("umax: %f\n", umax); + fflush (stdout); + + u = 0; + xs = quad_dXSdu_mph (u, data); + while (xs > 0.01) { + u -= 0.1; + xs = quad_dXSdu_mph (u, data); + } + u1 = u; + printf ("u1: %f\n", u1); + fflush (stdout); + + u = 0; + xs = quad_dXSdu_mph (u, data); + while (fabs (xs - 2 * PI) > 0.08) { + u += 0.1; + xs = quad_dXSdu_mph (u, data); + } + u2 = u; + printf ("u2: %f\n", u2); + fflush (stdout); + + np = data->np_u_mph; + + r = 0.1; // u resolution between u1 and u2 (r*du) + np1 = (int)round (np / (1 - r + r * (umax - umin) / (u2 - u1))); + np2 = np - np1; + + du = (u2 - u1) / (r * np1); - // rejection method - //for(i=0;iup[np-1]) { f = 2.*PI - a1/u - a2/(u*u); } else { f = interpFunc(u,np,up,xs); } - if(f/fmax>rand01()) { return u; } - } - printf("sample_u_mph: maxIter reached\n"); - printf("sample_u_mph: %f %f %f %.6e\n",umin,umax,up[np-1],fmax); - return -sqrt(-1.0); -}; - -double sample_Q2_mph(double u, double Erat, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - int np = data->np_u_mph; - double Q2, f, fmax, Q2m; - double x, x2, Q2min, Q2max; - double q1, q2, u1, u2; - double dQ2; - - x2 = 1.0 - u/Erat; - if(x2<0) { return -sqrt(-1.0); } - x = sqrt(x2); - //the commented lines are wrong. The conservation laws cannot be enforced here: - //the distribution would be biased - //Q2min = Erat*(data->mRat)*pow(1.0-x,2); - //Q2max = Erat*(data->mRat)*pow(1.0+x,2); - - // obtain fmax - if(u<(data->u)[0]) { - fmax = interpFunc(u,np,data->u,data->dXSdQ2_Fmax_mph); - Q2m = interpFunc(u,np,data->u,data->dXSdQ2_Q2max_mph); - fmax = (data->dXSdQ2_Fmax_mph)[data->np_u_mph-1]; - printf("uu[0]\n"); - } else if (u>(data->u)[np-1]) { - u1 = (data->u)[np-1]; - u2 = (data->u)[np-2]; - q1 = (data->dXSdQ2_Q2max_mph)[np-1]; - q2 = (data->dXSdQ2_Q2max_mph)[np-2]; - Q2m = q1 + (q2-q1)*((u-u1)/(u2-u1)); - Q2min = (data->Q2min)[np-1]; - q1 = (data->Q2max)[np-1]; - q2 = (data->Q2max)[np-2]; - Q2max = q1 + (q2-q1)*((u-u1)/(u2-u1)); - // fmax is overstimated, but it is best like this - fmax = (data->dXSdQ2_Fmax_mph)[data->np_u_mph-1]; - } else { - fmax = interpFunc(u,np,data->u,data->dXSdQ2_Fmax_mph); - Q2m = interpFunc(u,np,data->u,data->dXSdQ2_Q2max_mph); - Q2min = interpFunc(u,np,data->u,data->Q2min); - Q2max = interpFunc(u,np,data->u,data->Q2max); - } - - if(Q2mQ2max) { - // the maximum is attained at the borders - fmax = SFuncInterp(u/Q2min,Q2min,data); - if(isnan(fmax)) { - printf("isnan Q2min\n"); - printf("%f %f %.6e\n",u,Q2min,u/Q2min); - exit(1); - } - f = SFuncInterp(u/Q2max,Q2max,data); - if(isnan(f)) { - printf("isnan Q2max\n"); - printf("%f %f %.6e\n",u,Q2max,u/Q2max); - exit(1); - } - if(f>fmax) { fmax = f; } - } + data->u = (double*)malloc (np * sizeof (double)); + data->dXSdu_mph = (double*)malloc (np * sizeof (double)); - dQ2 = Q2max - Q2min; + u = umin; + for (i = 0; i < np; i++) { + xs = quad_dXSdu_mph (u, data); + printf ("i: %d u: %f xs: %.6e\n", i, u, xs); + fflush (stdout); + if (isnan (xs)) { + printf ("u: %f\n", u); + exit (1); + } + (data->u)[i] = u; + (data->dXSdu_mph)[i] = xs; + if ((u < u1 && fabs (u - u1) > r * du) || u >= u2) { + u += du; + } else { + u += r * du; + } + } - // rejection method - //for(i=0;ifilep, "compute_dXSdu_mph: end\n"); + fflush (data->filep); + }; + + double + quad_dXSdu_mph (double u, struct IncoherentPhonon_physics_storage_struct* data) { + int n; + double Q2max, s1, s2, sq1, sq2; + double tsp, g, d2g, H, S; + double xsTol = data->tol_dXSdu_mph; + + if (fabs (u) < 1.0e-9) { + // for u=0 the integral is singular but can be analytically performed + tspInterp (0, &tsp, &g, &d2g, &H, data); + return 2. * PI / sqrt (-2. * d2g * H); } - if(f/fmax>rand01()) { return Q2; } - } - printf("sample_Q2_mph: maxIter reached\n"); - return -sqrt(-1.0); -}; - -void compute_dXSdu_mph(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, np, np1, np2; - double u, du, umin, umax, xs, u1, u2, r; - double xsTol = data->tol_dXSdu_mph; - FILE *filep; - - fprintf(data->filep,"compute_dXSdu_mph: start\n"); - fflush(data->filep); - - // look for umin - u = -1; - xs = quad_dXSdu_mph(u,data); - while(xs>xsTol) { - u -= 1; - xs = quad_dXSdu_mph(u,data); - } - umin = u; - printf("umin: %f\n",umin); - fflush(stdout); - // look for umax - filep = fopen("tirar.txt","w"); - u = 0; - xs = quad_dXSdu_mph(u,data); - while(fabs(xs-2*PI)>0.01) { - u += 1; - xs = quad_dXSdu_mph(u,data); - fprintf(filep,"%f %.6e %.6e\n",u,xs,fabs(xs-2*PI)); - fflush(filep); - } - fclose(filep); - umax = u; - printf("umax: %f\n",umax); - fflush(stdout); - - u = 0; - xs = quad_dXSdu_mph(u,data); - while(xs>0.01) { - u -= 0.1; - xs = quad_dXSdu_mph(u,data); - } - u1 = u; - printf("u1: %f\n",u1); - fflush(stdout); - - u = 0; - xs = quad_dXSdu_mph(u,data); - while(fabs(xs-2*PI)>0.08) { - u += 0.1; - xs = quad_dXSdu_mph(u,data); - } - u2 = u; - printf("u2: %f\n",u2); - fflush(stdout); - - np = data->np_u_mph; - - r = 0.1; // u resolution between u1 and u2 (r*du) - np1 = (int)round(np/(1-r+r*(umax-umin)/(u2-u1))); - np2 = np - np1; - - du = (u2 - u1)/(r*np1); - - data->u = (double *)malloc(np*sizeof(double)); - data->dXSdu_mph = (double *)malloc(np*sizeof(double)); - - u = umin; - for(i=0;iu)[i] = u; - (data->dXSdu_mph)[i] = xs; - if((ur*du) || u>=u2) { u += du; } else { u += r*du; } - } - fprintf(data->filep,"compute_dXSdu_mph: end\n"); - fflush(data->filep); -}; - -double quad_dXSdu_mph(double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - int n; - double Q2max, s1, s2, sq1, sq2; - double tsp, g, d2g, H, S; - double xsTol = data->tol_dXSdu_mph; - - if(fabs(u)<1.0e-9) { - // for u=0 the integral is singular but can be analytically performed - tspInterp(0,&tsp,&g,&d2g,&H,data); - return 2.*PI/sqrt(-2.*d2g*H); - } + Q2max = 10; + S = SFuncInterp (u / Q2max, Q2max, data); + printf ("quad_dXSdu_mph a: %f %.6e %.6e\n", u, Q2max, S); + fflush (stdout); + while (Q2max > 0 && S < 1.0e-9) { + Q2max -= 1; + S = SFuncInterp (u / Q2max, Q2max, data); + printf ("quad_dXSdu_mph c1: %f %.6e %.6e\n", u, Q2max, S); + fflush (stdout); + } + while (S > 1.0e-9) { + Q2max += 1; + S = SFuncInterp (u / Q2max, Q2max, data); + printf ("quad_dXSdu_mph c2: %f %.6e %.6e\n", u, Q2max, S); + fflush (stdout); + } + if (Q2max < 2 * u) { + Q2max = 2 * u; + } + printf ("quad_dXSdu_mph b: %f %.6e %.6e\n", u, Q2max, S); + fflush (stdout); + + n = 100; + s1 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s1)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } - Q2max = 10; - S = SFuncInterp(u/Q2max,Q2max,data); - printf("quad_dXSdu_mph a: %f %.6e %.6e\n",u,Q2max,S); - fflush(stdout); - while(Q2max>0 && S<1.0e-9) { - Q2max -= 1; - S = SFuncInterp(u/Q2max,Q2max,data); - printf("quad_dXSdu_mph c1: %f %.6e %.6e\n",u,Q2max,S); - fflush(stdout); - } - while(S>1.0e-9) { - Q2max += 1; - S = SFuncInterp(u/Q2max,Q2max,data); - printf("quad_dXSdu_mph c2: %f %.6e %.6e\n",u,Q2max,S); - fflush(stdout); - } - if(Q2max<2*u) { Q2max = 2*u; } - printf("quad_dXSdu_mph b: %f %.6e %.6e\n",u,Q2max,S); - fflush(stdout); - - n = 100; - s1 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s1)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } - - n *= 2; - s2 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s2)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } - while(fabs(s2-s1)>xsTol) { n *= 2; - if(n>nFCmax) { - printf("quad_dXSdu_mph a: n>nFCmax for u = %f Q2max = %.6e\n",u,Q2max); - printf("%.6e %.6e %.6e\n",s2,s1,s2-s1); - fflush(stdout); - exit(1); - } - s1 = s2; - s2 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s2)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } - } + s2 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s2)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } + while (fabs (s2 - s1) > xsTol) { + n *= 2; + if (n > nFCmax) { + printf ("quad_dXSdu_mph a: n>nFCmax for u = %f Q2max = %.6e\n", u, Q2max); + printf ("%.6e %.6e %.6e\n", s2, s1, s2 - s1); + fflush (stdout); + exit (1); + } + s1 = s2; + s2 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s2)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } + } - return s2; - - // the following is useless since S<10^-9 for Q2>Q2max - sq1 = s2; - Q2max *= 2; - n = n/2; - s1 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s1)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } - n *= 2; - s2 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s2)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } - while(fabs(s2-s1)>xsTol) { - n *= 2; - if(n>nFCmax) { - printf("quad_dXSdu_mph b: n>nFCmax for u = %f Q2max = %.6e\n",u,Q2max); - printf("%.6e %.6e %.6e\n",s2,s1,s2-s1); - exit(1); - } - s1 = s2; - s2 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s2)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } - } - sq2 = s2; - - while(fabs(sq2-sq1)>xsTol) { + return s2; + + // the following is useless since S<10^-9 for Q2>Q2max + sq1 = s2; Q2max *= 2; - sq1 = sq2; - n = n/2; - s1 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s1)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } + n = n / 2; + s1 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s1)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } n *= 2; - s2 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s2)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } - while(fabs(s2-s1)>xsTol) { + s2 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s2)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } + while (fabs (s2 - s1) > xsTol) { n *= 2; - if(n>nFCmax) { - printf("quad_dXSdu_mph c: n>nFCmax for u = %f Q2max = %.6e\n",u,Q2max); - printf("%.6e %.6e %.6e\n",s2,s1,s2-s1); - exit(1); + if (n > nFCmax) { + printf ("quad_dXSdu_mph b: n>nFCmax for u = %f Q2max = %.6e\n", u, Q2max); + printf ("%.6e %.6e %.6e\n", s2, s1, s2 - s1); + exit (1); } s1 = s2; - s2 = trapez_dXSdu_mph(u,n,Q2max,data); - if(isnan(s2)) { printf("quad_dXSdu_mph nan for u = %f\n",u); return -sqrt(-1.0); } + s2 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s2)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } } sq2 = s2; - } - return sq2; -}; - -double trapez_dXSdu_mph(double u, int n, double Q2max, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - double Q2, dQ2, S, sum, sum0; - FILE *filep; - - //filep = fopen("trapez.txt","w"); - - dQ2 = 1.0/n; - Q2 = dQ2; - sum0 = 0; - for(i=1;inp_u_mph; - FILE *filep; - - fprintf(data->filep,"compute_dXSdQ2_max_mph\n"); - fflush(data->filep); - - pQ2 = (double *)malloc(np*sizeof(double)); - pfm = (double *)malloc(np*sizeof(double)); - Q2min = (double *)malloc(np*sizeof(double)); - Q2max = (double *)malloc(np*sizeof(double)); - - n = 10000; - dQ2 = 50./n; - - filep = fopen("dXSdQ2_mph.txt","w"); - for(i=0;iu)[i]; - pfm[i] = -1.0; - pQ2[i] = 0; - for(j=0;jpfm[i]) { pfm[i] = xs; pQ2[i] = Q2; } - } - fprintf(filep,"\n\n"); - fflush(filep); - // limits - Q2min[i] = 0; - Q2 = pQ2[i]; - while(1) { - Q2 -= dQ2; - if(Q2<=0) { break; } - xs = SFuncInterp(u/Q2,Q2,data); - if(xs/pfm[i] < 1.0e-6) { Q2min[i] = Q2; break; } - } - Q2 = pQ2[i]; - while(1) { + while (fabs (sq2 - sq1) > xsTol) { + Q2max *= 2; + sq1 = sq2; + n = n / 2; + s1 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s1)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } + n *= 2; + s2 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s2)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } + while (fabs (s2 - s1) > xsTol) { + n *= 2; + if (n > nFCmax) { + printf ("quad_dXSdu_mph c: n>nFCmax for u = %f Q2max = %.6e\n", u, Q2max); + printf ("%.6e %.6e %.6e\n", s2, s1, s2 - s1); + exit (1); + } + s1 = s2; + s2 = trapez_dXSdu_mph (u, n, Q2max, data); + if (isnan (s2)) { + printf ("quad_dXSdu_mph nan for u = %f\n", u); + return -sqrt (-1.0); + } + } + sq2 = s2; + } + + return sq2; + }; + + double + trapez_dXSdu_mph (double u, int n, double Q2max, struct IncoherentPhonon_physics_storage_struct* data) { + int i; + double Q2, dQ2, S, sum, sum0; + FILE* filep; + + // filep = fopen("trapez.txt","w"); + + dQ2 = 1.0 / n; + Q2 = dQ2; + sum0 = 0; + for (i = 1; i < n; i++) { + S = SFuncInterp (u / Q2, Q2, data); + // fprintf(filep,"%.6e %.6e %.6e\n",u,Q2,S); + if (isnan (S)) { + return -sqrt (-1.0); + } + sum0 += S; Q2 += dQ2; - xs = SFuncInterp(u/Q2,Q2,data); - if(xs/pfm[i] < 1.0e-6) { Q2max[i] = Q2; break; } } - } - fclose(filep); + Q2 = 1.0; + S = SFuncInterp (u / Q2, Q2, data); + // fprintf(filep,"%.6e %.6e %.6e\n",u,Q2,S); + if (isnan (S)) { + return -sqrt (-1.0); + } + sum0 += 0.5 * S; + sum0 *= dQ2; + + dQ2 = (Q2max - 1.0) / n; + Q2 = 1.0; + S = SFuncInterp (u / Q2, Q2, data); + // fprintf(filep,"%.6e %.6e %.6e\n",u,Q2,S); + if (isnan (S)) { + return -sqrt (-1.0); + } + sum = 0.5 * S; + for (i = 1; i < n; i++) { + Q2 += dQ2; + S = SFuncInterp (u / Q2, Q2, data); + // fprintf(filep,"%.6e %.6e %.6e\n",u,Q2,S); + if (isnan (S)) { + return -sqrt (-1.0); + } + sum += S; + } + Q2 = Q2max; + S = SFuncInterp (u / Q2, Q2, data); + // fprintf(filep,"%.6e %.6e %.6e\n",u,Q2,S); + if (isnan (S)) { + return -sqrt (-1.0); + } + sum += 0.5 * S; + sum *= dQ2; + + // fclose(filep); + + return sum0 + sum; + }; + + void + compute_dXSdQ2_max_mph (struct IncoherentPhonon_physics_storage_struct* data) { + int i, j, n; + double u, xs, Q2, dQ2, fmax; + double *pQ2, *pfm, *Q2min, *Q2max; + int np = data->np_u_mph; + FILE* filep; + + fprintf (data->filep, "compute_dXSdQ2_max_mph\n"); + fflush (data->filep); + + pQ2 = (double*)malloc (np * sizeof (double)); + pfm = (double*)malloc (np * sizeof (double)); + Q2min = (double*)malloc (np * sizeof (double)); + Q2max = (double*)malloc (np * sizeof (double)); + + n = 10000; + dQ2 = 50. / n; + + filep = fopen ("dXSdQ2_mph.txt", "w"); + for (i = 0; i < np; i++) { + u = (data->u)[i]; + pfm[i] = -1.0; + pQ2[i] = 0; + for (j = 0; j < n; j++) { + Q2 = j * dQ2; + xs = SFuncInterp (u / Q2, Q2, data); + fprintf (filep, "%d %f %f %.6e\n", i, u, Q2, xs); + if (xs > pfm[i]) { + pfm[i] = xs; + pQ2[i] = Q2; + } + } + fprintf (filep, "\n\n"); + fflush (filep); + // limits + Q2min[i] = 0; + Q2 = pQ2[i]; + while (1) { + Q2 -= dQ2; + if (Q2 <= 0) { + break; + } + xs = SFuncInterp (u / Q2, Q2, data); + if (xs / pfm[i] < 1.0e-6) { + Q2min[i] = Q2; + break; + } + } + Q2 = pQ2[i]; + while (1) { + Q2 += dQ2; + xs = SFuncInterp (u / Q2, Q2, data); + if (xs / pfm[i] < 1.0e-6) { + Q2max[i] = Q2; + break; + } + } + } + fclose (filep); + + data->dXSdQ2_Q2max_mph = pQ2; + data->dXSdQ2_Fmax_mph = pfm; + data->Q2min = Q2min; + data->Q2max = Q2max; + + fprintf (data->filep, "compute_dXSdQ2_max_mph\n"); + fflush (data->filep); + }; + + void + compute_SQ2_mph (struct IncoherentPhonon_physics_storage_struct* data) { + double Q2, ximin, ximax, tol; + int i, np = data->np_Q2_mph; + double Q2min, Q2max, dQ2; + FILE *filep, *filep2; + + fprintf (data->filep, "compute_SQ2_mph: start\n"); + fflush (data->filep); + + filep = fopen ("SQ2_mph.txt", "r"); + fprintf (data->filep, "compute_SQ2_mph: open done\n"); + fflush (data->filep); + if (filep != NULL) { + fprintf (data->filep, "compute_SQ2_mph: read SQ2\n"); + fflush (data->filep); + fscanf (filep, "%d", &(data->np_Q2_mph)); + data->Q2 = (double*)malloc ((data->np_Q2_mph) * sizeof (double)); + data->SQ2_mph = (double*)malloc ((data->np_Q2_mph) * sizeof (double)); + for (i = 0; i < (data->np_Q2_mph); i++) { + fscanf (filep, "%lf %lf", (data->Q2) + i, (data->SQ2_mph) + i); + } + fclose (filep); + return; + } - data->dXSdQ2_Q2max_mph = pQ2; - data->dXSdQ2_Fmax_mph = pfm; - data->Q2min = Q2min; - data->Q2max = Q2max; + fprintf (data->filep, "compute_SQ2_mph: compute SQ2\n"); + fflush (data->filep); - fprintf(data->filep,"compute_dXSdQ2_max_mph\n"); - fflush(data->filep); -}; + Q2min = 1.0e-6; + Q2max = 10; + dQ2 = (Q2max - Q2min) / np; + fprintf (data->filep, "compute_SQ2_mph: Q2min %f\n", Q2min); + fprintf (data->filep, "compute_SQ2_mph: Q2max %f\n", Q2max); + fprintf (data->filep, "compute_SQ2_mph: dQ2 %f\n", dQ2); + fflush (data->filep); -void compute_SQ2_mph(struct IncoherentPhonon_physics_storage_struct *data) -{ - double Q2, ximin, ximax, tol; - int i, np = data->np_Q2_mph; - double Q2min, Q2max, dQ2; - FILE *filep, *filep2; + data->SQ2_mph = (double*)malloc (np * sizeof (double)); + data->Q2 = (double*)malloc (np * sizeof (double)); - fprintf(data->filep,"compute_SQ2_mph: start\n"); - fflush(data->filep); + tol = 1.0e-6; - filep = fopen("SQ2_mph.txt","r"); - fprintf(data->filep,"compute_SQ2_mph: open done\n"); - fflush(data->filep); - if(filep != NULL) { - fprintf(data->filep,"compute_SQ2_mph: read SQ2\n"); - fflush(data->filep); - fscanf(filep,"%d",&(data->np_Q2_mph)); - data->Q2 = (double *)malloc((data->np_Q2_mph)*sizeof(double)); - data->SQ2_mph = (double *)malloc((data->np_Q2_mph)*sizeof(double)); - for(i=0;i<(data->np_Q2_mph);i++) { - fscanf(filep,"%lf %lf",(data->Q2)+i,(data->SQ2_mph)+i); + filep2 = fopen ("Qlim.txt", "a"); + + filep = fopen ("SQ2_mph_comp.txt", "w"); + fprintf (data->filep, "compute_SQ2_mph: open\n"); + fflush (data->filep); + + fprintf (filep, "%d\n", np); + Q2 = Q2min; + for (i = 0; i < np; i++) { + ximin = -100; + fprintf (filep2, "==========\n"); + fflush (filep2); + if (fabs (SFuncInterp (ximin, Q2, data)) < 1.0e-12) { + while (fabs (SFuncInterp (ximin, Q2, data)) < 1.0e-12) { + fprintf (filep2, "0 %f %f %.16e\n", Q2, ximin, SFuncInterp (ximin, Q2, data)); + fflush (filep2); + ximin += 1; + } + ximin -= 1; + } else { + while (fabs (SFuncInterp (ximin, Q2, data)) < 1.0e-12) { + fprintf (filep2, "0 %f %f %.16e\n", Q2, ximin, SFuncInterp (ximin, Q2, data)); + fflush (filep2); + ximin -= 1; + } + ximin += 1; + } + ximax = 100; + if (fabs (SFuncInterp (ximax, Q2, data)) < 1.0e-12) { + while (fabs (SFuncInterp (ximax, Q2, data)) < 1.0e-12) { + fprintf (filep2, "1 %f %f %.16e\n", Q2, ximax, SFuncInterp (ximax, Q2, data)); + fflush (filep2); + ximax -= 1; + } + ximax += 1; + } else { + while (fabs (SFuncInterp (ximax, Q2, data)) < 1.0e-12) { + fprintf (filep2, "1 %f %f %.16e\n", Q2, ximax, SFuncInterp (ximax, Q2, data)); + fflush (filep2); + ximax += 1; + } + ximax -= 1; + } + (data->Q2)[i] = Q2; + (data->SQ2_mph)[i] = quadFunc (ximin, ximax, Q2, tol, data, SFuncInterp); + fprintf (filep, "%f %.6e\n", (data->Q2)[i], (data->SQ2_mph)[i]); + fflush (filep); + Q2 += dQ2; } - fclose(filep); - return; - } + fclose (filep); + fclose (filep2); + + fprintf (data->filep, "compute_SQ2_mph: end\n"); - fprintf(data->filep,"compute_SQ2_mph: compute SQ2\n"); - fflush(data->filep); - - Q2min = 1.0e-6; - Q2max = 10; - dQ2 = (Q2max - Q2min)/np; - - fprintf(data->filep,"compute_SQ2_mph: Q2min %f\n",Q2min); - fprintf(data->filep,"compute_SQ2_mph: Q2max %f\n",Q2max); - fprintf(data->filep,"compute_SQ2_mph: dQ2 %f\n",dQ2); - fflush(data->filep); - - data->SQ2_mph = (double *)malloc(np*sizeof(double)); - data->Q2 = (double *)malloc(np*sizeof(double)); - - tol = 1.0e-6; - - filep2 = fopen("Qlim.txt","a"); - - filep = fopen("SQ2_mph_comp.txt","w"); - fprintf(data->filep,"compute_SQ2_mph: open\n"); - fflush(data->filep); - - fprintf(filep,"%d\n",np); - Q2 = Q2min; - for(i=0;inp_Q2_mph); + for (i = 0; i < (data->np_Q2_mph); i++) { + fprintf (filep, "%f %.6e\n", (data->Q2)[i], (data->SQ2_mph)[i]); + } + fclose (filep); + }; + + void + compute_dXSdu_dXSdQ2_max_mph (struct IncoherentPhonon_physics_storage_struct* data) { + int i; + FILE* filep; + + filep = fopen ("dXSdu_dXSdQ2_max_mph.txt", "r"); + fprintf (data->filep, "compute_dXSdu_dXSdQ2_max_mph: trying to open dXSdu_dXSdQ2_max_mph.txt\n"); + fflush (data->filep); + if (filep != NULL) { + fprintf (data->filep, "compute_dXSdu_dXSdQ2_max_mph: reading dXSdu_dXSdQ2_max_mph.txt\n"); + fflush (data->filep); + fscanf (filep, "%d", &(data->np_u_mph)); + data->u = (double*)malloc ((data->np_u_mph) * sizeof (double)); + data->dXSdu_mph = (double*)malloc ((data->np_u_mph) * sizeof (double)); + data->Q2min = (double*)malloc ((data->np_u_mph) * sizeof (double)); + data->Q2max = (double*)malloc ((data->np_u_mph) * sizeof (double)); + data->dXSdQ2_Q2max_mph = (double*)malloc ((data->np_u_mph) * sizeof (double)); + data->dXSdQ2_Fmax_mph = (double*)malloc ((data->np_u_mph) * sizeof (double)); + for (i = 0; i < (data->np_u_mph); i++) { + fscanf (filep, "%lf %lf %lf %lf %lf %lf", (data->u) + i, (data->dXSdu_mph) + i, (data->Q2min) + i, (data->Q2max) + i, (data->dXSdQ2_Q2max_mph) + i, + (data->dXSdQ2_Fmax_mph) + i); + } + fclose (filep); } else { - while(fabs(SFuncInterp(ximin,Q2,data))<1.0e-12) { - fprintf(filep2,"0 %f %f %.16e\n",Q2,ximin,SFuncInterp(ximin,Q2,data)); - fflush(filep2); - ximin -= 1; + fprintf (data->filep, "compute_dXSdu_dXSdQ2_max_mph: computing dXSdu_dXSdQ2_max_mph\n"); + fflush (data->filep); + compute_dXSdu_mph (data); + compute_dXSdQ2_max_mph (data); + // write the results + filep = fopen ("dXSdu_dXSdQ2_max_mph.txt", "w"); + fprintf (filep, "%d\n", data->np_u_mph); + for (i = 0; i < (data->np_u_mph); i++) { + fprintf (filep, "%f %.6e %.6e %.6e %.6e %.6e\n", (data->u)[i], (data->dXSdu_mph)[i], (data->Q2min)[i], (data->Q2max)[i], (data->dXSdQ2_Q2max_mph)[i], + (data->dXSdQ2_Fmax_mph)[i]); + fflush (filep); } - ximin += 1; + fclose (filep); } - ximax = 100; - if(fabs(SFuncInterp(ximax,Q2,data))<1.0e-12) { - while(fabs(SFuncInterp(ximax,Q2,data))<1.0e-12) { - fprintf(filep2,"1 %f %f %.16e\n",Q2,ximax,SFuncInterp(ximax,Q2,data)); - fflush(filep2); - ximax -= 1; + }; + + double + totXS_mph (double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/k + // z = cos(theta) + int i, j, nx, nz, num, p; + double E, x, xmin, xmax, dx, z, dz, u, Q2, tsp, Erat, Q2f; + double fac1, fac2, yp, g0, g0Q2; + double S, s1, ss; + double Se, s1e; + double stol = 1.0e-8; + FILE* filep; + + g0 = data->g0; + + E = KS2E * kabs * kabs; + + Erat = E / (data->Emax); + Q2f = Erat * (data->mRat); + + nz = 10000; + dz = 2. / nz; + + // calculate xmin and xmax + dx = 0.01; + x = 1; + num = 0; + while (1) { + u = Erat * (1.0 - x * x); + s1 = 0; + s1e = 0; + for (j = 0; j <= nz; j++) { + z = -1.0 + j * dz; + Q2 = Q2f * (1.0 + x * x - 2.0 * x * z); + if (Q2 < 1.0e-12) { + S = 0; + } else { + S = SFuncInterp (u / Q2, Q2, data); + } + if (isnan (S)) { + printf ("%f %f %.6e %.6e %.6e\n", x, z, u, Q2, S); + exit (1); + } + // normalization + g0Q2 = g0 * Q2; + yp = g0Q2; + fac1 = 1.0 + yp; + for (p = 2; p <= 3; p++) { + yp *= g0Q2 / p; + fac1 += yp; + } + fac1 = 1.0 - exp (-g0Q2) * fac1; + // fac2 = (2.0*PI)/(Q2*interpFunc(Q2,data->np_Q2_mph,data->Q2,data->SQ2_mph)); + fac2 = 1.; + S *= fac1 * fac2; + // + if (j != 0 && j != nz) { + s1 += S; + s1e += Se; + } else { + s1 += 0.5 * S; + s1e += 0.5 * Se; + } } - ximax += 1; - } else { - while(fabs(SFuncInterp(ximax,Q2,data))<1.0e-12) { - fprintf(filep2,"1 %f %f %.16e\n",Q2,ximax,SFuncInterp(ximax,Q2,data)); - fflush(filep2); - ximax += 1; - } - ximax -= 1; - } - (data->Q2)[i] = Q2; - (data->SQ2_mph)[i] = quadFunc(ximin,ximax,Q2,tol,data,SFuncInterp); - fprintf(filep,"%f %.6e\n",(data->Q2)[i],(data->SQ2_mph)[i]); - fflush(filep); - Q2 += dQ2; - } - fclose(filep); - fclose(filep2); - - fprintf(data->filep,"compute_SQ2_mph: end\n"); + if (x * x * dz * s1 < stol) { + xmin = x; + break; + } + x -= dx; + } + x = 1.0 + dx; + while (1) { + u = Erat * (1.0 - x * x); + s1 = 0; + s1e = 0; + for (j = 0; j <= nz; j++) { + z = -1.0 + j * dz; + Q2 = Q2f * (1.0 + x * x - 2.0 * x * z); + if (Q2 < 1.0e-12) { + S = 0; + } else { + S = SFuncInterp (u / Q2, Q2, data); + } + if (isnan (S)) { + printf ("%f %f %.6e %.6e %.6e\n", x, z, u, Q2, S); + exit (1); + } + // normalization + g0Q2 = g0 * Q2; + yp = g0Q2; + fac1 = 1.0 + yp; + for (p = 2; p <= 3; p++) { + yp *= g0Q2 / p; + fac1 += yp; + } + fac1 = 1.0 - exp (-g0Q2) * fac1; + // fac2 = (2.0*PI)/(Q2*interpFunc(Q2,data->np_Q2_mph,data->Q2,data->SQ2_mph)); + fac2 = 1; + S *= fac1 * fac2; + // + if (j != 0 && j != nz) { + s1 += S; + s1e += Se; + } else { + s1 += 0.5 * S; + s1e += 0.5 * Se; + } + } + if (x * x * dz * s1 < stol) { + xmax = x; + break; + } + x += dx; + } - //write the results - filep = fopen("SQ2_mph.txt","w"); - fprintf(filep,"%d\n",data->np_Q2_mph); - for(i=0;i<(data->np_Q2_mph);i++) { - fprintf(filep,"%f %.6e\n",(data->Q2)[i],(data->SQ2_mph)[i]); - } - fclose(filep); -}; - -void compute_dXSdu_dXSdQ2_max_mph(struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - FILE *filep; - - filep = fopen("dXSdu_dXSdQ2_max_mph.txt","r"); - fprintf(data->filep,"compute_dXSdu_dXSdQ2_max_mph: trying to open dXSdu_dXSdQ2_max_mph.txt\n"); - fflush(data->filep); - if(filep != NULL) { - fprintf(data->filep,"compute_dXSdu_dXSdQ2_max_mph: reading dXSdu_dXSdQ2_max_mph.txt\n"); - fflush(data->filep); - fscanf(filep,"%d",&(data->np_u_mph)); - data->u = (double *)malloc((data->np_u_mph)*sizeof(double)); - data->dXSdu_mph = (double *)malloc((data->np_u_mph)*sizeof(double)); - data->Q2min = (double *)malloc((data->np_u_mph)*sizeof(double)); - data->Q2max = (double *)malloc((data->np_u_mph)*sizeof(double)); - data->dXSdQ2_Q2max_mph = (double *)malloc((data->np_u_mph)*sizeof(double)); - data->dXSdQ2_Fmax_mph = (double *)malloc((data->np_u_mph)*sizeof(double)); - for(i=0;i<(data->np_u_mph);i++) { - fscanf(filep,"%lf %lf %lf %lf %lf %lf",(data->u)+i,(data->dXSdu_mph)+i, - (data->Q2min)+i,(data->Q2max)+i, - (data->dXSdQ2_Q2max_mph)+i,(data->dXSdQ2_Fmax_mph)+i); + filep = fopen ("xlim.txt", "a"); + fprintf (filep, "%.6e %.6e %.6e %.6e\n", kabs, E, xmin, xmax); + fclose (filep); + + nx = 10000; + dx = (xmax - xmin) / nx; + + ss = 0; + for (i = 0; i <= nx; i++) { + x = xmin + i * dx; + u = Erat * (1.0 - x * x); + s1 = 0; + for (j = 0; j <= nz; j++) { + z = -1.0 + j * dz; + Q2 = Q2f * (1.0 + x * x - 2.0 * x * z); + if (Q2 < 1.0e-12) { + S = 0; + } else { + S = SFuncInterp (u / Q2, Q2, data); + } + if (isnan (S)) { + printf ("%f %f %.6e %.6e %.6e\n", x, z, u, Q2, S); + exit (1); + } + // normalization + g0Q2 = g0 * Q2; + yp = g0Q2; + fac1 = 1.0 + yp; + for (p = 2; p <= 3; p++) { + yp *= g0Q2 / p; + fac1 += yp; + } + fac1 = 1.0 - exp (-g0Q2) * fac1; + // fac2 = (2.0*PI)/(Q2*interpFunc(Q2,data->np_Q2_mph,data->Q2,data->SQ2_mph)); + fac2 = 1; + S *= fac1 * fac2; + // + if (j != 0 && j != nz) { + s1 += S; + } else { + s1 += 0.5 * S; + } + } + if (i != 0 && i != nx) { + ss += x * x * dz * s1; + } else { + ss += 0.5 * x * x * dz * s1; + } } - fclose(filep); - } else { - fprintf(data->filep,"compute_dXSdu_dXSdQ2_max_mph: computing dXSdu_dXSdQ2_max_mph\n"); - fflush(data->filep); - compute_dXSdu_mph(data); - compute_dXSdQ2_max_mph(data); - //write the results - filep = fopen("dXSdu_dXSdQ2_max_mph.txt","w"); - fprintf(filep,"%d\n",data->np_u_mph); - for(i=0;i<(data->np_u_mph);i++) { - fprintf(filep,"%f %.6e %.6e %.6e %.6e %.6e\n",(data->u)[i],(data->dXSdu_mph)[i], - (data->Q2min)[i],(data->Q2max)[i], - (data->dXSdQ2_Q2max_mph)[i],(data->dXSdQ2_Fmax_mph)[i]); - fflush(filep); + ss *= dx * Erat; + + ss *= (data->sigmaCoh + data->sigmaInc) / (2 * PI); + + return ss; + }; + + double + dXSdxdz_mph (double kabs, double x, double z, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/k + // z = cos(theta) + double xs; + double E = KS2E * kabs * kabs; + double Erat = E / (data->Emax); + double u = Erat * (1.0 - x * x); + double Q2 = Erat * (data->mRat) * (1.0 + x * x - 2.0 * x * z); + if (Q2 < 1.0e-8) { + return 0; } - fclose(filep); - } -}; - -double totXS_mph(double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - // x = kprime/k - // z = cos(theta) - int i, j, nx, nz, num, p; - double E, x, xmin, xmax, dx, z, dz, u, Q2, tsp, Erat, Q2f; - double fac1, fac2, yp, g0, g0Q2; - double S, s1, ss; - double Se, s1e; - double stol = 1.0e-8; - FILE *filep; - - g0 = data->g0; - - E = KS2E*kabs*kabs; - - Erat = E/(data->Emax); - Q2f = Erat*(data->mRat); - - nz = 10000; - dz = 2./nz; - - // calculate xmin and xmax - dx = 0.01; - x = 1; - num = 0; - while(1) { - u = Erat*(1.0 - x*x); - s1 = 0; - s1e = 0; - for(j=0;j<=nz;j++) { - z = -1.0 + j*dz; - Q2 = Q2f*(1.0 + x*x - 2.0*x*z); - if(Q2<1.0e-12) { S = 0; } else { S = SFuncInterp(u/Q2,Q2,data); } - if(isnan(S)) { - printf("%f %f %.6e %.6e %.6e\n",x,z,u,Q2,S); - exit(1); - } - // normalization - g0Q2 = g0*Q2; - yp = g0Q2; - fac1 = 1.0 + yp; - for(p=2;p<=3;p++) { - yp *= g0Q2/p; - fac1 += yp; - } - fac1 = 1.0 - exp(-g0Q2)*fac1; - //fac2 = (2.0*PI)/(Q2*interpFunc(Q2,data->np_Q2_mph,data->Q2,data->SQ2_mph)); - fac2 = 1.; - S *= fac1*fac2; - // - if(j!=0 && j!=nz) { s1 += S; s1e += Se; } else { s1 += 0.5*S; s1e += 0.5*Se; } - } - if(x*x*dz*s1np_Q2_mph,data->Q2,data->SQ2_mph)); - fac2 = 1; - S *= fac1*fac2; - // - if(j!=0 && j!=nz) { s1 += S; s1e += Se; } else { s1 += 0.5*S; s1e += 0.5*Se; } - } - if(x*x*dz*s1np_Q2_mph,data->Q2,data->SQ2_mph)); - fac2 = 1; - S *= fac1*fac2; - // - if(j!=0 && j!=nz) { s1 += S; } else { s1 += 0.5*S; } - } - if(i!=0 && i!=nx) { ss += x*x*dz*s1; } else { ss += 0.5*x*x*dz*s1; } - } - ss *= dx*Erat; - - ss *= (data->sigmaCoh+data->sigmaInc)/(2*PI); - - return ss; -}; - -double dXSdxdz_mph(double kabs, double x, double z, struct IncoherentPhonon_physics_storage_struct *data) -{ - // x = kprime/k - // z = cos(theta) - double xs; - double E = KS2E*kabs*kabs; - double Erat = E/(data->Emax); - double u = Erat*(1.0 - x*x); - double Q2 = Erat*(data->mRat)*(1.0 + x*x - 2.0*x*z); - if(Q2<1.0e-8) { return 0; } - xs = Erat*(x*x/PI)*SFuncInterp(u/Q2,Q2,data); - return xs; -}; - -double dXSdx_mph(double kabs, double x, struct IncoherentPhonon_physics_storage_struct *data) -{ - // x = kprime/k - // z = cos(theta) - int i, n = 200000; - double z, dz, f, ss; - - dz = 2.0/n; - ss = 0; - for(i=1;ig0; + d2g = d2Gt (tsp, data); - tsp = saddlePoint(xi,data); - g = Gt(tsp,data); - g0 = data->g0; - d2g = d2Gt(tsp,data); + S = sqrt (2. * PI / (Q2 * d2g)) * exp (Q2 * (xi * tsp + g - g0)); - S = sqrt(2.*PI/(Q2*d2g))*exp(Q2*(xi*tsp+g-g0)); + return S; + }; - return S; -}; + double + SFuncInterp (double xi, double Q2, struct IncoherentPhonon_physics_storage_struct* data) { + // xi = u/Q2 + double tsp, g, g0, d2g, H, Q2H, Q2g, S; -double SFuncInterp(double xi, double Q2, struct IncoherentPhonon_physics_storage_struct *data) -{ - // xi = u/Q2 - double tsp, g, g0, d2g, H, Q2H, Q2g, S; + if (Q2 <= 0) { + return 0; + } - if(Q2<=0) { return 0; } + g0 = data->g0; + tspInterp (xi, &tsp, &g, &d2g, &H, data); + // it is much better to interpolate the function H than computing it from interpolated values + // H = xi*tsp + g - g0; + if (fabs (xi - 1) < 0.2) { + H = -0.5 * pow (xi - 1, 2) / (data->d2g0) + (data->aH3) * pow (xi - 1, 3) + (data->aH4) * pow (xi - 1, 4); + } - g0 = data->g0; - tspInterp(xi,&tsp,&g,&d2g,&H,data); - // it is much better to interpolate the function H than computing it from interpolated values - //H = xi*tsp + g - g0; - if(fabs(xi-1)<0.2) { - H = -0.5*pow(xi-1,2)/(data->d2g0) + (data->aH3)*pow(xi-1,3) + (data->aH4)*pow(xi-1,4); - } + Q2H = Q2 * H; + if (Q2H < -35) { + return 0; + } - Q2H = Q2*H; - if(Q2H<-35) { return 0; } + if (Q2H > 0) { + fprintf (data->filep, "SFuncInterp: positive Q2H %.6e\n", Q2H); + fprintf (data->filep, "SFuncInterp: %.6e %.6e %.6e %.6e %.6e %.6e\n", Q2, xi, tsp, g, d2g, xi * tsp + g - g0); + } - if(Q2H>0) { - fprintf(data->filep,"SFuncInterp: positive Q2H %.6e\n",Q2H); - fprintf(data->filep,"SFuncInterp: %.6e %.6e %.6e %.6e %.6e %.6e\n",Q2,xi,tsp,g,d2g,xi*tsp+g-g0); - } + S = sqrt (2.0 * PI / (Q2 * d2g)) * exp (Q2H); - S = sqrt(2.0*PI/(Q2*d2g))*exp(Q2H); + // fprintf(data->filep,"%.6e %.6e %.6e %.6e %.6e\n",xi,tsp,g,d2g,H); - //fprintf(data->filep,"%.6e %.6e %.6e %.6e %.6e\n",xi,tsp,g,d2g,H); + if (isnan (S)) { + fprintf (data->filep, "SFuncInterp: nan\n"); + fprintf (data->filep, "%.6e %.6e %.6e %.6e %.6e %.6e\n", Q2, xi, tsp, g, d2g, H); + } - if(isnan(S)) { - fprintf(data->filep,"SFuncInterp: nan\n"); - fprintf(data->filep,"%.6e %.6e %.6e %.6e %.6e %.6e\n",Q2,xi,tsp,g,d2g,H); - } + return S; + }; + + void + tspInterp (double xi, double* tsp, double* g, double* d2g, double* H, struct IncoherentPhonon_physics_storage_struct* data) { + int i, imin, imax; + double a; + int ntsp_ = data->ntsp; + double* xi_ = data->xi; + double* tsp_ = data->tsp; + double* g_ = data->g; + double* d2g_ = data->d2g; + double* H_ = data->H; + double a0, a2, a4, a6, a8, a10; + double b0, b1, b3, b5, b7, b9, b11; + + if (xi < xi_[0]) { + *tsp = tsp_[0] + log (xi / xi_[0]) + 1.5 * log (log (-xi) / log (-xi_[0])); + a = (xi - xi_[0]) / (xi_[1] - xi_[0]); + *g = g_[0] + a * (g_[1] - g_[0]); + *d2g = d2g_[0] + a * (d2g_[1] - d2g_[0]); + *H = H_[0] + a * (H_[1] - H_[0]); + return; + } + if (xi > xi_[ntsp_ - 1]) { + *tsp = tsp_[ntsp_ - 1] - log (xi / xi_[ntsp_ - 1]) - 1.5 * log (log (xi) / log (xi_[ntsp_ - 1])); + a = (xi - xi_[ntsp_ - 1]) / (xi_[ntsp_ - 2] - xi_[ntsp_ - 1]); + *g = g_[ntsp_ - 1] + a * (g_[ntsp_ - 2] - g_[ntsp_ - 1]); + *d2g = d2g_[ntsp_ - 1] + a * (d2g_[ntsp_ - 2] - d2g_[ntsp_ - 1]); + *H = H_[ntsp_ - 1] + a * (H_[ntsp_ - 2] - H_[ntsp_ - 1]); + return; + } - return S; -}; - -void tspInterp(double xi, double *tsp, double *g, double *d2g, double *H, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, imin, imax; - double a; - int ntsp_ = data->ntsp; - double *xi_ = data->xi; - double *tsp_ = data->tsp; - double *g_ = data->g; - double *d2g_ = data->d2g; - double *H_ = data->H; - double a0, a2, a4, a6, a8, a10; - double b0, b1, b3, b5, b7, b9, b11; - - if(xixi_[ntsp_-1]) { - *tsp = tsp_[ntsp_-1] - log(xi/xi_[ntsp_-1]) - 1.5*log(log(xi)/log(xi_[ntsp_-1])); - a = (xi-xi_[ntsp_-1])/(xi_[ntsp_-2]-xi_[ntsp_-1]); - *g = g_[ntsp_-1] + a*(g_[ntsp_-2]-g_[ntsp_-1]); - *d2g = d2g_[ntsp_-1] + a*(d2g_[ntsp_-2]-d2g_[ntsp_-1]); - *H = H_[ntsp_-1] + a*(H_[ntsp_-2]-H_[ntsp_-1]); - return; - } + // linear interpolation otherwise + imin = 0; + imax = ntsp_ - 1; + while (imax - imin > 1) { + i = (imax + imin) / 2; + if (xi < xi_[i]) { + imax = i; + } else { + imin = i; + } + } - // linear interpolation otherwise - imin=0; imax=ntsp_-1; - while(imax-imin>1) { - i = (imax + imin)/2; - if (xi xi_[imax]) { + printf ("bad bracketing: %d %d %f %f %f\n", imin, imax, xi_[imin], xi, xi_[imax]); + exit (1); + } - if(imax==imin) { printf("imax = imin %d %d\n",imin,imax); exit(1); } - if(xixi_[imax]) { - printf("bad bracketing: %d %d %f %f %f\n",imin,imax,xi_[imin],xi,xi_[imax]); - exit(1); - } + a = (xi - xi_[imin]) / (xi_[imax] - xi_[imin]); - a = (xi-xi_[imin])/(xi_[imax]-xi_[imin]); + *tsp = tsp_[imin] + a * (tsp_[imax] - tsp_[imin]); + *g = g_[imin] + a * (g_[imax] - g_[imin]); + *d2g = d2g_[imin] + a * (d2g_[imax] - d2g_[imin]); + *H = H_[imin] + a * (H_[imax] - H_[imin]); + }; - *tsp = tsp_[imin] + a*(tsp_[imax]-tsp_[imin]); - *g = g_[imin] + a*(g_[imax]-g_[imin]); - *d2g = d2g_[imin] + a*(d2g_[imax]-d2g_[imin]); - *H = H_[imin] + a*(H_[imax]-H_[imin]); -}; + double + saddlePoint (double xi, struct IncoherentPhonon_physics_storage_struct* data) { + // solves dgt(tsp) = -z for tsp + double tl, th, tm, y; + double tol; -double saddlePoint(double xi, struct IncoherentPhonon_physics_storage_struct *data) -{ - // solves dgt(tsp) = -z for tsp - double tl, th, tm, y; - double tol; + tol = data->tolSaddlePoint; - tol = data->tolSaddlePoint; + tl = -1; + y = dGt (tl, data) + xi; + while (y > 0) { + tl *= 2; + y = dGt (tl, data) + xi; + } - tl = -1; - y = dGt(tl,data) + xi; - while(y>0) { - tl *= 2; - y = dGt(tl,data) + xi; - } + th = 1; + y = dGt (th, data) + xi; + while (y < 0) { + th *= 2; + y = dGt (th, data) + xi; + } - th = 1; - y = dGt(th,data) + xi; - while(y<0) { - th *= 2; - y = dGt(th,data) + xi; - } + while (th - tl > tol) { + tm = 0.5 * (tl + th); + y = dGt (tm, data) + xi; + if (y < 0) { + tl = tm; + } else { + th = tm; + } + } - while(th-tl>tol) { - tm = 0.5*(tl + th); - y = dGt(tm,data) + xi; - if(y<0) { tl = tm; } else { th = tm; } - } + return 0.5 * (tl + th); + }; + + double + Gt (double ti, struct IncoherentPhonon_physics_storage_struct* data) { + return quad_mp (ti, data, Gtint); + }; + + double + dGt (double ti, struct IncoherentPhonon_physics_storage_struct* data) { + return quad_mp (ti, data, dGtint); + }; + + double + d2Gt (double ti, struct IncoherentPhonon_physics_storage_struct* data) { + return quad_mp (ti, data, d2Gtint); + }; + + double + Gtint (double u, double ti, struct IncoherentPhonon_physics_storage_struct* data) { + double E = u * data->Emax; + double x = E / data->kBT; + if (fabs (u) < 1.0e-7) { + return (data->dosPar) * (data->Emax) * (data->Emax) * (data->kBT); + } + return (data->Emax) * dos (E, data) * bose (x) * exp (u * ti) / u; + }; + + double + dGtint (double u, double ti, struct IncoherentPhonon_physics_storage_struct* data) { + double E = u * data->Emax; + double x = E / data->kBT; + if (fabs (u) < 1.0e-14) { + return (data->dosPar) * (data->Emax) * (data->Emax) * (data->kBT) * u; + } + return (data->Emax) * dos (E, data) * bose (x) * exp (u * ti); + }; + + double + d2Gtint (double u, double ti, struct IncoherentPhonon_physics_storage_struct* data) { + double E = u * data->Emax; + double x = E / data->kBT; + if (fabs (u) < 1.0e-6) { + return (data->dosPar) * (data->Emax) * (data->Emax) * (data->kBT) * u * u; + } + return (data->Emax) * dos (E, data) * bose (x) * u * exp (u * ti); + }; + + double + quad_mp (double ti, struct IncoherentPhonon_physics_storage_struct* data, double (*func) (double, double, struct IncoherentPhonon_physics_storage_struct*)) { + int n; + double umin = -1.0; + double umax = 1.0; + double g1, g2; + double tol, relTol; + + tol = data->tolQuadratureGs; + + n = 100; + g1 = trapez_mp (n, umin, umax, ti, data, func); + n = 200; + g2 = trapez_mp (n, umin, umax, ti, data, func); + while (n < nFCmax) { + if (fabs (0.5 * (g1 + g2)) < 10) { + relTol = tol; + } else { + relTol = tol * fabs (0.5 * (g1 + g2)); + } + if (fabs (g2 - g1) < relTol) { + return g2; + } + n *= 2; + g1 = g2; + g2 = trapez_mp (n, umin, umax, ti, data, func); + } - return 0.5*(tl+th); -}; - -double Gt(double ti, struct IncoherentPhonon_physics_storage_struct *data) -{ - return quad_mp(ti,data,Gtint); -}; - -double dGt(double ti, struct IncoherentPhonon_physics_storage_struct *data) -{ - return quad_mp(ti,data,dGtint); -}; - -double d2Gt(double ti, struct IncoherentPhonon_physics_storage_struct *data) -{ - return quad_mp(ti,data,d2Gtint); -}; - -double Gtint(double u, double ti, struct IncoherentPhonon_physics_storage_struct *data) -{ - double E = u*data->Emax; - double x = E/data->kBT; - if(fabs(u)<1.0e-7) { return (data->dosPar)*(data->Emax)*(data->Emax)*(data->kBT); } - return (data->Emax)*dos(E,data)*bose(x)*exp(u*ti)/u; -}; - -double dGtint(double u, double ti, struct IncoherentPhonon_physics_storage_struct *data) -{ - double E = u*data->Emax; - double x = E/data->kBT; - if(fabs(u)<1.0e-14) { return (data->dosPar)*(data->Emax)*(data->Emax)*(data->kBT)*u; } - return (data->Emax)*dos(E,data)*bose(x)*exp(u*ti); -}; - -double d2Gtint(double u, double ti, struct IncoherentPhonon_physics_storage_struct *data) -{ - double E = u*data->Emax; - double x = E/data->kBT; - if(fabs(u)<1.0e-6) { return (data->dosPar)*(data->Emax)*(data->Emax)*(data->kBT)*u*u; } - return (data->Emax)*dos(E,data)*bose(x)*u*exp(u*ti); -}; - -double quad_mp(double ti, struct IncoherentPhonon_physics_storage_struct *data, - double (*func)(double,double,struct IncoherentPhonon_physics_storage_struct *)) -{ - int n; - double umin = -1.0; - double umax = 1.0; - double g1, g2; - double tol, relTol; - - tol = data->tolQuadratureGs; - - n = 100; - g1 = trapez_mp(n,umin,umax,ti,data,func); - n = 200; - g2 = trapez_mp(n,umin,umax,ti,data,func); - while(nxi1),&(data->xi2)); - fscanf(filep,"%lf",&(data->aH3)); - fscanf(filep,"%lf",&(data->aH4)); - xi_ = (double *)malloc(ntsp*sizeof(double)); - tsp_ = (double *)malloc(ntsp*sizeof(double)); - g_ = (double *)malloc(ntsp*sizeof(double)); - d2g_ = (double *)malloc(ntsp*sizeof(double)); - H_ = (double *)malloc(ntsp*sizeof(double)); - for(i=0;ixi1), &(data->xi2)); + fscanf (filep, "%lf", &(data->aH3)); + fscanf (filep, "%lf", &(data->aH4)); + xi_ = (double*)malloc (ntsp * sizeof (double)); + tsp_ = (double*)malloc (ntsp * sizeof (double)); + g_ = (double*)malloc (ntsp * sizeof (double)); + d2g_ = (double*)malloc (ntsp * sizeof (double)); + H_ = (double*)malloc (ntsp * sizeof (double)); + for (i = 0; i < ntsp; i++) { + fscanf (filep, "%lf %lf %lf %lf %lf", xi_ + i, tsp_ + i, g_ + i, d2g_ + i, H_ + i); + } + fclose (filep); + data->ntsp = ntsp; + data->xi = xi_; + data->tsp = tsp_; + data->g = g_; + data->d2g = d2g_; + data->H = H_; + fprintf (data->filep, "final ntsp: %d\n", data->ntsp); + fprintf (data->filep, "final ximin: %f\n", (data->xi)[0]); + fprintf (data->filep, "final ximax: %f\n", (data->xi)[(data->ntsp) - 1]); + fflush (data->filep); + return; + } + + // computing if necessary + printf ("Computing saddle point solution...\n"); + + // around xi = 1; + xi1 = data->xi1; + tsp1 = saddlePoint (xi1, data); + g1 = Gt (tsp1, data); + d2g1 = d2Gt (tsp1, data); + H1 = xi1 * tsp1 + g1 - (data->g0); + + xi2 = data->xi2; + tsp2 = saddlePoint (xi2, data); + g2 = Gt (tsp2, data); + d2g2 = d2Gt (tsp2, data); + H2 = xi2 * tsp2 + g2 - (data->g0); + + r1 = H1 + (0.5 / (data->d2g0)) * pow (xi1 - 1, 2); + r1 /= pow (xi1 - 1, 3); + r2 = H2 + (0.5 / (data->d2g0)) * pow (xi2 - 1, 2); + r2 /= pow (xi2 - 1, 3); + + data->aH4 = (r1 - r2) / (xi1 - xi2); + data->aH3 = r1 - (xi1 - 1) * data->aH4; + + fprintf (data->filep, "xi1: %f\n", data->xi1); + fprintf (data->filep, "xi2: %f\n", data->xi2); + fprintf (data->filep, "aH3: %f\n", data->aH3); + fprintf (data->filep, "aH4: %f\n", data->aH4); + fflush (data->filep); + + /////////// + + if (ntsp <= 0) { + printf ("computeSaddlePointSol: invalid ntsp %d\n", ntsp); + fprintf (data->filep, "computeSaddlePointSol: invalid ntsp %d\n", ntsp); + exit (1); + } + + dximax = (ximax - ximin) / ntsp; + + xi1 = 0.5; + xi2 = 1.5; + + // count ntsp + ntsp = 0; + xi = ximin; + while (xi < ximax) { + if (!done1 && (fabs (xi - 1) < 0.05 * dximax || (xi - dxi <= 1 && xi >= 1))) { + done1 = 1; + ntsp++; + if (fabs (xi - 1) > 0.05 * dximax) { + continue; /* one point added */ + } + } else if (!doneXi1 && (fabs (xi - data->xi1) < 0.05 * dximax || (xi - dxi <= data->xi1 && xi >= data->xi1))) { + doneXi1 = 1; + ntsp++; + if (fabs (xi - data->xi1) > 0.05 * dximax) { + continue; /* one point added */ + } + } else if (!doneXi2 && (fabs (xi - data->xi2) < 0.05 * dximax || (xi - dxi <= data->xi2 && xi >= data->xi2))) { + doneXi2 = 1; + ntsp++; + if (fabs (xi - data->xi2) > 0.05 * dximax) { + continue; /* one point added */ + } + } else { + ntsp++; + } + if ((xi < xi1 && fabs (xi - xi1) > 1.0e-8) || xi > xi2 || fabs (xi - xi2) < 1.0e-8) { + dxi = dximax; + } else { + dxi = 0.1 * dximax; + } + xi += dxi; + } + if (fabs (xi - ximax) < 1.0e-8) { + ntsp++; + } + + xi_ = (double*)malloc (ntsp * sizeof (double)); + tsp_ = (double*)malloc (ntsp * sizeof (double)); + g_ = (double*)malloc (ntsp * sizeof (double)); + d2g_ = (double*)malloc (ntsp * sizeof (double)); + H_ = (double*)malloc (ntsp * sizeof (double)); + + filep = fopen ("sp.txt", "w"); + fprintf (filep, "%d\n", ntsp); + fprintf (filep, "%f %f\n", data->xi1, data->xi2); + fprintf (filep, "%.16e\n", data->aH3); + fprintf (filep, "%.16e\n", data->aH4); + xi = ximin; + done1 = 0; + doneXi1 = 0; + doneXi2 = 0; + for (i = 0; i < ntsp; i++) { + printf ("%d %d\n", i, ntsp); + if (!done1 && (fabs (xi - 1) < 0.05 * dximax || (xi - dxi <= 1 && xi >= 1))) { + done1 = 1; + xi_[i] = 1; + tsp_[i] = 0; + g_[i] = Gt (tsp_[i], data); + d2g_[i] = d2Gt (tsp_[i], data); + H_[i] = xi_[i] * tsp_[i] + g_[i] - (data->g0); + fprintf (filep, "%.16e %.16e %.16e %.16e %.16e\n", xi_[i], tsp_[i], g_[i], d2g_[i], H_[i]); + fflush (filep); + } else if (!doneXi1 && (fabs (xi - data->xi1) < 0.05 * dximax || (xi - dxi <= data->xi1 && xi >= data->xi1))) { + doneXi1 = 1; + xi_[i] = data->xi1; + tsp_[i] = saddlePoint (xi_[i], data); + g_[i] = Gt (tsp_[i], data); + d2g_[i] = d2Gt (tsp_[i], data); + H_[i] = xi_[i] * tsp_[i] + g_[i] - (data->g0); + fprintf (filep, "%.16e %.16e %.16e %.16e %.16e\n", xi_[i], tsp_[i], g_[i], d2g_[i], H_[i]); + fflush (filep); + } else if (!doneXi2 && (fabs (xi - data->xi2) < 0.05 * dximax || (xi - dxi <= data->xi2 && xi >= data->xi2))) { + doneXi2 = 1; + xi_[i] = data->xi2; + tsp_[i] = saddlePoint (xi_[i], data); + g_[i] = Gt (tsp_[i], data); + d2g_[i] = d2Gt (tsp_[i], data); + H_[i] = xi_[i] * tsp_[i] + g_[i] - (data->g0); + fprintf (filep, "%.16e %.16e %.16e %.16e %.16e\n", xi_[i], tsp_[i], g_[i], d2g_[i], H_[i]); + fflush (filep); + } else { + xi_[i] = xi; + tsp_[i] = saddlePoint (xi_[i], data); + g_[i] = Gt (tsp_[i], data); + d2g_[i] = d2Gt (tsp_[i], data); + H_[i] = xi_[i] * tsp_[i] + g_[i] - (data->g0); + fprintf (filep, "%.16e %.16e %.16e %.16e %.16e\n", xi_[i], tsp_[i], g_[i], d2g_[i], H_[i]); + fflush (filep); + } + if ((xi < xi1 && fabs (xi - xi1) > 1.0e-8) || xi > xi2 || fabs (xi - xi2) < 1.0e-8) { + dxi = dximax; + } else { + dxi = 0.1 * dximax; + } + xi += dxi; + } + fclose (filep); + data->ntsp = ntsp; data->xi = xi_; data->tsp = tsp_; data->g = g_; data->d2g = d2g_; data->H = H_; - fprintf(data->filep,"final ntsp: %d\n",data->ntsp); - fprintf(data->filep,"final ximin: %f\n",(data->xi)[0]); - fprintf(data->filep,"final ximax: %f\n",(data->xi)[(data->ntsp)-1]); - fflush(data->filep); - return; - } - // computing if necessary - printf("Computing saddle point solution...\n"); - - // around xi = 1; - xi1 = data->xi1; - tsp1 = saddlePoint(xi1,data); - g1 = Gt(tsp1,data); - d2g1 = d2Gt(tsp1,data); - H1 = xi1*tsp1 + g1 - (data->g0); - - xi2 = data->xi2; - tsp2 = saddlePoint(xi2,data); - g2 = Gt(tsp2,data); - d2g2 = d2Gt(tsp2,data); - H2 = xi2*tsp2 + g2 - (data->g0); - - r1 = H1 + (0.5/(data->d2g0))*pow(xi1-1,2); - r1 /= pow(xi1-1,3); - r2 = H2 + (0.5/(data->d2g0))*pow(xi2-1,2); - r2 /= pow(xi2-1,3); - - data->aH4 = (r1 -r2)/(xi1 -xi2); - data->aH3 = r1 - (xi1-1)*data->aH4; - - fprintf(data->filep,"xi1: %f\n",data->xi1); - fprintf(data->filep,"xi2: %f\n",data->xi2); - fprintf(data->filep,"aH3: %f\n",data->aH3); - fprintf(data->filep,"aH4: %f\n",data->aH4); - fflush(data->filep); - - /////////// - - if(ntsp<=0) { - printf("computeSaddlePointSol: invalid ntsp %d\n",ntsp); - fprintf(data->filep,"computeSaddlePointSol: invalid ntsp %d\n",ntsp); - exit(1); - } - - dximax = (ximax - ximin)/ntsp; - - xi1 = 0.5; - xi2 = 1.5; - - // count ntsp - ntsp = 0; - xi = ximin; - while(xi= 1)) ) { - done1 = 1; - ntsp++; - if(fabs(xi-1) > 0.05*dximax) { continue; /* one point added */ } - } else if ( !doneXi1 && (fabs(xi-data->xi1)<0.05*dximax || (xi-dxi <= data->xi1 && xi >= data->xi1)) ) { - doneXi1 = 1; - ntsp++; - if(fabs(xi-data->xi1) > 0.05*dximax) { continue; /* one point added */ } - } else if ( !doneXi2 && (fabs(xi-data->xi2)<0.05*dximax || (xi-dxi <= data->xi2 && xi >= data->xi2)) ) { - doneXi2 = 1; - ntsp++; - if(fabs(xi-data->xi2) > 0.05*dximax) { continue; /* one point added */ } + fprintf (data->filep, "final ntsp: %d\n", data->ntsp); + fprintf (data->filep, "final ximin: %f\n", (data->xi)[0]); + fprintf (data->filep, "final ximax: %f\n", (data->xi)[(data->ntsp) - 1]); + fflush (data->filep); + }; + + ///////////////////////////////////////////////////////// + // multiphonon correlation function in gaussian approx // + ///////////////////////////////////////////////////////// + + double + totXS_pph_gauss (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + int i, n; + double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; + double E = KS2E * kabs * kabs; + double Erat = E / (data->Emax); + double alpha = Erat * (data->mRat) * (data->g0); + double g0 = data->g0; + double twosigma2 = 2.0 * p * data->Delta2; + + // In gaussian approx, xmin=0 and xmax=infty. However, the tails are unphysical and we cut them + // at the physical values + // we should renormalize the corresponding Fp by 2*errf(p), so that int_-p^p du Fp(u) = 1; + n = p * 10000; + if (Erat > p) { + xmin = sqrt (1.0 - p / Erat); } else { - ntsp++; - } - if( (xi1.0e-8) || xi>xi2 || fabs(xi-xi2)<1.0e-8) { - dxi = dximax; + xmin = 0; + } + xmax = sqrt (1.0 + p / Erat); + dx = (xmax - xmin) / n; + + x = xmin; + u = Erat * (1.0 - x * x); + Fp = exp (-pow (u - p / g0, 2) / twosigma2); + + f = x * Fp * angularIntegral_p_phonon (p, alpha, x); + ss = 0.5 * f; + for (i = 1; i < n; i++) { + x = xmin + i * dx; + u = Erat * (1.0 - x * x); + Fp = exp (-pow (u - p / g0, 2) / twosigma2); + f = x * Fp * angularIntegral_p_phonon (p, alpha, x); + ss += f; + } + x = xmax; + u = Erat * (1.0 - x * x); + Fp = exp (-pow (u - p / g0, 2) / twosigma2); + f = x * Fp * angularIntegral_p_phonon (p, alpha, x); + ss += 0.5 * f; + + // multiply by all constant factors + ss *= dx; + ss /= sqrt (PI * twosigma2); + ss *= (data->sigmaCoh + data->sigmaInc) / (2. * (data->mRat) * (data->g0)); + + return ss; + }; + + double + sampleKprime_pph_gauss (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/k + int i; + double x, px; + double E = KS2E * kabs * kabs; + double iErat = data->Emax / E; + double pxmax = interpFunc (kabs, data->nxs, data->kabs, data->dXSdx_Fmax_pph_gauss[p]); + // this is a bias since the gaussian has not compact support. But it is a physical bias which + // may correct some defects of the gaussian approximation + double xmax = sqrt (1. + p * iErat); + double xmin, delta_x; + if (iErat < 1. / p) { + xmin = sqrt (1. - p * iErat); } else { - dxi = 0.1*dximax; + xmin = 0; + } + delta_x = xmax - xmin; + FILE* filep; + for (i = 0; i < maxIter; i++) { + x = xmin + delta_x * rand01 (); + px = dXSdx_pph_gauss (p, x, E, data); + if (px > pxmax) { + fprintf (data->filep, "sampleKprime_pph_gauss: p = %d\n", p); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "xmax: %.6e\n", xmax); + fprintf (data->filep, "pxmax: %.6e\n", pxmax); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "px/pxmax: %.6e\n", px / pxmax); + fflush (data->filep); + filep = fopen ("dXSdx_pph_gauss.txt", "w"); + fprintf (filep, "p: %d\n", p); + x = 0; + while (x <= xmax) { + px = dXSdx_pph_gauss (p, x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + exit (1); + } + if (px / pxmax > rand01 ()) { + return x; } - xi += dxi; - } - if(fabs(xi-ximax)<1.0e-8) { ntsp++; } - - xi_ = (double *)malloc(ntsp*sizeof(double)); - tsp_ = (double *)malloc(ntsp*sizeof(double)); - g_ = (double *)malloc(ntsp*sizeof(double)); - d2g_ = (double *)malloc(ntsp*sizeof(double)); - H_ = (double *)malloc(ntsp*sizeof(double)); - - filep = fopen("sp.txt","w"); - fprintf(filep,"%d\n",ntsp); - fprintf(filep,"%f %f\n",data->xi1,data->xi2); - fprintf(filep,"%.16e\n",data->aH3); - fprintf(filep,"%.16e\n",data->aH4); - xi = ximin; - done1 = 0; - doneXi1 = 0; - doneXi2 = 0; - for(i=0;i= 1)) ) { - done1 = 1; - xi_[i] = 1; - tsp_[i] = 0; - g_[i] = Gt(tsp_[i],data); - d2g_[i] = d2Gt(tsp_[i],data); - H_[i] = xi_[i]*tsp_[i] + g_[i] - (data->g0); - fprintf(filep,"%.16e %.16e %.16e %.16e %.16e\n",xi_[i],tsp_[i],g_[i],d2g_[i],H_[i]); - fflush(filep); - } else if ( !doneXi1 && (fabs(xi-data->xi1)<0.05*dximax || (xi-dxi <= data->xi1 && xi >= data->xi1)) ) { - doneXi1 = 1; - xi_[i] = data->xi1; - tsp_[i] = saddlePoint(xi_[i],data); - g_[i] = Gt(tsp_[i],data); - d2g_[i] = d2Gt(tsp_[i],data); - H_[i] = xi_[i]*tsp_[i] + g_[i] - (data->g0); - fprintf(filep,"%.16e %.16e %.16e %.16e %.16e\n",xi_[i],tsp_[i],g_[i],d2g_[i],H_[i]); - fflush(filep); - } else if ( !doneXi2 && (fabs(xi-data->xi2)<0.05*dximax || (xi-dxi <= data->xi2 && xi >= data->xi2)) ) { - doneXi2 = 1; - xi_[i] = data->xi2; - tsp_[i] = saddlePoint(xi_[i],data); - g_[i] = Gt(tsp_[i],data); - d2g_[i] = d2Gt(tsp_[i],data); - H_[i] = xi_[i]*tsp_[i] + g_[i] - (data->g0); - fprintf(filep,"%.16e %.16e %.16e %.16e %.16e\n",xi_[i],tsp_[i],g_[i],d2g_[i],H_[i]); - fflush(filep); - } else { - xi_[i] = xi; - tsp_[i] = saddlePoint(xi_[i],data); - g_[i] = Gt(tsp_[i],data); - d2g_[i] = d2Gt(tsp_[i],data); - H_[i] = xi_[i]*tsp_[i] + g_[i] - (data->g0); - fprintf(filep,"%.16e %.16e %.16e %.16e %.16e\n",xi_[i],tsp_[i],g_[i],d2g_[i],H_[i]); - fflush(filep); - } - if( (xi1.0e-8) || xi>xi2 || fabs(xi-xi2)<1.0e-8) { - dxi = dximax; - } else { - dxi = 0.1*dximax; } - xi += dxi; - } - fclose(filep); - - data->ntsp = ntsp; - data->xi = xi_; - data->tsp = tsp_; - data->g = g_; - data->d2g = d2g_; - data->H = H_; - - fprintf(data->filep,"final ntsp: %d\n",data->ntsp); - fprintf(data->filep,"final ximin: %f\n",(data->xi)[0]); - fprintf(data->filep,"final ximax: %f\n",(data->xi)[(data->ntsp)-1]); - fflush(data->filep); -}; - -///////////////////////////////////////////////////////// -// multiphonon correlation function in gaussian approx // -///////////////////////////////////////////////////////// - -double totXS_pph_gauss(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, n; - double f, ym, yp, u, Fp, ss, x, xmin, xmax, dx; - double E = KS2E*kabs*kabs; - double Erat = E/(data->Emax); - double alpha = Erat*(data->mRat)*(data->g0); - double g0 = data->g0; - double twosigma2 = 2.0*p*data->Delta2; - - //In gaussian approx, xmin=0 and xmax=infty. However, the tails are unphysical and we cut them - //at the physical values - //we should renormalize the corresponding Fp by 2*errf(p), so that int_-p^p du Fp(u) = 1; - n = p*10000; - if(Erat>p) { xmin = sqrt(1.0-p/Erat); } else { xmin = 0; } - xmax = sqrt(1.0 + p/Erat); - dx = (xmax-xmin)/n; - - x = xmin; - u =Erat*(1.0-x*x); - Fp = exp(-pow(u-p/g0,2)/twosigma2); - - f = x*Fp*angularIntegral_p_phonon(p,alpha,x); - ss = 0.5*f; - for(i=1;isigmaCoh+data->sigmaInc)/(2.*(data->mRat)*(data->g0)); - - return ss; -}; - -double sampleKprime_pph_gauss(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - //x = kprime/k - int i; - double x, px; - double E = KS2E*kabs*kabs; - double iErat = data->Emax/E; - double pxmax = interpFunc(kabs,data->nxs,data->kabs,data->dXSdx_Fmax_pph_gauss[p]); - // this is a bias since the gaussian has not compact support. But it is a physical bias which - // may correct some defects of the gaussian approximation - double xmax = sqrt(1.+p*iErat); - double xmin, delta_x; - if(iErat<1./p) { xmin = sqrt(1.-p*iErat); } else { xmin = 0; } - delta_x = xmax - xmin; - FILE *filep; - for(i=0;ipxmax) { - fprintf(data->filep,"sampleKprime_pph_gauss: p = %d\n",p); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"xmax: %.6e\n",xmax); - fprintf(data->filep,"pxmax: %.6e\n",pxmax); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"px/pxmax: %.6e\n",px/pxmax); - fflush(data->filep); - filep = fopen("dXSdx_pph_gauss.txt","w"); - fprintf(filep,"p: %d\n",p); - x = 0; - while(x<=xmax) { - px = dXSdx_pph_gauss(p,x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - exit(1); - } - if(px/pxmax>rand01()) { return x; } - } - //What happens if maxIter is exceeded?? return negative value to control - filep = fopen("dXSdx_pph_gauss_maxIter_exceeded.txt","w"); - fprintf(filep,"p: %d\n",p); - x = 0; - while(x<=xmax) { - px = dXSdx_pph_gauss(p,x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - return -1; -}; - -double dXSdx_pph_gauss(int p, double x, double E, struct IncoherentPhonon_physics_storage_struct *data) -{ - double Erat = E/(data->Emax); - double u = Erat*(1.0-x*x); - if(fabs(u)>p) { return 0; } - double twosigma2 = 2.0*p*data->Delta*data->Delta; - // do not normalize by sqrt(PI*twosigma2), to save time. - double Fp = exp(-pow(u-p/data->g0,2)/twosigma2); - double alpha = Erat*(data->mRat)*(data->g0); - double ang = angularIntegral_p_phonon(p,alpha,x); - return x*Fp*ang; -}; - -int compute_dXSdx_max_pph_gauss(int n, int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax) -{ - int i; - double x, xmax, dx, ss; - double E = KS2E*kabs*kabs; - - // this is a byas since a gaussian has no xmax (is not of compact support) - xmax = sqrt(1.+p*(data->Emax)/E); - dx = xmax/n; - - x = 0; - *xm = 0; - *xsDiffMax = dXSdx_pph_gauss(p,x,E,data); - for(i=0;i(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } - } - ss = dXSdx_pph_gauss(p,xmax,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = xmax; } - // refine - if(*xm>0 && *xm(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } + // What happens if maxIter is exceeded?? return negative value to control + filep = fopen ("dXSdx_pph_gauss_maxIter_exceeded.txt", "w"); + fprintf (filep, "p: %d\n", p); + x = 0; + while (x <= xmax) { + px = dXSdx_pph_gauss (p, x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; } - } - // security (better to overstimate maximum) - *xsDiffMax *= 1.01; - - return 0; -}; - -double Sgauss(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data) -{ - // from Lovesey, p. 164, Eq. (4.247) - int p, pmin, pmax; - double Delta = data->Delta; - double g0 = data->g0; - double x, y, F, hx2, yp; - - x = u/Delta; - y = Q2*g0*exp(-0.5/pow(Delta*g0,2)); - - hx2 = 0.5*x*x; - - pmin = data->nphe + 1; - pmax = data->npmax; - // get y**pmin/pmin! - yp = y; - for(p=2;p<=pmin;p++) { yp *= y/p; } - - F = yp*exp(-hx2/pmin-Q2*g0)/sqrt(pmin); - for(p=pmin+1;p<=pmax;p++) { - yp *= y/p; - F += yp*exp(-hx2/p-Q2*g0)/sqrt(p); - } - F /= sqrt(2.*PI); - - return exp(u/(Delta*Delta*g0))*F/Delta; -} - -void computeEpsilon(struct IncoherentPhonon_physics_storage_struct *data) -{ - double tol = 1.0e-8; - data->epsilon = 1.5*quadFunc(0,1,1.0e99,tol,data,epsilonInt); -} - -double epsilonInt(double u, double v, struct IncoherentPhonon_physics_storage_struct *data) -{ - double E = u*data->Emax; - double x = E/data->kBT; - if(fabs(u)<1.0e-6) { return (data->dosPar)*(data->Emax)*(data->Emax)*(data->kBT)*u*u; } - return (data->Emax)*dos(E,data)*u*(0.5+bose(x)); -} - -/////////////////////////////////////////////// -// multiphonon expansion in SP approximation // -/////////////////////////////////////////////// - -double sampleKprime_pph_sp(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - //x = kprime/k - FILE *filep; - int i; - double x, px; - double E = KS2E*kabs*kabs; - double iErat = data->Emax/E; - double pxmax = interpFunc(kabs,data->nxs,data->kabs,data->dXSdx_Fmax_pph_sp[p]); - double xmax = sqrt(1.+p*iErat); - double xmin, delta_x; - if(iErat<1./p) { xmin = sqrt(1.-p*iErat); } else { xmin = 0; } - delta_x = xmax - xmin; - for(i=0;ipxmax) { - fprintf(data->filep,"sampleKprime_pph_sp: p = %d\n",p); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"xmax: %.6e\n",xmax); - fprintf(data->filep,"pxmax: %.6e\n",pxmax); - fprintf(data->filep,"px: %.6e\n",px); - fprintf(data->filep,"px/pxmax: %.6e\n",px/pxmax); - filep = fopen("dXSdx_pph_sp.txt","w"); - fprintf(filep,"p: %d\n",p); - x = 0; - while(x<=xmax) { - px = dXSdx_pph_sp(p,x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - exit(1); - } - if(px/pxmax>rand01()) { return x; } - } - //What happens if maxIter is exceeded?? return negative value to control - filep = fopen("dXSdx_pph_sp_maxIter_exceeded.txt","w"); - fprintf(filep,"p: %d\n",p); - x = 0; - while(x<=xmax) { - px = dXSdx_pph_sp(p,x,E,data); - fprintf(filep,"%f %.16e %.16e\n",x,px,pxmax); - x += xmax/1000; - } - fclose(filep); - return -1; -}; - -double dXSdx_pph_sp(int p, double x, double E, struct IncoherentPhonon_physics_storage_struct *data) -{ - double Erat = E/(data->Emax); - double u = Erat*(1.0-x*x); - if(fabs(u)>p) { return 0; } - double Fp = Fp_sp(p,u,data); - double alpha = Erat*(data->mRat)*(data->g0); - double ang = angularIntegral_p_phonon(p,alpha,x); - return x*Fp*ang; -}; - -int compute_dXSdx_max_pph_sp(int n, int p, double kabs, - struct IncoherentPhonon_physics_storage_struct *data, double *xm, double *xsDiffMax) -{ - int i; - double x, xmax, dx, ss; - double E = KS2E*kabs*kabs; - - xmax = sqrt(1.+p*(data->Emax)/E); - dx = xmax/n; - - x = 0; - *xm = 0; - *xsDiffMax = dXSdx_pph_sp(p,x,E,data); - for(i=0;i(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } - } - ss = dXSdx_pph_sp(p,xmax,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = xmax; } - // refine - if(*xm>0 && *xmEmax); + double u = Erat * (1.0 - x * x); + if (fabs (u) > p) { + return 0; + } + double twosigma2 = 2.0 * p * data->Delta * data->Delta; + // do not normalize by sqrt(PI*twosigma2), to save time. + double Fp = exp (-pow (u - p / data->g0, 2) / twosigma2); + double alpha = Erat * (data->mRat) * (data->g0); + double ang = angularIntegral_p_phonon (p, alpha, x); + return x * Fp * ang; + }; + + int + compute_dXSdx_max_pph_gauss (int n, int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax) { + int i; + double x, xmax, dx, ss; + double E = KS2E * kabs * kabs; + + // this is a byas since a gaussian has no xmax (is not of compact support) + xmax = sqrt (1. + p * (data->Emax) / E); + dx = xmax / n; + + x = 0; + *xm = 0; + *xsDiffMax = dXSdx_pph_gauss (p, x, E, data); + for (i = 0; i < n; i++) { x += dx; - ss = dXSdx_pph_sp(p,x,E,data); - if(ss>(*xsDiffMax)) { *xsDiffMax = ss; *xm = x; } + ss = dXSdx_pph_gauss (p, x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } } + ss = dXSdx_pph_gauss (p, xmax, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = xmax; + } + // refine + if (*xm > 0 && *xm < xmax) { + xmax = *xm + dx; + x = *xm - dx; + dx /= 100; + *xm = x; + *xsDiffMax = dXSdx_pph_gauss (p, x, E, data); + for (i = 0; i < 200; i++) { + x += dx; + ss = dXSdx_pph_gauss (p, x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } + } + } + // security (better to overstimate maximum) + *xsDiffMax *= 1.01; + + return 0; + }; + + double + Sgauss (double u, double Q2, struct IncoherentPhonon_physics_storage_struct* data) { + // from Lovesey, p. 164, Eq. (4.247) + int p, pmin, pmax; + double Delta = data->Delta; + double g0 = data->g0; + double x, y, F, hx2, yp; + + x = u / Delta; + y = Q2 * g0 * exp (-0.5 / pow (Delta * g0, 2)); + + hx2 = 0.5 * x * x; + + pmin = data->nphe + 1; + pmax = data->npmax; + // get y**pmin/pmin! + yp = y; + for (p = 2; p <= pmin; p++) { + yp *= y / p; + } + + F = yp * exp (-hx2 / pmin - Q2 * g0) / sqrt (pmin); + for (p = pmin + 1; p <= pmax; p++) { + yp *= y / p; + F += yp * exp (-hx2 / p - Q2 * g0) / sqrt (p); + } + F /= sqrt (2. * PI); + + return exp (u / (Delta * Delta * g0)) * F / Delta; } - // security (better to overstimate maximum) - *xsDiffMax *= 1.01; - - return 0; -}; - -double totXS_pph_sp(int p, double kabs, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, n; - double f, u, Fp, ss, x, xmin, xmax, dx; - double E = KS2E*kabs*kabs; - double Erat = E/(data->Emax); - double alpha = Erat*(data->mRat)*(data->g0); - //double g0 = data->g0; - - n = p*10000; - if(Erat>p) { xmin = sqrt(1.0-p/Erat); } else { xmin = 0; } - xmax = sqrt(1.0 + p/Erat); - dx = (xmax-xmin)/n; - - x = xmin; - u = Erat*(1.0-x*x); - Fp = Fp_sp(p,u,data); - f = x*Fp*angularIntegral_p_phonon(p,alpha,x); - ss = 0.5*f; - for(i=1;isigmaCoh+data->sigmaInc)/(2.*(data->mRat)*(data->g0)); - - return ss; -}; - -double Fp_sp(int p, double u, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - double tsp, logg, d2gDg, logpf, rt; - double xi = u/p; - if(xi < data->xi_p[0] || xi > data->xi_p[data->ntsp_p-1]) { return 0; } - tspInterp_p(xi,&tsp,&logg,&d2gDg,data); - logpf = 0; - //for(i=2;i<=p;i++) { logpf += log(1.0*i); } - // notice that what we calles d2gDg is actually -d2gDg - rt = sqrt((2.*PI)/(p*(d2gDg-xi*xi))); - return rt*exp(u*tsp + p*(logg-log(data->g0)) - logpf); -}; - -double Smp_phe(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data) -{ - int p; - double s = 0; - for(p=(data->nphe)+1;p<=(data->npmax);p++) { - s += Smp_p(u,Q2,p,data); - } - return s; -}; -double Smp_p(double u, double Q2, int p, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i; - double tsp, logg, d2gDg, rt, logpf; - double xi = u/p; + void + computeEpsilon (struct IncoherentPhonon_physics_storage_struct* data) { + double tol = 1.0e-8; + data->epsilon = 1.5 * quadFunc (0, 1, 1.0e99, tol, data, epsilonInt); + } - //if(1.0-fabs(xi) < 1.0e-6) { return 0; } + double + epsilonInt (double u, double v, struct IncoherentPhonon_physics_storage_struct* data) { + double E = u * data->Emax; + double x = E / data->kBT; + if (fabs (u) < 1.0e-6) { + return (data->dosPar) * (data->Emax) * (data->Emax) * (data->kBT) * u * u; + } + return (data->Emax) * dos (E, data) * u * (0.5 + bose (x)); + } + + /////////////////////////////////////////////// + // multiphonon expansion in SP approximation // + /////////////////////////////////////////////// + + double + sampleKprime_pph_sp (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + // x = kprime/k + FILE* filep; + int i; + double x, px; + double E = KS2E * kabs * kabs; + double iErat = data->Emax / E; + double pxmax = interpFunc (kabs, data->nxs, data->kabs, data->dXSdx_Fmax_pph_sp[p]); + double xmax = sqrt (1. + p * iErat); + double xmin, delta_x; + if (iErat < 1. / p) { + xmin = sqrt (1. - p * iErat); + } else { + xmin = 0; + } + delta_x = xmax - xmin; + for (i = 0; i < maxIter; i++) { + x = xmin + delta_x * rand01 (); + px = dXSdx_pph_sp (p, x, E, data); + if (px > pxmax) { + fprintf (data->filep, "sampleKprime_pph_sp: p = %d\n", p); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "xmax: %.6e\n", xmax); + fprintf (data->filep, "pxmax: %.6e\n", pxmax); + fprintf (data->filep, "px: %.6e\n", px); + fprintf (data->filep, "px/pxmax: %.6e\n", px / pxmax); + filep = fopen ("dXSdx_pph_sp.txt", "w"); + fprintf (filep, "p: %d\n", p); + x = 0; + while (x <= xmax) { + px = dXSdx_pph_sp (p, x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + exit (1); + } + if (px / pxmax > rand01 ()) { + return x; + } + } + // What happens if maxIter is exceeded?? return negative value to control + filep = fopen ("dXSdx_pph_sp_maxIter_exceeded.txt", "w"); + fprintf (filep, "p: %d\n", p); + x = 0; + while (x <= xmax) { + px = dXSdx_pph_sp (p, x, E, data); + fprintf (filep, "%f %.16e %.16e\n", x, px, pxmax); + x += xmax / 1000; + } + fclose (filep); + return -1; + }; + + double + dXSdx_pph_sp (int p, double x, double E, struct IncoherentPhonon_physics_storage_struct* data) { + double Erat = E / (data->Emax); + double u = Erat * (1.0 - x * x); + if (fabs (u) > p) { + return 0; + } + double Fp = Fp_sp (p, u, data); + double alpha = Erat * (data->mRat) * (data->g0); + double ang = angularIntegral_p_phonon (p, alpha, x); + return x * Fp * ang; + }; + + int + compute_dXSdx_max_pph_sp (int n, int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data, double* xm, double* xsDiffMax) { + int i; + double x, xmax, dx, ss; + double E = KS2E * kabs * kabs; + + xmax = sqrt (1. + p * (data->Emax) / E); + dx = xmax / n; + + x = 0; + *xm = 0; + *xsDiffMax = dXSdx_pph_sp (p, x, E, data); + for (i = 0; i < n; i++) { + x += dx; + ss = dXSdx_pph_sp (p, x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } + } + ss = dXSdx_pph_sp (p, xmax, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = xmax; + } + // refine + if (*xm > 0 && *xm < xmax) { + xmax = *xm + dx; + x = *xm - dx; + dx /= 100; + *xm = x; + *xsDiffMax = dXSdx_pph_sp (p, x, E, data); + for (i = 0; i < 200; i++) { + x += dx; + ss = dXSdx_pph_sp (p, x, E, data); + if (ss > (*xsDiffMax)) { + *xsDiffMax = ss; + *xm = x; + } + } + } + // security (better to overstimate maximum) + *xsDiffMax *= 1.01; + + return 0; + }; + + double + totXS_pph_sp (int p, double kabs, struct IncoherentPhonon_physics_storage_struct* data) { + int i, n; + double f, u, Fp, ss, x, xmin, xmax, dx; + double E = KS2E * kabs * kabs; + double Erat = E / (data->Emax); + double alpha = Erat * (data->mRat) * (data->g0); + // double g0 = data->g0; + + n = p * 10000; + if (Erat > p) { + xmin = sqrt (1.0 - p / Erat); + } else { + xmin = 0; + } + xmax = sqrt (1.0 + p / Erat); + dx = (xmax - xmin) / n; + + x = xmin; + u = Erat * (1.0 - x * x); + Fp = Fp_sp (p, u, data); + f = x * Fp * angularIntegral_p_phonon (p, alpha, x); + ss = 0.5 * f; + for (i = 1; i < n; i++) { + x = xmin + i * dx; + u = Erat * (1.0 - x * x); + Fp = Fp_sp (p, u, data); + f = x * Fp * angularIntegral_p_phonon (p, alpha, x); + ss += f; + } + x = xmax; + u = Erat * (1.0 - x * x); + Fp = Fp_sp (p, u, data); + f = x * Fp * angularIntegral_p_phonon (p, alpha, x); + ss += 0.5 * f; + + // multiply by all constant factors + ss *= dx; + ss *= (data->sigmaCoh + data->sigmaInc) / (2. * (data->mRat) * (data->g0)); + + return ss; + }; + + double + Fp_sp (int p, double u, struct IncoherentPhonon_physics_storage_struct* data) { + int i; + double tsp, logg, d2gDg, logpf, rt; + double xi = u / p; + if (xi < data->xi_p[0] || xi > data->xi_p[data->ntsp_p - 1]) { + return 0; + } + tspInterp_p (xi, &tsp, &logg, &d2gDg, data); + logpf = 0; + // for(i=2;i<=p;i++) { logpf += log(1.0*i); } + // notice that what we calles d2gDg is actually -d2gDg + rt = sqrt ((2. * PI) / (p * (d2gDg - xi * xi))); + return rt * exp (u * tsp + p * (logg - log (data->g0)) - logpf); + }; + + double + Smp_phe (double u, double Q2, struct IncoherentPhonon_physics_storage_struct* data) { + int p; + double s = 0; + for (p = (data->nphe) + 1; p <= (data->npmax); p++) { + s += Smp_p (u, Q2, p, data); + } + return s; + }; - if(xi < data->xi_p[0] || xi > data->xi_p[data->ntsp_p-1]) { return 0; } + double + Smp_p (double u, double Q2, int p, struct IncoherentPhonon_physics_storage_struct* data) { + int i; + double tsp, logg, d2gDg, rt, logpf; + double xi = u / p; - tspInterp_p(xi,&tsp,&logg,&d2gDg,data); + // if(1.0-fabs(xi) < 1.0e-6) { return 0; } - logpf = 0; - for(i=2;i<=p;i++) { logpf += log(1.0*i); } + if (xi < data->xi_p[0] || xi > data->xi_p[data->ntsp_p - 1]) { + return 0; + } - // notice that what we calles d2gDg is actually -d2gDg - rt = sqrt((2.*PI)/(p*(d2gDg-xi*xi))); + tspInterp_p (xi, &tsp, &logg, &d2gDg, data); - return rt*exp(-Q2*(data->g0) + u*tsp + p*log(Q2) + p*logg - logpf); -} + logpf = 0; + for (i = 2; i <= p; i++) { + logpf += log (1.0 * i); + } -double Smp_p_int(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data) -{ - return Smp_p(u,Q2,data->p,data); -} + // notice that what we calles d2gDg is actually -d2gDg + rt = sqrt ((2. * PI) / (p * (d2gDg - xi * xi))); -double integral_Smp_phe(double Q2, double tol, struct IncoherentPhonon_physics_storage_struct *data) -{ - double u1, u2, S; - u1 = 0; - S = Smp_phe(u1,Q2,data); - while(S>0.1*tol) { - u1 -= 1; - S = Smp_phe(u1,Q2,data); - } - u2 = 0; - S = Smp_phe(u2,Q2,data); - while(S>0.1*tol) { - u2 += 1; - S = Smp_phe(u2,Q2,data); + return rt * exp (-Q2 * (data->g0) + u * tsp + p * log (Q2) + p * logg - logpf); } - return quadFunc(u1,u2,Q2,tol,data,Smp_phe); -} - -void tspInterp_p(double xi, double *tsp, double *logg, double *d2gDg, - struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, imin, imax; - double a; - - int ntsp_ = data->ntsp_p; - double *xi_ = data->xi_p; - double *tsp_ = data->tsp_p; - double *g_ = data->g_p; - double *d2gDg_ = data->d2gDg_p; - - if(xiB_p/(1.0+xi); - a = (xi-xi_[0])/(xi_[1]-xi_[0]); - *g = g_[0] + a*(g_[1]-g_[0]); - *d2g = d2g_[0] + a*(d2g_[1]-d2g_[0]); - *H = H_[0] + a*(H_[1]-H_[0]); - return; - */ - fprintf(data->filep,"tspInterp_p: xixi_[ntsp_-1]) { - /* - *tsp = -data->B_p/(1.0-xi); - a = (xi-xi_[ntsp_-1])/(xi_[ntsp_-2]-xi_[ntsp_-1]); - *g = g_[ntsp_-1] + a*(g_[ntsp_-2]-g_[ntsp_-1]); - *d2g = d2g_[ntsp_-1] + a*(d2g_[ntsp_-2]-d2g_[ntsp_-1]); - *H = H_[ntsp_-1] + a*(H_[ntsp_-2]-H_[ntsp_-1]); - return; - */ - fprintf(data->filep,"tspInterp_p: xi>xi_p[ntsp_-1]\n"); - printf("tspInterp_p: xip, data); } - // linear interpolation otherwise - imin=0; imax=ntsp_-1; - while(imax-imin>1) { - i = (imax + imin)/2; - if (xi 0.1 * tol) { + u1 -= 1; + S = Smp_phe (u1, Q2, data); + } + u2 = 0; + S = Smp_phe (u2, Q2, data); + while (S > 0.1 * tol) { + u2 += 1; + S = Smp_phe (u2, Q2, data); + } + return quadFunc (u1, u2, Q2, tol, data, Smp_phe); + } + + void + tspInterp_p (double xi, double* tsp, double* logg, double* d2gDg, struct IncoherentPhonon_physics_storage_struct* data) { + int i, imin, imax; + double a; + + int ntsp_ = data->ntsp_p; + double* xi_ = data->xi_p; + double* tsp_ = data->tsp_p; + double* g_ = data->g_p; + double* d2gDg_ = data->d2gDg_p; + + if (xi < xi_[0]) { + /* + *tsp = data->B_p/(1.0+xi); + a = (xi-xi_[0])/(xi_[1]-xi_[0]); + *g = g_[0] + a*(g_[1]-g_[0]); + *d2g = d2g_[0] + a*(d2g_[1]-d2g_[0]); + *H = H_[0] + a*(H_[1]-H_[0]); + return; + */ + fprintf (data->filep, "tspInterp_p: xi xi_[ntsp_ - 1]) { + /* + *tsp = -data->B_p/(1.0-xi); + a = (xi-xi_[ntsp_-1])/(xi_[ntsp_-2]-xi_[ntsp_-1]); + *g = g_[ntsp_-1] + a*(g_[ntsp_-2]-g_[ntsp_-1]); + *d2g = d2g_[ntsp_-1] + a*(d2g_[ntsp_-2]-d2g_[ntsp_-1]); + *H = H_[ntsp_-1] + a*(H_[ntsp_-2]-H_[ntsp_-1]); + return; + */ + fprintf (data->filep, "tspInterp_p: xi>xi_p[ntsp_-1]\n"); + printf ("tspInterp_p: xi 1) { + i = (imax + imin) / 2; + if (xi < xi_[i]) { + imax = i; + } else { + imin = i; + } + } + + if (imax == imin) { + printf ("imax = imin %d %d\n", imin, imax); + exit (1); + } + if (xi < xi_[imin] || xi > xi_[imax]) { + printf ("bad bracketing: %d %d %f %f %f\n", imin, imax, xi_[imin], xi, xi_[imax]); + exit (1); + } - if(imax==imin) { printf("imax = imin %d %d\n",imin,imax); exit(1); } - if(xixi_[imax]) { - printf("bad bracketing: %d %d %f %f %f\n",imin,imax,xi_[imin],xi,xi_[imax]); - exit(1); + a = (xi - xi_[imin]) / (xi_[imax] - xi_[imin]); + + *tsp = tsp_[imin] + a * (tsp_[imax] - tsp_[imin]); + *logg = log (g_[imin]) + a * (log (g_[imax]) - log (g_[imin])); + *d2gDg = d2gDg_[imin] + a * (d2gDg_[imax] - d2gDg_[imin]); } - a = (xi-xi_[imin])/(xi_[imax]-xi_[imin]); + void + computeSP_p (int ntsp, double ximin, double ximax, struct IncoherentPhonon_physics_storage_struct* data) { + int i, nread; + double xi, dxi, *xi_, *tsp_, *g_, *d2gDg_; + FILE* filep; - *tsp = tsp_[imin] + a*(tsp_[imax]-tsp_[imin]); - *logg = log(g_[imin]) + a*(log(g_[imax])-log(g_[imin])); - *d2gDg = d2gDg_[imin] + a*(d2gDg_[imax]-d2gDg_[imin]); -} + fprintf (data->filep, "computeSP_p: start\n"); + fflush (data->filep); + if (ximin <= -1.0 || ximax >= 1.0) { + fprintf (data->filep, "computeSP_p: ximin: %.16e ximax: %.16e\n", ximin, ximax); + fflush (data->filep); + printf ("computeSP_p: ximin: %.16e ximax: %.16e\n", ximin, ximax); + exit (1); + } -void computeSP_p(int ntsp, double ximin, double ximax, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, nread; - double xi, dxi, *xi_, *tsp_, *g_, *d2gDg_; - FILE *filep; + fprintf (data->filep, "computeSP_p: try open sp_p.txt\n"); + filep = fopen ("sp_p.txt", "r"); + if (filep != NULL) { + fprintf (data->filep, "computeSP_p: opened\n"); + fflush (data->filep); + nread = fscanf (filep, "%d", &ntsp); + fprintf (data->filep, "computeSP_p: nread %d ntsp %d\n", nread, ntsp); + fflush (data->filep); + xi_ = (double*)malloc (ntsp * sizeof (double)); + tsp_ = (double*)malloc (ntsp * sizeof (double)); + g_ = (double*)malloc (ntsp * sizeof (double)); + d2gDg_ = (double*)malloc (ntsp * sizeof (double)); + fprintf (data->filep, "computeSP_p: reading\n"); + fflush (data->filep); + for (i = 0; i < ntsp; i++) { + fscanf (filep, "%lf %lf %lf %lf", xi_ + i, tsp_ + i, g_ + i, d2gDg_ + i); + } + fclose (filep); - fprintf(data->filep,"computeSP_p: start\n"); - fflush(data->filep); - if(ximin<=-1.0 || ximax >= 1.0) { - fprintf(data->filep,"computeSP_p: ximin: %.16e ximax: %.16e\n",ximin,ximax); - fflush(data->filep); - printf("computeSP_p: ximin: %.16e ximax: %.16e\n",ximin,ximax); - exit(1); - } + fprintf (data->filep, "computeSP_p: reading finished\n"); + fflush (data->filep); - fprintf(data->filep,"computeSP_p: try open sp_p.txt\n"); - filep = fopen("sp_p.txt","r"); - if(filep != NULL) { - fprintf(data->filep,"computeSP_p: opened\n"); - fflush(data->filep); - nread = fscanf(filep,"%d",&ntsp); - fprintf(data->filep,"computeSP_p: nread %d ntsp %d\n",nread,ntsp); - fflush(data->filep); - xi_ = (double *)malloc(ntsp*sizeof(double)); - tsp_ = (double *)malloc(ntsp*sizeof(double)); - g_ = (double *)malloc(ntsp*sizeof(double)); - d2gDg_ = (double *)malloc(ntsp*sizeof(double)); - fprintf(data->filep,"computeSP_p: reading\n"); - fflush(data->filep); - for(i=0;intsp_p = ntsp; + data->xi_p = xi_; + data->tsp_p = tsp_; + data->g_p = g_; + data->d2gDg_p = d2gDg_; + + fprintf (data->filep, "final ntsp_p: %d\n", data->ntsp_p); + fprintf (data->filep, "final ximin_p: %f\n", (data->xi_p)[0]); + fprintf (data->filep, "final ximax_p: %f\n", (data->xi_p)[(data->ntsp_p) - 1]); + fprintf (data->filep, "computeSP_p: end\n"); + fflush (data->filep); + + return; } - fclose(filep); - fprintf(data->filep,"computeSP_p: reading finished\n"); - fflush(data->filep); + // computing if necessary + fprintf (data->filep, "Computing saddle point solution for multiphon expansion in SP...\n"); + fflush (data->filep); + + dxi = (ximax - ximin) / ntsp; + + xi_ = (double*)malloc (ntsp * sizeof (double)); + tsp_ = (double*)malloc (ntsp * sizeof (double)); + g_ = (double*)malloc (ntsp * sizeof (double)); + d2gDg_ = (double*)malloc (ntsp * sizeof (double)); + + filep = fopen ("sp_p.txt", "w"); + fprintf (filep, "%d\n", ntsp); + fflush (filep); + xi = ximin; + for (i = 0; i < ntsp; i++) { + // printf("%d %d\n",i,ntsp); + xi_[i] = xi; + tsp_[i] = saddlePoint_p (xi_[i], data); + g_[i] = Gt (tsp_[i], data); + d2gDg_[i] = d2Gt (tsp_[i], data) / Gt (tsp_[i], data); + fprintf (filep, "%.16e %.16e %.16e %.16e\n", xi_[i], tsp_[i], g_[i], d2gDg_[i]); + fflush (filep); + xi += dxi; + } + fclose (filep); + + fprintf (data->filep, "computeSP_p: computation end\n"); data->ntsp_p = ntsp; data->xi_p = xi_; @@ -3669,1000 +3997,1176 @@ void computeSP_p(int ntsp, double ximin, double ximax, struct IncoherentPhonon_p data->g_p = g_; data->d2gDg_p = d2gDg_; - fprintf(data->filep,"final ntsp_p: %d\n",data->ntsp_p); - fprintf(data->filep,"final ximin_p: %f\n",(data->xi_p)[0]); - fprintf(data->filep,"final ximax_p: %f\n",(data->xi_p)[(data->ntsp_p)-1]); - fprintf(data->filep,"computeSP_p: end\n"); - fflush(data->filep); - - return; + fprintf (data->filep, "final ntsp_p: %d\n", data->ntsp_p); + fprintf (data->filep, "final ximin_p: %f\n", (data->xi_p)[0]); + fprintf (data->filep, "final ximax_p: %f\n", (data->xi_p)[(data->ntsp_p) - 1]); + fprintf (data->filep, "computeSP_p: end\n"); + fflush (data->filep); } - // computing if necessary - fprintf(data->filep,"Computing saddle point solution for multiphon expansion in SP...\n"); - fflush(data->filep); - - dxi = (ximax - ximin)/ntsp; - - xi_ = (double *)malloc(ntsp*sizeof(double)); - tsp_ = (double *)malloc(ntsp*sizeof(double)); - g_ = (double *)malloc(ntsp*sizeof(double)); - d2gDg_ = (double *)malloc(ntsp*sizeof(double)); - - filep = fopen("sp_p.txt","w"); - fprintf(filep,"%d\n",ntsp); - fflush(filep); - xi = ximin; - for(i=0;ifilep,"computeSP_p: computation end\n"); - - data->ntsp_p = ntsp; - data->xi_p = xi_; - data->tsp_p = tsp_; - data->g_p = g_; - data->d2gDg_p = d2gDg_; - - fprintf(data->filep,"final ntsp_p: %d\n",data->ntsp_p); - fprintf(data->filep,"final ximin_p: %f\n",(data->xi_p)[0]); - fprintf(data->filep,"final ximax_p: %f\n",(data->xi_p)[(data->ntsp_p)-1]); - fprintf(data->filep,"computeSP_p: end\n"); - fflush(data->filep); -} - -double saddlePoint_p(double xi, struct IncoherentPhonon_physics_storage_struct *data) -{ - // solves dgt(tsp)/gt(tsp) = -z for tsp - double tl, th, tm, y; - double tol; - FILE *filep; - - /* - filep = fopen("tirar.txt","w"); - tm = -20.0; - while(tm<20.0) { - fprintf(filep,"%f %.16e\n",tm,dGt(tm,data)/Gt(tm,data)); - tm += 0.1; - } - fclose(filep); - exit(1); - */ - - if(1.0-fabs(xi)<1.0e-8) { return -sqrt(-1.0); } - - //tol = data->tolSaddlePoint; - tol = 1.0e-4; - - //filep = fopen("tirar2.txt","w"); - - tl = -1; - y = dGt(tl,data)/Gt(tl,data) + xi; - //fprintf(filep,"%f %.6e %.16e\n",xi,tl,y); - //fflush(filep); - while(y>0) { - tl *= 2; - y = dGt(tl,data)/Gt(tl,data) + xi; - //fprintf(filep,"%f %.6e %.16e\n",xi,tl,y); - //fflush(filep); - } + double + saddlePoint_p (double xi, struct IncoherentPhonon_physics_storage_struct* data) { + // solves dgt(tsp)/gt(tsp) = -z for tsp + double tl, th, tm, y; + double tol; + FILE* filep; - //fprintf(filep,"\n\n",xi,tl,y); - //fflush(filep); - - th = 1; - y = dGt(th,data)/Gt(th,data) + xi; - //fprintf(filep,"%f %.6e %.16e\n",xi,th,y); - //fflush(filep); - while(y<0) { - th *= 2; - y = dGt(th,data)/Gt(th,data) + xi; - //fprintf(filep,"%f %.6e %.16e\n",xi,th,y); - //fflush(filep); - } + /* + filep = fopen("tirar.txt","w"); + tm = -20.0; + while(tm<20.0) { + fprintf(filep,"%f %.16e\n",tm,dGt(tm,data)/Gt(tm,data)); + tm += 0.1; + } + fclose(filep); + exit(1); + */ - //fclose(filep); - //exit(1); + if (1.0 - fabs (xi) < 1.0e-8) { + return -sqrt (-1.0); + } - while(th-tl>tol) { - tm = 0.5*(tl + th); - y = dGt(tm,data)/Gt(tm,data) + xi; - if(y<0) { tl = tm; } else { th = tm; } - } + // tol = data->tolSaddlePoint; + tol = 1.0e-4; - return 0.5*(tl+th); -}; - -///////////////////////////////////////////////////////// -// for the exact correlation function (only for tests) // -///////////////////////////////////////////////////////// - -double exactS(double u, double Q2, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, n; - double *s, *rGs, *iGs; - double rSF, y1, y2, cus, sus, phe; - double Q2p1, Q2p2, Q2p3, Q2p4, EDW; - - Q2p1 = Q2; - Q2p2 = 0.5*Q2p1*Q2; - Q2p3 = Q2p2*Q2/3.; - Q2p4 = 0.25*Q2p3*Q2; - EDW = exp(-Q2*(data->g0)); - - n = data->npGs; - s = data->s; - rGs = data->rGs; - iGs = data->iGs; - - rSF = 0; - for(i=0;inphe>0) { phe += Q2p1*(cus*rGs[i]+sus*iGs[i]); } // observe that g0 is absorbed in Gs - if(data->nphe>1) { phe += Q2p2*(cus*(rGs[i]*rGs[i]-iGs[i]*iGs[i]) + 2.0*sus*rGs[i]*iGs[i]); } - if(data->nphe>2) { - phe += Q2p3*(cus*pow(rGs[i],3)+3.0*sus*iGs[i]*rGs[i]*rGs[i]-3.0*cus*rGs[i]*iGs[i]*iGs[i]-sus*pow(iGs[i],3)); - } - if(data->nphe>3) { - phe += Q2p4*( cus*pow(rGs[i],4) + 4.0*sus*iGs[i]*pow(rGs[i],3) - 6.0*cus*pow(iGs[i]*rGs[i],2) - - 4.0*sus*pow(iGs[i],3)*rGs[i] + cus*pow(iGs[i],4) ); - } - y1 = EDW*(exp(Q2*rGs[i])*cos(Q2*iGs[i]-u*s[i]) - phe); - - cus = cos(u*s[i+1]); - sus = sin(u*s[i+1]); - phe = cus; - if(data->nphe>0) { phe += Q2p1*(cus*rGs[i+1]+sus*iGs[i+1]); } - if(data->nphe>1) { phe += Q2p2*(cus*(rGs[i+1]*rGs[i+1]-iGs[i+1]*iGs[i+1]) + 2.0*sus*rGs[i+1]*iGs[i+1]); } - if(data->nphe>2) { - phe += Q2p3*(cus*pow(rGs[i+1],3)+3.0*sus*iGs[i+1]*rGs[i+1]*rGs[i+1]-3.0*cus*rGs[i+1]*iGs[i+1]*iGs[i+1]-sus*pow(iGs[i+1],3)); - } - if(data->nphe>3) { - phe += Q2p4*( cus*pow(rGs[i+1],4) + 4.0*sus*iGs[i+1]*pow(rGs[i+1],3) - 6.0*cus*pow(iGs[i+1]*rGs[i+1],2) - - 4.0*sus*pow(iGs[i+1],3)*rGs[i+1] + cus*pow(iGs[i+1],4) ); - } - y2 = EDW*(exp(Q2*rGs[i+1])*cos(Q2*iGs[i+1]-u*s[i+1]) - phe); - - rSF += 0.5*(s[i+1]-s[i])*(y1 + y2); - } - rSF *= 2; - - return rSF/(2*PI); -} - -void getExactS(double Q2, double nu1, double nu2, struct IncoherentPhonon_physics_storage_struct *data) -{ - double h = 4.13567; // planck constant in meV*ps - int i, n = 200000; - double *s, *rGs, *iGs; - double smin, smax, ds; - double nu, u, rSF, y1, y2, cus, sus, phe; - double S1, S2, S3, Fp1, Fp2, Fp3; - double g0 = data->g0; - FILE *filep; - - filep = fopen("Gs.txt","r"); - fprintf(data->filep,"exactS: open Gs done\n"); - fflush(data->filep); - if(filep != NULL) { - fscanf(filep,"%d",&n); - printf("n=%d\n",n); - s = (double *)malloc(n*sizeof(double)); - rGs = (double *)malloc(n*sizeof(double)); - iGs = (double *)malloc(n*sizeof(double)); - for(i=0;i 0) { + tl *= 2; + y = dGt (tl, data) / Gt (tl, data) + xi; + // fprintf(filep,"%f %.6e %.16e\n",xi,tl,y); + // fflush(filep); } - fclose(filep); - } else { - smin = 0; - smax = 200; - ds = (smax - smin)/n; - s = (double *)malloc(n*sizeof(double)); - rGs = (double *)malloc(n*sizeof(double)); - iGs = (double *)malloc(n*sizeof(double)); - filep = fopen("Gs.txt","w"); - fprintf(filep,"%d\n",n); - for(i=0;iEmax; - // the three firts terms of the phonon expansion - if(fabs(u)<1) { Fp1 = interpFunc(u,data->nF1,data->u1,data->F1); } else { Fp1 = 0; } - if(fabs(u)<2) { Fp2 = interpFunc(u,data->nF2,data->u2,data->F2); } else { Fp2 = 0; } - if(fabs(u)<3) { Fp3 = interpFunc(u,data->nF3,data->u3,data->F3); } else { Fp3 = 0; } - S1 = g0*Fp1*exp(-g0*Q2)*Q2; - S2 = g0*g0*Fp2*exp(-g0*Q2)*pow(Q2,2); - S3 = g0*g0*g0*Fp3*exp(-g0*Q2)*pow(Q2,3); - // the exact multiphonon term + // fclose(filep); + // exit(1); + + while (th - tl > tol) { + tm = 0.5 * (tl + th); + y = dGt (tm, data) / Gt (tm, data) + xi; + if (y < 0) { + tl = tm; + } else { + th = tm; + } + } + + return 0.5 * (tl + th); + }; + + ///////////////////////////////////////////////////////// + // for the exact correlation function (only for tests) // + ///////////////////////////////////////////////////////// + + double + exactS (double u, double Q2, struct IncoherentPhonon_physics_storage_struct* data) { + int i, n; + double *s, *rGs, *iGs; + double rSF, y1, y2, cus, sus, phe; + double Q2p1, Q2p2, Q2p3, Q2p4, EDW; + + Q2p1 = Q2; + Q2p2 = 0.5 * Q2p1 * Q2; + Q2p3 = Q2p2 * Q2 / 3.; + Q2p4 = 0.25 * Q2p3 * Q2; + EDW = exp (-Q2 * (data->g0)); + + n = data->npGs; + s = data->s; + rGs = data->rGs; + iGs = data->iGs; + rSF = 0; - for(i=0;inphe>0) { phe += Q2*(cus*rGs[i]+sus*iGs[i]); } - if(data->nphe>1) { phe += 0.5*pow(Q2,2)*(cus*(rGs[i]*rGs[i]-iGs[i]*iGs[i]) + 2.0*sus*rGs[i]*iGs[i]); } - if(data->nphe>2) { - phe += (1./6.)*pow(Q2,3)*(cus*pow(rGs[i],3)+3.0*sus*iGs[i]*rGs[i]*rGs[i]-3.0*cus*rGs[i]*iGs[i]*iGs[i]-sus*pow(iGs[i],3)); + if (data->nphe > 0) { + phe += Q2p1 * (cus * rGs[i] + sus * iGs[i]); + } // observe that g0 is absorbed in Gs + if (data->nphe > 1) { + phe += Q2p2 * (cus * (rGs[i] * rGs[i] - iGs[i] * iGs[i]) + 2.0 * sus * rGs[i] * iGs[i]); + } + if (data->nphe > 2) { + phe += Q2p3 * (cus * pow (rGs[i], 3) + 3.0 * sus * iGs[i] * rGs[i] * rGs[i] - 3.0 * cus * rGs[i] * iGs[i] * iGs[i] - sus * pow (iGs[i], 3)); } - if(data->nphe>3) { - phe += (1./24.)*pow(Q2,4)*( cus*pow(rGs[i],4) + 4.0*sus*iGs[i]*pow(rGs[i],3) - 6.0*cus*pow(iGs[i]*rGs[i],2) - - 4.0*sus*pow(iGs[i],3)*rGs[i] + cus*pow(iGs[i],4) ); + if (data->nphe > 3) { + phe += Q2p4 + * (cus * pow (rGs[i], 4) + 4.0 * sus * iGs[i] * pow (rGs[i], 3) - 6.0 * cus * pow (iGs[i] * rGs[i], 2) - 4.0 * sus * pow (iGs[i], 3) * rGs[i] + + cus * pow (iGs[i], 4)); } - y1 = exp(-Q2*g0)*(exp(Q2*rGs[i])*cos(Q2*iGs[i]-u*s[i]) - phe); + y1 = EDW * (exp (Q2 * rGs[i]) * cos (Q2 * iGs[i] - u * s[i]) - phe); - cus = cos(u*s[i+1]); - sus = sin(u*s[i+1]); + cus = cos (u * s[i + 1]); + sus = sin (u * s[i + 1]); phe = cus; - if(data->nphe>0) { phe += Q2*(cus*rGs[i+1]+sus*iGs[i+1]); } - if(data->nphe>1) { phe += 0.5*pow(Q2,2)*(cus*(rGs[i+1]*rGs[i+1]-iGs[i+1]*iGs[i+1]) + 2.0*sus*rGs[i+1]*iGs[i+1]); } - if(data->nphe>2) { - phe += (1./6.)*pow(Q2,3)*(cus*pow(rGs[i+1],3)+3.0*sus*iGs[i+1]*rGs[i+1]*rGs[i+1]-3.0*cus*rGs[i+1]*iGs[i+1]*iGs[i+1]-sus*pow(iGs[i+1],3)); + if (data->nphe > 0) { + phe += Q2p1 * (cus * rGs[i + 1] + sus * iGs[i + 1]); } - if(data->nphe>3) { - phe += (1./24.)*pow(Q2,4)*( cus*pow(rGs[i+1],4) + 4.0*sus*iGs[i+1]*pow(rGs[i+1],3) - 6.0*cus*pow(iGs[i+1]*rGs[i+1],2) - - 4.0*sus*pow(iGs[i+1],3)*rGs[i+1] + cus*pow(iGs[i+1],4) ); + if (data->nphe > 1) { + phe += Q2p2 * (cus * (rGs[i + 1] * rGs[i + 1] - iGs[i + 1] * iGs[i + 1]) + 2.0 * sus * rGs[i + 1] * iGs[i + 1]); } - y2 = exp(-Q2*g0)*(exp(Q2*rGs[i+1])*cos(Q2*iGs[i+1]-u*s[i+1]) - phe); + if (data->nphe > 2) { + phe += Q2p3 + * (cus * pow (rGs[i + 1], 3) + 3.0 * sus * iGs[i + 1] * rGs[i + 1] * rGs[i + 1] - 3.0 * cus * rGs[i + 1] * iGs[i + 1] * iGs[i + 1] + - sus * pow (iGs[i + 1], 3)); + } + if (data->nphe > 3) { + phe += Q2p4 + * (cus * pow (rGs[i + 1], 4) + 4.0 * sus * iGs[i + 1] * pow (rGs[i + 1], 3) - 6.0 * cus * pow (iGs[i + 1] * rGs[i + 1], 2) + - 4.0 * sus * pow (iGs[i + 1], 3) * rGs[i + 1] + cus * pow (iGs[i + 1], 4)); + } + y2 = EDW * (exp (Q2 * rGs[i + 1]) * cos (Q2 * iGs[i + 1] - u * s[i + 1]) - phe); - rSF += 0.5*(s[i+1]-s[i])*(y1 + y2); + rSF += 0.5 * (s[i + 1] - s[i]) * (y1 + y2); } rSF *= 2; - fprintf(filep,"%f %f %f %.6e %.6e %.6e %.6e\n",Q2,nu,u,S1,S2,S3,rSF); - fflush(filep); - nu += 0.05; - } - fclose(filep); - - free(s); - free(rGs); - free(iGs); -} - -void computeGs(double s, double *rGs, double *iGs, struct IncoherentPhonon_physics_storage_struct *data) -{ - double tol = 1.0e-6; - *rGs = quadFunc(-1,1,s,tol,data,realGsInt); - *iGs = quadFunc(-1,1,s,tol,data,imagGsInt); -} - -double realGsInt(double u, double s, struct IncoherentPhonon_physics_storage_struct *data) -{ - return Gu(u,data)*cos(u*s); -} - -double imagGsInt(double u, double s, struct IncoherentPhonon_physics_storage_struct *data) -{ - return -Gu(u,data)*sin(u*s); -} - -//////////////////////////// -// Auxiliary functions /// -//////////////////////////// - -double quadFunc(double x1, double x2, double v, double tol, struct IncoherentPhonon_physics_storage_struct *data, - double (*func)(double,double,struct IncoherentPhonon_physics_storage_struct *)) -{ - int n; - double s1, s2; - double relTol; - FILE *filep; - - filep = fopen("quad.txt","a"); - - fprintf(filep,"===============\n"); - fflush(filep); - - n = 100; - s1 = trapezFunc(n,x1,x2,v,data,func); - n = 200; - s2 = trapezFunc(n,x1,x2,v,data,func); - if(fabs(0.5*(s1+s2))<10) { relTol = tol; } else { relTol = tol*fabs(0.5*(s1+s2)); } - fprintf(filep,"%f %d %.6e %.6e %.16e %.16e\n",v,n,s1,s2,s2-s1,relTol); - fflush(filep); - while(ng0; + FILE* filep; + + filep = fopen ("Gs.txt", "r"); + fprintf (data->filep, "exactS: open Gs done\n"); + fflush (data->filep); + if (filep != NULL) { + fscanf (filep, "%d", &n); + printf ("n=%d\n", n); + s = (double*)malloc (n * sizeof (double)); + rGs = (double*)malloc (n * sizeof (double)); + iGs = (double*)malloc (n * sizeof (double)); + for (i = 0; i < n; i++) { + fscanf (filep, "%lf %lf %lf", s + i, rGs + i, iGs + i); + } + fclose (filep); + } else { + smin = 0; + smax = 200; + ds = (smax - smin) / n; + s = (double*)malloc (n * sizeof (double)); + rGs = (double*)malloc (n * sizeof (double)); + iGs = (double*)malloc (n * sizeof (double)); + filep = fopen ("Gs.txt", "w"); + fprintf (filep, "%d\n", n); + for (i = 0; i < n; i++) { + s[i] = smin + i * ds; + computeGs (s[i], rGs + i, iGs + i, data); + fprintf (filep, "%.16e %.16e %.16e\n", s[i], rGs[i], iGs[i]); + fflush (filep); + } + fclose (filep); + } + + filep = fopen ("exactS.txt", "w"); + nu = nu1; + while (nu < nu2) { + u = (h * nu) / data->Emax; + // the three firts terms of the phonon expansion + if (fabs (u) < 1) { + Fp1 = interpFunc (u, data->nF1, data->u1, data->F1); + } else { + Fp1 = 0; + } + if (fabs (u) < 2) { + Fp2 = interpFunc (u, data->nF2, data->u2, data->F2); + } else { + Fp2 = 0; + } + if (fabs (u) < 3) { + Fp3 = interpFunc (u, data->nF3, data->u3, data->F3); + } else { + Fp3 = 0; + } + S1 = g0 * Fp1 * exp (-g0 * Q2) * Q2; + S2 = g0 * g0 * Fp2 * exp (-g0 * Q2) * pow (Q2, 2); + S3 = g0 * g0 * g0 * Fp3 * exp (-g0 * Q2) * pow (Q2, 3); + // the exact multiphonon term + rSF = 0; + for (i = 0; i < n - 1; i++) { + cus = cos (u * s[i]); + sus = sin (u * s[i]); + phe = cus; + if (data->nphe > 0) { + phe += Q2 * (cus * rGs[i] + sus * iGs[i]); + } + if (data->nphe > 1) { + phe += 0.5 * pow (Q2, 2) * (cus * (rGs[i] * rGs[i] - iGs[i] * iGs[i]) + 2.0 * sus * rGs[i] * iGs[i]); + } + if (data->nphe > 2) { + phe += (1. / 6.) * pow (Q2, 3) + * (cus * pow (rGs[i], 3) + 3.0 * sus * iGs[i] * rGs[i] * rGs[i] - 3.0 * cus * rGs[i] * iGs[i] * iGs[i] - sus * pow (iGs[i], 3)); + } + if (data->nphe > 3) { + phe += (1. / 24.) * pow (Q2, 4) + * (cus * pow (rGs[i], 4) + 4.0 * sus * iGs[i] * pow (rGs[i], 3) - 6.0 * cus * pow (iGs[i] * rGs[i], 2) - 4.0 * sus * pow (iGs[i], 3) * rGs[i] + + cus * pow (iGs[i], 4)); + } + y1 = exp (-Q2 * g0) * (exp (Q2 * rGs[i]) * cos (Q2 * iGs[i] - u * s[i]) - phe); + + cus = cos (u * s[i + 1]); + sus = sin (u * s[i + 1]); + phe = cus; + if (data->nphe > 0) { + phe += Q2 * (cus * rGs[i + 1] + sus * iGs[i + 1]); + } + if (data->nphe > 1) { + phe += 0.5 * pow (Q2, 2) * (cus * (rGs[i + 1] * rGs[i + 1] - iGs[i + 1] * iGs[i + 1]) + 2.0 * sus * rGs[i + 1] * iGs[i + 1]); + } + if (data->nphe > 2) { + phe += (1. / 6.) * pow (Q2, 3) + * (cus * pow (rGs[i + 1], 3) + 3.0 * sus * iGs[i + 1] * rGs[i + 1] * rGs[i + 1] - 3.0 * cus * rGs[i + 1] * iGs[i + 1] * iGs[i + 1] + - sus * pow (iGs[i + 1], 3)); + } + if (data->nphe > 3) { + phe += (1. / 24.) * pow (Q2, 4) + * (cus * pow (rGs[i + 1], 4) + 4.0 * sus * iGs[i + 1] * pow (rGs[i + 1], 3) - 6.0 * cus * pow (iGs[i + 1] * rGs[i + 1], 2) + - 4.0 * sus * pow (iGs[i + 1], 3) * rGs[i + 1] + cus * pow (iGs[i + 1], 4)); + } + y2 = exp (-Q2 * g0) * (exp (Q2 * rGs[i + 1]) * cos (Q2 * iGs[i + 1] - u * s[i + 1]) - phe); - printf("quadFunc: not converged\n"); - printf("%f %f %d %.6e %.6e %.16e\n",x1,x2,n,s1,s2,s2-s1); - - return -sqrt(-1.0); -}; + rSF += 0.5 * (s[i + 1] - s[i]) * (y1 + y2); + } + rSF *= 2; + fprintf (filep, "%f %f %f %.6e %.6e %.6e %.6e\n", Q2, nu, u, S1, S2, S3, rSF); + fflush (filep); + nu += 0.05; + } + fclose (filep); -double trapezFunc(int n, double umin, double umax, double v, struct IncoherentPhonon_physics_storage_struct *data, - double (*func)(double,double,struct IncoherentPhonon_physics_storage_struct *)) -{ - int i; - double u, du, s; + free (s); + free (rGs); + free (iGs); + } - if(n<=0) { - printf("quad: invalid n = %d\n",n); - exit(1); + void + computeGs (double s, double* rGs, double* iGs, struct IncoherentPhonon_physics_storage_struct* data) { + double tol = 1.0e-6; + *rGs = quadFunc (-1, 1, s, tol, data, realGsInt); + *iGs = quadFunc (-1, 1, s, tol, data, imagGsInt); } - du = (umax-umin)/n; + double + realGsInt (double u, double s, struct IncoherentPhonon_physics_storage_struct* data) { + return Gu (u, data) * cos (u * s); + } - u = umin; - s = 0.5*du*func(u,v,data); - for(i=1;iup[n-1]) { - if(fabs(u-up[n-1])<1.0e-8) { return Fp[n-1]; } - printf("interpFunc out of range np: %.16e %.16e\n",u,up[n-1]); - return -sqrt(-1.); - } + filep = fopen ("quad.txt", "a"); - // linear interpolation - imin=0; imax=n-1; - while(imax-imin>1) { - i = (imax + imin)/2; - if (uup[imax]) { - printf("interpFunc: bad bracketing: %d %d %f %f %f\n",imin,imax,up[imin],u,up[imax]); - return -sqrt(-1.); - } + n = 100; + s1 = trapezFunc (n, x1, x2, v, data, func); + n = 200; + s2 = trapezFunc (n, x1, x2, v, data, func); + if (fabs (0.5 * (s1 + s2)) < 10) { + relTol = tol; + } else { + relTol = tol * fabs (0.5 * (s1 + s2)); + } + fprintf (filep, "%f %d %.6e %.6e %.16e %.16e\n", v, n, s1, s2, s2 - s1, relTol); + fflush (filep); + while (n < nFCmax) { + if (fabs (0.5 * (s1 + s2)) < 10) { + relTol = tol; + } else { + relTol = tol * fabs (0.5 * (s1 + s2)); + } + if (fabs (s2 - s1) < relTol) { + fprintf (filep, "===============\n"); + fclose (filep); + return s2; + } + n *= 2; + s1 = s2; + s2 = trapezFunc (n, x1, x2, v, data, func); + fprintf (filep, "%f %d %.6e %.6e %.16e %.16e\n", v, n, s1, s2, s2 - s1, relTol); + fflush (filep); + } + + fprintf (filep, "===============\n"); + fclose (filep); + + printf ("quadFunc: not converged\n"); + printf ("%f %f %d %.6e %.6e %.16e\n", x1, x2, n, s1, s2, s2 - s1); - // slope - a = (Fp[imax]-Fp[imin])/(up[imax]-up[imin]); - - return Fp[imin] + a*(u-up[imin]); -}; - -//////////////////////////////////////// -// double differential cross section /// -//////////////////////////////////////// - -// the following functions are for computing the differential cross sections, not not for simulation - -void compute_dXS_dEp_dOmega(struct IncoherentPhonon_physics_storage_struct *data) -{ - double h = 4.13567; // planck constant in meV*ps - int i, n = 200000; - double *s, *rGs, *iGs; - double smin, smax, ds; - double E, Ep, Epmin, Epmax, dEp, z, dz; - double xs0, xs1, xs2, xs3, Smp0, Smp1, Smp2, Smp3; - FILE *filep, *filep2; - - if(data->s!=NULL) { free(data->s); data->s = NULL; } - if(data->rGs!=NULL) { free(data->rGs); data->rGs = NULL; } - if(data->iGs!=NULL) { free(data->iGs); data->iGs = NULL; } - - filep = fopen("Gs.txt","r"); - fprintf(data->filep," compute_dXS_dEp_dOmega: open Gs done\n"); - fflush(data->filep); - if(filep != NULL) { - fscanf(filep,"%d",&n); - printf("n=%d\n",n); - s = (double *)malloc(n*sizeof(double)); - rGs = (double *)malloc(n*sizeof(double)); - iGs = (double *)malloc(n*sizeof(double)); - for(i=0;inpGs = n; - data->s = s; - data->rGs = rGs; - data->iGs = iGs; - } else { - smin = 0; - smax = 200; - ds = (smax - smin)/n; - s = (double *)malloc(n*sizeof(double)); - rGs = (double *)malloc(n*sizeof(double)); - iGs = (double *)malloc(n*sizeof(double)); - filep = fopen("Gs.txt","w"); - fprintf(filep,"%d\n",n); - for(i=0;inpGs = n; - data->s = s; - data->rGs = rGs; - data->iGs = iGs; - } + u = umax; + s += 0.5 * du * func (u, v, data); - E = 400.0; // meV - - dz = 0.1; - Epmin = 0.5*E; - Epmax = E + 10*(data->Emax); - dEp = (Epmax-Epmin)/1000; - - filep = fopen("double_diff_XS.txt","w"); - fprintf(filep,"#E: %f\n",E); - fflush(filep); - filep2 = fopen("XS_mp.txt","w"); - fprintf(filep2,"#E: %f\n",E); - fflush(filep2); - z = -1.0; - while(z<1.0) { - Ep = Epmin; - while(EpEmax; - double x = sqrt(Ep/E); - double Q2 = 1.0 + x*x - 2.0*x*z; - - if(Q2<=0) { return 0; } - - Erat = E/Emax; - Mrat = (MNEUTRON/amu)/data->M; - - Q2 *= Erat*Mrat; - u = (E-Ep)/Emax; - - // p-phonon contribution - W = Q2*(data->g0); - fac1 = 1.0; - if(data->nphe>0) { - yp = W; - fac1 += yp; - if(fabs(u)<1) { - Fp1 = interpFunc(u,data->nF1,data->u1,data->F1); - Sphe = yp*Fp1; - } else { - Sphe = 0; + return s; + }; + + double + interpFunc (double u, int n, double* up, double* Fp) { + int i, imin, imax; + double a; + + if (u < up[0]) { + if (fabs (u - up[0]) < 1.0e-8) { + return Fp[0]; + } + printf ("interpFunc out of range 0: %.16e %.16e\n", u, up[0]); + return -sqrt (-1.); } - } - if(data->nphe>1) { - yp *= W; - fac1 += 0.5*yp; - if(fabs(u)<2) { - Fp2 = interpFunc(u,data->nF2,data->u2,data->F2); - Sphe += 0.5*yp*Fp2; - } else { - Sphe += 0; + if (u > up[n - 1]) { + if (fabs (u - up[n - 1]) < 1.0e-8) { + return Fp[n - 1]; + } + printf ("interpFunc out of range np: %.16e %.16e\n", u, up[n - 1]); + return -sqrt (-1.); } - } - if(data->nphe>2) { - yp *= W; - fac1 += yp/6.; - if(fabs(u)<3) { - Fp3 = interpFunc(u,data->nF3,data->u3,data->F3); - Sphe += yp*Fp3/6.; + + // linear interpolation + imin = 0; + imax = n - 1; + while (imax - imin > 1) { + i = (imax + imin) / 2; + if (u < up[i]) { + imax = i; + } else { + imin = i; + } + } + + if (imax == imin) { + printf ("interpFunc: imax = imin %d %d\n", imin, imax); + return -sqrt (-1.0); + } + if (u < up[imin] || u > up[imax]) { + printf ("interpFunc: bad bracketing: %d %d %f %f %f\n", imin, imax, up[imin], u, up[imax]); + return -sqrt (-1.); + } + + // slope + a = (Fp[imax] - Fp[imin]) / (up[imax] - up[imin]); + + return Fp[imin] + a * (u - up[imin]); + }; + + //////////////////////////////////////// + // double differential cross section /// + //////////////////////////////////////// + + // the following functions are for computing the differential cross sections, not not for simulation + + void + compute_dXS_dEp_dOmega (struct IncoherentPhonon_physics_storage_struct* data) { + double h = 4.13567; // planck constant in meV*ps + int i, n = 200000; + double *s, *rGs, *iGs; + double smin, smax, ds; + double E, Ep, Epmin, Epmax, dEp, z, dz; + double xs0, xs1, xs2, xs3, Smp0, Smp1, Smp2, Smp3; + FILE *filep, *filep2; + + if (data->s != NULL) { + free (data->s); + data->s = NULL; + } + if (data->rGs != NULL) { + free (data->rGs); + data->rGs = NULL; + } + if (data->iGs != NULL) { + free (data->iGs); + data->iGs = NULL; + } + + filep = fopen ("Gs.txt", "r"); + fprintf (data->filep, " compute_dXS_dEp_dOmega: open Gs done\n"); + fflush (data->filep); + if (filep != NULL) { + fscanf (filep, "%d", &n); + printf ("n=%d\n", n); + s = (double*)malloc (n * sizeof (double)); + rGs = (double*)malloc (n * sizeof (double)); + iGs = (double*)malloc (n * sizeof (double)); + for (i = 0; i < n; i++) { + fscanf (filep, "%lf %lf %lf", s + i, rGs + i, iGs + i); + } + fclose (filep); + // assign + data->npGs = n; + data->s = s; + data->rGs = rGs; + data->iGs = iGs; } else { - Sphe += 0; + smin = 0; + smax = 200; + ds = (smax - smin) / n; + s = (double*)malloc (n * sizeof (double)); + rGs = (double*)malloc (n * sizeof (double)); + iGs = (double*)malloc (n * sizeof (double)); + filep = fopen ("Gs.txt", "w"); + fprintf (filep, "%d\n", n); + for (i = 0; i < n; i++) { + s[i] = smin + i * ds; + computeGs (s[i], rGs + i, iGs + i, data); + fprintf (filep, "%.16e %.16e %.16e\n", s[i], rGs[i], iGs[i]); + fflush (filep); + } + fclose (filep); + // assign + data->npGs = n; + data->s = s; + data->rGs = rGs; + data->iGs = iGs; } - } - if(data->nphe>3) { - fprintf(data->filep,"dXS_dEp_dO: too large nphe = %d\n",data->nphe); - exit(1); + + E = 400.0; // meV + + dz = 0.1; + Epmin = 0.5 * E; + Epmax = E + 10 * (data->Emax); + dEp = (Epmax - Epmin) / 1000; + + filep = fopen ("double_diff_XS.txt", "w"); + fprintf (filep, "#E: %f\n", E); + fflush (filep); + filep2 = fopen ("XS_mp.txt", "w"); + fprintf (filep2, "#E: %f\n", E); + fflush (filep2); + z = -1.0; + while (z < 1.0) { + Ep = Epmin; + while (Ep < Epmax) { + xs0 = dXS_dEp_dOmega (0, E, Ep, z, &Smp0, data); + xs1 = dXS_dEp_dOmega (1, E, Ep, z, &Smp1, data); + xs2 = dXS_dEp_dOmega (2, E, Ep, z, &Smp2, data); + xs3 = dXS_dEp_dOmega (3, E, Ep, z, &Smp3, data); + fprintf (filep, "%f %.6e %.6e %.6e %.6e %.6e\n", z, Ep, xs0, xs1, xs2, xs3); + fflush (filep); + fprintf (filep2, "%f %.6e %.6e %.6e %.6e %.6e\n", z, Ep, Smp0, Smp1, Smp2, Smp3); + fflush (filep2); + Ep += dEp; + } + fprintf (filep, "\n\n"); + fflush (filep); + fprintf (filep2, "\n\n"); + fflush (filep2); + z += dz; + } + fclose (filep2); + fclose (filep2); } - EDW = exp(-W); - fac1 = 1.0 - EDW*fac1; + double + dXS_dEp_dOmega (int type, double E, double Ep, double z, double* XSmphon, struct IncoherentPhonon_physics_storage_struct* data) { + double Erat, Mrat, S, Sphe, Smp, Fp1, Fp2, Fp3, W, EDW, yp, u; + double fac1, fac2, tol; + double Emax = data->Emax; + double x = sqrt (Ep / E); + double Q2 = 1.0 + x * x - 2.0 * x * z; - Sphe *= EDW; + if (Q2 <= 0) { + return 0; + } - // multiphonon - switch(type) { - case 0: - Smp = exactS(u,Q2,data); // no need for normalization - break; - case 1: - tol = 1.0e-6; - fac2 = 1.0/integral_Smp_phe(Q2,tol,data); - Smp = fac1*fac2*Smp_phe(u,Q2,data); - break; - case 2: - Smp = Sgauss(u,Q2,data); // no need for normalization - break; - case 3: - fac2 = 1.0/(Q2*interpFunc(Q2,data->np_Q2_mph,data->Q2,data->SQ2_mph)); - Smp = fac1*fac2*SFuncInterp(u/Q2,Q2,data); - break; - default: - fprintf(data->filep,"dXS_dEp_dO: bad type %d\n",type); - exit(1); + Erat = E / Emax; + Mrat = (MNEUTRON / amu) / data->M; + + Q2 *= Erat * Mrat; + u = (E - Ep) / Emax; + + // p-phonon contribution + W = Q2 * (data->g0); + fac1 = 1.0; + if (data->nphe > 0) { + yp = W; + fac1 += yp; + if (fabs (u) < 1) { + Fp1 = interpFunc (u, data->nF1, data->u1, data->F1); + Sphe = yp * Fp1; + } else { + Sphe = 0; + } + } + if (data->nphe > 1) { + yp *= W; + fac1 += 0.5 * yp; + if (fabs (u) < 2) { + Fp2 = interpFunc (u, data->nF2, data->u2, data->F2); + Sphe += 0.5 * yp * Fp2; + } else { + Sphe += 0; + } + } + if (data->nphe > 2) { + yp *= W; + fac1 += yp / 6.; + if (fabs (u) < 3) { + Fp3 = interpFunc (u, data->nF3, data->u3, data->F3); + Sphe += yp * Fp3 / 6.; + } else { + Sphe += 0; + } + } + if (data->nphe > 3) { + fprintf (data->filep, "dXS_dEp_dO: too large nphe = %d\n", data->nphe); + exit (1); + } + + EDW = exp (-W); + fac1 = 1.0 - EDW * fac1; + + Sphe *= EDW; + + // multiphonon + switch (type) { + case 0: + Smp = exactS (u, Q2, data); // no need for normalization + break; + case 1: + tol = 1.0e-6; + fac2 = 1.0 / integral_Smp_phe (Q2, tol, data); + Smp = fac1 * fac2 * Smp_phe (u, Q2, data); + break; + case 2: + Smp = Sgauss (u, Q2, data); // no need for normalization + break; + case 3: + fac2 = 1.0 / (Q2 * interpFunc (Q2, data->np_Q2_mph, data->Q2, data->SQ2_mph)); + Smp = fac1 * fac2 * SFuncInterp (u / Q2, Q2, data); + break; + default: + fprintf (data->filep, "dXS_dEp_dO: bad type %d\n", type); + exit (1); + } + + *XSmphon = (data->sigmaCoh + data->sigmaInc) * x * Smp / (4.0 * PI * Emax); + + S = Sphe + Smp; + + // sigma in barn/meV + return (data->sigmaCoh + data->sigmaInc) * x * S / (4.0 * PI * Emax); } - *XSmphon = (data->sigmaCoh+data->sigmaInc)*x*Smp/(4.0*PI*Emax); + //////////////////////////////// + // functions for the DoS /// + //////////////////////////////// - S = Sphe + Smp; + double + dos (double E, struct IncoherentPhonon_physics_storage_struct* data) { + int i, imin, imax; + double Emax = data->Emax; + double* e = data->e; + double* Z = data->Z; + int np = data->np; - // sigma in barn/meV - return (data->sigmaCoh+data->sigmaInc)*x*S/(4.0*PI*Emax); -} + // if(E<=0 || E>=Emax) { return 0; } -//////////////////////////////// -// functions for the DoS /// -//////////////////////////////// + if (E < 0) { + E = -E; + } -double dos(double E, struct IncoherentPhonon_physics_storage_struct *data) -{ - int i, imin, imax; - double Emax = data->Emax; - double *e = data->e; - double *Z = data->Z; - int np = data->np; + if (E >= Emax) { + return 0; + } - //if(E<=0 || E>=Emax) { return 0; } + // parabolic around E=0 + if (E <= e[1]) { + return (data->dosPar) * E * E; + } - if(E<0) { E = -E; } + // linear interpolation elsewhere + imin = 1; + imax = np - 1; + while (imax - imin > 1) { + i = (imax + imin) / 2; + if (E < e[i]) { + imax = i; + } else { + imin = i; + } + } - if(E>=Emax) { return 0; } + return Z[imin] + (E - e[imin]) * (Z[imax] - Z[imin]) / (e[imax] - e[imin]); + }; - // parabolic around E=0 - if(E<=e[1]) { - return (data->dosPar)*E*E; - } + void + readDoS (struct IncoherentPhonon_physics_storage_struct* data) { + char *snp = "#np:", s[100] = ""; + int i, np, nptrim, nread; + double *e, *Z, norm; + FILE* filep; - // linear interpolation elsewhere - imin=1; imax=np-1; - while(imax-imin>1) { - i = (imax + imin)/2; - if (Edosfn, "r"); - return Z[imin]+(E-e[imin])*(Z[imax]-Z[imin])/(e[imax]-e[imin]); -}; + if (filep == NULL) { + fprintf (data->filep, "readDos: dos file %s not found\n", data->dosfn); + fprintf (data->filep, "stopping computation\n"); + printf ("readDos: dos file %s not found\n", data->dosfn); + printf ("stopping computation\n"); + exit (1); + } -void readDoS(struct IncoherentPhonon_physics_storage_struct *data) -{ - char *snp = "#np:", s[100]=""; - int i, np, nptrim, nread; - double *e, *Z, norm; - FILE *filep; + while (strcmp (s, snp)) { + nread = fscanf (filep, "%s", s); + if (nread != 1) { + printf ("readDoS: not valid file %s\n", data->dosfn); + printf ("stopping computation\n"); + fprintf (data->filep, "readDoS: not valid file %s\n", data->dosfn); + fprintf (data->filep, "stopping computation\n"); + exit (1); + } + } + nread = fscanf (filep, "%d", &np); - filep = fopen(data->dosfn,"r"); + e = (double*)malloc (np * sizeof (double)); + Z = (double*)malloc (np * sizeof (double)); - if(filep==NULL) { - fprintf(data->filep,"readDos: dos file %s not found\n",data->dosfn); - fprintf(data->filep,"stopping computation\n"); - printf("readDos: dos file %s not found\n",data->dosfn); - printf("stopping computation\n"); - exit(1); - } + for (i = 0; i < np; i++) { + nread = fscanf (filep, "%lf %lf", e + i, Z + i); + } - while(strcmp(s,snp)) { - nread = fscanf(filep,"%s",s); - if(nread!=1) { - printf("readDoS: not valid file %s\n",data->dosfn); - printf("stopping computation\n"); - fprintf(data->filep,"readDoS: not valid file %s\n",data->dosfn); - fprintf(data->filep,"stopping computation\n"); - exit(1); - } - } - nread = fscanf(filep,"%d",&np); + fclose (filep); - e = (double *)malloc(np*sizeof(double)); - Z = (double *)malloc(np*sizeof(double)); + // Make DoS vanish at E=0 + for (i = np - 1; i >= 0; i--) { + Z[i] -= Z[0]; + } - for(i=0;i= 0; i--) { + if (Z[i] > 1.0e-12) { + nptrim = i + 2; + break; + } + } - fclose(filep); + data->np = nptrim; + data->e = (double*)malloc (nptrim * sizeof (double)); + data->Z = (double*)malloc (nptrim * sizeof (double)); + for (i = 0; i < nptrim && i < np; i++) { + (data->e)[i] = e[i]; + (data->Z)[i] = Z[i]; + } + if (nptrim > np) { + (data->e)[nptrim - 1] = 2. * e[np - 1] - e[nptrim - 2]; + } + (data->Z)[nptrim - 1] = 0; - // Make DoS vanish at E=0 - for(i=np-1;i>=0;i--) { Z[i] -= Z[0]; } + // parameters + data->dosPar = (data->Z)[1] / pow ((data->e)[1] - (data->e)[0], 2); + data->Emax = (data->e)[nptrim - 1]; - //trim the dos - nptrim = 0; - for(i=np-1;i>=0;i--) { - if(Z[i]>1.0e-12) { - nptrim = i+2; - break; + // dos normalization (very important) + norm = (data->dosPar) * pow ((data->e)[1], 3) / 3.; // parabolic at origin + for (i = 2; i < nptrim; i++) { + norm += 0.5 * ((data->Z)[i] + (data->Z)[i - 1]) * ((data->e)[i] - (data->e)[i - 1]); } - } + for (i = 0; i < nptrim; i++) { + (data->Z)[i] /= norm; + } + data->dosPar /= norm; - data->np = nptrim; - data->e = (double *)malloc(nptrim*sizeof(double)); - data->Z = (double *)malloc(nptrim*sizeof(double)); - for(i=0;ie)[i] = e[i]; - (data->Z)[i] = Z[i]; - } - if(nptrim > np) { - (data->e)[nptrim-1] = 2.*e[np-1] - e[nptrim-2]; - } - (data->Z)[nptrim-1] = 0; + fprintf (data->filep, "DoS norm: %f\n", norm); - // parameters - data->dosPar = (data->Z)[1]/pow((data->e)[1]-(data->e)[0],2); - data->Emax = (data->e)[nptrim-1]; + free (e); + free (Z); - // dos normalization (very important) - norm = (data->dosPar)*pow((data->e)[1],3)/3.; // parabolic at origin - for(i=2;iZ)[i]+(data->Z)[i-1])*((data->e)[i]-(data->e)[i-1]); - } - for(i=0;iZ)[i] /= norm; - } - data->dosPar /= norm; + filep = fopen ("interpDoS.txt", "w"); + for (i = 0; i < 10001; i++) { + fprintf (filep, "%.16e %.16e\n", i * (data->Emax) / 10000, dos (i * (data->Emax) / 10000, data)); + } + fclose (filep); + }; + + ////////////////////////////// + // initialization functions // + ////////////////////////////// + + void + setParams (struct IncoherentPhonon_physics_storage_struct* data, int nphe_exact, int nphe_approx, int approx, int mph_resum, double T, double density, double M, + double sigmaCoh, double sigmaInc, double kabsmin, double kabsmax, int nxs, char* dosfn, int ntsp, double ximin, double ximax, char* filelog) { + // log file + data->filep = fopen (filelog, "w"); + fprintf (data->filep, "Initializing\n"); + + data->nphe_exact = nphe_exact; + data->nphe_approx = nphe_approx; + data->approx = approx; + data->mph_resum = mph_resum; + + data->npmax = data->nphe_approx; + data->nphe = nphe_exact; + + // initialize parameters + data->T = T; + data->density = density; + data->M = M; + data->sigmaCoh = sigmaCoh; + data->sigmaInc = sigmaInc; + data->kabsmin = kabsmin; + data->kabsmax = kabsmax; + data->nxs = nxs; + data->kBT = kB * T; + data->mRat = (MNEUTRON / amu) / M; + data->XS2mu = 100 * (density / M) * (NA * barn2cmsq); // the factor 100 to convert from cm-1 to m-1 - fprintf(data->filep,"DoS norm: %f\n",norm); + data->ntsp = ntsp; + data->ximin = ximin; + data->ximax = ximax; + data->xi1 = 0.8; + data->xi2 = 1.2; + + data->tolSaddlePoint = 1.0e-8; + data->tolQuadratureFs = 1.0e-6; + data->tolQuadratureGs = 1.0e-8; + + data->np_u_mph = 100; + data->tol_dXSdu_mph = 1.0e-6; + + data->np_Q2_mph = 1000; + + strcpy (data->dosfn, dosfn); + + readDoS (data); + + data->g0 = Gt (0, data); + data->d2g0 = d2Gt (0, data); + + fprintf (data->filep, "Parameters computed\n"); + fprintf (data->filep, "*************************\n"); + fprintf (data->filep, "Input parameters:\n"); + fprintf (data->filep, "nphe_exact: %d\n", data->nphe_exact); + fprintf (data->filep, "nphe_approx: %d\n", data->nphe_approx); + fprintf (data->filep, "approx: %d\n", data->approx); + fprintf (data->filep, "mph_resum: %d\n", data->mph_resum); + fprintf (data->filep, "T: %f\n", data->T); + fprintf (data->filep, "density: %f\n", data->density); + fprintf (data->filep, "M: %f\n", data->M); + fprintf (data->filep, "sigmaCoh: %f\n", data->sigmaCoh); + fprintf (data->filep, "sigmaInc: %f\n", data->sigmaInc); + fprintf (data->filep, "kabsmin: %f\n", data->kabsmin); + fprintf (data->filep, "kabsmax: %f\n", data->kabsmax); + fprintf (data->filep, "nxs: %d\n", data->nxs); + fprintf (data->filep, "kBT: %f\n", data->kBT); + fprintf (data->filep, "mRat: %f\n", data->mRat); + fprintf (data->filep, "XS2mu: %f\n", data->XS2mu); + fprintf (data->filep, "Emax: %f\n", data->Emax); + fprintf (data->filep, "dosPar: %f\n", data->dosPar); + fprintf (data->filep, "ntsp: %d\n", data->ntsp); + fprintf (data->filep, "ximin: %f\n", data->ximin); + fprintf (data->filep, "ximax: %f\n", data->ximax); + fprintf (data->filep, "G(0): %f\n", data->g0); + fprintf (data->filep, "d2G(0): %f\n", data->d2g0); + fprintf (data->filep, "np_u_mph: %d\n", data->np_u_mph); + fprintf (data->filep, "np_Q2_mph: %d\n", data->np_Q2_mph); + fprintf (data->filep, "tolSaddlePoint: %.6e\n", data->tolSaddlePoint); + fprintf (data->filep, "tolQuadratureGs: %.6e\n", data->tolQuadratureGs); + fprintf (data->filep, "tolQuadratureFs: %.6e\n", data->tolQuadratureFs); + fprintf (data->filep, "tol_dXSdu_mph: %.6e\n", data->tol_dXSdu_mph); + fprintf (data->filep, "*************************\n"); + + fflush (data->filep); + + // Null pointers + data->xs_p_phe_gauss = NULL; + data->xs_p_phe_sp = NULL; + + // for multiphonon expansion gaussian approximation + if (data->approx == 1) { + computeEpsilon (data); + data->Delta = sqrt (4. * (data->epsilon) * (data->g0) / 3. - 1.) / (data->g0); + data->Delta2 = (data->Delta) * (data->Delta); + + if (data->nphe_approx > 0) { + data->xs_p_phe_gauss = (double*)malloc ((data->nphe_approx + 1) * sizeof (double)); + } - free(e); - free(Z); + fprintf (data->filep, "epsilon: %.6e\n", data->epsilon); + fprintf (data->filep, "Delta: %.6e\n", data->Delta); + fprintf (data->filep, "*************************\n"); + fflush (data->filep); + } - filep = fopen("interpDoS.txt","w"); - for(i=0;i<10001;i++) { - fprintf(filep,"%.16e %.16e\n",i*(data->Emax)/10000,dos(i*(data->Emax)/10000,data)); - } - fclose(filep); -}; - -////////////////////////////// -// initialization functions // -////////////////////////////// - -void setParams(struct IncoherentPhonon_physics_storage_struct *data, - int nphe_exact, int nphe_approx, int approx, int mph_resum, - double T, double density, double M, - double sigmaCoh, double sigmaInc, - double kabsmin, double kabsmax, int nxs, - char *dosfn, int ntsp, double ximin, double ximax, char *filelog) -{ - // log file - data->filep = fopen(filelog,"w"); - fprintf(data->filep,"Initializing\n"); - - data->nphe_exact = nphe_exact; - data->nphe_approx = nphe_approx; - data->approx = approx; - data->mph_resum = mph_resum; - - data->npmax = data->nphe_approx; - data->nphe = nphe_exact; - - // initialize parameters - data->T = T; - data->density = density; - data->M = M; - data->sigmaCoh = sigmaCoh; - data->sigmaInc = sigmaInc; - data->kabsmin = kabsmin; - data->kabsmax = kabsmax; - data->nxs = nxs; - data->kBT = kB*T; - data->mRat = (MNEUTRON/amu)/M; - data->XS2mu = 100*(density/M)*(NA*barn2cmsq); //the factor 100 to convert from cm-1 to m-1 - - data->ntsp = ntsp; - data->ximin = ximin; - data->ximax = ximax; - data->xi1 = 0.8; - data->xi2 = 1.2; - - data->tolSaddlePoint = 1.0e-8; - data->tolQuadratureFs = 1.0e-6; - data->tolQuadratureGs = 1.0e-8; - - data->np_u_mph = 100; - data->tol_dXSdu_mph = 1.0e-6; - - data->np_Q2_mph = 1000; - - strcpy(data->dosfn,dosfn); - - readDoS(data); - - data->g0 = Gt(0,data); - data->d2g0 = d2Gt(0,data); - - fprintf(data->filep,"Parameters computed\n"); - fprintf(data->filep,"*************************\n"); - fprintf(data->filep,"Input parameters:\n"); - fprintf(data->filep,"nphe_exact: %d\n",data->nphe_exact); - fprintf(data->filep,"nphe_approx: %d\n",data->nphe_approx); - fprintf(data->filep,"approx: %d\n",data->approx); - fprintf(data->filep,"mph_resum: %d\n",data->mph_resum); - fprintf(data->filep,"T: %f\n",data->T); - fprintf(data->filep,"density: %f\n",data->density); - fprintf(data->filep,"M: %f\n",data->M); - fprintf(data->filep,"sigmaCoh: %f\n",data->sigmaCoh); - fprintf(data->filep,"sigmaInc: %f\n",data->sigmaInc); - fprintf(data->filep,"kabsmin: %f\n",data->kabsmin); - fprintf(data->filep,"kabsmax: %f\n",data->kabsmax); - fprintf(data->filep,"nxs: %d\n",data->nxs); - fprintf(data->filep,"kBT: %f\n",data->kBT); - fprintf(data->filep,"mRat: %f\n",data->mRat); - fprintf(data->filep,"XS2mu: %f\n",data->XS2mu); - fprintf(data->filep,"Emax: %f\n",data->Emax); - fprintf(data->filep,"dosPar: %f\n",data->dosPar); - fprintf(data->filep,"ntsp: %d\n",data->ntsp); - fprintf(data->filep,"ximin: %f\n",data->ximin); - fprintf(data->filep,"ximax: %f\n",data->ximax); - fprintf(data->filep,"G(0): %f\n",data->g0); - fprintf(data->filep,"d2G(0): %f\n",data->d2g0); - fprintf(data->filep,"np_u_mph: %d\n",data->np_u_mph); - fprintf(data->filep,"np_Q2_mph: %d\n",data->np_Q2_mph); - fprintf(data->filep,"tolSaddlePoint: %.6e\n",data->tolSaddlePoint); - fprintf(data->filep,"tolQuadratureGs: %.6e\n",data->tolQuadratureGs); - fprintf(data->filep,"tolQuadratureFs: %.6e\n",data->tolQuadratureFs); - fprintf(data->filep,"tol_dXSdu_mph: %.6e\n",data->tol_dXSdu_mph); - fprintf(data->filep,"*************************\n"); - - fflush(data->filep); - - // Null pointers - data->xs_p_phe_gauss = NULL; - data->xs_p_phe_sp = NULL; - - // for multiphonon expansion gaussian approximation - if(data->approx==1) { - computeEpsilon(data); - data->Delta = sqrt(4.*(data->epsilon)*(data->g0)/3.-1.)/(data->g0); - data->Delta2 = (data->Delta)*(data->Delta); - - if(data->nphe_approx>0) { - data->xs_p_phe_gauss = (double *)malloc((data->nphe_approx+1)*sizeof(double)); - } - - fprintf(data->filep,"epsilon: %.6e\n",data->epsilon); - fprintf(data->filep,"Delta: %.6e\n",data->Delta); - fprintf(data->filep,"*************************\n"); - fflush(data->filep); - } + // for multiphonon expansion in SP approximation + if (data->approx == 2) { + data->ntsp_p = 1000; + data->ximin_p = -0.99; + data->ximax_p = -data->ximin_p; - // for multiphonon expansion in SP approximation - if(data->approx==2) { - data->ntsp_p = 1000; - data->ximin_p = -0.99; - data->ximax_p = -data->ximin_p; + if (data->nphe_approx > 0) { + data->xs_p_phe_sp = (double*)malloc ((data->nphe_approx + 1) * sizeof (double)); + } - if(data->nphe_approx>0) { - data->xs_p_phe_sp = (double *)malloc((data->nphe_approx+1)*sizeof(double)); + fprintf (data->filep, "ntsp_p: %d\n", data->ntsp_p); + fprintf (data->filep, "xmin_p: %f\n", data->ximin_p); + fprintf (data->filep, "xmax_p: %f\n", data->ximax_p); + fprintf (data->filep, "*************************\n"); + fflush (data->filep); } - fprintf(data->filep,"ntsp_p: %d\n",data->ntsp_p); - fprintf(data->filep,"xmin_p: %f\n",data->ximin_p); - fprintf(data->filep,"xmax_p: %f\n",data->ximax_p); - fprintf(data->filep,"*************************\n"); - fflush(data->filep); - } + // precompute total cross sections and other data + precomputations (data); + + fprintf (data->filep, "setParams: precomputations done\n"); + fflush (data->filep); + }; - // precompute total cross sections and other data - precomputations(data); + //////////////////////////// + // finishing functions //// + //////////////////////////// - fprintf(data->filep,"setParams: precomputations done\n"); - fflush(data->filep); -}; + int + finish (struct IncoherentPhonon_physics_storage_struct* data) { + // deallocate allocated memory -//////////////////////////// -// finishing functions //// -//////////////////////////// + int p; -int finish(struct IncoherentPhonon_physics_storage_struct *data) -{ - // deallocate allocated memory + if (data->e != NULL) { + free (data->e); + data->e = NULL; + } + if (data->Z != NULL) { + free (data->Z); + data->Z = NULL; + } - int p; + if (data->kabs != NULL) { + free (data->kabs); + data->kabs = NULL; + } - if(data->e != NULL) { free(data->e); data->e=NULL;} - if(data->Z != NULL) { free(data->Z); data->Z=NULL;} + if (data->xsTot_1ph != NULL) { + free (data->xsTot_1ph); + data->xsTot_1ph = NULL; + } + if (data->xsTot_2ph != NULL) { + free (data->xsTot_2ph); + data->xsTot_2ph = NULL; + } + if (data->xsTot_3ph != NULL) { + free (data->xsTot_3ph); + data->xsTot_3ph = NULL; + } + if (data->xsTot_mph != NULL) { + free (data->xsTot_mph); + data->xsTot_mph = NULL; + } + if (data->dXSdx_xmax_1ph != NULL) { + free (data->dXSdx_xmax_1ph); + data->dXSdx_xmax_1ph = NULL; + } + if (data->dXSdx_xmax_2ph != NULL) { + free (data->dXSdx_xmax_2ph); + data->dXSdx_xmax_2ph = NULL; + } + if (data->dXSdx_xmax_3ph != NULL) { + free (data->dXSdx_xmax_3ph); + data->dXSdx_xmax_3ph = NULL; + } + if (data->dXSdx_Fmax_1ph != NULL) { + free (data->dXSdx_Fmax_1ph); + data->dXSdx_Fmax_1ph = NULL; + } + if (data->dXSdx_Fmax_2ph != NULL) { + free (data->dXSdx_Fmax_2ph); + data->dXSdx_Fmax_2ph = NULL; + } + if (data->dXSdx_Fmax_3ph != NULL) { + free (data->dXSdx_Fmax_3ph); + data->dXSdx_Fmax_3ph = NULL; + } - if(data->kabs != NULL) { free(data->kabs); data->kabs=NULL;} + if (data->xs_p_phe_gauss != NULL) { + free (data->xs_p_phe_gauss); + } + if (data->xsTot_pph_gauss != NULL) { + for (p = 1; p <= data->nphe_approx; p++) { + free ((data->xsTot_pph_gauss)[p]); + } + free (data->xsTot_pph_gauss); + } + if (data->dXSdx_xmax_pph_gauss != NULL) { + for (p = 1; p <= data->nphe_approx; p++) { + free ((data->dXSdx_xmax_pph_gauss)[p]); + } + free (data->dXSdx_xmax_pph_gauss); + } + if (data->dXSdx_Fmax_pph_gauss != NULL) { + for (p = 1; p <= data->nphe_approx; p++) { + free ((data->dXSdx_Fmax_pph_gauss)[p]); + } + free (data->dXSdx_Fmax_pph_gauss); + } - if(data->xsTot_1ph != NULL) { free(data->xsTot_1ph); data->xsTot_1ph=NULL; } - if(data->xsTot_2ph != NULL) { free(data->xsTot_2ph); data->xsTot_2ph=NULL; } - if(data->xsTot_3ph != NULL) { free(data->xsTot_3ph); data->xsTot_3ph=NULL; } - if(data->xsTot_mph != NULL) { free(data->xsTot_mph); data->xsTot_mph=NULL; } - if(data->dXSdx_xmax_1ph != NULL) { free(data->dXSdx_xmax_1ph); data->dXSdx_xmax_1ph=NULL; } - if(data->dXSdx_xmax_2ph != NULL) { free(data->dXSdx_xmax_2ph); data->dXSdx_xmax_2ph=NULL; } - if(data->dXSdx_xmax_3ph != NULL) { free(data->dXSdx_xmax_3ph); data->dXSdx_xmax_3ph=NULL; } - if(data->dXSdx_Fmax_1ph != NULL) { free(data->dXSdx_Fmax_1ph); data->dXSdx_Fmax_1ph=NULL; } - if(data->dXSdx_Fmax_2ph != NULL) { free(data->dXSdx_Fmax_2ph); data->dXSdx_Fmax_2ph=NULL; } - if(data->dXSdx_Fmax_3ph != NULL) { free(data->dXSdx_Fmax_3ph); data->dXSdx_Fmax_3ph=NULL; } + if (data->xs_p_phe_sp != NULL) { + free (data->xs_p_phe_sp); + } + if (data->xsTot_pph_sp != NULL) { + for (p = 1; p <= data->nphe_approx; p++) { + free ((data->xsTot_pph_sp)[p]); + } + free (data->xsTot_pph_sp); + } + if (data->dXSdx_xmax_pph_sp != NULL) { + for (p = 1; p <= data->nphe_approx; p++) { + free ((data->dXSdx_xmax_pph_sp)[p]); + } + free (data->dXSdx_xmax_pph_sp); + } + if (data->dXSdx_Fmax_pph_sp != NULL) { + for (p = 1; p <= data->nphe_approx; p++) { + free ((data->dXSdx_Fmax_pph_sp)[p]); + } + free (data->dXSdx_Fmax_pph_sp); + } - if(data->xs_p_phe_gauss != NULL) { free(data->xs_p_phe_gauss); } - if(data->xsTot_pph_gauss != NULL) { - for(p=1;p<=data->nphe_approx;p++) { free((data->xsTot_pph_gauss)[p]); } - free(data->xsTot_pph_gauss); - } - if(data->dXSdx_xmax_pph_gauss != NULL) { - for(p=1;p<=data->nphe_approx;p++) { free((data->dXSdx_xmax_pph_gauss)[p]); } - free(data->dXSdx_xmax_pph_gauss); - } - if(data->dXSdx_Fmax_pph_gauss != NULL) { - for(p=1;p<=data->nphe_approx;p++) { free((data->dXSdx_Fmax_pph_gauss)[p]); } - free(data->dXSdx_Fmax_pph_gauss); - } + if (data->u != NULL) { + free (data->u); + data->u = NULL; + } + if (data->dXSdu_mph != NULL) { + free (data->dXSdu_mph); + data->dXSdu_mph = NULL; + } - if(data->xs_p_phe_sp != NULL) { free(data->xs_p_phe_sp); } - if(data->xsTot_pph_sp != NULL) { - for(p=1;p<=data->nphe_approx;p++) { free((data->xsTot_pph_sp)[p]); } - free(data->xsTot_pph_sp); - } - if(data->dXSdx_xmax_pph_sp != NULL) { - for(p=1;p<=data->nphe_approx;p++) { free((data->dXSdx_xmax_pph_sp)[p]); } - free(data->dXSdx_xmax_pph_sp); - } - if(data->dXSdx_Fmax_pph_sp != NULL) { - for(p=1;p<=data->nphe_approx;p++) { free((data->dXSdx_Fmax_pph_sp)[p]); } - free(data->dXSdx_Fmax_pph_sp); - } + if (data->u1 != NULL) { + free (data->u1); + data->u1 = NULL; + } + if (data->u2 != NULL) { + free (data->u2); + data->u2 = NULL; + } + if (data->u3 != NULL) { + free (data->u3); + data->u3 = NULL; + } + if (data->F1 != NULL) { + free (data->F1); + data->F1 = NULL; + } + if (data->F2 != NULL) { + free (data->F2); + data->F2 = NULL; + } + if (data->F3 != NULL) { + free (data->F3); + data->F3 = NULL; + } - if(data->u != NULL) { free(data->u); data->u=NULL; } - if(data->dXSdu_mph != NULL) { free(data->dXSdu_mph); data->dXSdu_mph=NULL; } + if (data->xi != NULL) { + free (data->xi); + data->xi = NULL; + } + if (data->tsp != NULL) { + free (data->tsp); + data->tsp = NULL; + } + if (data->g != NULL) { + free (data->g); + data->g = NULL; + } + if (data->d2g != NULL) { + free (data->d2g); + data->d2g = NULL; + } + if (data->H != NULL) { + free (data->H); + data->H = NULL; + } - if(data->u1 != NULL) { free(data->u1); data->u1=NULL; } - if(data->u2 != NULL) { free(data->u2); data->u2=NULL; } - if(data->u3 != NULL) { free(data->u3); data->u3=NULL; } - if(data->F1 != NULL) { free(data->F1); data->F1=NULL; } - if(data->F2 != NULL) { free(data->F2); data->F2=NULL; } - if(data->F3 != NULL) { free(data->F3); data->F3=NULL; } + if (data->u != NULL) { + free (data->u); + data->u = NULL; + } + if (data->dXSdu_mph != NULL) { + free (data->dXSdu_mph); + data->dXSdu_mph = NULL; + } - if(data->xi != NULL) { free(data->xi); data->xi=NULL; } - if(data->tsp != NULL) { free(data->tsp); data->tsp=NULL; } - if(data->g != NULL) { free(data->g); data->g=NULL; } - if(data->d2g != NULL) { free(data->d2g); data->d2g=NULL; } - if(data->H != NULL) { free(data->H); data->H=NULL; } + if (data->Q2min != NULL) { + free (data->Q2min); + data->Q2min = NULL; + } + if (data->Q2max != NULL) { + free (data->Q2max); + data->Q2max = NULL; + } - if(data->u != NULL) { free(data->u); data->u=NULL; } - if(data->dXSdu_mph != NULL) { free(data->dXSdu_mph); data->dXSdu_mph=NULL; } + if (data->Q2 != NULL) { + free (data->Q2); + data->Q2 = NULL; + } + if (data->SQ2_mph != NULL) { + free (data->SQ2_mph); + data->SQ2_mph = NULL; + } - if(data->Q2min != NULL) { free(data->Q2min); data->Q2min=NULL; } - if(data->Q2max != NULL) { free(data->Q2max); data->Q2max=NULL; } + if (data->xi_p != NULL) { + free (data->xi_p); + data->xi_p = NULL; + } + if (data->tsp_p != NULL) { + free (data->tsp_p); + data->tsp_p = NULL; + } + if (data->g_p != NULL) { + free (data->g_p); + data->g_p = NULL; + } + if (data->d2gDg_p != NULL) { + free (data->d2gDg_p); + data->d2gDg_p = NULL; + } - if(data->Q2 != NULL) { free(data->Q2); data->Q2=NULL; } - if(data->SQ2_mph != NULL) { free(data->SQ2_mph); data->SQ2_mph=NULL; } + if (data->dXSdQ2_Q2max_mph != NULL) { + free (data->dXSdQ2_Q2max_mph); + data->dXSdQ2_Q2max_mph = NULL; + } + if (data->dXSdQ2_Fmax_mph != NULL) { + free (data->dXSdQ2_Fmax_mph); + data->dXSdQ2_Fmax_mph = NULL; + } - if(data->xi_p != NULL) { free(data->xi_p); data->xi_p=NULL; } - if(data->tsp_p != NULL) { free(data->tsp_p); data->tsp_p=NULL; } - if(data->g_p != NULL) { free(data->g_p); data->g_p=NULL; } - if(data->d2gDg_p != NULL) { free(data->d2gDg_p); data->d2gDg_p=NULL; } + if (data->s != NULL) { + free (data->s); + data->s = NULL; + } + if (data->rGs != NULL) { + free (data->rGs); + data->rGs = NULL; + } + if (data->iGs != NULL) { + free (data->iGs); + data->iGs = NULL; + } - if(data->dXSdQ2_Q2max_mph != NULL) { free(data->dXSdQ2_Q2max_mph); data->dXSdQ2_Q2max_mph=NULL; } - if(data->dXSdQ2_Fmax_mph != NULL) { free(data->dXSdQ2_Fmax_mph); data->dXSdQ2_Fmax_mph=NULL; } + fprintf (data->filep, "run finished\n"); - if(data->s != NULL) { free(data->s); data->s=NULL; } - if(data->rGs != NULL) { free(data->rGs); data->rGs=NULL; } - if(data->iGs != NULL) { free(data->iGs); data->iGs=NULL; } + if (data->filep != NULL) { + fclose (data->filep); + data->filep = NULL; + } - fprintf(data->filep,"run finished\n"); - - if(data->filep!=NULL) { fclose(data->filep); data->filep=NULL; } - - return 1; -}; + return 1; + }; -// End implementation of internal functions + // End implementation of internal functions -#ifndef PROCESS_DETECTOR - //struct pointer_to_global_process_list global_process_list = {0,NULL}; - #define PROCESS_DETECTOR dummy -#endif + #ifndef PROCESS_DETECTOR + // struct pointer_to_global_process_list global_process_list = {0,NULL}; + #define PROCESS_DETECTOR dummy + #endif -#ifndef PROCESS_INCOHERENTPHONON_DETECTOR - #define PROCESS_INCOHERENTPHONON_DETECTOR dummy -#endif + #ifndef PROCESS_INCOHERENTPHONON_DETECTOR + #define PROCESS_INCOHERENTPHONON_DETECTOR dummy + #endif %} DECLARE %{ -// Needed for transport to the main component -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; - -// Declare for this component, to do calculations on the input / store in the transported data -struct IncoherentPhonon_physics_storage_struct IncoherentPhonon_storage; + // Needed for transport to the main component + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; + // Declare for this component, to do calculations on the input / store in the transported data + struct IncoherentPhonon_physics_storage_struct IncoherentPhonon_storage; %} INITIALIZE %{ // Initialize done in the component char filelog[250]; - sprintf(filelog,"IncoherentPhonon_process_%s.log",NAME_CURRENT_COMP); + sprintf (filelog, "IncoherentPhonon_process_%s.log", NAME_CURRENT_COMP); // parameters for numerical computation - int ntsp = 2000; + int ntsp = 2000; double ximin = -200; double ximax = 200; - setParams(&IncoherentPhonon_storage, - nphe_exact, nphe_approx, approx, mph_resum, - T,density,M,sigmaCoh,sigmaInc,kabsmin,kabsmax,nxs, - DOSfn,ntsp,ximin,ximax,filelog); + setParams (&IncoherentPhonon_storage, nphe_exact, nphe_approx, approx, mph_resum, T, density, M, sigmaCoh, sigmaInc, kabsmin, kabsmax, nxs, DOSfn, ntsp, ximin, + ximax, filelog); - fprintf(IncoherentPhonon_storage.filep,"setParams done\n"); - fflush(IncoherentPhonon_storage.filep); + fprintf (IncoherentPhonon_storage.filep, "setParams done\n"); + fflush (IncoherentPhonon_storage.filep); - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic This_process.non_isotropic_rot_index = -1; // Yes (powder) - //This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No // The type of the process must be saved in the global enum process This_process.eProcess = IncoherentPhonon; // Packing the data into a structure that is transported to the main component - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); This_process.process_p_interact = interact_fraction; This_process.data_transfer.pointer_to_a_IncoherentPhonon_physics_storage_struct = &IncoherentPhonon_storage; @@ -4670,22 +5174,20 @@ INITIALIZE This_process.scattering_function = &IncoherentPhonon_physics_scattering; // This will be the same for all process's, and can thus be moved to an include. - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; - if (_getcomp_index(init) < 0) { - fprintf(stderr,"IncoherentPhonon_process:%s: Error identifying Union_init component, %s is not a known component name.\n", - NAME_CURRENT_COMP, init); - exit(-1); + if (_getcomp_index (init) < 0) { + fprintf (stderr, "IncoherentPhonon_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); } + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); -struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list,global_process_element); - - fprintf(IncoherentPhonon_storage.filep,"Initialization done\n"); - fflush(IncoherentPhonon_storage.filep); + fprintf (IncoherentPhonon_storage.filep, "Initialization done\n"); + fflush (IncoherentPhonon_storage.filep); %} TRACE @@ -4694,9 +5196,9 @@ TRACE FINALLY %{ -// deallocate allocated memory, etc. -struct IncoherentPhonon_physics_storage_struct *data = This_process.data_transfer.pointer_to_a_IncoherentPhonon_physics_storage_struct; -finish(data); + // deallocate allocated memory, etc. + struct IncoherentPhonon_physics_storage_struct* data = This_process.data_transfer.pointer_to_a_IncoherentPhonon_physics_storage_struct; + finish (data); %} END diff --git a/mcstas-comps/union/Incoherent_process.comp b/mcstas-comps/union/Incoherent_process.comp index 801cade2a0..bb9da5d4c1 100755 --- a/mcstas-comps/union/Incoherent_process.comp +++ b/mcstas-comps/union/Incoherent_process.comp @@ -60,124 +60,126 @@ SETTING PARAMETERS(sigma=5.08, f_QE=0, gamma=0, packing_factor=1, unit_cell_volu SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Incoherent_process component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Incoherent_process component" + #endif - -struct Incoherent_physics_storage_struct{ + struct Incoherent_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + double my_scattering; double QE_sampling_frequency; double lorentzian_width; - -}; + }; -// Function for calculating my in Incoherent case -int Incoherent_physics_my(double *my,double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function for calculating my in Incoherent case + int + Incoherent_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { *my = data_transfer.pointer_to_a_Incoherent_physics_storage_struct->my_scattering; return 1; -}; + }; -// Function for basic incoherent scattering event -int Incoherent_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function for basic incoherent scattering event + int + Incoherent_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, + struct focus_data_struct* focus_data, _class_particle* _particle) { - //New version of incoherent scattering - double k_length = sqrt(k_initial[0]*k_initial[0]+k_initial[1]*k_initial[1]+k_initial[2]*k_initial[2]); + // New version of incoherent scattering + double k_length = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); Coords k_out; // Here is the focusing system in action, get a vector double solid_angle; - focus_data->focusing_function(&k_out,&solid_angle,focus_data); - NORM(k_out.x,k_out.y,k_out.z); - *weight *= solid_angle*0.25/PI; - - double v_i,v_f,E_i,dE,E_f; - - if (rand01() < data_transfer.pointer_to_a_Incoherent_physics_storage_struct->QE_sampling_frequency) { + focus_data->focusing_function (&k_out, &solid_angle, focus_data); + NORM (k_out.x, k_out.y, k_out.z); + *weight *= solid_angle * 0.25 / PI; + + double v_i, v_f, E_i, dE, E_f; + + if (rand01 () < data_transfer.pointer_to_a_Incoherent_physics_storage_struct->QE_sampling_frequency) { v_i = k_length * K2V; - E_i = VS2E*v_i*v_i; - dE = data_transfer.pointer_to_a_Incoherent_physics_storage_struct->lorentzian_width*tan(PI/2*randpm1()); + E_i = VS2E * v_i * v_i; + dE = data_transfer.pointer_to_a_Incoherent_physics_storage_struct->lorentzian_width * tan (PI / 2 * randpm1 ()); E_f = E_i + dE; if (E_f <= 0) return 0; - v_f = SE2V*sqrt(E_f); - k_length = v_f*V2K; + v_f = SE2V * sqrt (E_f); + k_length = v_f * V2K; } - - k_final[0] = k_out.x*k_length; k_final[1] = k_out.y*k_length; k_final[2] = k_out.z*k_length; + + k_final[0] = k_out.x * k_length; + k_final[1] = k_out.y * k_length; + k_final[2] = k_out.z * k_length; return 1; -}; + }; -#ifndef PROCESS_DETECTOR - #define PROCESS_DETECTOR dummy -#endif + #ifndef PROCESS_DETECTOR + #define PROCESS_DETECTOR dummy + #endif -#ifndef PROCESS_INCOHERENT_DETECTOR - #define PROCESS_INCOHERENT_DETECTOR dummy -#endif + #ifndef PROCESS_INCOHERENT_DETECTOR + #define PROCESS_INCOHERENT_DETECTOR dummy + #endif %} DECLARE %{ -// Needed for transport to the main component -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; - -// Declare for this component, to do calculations on the input / store in the transported data -struct Incoherent_physics_storage_struct Incoherent_storage; -double effective_my_scattering; + // Needed for transport to the main component + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; + // Declare for this component, to do calculations on the input / store in the transported data + struct Incoherent_physics_storage_struct Incoherent_storage; + double effective_my_scattering; %} INITIALIZE %{ // Initialize done in the component - effective_my_scattering = ((packing_factor/unit_cell_volume) * 100 * sigma); + effective_my_scattering = ((packing_factor / unit_cell_volume) * 100 * sigma); Incoherent_storage.my_scattering = effective_my_scattering; - + Incoherent_storage.QE_sampling_frequency = f_QE; Incoherent_storage.lorentzian_width = gamma; - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic This_process.non_isotropic_rot_index = -1; // Yes (powder) - //This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No // The type of the process must be saved in the global enum process This_process.eProcess = Incoherent; // Packing the data into a structure that is transported to the main component - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); This_process.process_p_interact = interact_fraction; This_process.data_transfer.pointer_to_a_Incoherent_physics_storage_struct = &Incoherent_storage; - //This_process.data_transfer.pointer_to_a_Incoherent_physics_storage_struct->my_scattering = effective_my_scattering; + // This_process.data_transfer.pointer_to_a_Incoherent_physics_storage_struct->my_scattering = effective_my_scattering; This_process.probability_for_scattering_function = &Incoherent_physics_my; This_process.scattering_function = &Incoherent_physics_scattering; // This will be the same for all process's, and can thus be moved to an include. - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; - if (_getcomp_index(init) < 0) { - fprintf(stderr,"Incoherent_process:%s: Error identifying Union_init component, %s is not a known component name.\n", - NAME_CURRENT_COMP, init); - exit(-1); + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Incoherent_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); } - struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list, global_process_element); + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE @@ -186,8 +188,7 @@ TRACE FINALLY %{ -// Since the process and it's storage is a static allocation, there is nothing to deallocate - + // Since the process and it's storage is a static allocation, there is nothing to deallocate %} END diff --git a/mcstas-comps/union/Mirror_surface.comp b/mcstas-comps/union/Mirror_surface.comp index 5c1ec79868..b5a32ebc99 100644 --- a/mcstas-comps/union/Mirror_surface.comp +++ b/mcstas-comps/union/Mirror_surface.comp @@ -60,121 +60,125 @@ SETTING PARAMETERS(string reflect=0, R0=0.99, Qc=0.0219, alpha=6.07, m=2, W=0.00 SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Mirror_surface component" -#endif - - -%include "read_table-lib" -%include "ref-lib" - -// Very important to add a pointer to this struct in the union-lib.c file -struct Mirror_surface_storage_struct{ + #ifndef Union + #error "The Union_init component must be included before this Mirror_surface component" + #endif + + %include "read_table-lib" + %include "ref-lib" + + // Very important to add a pointer to this struct in the union-lib.c file + struct Mirror_surface_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + // Avoid duplicates of setting parameters in naming - double par[5]; - t_Table pTable; - int table_present; -}; - -// Function for handling surface physics -// The input for this function and its order may not be changed, but the names may be updated. -int Mirror_surface_function(union surface_data_transfer_union data_transfer, // data in struct defined above, can have data stored in initialize and other calls to this function - double *weight, double *wavevector, int *continues, // given weight and wavevector, to be updated, and pointer to continues which should be provided by function - double *normal_vector, enum in_or_out inward_or_outward, // normal_vector of surface and information on whether the neutron is going into or out of this surface - _class_particle *_particle) { + double par[5]; + t_Table pTable; + int table_present; + }; + + // Function for handling surface physics + // The input for this function and its order may not be changed, but the names may be updated. + int + Mirror_surface_function ( + union surface_data_transfer_union data_transfer, // data in struct defined above, can have data stored in initialize and other calls to this function + double* weight, double* wavevector, + int* continues, // given weight and wavevector, to be updated, and pointer to continues which should be provided by function + double* normal_vector, + enum in_or_out inward_or_outward, // normal_vector of surface and information on whether the neutron is going into or out of this surface + _class_particle* _particle) { // wavevector and normal_vector are a pointers to a simple array with 3 doubles, wavevector[0], wavevector[1], wavevector[2] which describes the vector - // Retrieve data storage struct - struct Mirror_surface_storage_struct *storage; - storage = data_transfer.pointer_to_a_Mirror_surface_storage_struct; - - double k_n_dot = wavevector[0]*normal_vector[0] + wavevector[1]*normal_vector[1] + wavevector[2]*normal_vector[2]; - - // Calculate q normal - double q_normal = 2.0*fabs(k_n_dot); - - // Calculate or read reflectivity - double reflectivity; - if (storage->table_present == 1) { - TableReflecFunc(q_normal, &storage->pTable, &reflectivity); - } else { - StdReflecFunc(q_normal, storage->par, &reflectivity); - } - - // Take monte carlo choice on whether to be reflected by the mirror or not - if (rand01() > reflectivity) { - *continues = 1; // Tells algorithm the ray goes through this surface - } else { - // mirror ray - wavevector[0] = wavevector[0] - 2.0 * k_n_dot * normal_vector[0]; - wavevector[1] = wavevector[1] - 2.0 * k_n_dot * normal_vector[1]; - wavevector[2] = wavevector[2] - 2.0 * k_n_dot * normal_vector[2]; - - if ((wavevector[0]*normal_vector[0] + wavevector[1]*normal_vector[1] + wavevector[2]*normal_vector[2])*k_n_dot > 0) printf("w.n same sign before and after reflection?? \n"); - - *continues = 0; // Tells algorithm the ray does not go through this surface - } + // Retrieve data storage struct + struct Mirror_surface_storage_struct* storage; + storage = data_transfer.pointer_to_a_Mirror_surface_storage_struct; + + double k_n_dot = wavevector[0] * normal_vector[0] + wavevector[1] * normal_vector[1] + wavevector[2] * normal_vector[2]; + + // Calculate q normal + double q_normal = 2.0 * fabs (k_n_dot); + + // Calculate or read reflectivity + double reflectivity; + if (storage->table_present == 1) { + TableReflecFunc (q_normal, &storage->pTable, &reflectivity); + } else { + StdReflecFunc (q_normal, storage->par, &reflectivity); + } + + // Take monte carlo choice on whether to be reflected by the mirror or not + if (rand01 () > reflectivity) { + *continues = 1; // Tells algorithm the ray goes through this surface + } else { + // mirror ray + wavevector[0] = wavevector[0] - 2.0 * k_n_dot * normal_vector[0]; + wavevector[1] = wavevector[1] - 2.0 * k_n_dot * normal_vector[1]; + wavevector[2] = wavevector[2] - 2.0 * k_n_dot * normal_vector[2]; + + if ((wavevector[0] * normal_vector[0] + wavevector[1] * normal_vector[1] + wavevector[2] * normal_vector[2]) * k_n_dot > 0) + printf ("w.n same sign before and after reflection?? \n"); + + *continues = 0; // Tells algorithm the ray does not go through this surface + } return 1; - + // There is access to the data_transfer from within this function: // int table_present = data_transfer.pointer_to_a_Mirror_physics_storage_struct->table_present; - // Its even possible to write to this data structure and use results for a later ray if relevant -}; - -// These lines help with future error correction, and tell other Union components -// that at least one surface have been defined. -#ifndef SURFACE_DETECTOR - #define SURFACE_DETECTOR dummy -#endif -#ifndef SURFACE_PROCESS_MIRROR_DETECTOR - #define SURFACE_PROCESS_MIRROR_DETECTOR dummy -#endif + // Its even possible to write to this data structure and use results for a later ray if relevant + }; + + // These lines help with future error correction, and tell other Union components + // that at least one surface have been defined. + #ifndef SURFACE_DETECTOR + #define SURFACE_DETECTOR dummy + #endif + #ifndef SURFACE_PROCESS_MIRROR_DETECTOR + #define SURFACE_PROCESS_MIRROR_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct Mirror_surface_storage_struct Mirror_storage; // Replace Mirror with your own name here + // Declare for this component, to do calculations on the input / store in the transported data + struct Mirror_surface_storage_struct Mirror_storage; // Replace Mirror with your own name here -// Needed for transport to the main component, will be the same for all surface processes -struct global_surface_element_struct global_surface_element; -struct surface_process_struct This_surface; + // Needed for transport to the main component, will be the same for all surface processes + struct global_surface_element_struct global_surface_element; + struct surface_process_struct This_surface; %} INITIALIZE %{ // Initialize done in the component - if (reflect && strlen(reflect) && strcmp(reflect,"NULL") && strcmp(reflect,"0")) { - if (Table_Read(&Mirror_storage.pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */ - exit(fprintf(stderr,"Mirror_surface: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect)); - Mirror_storage.table_present=1; + if (reflect && strlen (reflect) && strcmp (reflect, "NULL") && strcmp (reflect, "0")) { + if (Table_Read (&Mirror_storage.pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */ + exit (fprintf (stderr, "Mirror_surface: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect)); + Mirror_storage.table_present = 1; } else { - Mirror_storage.table_present=0; - if (W < 0 || R0 < 0 || Qc < 0 || m < 0) { - fprintf(stderr,"Mirror_surface: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP); - exit(-1); - } + Mirror_storage.table_present = 0; + if (W < 0 || R0 < 0 || Qc < 0 || m < 0) { + fprintf (stderr, "Mirror_surface: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP); + exit (-1); + } } - + // Insert input parameter to par array as required for the standard reflectivity function Mirror_storage.par[0] = R0; Mirror_storage.par[1] = Qc; Mirror_storage.par[2] = alpha; Mirror_storage.par[3] = m; - Mirror_storage.par[4] = W; + Mirror_storage.par[4] = W; // Will need to do similar system for surfaces // Need to specify if this process is isotropic - //This_process.non_isotropic_rot_index = -1; // Yes (powder) - //This_process.non_isotropic_rot_index = 1; // No (single crystal) - //rot_copy(This_surface.rotation_matrix, ROT_A_CURRENT_COMP); + // This_process.non_isotropic_rot_index = -1; // Yes (powder) + // This_process.non_isotropic_rot_index = 1; // No (single crystal) + // rot_copy(This_surface.rotation_matrix, ROT_A_CURRENT_COMP); // The type of the process must be saved in the global enum process located in union-lib.c This_surface.eSurface = Mirror; @@ -183,24 +187,23 @@ INITIALIZE This_surface.data_transfer.pointer_to_a_Mirror_surface_storage_struct = &Mirror_storage; // This will be the same for all process's, and can thus be moved to an include. - sprintf(This_surface.name,"%s",NAME_CURRENT_COMP); - sprintf(global_surface_element.name,"%s",NAME_CURRENT_COMP); + sprintf (This_surface.name, "%s", NAME_CURRENT_COMP); + sprintf (global_surface_element.name, "%s", NAME_CURRENT_COMP); global_surface_element.component_index = INDEX_CURRENT_COMP; global_surface_element.p_surface_process = &This_surface; - if (_getcomp_index(init) < 0) { - fprintf(stderr,"Mirror_surface:%s: Error identifying Union_init component, %s is not a known component name.\n", - NAME_CURRENT_COMP, init); - exit(-1); + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Mirror_surface:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); } - struct pointer_to_global_surface_list *global_surface_list = COMP_GETPAR3(Union_init, init, global_surface_list); - add_element_to_surface_list(global_surface_list, global_surface_element); + struct pointer_to_global_surface_list* global_surface_list = COMP_GETPAR3 (Union_init, init, global_surface_list); + add_element_to_surface_list (global_surface_list, global_surface_element); %} TRACE %{ - // Trace should be empty, the simulation is perfomed in Union_master + // Trace should be empty, the simulation is perfomed in Union_master %} END diff --git a/mcstas-comps/union/NCrystal_process.comp b/mcstas-comps/union/NCrystal_process.comp index 4daadb9274..7e4144c827 100644 --- a/mcstas-comps/union/NCrystal_process.comp +++ b/mcstas-comps/union/NCrystal_process.comp @@ -120,21 +120,21 @@ DEPENDENCY "@NCRYSTALFLAGS@" SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this NCrystal_process component" -#endif - -#include "NCrystal/ncrystal.h" -#include "stdio.h" -#include "stdlib.h" -#ifndef NCMCERR2 + #ifndef Union + #error "The Union_init component must be included before this NCrystal_process component" + #endif + + #include "NCrystal/ncrystal.h" + #include "stdio.h" + #include "stdlib.h" + #ifndef NCMCERR2 /* consistent/convenient error reporting */ -# define NCMCERR2(compname,msg) do { fprintf(stderr, "\nNCrystal: %s: ERROR: %s\n\n", compname, msg); exit(1); } while (0) -#endif + # define NCMCERR2(compname,msg) do { fprintf(stderr, "\nNCrystal: %s: ERROR: %s\n\n", compname, msg); exit(1); } while (0) + #endif static int ncsample_reported_version_union = 0; - //Keep all instance-specific parameters on a few structs: + // Keep all instance-specific parameters on a few structs: typedef struct { double density_factor; double inv_density_factor; @@ -144,265 +144,265 @@ SHARE int absmode; } ncrystalsample_t_union; -#ifndef NCMCERR + #ifndef NCMCERR /* more convenient form (only works in TRACE section, not in SHARE functions) */ -# define NCMCERR(msg) NCMCERR2(NAME_CURRENT_COMP,msg) -#endif + # define NCMCERR(msg) NCMCERR2(NAME_CURRENT_COMP,msg) + #endif -// Very important to add a pointer to this struct in the union-lib.c file -struct NCrystal_physics_storage_struct{ + // Very important to add a pointer to this struct in the union-lib.c file + struct NCrystal_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + // Avoid duplicates of output parameters and setting parameters in naming ncrystalsample_t_union stored_params; double ncrystal_convfact_vsq2ekin; double ncrystal_convfact_ekin2vsq; -}; + }; -// Function for calculating my, the inverse penetration depth (for only this scattering process). -// The input for this function and its order may not be changed, but the names may be updated. -int NCrystal_physics_my(double *my, double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function for calculating my, the inverse penetration depth (for only this scattering process). + // The input for this function and its order may not be changed, but the names may be updated. + int + NCrystal_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, _class_particle* _particle) { // *k_initial is a pointer to a simple vector with 3 doubles, k[0], k[1], k[2] which describes the wavevector - double k_mag = sqrt(k_initial[0]*k_initial[0] + k_initial[1]*k_initial[1] + k_initial[2]*k_initial[2]); - + double k_mag = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); + // Normalized direction dir[3] double dir[3]; - dir[0] = k_initial[0]/k_mag; - dir[1] = k_initial[1]/k_mag; - dir[2] = k_initial[2]/k_mag; - + dir[0] = k_initial[0] / k_mag; + dir[1] = k_initial[1] / k_mag; + dir[2] = k_initial[2] / k_mag; + // Kinetic energy double vsq2ekin = data_transfer.pointer_to_a_NCrystal_physics_storage_struct->ncrystal_convfact_vsq2ekin; - - double ekin = vsq2ekin*K2V*k_mag*K2V*k_mag; - + + double ekin = vsq2ekin * K2V * k_mag * K2V * k_mag; + double xsect_scat = 0.0; // Call NCrystal library, xsect_scat is updated - ncrystal_crosssection(data_transfer.pointer_to_a_NCrystal_physics_storage_struct->stored_params.proc_scat, ekin, (const double(*)[3])&dir, &xsect_scat); + ncrystal_crosssection (data_transfer.pointer_to_a_NCrystal_physics_storage_struct->stored_params.proc_scat, ekin, (const double (*)[3]) & dir, &xsect_scat); double density_factor = data_transfer.pointer_to_a_NCrystal_physics_storage_struct->stored_params.density_factor; // Convert xsect_scat to inverse penetration depth *my = xsect_scat / density_factor; - + return 1; -}; + }; -// Function that provides description of a basic scattering event. -// Do not change the function signature - int NCrystal_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function that provides description of a basic scattering event. + // Do not change the function signature + int + NCrystal_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { // Magnitude of given wavevector - double k_mag = sqrt(k_initial[0]*k_initial[0] + k_initial[1]*k_initial[1] + k_initial[2]*k_initial[2]); - + double k_mag = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); + // Normalized direction dir[3] double dir[3], dirout[3]; - dir[0] = k_initial[0]/k_mag; - dir[1] = k_initial[1]/k_mag; - dir[2] = k_initial[2]/k_mag; - + dir[0] = k_initial[0] / k_mag; + dir[1] = k_initial[1] / k_mag; + dir[2] = k_initial[2] / k_mag; + double vsq2ekin = data_transfer.pointer_to_a_NCrystal_physics_storage_struct->ncrystal_convfact_vsq2ekin; double ekin, delta_ekin, v2, absv; - - ekin = vsq2ekin*K2V*k_mag*K2V*k_mag; + + ekin = vsq2ekin * K2V * k_mag * K2V * k_mag; delta_ekin = 0.0; // Call NCrystal library, dirout and delta_ekin is updated - ncrystal_genscatter(data_transfer.pointer_to_a_NCrystal_physics_storage_struct->stored_params.scat, ekin, (const double(*)[3])&dir, &dirout, &delta_ekin); - + ncrystal_genscatter (data_transfer.pointer_to_a_NCrystal_physics_storage_struct->stored_params.scat, ekin, (const double (*)[3]) & dir, &dirout, &delta_ekin); + if (delta_ekin) { ekin += delta_ekin; - if (ekin<=0) { - //not expected to happen much, but an interaction could in principle bring the neutron to rest. + if (ekin <= 0) { + // not expected to happen much, but an interaction could in principle bring the neutron to rest. return 0; // Eqivalent to ABSORB } v2 = data_transfer.pointer_to_a_NCrystal_physics_storage_struct->ncrystal_convfact_ekin2vsq * ekin; - absv = sqrt(v2); - k_mag = absv*V2K; + absv = sqrt (v2); + k_mag = absv * V2K; } - - k_final[0] = dirout[0]*k_mag; - k_final[1] = dirout[1]*k_mag; - k_final[2] = dirout[2]*k_mag; - + + k_final[0] = dirout[0] * k_mag; + k_final[1] = dirout[1] * k_mag; + k_final[2] = dirout[2] * k_mag; + // A pointer to k_final is returned, and the wavevector will be set to k_final after a scattering event return 1; // return 1 is sucess, return 0 is failure, and the ray will be absorbed. // failure should not happen, as this function will only be called when // the cross section for the current k_initial is above zero. - + // There is access to the data_transfer from within the scattering function // In this case the only variable is my, but it could be read by: // double my = data_transfer.pointer_to_a_NCrystal_physics_storage_struct->my_scattering; // One can assume that if the scattering function is running, the my fuction was // executed just before and for the same k_initial. -#ifndef PROCESS_DETECTOR + #ifndef PROCESS_DETECTOR #define PROCESS_DETECTOR dummy -#endif + #endif -#ifndef PROCESS_NCRYSTAL_DETECTOR + #ifndef PROCESS_NCRYSTAL_DETECTOR #define PROCESS_NCRYSTAL_DETECTOR dummy -#endif -}; - + #endif + }; %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct NCrystal_physics_storage_struct NCrystal_storage; // Replace NCrystal with your own name here + // Declare for this component, to do calculations on the input / store in the transported data + struct NCrystal_physics_storage_struct NCrystal_storage; // Replace NCrystal with your own name here -// Variables needed in initialize of this function. + // Variables needed in initialize of this function. -// Needed for transport to the main component, will be the same for all processes -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Needed for transport to the main component, will be the same for all processes + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; -double NCrystal_convfact_ekin2vsq; -double NCrystal_convfact_vsq2ekin; + double NCrystal_convfact_ekin2vsq; + double NCrystal_convfact_vsq2ekin; -ncrystalsample_t_union params; + ncrystalsample_t_union params; -// These lines help with future error correction, and tell other Union components -// that at least one process have been defined. -#ifndef PROCESS_DETECTOR - // Obsolete - //struct pointer_to_global_process_list global_process_list = {0,NULL}; - #define PROCESS_DETECTOR dummy -#endif + // These lines help with future error correction, and tell other Union components + // that at least one process have been defined. + #ifndef PROCESS_DETECTOR + // Obsolete + // struct pointer_to_global_process_list global_process_list = {0,NULL}; + #define PROCESS_DETECTOR dummy + #endif %} INITIALIZE %{ // Initialize done in the component - //Print NCrystal version + sanity check setup. - if ( NCRYSTAL_VERSION != ncrystal_version() ) { - NCMCERR("Inconsistency detected between included ncrystal.h and linked NCrystal library!"); + // Print NCrystal version + sanity check setup. + if (NCRYSTAL_VERSION != ncrystal_version ()) { + NCMCERR ("Inconsistency detected between included ncrystal.h and linked NCrystal library!"); } - if (ncsample_reported_version_union != ncrystal_version()) { + if (ncsample_reported_version_union != ncrystal_version ()) { if (ncsample_reported_version_union) { - NCMCERR("Inconsistent NCrystal library versions detected - this should normally not be possible!"); + NCMCERR ("Inconsistent NCrystal library versions detected - this should normally not be possible!"); } - ncsample_reported_version_union = ncrystal_version(); - MPI_MASTER( - printf( "NCrystal: McStas Union process component(s) are using version %s of the NCrystal library.\n", ncrystal_version_str()); - ); + ncsample_reported_version_union = ncrystal_version (); + MPI_MASTER (printf ("NCrystal: McStas Union process component(s) are using version %s of the NCrystal library.\n", ncrystal_version_str ());); } - //The following conversion factors might look slightly odd. They reflect the - //fact that the various conversion factors used in McStas and NCrystal are not - //completely consistent among each other (TODO: Follow up on this with McStas - //developers!). Also McStas's V2K*K2V is not exactly 1. All in all, this can - //give issues when a McStas user is trying to set up a narrow beam very - //precisely in an instrument file, attempting to carefully hit a certain - //narrow Bragg reflection in this NCrystal component. We can not completely - //work around all issues here, but for now, we assume that the user is - //carefully setting up things by specifying the wavelength to some source - //component. That wavelength is then converted to the McStas state pars + // The following conversion factors might look slightly odd. They reflect the + // fact that the various conversion factors used in McStas and NCrystal are not + // completely consistent among each other (TODO: Follow up on this with McStas + // developers!). Also McStas's V2K*K2V is not exactly 1. All in all, this can + // give issues when a McStas user is trying to set up a narrow beam very + // precisely in an instrument file, attempting to carefully hit a certain + // narrow Bragg reflection in this NCrystal component. We can not completely + // work around all issues here, but for now, we assume that the user is + // carefully setting up things by specifying the wavelength to some source + // component. That wavelength is then converted to the McStas state pars //(vx,vy,vz) via K2V. We thus here first use 1/K2V (and *not* V2K) to convert - //back to a wavelength, and then we use NCrystal's conversion constants to - //convert the resulting wavelength to kinetic energy needed for NCrystal's - //interfaces. + // back to a wavelength, and then we use NCrystal's conversion constants to + // convert the resulting wavelength to kinetic energy needed for NCrystal's + // interfaces. // 0.0253302959105844428609698658024319097260896937 is 1/(4*pi^2) - NCrystal_convfact_vsq2ekin = ncrystal_wl2ekin(1.0) * 0.0253302959105844428609698658024319097260896937 / ( K2V*K2V ); + NCrystal_convfact_vsq2ekin = ncrystal_wl2ekin (1.0) * 0.0253302959105844428609698658024319097260896937 / (K2V * K2V); NCrystal_convfact_ekin2vsq = 1.0 / NCrystal_convfact_vsq2ekin; - //for our sanity, zero-initialise all instance-specific data: - memset(¶ms,0,sizeof(params)); + // for our sanity, zero-initialise all instance-specific data: + memset (¶ms, 0, sizeof (params)); /* Make sure NCrystal use the McStas RNG (ok if more than one component instance does this): */ -#ifndef rand01 + #ifndef rand01 /* Tell NCrystal to use the rand01 function provided by McStas: */ - ncrystal_setrandgen(rand01); -#else + ncrystal_setrandgen (rand01); + #else /* rand01 is actually a macro not an actual C-function (most likely defined as */ /* _rand01(_particle->randstate) for OPENACC purposes), which we can not */ /* register with NCrystal. As a workaround we tell NCrystal to use its own RNG */ /* algorithm, with merely the seed provided by McStas: */ - ncrystal_setbuiltinrandgen_withseed( mcseed ); -#endif + ncrystal_setbuiltinrandgen_withseed (mcseed); + #endif /* access powder packingfactor (nb: always 1.0 for non-powders): */ // Union change: multiplying by Union packing_factor - double packingfactor = ncrystal_decodecfg_packfact(cfg)*packing_factor; + double packingfactor = ncrystal_decodecfg_packfact (cfg) * packing_factor; /* access crystal structure to get number density (natoms/volume): */ - ncrystal_info_t info = ncrystal_create_info(cfg); - + ncrystal_info_t info = ncrystal_create_info (cfg); + // Depending on the version of NCrystal, the number density is retrieved in // two different ways. The preprocessor is used to switch between the two // methods depending on the NCRYSTAL_VERSION #if NCRYSTAL_VERSION >= 1099001 - double numberdensity = ncrystal_info_getnumberdensity(info); - if( numberdensity <= 0.0 ) - NCMCERR("Number density information is unavailable in the loaded NCrystal Info"); - ncrystal_unref(&info); - - //numberdensity is the atomic number density in units of Aa^-3=1e30m^3, and - //given that we have cross-sections in barn (1e-28m^2) and want to generate - //distances in meters with -log(R)/(numberdensity*xsect), we get the unit - //conversion factor of 0.01. We also apply the powder packing factor here (it - //is guaranteed to be non-zero): - - // Union change: In NCrystal_sample density factor is negative for easier sampling, - // but as the sampling is performed in the master we use a positive sign for the - // density factor as this is more intuitive. - params.density_factor = 0.01 / ( numberdensity * packingfactor ); - params.inv_density_factor = 1.0/params.density_factor; + double numberdensity = ncrystal_info_getnumberdensity (info); + if (numberdensity <= 0.0) + NCMCERR ("Number density information is unavailable in the loaded NCrystal Info"); + ncrystal_unref (&info); + + // numberdensity is the atomic number density in units of Aa^-3=1e30m^3, and + // given that we have cross-sections in barn (1e-28m^2) and want to generate + // distances in meters with -log(R)/(numberdensity*xsect), we get the unit + // conversion factor of 0.01. We also apply the powder packing factor here (it + // is guaranteed to be non-zero): + + // Union change: In NCrystal_sample density factor is negative for easier sampling, + // but as the sampling is performed in the master we use a positive sign for the + // density factor as this is more intuitive. + params.density_factor = 0.01 / (numberdensity * packingfactor); + params.inv_density_factor = 1.0 / params.density_factor; #else - unsigned cell_sg,cell_atnum; - double cell_a,cell_b,cell_c,cell_alpha,cell_beta,cell_gamma,cell_volume; - if(!ncrystal_info_getstructure(info,&cell_sg,&cell_a,&cell_b,&cell_c,&cell_alpha,&cell_beta,&cell_gamma,&cell_volume,&cell_atnum)) - NCMCERR("Structure information is unavailable in the loaded NCrystal Info"); - ncrystal_unref(&info); - - //cell_atnum/cell_volume is the atomic number density in units of - //Aa^-3=1e30m^3, and given that we have cross-sections in barn (1e-28m^2) and - //want to generate distances in meters with -log(R)/(numberdensity*xsect), we - //get the unit conversion factor of 0.01. We also apply the powder packing - //factor here (it is guaranteed to be non-zero): - - // Union change: In NCrystal_sample density factor is negative for easier sampling, - // but as the sampling is performed in the master we use a positive sign for the - // density factor as this is more intuitive. - params.density_factor = 0.01 * cell_volume / ( cell_atnum * packingfactor ); - params.inv_density_factor = 1.0/params.density_factor; + unsigned cell_sg, cell_atnum; + double cell_a, cell_b, cell_c, cell_alpha, cell_beta, cell_gamma, cell_volume; + if (!ncrystal_info_getstructure (info, &cell_sg, &cell_a, &cell_b, &cell_c, &cell_alpha, &cell_beta, &cell_gamma, &cell_volume, &cell_atnum)) + NCMCERR ("Structure information is unavailable in the loaded NCrystal Info"); + ncrystal_unref (&info); + + // cell_atnum/cell_volume is the atomic number density in units of + // Aa^-3=1e30m^3, and given that we have cross-sections in barn (1e-28m^2) and + // want to generate distances in meters with -log(R)/(numberdensity*xsect), we + // get the unit conversion factor of 0.01. We also apply the powder packing + // factor here (it is guaranteed to be non-zero): + + // Union change: In NCrystal_sample density factor is negative for easier sampling, + // but as the sampling is performed in the master we use a positive sign for the + // density factor as this is more intuitive. + params.density_factor = 0.01 * cell_volume / (cell_atnum * packingfactor); + params.inv_density_factor = 1.0 / params.density_factor; #endif - //TODO for NC2: The density used here is in principle different from the one - //used in the Geant4 interface, which is possibly inconsistent when not using + // TODO for NC2: The density used here is in principle different from the one + // used in the Geant4 interface, which is possibly inconsistent when not using //.ncmat files (more info at https://github.com/mctools/ncrystal/issues/9). - //Setup scattering: - params.scat = ncrystal_create_scatter(cfg); - params.proc_scat = ncrystal_cast_scat2proc(params.scat); - params.proc_scat_isoriented = ! ncrystal_isnonoriented(params.proc_scat); + // Setup scattering: + params.scat = ncrystal_create_scatter (cfg); + params.proc_scat = ncrystal_cast_scat2proc (params.scat); + params.proc_scat_isoriented = !ncrystal_isnonoriented (params.proc_scat); // It may be possible to get whether or not the physics is isotropic or not from the above - - //Setup absorption: + + // Setup absorption: if (params.absmode) { - params.proc_abs = ncrystal_cast_abs2proc(ncrystal_create_absorption(cfg)); - if (!ncrystal_isnonoriented(params.proc_abs)) - NCMCERR("Encountered oriented NCAbsorption process which is not currently supported by this component."); + params.proc_abs = ncrystal_cast_abs2proc (ncrystal_create_absorption (cfg)); + if (!ncrystal_isnonoriented (params.proc_abs)) + NCMCERR ("Encountered oriented NCAbsorption process which is not currently supported by this component."); } - + NCrystal_storage.stored_params = params; NCrystal_storage.ncrystal_convfact_vsq2ekin = NCrystal_convfact_vsq2ekin; NCrystal_storage.ncrystal_convfact_ekin2vsq = NCrystal_convfact_ekin2vsq; - - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic - //This_process.non_isotropic_rot_index = -1; // Yes (powder) - This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = -1; // Yes (powder) + This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No - + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No + // The type of the process must be saved in the global enum process This_process.eProcess = NCrystal; @@ -412,34 +412,33 @@ INITIALIZE This_process.scattering_function = &NCrystal_physics_scattering; // This will be the same for all process's, and can thus be moved to an include. - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); This_process.process_p_interact = interact_fraction; - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"NCrystal_process:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "NCrystal_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list, global_process_element); + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE %{ - // Trace should be empty, the simulation is done in Union_master + // Trace should be empty, the simulation is done in Union_master %} FINALLY %{ - ncrystal_unref(¶ms.scat); - ncrystal_invalidate(¶ms.proc_scat);//a cast of params.scat, so just invalidate handle don't unref + ncrystal_unref (¶ms.scat); + ncrystal_invalidate (¶ms.proc_scat); // a cast of params.scat, so just invalidate handle don't unref if (params.absmode) - ncrystal_unref(¶ms.proc_abs); + ncrystal_unref (¶ms.proc_abs); %} END diff --git a/mcstas-comps/union/Non_process.comp b/mcstas-comps/union/Non_process.comp index 47f5fe62d5..d96aa648c3 100755 --- a/mcstas-comps/union/Non_process.comp +++ b/mcstas-comps/union/Non_process.comp @@ -57,34 +57,37 @@ SETTING PARAMETERS(sigma=5.08,packing_factor=1,unit_cell_volume=13.8,interact_fr SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Non_process component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Non_process component" + #endif -// Very important to add a pointer to this struct in the union-lib.c file -struct Non_physics_storage_struct{ + // Very important to add a pointer to this struct in the union-lib.c file + struct Non_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + // Avoid duplicates of output parameters and setting parameters in naming double my_scattering; -}; + }; -// Function for calculating my, the inverse penetration depth (for only this scattering process). -// The input for this function and its order may not be changed, but the names may be updated. -int Non_physics_my(double *my, double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function for calculating my, the inverse penetration depth (for only this scattering process). + // The input for this function and its order may not be changed, but the names may be updated. + int + Non_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, _class_particle* _particle) { // *k_initial is a pointer to a simple vector with 3 doubles, k[0], k[1], k[2] which describes the wavevector // Simple case, just retrive the parameter saved from initialize *my = data_transfer.pointer_to_a_Non_physics_storage_struct->my_scattering; return 1; -}; + }; -// Function that provides description of a basic scattering event. -// Do not change the -int Non_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function that provides description of a basic scattering event. + // Do not change the + int + Non_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { k_final[0] = k_initial[0]; k_final[1] = k_initial[1]; @@ -92,57 +95,55 @@ int Non_physics_scattering(double *k_final, double *k_initial, double *weight, u return 1; // return 1 is sucess, return 0 is failure, and the ray will be absorbed. // failure should not happen, as this function will only be called when // the cross section for the current k_initial is above zero. - + // There is access to the data_transfer from within the scattering function // In this case the only variable is my, but it could be read by: // double my = data_transfer.pointer_to_a_Non_physics_storage_struct->my_scattering; // One can assume that if the scattering function is running, the my fuction was // executed just before and for the same k_initial. - -}; + }; -// These lines help with future error correction, and tell other Union components -// that at least one process have been defined. -#ifndef PROCESS_DETECTOR - #define PROCESS_DETECTOR dummy -#endif - -#ifndef PROCESS_NON_DETECTOR - #define PROCESS_NON_DETECTOR dummy -#endif + // These lines help with future error correction, and tell other Union components + // that at least one process have been defined. + #ifndef PROCESS_DETECTOR + #define PROCESS_DETECTOR dummy + #endif + #ifndef PROCESS_NON_DETECTOR + #define PROCESS_NON_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct Non_physics_storage_struct Non_storage; // Replace Non with your own name here + // Declare for this component, to do calculations on the input / store in the transported data + struct Non_physics_storage_struct Non_storage; // Replace Non with your own name here -// Variables needed in initialize of this function. -double effective_my_scattering; + // Variables needed in initialize of this function. + double effective_my_scattering; -// Needed for transport to the main component, will be the same for all processes -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Needed for transport to the main component, will be the same for all processes + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; %} INITIALIZE %{ // Initialize done in the component - effective_my_scattering = ((packing_factor/unit_cell_volume) * 100 * sigma); + effective_my_scattering = ((packing_factor / unit_cell_volume) * 100 * sigma); Non_storage.my_scattering = effective_my_scattering; - - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic This_process.non_isotropic_rot_index = -1; // Yes (powder) - //This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No - + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No + // The type of the process must be saved in the global enum process This_process.eProcess = Non; @@ -152,27 +153,25 @@ INITIALIZE This_process.scattering_function = &Non_physics_scattering; // This will be the same for all process's, and can thus be moved to an include. - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); This_process.process_p_interact = interact_fraction; - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Non_process:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} - + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Non_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list,global_process_element); + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE %{ - // Trace should be empty, the simulation is done in Union_master + // Trace should be empty, the simulation is done in Union_master %} END diff --git a/mcstas-comps/union/PhononSimple_process.comp b/mcstas-comps/union/PhononSimple_process.comp index 8d1805977d..49fd84509f 100644 --- a/mcstas-comps/union/PhononSimple_process.comp +++ b/mcstas-comps/union/PhononSimple_process.comp @@ -64,17 +64,17 @@ SETTING PARAMETERS(packing_factor=1,unit_cell_volume=13.8,interact_fraction=-1,a SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this PhononSimple_process component" -#endif + #ifndef Union + #error "The Union_init component must be included before this PhononSimple_process component" + #endif -// Very important to add a pointer to this struct in the union-lib.c file -struct PhononSimple_physics_storage_struct{ + // Very important to add a pointer to this struct in the union-lib.c file + struct PhononSimple_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + double k_init; double kk_x; double kk_y; @@ -82,14 +82,14 @@ struct PhononSimple_physics_storage_struct{ double ki_x; double ki_y; double ki_z; - + // Avoid duplicates of output parameters and setting parameters in naming double atom_mass_au; double V_rho; double my_scattering; int mc_steps; double DW_factor; - + double k_f[3]; double k_final; double aa; @@ -101,334 +101,327 @@ struct PhononSimple_physics_storage_struct{ double parms[10]; int enable_longitudinal; int enable_transverse; - + Coords pol_vector; int pol_mode; -}; + }; -/* Ridder's false position algorithm for finding roots. */ -#define T2E (1/11.605) /* Kelvin to meV */ + /* Ridder's false position algorithm for finding roots. */ + #define T2E (1/11.605) /* Kelvin to meV */ -double nbose_union(double omega, double T) /* Other name ?? */ + double + nbose_union (double omega, double T) /* Other name ?? */ { double nb; - nb= (omega>0) ? 1+1/(exp(omega/(T*T2E))-1) : 1/(exp(-omega/(T*T2E))-1); + nb = (omega > 0) ? 1 + 1 / (exp (omega / (T * T2E)) - 1) : 1 / (exp (-omega / (T * T2E)) - 1); return nb; } -#undef T2E -/* Routine types from Numerical Recipies book */ -#define UNUSED (-1.11e30) -#define MAXRIDD 60 + #undef T2E + /* Routine types from Numerical Recipies book */ + #define UNUSED (-1.11e30) + #define MAXRIDD 60 + + void + fatalerror_union (char* s) { + fprintf (stderr, "%s \n", s); + exit (1); + } -void fatalerror_union(char *s) - { - fprintf(stderr,"%s \n",s); - exit(1); + double + zridd_union (double (*func) (double*), double x1, double x2, double* parms, double xacc) { + int j; + double ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew; + + /* printf("zridd called with brackets %g %g acceptance %g \n",x1,x2,xacc); + printf("and %i parameters %g %g %g %g %g \n",Nparms,parms[0],parms[1],parms[2],parms[3], parms[4]); */ + parms[0] = x1; + fl = (*func) (parms); + parms[0] = x2; + fh = (*func) (parms); + /* printf("Function values: %g %g \n",fl,fh); */ + if (fl * fh >= 0) { + if (fl == 0) + return x1; + if (fh == 0) + return x2; + return UNUSED; + } else { + xl = x1; + xh = x2; + ans = UNUSED; + for (j = 1; j < MAXRIDD; j++) { + xm = 0.5 * (xl + xh); + parms[0] = xm; + fm = (*func) (parms); + s = sqrt (fm * fm - fl * fh); + if (s == 0.0) + return ans; + xnew = xm + (xm - xl) * ((fl >= fh ? 1.0 : -1.0) * fm / s); + if (fabs (xnew - ans) <= xacc) + return ans; + ans = xnew; + parms[0] = ans; + fnew = (*func) (parms); + if (fnew == 0.0) + return ans; + if (fabs (fm) * SIGN (fnew) != fm) { + xl = xm; + fl = fm; + xh = ans; + fh = fnew; + } else if (fabs (fl) * SIGN (fnew) != fl) { + xh = ans; + fh = fnew; + } else if (fabs (fh) * SIGN (fnew) != fh) { + xl = ans; + fl = fnew; + } else + fatalerror_union ("never get here in zridd"); + if (fabs (xh - xl) <= xacc) + return ans; + } + fatalerror_union ("zridd exceeded maximum iterations"); + } + return 0.0; /* Never get here */ } -double zridd_union(double (*func)(double*), double x1, double x2, double *parms, double xacc) - { - int j; - double ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew; - -/* printf("zridd called with brackets %g %g acceptance %g \n",x1,x2,xacc); - printf("and %i parameters %g %g %g %g %g \n",Nparms,parms[0],parms[1],parms[2],parms[3], parms[4]); */ - parms[0]=x1; - fl=(*func)(parms); - parms[0]=x2; - fh=(*func)(parms); -/* printf("Function values: %g %g \n",fl,fh); */ - if (fl*fh >= 0) - { - if (fl==0) return x1; - if (fh==0) return x2; - return UNUSED; + #define ROOTACC 1e-8 + int + findroots_union (double brack_low, double brack_mid, double brack_high, double* list, int* index, double (*f) (double*), double* parms) { + double root, range = brack_mid - brack_low; + int i, steps = 100; + + for (i = 0; i < steps; i++) { + root = zridd_union (f, brack_low + range * i / (int)steps, brack_low + range * (i + 1) / (int)steps, (double*)parms, ROOTACC); + if (root != UNUSED) { + list[(*index)++] = root; + /* printf("findroots found a low root: %g \n",root); */ } - else - { - xl=x1; - xh=x2; - ans=UNUSED; - for (j=1; j= fh ? 1.0 : -1.0)*fm/s); - if (fabs(xnew-ans) <= xacc) - return ans; - ans=xnew; - parms[0]=ans; - fnew=(*func)(parms); - if (fnew == 0.0) return ans; - if (fabs(fm)*SIGN(fnew) != fm) - { - xl=xm; - fl=fm; - xh=ans; - fh=fnew; - } - else - if (fabs(fl)*SIGN(fnew) != fl) - { - xh=ans; - fh=fnew; - } - else - if(fabs(fh)*SIGN(fnew) != fh) - { - xl=ans; - fl=fnew; + } + root = zridd_union (f, brack_mid, brack_high, (double*)parms, ROOTACC); + if (root != UNUSED) { + list[(*index)++] = root; + /* printf("findroots found a high root: %g \n",root); */ + } + } + + double + omega_q_union (double* parms) { + /* dispersion in units of meV */ + double vi, vf, vv_x, vv_y, vv_z, vi_x, vi_y, vi_z; + double q, qx, qy, qz, Jq, res_phonon, res_neutron; + double ah, a, c; + + vf = parms[0]; + vi = parms[1]; + vv_x = parms[2]; + vv_y = parms[3]; + vv_z = parms[4]; + vi_x = parms[5]; + vi_y = parms[6]; + vi_z = parms[7]; + a = parms[8]; + c = parms[9]; + ah = a / 2.0; + + /* printf("omega_q called with parameters vf= %g, vi=%g (%g %g %g) vv=(%g, %g, %g) \n",vf,vi,vi_x,vi_y,vi_z,vv_x,vv_y,vv_z); */ + qx = V2K * (vi_x - vf * vv_x); + qy = V2K * (vi_y - vf * vv_y); + qz = V2K * (vi_z - vf * vv_z); + q = sqrt (qx * qx + qy * qy + qz * qz); + Jq = 2 * (cos (ah * (qx + qy)) + cos (ah * (qx - qy)) + cos (ah * (qx + qz)) + cos (ah * (qx - qz)) + cos (ah * (qy + qz)) + cos (ah * (qy - qz))); + res_phonon = c / a * sqrt (12 - Jq); + res_neutron = fabs (VS2E * (vi * vi - vf * vf)); + /* if (fabs(res_phonon-res_neutron)<1e-3) + printf("in omega_q: q=(%g %g %g), omega_phonon=%g, omega_neutron=%g\n ", + qx,qy,qz,res_phonon,res_neutron); */ + /* printf("omega_q returning %g - %g\n",res_phonon,res_neutron); */ + + return (res_phonon - res_neutron); + } + #undef UNUSED + #undef MAXRIDD + + // Function for calculating my, the inverse penetration depth (for only this scattering process). + // The input for this function and its order may not be changed, but the names may be updated. + int + PhononSimple_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { + + double k_length = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); + // printf("energy = %f \n",k_length*K2V*k_length*K2V*VS2E); + double v_i = k_length * K2V; + + double a, b, c, T; + double vf_list[6]; /* List of allowed final velocities */ + int nf, index; + double* parms; + double f1, f2, J_factor; + double DV = 0.001; /* Velocity change used for numerical derivative */ + double omega; + double v_f; + double k_f[3], k_final; + double kappa2, kappa_x, kappa_y, kappa_z; + double solid_angle; + + a = data_transfer.pointer_to_a_PhononSimple_storage_struct->aa; + b = data_transfer.pointer_to_a_PhononSimple_storage_struct->bb; + c = data_transfer.pointer_to_a_PhononSimple_storage_struct->cc; + T = data_transfer.pointer_to_a_PhononSimple_storage_struct->Temp; + + Coords k_out; + focus_data->focusing_function (&k_out, &solid_angle, focus_data); + NORM (k_out.x, k_out.y, k_out.z); + data_transfer.pointer_to_a_PhononSimple_storage_struct->solid_angle = solid_angle; + + // Avoid allocating the array for each neutron + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0] = -1; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[1] = v_i; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[2] = k_out.x; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[3] = k_out.y; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[4] = k_out.z; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[5] = k_initial[0] * K2V; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[6] = k_initial[1] * K2V; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[7] = k_initial[2] * K2V; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[8] = a; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[9] = c; + + parms = &data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0]; + + nf = 0; + findroots_union (0, v_i, v_i + 2 * c * V2K / VS2E, vf_list, &nf, omega_q_union, parms); + index = (int)floor (rand01 () * nf); + + if (nf > 4 || index > 3) { + printf ("index = %d, nf = %d \n", index, nf); + printf ("energy = %f \n", k_length * K2V * k_length * K2V * VS2E); + } + + v_f = vf_list[index]; + // parms[0]=v_f-DV; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0] = v_f - DV; + f1 = omega_q_union (parms); + // parms[0]=v_f+DV; + data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0] = v_f + DV; + f2 = omega_q_union (parms); + // J_factor = fabs(f2-f1)/(2*DV*K2V); + J_factor = fabs (f2 - f1) / (2 * DV); + omega = VS2E * (v_i * v_i - v_f * v_f); /* unit of energy */ + + k_final = v_f * V2K; + k_f[0] = k_out.x * k_final; + k_f[1] = k_out.y * k_final; + k_f[2] = k_out.z * k_final; + + kappa_x = k_initial[0] - k_f[0]; + kappa_y = k_initial[1] - k_f[1]; + kappa_z = k_initial[2] - k_f[2]; + kappa2 = kappa_z * kappa_z + kappa_y * kappa_y + kappa_x * kappa_x; + + double pol_weight_factor; + if (data_transfer.pointer_to_a_PhononSimple_storage_struct->enable_transverse == 1 + && data_transfer.pointer_to_a_PhononSimple_storage_struct->enable_longitudinal == 1) { + pol_weight_factor = kappa2; + } else { + // polarization mode + // Find nearest bragg point. FCC: HKL all even or odd. + double h_value, k_value, l_value; + h_value = kappa_x * a * 0.5 / PI; + k_value = kappa_y * a * 0.5 / PI; + l_value = kappa_z * a * 0.5 / PI; + + int h_guess, k_guess, l_guess; + h_guess = floor (h_value); + k_guess = floor (k_value); + l_guess = floor (l_value); + + int h_check, k_check, l_check; + int nearest_bragg_h, nearest_bragg_k, nearest_bragg_l; + int check_sum; + + double dist, min_dist = 99999; + for (h_check = h_guess; h_check < h_guess + 2; h_check++) { + for (k_check = k_guess; k_check < k_guess + 2; k_check++) { + for (l_check = l_guess; l_check < l_guess + 2; l_check++) { + check_sum = h_check % 2 + k_check % 2 + l_check % 2; + if (check_sum == 0 || check_sum == 3) { + dist = sqrt ((h_value - h_check) * (h_value - h_check) + (k_value - k_check) * (k_value - k_check) + (l_value - l_check) * (l_value * l_check)); + if (dist < min_dist) { + min_dist = dist; + nearest_bragg_h = h_check; + nearest_bragg_k = k_check; + nearest_bragg_l = l_check; } - else - fatalerror_union("never get here in zridd"); - if (fabs(xh-xl) <= xacc) - return ans; + } + } } - fatalerror_union("zridd exceeded maximum iterations"); } - return 0.0; /* Never get here */ - } -#define ROOTACC 1e-8 - int findroots_union(double brack_low, double brack_mid, double brack_high, double *list, int* index, double (*f)(double*), double *parms) - { - double root,range=brack_mid-brack_low; - int i, steps=100; - - for (i=0; ienable_longitudinal == 1) { + pol_weight_factor + = (kappa_x * k_phonon_h + kappa_y * k_phonon_k + kappa_z * k_phonon_l) * (kappa_x * k_phonon_h + kappa_y * k_phonon_k + kappa_z * k_phonon_l); } - } - root = zridd_union(f, brack_mid, brack_high, (double *)parms, ROOTACC); - if (root != UNUSED) - { - list[(*index)++]=root; -/* printf("findroots found a high root: %g \n",root); */ + + if (data_transfer.pointer_to_a_PhononSimple_storage_struct->enable_transverse == 1) { + pol_weight_factor + = kappa_x * kappa_x + kappa_y * kappa_y + kappa_z * kappa_z + - (kappa_x * k_phonon_h + kappa_y * k_phonon_k + kappa_z * k_phonon_l) * (kappa_x * k_phonon_h + kappa_y * k_phonon_k + kappa_z * k_phonon_l); } - } - double omega_q_union(double* parms) - { - /* dispersion in units of meV */ - double vi, vf, vv_x, vv_y, vv_z, vi_x, vi_y, vi_z; - double q, qx, qy, qz, Jq, res_phonon, res_neutron; - double ah, a, c; - - vf=parms[0]; - vi=parms[1]; - vv_x=parms[2]; - vv_y=parms[3]; - vv_z=parms[4]; - vi_x=parms[5]; - vi_y=parms[6]; - vi_z=parms[7]; - a =parms[8]; - c =parms[9]; - ah=a/2.0; - -/* printf("omega_q called with parameters vf= %g, vi=%g (%g %g %g) vv=(%g, %g, %g) \n",vf,vi,vi_x,vi_y,vi_z,vv_x,vv_y,vv_z); */ - qx=V2K*(vi_x-vf*vv_x); - qy=V2K*(vi_y-vf*vv_y); - qz=V2K*(vi_z-vf*vv_z); - q=sqrt(qx*qx+qy*qy+qz*qz); - Jq=2*(cos(ah*(qx+qy))+cos(ah*(qx-qy))+cos(ah*(qx+qz))+cos(ah*(qx-qz)) - +cos(ah*(qy+qz))+cos(ah*(qy-qz)) ); - res_phonon=c/a*sqrt(12-Jq); - res_neutron = fabs(VS2E*(vi*vi-vf*vf)); -/* if (fabs(res_phonon-res_neutron)<1e-3) - printf("in omega_q: q=(%g %g %g), omega_phonon=%g, omega_neutron=%g\n ", - qx,qy,qz,res_phonon,res_neutron); */ -/* printf("omega_q returning %g - %g\n",res_phonon,res_neutron); */ - - return (res_phonon - res_neutron); + // Coords pol_vector = data_transfer.pointer_to_a_PhononSimple_storage_struct->pol_vector; + // pol_weight_factor = k_phonon_h*pol_vector.x + k_phonon_k*pol_vector.y + k_phonon_l*pol_vector.z; + /* + // This test shows the predicted behavior where all nearest bragg sets corresponds to Bragg peaks. + printf("--------------------------------------------\n"); + printf("hkl input = [%1.3f %1.3f %1.3f] \n",h_value,k_value,l_value); + printf("Nearest bragg = [%d %d %d] \n",nearest_bragg_h,nearest_bragg_k,nearest_bragg_l); + */ } -#undef UNUSED -#undef MAXRIDD - - -// Function for calculating my, the inverse penetration depth (for only this scattering process). -// The input for this function and its order may not be changed, but the names may be updated. -int PhononSimple_physics_my(double *my, double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { - - double k_length = sqrt(k_initial[0]*k_initial[0]+k_initial[1]*k_initial[1]+k_initial[2]*k_initial[2]); - //printf("energy = %f \n",k_length*K2V*k_length*K2V*VS2E); - double v_i = k_length * K2V; - - double a,b,c,T; - double vf_list[6]; /* List of allowed final velocities */ - int nf,index; - double *parms; - double f1,f2,J_factor; - double DV = 0.001; /* Velocity change used for numerical derivative */ - double omega; - double v_f; - double k_f[3],k_final; - double kappa2,kappa_x,kappa_y,kappa_z; - double solid_angle; - - a=data_transfer.pointer_to_a_PhononSimple_storage_struct->aa; - b=data_transfer.pointer_to_a_PhononSimple_storage_struct->bb; - c=data_transfer.pointer_to_a_PhononSimple_storage_struct->cc; - T=data_transfer.pointer_to_a_PhononSimple_storage_struct->Temp; - - Coords k_out; - focus_data->focusing_function(&k_out,&solid_angle,focus_data); - NORM(k_out.x,k_out.y,k_out.z); - data_transfer.pointer_to_a_PhononSimple_storage_struct->solid_angle = solid_angle; - - // Avoid allocating the array for each neutron - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0] = -1; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[1] = v_i; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[2] = k_out.x; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[3] = k_out.y; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[4] = k_out.z; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[5] = k_initial[0]*K2V; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[6] = k_initial[1]*K2V; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[7] = k_initial[2]*K2V; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[8] = a; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[9] = c; - - parms = &data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0]; - - nf = 0; - findroots_union(0, v_i, v_i+2*c*V2K/VS2E, vf_list, &nf, omega_q_union, parms); - index=(int)floor(rand01()*nf); - - if (nf > 4 || index > 3) { - printf("index = %d, nf = %d \n",index, nf); - printf("energy = %f \n",k_length*K2V*k_length*K2V*VS2E); - } - - v_f=vf_list[index]; - //parms[0]=v_f-DV; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0]=v_f-DV; - f1=omega_q_union(parms); - //parms[0]=v_f+DV; - data_transfer.pointer_to_a_PhononSimple_storage_struct->parms[0]=v_f+DV; - f2=omega_q_union(parms); - //J_factor = fabs(f2-f1)/(2*DV*K2V); - J_factor = fabs(f2-f1)/(2*DV); - omega=VS2E*(v_i*v_i-v_f*v_f); /* unit of energy */ - - k_final = v_f * V2K; - k_f[0] = k_out.x * k_final; - k_f[1] = k_out.y * k_final; - k_f[2] = k_out.z * k_final; - - kappa_x = k_initial[0]-k_f[0]; - kappa_y = k_initial[1]-k_f[1]; - kappa_z = k_initial[2]-k_f[2]; - kappa2=kappa_z*kappa_z+kappa_y*kappa_y+kappa_x*kappa_x; - - double pol_weight_factor; - if (data_transfer.pointer_to_a_PhononSimple_storage_struct->enable_transverse == 1 && data_transfer.pointer_to_a_PhononSimple_storage_struct->enable_longitudinal == 1) { - pol_weight_factor = kappa2; - } else { - // polarization mode - // Find nearest bragg point. FCC: HKL all even or odd. - double h_value,k_value,l_value; - h_value = kappa_x*a*0.5/PI; - k_value = kappa_y*a*0.5/PI; - l_value = kappa_z*a*0.5/PI; - - int h_guess,k_guess,l_guess; - h_guess = floor(h_value); - k_guess = floor(k_value); - l_guess = floor(l_value); - - int h_check,k_check,l_check; - int nearest_bragg_h,nearest_bragg_k,nearest_bragg_l; - int check_sum; - - double dist,min_dist = 99999; - for (h_check=h_guess;h_checkenable_longitudinal == 1) { - pol_weight_factor = (kappa_x*k_phonon_h+kappa_y*k_phonon_k+kappa_z*k_phonon_l)*(kappa_x*k_phonon_h+kappa_y*k_phonon_k+kappa_z*k_phonon_l); - } - - if (data_transfer.pointer_to_a_PhononSimple_storage_struct->enable_transverse == 1) { - pol_weight_factor = kappa_x*kappa_x+kappa_y*kappa_y+kappa_z*kappa_z - (kappa_x*k_phonon_h+kappa_y*k_phonon_k+kappa_z*k_phonon_l)*(kappa_x*k_phonon_h+kappa_y*k_phonon_k+kappa_z*k_phonon_l); - } - - //Coords pol_vector = data_transfer.pointer_to_a_PhononSimple_storage_struct->pol_vector; - //pol_weight_factor = k_phonon_h*pol_vector.x + k_phonon_k*pol_vector.y + k_phonon_l*pol_vector.z; - /* - // This test shows the predicted behavior where all nearest bragg sets corresponds to Bragg peaks. - printf("--------------------------------------------\n"); - printf("hkl input = [%1.3f %1.3f %1.3f] \n",h_value,k_value,l_value); - printf("Nearest bragg = [%d %d %d] \n",nearest_bragg_h,nearest_bragg_k,nearest_bragg_l); - */ - } - - - - //*my = nf*V_rho*(k_final/k_length)*DW*(kappa2*K2V*K2V*VS2E)/fabs(omega)*nbose(omega,T)*2*VS2E*K2V*k_final/J_factor*b*b/M; - // my_constant = V_rho*DW*K2V*K2V*VS2E*2*VS2E*K2V*b*b/M // done in initialize - - //*my = (double) nf*k_final/k_length*kappa2/fabs(omega)*nbose_union(omega,T)*k_final/J_factor*data_transfer.pointer_to_a_PhononSimple_storage_struct->my_constant; - - *my = (double) nf*k_final/k_length*pol_weight_factor/fabs(omega)*nbose_union(omega,T)*k_final/J_factor*data_transfer.pointer_to_a_PhononSimple_storage_struct->my_constant; - - //*my = 10; - - data_transfer.pointer_to_a_PhononSimple_storage_struct->k_final = k_final; - data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[0] = k_f[0]; - data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[1] = k_f[1]; - data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[2] = k_f[2]; + + //*my = nf*V_rho*(k_final/k_length)*DW*(kappa2*K2V*K2V*VS2E)/fabs(omega)*nbose(omega,T)*2*VS2E*K2V*k_final/J_factor*b*b/M; + // my_constant = V_rho*DW*K2V*K2V*VS2E*2*VS2E*K2V*b*b/M // done in initialize + + //*my = (double) + //nf*k_final/k_length*kappa2/fabs(omega)*nbose_union(omega,T)*k_final/J_factor*data_transfer.pointer_to_a_PhononSimple_storage_struct->my_constant; + + *my = (double)nf * k_final / k_length * pol_weight_factor / fabs (omega) * nbose_union (omega, T) * k_final / J_factor + * data_transfer.pointer_to_a_PhononSimple_storage_struct->my_constant; + + //*my = 10; + + data_transfer.pointer_to_a_PhononSimple_storage_struct->k_final = k_final; + data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[0] = k_f[0]; + data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[1] = k_f[1]; + data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[2] = k_f[2]; // Simple case, just retrive the parameter saved from initialize return 1; -}; + }; -// Function that provides description of a basic scattering event. -// Do not change the -int PhononSimple_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function that provides description of a basic scattering event. + // Do not change the + int + PhononSimple_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, + struct focus_data_struct* focus_data, _class_particle* _particle) { // k_final and k_initial are passed as pointers to double vector[3] - //double k_length = data_transfer.pointer_to_a_Template_physics_storage_struct->k_init; - //printf("Naar vi her til?\n"); - + // double k_length = data_transfer.pointer_to_a_Template_physics_storage_struct->k_init; + // printf("Naar vi her til?\n"); + k_final[0] = data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[0]; k_final[1] = data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[1]; k_final[2] = data_transfer.pointer_to_a_PhononSimple_storage_struct->k_f[2]; - - *weight *= 0.25/PI*data_transfer.pointer_to_a_PhononSimple_storage_struct->solid_angle; - + + *weight *= 0.25 / PI * data_transfer.pointer_to_a_PhononSimple_storage_struct->solid_angle; + // A pointer to k_final is returned, and the wavevector will be set to k_final after a scattering event return 1; // return 1 is sucess, return 0 is failure, and the ray will be absorbed. // failure should not happen, as this function will only be called when @@ -439,49 +432,47 @@ int PhononSimple_physics_scattering(double *k_final, double *k_initial, double * // double my = data_transfer.pointer_to_a_Template_physics_storage_struct->my_scattering; // One can assume that if the scattering function is running, the my fuction was // executed just before and for the same k_initial. + }; -}; - -// These lines help with future error correction, and tell other Union components -// that at least one process have been defined. -#ifndef PROCESS_DETECTOR - #define PROCESS_DETECTOR dummy -#endif + // These lines help with future error correction, and tell other Union components + // that at least one process have been defined. + #ifndef PROCESS_DETECTOR + #define PROCESS_DETECTOR dummy + #endif -#ifndef PROCESS_PHONONSIMPLE_DETECTOR - #define PROCESS_PHONONSIMPLE_DETECTOR dummy -#endif + #ifndef PROCESS_PHONONSIMPLE_DETECTOR + #define PROCESS_PHONONSIMPLE_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct PhononSimple_physics_storage_struct PhononSimple_storage; // Replace template with your own name here - -// Variables needed in initialize of this function. -double effective_my_scattering; -double sigma_const; + // Declare for this component, to do calculations on the input / store in the transported data + struct PhononSimple_physics_storage_struct PhononSimple_storage; // Replace template with your own name here -// Needed for transport to the main component, will be the same for all processes -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Variables needed in initialize of this function. + double effective_my_scattering; + double sigma_const; + // Needed for transport to the main component, will be the same for all processes + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; %} INITIALIZE %{ // Initialize done in the component - //PhononSimple_storage.my_scattering = effective_my_scattering; + // PhononSimple_storage.my_scattering = effective_my_scattering; PhononSimple_storage.aa = a; // lattice side length PhononSimple_storage.bb = b; // scattering length PhononSimple_storage.cc = c; // speed of sound - //PhononSimple_storage.V_rho = 4.0/(a*a*a); - //PhononSimple_storage.Atom_mass_au = M; - //PhononSimple_storage.mc_steps = MCsteps; - //PhononSimple_storage.DW_factor = DW; + // PhononSimple_storage.V_rho = 4.0/(a*a*a); + // PhononSimple_storage.Atom_mass_au = M; + // PhononSimple_storage.mc_steps = MCsteps; + // PhononSimple_storage.DW_factor = DW; PhononSimple_storage.Temp = T; - + /* if (!pol_h && !pol_k && !pol_l) PhononSimple_storage.pol_mode = 0; @@ -493,35 +484,35 @@ INITIALIZE PhononSimple_storage.pol_vector.z = pol_l; } */ - + if (longitudinal > 0.5) PhononSimple_storage.enable_longitudinal = 1; else PhononSimple_storage.enable_longitudinal = 0; - + if (transverse > 0.5) PhononSimple_storage.enable_transverse = 1; else PhononSimple_storage.enable_transverse = 0; - + if (PhononSimple_storage.enable_transverse == 0 && PhononSimple_storage.enable_longitudinal == 0) { - printf("PhononSimple_process named %s has no branches as both longitudinal and transverse is disabled! \n"); - exit(1); + printf ("PhononSimple_process named %s has no branches as both longitudinal and transverse is disabled! \n"); + exit (1); } - - PhononSimple_storage.my_constant = packing_factor*4.0/(a*a*a)*DW*K2V*K2V*VS2E*2*VS2E*K2V*b*b/M; + + PhononSimple_storage.my_constant = packing_factor * 4.0 / (a * a * a) * DW * K2V * K2V * VS2E * 2 * VS2E * K2V * b * b / M; // my_constant = V_rho*DW*K2V*K2V*VS2E*2*VS"E*K2V*b*b/M // done in initialize - - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic - //This_process.non_isotropic_rot_index = -1; // Yes (powder) - This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = -1; // Yes (powder) + This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) This_process.needs_cross_section_focus = 1; // Yes - //This_process.needs_cross_section_focus = -1; // No + // This_process.needs_cross_section_focus = -1; // No // The type of the process must be saved in the global enum process This_process.eProcess = PhononSimple; @@ -532,27 +523,25 @@ INITIALIZE This_process.scattering_function = &PhononSimple_physics_scattering; // This will be the same for all process's, and can thus be moved to an include. - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); This_process.process_p_interact = interact_fraction; - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"PhononSimple_process:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "PhononSimple_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } - - struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list,global_process_element); + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE %{ - // Trace should be empty, the simulation is done in Union_master + // Trace should be empty, the simulation is done in Union_master %} END diff --git a/mcstas-comps/union/Powder_process.comp b/mcstas-comps/union/Powder_process.comp index e6dafce79e..0512d24d31 100755 --- a/mcstas-comps/union/Powder_process.comp +++ b/mcstas-comps/union/Powder_process.comp @@ -66,597 +66,635 @@ SETTING PARAMETERS(string reflections="NULL",packing_factor=1, Vc=0, delta_d_d=0 SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Powder_process component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Powder_process component" + #endif - - -// Share section of PowderN 8/3 2016 from McStas.org + // Share section of PowderN 8/3 2016 from McStas.org /* used for reading data table from file */ %include "read_table-lib" %include "interoff-lib" -/* Declare structures and functions only once in each instrument. */ -#ifndef POWDERN_DECL_UNION -#define POWDERN_DECL_UNION -/* format definitions in the order {j d F2 DW Dd inv2d q F strain} */ -#ifndef Crystallographica -#define Crystallographica { 4,5,7,0,0,0,0,0,0 } -#define Fullprof { 4,0,8,0,0,5,0,0,0 } -#define Lazy {17,6,0,0,0,0,0,13,0 } -#define Undefined { 0,0,0,0,0,0,0,0,0 } -#endif - - struct line_data_union - { - double F2; /* Value of structure factor */ - double q; /* Qvector */ - int j; /* Multiplicity */ - double DWfactor; /* Debye-Waller factor */ - double w; /* Intrinsic line width */ - double Epsilon; /* Strain=delta_d_d/d shift in ppm */ - }; - - struct line_info_struct_union - { - struct line_data_union *list; /* Reflection array */ - int count; /* Number of reflections */ - double Dd; - double DWfactor; - double V_0; - double rho; - double at_weight; - double at_nb; - double sigma_a; // should not be used - double sigma_i; // should not be used - char compname[256]; - double flag_barns; - int shape; /* 0 cylinder, 1 box, 2 sphere, 3 OFF file */ - int column_order[9]; /* column signification */ - int flag_warning; - char type; /* interaction type of event t=Transmit, i=Incoherent, c=Coherent */ - double dq; /* wavevector transfer [Angs-1] */ - double Epsilon; /* global strain in ppm */ - double XsectionFactor; - double my_s_v2_sum; - double my_a_v; - double my_inc; - double *w_v,*q_v, *my_s_v2; - double radius_i,xwidth_i,yheight_i,zdepth_i; // not to be used, but still here - double v; /* last velocity (cached) */ - double Nq; - int nb_reuses, nb_refl, nb_refl_count; - double v_min, v_max; - double xs_Nq[CHAR_BUF_LENGTH]; - double xs_sum[CHAR_BUF_LENGTH]; - double neutron_passed; - long xs_compute, xs_reuse, xs_calls; - }; + /* Declare structures and functions only once in each instrument. */ + #ifndef POWDERN_DECL_UNION + #define POWDERN_DECL_UNION + /* format definitions in the order {j d F2 DW Dd inv2d q F strain} */ + #ifndef Crystallographica + #define Crystallographica { 4,5,7,0,0,0,0,0,0 } + #define Fullprof { 4,0,8,0,0,5,0,0,0 } + #define Lazy {17,6,0,0,0,0,0,13,0 } + #define Undefined { 0,0,0,0,0,0,0,0,0 } + #endif + + struct line_data_union { + double F2; /* Value of structure factor */ + double q; /* Qvector */ + int j; /* Multiplicity */ + double DWfactor; /* Debye-Waller factor */ + double w; /* Intrinsic line width */ + double Epsilon; /* Strain=delta_d_d/d shift in ppm */ + }; + + struct line_info_struct_union { + struct line_data_union* list; /* Reflection array */ + int count; /* Number of reflections */ + double Dd; + double DWfactor; + double V_0; + double rho; + double at_weight; + double at_nb; + double sigma_a; // should not be used + double sigma_i; // should not be used + char compname[256]; + double flag_barns; + int shape; /* 0 cylinder, 1 box, 2 sphere, 3 OFF file */ + int column_order[9]; /* column signification */ + int flag_warning; + char type; /* interaction type of event t=Transmit, i=Incoherent, c=Coherent */ + double dq; /* wavevector transfer [Angs-1] */ + double Epsilon; /* global strain in ppm */ + double XsectionFactor; + double my_s_v2_sum; + double my_a_v; + double my_inc; + double *w_v, *q_v, *my_s_v2; + double radius_i, xwidth_i, yheight_i, zdepth_i; // not to be used, but still here + double v; /* last velocity (cached) */ + double Nq; + int nb_reuses, nb_refl, nb_refl_count; + double v_min, v_max; + double xs_Nq[CHAR_BUF_LENGTH]; + double xs_sum[CHAR_BUF_LENGTH]; + double neutron_passed; + long xs_compute, xs_reuse, xs_calls; + }; off_struct offdata_union; - + // PN_list_compare ***************************************************************** -int PN_list_compare_union(const void *a, const void *b) -{ - const struct line_data_union *pa = a; - const struct line_data_union *pb = b; + int + PN_list_compare_union (const void* a, const void* b) { + const struct line_data_union* pa = a; + const struct line_data_union* pb = b; /* Sort by q */ - if (pa->q < pb->q) return -1; - if (pa->q > pb->q) return 1; + if (pa->q < pb->q) + return -1; + if (pa->q > pb->q) + return 1; /* In case of tie, sort by F2 also */ - if (pa->F2 < pb->F2) return -1; - if (pa->F2 > pb->F2) return 1; + if (pa->F2 < pb->F2) + return -1; + if (pa->F2 > pb->F2) + return 1; /* In case of tie, sort by j also */ - if (pa->j < pb->j) return -1; - if (pa->j > pb->j) return 1; + if (pa->j < pb->j) + return -1; + if (pa->j > pb->j) + return 1; return 0; } /* PN_list_compare */ - int read_line_data_union(char *SC_file, struct line_info_struct_union *info) - { - struct line_data_union *list = NULL; - int size = 0; + int + read_line_data_union (char* SC_file, struct line_info_struct_union* info) { + struct line_data_union* list = NULL; + int size = 0; t_Table sTable; /* sample data table structure from SC_file */ - int i=0; - int mult_count =0; - char flag=0; - double q_count=0, j_count=0, F2_count=0; - char **parsing; - int list_count=0; - - if (!SC_file || !strlen(SC_file) || !strcmp(SC_file, "NULL")) { - MPI_MASTER( - printf("PowderN: %s: Using incoherent elastic scattering only\n",info->compname); - ); + int i = 0; + int mult_count = 0; + char flag = 0; + double q_count = 0, j_count = 0, F2_count = 0; + char** parsing; + int list_count = 0; + + if (!SC_file || !strlen (SC_file) || !strcmp (SC_file, "NULL")) { + MPI_MASTER (printf ("PowderN: %s: Using incoherent elastic scattering only\n", info->compname);); info->count = 0; - return(0); + return (0); } - Table_Read(&sTable, SC_file, 1); /* read 1st block data from SC_file into sTable*/ + Table_Read (&sTable, SC_file, 1); /* read 1st block data from SC_file into sTable*/ /* parsing of header */ - parsing = Table_ParseHeader(sTable.header, - "Vc","V_0", - "sigma_abs","sigma_a ", - "sigma_inc","sigma_i ", - "column_j", - "column_d", - "column_F2", - "column_DW", - "column_Dd", - "column_inv2d", "column_1/2d", "column_sintheta/lambda", - "column_q", /* 14 */ - "DW", "Debye_Waller", - "delta_d_d/d", - "column_F ", - "V_rho", - "density", - "weight", - "nb_atoms","multiplicity", /* 23 */ - "column_ppm","column_strain", - NULL); + parsing = Table_ParseHeader (sTable.header, "Vc", "V_0", "sigma_abs", "sigma_a ", "sigma_inc", "sigma_i ", "column_j", "column_d", "column_F2", "column_DW", + "column_Dd", "column_inv2d", "column_1/2d", "column_sintheta/lambda", "column_q", /* 14 */ + "DW", "Debye_Waller", "delta_d_d/d", "column_F ", "V_rho", "density", "weight", "nb_atoms", "multiplicity", /* 23 */ + "column_ppm", "column_strain", NULL); if (parsing) { - if (parsing[0] && !info->V_0) info->V_0 =atof(parsing[0]); - if (parsing[1] && !info->V_0) info->V_0 =atof(parsing[1]); - if (parsing[2] && !info->sigma_a) info->sigma_a=atof(parsing[2]); - if (parsing[3] && !info->sigma_a) info->sigma_a=atof(parsing[3]); - if (parsing[4] && !info->sigma_i) info->sigma_i=atof(parsing[4]); - if (parsing[5] && !info->sigma_i) info->sigma_i=atof(parsing[5]); - if (parsing[6]) info->column_order[0]=atoi(parsing[6]); - if (parsing[7]) info->column_order[1]=atoi(parsing[7]); - if (parsing[8]) info->column_order[2]=atoi(parsing[8]); - if (parsing[9]) info->column_order[3]=atoi(parsing[9]); - if (parsing[10]) info->column_order[4]=atoi(parsing[10]); - if (parsing[11]) info->column_order[5]=atoi(parsing[11]); - if (parsing[12]) info->column_order[5]=atoi(parsing[12]); - if (parsing[13]) info->column_order[5]=atoi(parsing[13]); - if (parsing[14]) info->column_order[6]=atoi(parsing[14]); - if (parsing[15] && info->DWfactor<=0) info->DWfactor=atof(parsing[15]); - if (parsing[16] && info->DWfactor<=0) info->DWfactor=atof(parsing[16]); - if (parsing[17] && info->Dd <0) info->Dd =atof(parsing[17]); - if (parsing[18]) info->column_order[7]=atoi(parsing[18]); - if (parsing[19] && !info->V_0) info->V_0 =1/atof(parsing[19]); - if (parsing[20] && !info->rho) info->rho =atof(parsing[20]); - if (parsing[21] && !info->at_weight) info->at_weight =atof(parsing[21]); - if (parsing[22] && info->at_nb <= 1) info->at_nb =atof(parsing[22]); - if (parsing[23] && info->at_nb <= 1) info->at_nb =atof(parsing[23]); - if (parsing[24]) info->column_order[8]=atoi(parsing[24]); - if (parsing[25]) info->column_order[8]=atoi(parsing[25]); - for (i=0; i<=25; i++) if (parsing[i]) free(parsing[i]); - free(parsing); + if (parsing[0] && !info->V_0) + info->V_0 = atof (parsing[0]); + if (parsing[1] && !info->V_0) + info->V_0 = atof (parsing[1]); + if (parsing[2] && !info->sigma_a) + info->sigma_a = atof (parsing[2]); + if (parsing[3] && !info->sigma_a) + info->sigma_a = atof (parsing[3]); + if (parsing[4] && !info->sigma_i) + info->sigma_i = atof (parsing[4]); + if (parsing[5] && !info->sigma_i) + info->sigma_i = atof (parsing[5]); + if (parsing[6]) + info->column_order[0] = atoi (parsing[6]); + if (parsing[7]) + info->column_order[1] = atoi (parsing[7]); + if (parsing[8]) + info->column_order[2] = atoi (parsing[8]); + if (parsing[9]) + info->column_order[3] = atoi (parsing[9]); + if (parsing[10]) + info->column_order[4] = atoi (parsing[10]); + if (parsing[11]) + info->column_order[5] = atoi (parsing[11]); + if (parsing[12]) + info->column_order[5] = atoi (parsing[12]); + if (parsing[13]) + info->column_order[5] = atoi (parsing[13]); + if (parsing[14]) + info->column_order[6] = atoi (parsing[14]); + if (parsing[15] && info->DWfactor <= 0) + info->DWfactor = atof (parsing[15]); + if (parsing[16] && info->DWfactor <= 0) + info->DWfactor = atof (parsing[16]); + if (parsing[17] && info->Dd < 0) + info->Dd = atof (parsing[17]); + if (parsing[18]) + info->column_order[7] = atoi (parsing[18]); + if (parsing[19] && !info->V_0) + info->V_0 = 1 / atof (parsing[19]); + if (parsing[20] && !info->rho) + info->rho = atof (parsing[20]); + if (parsing[21] && !info->at_weight) + info->at_weight = atof (parsing[21]); + if (parsing[22] && info->at_nb <= 1) + info->at_nb = atof (parsing[22]); + if (parsing[23] && info->at_nb <= 1) + info->at_nb = atof (parsing[23]); + if (parsing[24]) + info->column_order[8] = atoi (parsing[24]); + if (parsing[25]) + info->column_order[8] = atoi (parsing[25]); + for (i = 0; i <= 25; i++) + if (parsing[i]) + free (parsing[i]); + free (parsing); } if (!sTable.rows) - exit(fprintf(stderr, "PowderN: %s: Error: The number of rows in %s " - "should be at least %d\n", info->compname, SC_file, 1)); - else size = sTable.rows; - Table_Info(sTable); - MPI_MASTER( - printf("PowderN: %s: Reading %d rows from %s\n", - info->compname, size, SC_file); - if (info->column_order[0] == 4 && info->flag_barns !=0) - printf("PowderN: %s: Powder file probably of type Crystallographica/Fullprof (lau)\n" - "WARNING: but F2 unit is set to barns=1 (barns). Intensity might be 100 times too high.\n", - info->compname); - if (info->column_order[0] == 17 && info->flag_barns == 0) - printf("PowderN: %s: Powder file probably of type Lazy Pulver (laz)\n" - "WARNING: but F2 unit is set to barns=0 (fm^2). Intensity might be 100 times too low.\n", - info->compname); - ); + exit (fprintf (stderr, + "PowderN: %s: Error: The number of rows in %s " + "should be at least %d\n", + info->compname, SC_file, 1)); + else + size = sTable.rows; + Table_Info (sTable); + MPI_MASTER (printf ("PowderN: %s: Reading %d rows from %s\n", info->compname, size, SC_file); if (info->column_order[0] == 4 && info->flag_barns != 0) + printf ("PowderN: %s: Powder file probably of type Crystallographica/Fullprof (lau)\n" + "WARNING: but F2 unit is set to barns=1 (barns). Intensity might be 100 times too high.\n", + info->compname); + if (info->column_order[0] == 17 && info->flag_barns == 0) + printf ("PowderN: %s: Powder file probably of type Lazy Pulver (laz)\n" + "WARNING: but F2 unit is set to barns=0 (fm^2). Intensity might be 100 times too low.\n", + info->compname);); /* allocate line_data array */ - list = (struct line_data_union*)malloc(size*sizeof(struct line_data_union)); + list = (struct line_data_union*)malloc (size * sizeof (struct line_data_union)); - for (i=0; iDd >= 0) w = info->Dd; - if (info->DWfactor > 0) DWfactor = info->DWfactor; - if (info->Epsilon) Epsilon = info->Epsilon*1e-6; + if (info->Dd >= 0) + w = info->Dd; + if (info->DWfactor > 0) + DWfactor = info->DWfactor; + if (info->Epsilon) + Epsilon = info->Epsilon * 1e-6; /* get data from table using columns {j d F2 DW Dd inv2d q F} */ /* column indexes start at 1, thus need to substract 1 */ - if (info->column_order[0] >0) - j = Table_Index(sTable, i, info->column_order[0]-1); - if (info->column_order[1] >0) - d = Table_Index(sTable, i, info->column_order[1]-1); - if (info->column_order[2] >0) - F2 = Table_Index(sTable, i, info->column_order[2]-1); - if (info->column_order[3] >0) - DWfactor = Table_Index(sTable, i, info->column_order[3]-1); - if (info->column_order[4] >0) - w = Table_Index(sTable, i, info->column_order[4]-1); - if (info->column_order[5] >0) - { d = Table_Index(sTable, i, info->column_order[5]-1); - d = (d > 0? 1/d/2 : 0); } - if (info->column_order[6] >0) - { q = Table_Index(sTable, i, info->column_order[6]-1); - d = (q > 0 ? 2*PI/q : 0); } - if (info->column_order[7] >0 && !F2) - { F2 = Table_Index(sTable, i, info->column_order[7]-1); F2 *= F2; } - if (info->column_order[8] >0 && !Epsilon) - { Epsilon = Table_Index(sTable, i, info->column_order[8]-1)*1e-6; } + if (info->column_order[0] > 0) + j = Table_Index (sTable, i, info->column_order[0] - 1); + if (info->column_order[1] > 0) + d = Table_Index (sTable, i, info->column_order[1] - 1); + if (info->column_order[2] > 0) + F2 = Table_Index (sTable, i, info->column_order[2] - 1); + if (info->column_order[3] > 0) + DWfactor = Table_Index (sTable, i, info->column_order[3] - 1); + if (info->column_order[4] > 0) + w = Table_Index (sTable, i, info->column_order[4] - 1); + if (info->column_order[5] > 0) { + d = Table_Index (sTable, i, info->column_order[5] - 1); + d = (d > 0 ? 1 / d / 2 : 0); + } + if (info->column_order[6] > 0) { + q = Table_Index (sTable, i, info->column_order[6] - 1); + d = (q > 0 ? 2 * PI / q : 0); + } + if (info->column_order[7] > 0 && !F2) { + F2 = Table_Index (sTable, i, info->column_order[7] - 1); + F2 *= F2; + } + if (info->column_order[8] > 0 && !Epsilon) { + Epsilon = Table_Index (sTable, i, info->column_order[8] - 1) * 1e-6; + } /* assign and check values */ - j = (j > 0 ? j : 0); - q = (d > 0 ? 2*PI/d : 0); /* this is q */ - if (Epsilon && fabs(Epsilon) < 1e6) { - q -= Epsilon*q; /* dq/q = -delta_d_d/d = -Epsilon */ + j = (j > 0 ? j : 0); + q = (d > 0 ? 2 * PI / d : 0); /* this is q */ + if (Epsilon && fabs (Epsilon) < 1e6) { + q -= Epsilon * q; /* dq/q = -delta_d_d/d = -Epsilon */ } DWfactor = (DWfactor > 0 ? DWfactor : 1); - w = (w>0 ? w : 0); /* this is q and d relative spreading */ - F2 = (F2 >= 0 ? F2 : 0); + w = (w > 0 ? w : 0); /* this is q and d relative spreading */ + F2 = (F2 >= 0 ? F2 : 0); if (j == 0 || q == 0) { - MPI_MASTER( - printf("PowderN: %s: line %i has invalid definition\n" - " (mult=0 or q=0 or d=0)\n", info->compname, i); - ); + MPI_MASTER (printf ("PowderN: %s: line %i has invalid definition\n" + " (mult=0 or q=0 or d=0)\n", + info->compname, i);); continue; } list[list_count].j = j; list[list_count].q = q; list[list_count].DWfactor = DWfactor; list[list_count].w = w; - list[list_count].F2= F2; + list[list_count].F2 = F2; list[list_count].Epsilon = Epsilon; /* adjust multiplicity if j-column + multiple d-spacing lines */ /* if d = previous d, increase line duplication index */ - if (!q_count) q_count = q; - if (!j_count) j_count = j; - if (!F2_count) F2_count = F2; - if (fabs(q_count-q) < 0.0001*fabs(q) - && fabs(F2_count-F2) < 0.0001*fabs(F2) && j_count == j) { - mult_count++; flag=0; } - else flag=1; - if (i == size-1) flag=1; + if (!q_count) + q_count = q; + if (!j_count) + j_count = j; + if (!F2_count) + F2_count = F2; + if (fabs (q_count - q) < 0.0001 * fabs (q) && fabs (F2_count - F2) < 0.0001 * fabs (F2) && j_count == j) { + mult_count++; + flag = 0; + } else + flag = 1; + if (i == size - 1) + flag = 1; /* else if d != previous d : just passed equivalent lines */ if (flag) { - if (i == size-1) list_count++; - /* if duplication index == previous multiplicity */ - /* set back multiplicity of previous lines to 1 */ - if ((mult_count && list_count>0) - && (mult_count == list[list_count-1].j - || ((list_count < size) && (i == size - 1) - && (mult_count == list[list_count].j))) ) { - MPI_MASTER( - printf("PowderN: %s: Set multiplicity to 1 for lines [%i:%i]\n" - " (d-spacing %g is duplicated %i times)\n", - info->compname, list_count-mult_count, list_count-1, list[list_count-1].q, mult_count); - ); - for (index=list_count-mult_count; index 0) + && (mult_count == list[list_count - 1].j || ((list_count < size) && (i == size - 1) && (mult_count == list[list_count].j)))) { + MPI_MASTER (printf ("PowderN: %s: Set multiplicity to 1 for lines [%i:%i]\n" + " (d-spacing %g is duplicated %i times)\n", + info->compname, list_count - mult_count, list_count - 1, list[list_count - 1].q, mult_count);); + for (index = list_count - mult_count; index < list_count; list[index++].j = 1) + ; mult_count = 1; - q_count = q; - j_count = j; - F2_count = F2; + q_count = q; + j_count = j; + F2_count = F2; } - if (i == size-1) list_count--; - flag=0; + if (i == size - 1) + list_count--; + flag = 0; } list_count++; - } /* end for */ - - Table_Free(&sTable); - + } /* end for */ + + Table_Free (&sTable); + /* sort the list with increasing q */ - qsort(list, list_count, sizeof(struct line_data_union), PN_list_compare_union); - - MPI_MASTER( - printf("PowderN: %s: Read %i reflections from file '%s'\n", - info->compname, list_count, SC_file); - ); - info->list = list; + qsort (list, list_count, sizeof (struct line_data_union), PN_list_compare_union); + + MPI_MASTER (printf ("PowderN: %s: Read %i reflections from file '%s'\n", info->compname, list_count, SC_file);); + info->list = list; info->count = list_count; - return(list_count); + return (list_count); } /* read_line_data_union */ + /* computes the number of possible reflections (return value), and the total xsection 'sum' */ + /* this routine looks for a pre-computed value in the Nq and sum cache tables */ + /* when found, the earch starts from the corresponding lower element in the table */ + int + calc_xsect_union (double v, double* qv, double* my_sv2, int count, double* sum, struct line_info_struct_union* line_info) { + int Nq = 0, line = 0, line0 = 0; + *sum = 0; + + // printf("Line_info when entering cross_section calculation\n"); + // printf("v = %f, qv = %f, my_sv2 = %f, count = %d, sum = %f\n",v,*qv,*my_sv2,count,*sum); + // printf("v = %f\n",v); + // printf("line_info->v = %f, line_info->v_min = %f, line_info->v_max = %f, line_info->neutron_passed = + // %f\n",line_info->v,line_info->v_min,line_info->v_max,line_info->neutron_passed); printf("line_info->xs_reuses = %d, line_info->xs_compute = + // %d\n",line_info->xs_reuse,line_info->xs_compute); + + /* check if a line_info element has been recorded already */ + if (v >= line_info->v_min && v <= line_info->v_max && line_info->neutron_passed >= CHAR_BUF_LENGTH) { + line = (int)floor (v - line_info->v_min) * CHAR_BUF_LENGTH / (line_info->v_max - line_info->v_min); + Nq = line_info->xs_Nq[line]; + *sum = line_info->xs_sum[line]; + if (!Nq && *sum == 0) { + /* not yet set: we compute the sum up to the corresponding speed in the table cache */ + // printf("Nq and sum not yet set, have to do this calculation now\n"); + double line_v = line_info->v_min + line * (line_info->v_max - line_info->v_min) / CHAR_BUF_LENGTH; + for (line0 = 0; line0 < count; line0++) { + if (qv[line0] <= 2 * line_v) { /* q < 2*kf: restrict structural range */ + *sum += my_sv2[line0]; + if (Nq < line0 + 1) + Nq = line0 + 1; /* determine maximum line index which can scatter */ + } else + break; + } + line_info->xs_Nq[line] = Nq; + line_info->xs_sum[line] = *sum; + line_info->xs_compute++; + // printf("line_info->xs_Nq[line] = %f, line_info->xs_sum[line] = %f, line_info->xs_compute = + // %d\n",line_info->xs_Nq[line],line_info->xs_sum[line],line_info->xs_compute); + } else + line_info->xs_reuse++; + line0 = Nq; + } -/* computes the number of possible reflections (return value), and the total xsection 'sum' */ -/* this routine looks for a pre-computed value in the Nq and sum cache tables */ -/* when found, the earch starts from the corresponding lower element in the table */ -int calc_xsect_union(double v, double *qv, double *my_sv2, int count, double *sum, - struct line_info_struct_union *line_info) { - int Nq = 0, line=0, line0=0; - *sum=0; - - //printf("Line_info when entering cross_section calculation\n"); - //printf("v = %f, qv = %f, my_sv2 = %f, count = %d, sum = %f\n",v,*qv,*my_sv2,count,*sum); - //printf("v = %f\n",v); - //printf("line_info->v = %f, line_info->v_min = %f, line_info->v_max = %f, line_info->neutron_passed = %f\n",line_info->v,line_info->v_min,line_info->v_max,line_info->neutron_passed); - //printf("line_info->xs_reuses = %d, line_info->xs_compute = %d\n",line_info->xs_reuse,line_info->xs_compute); - - - /* check if a line_info element has been recorded already */ - if (v >= line_info->v_min && v <= line_info->v_max && line_info->neutron_passed >= CHAR_BUF_LENGTH) { - line = (int)floor(v - line_info->v_min)*CHAR_BUF_LENGTH/(line_info->v_max - line_info->v_min); - Nq = line_info->xs_Nq[line]; - *sum = line_info->xs_sum[line]; - if (!Nq && *sum == 0) { - /* not yet set: we compute the sum up to the corresponding speed in the table cache */ - //printf("Nq and sum not yet set, have to do this calculation now\n"); - double line_v = line_info->v_min + line*(line_info->v_max - line_info->v_min)/CHAR_BUF_LENGTH; - for(line0=0; line0xs_Nq[line] = Nq; - line_info->xs_sum[line]= *sum; - line_info->xs_compute++; - //printf("line_info->xs_Nq[line] = %f, line_info->xs_sum[line] = %f, line_info->xs_compute = %d\n",line_info->xs_Nq[line],line_info->xs_sum[line],line_info->xs_compute); - } else line_info->xs_reuse++; - line0 = Nq; - } - - line_info->xs_calls++; - - for(line=line0; linexs_calls++; -#endif /* !POWDERN_DECL */ + for (line = line0; line < count; line++) { + if (qv[line] <= 2 * v) { /* q < 2*kf: restrict structural range */ + *sum += my_sv2[line]; + if (Nq < line + 1) + Nq = line + 1; /* determine maximum line index which can scatter */ + } else + break; + } + // printf("cross_section function to return %d lines to scatter with, with cross section sum %f \n",Nq,*sum); + return (Nq); + } /* calc_xsect_union */ + #endif /* !POWDERN_DECL */ -struct Powder_physics_storage_struct{ + struct Powder_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - - struct line_info_struct_union *line_info_storage; + + struct line_info_struct_union* line_info_storage; double my_scattering; double vertical_angular_limit; -}; + }; -// Obsolete: Function for initializing test_physics. Done in component instead. -int Powder_physics_initialize(union data_transfer_union data_transfer) { - // Obsolte - return 1; -}; + // Obsolete: Function for initializing test_physics. Done in component instead. + int + Powder_physics_initialize (union data_transfer_union data_transfer) { + // Obsolte + return 1; + }; -// Function for calculating my in a test case. -int Powder_physics_my(double *my,double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function for calculating my in a test case. + int + Powder_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, _class_particle* _particle) { //*my = data_transfer.pointer_to_a_Powder_physics_storage_struct->my_scattering; - - + int method_switch = 1; // For test - int line_v,line0,line; - + int line_v, line0, line; + // Should not interfer with the global variables - double vx = k_initial[0]*K2V; - double vy = k_initial[1]*K2V; - double vz = k_initial[2]*K2V; - + double vx = k_initial[0] * K2V; + double vy = k_initial[1] * K2V; + double vz = k_initial[2] * K2V; + // Not sure one can do this, but I do not see why not - struct line_info_struct_union *line_info = data_transfer.pointer_to_a_Powder_physics_storage_struct->line_info_storage; - - double v = sqrt(vx*vx + vy*vy + vz*vz); - //printf("Velocity = %f \n",v); - - //printf("line_info->v = %f, line_info->v_min = %f, line_info->v_max = %f, line_info->neutron_passed = %f\n",line_info->v,line_info->v_min,line_info->v_max,line_info->neutron_passed); - // Here the maximum and minimum v is recorded, should this be for scattering events or cross section calculations? + struct line_info_struct_union* line_info = data_transfer.pointer_to_a_Powder_physics_storage_struct->line_info_storage; + + double v = sqrt (vx * vx + vy * vy + vz * vz); + // printf("Velocity = %f \n",v); + + // printf("line_info->v = %f, line_info->v_min = %f, line_info->v_max = %f, line_info->neutron_passed = + // %f\n",line_info->v,line_info->v_min,line_info->v_max,line_info->neutron_passed); + // Here the maximum and minimum v is recorded, should this be for scattering events or cross section calculations? if (line_info->neutron_passed < CHAR_BUF_LENGTH) { - if (v < line_info->v_min) line_info->v_min = v; - if (v > line_info->v_max) line_info->v_max = v; + if (v < line_info->v_min) + line_info->v_min = v; + if (v > line_info->v_max) + line_info->v_max = v; line_info->neutron_passed++; } - + if (method_switch == 1) { - // Here the cross section is calculated and stored - if ( fabs(v - line_info->v) < 1e-6) { + // Here the cross section is calculated and stored + if (fabs (v - line_info->v) < 1e-6) { line_info->nb_reuses++; } else { - //printf("calling crosssection calculation \n"); - // int calc_xsect_union(double v, double *qv, double *my_sv2, int count, double *sum, struct line_info_struct *line_info) - line_info->Nq = calc_xsect_union(v, line_info->q_v, line_info->my_s_v2, line_info->count, &line_info->my_s_v2_sum, line_info); + // printf("calling crosssection calculation \n"); + // int calc_xsect_union(double v, double *qv, double *my_sv2, int count, double *sum, struct line_info_struct *line_info) + line_info->Nq = calc_xsect_union (v, line_info->q_v, line_info->my_s_v2, line_info->count, &line_info->my_s_v2_sum, line_info); line_info->v = v; line_info->nb_refl += line_info->Nq; line_info->nb_refl_count++; } } else { - if ( fabs(v - line_info->v) < 1e-6) { + if (fabs (v - line_info->v) < 1e-6) { line_info->nb_reuses++; } else { - //printf("calling crosssection calculation \n"); + // printf("calling crosssection calculation \n"); if (v >= line_info->v_min && v <= line_info->v_max && line_info->neutron_passed >= CHAR_BUF_LENGTH) { - line = (int)floor(v - line_info->v_min)*CHAR_BUF_LENGTH/(line_info->v_max - line_info->v_min); - line_info->Nq = line_info->xs_Nq[line]; - line_info->my_s_v2_sum = line_info->xs_sum[line]; - if (!line_info->Nq && line_info->my_s_v2_sum == 0) { - /* not yet set: we compute the sum up to the corresponding speed in the table cache */ - //printf("Nq and sum not yet set, have to do this calculation now\n"); - double line_v = line_info->v_min + line*(line_info->v_max - line_info->v_min)/CHAR_BUF_LENGTH; - for(line0=0; line0count; line0++) { - if (line_info->q_v[line0] <= 2*line_v) { /* q < 2*kf: restrict structural range */ - line_info->my_s_v2_sum += line_info->my_s_v2[line0]; - if (line_info->Nq < line0+1) line_info->Nq=line0+1; /* determine maximum line index which can scatter */ - } else break; - } - line_info->xs_Nq[line] = line_info->Nq; - line_info->xs_sum[line]= line_info->my_s_v2_sum; - line_info->xs_compute++; - //printf("line_info->xs_Nq[line] = %f, line_info->xs_sum[line] = %f, line_info->xs_compute = %d\n",line_info->xs_Nq[line],line_info->xs_sum[line],line_info->xs_compute); - } else line_info->xs_reuse++; - line0 = line_info->Nq; + line = (int)floor (v - line_info->v_min) * CHAR_BUF_LENGTH / (line_info->v_max - line_info->v_min); + line_info->Nq = line_info->xs_Nq[line]; + line_info->my_s_v2_sum = line_info->xs_sum[line]; + if (!line_info->Nq && line_info->my_s_v2_sum == 0) { + /* not yet set: we compute the sum up to the corresponding speed in the table cache */ + // printf("Nq and sum not yet set, have to do this calculation now\n"); + double line_v = line_info->v_min + line * (line_info->v_max - line_info->v_min) / CHAR_BUF_LENGTH; + for (line0 = 0; line0 < line_info->count; line0++) { + if (line_info->q_v[line0] <= 2 * line_v) { /* q < 2*kf: restrict structural range */ + line_info->my_s_v2_sum += line_info->my_s_v2[line0]; + if (line_info->Nq < line0 + 1) + line_info->Nq = line0 + 1; /* determine maximum line index which can scatter */ + } else + break; + } + line_info->xs_Nq[line] = line_info->Nq; + line_info->xs_sum[line] = line_info->my_s_v2_sum; + line_info->xs_compute++; + // printf("line_info->xs_Nq[line] = %f, line_info->xs_sum[line] = %f, line_info->xs_compute = + // %d\n",line_info->xs_Nq[line],line_info->xs_sum[line],line_info->xs_compute); + } else + line_info->xs_reuse++; + line0 = line_info->Nq; } - + line_info->xs_calls++; - - for(line=line0; linecount; line++) { - if (line_info->q_v[line] <= 2*v) { /* q < 2*kf: restrict structural range */ + + for (line = line0; line < line_info->count; line++) { + if (line_info->q_v[line] <= 2 * v) { /* q < 2*kf: restrict structural range */ line_info->my_s_v2_sum += line_info->my_s_v2[line]; - if (line_info->Nq < line+1) line_info->Nq=line+1; /* determine maximum line index which can scatter */ - } else break; + if (line_info->Nq < line + 1) + line_info->Nq = line + 1; /* determine maximum line index which can scatter */ + } else + break; } line_info->v = v; line_info->nb_refl += line_info->Nq; line_info->nb_refl_count++; } } - - *my = line_info->my_s_v2_sum/(v*v); - //printf("Returned my scattering of %f \n",*my); - //printf("compute = %d and reuse = %d \n",line_info->xs_compute,line_info->xs_reuse); - + + *my = line_info->my_s_v2_sum / (v * v); + // printf("Returned my scattering of %f \n",*my); + // printf("compute = %d and reuse = %d \n",line_info->xs_compute,line_info->xs_reuse); + return 1; -}; + }; -// Function that provides a basic nonuniform elastic scattering. Unphysical for testing purposes. -int Powder_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function that provides a basic nonuniform elastic scattering. Unphysical for testing purposes. + int + Powder_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { // This component need to write to its storage transfer for each event, is that possible with this structure? - struct line_info_struct_union *line_info = data_transfer.pointer_to_a_Powder_physics_storage_struct->line_info_storage; + struct line_info_struct_union* line_info = data_transfer.pointer_to_a_Powder_physics_storage_struct->line_info_storage; double vertical_angular_limit = data_transfer.pointer_to_a_Powder_physics_storage_struct->vertical_angular_limit; - - + // Should not interfer with the global variables - double vx = k_initial[0]*K2V; - double vy = k_initial[1]*K2V; - double vz = k_initial[2]*K2V; - - double v = sqrt(vx*vx + vy*vy + vz*vz); - + double vx = k_initial[0] * K2V; + double vy = k_initial[1] * K2V; + double vz = k_initial[2] * K2V; + + double v = sqrt (vx * vx + vy * vy + vz * vz); + int line; double arg; double theta; - double alpha,alpha0; - - double vout_x,vout_y,vout_z; - double tmp_vx,tmp_vy,tmp_vz; - double nx,ny,nz; + double alpha, alpha0; + + double vout_x, vout_y, vout_z; + double tmp_vx, tmp_vy, tmp_vz; + double nx, ny, nz; double my_s_n; - + // copy from PowderN component if (line_info->count > 0) { - /* choose line */ - if (line_info->Nq > 1) line=floor(line_info->Nq*rand01()); /* Select between Nq powder lines */ - else line = 0; - if (line_info->w_v[line]) - arg = line_info->q_v[line]*(1+line_info->w_v[line]*randnorm())/(2.0*v); - else - arg = line_info->q_v[line]/(2.0*v); - my_s_n = line_info->my_s_v2[line]/(v*v); - if(fabs(arg) > 1) { - //printf("Powder scattering function returned 0, should not happen\n"); - return 0; /* No bragg scattering possible (was absorb)*/ - } - theta = asin(arg); /* Bragg scattering law */ - - /* Choose point on Debye-Scherrer cone */ - if (vertical_angular_limit) - { /* relate height of detector to the height on DS cone */ - arg = sin(vertical_angular_limit*DEG2RAD/2)/sin(2*theta); - /* If full Debye-Scherrer cone is within d_phi, don't focus */ - if (arg < -1 || arg > 1) vertical_angular_limit = 0; - /* Otherwise, determine alpha to rotate from scattering plane - into vertical_angular_limit focusing area*/ - else alpha = 2*asin(arg); - } - if (vertical_angular_limit) { - /* Focusing */ - alpha = fabs(alpha); - /* Trick to get scattering for pos/neg theta's */ - alpha0= 2*rand01()*alpha; - if (alpha0 > alpha) { - alpha0=PI+(alpha0-1.5*alpha); - } else { - alpha0=alpha0-0.5*alpha; - } - } - else - alpha0 = PI*randpm1(); - - /* now find a nearly vertical rotation axis: - * Either - * (v along Z) x (X axis) -> nearly Y axis - * Or - * (v along X) x (Z axis) -> nearly Y axis - */ - if (fabs(scalar_prod(1,0,0,vx/v,vy/v,vz/v)) < fabs(scalar_prod(0,0,1,vx/v,vy/v,vz/v))) { - nx = 1; ny = 0; nz = 0; - } else { - nx = 0; ny = 0; nz = 1; - } - vec_prod(tmp_vx,tmp_vy,tmp_vz, vx,vy,vz, nx,ny,nz); - - /* v_out = rotate 'v' by 2*theta around tmp_v: Bragg angle */ - rotate(vout_x,vout_y,vout_z, vx,vy,vz, 2*theta, tmp_vx,tmp_vy,tmp_vz); - - /* tmp_v = rotate v_out by alpha0 around 'v' (Debye-Scherrer cone) */ - rotate(tmp_vx,tmp_vy,tmp_vz, vout_x,vout_y,vout_z, alpha0, vx, vy, vz); - vx = tmp_vx; - vy = tmp_vy; - vz = tmp_vz; - - k_final[0] = V2K*vx; k_final[1] = V2K*vy; k_final[2] = V2K*vz; - - //*weight *= line_info->Nq*my_s_n; I believe my_s_n is part of the correction for sampling posistion, not to be done here - *weight *= line_info->Nq*my_s_n/line_info->my_s_v2_sum*v*v; - - //printf("my_s_n = %f \n",my_s_n); - - // What to do with my_s_n ? - /* - pmul = line_info->Nq*l_full*my_s_n*exp(-(line_info->my_a_v/v+my_s)*(l+l_1)) - /(1-(p_inc+p_transmit)); - */ - // Correction in case of vertical_angular_limit focusing - BUT only when d_phi != 0 - if (vertical_angular_limit) *weight *= alpha/PI; - - - line_info->type = 'c'; - line_info->dq = line_info->q_v[line]*V2K; - - + /* choose line */ + if (line_info->Nq > 1) + line = floor (line_info->Nq * rand01 ()); /* Select between Nq powder lines */ + else + line = 0; + if (line_info->w_v[line]) + arg = line_info->q_v[line] * (1 + line_info->w_v[line] * randnorm ()) / (2.0 * v); + else + arg = line_info->q_v[line] / (2.0 * v); + my_s_n = line_info->my_s_v2[line] / (v * v); + if (fabs (arg) > 1) { + // printf("Powder scattering function returned 0, should not happen\n"); + return 0; /* No bragg scattering possible (was absorb)*/ + } + theta = asin (arg); /* Bragg scattering law */ + + /* Choose point on Debye-Scherrer cone */ + if (vertical_angular_limit) { /* relate height of detector to the height on DS cone */ + arg = sin (vertical_angular_limit * DEG2RAD / 2) / sin (2 * theta); + /* If full Debye-Scherrer cone is within d_phi, don't focus */ + if (arg < -1 || arg > 1) + vertical_angular_limit = 0; + /* Otherwise, determine alpha to rotate from scattering plane + into vertical_angular_limit focusing area*/ + else + alpha = 2 * asin (arg); + } + if (vertical_angular_limit) { + /* Focusing */ + alpha = fabs (alpha); + /* Trick to get scattering for pos/neg theta's */ + alpha0 = 2 * rand01 () * alpha; + if (alpha0 > alpha) { + alpha0 = PI + (alpha0 - 1.5 * alpha); } else { - /* else transmit <-- No powder lines in file */ - printf("Error, need lines in the PowderN input file\n"); + alpha0 = alpha0 - 0.5 * alpha; } + } else + alpha0 = PI * randpm1 (); + + /* now find a nearly vertical rotation axis: + * Either + * (v along Z) x (X axis) -> nearly Y axis + * Or + * (v along X) x (Z axis) -> nearly Y axis + */ + if (fabs (scalar_prod (1, 0, 0, vx / v, vy / v, vz / v)) < fabs (scalar_prod (0, 0, 1, vx / v, vy / v, vz / v))) { + nx = 1; + ny = 0; + nz = 0; + } else { + nx = 0; + ny = 0; + nz = 1; + } + vec_prod (tmp_vx, tmp_vy, tmp_vz, vx, vy, vz, nx, ny, nz); + + /* v_out = rotate 'v' by 2*theta around tmp_v: Bragg angle */ + rotate (vout_x, vout_y, vout_z, vx, vy, vz, 2 * theta, tmp_vx, tmp_vy, tmp_vz); + + /* tmp_v = rotate v_out by alpha0 around 'v' (Debye-Scherrer cone) */ + rotate (tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z, alpha0, vx, vy, vz); + vx = tmp_vx; + vy = tmp_vy; + vz = tmp_vz; + k_final[0] = V2K * vx; + k_final[1] = V2K * vy; + k_final[2] = V2K * vz; - //printf("Powder scattering function returned 1\n"); + //*weight *= line_info->Nq*my_s_n; I believe my_s_n is part of the correction for sampling posistion, not to be done here + *weight *= line_info->Nq * my_s_n / line_info->my_s_v2_sum * v * v; + + // printf("my_s_n = %f \n",my_s_n); + + // What to do with my_s_n ? + /* + pmul = line_info->Nq*l_full*my_s_n*exp(-(line_info->my_a_v/v+my_s)*(l+l_1)) + /(1-(p_inc+p_transmit)); + */ + // Correction in case of vertical_angular_limit focusing - BUT only when d_phi != 0 + if (vertical_angular_limit) + *weight *= alpha / PI; + + line_info->type = 'c'; + line_info->dq = line_info->q_v[line] * V2K; + + } else { + /* else transmit <-- No powder lines in file */ + printf ("Error, need lines in the PowderN input file\n"); + } + + // printf("Powder scattering function returned 1\n"); return 1; -}; -#ifndef PROCESS_DETECTOR - #define PROCESS_DETECTOR dummy -#endif - -#ifndef PROCESS_POWDER_DETECTOR - #define PROCESS_POWDER_DETECTOR dummy -#endif + }; + #ifndef PROCESS_DETECTOR + #define PROCESS_DETECTOR dummy + #endif + + #ifndef PROCESS_POWDER_DETECTOR + #define PROCESS_POWDER_DETECTOR dummy + #endif %} DECLARE %{ -// Needed for transport to the main component -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Needed for transport to the main component + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; -// Declare for this component, to do calculations on the input / store in the transported data -struct Powder_physics_storage_struct Powder_storage; -struct line_info_struct_union line_info; -double effective_my_scattering; + // Declare for this component, to do calculations on the input / store in the transported data + struct Powder_physics_storage_struct Powder_storage; + struct line_info_struct_union line_info; + double effective_my_scattering; -double *columns; + double* columns; %} INITIALIZE @@ -664,66 +702,68 @@ INITIALIZE // Initialize done in the component columns = format; - + // Copy from PowderN component - int i=0; - struct line_data_union *L; - line_info.Dd = delta_d_d; + int i = 0; + struct line_data_union* L; + line_info.Dd = delta_d_d; line_info.DWfactor = DW; - line_info.V_0 = Vc; - line_info.rho = density; - line_info.at_weight= weight; - line_info.at_nb = nb_atoms; - line_info.sigma_a = 0; // This inputs are not needed, as absorption is handled elsewhere - line_info.sigma_i = 0; // This input is not needed, as incoherent scattering is handled elsewhere - line_info.flag_barns=barns; - //line_info.shape = 0; - line_info.flag_warning=0; - line_info.Epsilon = Strain; - line_info.radius_i =line_info.xwidth_i=line_info.yheight_i=line_info.zdepth_i=0; - line_info.v = 0; + line_info.V_0 = Vc; + line_info.rho = density; + line_info.at_weight = weight; + line_info.at_nb = nb_atoms; + line_info.sigma_a = 0; // This inputs are not needed, as absorption is handled elsewhere + line_info.sigma_i = 0; // This input is not needed, as incoherent scattering is handled elsewhere + line_info.flag_barns = barns; + // line_info.shape = 0; + line_info.flag_warning = 0; + line_info.Epsilon = Strain; + line_info.radius_i = line_info.xwidth_i = line_info.yheight_i = line_info.zdepth_i = 0; + line_info.v = 0; line_info.Nq = 0; - //line_info.v_min = FLT_MAX; line_info.v_max = 0; - line_info.v_min = 10000000000; line_info.v_max = 0; - line_info.neutron_passed=0; + // line_info.v_min = FLT_MAX; line_info.v_max = 0; + line_info.v_min = 10000000000; + line_info.v_max = 0; + line_info.neutron_passed = 0; line_info.nb_reuses = line_info.nb_refl = line_info.nb_refl_count = 0; - line_info.xs_compute= line_info.xs_reuse= line_info.xs_calls =0; - for (i=0; i< 9; i++) line_info.column_order[i] = columns[i]; - strncpy(line_info.compname, NAME_CURRENT_COMP, 256); + line_info.xs_compute = line_info.xs_reuse = line_info.xs_calls = 0; + for (i = 0; i < 9; i++) + line_info.column_order[i] = columns[i]; + strncpy (line_info.compname, NAME_CURRENT_COMP, 256); // p_interact handled elsewhere - //if (p_interact) { + // if (p_interact) { // if (p_interact < p_inc) { double tmp=p_interact; p_interact=p_inc; p_inc=tmp; } // p_transmit = 1-p_interact-p_inc; //} - if (reflections && strlen(reflections) && strcmp(reflections, "NULL") && strcmp(reflections, "0")) { - i = read_line_data_union(reflections, &line_info); + if (reflections && strlen (reflections) && strcmp (reflections, "NULL") && strcmp (reflections, "0")) { + i = read_line_data_union (reflections, &line_info); if (i == 0) - exit(fprintf(stderr,"PowderN: %s: reflection file %s is not valid.\n" - "ERROR Please check file format (laz or lau).\n", NAME_CURRENT_COMP, reflections)); + exit (fprintf (stderr, + "PowderN: %s: reflection file %s is not valid.\n" + "ERROR Please check file format (laz or lau).\n", + NAME_CURRENT_COMP, reflections)); } /* compute the scattering unit density from material weight and density */ /* the weight of the scattering element is the chemical formula molecular weight * times the nb of chemical formulae in the scattering element (nb_atoms) */ - if (!line_info.V_0 && line_info.at_nb > 0 - && line_info.at_weight > 0 && line_info.rho > 0) { + if (!line_info.V_0 && line_info.at_nb > 0 && line_info.at_weight > 0 && line_info.rho > 0) { /* molar volume [cm^3/mol] = weight [g/mol] / density [g/cm^3] */ /* atom density per Angs^3 = [mol/cm^3] * N_Avogadro *(1e-8)^3 */ - line_info.V_0 = line_info.at_nb - /(line_info.rho/line_info.at_weight/1e24*6.02214199e23); + line_info.V_0 = line_info.at_nb / (line_info.rho / line_info.at_weight / 1e24 * 6.02214199e23); } /* the scattering unit cross sections are the chemical formula onces * times the nb of chemical formulae in the scattering element */ if (line_info.at_nb > 0) { - line_info.sigma_a *= line_info.at_nb; line_info.sigma_i *= line_info.at_nb; + line_info.sigma_a *= line_info.at_nb; + line_info.sigma_i *= line_info.at_nb; } if (line_info.V_0 <= 0) - fprintf(stderr,"PowderN: %s: density/unit cell volume is NULL (Vc). Unactivating component.\n", NAME_CURRENT_COMP); - + fprintf (stderr, "PowderN: %s: density/unit cell volume is NULL (Vc). Unactivating component.\n", NAME_CURRENT_COMP); if (line_info.flag_barns) { /* Factor 100 to convert from barns to fm^2 */ line_info.XsectionFactor = 100; @@ -734,48 +774,45 @@ INITIALIZE if (line_info.V_0 && i) { L = line_info.list; - line_info.q_v = malloc(line_info.count*sizeof(double)); - line_info.w_v = malloc(line_info.count*sizeof(double)); - line_info.my_s_v2 = malloc(line_info.count*sizeof(double)); + line_info.q_v = malloc (line_info.count * sizeof (double)); + line_info.w_v = malloc (line_info.count * sizeof (double)); + line_info.my_s_v2 = malloc (line_info.count * sizeof (double)); if (!line_info.q_v || !line_info.w_v || !line_info.my_s_v2) - exit(fprintf(stderr,"PowderN: %s: ERROR allocating memory (init)\n", NAME_CURRENT_COMP)); - for(i=0; imy_scattering = effective_my_scattering; This_process.probability_for_scattering_function = &Powder_physics_my; This_process.scattering_function = &Powder_physics_scattering; - + // This will be the same for all process's, and can thus be moved to an include. This_process.process_p_interact = interact_fraction; - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Powder_process:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} - + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Powder_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list,global_process_element); + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE @@ -811,10 +846,10 @@ TRACE FINALLY %{ - free(line_info.list); - free(line_info.q_v); - free(line_info.w_v); - free(line_info.my_s_v2); + free (line_info.list); + free (line_info.q_v); + free (line_info.w_v); + free (line_info.my_s_v2); %} END diff --git a/mcstas-comps/union/Single_crystal_process.comp b/mcstas-comps/union/Single_crystal_process.comp index 4bd2d37d3c..55e8d77af7 100755 --- a/mcstas-comps/union/Single_crystal_process.comp +++ b/mcstas-comps/union/Single_crystal_process.comp @@ -89,278 +89,298 @@ SETTING PARAMETERS(string reflections=0, delta_d_d=1e-4, SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Single_crystal_process component" -#endif - -%include "read_table-lib" -%include "interoff-lib" - -#ifndef SINGLE_CRYSTAL_PROCESS_DECL -#define SINGLE_CRYSTAL_PROCESS_DECL - -#ifndef Mosaic_AB_Undefined -#define Mosaic_AB_Undefined {0,0, 0,0,0, 0,0,0} -#endif - - struct hkl_data_union - { - int h,k,l; /* Indices for this reflection */ - double F2; /* Value of structure factor */ - double tau_x, tau_y, tau_z; /* Coordinates in reciprocal space */ - double tau; /* Length of (tau_x, tau_y, tau_z) */ - double u1x, u1y, u1z; /* First axis of local coordinate system */ - double u2x, u2y, u2z; /* Second axis of local coordinate system */ - double u3x, u3y, u3z; /* Third axis of local coordinate system */ - double sig123; /* The product sig1*sig2*sig3 = volume of spot */ - double m1, m2, m3; /* Diagonal matrix representation of Gauss */ - double cutoff; /* Cutoff value for Gaussian tails */ - }; - - struct tau_data_union - { - int index; /* Index into reflection table */ - double refl; - double xsect; - /* The following vectors are in local koordinates. */ - double rho_x, rho_y, rho_z; /* The vector ki - tau */ - double rho; /* Length of rho vector */ - double ox, oy, oz; /* Origin of Ewald sphere tangent plane */ - double b1x, b1y, b1z; /* Spanning vectors of Ewald sphere tangent */ - double b2x, b2y, b2z; - double l11, l12, l22; /* Cholesky decomposition L of 2D Gauss */ - double y0x, y0y; /* 2D Gauss center in tangent plane */ - }; - - struct hkl_info_struct_union - { - struct hkl_data_union *list; /* Reflection array */ - int count; /* Number of reflections */ - struct tau_data_union *tau_list; /* Reflections close to Ewald Sphere */ - double m_delta_d_d; /* Delta-d/d FWHM */ - double m_ax,m_ay,m_az; /* First unit cell axis (direct space, AA) */ - double m_bx,m_by,m_bz; /* Second unit cell axis */ - double m_cx,m_cy,m_cz; /* Third unit cell axis */ - double asx,asy,asz; /* First reciprocal lattice axis (1/AA) */ - double bsx,bsy,bsz; /* Second reciprocal lattice axis */ - double csx,csy,csz; /* Third reciprocal lattice axis */ - double m_a, m_b, m_c; /* length of lattice parameter lengths */ - double m_aa, m_bb, m_cc; /* lattice angles */ - double sigma_a, sigma_i; /* abs and inc X sect */ - double rho; /* density */ - double at_weight; /* atomic weight */ - double at_nb; /* nb of atoms in a cell */ - double V0; /* Unit cell volume (AA**3) */ - int column_order[5]; /* column signification [h,k,l,F,F2] */ - int recip; /* Flag to indicate if recip or direct cell axes given */ - int shape; /* 0:cylinder, 1:box, 2:sphere 3:any shape*/ - int flag_warning; /* number of warnings */ - char type; /* type of last event: t=transmit,c=coherent or i=incoherent */ - int h,k,l; /* last coherent scattering momentum transfer indices */ - int tau_count; /* Number of reflections within cutoff */ - double coh_refl, coh_xsect; /* cross section computed with last tau_list */ - double kix, kiy, kiz; /* last incoming neutron ki */ - int nb_reuses, nb_refl, nb_refl_count; - }; - - int SX_list_compare_union (void const *a, void const *b) - { - struct hkl_data_union const *pa = a; - struct hkl_data_union const *pb = b; + #ifndef Union + #error "The Union_init component must be included before this Single_crystal_process component" + #endif + + %include "read_table-lib" + %include "interoff-lib" + + #ifndef SINGLE_CRYSTAL_PROCESS_DECL + #define SINGLE_CRYSTAL_PROCESS_DECL + + #ifndef Mosaic_AB_Undefined + #define Mosaic_AB_Undefined {0,0, 0,0,0, 0,0,0} + #endif + + struct hkl_data_union { + int h, k, l; /* Indices for this reflection */ + double F2; /* Value of structure factor */ + double tau_x, tau_y, tau_z; /* Coordinates in reciprocal space */ + double tau; /* Length of (tau_x, tau_y, tau_z) */ + double u1x, u1y, u1z; /* First axis of local coordinate system */ + double u2x, u2y, u2z; /* Second axis of local coordinate system */ + double u3x, u3y, u3z; /* Third axis of local coordinate system */ + double sig123; /* The product sig1*sig2*sig3 = volume of spot */ + double m1, m2, m3; /* Diagonal matrix representation of Gauss */ + double cutoff; /* Cutoff value for Gaussian tails */ + }; + + struct tau_data_union { + int index; /* Index into reflection table */ + double refl; + double xsect; + /* The following vectors are in local koordinates. */ + double rho_x, rho_y, rho_z; /* The vector ki - tau */ + double rho; /* Length of rho vector */ + double ox, oy, oz; /* Origin of Ewald sphere tangent plane */ + double b1x, b1y, b1z; /* Spanning vectors of Ewald sphere tangent */ + double b2x, b2y, b2z; + double l11, l12, l22; /* Cholesky decomposition L of 2D Gauss */ + double y0x, y0y; /* 2D Gauss center in tangent plane */ + }; + + struct hkl_info_struct_union { + struct hkl_data_union* list; /* Reflection array */ + int count; /* Number of reflections */ + struct tau_data_union* tau_list; /* Reflections close to Ewald Sphere */ + double m_delta_d_d; /* Delta-d/d FWHM */ + double m_ax, m_ay, m_az; /* First unit cell axis (direct space, AA) */ + double m_bx, m_by, m_bz; /* Second unit cell axis */ + double m_cx, m_cy, m_cz; /* Third unit cell axis */ + double asx, asy, asz; /* First reciprocal lattice axis (1/AA) */ + double bsx, bsy, bsz; /* Second reciprocal lattice axis */ + double csx, csy, csz; /* Third reciprocal lattice axis */ + double m_a, m_b, m_c; /* length of lattice parameter lengths */ + double m_aa, m_bb, m_cc; /* lattice angles */ + double sigma_a, sigma_i; /* abs and inc X sect */ + double rho; /* density */ + double at_weight; /* atomic weight */ + double at_nb; /* nb of atoms in a cell */ + double V0; /* Unit cell volume (AA**3) */ + int column_order[5]; /* column signification [h,k,l,F,F2] */ + int recip; /* Flag to indicate if recip or direct cell axes given */ + int shape; /* 0:cylinder, 1:box, 2:sphere 3:any shape*/ + int flag_warning; /* number of warnings */ + char type; /* type of last event: t=transmit,c=coherent or i=incoherent */ + int h, k, l; /* last coherent scattering momentum transfer indices */ + int tau_count; /* Number of reflections within cutoff */ + double coh_refl, coh_xsect; /* cross section computed with last tau_list */ + double kix, kiy, kiz; /* last incoming neutron ki */ + int nb_reuses, nb_refl, nb_refl_count; + }; + + int + SX_list_compare_union (void const* a, void const* b) { + struct hkl_data_union const* pa = a; + struct hkl_data_union const* pb = b; /* Sort by tau */ - if (pa->tau < pb->tau) return -1; - if (pa->tau > pb->tau) return 1; + if (pa->tau < pb->tau) + return -1; + if (pa->tau > pb->tau) + return 1; /* Sort by tau_x */ - if (pa->tau_x < pb->tau_x) return -1; - if (pa->tau_x > pb->tau_x) return 1; + if (pa->tau_x < pb->tau_x) + return -1; + if (pa->tau_x > pb->tau_x) + return 1; /* Sort by tau_y */ - if (pa->tau_y < pb->tau_y) return -1; - if (pa->tau_y > pb->tau_y) return 1; + if (pa->tau_y < pb->tau_y) + return -1; + if (pa->tau_y > pb->tau_y) + return 1; /* Sort by tau_z */ - if (pa->tau_z < pb->tau_z) return -1; - if (pa->tau_z > pb->tau_z) return 1; + if (pa->tau_z < pb->tau_z) + return -1; + if (pa->tau_z > pb->tau_z) + return 1; /* In case of tie, sort by F2 also */ - if (pa->F2 < pb->F2) return -1; - if (pa->F2 > pb->F2) return 1; - + if (pa->F2 < pb->F2) + return -1; + if (pa->F2 > pb->F2) + return 1; return 0; } /* SX_list_compare */ - + /* ------------------------------------------------------------------------ */ int - read_hkl_data_union(char *SC_file, struct hkl_info_struct_union *info, - double SC_mosaic, double SC_mosaic_a, double SC_mosaic_b, double SC_mosaic_c, double *SC_mosaic_AB) - { - struct hkl_data_union *list = NULL; + read_hkl_data_union (char* SC_file, struct hkl_info_struct_union* info, double SC_mosaic, double SC_mosaic_a, double SC_mosaic_b, double SC_mosaic_c, + double* SC_mosaic_AB) { + struct hkl_data_union* list = NULL; int size = 0; t_Table sTable; /* sample data table structure from SC_file */ - int i=0; + int i = 0; double tmp_x, tmp_y, tmp_z; - char **parsing; - char flag=0; - double nb_atoms=1; + char** parsing; + char flag = 0; + double nb_atoms = 1; - if (!SC_file || !strlen(SC_file) || !strcmp(SC_file,"NULL") || !strcmp(SC_file,"0")) { + if (!SC_file || !strlen (SC_file) || !strcmp (SC_file, "NULL") || !strcmp (SC_file, "0")) { info->count = 0; - flag=1; + flag = 1; } if (!flag) { - Table_Read(&sTable, SC_file, 1); /* read 1st block data from SC_file into sTable*/ + Table_Read (&sTable, SC_file, 1); /* read 1st block data from SC_file into sTable*/ if (sTable.columns < 4) { - fprintf(stderr, "Single_crystal: Error: The number of columns in %s should be at least %d for [h,k,l,F2]\n", SC_file, 4); - return(0); + fprintf (stderr, "Single_crystal: Error: The number of columns in %s should be at least %d for [h,k,l,F2]\n", SC_file, 4); + return (0); } if (!sTable.rows) { - fprintf(stderr, "Single_crystal: Error: The number of rows in %s should be at least %d\n", SC_file, 1); - return(0); - } else size = sTable.rows; + fprintf (stderr, "Single_crystal: Error: The number of rows in %s should be at least %d\n", SC_file, 1); + return (0); + } else + size = sTable.rows; /* parsing of header */ - parsing = Table_ParseHeader(sTable.header, - "sigma_abs","sigma_a ", - "sigma_inc","sigma_i ", - "column_h", - "column_k", - "column_l", - "column_F ", - "column_F2", - "Delta_d/d", - "lattice_a ", - "lattice_b ", - "lattice_c ", - "lattice_aa", - "lattice_bb", - "lattice_cc", - "nb_atoms","multiplicity", - NULL); + parsing + = Table_ParseHeader (sTable.header, "sigma_abs", "sigma_a ", "sigma_inc", "sigma_i ", "column_h", "column_k", "column_l", "column_F ", "column_F2", + "Delta_d/d", "lattice_a ", "lattice_b ", "lattice_c ", "lattice_aa", "lattice_bb", "lattice_cc", "nb_atoms", "multiplicity", NULL); if (parsing) { - if (parsing[0] && !info->sigma_a) info->sigma_a=atof(parsing[0]); - if (parsing[1] && !info->sigma_a) info->sigma_a=atof(parsing[1]); - if (parsing[2] && !info->sigma_i) info->sigma_i=atof(parsing[2]); - if (parsing[3] && !info->sigma_i) info->sigma_i=atof(parsing[3]); - if (parsing[4]) info->column_order[0]=atoi(parsing[4]); - if (parsing[5]) info->column_order[1]=atoi(parsing[5]); - if (parsing[6]) info->column_order[2]=atoi(parsing[6]); - if (parsing[7]) info->column_order[3]=atoi(parsing[7]); - if (parsing[8]) info->column_order[4]=atoi(parsing[8]); - if (parsing[9] && info->m_delta_d_d <0) info->m_delta_d_d=atof(parsing[9]); - if (parsing[10] && !info->m_a) info->m_a =atof(parsing[10]); - if (parsing[11] && !info->m_b) info->m_b =atof(parsing[11]); - if (parsing[12] && !info->m_c) info->m_c =atof(parsing[12]); - if (parsing[13] && !info->m_aa) info->m_aa=atof(parsing[13]); - if (parsing[14] && !info->m_bb) info->m_bb=atof(parsing[14]); - if (parsing[15] && !info->m_cc) info->m_cc=atof(parsing[15]); - if (parsing[16]) nb_atoms=atof(parsing[16]); - if (parsing[17]) nb_atoms=atof(parsing[17]); - for (i=0; i<=17; i++) if (parsing[i]) free(parsing[i]); - free(parsing); + if (parsing[0] && !info->sigma_a) + info->sigma_a = atof (parsing[0]); + if (parsing[1] && !info->sigma_a) + info->sigma_a = atof (parsing[1]); + if (parsing[2] && !info->sigma_i) + info->sigma_i = atof (parsing[2]); + if (parsing[3] && !info->sigma_i) + info->sigma_i = atof (parsing[3]); + if (parsing[4]) + info->column_order[0] = atoi (parsing[4]); + if (parsing[5]) + info->column_order[1] = atoi (parsing[5]); + if (parsing[6]) + info->column_order[2] = atoi (parsing[6]); + if (parsing[7]) + info->column_order[3] = atoi (parsing[7]); + if (parsing[8]) + info->column_order[4] = atoi (parsing[8]); + if (parsing[9] && info->m_delta_d_d < 0) + info->m_delta_d_d = atof (parsing[9]); + if (parsing[10] && !info->m_a) + info->m_a = atof (parsing[10]); + if (parsing[11] && !info->m_b) + info->m_b = atof (parsing[11]); + if (parsing[12] && !info->m_c) + info->m_c = atof (parsing[12]); + if (parsing[13] && !info->m_aa) + info->m_aa = atof (parsing[13]); + if (parsing[14] && !info->m_bb) + info->m_bb = atof (parsing[14]); + if (parsing[15] && !info->m_cc) + info->m_cc = atof (parsing[15]); + if (parsing[16]) + nb_atoms = atof (parsing[16]); + if (parsing[17]) + nb_atoms = atof (parsing[17]); + for (i = 0; i <= 17; i++) + if (parsing[i]) + free (parsing[i]); + free (parsing); } } - - if (nb_atoms > 1) { info->sigma_a *= nb_atoms; info->sigma_i *= nb_atoms; } + + if (nb_atoms > 1) { + info->sigma_a *= nb_atoms; + info->sigma_i *= nb_atoms; + } /* special cases for the structure definition */ - if (info->m_ax || info->m_ay || info->m_az) info->m_a=0; /* means we specify by hand the vectors */ - if (info->m_bx || info->m_by || info->m_bz) info->m_b=0; - if (info->m_cx || info->m_cy || info->m_cz) info->m_c=0; + if (info->m_ax || info->m_ay || info->m_az) + info->m_a = 0; /* means we specify by hand the vectors */ + if (info->m_bx || info->m_by || info->m_bz) + info->m_b = 0; + if (info->m_cx || info->m_cy || info->m_cz) + info->m_c = 0; /* compute the norm from vector a if missing */ if (info->m_ax || info->m_ay || info->m_az) { - double as=sqrt(info->m_ax*info->m_ax+info->m_ay*info->m_ay+info->m_az*info->m_az); - if (!info->m_bx && !info->m_by && !info->m_bz) info->m_a=info->m_b=as; - if (!info->m_cx && !info->m_cy && !info->m_cz) info->m_a=info->m_c=as; + double as = sqrt (info->m_ax * info->m_ax + info->m_ay * info->m_ay + info->m_az * info->m_az); + if (!info->m_bx && !info->m_by && !info->m_bz) + info->m_a = info->m_b = as; + if (!info->m_cx && !info->m_cy && !info->m_cz) + info->m_a = info->m_c = as; } - if (info->m_a && !info->m_b) info->m_b=info->m_a; - if (info->m_b && !info->m_c) info->m_c=info->m_b; - + if (info->m_a && !info->m_b) + info->m_b = info->m_a; + if (info->m_b && !info->m_c) + info->m_c = info->m_b; + /* compute the lattive angles if not set from data file. Not used when in vector mode. */ - if (info->m_a && !info->m_aa) info->m_aa=90; - if (info->m_aa && !info->m_bb) info->m_bb=info->m_aa; - if (info->m_bb && !info->m_cc) info->m_cc=info->m_bb; - + if (info->m_a && !info->m_aa) + info->m_aa = 90; + if (info->m_aa && !info->m_bb) + info->m_bb = info->m_aa; + if (info->m_bb && !info->m_cc) + info->m_cc = info->m_bb; + /* parameters consistency checks */ if (!info->m_ax && !info->m_ay && !info->m_az && !info->m_a) { - fprintf(stderr, - "Single_crystal: Error: Wrong a lattice vector definition\n"); - return(0); + fprintf (stderr, "Single_crystal: Error: Wrong a lattice vector definition\n"); + return (0); } if (!info->m_bx && !info->m_by && !info->m_bz && !info->m_b) { - fprintf(stderr, - "Single_crystal: Error: Wrong b lattice vector definition\n"); - return(0); + fprintf (stderr, "Single_crystal: Error: Wrong b lattice vector definition\n"); + return (0); } if (!info->m_cx && !info->m_cy && !info->m_cz && !info->m_c) { - fprintf(stderr, - "Single_crystal: Error: Wrong c lattice vector definition\n"); - return(0); + fprintf (stderr, "Single_crystal: Error: Wrong c lattice vector definition\n"); + return (0); } if (info->m_aa && info->m_bb && info->m_cc && info->recip) { - fprintf(stderr, - "Single_crystal: Error: Selecting reciprocal cell and angles is unmeaningful\n"); - return(0); + fprintf (stderr, "Single_crystal: Error: Selecting reciprocal cell and angles is unmeaningful\n"); + return (0); } /* when lengths a,b,c + angles are given (instead of vectors a,b,c) */ - if (info->m_aa && info->m_bb && info->m_cc) - { - double as,bs,cs; - if (info->m_a) as = info->m_a; - else as = sqrt(info->m_ax*info->m_ax+info->m_ay*info->m_ay+info->m_az*info->m_az); - if (info->m_b) bs = info->m_b; - else bs = sqrt(info->m_bx*info->m_bx+info->m_by*info->m_by+info->m_bz*info->m_bz); - if (info->m_c) cs = info->m_c; - else cs = sqrt(info->m_cx*info->m_cx+info->m_cy*info->m_cy+info->m_cz*info->m_cz); - - info->m_bz = as; info->m_by = 0; info->m_bx = 0; - info->m_az = bs*cos(info->m_cc*DEG2RAD); - info->m_ay = bs*sin(info->m_cc*DEG2RAD); + if (info->m_aa && info->m_bb && info->m_cc) { + double as, bs, cs; + if (info->m_a) + as = info->m_a; + else + as = sqrt (info->m_ax * info->m_ax + info->m_ay * info->m_ay + info->m_az * info->m_az); + if (info->m_b) + bs = info->m_b; + else + bs = sqrt (info->m_bx * info->m_bx + info->m_by * info->m_by + info->m_bz * info->m_bz); + if (info->m_c) + cs = info->m_c; + else + cs = sqrt (info->m_cx * info->m_cx + info->m_cy * info->m_cy + info->m_cz * info->m_cz); + + info->m_bz = as; + info->m_by = 0; + info->m_bx = 0; + info->m_az = bs * cos (info->m_cc * DEG2RAD); + info->m_ay = bs * sin (info->m_cc * DEG2RAD); info->m_ax = 0; - info->m_cz = cs*cos(info->m_bb*DEG2RAD); - info->m_cy = cs*(cos(info->m_aa*DEG2RAD)-cos(info->m_cc*DEG2RAD)*cos(info->m_bb*DEG2RAD)) - /sin(info->m_cc*DEG2RAD); - info->m_cx = sqrt(cs*cs - info->m_cz*info->m_cz - info->m_cy*info->m_cy); + info->m_cz = cs * cos (info->m_bb * DEG2RAD); + info->m_cy = cs * (cos (info->m_aa * DEG2RAD) - cos (info->m_cc * DEG2RAD) * cos (info->m_bb * DEG2RAD)) / sin (info->m_cc * DEG2RAD); + info->m_cx = sqrt (cs * cs - info->m_cz * info->m_cz - info->m_cy * info->m_cy); - printf("Single_crystal: %s structure a=%g b=%g c=%g aa=%g bb=%g cc=%g ", - (flag ? "INC" : SC_file), as, bs, cs, info->m_aa, info->m_bb, info->m_cc); + printf ("Single_crystal: %s structure a=%g b=%g c=%g aa=%g bb=%g cc=%g ", (flag ? "INC" : SC_file), as, bs, cs, info->m_aa, info->m_bb, info->m_cc); } else { if (!info->recip) { - printf("Single_crystal: %s structure a=[%g,%g,%g] b=[%g,%g,%g] c=[%g,%g,%g] ", - (flag ? "INC" : SC_file), info->m_ax ,info->m_ay ,info->m_az, - info->m_bx ,info->m_by ,info->m_bz, - info->m_cx ,info->m_cy ,info->m_cz); + printf ("Single_crystal: %s structure a=[%g,%g,%g] b=[%g,%g,%g] c=[%g,%g,%g] ", (flag ? "INC" : SC_file), info->m_ax, info->m_ay, info->m_az, info->m_bx, + info->m_by, info->m_bz, info->m_cx, info->m_cy, info->m_cz); } else { - printf("Single_crystal: %s structure a*=[%g,%g,%g] b*=[%g,%g,%g] c*=[%g,%g,%g] ", - (flag ? "INC" : SC_file), info->m_ax ,info->m_ay ,info->m_az, - info->m_bx ,info->m_by ,info->m_bz, - info->m_cx ,info->m_cy ,info->m_cz); + printf ("Single_crystal: %s structure a*=[%g,%g,%g] b*=[%g,%g,%g] c*=[%g,%g,%g] ", (flag ? "INC" : SC_file), info->m_ax, info->m_ay, info->m_az, + info->m_bx, info->m_by, info->m_bz, info->m_cx, info->m_cy, info->m_cz); } } /* Compute reciprocal or direct lattice vectors. */ if (!info->recip) { - vec_prod(tmp_x, tmp_y, tmp_z, - info->m_bx, info->m_by, info->m_bz, - info->m_cx, info->m_cy, info->m_cz); - info->V0 = fabs(scalar_prod(info->m_ax, info->m_ay, info->m_az, tmp_x, tmp_y, tmp_z)); - printf("V0=%g\n", info->V0); - - info->asx = 2*PI/info->V0*tmp_x; - info->asy = 2*PI/info->V0*tmp_y; - info->asz = 2*PI/info->V0*tmp_z; - vec_prod(tmp_x, tmp_y, tmp_z, info->m_cx, info->m_cy, info->m_cz, info->m_ax, info->m_ay, info->m_az); - info->bsx = 2*PI/info->V0*tmp_x; - info->bsy = 2*PI/info->V0*tmp_y; - info->bsz = 2*PI/info->V0*tmp_z; - vec_prod(tmp_x, tmp_y, tmp_z, info->m_ax, info->m_ay, info->m_az, info->m_bx, info->m_by, info->m_bz); - info->csx = 2*PI/info->V0*tmp_x; - info->csy = 2*PI/info->V0*tmp_y; - info->csz = 2*PI/info->V0*tmp_z; + vec_prod (tmp_x, tmp_y, tmp_z, info->m_bx, info->m_by, info->m_bz, info->m_cx, info->m_cy, info->m_cz); + info->V0 = fabs (scalar_prod (info->m_ax, info->m_ay, info->m_az, tmp_x, tmp_y, tmp_z)); + printf ("V0=%g\n", info->V0); + + info->asx = 2 * PI / info->V0 * tmp_x; + info->asy = 2 * PI / info->V0 * tmp_y; + info->asz = 2 * PI / info->V0 * tmp_z; + vec_prod (tmp_x, tmp_y, tmp_z, info->m_cx, info->m_cy, info->m_cz, info->m_ax, info->m_ay, info->m_az); + info->bsx = 2 * PI / info->V0 * tmp_x; + info->bsy = 2 * PI / info->V0 * tmp_y; + info->bsz = 2 * PI / info->V0 * tmp_z; + vec_prod (tmp_x, tmp_y, tmp_z, info->m_ax, info->m_ay, info->m_az, info->m_bx, info->m_by, info->m_bz); + info->csx = 2 * PI / info->V0 * tmp_x; + info->csy = 2 * PI / info->V0 * tmp_y; + info->csz = 2 * PI / info->V0 * tmp_z; } else { info->asx = info->m_ax; info->asy = info->m_ay; @@ -371,107 +391,105 @@ SHARE info->csx = info->m_cx; info->csy = info->m_cy; info->csz = info->m_cz; - - vec_prod(tmp_x, tmp_y, tmp_z, - info->bsx/(2*PI), info->bsy/(2*PI), info->bsz/(2*PI), - info->csx/(2*PI), info->csy/(2*PI), info->csz/(2*PI)); - info->V0 = 1/fabs(scalar_prod(info->asx/(2*PI), info->asy/(2*PI), info->asz/(2*PI), tmp_x, tmp_y, tmp_z)); - printf("V0=%g\n", info->V0); - - /*compute the direct cell parameters, ofr completeness*/ - info->m_ax = tmp_x*info->V0; - info->m_ay = tmp_y*info->V0; - info->m_az = tmp_z*info->V0; - vec_prod(tmp_x, tmp_y, tmp_z,info->csx/(2*PI), info->csy/(2*PI), info->csz/(2*PI),info->asx/(2*PI), info->asy/(2*PI), info->asz/(2*PI)); - info->m_bx = tmp_x*info->V0; - info->m_by = tmp_y*info->V0; - info->m_bz = tmp_z*info->V0; - vec_prod(tmp_x, tmp_y, tmp_z,info->asx/(2*PI), info->asy/(2*PI), info->asz/(2*PI),info->bsx/(2*PI), info->bsy/(2*PI), info->bsz/(2*PI)); - info->m_cx = tmp_x*info->V0; - info->m_cy = tmp_y*info->V0; - info->m_cz = tmp_z*info->V0; + + vec_prod (tmp_x, tmp_y, tmp_z, info->bsx / (2 * PI), info->bsy / (2 * PI), info->bsz / (2 * PI), info->csx / (2 * PI), info->csy / (2 * PI), + info->csz / (2 * PI)); + info->V0 = 1 / fabs (scalar_prod (info->asx / (2 * PI), info->asy / (2 * PI), info->asz / (2 * PI), tmp_x, tmp_y, tmp_z)); + printf ("V0=%g\n", info->V0); + + /*compute the direct cell parameters, ofr completeness*/ + info->m_ax = tmp_x * info->V0; + info->m_ay = tmp_y * info->V0; + info->m_az = tmp_z * info->V0; + vec_prod (tmp_x, tmp_y, tmp_z, info->csx / (2 * PI), info->csy / (2 * PI), info->csz / (2 * PI), info->asx / (2 * PI), info->asy / (2 * PI), + info->asz / (2 * PI)); + info->m_bx = tmp_x * info->V0; + info->m_by = tmp_y * info->V0; + info->m_bz = tmp_z * info->V0; + vec_prod (tmp_x, tmp_y, tmp_z, info->asx / (2 * PI), info->asy / (2 * PI), info->asz / (2 * PI), info->bsx / (2 * PI), info->bsy / (2 * PI), + info->bsz / (2 * PI)); + info->m_cx = tmp_x * info->V0; + info->m_cy = tmp_y * info->V0; + info->m_cz = tmp_z * info->V0; } - if (flag) return(-1); + if (flag) + return (-1); if (!info->column_order[0] || !info->column_order[1] || !info->column_order[2]) { - fprintf(stderr, - "Single_crystal: Error: Wrong h,k,l column definition\n"); - return(0); + fprintf (stderr, "Single_crystal: Error: Wrong h,k,l column definition\n"); + return (0); } if (!info->column_order[3] && !info->column_order[4]) { - fprintf(stderr, - "Single_crystal: Error: Wrong F,F2 column definition\n"); - return(0); + fprintf (stderr, "Single_crystal: Error: Wrong F,F2 column definition\n"); + return (0); } /* allocate hkl_data array */ - list = (struct hkl_data_union*)malloc(size*sizeof(struct hkl_data_union)); + list = (struct hkl_data_union*)malloc (size * sizeof (struct hkl_data_union)); - for (i=0; icolumn_order[0]-1); - k = Table_Index(sTable, i, info->column_order[1]-1); - l = Table_Index(sTable, i, info->column_order[2]-1); - if (info->column_order[3]) - { F2= Table_Index(sTable, i, info->column_order[3]-1); F2 *= F2; } - else if (info->column_order[4]) - F2= Table_Index(sTable, i, info->column_order[4]-1); + h = Table_Index (sTable, i, info->column_order[0] - 1); + k = Table_Index (sTable, i, info->column_order[1] - 1); + l = Table_Index (sTable, i, info->column_order[2] - 1); + if (info->column_order[3]) { + F2 = Table_Index (sTable, i, info->column_order[3] - 1); + F2 *= F2; + } else if (info->column_order[4]) + F2 = Table_Index (sTable, i, info->column_order[4] - 1); list[i].h = h; list[i].k = k; list[i].l = l; list[i].F2 = F2; - + /* Precompute some values */ - list[i].tau_x = h*info->asx + k*info->bsx + l*info->csx; - list[i].tau_y = h*info->asy + k*info->bsy + l*info->csy; - list[i].tau_z = h*info->asz + k*info->bsz + l*info->csz; - list[i].tau = sqrt(list[i].tau_x*list[i].tau_x + - list[i].tau_y*list[i].tau_y + - list[i].tau_z*list[i].tau_z); - list[i].u1x = list[i].tau_x/list[i].tau; - list[i].u1y = list[i].tau_y/list[i].tau; - list[i].u1z = list[i].tau_z/list[i].tau; - sig1 = FWHM2RMS*info->m_delta_d_d*list[i].tau; + list[i].tau_x = h * info->asx + k * info->bsx + l * info->csx; + list[i].tau_y = h * info->asy + k * info->bsy + l * info->csy; + list[i].tau_z = h * info->asz + k * info->bsz + l * info->csz; + list[i].tau = sqrt (list[i].tau_x * list[i].tau_x + list[i].tau_y * list[i].tau_y + list[i].tau_z * list[i].tau_z); + list[i].u1x = list[i].tau_x / list[i].tau; + list[i].u1y = list[i].tau_y / list[i].tau; + list[i].u1z = list[i].tau_z / list[i].tau; + sig1 = FWHM2RMS * info->m_delta_d_d * list[i].tau; /* Find two arbitrary axes perpendicular to tau and each other. */ - normal_vec(&b1[0], &b1[1], &b1[2], - list[i].u1x, list[i].u1y, list[i].u1z); - vec_prod(b2[0], b2[1], b2[2], - list[i].u1x, list[i].u1y, list[i].u1z, - b1[0], b1[1], b1[2]); - + normal_vec (&b1[0], &b1[1], &b1[2], list[i].u1x, list[i].u1y, list[i].u1z); + vec_prod (b2[0], b2[1], b2[2], list[i].u1x, list[i].u1y, list[i].u1z, b1[0], b1[1], b1[2]); + /* Find the two mosaic axes perpendicular to tau. */ - if(SC_mosaic > 0) { + if (SC_mosaic > 0) { /* Use isotropic mosaic. */ list[i].u2x = b1[0]; list[i].u2y = b1[1]; list[i].u2z = b1[2]; - sig2 = FWHM2RMS*list[i].tau*MIN2RAD*SC_mosaic; + sig2 = FWHM2RMS * list[i].tau * MIN2RAD * SC_mosaic; list[i].u3x = b2[0]; list[i].u3y = b2[1]; list[i].u3z = b2[2]; - sig3 = FWHM2RMS*list[i].tau*MIN2RAD*SC_mosaic; - } else if(SC_mosaic_a > 0 && SC_mosaic_b > 0 && SC_mosaic_c > 0) { + sig3 = FWHM2RMS * list[i].tau * MIN2RAD * SC_mosaic; + } else if (SC_mosaic_a > 0 && SC_mosaic_b > 0 && SC_mosaic_c > 0) { /* Use anisotropic mosaic. */ - fprintf(stderr,"Single_crystal: Warning: you are using an experimental feature:\n" - " anistropic mosaicity. Please examine your data carefully.\n"); + fprintf (stderr, "Single_crystal: Warning: you are using an experimental feature:\n" + " anistropic mosaicity. Please examine your data carefully.\n"); /* compute the jacobian of (tau_v,tau_n) from rotations around the unit cell vectors. */ - struct hkl_data_union *l =&(list[i]); - double xia_x,xia_y,xia_z,xib_x,xib_y,xib_z,xic_x,xic_y,xic_z; + struct hkl_data_union* l = &(list[i]); + double xia_x, xia_y, xia_z, xib_x, xib_y, xib_z, xic_x, xic_y, xic_z; /*input parameters are in arc minutes*/ - double sig_fi_a=SC_mosaic_a*MIN2RAD; - double sig_fi_b=SC_mosaic_b*MIN2RAD; - double sig_fi_c=SC_mosaic_c*MIN2RAD; - if(info->m_a==0) info->m_a=sqrt(scalar_prod( info->m_ax,info->m_ay,info->m_az,info->m_ax,info->m_ay,info->m_az)); - if(info->m_b==0) info->m_b=sqrt(scalar_prod( info->m_bx,info->m_by,info->m_bz,info->m_bx,info->m_by,info->m_bz)); - if(info->m_c==0) info->m_c=sqrt(scalar_prod( info->m_cx,info->m_cy,info->m_cz,info->m_cx,info->m_cy,info->m_cz)); + double sig_fi_a = SC_mosaic_a * MIN2RAD; + double sig_fi_b = SC_mosaic_b * MIN2RAD; + double sig_fi_c = SC_mosaic_c * MIN2RAD; + if (info->m_a == 0) + info->m_a = sqrt (scalar_prod (info->m_ax, info->m_ay, info->m_az, info->m_ax, info->m_ay, info->m_az)); + if (info->m_b == 0) + info->m_b = sqrt (scalar_prod (info->m_bx, info->m_by, info->m_bz, info->m_bx, info->m_by, info->m_bz)); + if (info->m_c == 0) + info->m_c = sqrt (scalar_prod (info->m_cx, info->m_cy, info->m_cz, info->m_cx, info->m_cy, info->m_cz)); l->u2x = b1[0]; l->u2y = b1[1]; @@ -479,132 +497,138 @@ SHARE l->u3x = b2[0]; l->u3y = b2[1]; l->u3z = b2[2]; - - xia_x=l->tau_x-(M_2_PI*h/info->m_a)*info->asx; - xia_y=l->tau_y-(M_2_PI*h/info->m_a)*info->asy; - xia_z=l->tau_z-(M_2_PI*h/info->m_a)*info->asz; - xib_x=l->tau_x-(M_2_PI*h/info->m_b)*info->bsx; - xib_y=l->tau_y-(M_2_PI*h/info->m_b)*info->bsy; - xib_z=l->tau_z-(M_2_PI*h/info->m_b)*info->bsz; - xic_x=l->tau_x-(M_2_PI*h/info->m_c)*info->csx; - xic_y=l->tau_y-(M_2_PI*h/info->m_c)*info->csy; - xic_z=l->tau_z-(M_2_PI*h/info->m_c)*info->csz; - - double xia=sqrt(xia_x*xia_x + xia_y*xia_y + xia_z*xia_z); - double xib=sqrt(xib_x*xib_x + xib_y*xib_y + xib_z*xib_z); - double xic=sqrt(xic_x*xic_x + xic_y*xic_y + xic_z*xic_z); - - vec_prod(tmp_x,tmp_y,tmp_z,l->tau_x,l->tau_y,l->tau_z, l->u2x,l->u2y,l->u2z); - double J_n_fia= xia/info->m_a/l->tau*scalar_prod(info->asx,info->asy,info->asz,tmp_x,tmp_y,tmp_z); - vec_prod(tmp_x,tmp_y,tmp_z,l->tau_x,l->tau_y,l->tau_z, l->u2x,l->u2y,l->u2z); - double J_n_fib= xib/info->m_b/l->tau*scalar_prod(info->bsx,info->bsy,info->bsz,tmp_x,tmp_y,tmp_z); - vec_prod(tmp_x,tmp_y,tmp_z,l->tau_x,l->tau_y,l->tau_z, l->u2x,l->u2y,l->u2z); - double J_n_fic= xic/info->m_c/l->tau*scalar_prod(info->csx,info->csy,info->csz,tmp_x,tmp_y,tmp_z); - - vec_prod(tmp_x,tmp_y,tmp_z,l->tau_x,l->tau_y,l->tau_z, l->u3x,l->u3y,l->u3z); - double J_v_fia= xia/info->m_a/l->tau*scalar_prod(info->asx,info->asy,info->asz,tmp_x,tmp_y,tmp_z); - vec_prod(tmp_x,tmp_y,tmp_z,l->tau_x,l->tau_y,l->tau_z, l->u3x,l->u3y,l->u3z); - double J_v_fib= xib/info->m_b/l->tau*scalar_prod(info->bsx,info->bsy,info->bsz,tmp_x,tmp_y,tmp_z); - vec_prod(tmp_x,tmp_y,tmp_z,l->tau_x,l->tau_y,l->tau_z, l->u3x,l->u3y,l->u3z); - double J_v_fic= xic/info->m_c/l->tau*scalar_prod(info->csx,info->csy,info->csz,tmp_x,tmp_y,tmp_z); + + xia_x = l->tau_x - (M_2_PI * h / info->m_a) * info->asx; + xia_y = l->tau_y - (M_2_PI * h / info->m_a) * info->asy; + xia_z = l->tau_z - (M_2_PI * h / info->m_a) * info->asz; + xib_x = l->tau_x - (M_2_PI * h / info->m_b) * info->bsx; + xib_y = l->tau_y - (M_2_PI * h / info->m_b) * info->bsy; + xib_z = l->tau_z - (M_2_PI * h / info->m_b) * info->bsz; + xic_x = l->tau_x - (M_2_PI * h / info->m_c) * info->csx; + xic_y = l->tau_y - (M_2_PI * h / info->m_c) * info->csy; + xic_z = l->tau_z - (M_2_PI * h / info->m_c) * info->csz; + + double xia = sqrt (xia_x * xia_x + xia_y * xia_y + xia_z * xia_z); + double xib = sqrt (xib_x * xib_x + xib_y * xib_y + xib_z * xib_z); + double xic = sqrt (xic_x * xic_x + xic_y * xic_y + xic_z * xic_z); + + vec_prod (tmp_x, tmp_y, tmp_z, l->tau_x, l->tau_y, l->tau_z, l->u2x, l->u2y, l->u2z); + double J_n_fia = xia / info->m_a / l->tau * scalar_prod (info->asx, info->asy, info->asz, tmp_x, tmp_y, tmp_z); + vec_prod (tmp_x, tmp_y, tmp_z, l->tau_x, l->tau_y, l->tau_z, l->u2x, l->u2y, l->u2z); + double J_n_fib = xib / info->m_b / l->tau * scalar_prod (info->bsx, info->bsy, info->bsz, tmp_x, tmp_y, tmp_z); + vec_prod (tmp_x, tmp_y, tmp_z, l->tau_x, l->tau_y, l->tau_z, l->u2x, l->u2y, l->u2z); + double J_n_fic = xic / info->m_c / l->tau * scalar_prod (info->csx, info->csy, info->csz, tmp_x, tmp_y, tmp_z); + + vec_prod (tmp_x, tmp_y, tmp_z, l->tau_x, l->tau_y, l->tau_z, l->u3x, l->u3y, l->u3z); + double J_v_fia = xia / info->m_a / l->tau * scalar_prod (info->asx, info->asy, info->asz, tmp_x, tmp_y, tmp_z); + vec_prod (tmp_x, tmp_y, tmp_z, l->tau_x, l->tau_y, l->tau_z, l->u3x, l->u3y, l->u3z); + double J_v_fib = xib / info->m_b / l->tau * scalar_prod (info->bsx, info->bsy, info->bsz, tmp_x, tmp_y, tmp_z); + vec_prod (tmp_x, tmp_y, tmp_z, l->tau_x, l->tau_y, l->tau_z, l->u3x, l->u3y, l->u3z); + double J_v_fic = xic / info->m_c / l->tau * scalar_prod (info->csx, info->csy, info->csz, tmp_x, tmp_y, tmp_z); /*with the jacobian we can compute the sigmas in terms of the orthogonal vectors u2 and u3*/ - sig2=sig_fi_a*fabs(J_v_fia) + sig_fi_b*fabs(J_v_fib) + sig_fi_c*fabs(J_v_fic); - sig3=sig_fi_a*fabs(J_n_fia) + sig_fi_b*fabs(J_n_fib) + sig_fi_c*fabs(J_n_fic); - } else if (SC_mosaic_AB[0]!=0 && SC_mosaic_AB[1]!=0){ - if ( (SC_mosaic_AB[2]==0 && SC_mosaic_AB[3]==0 && SC_mosaic_AB[4]==0) || (SC_mosaic_AB[5]==0 && SC_mosaic_AB[6]==0 && SC_mosaic_AB[7]==0) ){ - fprintf(stderr,"Single_crystal: Error: in-plane mosaics are specified but one (or both)\n" - " in-plane reciprocal vector is the zero vector\n"); - return(0); + sig2 = sig_fi_a * fabs (J_v_fia) + sig_fi_b * fabs (J_v_fib) + sig_fi_c * fabs (J_v_fic); + sig3 = sig_fi_a * fabs (J_n_fia) + sig_fi_b * fabs (J_n_fib) + sig_fi_c * fabs (J_n_fic); + } else if (SC_mosaic_AB[0] != 0 && SC_mosaic_AB[1] != 0) { + if ((SC_mosaic_AB[2] == 0 && SC_mosaic_AB[3] == 0 && SC_mosaic_AB[4] == 0) || (SC_mosaic_AB[5] == 0 && SC_mosaic_AB[6] == 0 && SC_mosaic_AB[7] == 0)) { + fprintf (stderr, "Single_crystal: Error: in-plane mosaics are specified but one (or both)\n" + " in-plane reciprocal vector is the zero vector\n"); + return (0); } - fprintf(stderr,"Single_crystal: Warning: you are using an experimental feature: \n" - " \"in-plane\" anistropic mosaicity. Please examine your data carefully.\n"); - + fprintf (stderr, "Single_crystal: Warning: you are using an experimental feature: \n" + " \"in-plane\" anistropic mosaicity. Please examine your data carefully.\n"); + /*for given reflection in list - compute linear comb of tau_a and tau_b*/ /*check for not in plane - f.i. check if (tau_a X tau_b).tau_i)==0*/ - struct hkl_data_union *l =&(list[i]); - double det,c1,c2,sig_tau_c; - double em_x,em_y,em_z, tmp_x,tmp_y,tmp_z; - double tau_a[3],tau_b[3]; + struct hkl_data_union* l = &(list[i]); + double det, c1, c2, sig_tau_c; + double em_x, em_y, em_z, tmp_x, tmp_y, tmp_z; + double tau_a[3], tau_b[3]; /*convert Miller indices to taus*/ - if(info->m_a==0) info->m_a=sqrt(scalar_prod( info->m_ax,info->m_ay,info->m_az,info->m_ax,info->m_ay,info->m_az)); - if(info->m_b==0) info->m_b=sqrt(scalar_prod( info->m_bx,info->m_by,info->m_bz,info->m_bx,info->m_by,info->m_bz)); - if(info->m_c==0) info->m_c=sqrt(scalar_prod( info->m_cx,info->m_cy,info->m_cz,info->m_cx,info->m_cy,info->m_cz)); - tau_a[0]=M_2_PI*( (SC_mosaic_AB[2]/info->m_a)*info->asx + (SC_mosaic_AB[3]/info->m_b)*info->bsx + (SC_mosaic_AB[4]/info->m_c)*info->csx ); - tau_a[1]=M_2_PI*( (SC_mosaic_AB[2]/info->m_a)*info->asy + (SC_mosaic_AB[3]/info->m_b)*info->bsy + (SC_mosaic_AB[4]/info->m_c)*info->csy ); - tau_a[2]=M_2_PI*( (SC_mosaic_AB[2]/info->m_a)*info->asz + (SC_mosaic_AB[3]/info->m_b)*info->bsz + (SC_mosaic_AB[4]/info->m_c)*info->csz ); - tau_b[0]=M_2_PI*( (SC_mosaic_AB[5]/info->m_a)*info->asx + (SC_mosaic_AB[6]/info->m_b)*info->bsx + (SC_mosaic_AB[7]/info->m_c)*info->csx ); - tau_b[1]=M_2_PI*( (SC_mosaic_AB[5]/info->m_a)*info->asy + (SC_mosaic_AB[6]/info->m_b)*info->bsy + (SC_mosaic_AB[7]/info->m_c)*info->csy ); - tau_b[2]=M_2_PI*( (SC_mosaic_AB[5]/info->m_a)*info->asz + (SC_mosaic_AB[6]/info->m_b)*info->bsz + (SC_mosaic_AB[7]/info->m_c)*info->csz ); - + if (info->m_a == 0) + info->m_a = sqrt (scalar_prod (info->m_ax, info->m_ay, info->m_az, info->m_ax, info->m_ay, info->m_az)); + if (info->m_b == 0) + info->m_b = sqrt (scalar_prod (info->m_bx, info->m_by, info->m_bz, info->m_bx, info->m_by, info->m_bz)); + if (info->m_c == 0) + info->m_c = sqrt (scalar_prod (info->m_cx, info->m_cy, info->m_cz, info->m_cx, info->m_cy, info->m_cz)); + tau_a[0] = M_2_PI * ((SC_mosaic_AB[2] / info->m_a) * info->asx + (SC_mosaic_AB[3] / info->m_b) * info->bsx + (SC_mosaic_AB[4] / info->m_c) * info->csx); + tau_a[1] = M_2_PI * ((SC_mosaic_AB[2] / info->m_a) * info->asy + (SC_mosaic_AB[3] / info->m_b) * info->bsy + (SC_mosaic_AB[4] / info->m_c) * info->csy); + tau_a[2] = M_2_PI * ((SC_mosaic_AB[2] / info->m_a) * info->asz + (SC_mosaic_AB[3] / info->m_b) * info->bsz + (SC_mosaic_AB[4] / info->m_c) * info->csz); + tau_b[0] = M_2_PI * ((SC_mosaic_AB[5] / info->m_a) * info->asx + (SC_mosaic_AB[6] / info->m_b) * info->bsx + (SC_mosaic_AB[7] / info->m_c) * info->csx); + tau_b[1] = M_2_PI * ((SC_mosaic_AB[5] / info->m_a) * info->asy + (SC_mosaic_AB[6] / info->m_b) * info->bsy + (SC_mosaic_AB[7] / info->m_c) * info->csy); + tau_b[2] = M_2_PI * ((SC_mosaic_AB[5] / info->m_a) * info->asz + (SC_mosaic_AB[6] / info->m_b) * info->bsz + (SC_mosaic_AB[7] / info->m_c) * info->csz); + /*check determinants to see how we should compute the linear combination of a and b (to match c)*/ - if ((det=tau_a[0]*tau_b[1]-tau_a[1]*tau_b[0])!=0){ - c1= (l->tau_x*tau_b[1] - l->tau_y*tau_b[0])/det; - c2= (tau_a[0]*l->tau_y - tau_a[1]*l->tau_x)/det; - }else if ((det=tau_a[1]*tau_b[2]-tau_a[2]*tau_b[1])!=0){ - c1= (l->tau_y*tau_b[2] - l->tau_z*tau_b[1])/det; - c2= (tau_a[1]*l->tau_z - tau_a[2]*l->tau_y)/det; - }else if ((det=tau_a[0]*tau_b[2]-tau_a[2]*tau_b[0])!=0){ - c1= (l->tau_x*tau_b[2] - l->tau_z*tau_b[0])/det; - c2= (tau_a[0]*l->tau_z - tau_a[2]*l->tau_x)/det; + if ((det = tau_a[0] * tau_b[1] - tau_a[1] * tau_b[0]) != 0) { + c1 = (l->tau_x * tau_b[1] - l->tau_y * tau_b[0]) / det; + c2 = (tau_a[0] * l->tau_y - tau_a[1] * l->tau_x) / det; + } else if ((det = tau_a[1] * tau_b[2] - tau_a[2] * tau_b[1]) != 0) { + c1 = (l->tau_y * tau_b[2] - l->tau_z * tau_b[1]) / det; + c2 = (tau_a[1] * l->tau_z - tau_a[2] * l->tau_y) / det; + } else if ((det = tau_a[0] * tau_b[2] - tau_a[2] * tau_b[0]) != 0) { + c1 = (l->tau_x * tau_b[2] - l->tau_z * tau_b[0]) / det; + c2 = (tau_a[0] * l->tau_z - tau_a[2] * l->tau_x) / det; } - if ((c1==0) && (c2==0)){ - fprintf(stderr,"Single_crystal: Warning: reflection tau[%i]=(%g %g %g) " - "has no component in defined mosaic plane\n", - i, l->tau_x,l->tau_y,l->tau_z); + if ((c1 == 0) && (c2 == 0)) { + fprintf (stderr, + "Single_crystal: Warning: reflection tau[%i]=(%g %g %g) " + "has no component in defined mosaic plane\n", + i, l->tau_x, l->tau_y, l->tau_z); } /*compute linear combination => sig_tau_i = | c1*sig_tau_a + c2*sig_tau_b | - also add in the minute to radian scaling factor*/; - sig_tau_c = MIN2RAD*sqrt(c1*SC_mosaic_AB[0]*c1*SC_mosaic_AB[0] + c2*SC_mosaic_AB[1]*c2*SC_mosaic_AB[1]); - l->u2x = b1[0]; l->u2y = b1[1]; l->u2z = b1[2]; - l->u3x = b2[0]; l->u3y = b2[1]; l->u3z = b2[2]; + sig_tau_c = MIN2RAD * sqrt (c1 * SC_mosaic_AB[0] * c1 * SC_mosaic_AB[0] + c2 * SC_mosaic_AB[1] * c2 * SC_mosaic_AB[1]); + l->u2x = b1[0]; + l->u2y = b1[1]; + l->u2z = b1[2]; + l->u3x = b2[0]; + l->u3y = b2[1]; + l->u3z = b2[2]; /*so now let's compute the rotation around planenormal tau_a X tau_b*/ /*g_bar (unit normal of rotation plane) = tau_a X tau_b / norm(tau_a X tau_b)*/ - vec_prod(tmp_x,tmp_y,tmp_z, tau_a[0],tau_a[1],tau_a[2],tau_b[0],tau_b[1],tau_b[2]); - vec_prod(em_x,em_y,em_z, l->tau_x, l->tau_y, l->tau_z, tmp_x,tmp_y,tmp_z); - NORM(em_x,em_y,em_z); - sig2 = l->tau*sig_tau_c*fabs(scalar_prod(em_x,em_y,em_z, l->u2x,l->u2y,l->u2z)); - sig3 = l->tau*sig_tau_c*fabs(scalar_prod(em_x,em_y,em_z, l->u3x,l->u3y,l->u3z)); + vec_prod (tmp_x, tmp_y, tmp_z, tau_a[0], tau_a[1], tau_a[2], tau_b[0], tau_b[1], tau_b[2]); + vec_prod (em_x, em_y, em_z, l->tau_x, l->tau_y, l->tau_z, tmp_x, tmp_y, tmp_z); + NORM (em_x, em_y, em_z); + sig2 = l->tau * sig_tau_c * fabs (scalar_prod (em_x, em_y, em_z, l->u2x, l->u2y, l->u2z)); + sig3 = l->tau * sig_tau_c * fabs (scalar_prod (em_x, em_y, em_z, l->u3x, l->u3y, l->u3z)); /*protect against collapsing gaussians. These seem to be sensible values.*/ - if (sig2<1e-5) sig2=1e-5; - if (sig3<1e-5) sig3=1e-5; - } - else { - fprintf(stderr, - "Single_crystal: Error: EITHER mosaic OR (mosaic_a, mosaic_b, mosaic_c)\n" - " must be given and be >0.\n"); - return(0); + if (sig2 < 1e-5) + sig2 = 1e-5; + if (sig3 < 1e-5) + sig3 = 1e-5; + } else { + fprintf (stderr, "Single_crystal: Error: EITHER mosaic OR (mosaic_a, mosaic_b, mosaic_c)\n" + " must be given and be >0.\n"); + return (0); } - list[i].sig123 = sig1*sig2*sig3; - list[i].m1 = 1/(2*sig1*sig1); - list[i].m2 = 1/(2*sig2*sig2); - list[i].m3 = 1/(2*sig3*sig3); + list[i].sig123 = sig1 * sig2 * sig3; + list[i].m1 = 1 / (2 * sig1 * sig1); + list[i].m2 = 1 / (2 * sig2 * sig2); + list[i].m3 = 1 / (2 * sig3 * sig3); /* Set Gauss cutoff to 5 times the maximal sigma. */ - if(sig1 > sig2) - if(sig1 > sig3) - list[i].cutoff = 5*sig1; + if (sig1 > sig2) + if (sig1 > sig3) + list[i].cutoff = 5 * sig1; else - list[i].cutoff = 5*sig3; + list[i].cutoff = 5 * sig3; + else if (sig2 > sig3) + list[i].cutoff = 5 * sig2; else - if(sig2 > sig3) - list[i].cutoff = 5*sig2; - else - list[i].cutoff = 5*sig3; + list[i].cutoff = 5 * sig3; } - Table_Free(&sTable); - + Table_Free (&sTable); + /* sort the list with increasing tau */ - qsort(list, i, sizeof(struct hkl_data_union), SX_list_compare_union); - + qsort (list, i, sizeof (struct hkl_data_union), SX_list_compare_union); + info->list = list; info->count = i; - info->tau_list = malloc(i*sizeof(*info->tau_list)); - if(!info->tau_list) - { - fprintf(stderr, "Single_crystal: Error: Out of memory!\n"); - return(0); + info->tau_list = malloc (i * sizeof (*info->tau_list)); + if (!info->tau_list) { + fprintf (stderr, "Single_crystal: Error: Out of memory!\n"); + return (0); } - return(info->count); + return (info->count); } /* read_hkl_data */ /* ------------------------------------------------------------------------ */ @@ -616,380 +640,388 @@ SHARE this function returns: tau_count (return), coh_refl, coh_xsect, T (updated elements in the array up to [j]) */ - int hkl_search_union(struct hkl_data_union *L, struct tau_data_union *T, int count, double V0, - double kix, double kiy, double kiz, double tau_max, - double *coh_refl, double *coh_xsect) - { + int + hkl_search_union (struct hkl_data_union* L, struct tau_data_union* T, int count, double V0, double kix, double kiy, double kiz, double tau_max, + double* coh_refl, double* coh_xsect) { double rho, rho_x, rho_y, rho_z; double diff; - int i,j; - double ox,oy,oz; - double b1x,b1y,b1z, b2x,b2y,b2z, kx, ky, kz, nx, ny, nz; - double n11, n22, n12, det_N, inv_n11, inv_n22, inv_n12, l11, l22, l12, det_L; + int i, j; + double ox, oy, oz; + double b1x, b1y, b1z, b2x, b2y, b2z, kx, ky, kz, nx, ny, nz; + double n11, n22, n12, det_N, inv_n11, inv_n22, inv_n12, l11, l22, l12, det_L; double Bt_D_O_x, Bt_D_O_y, y0x, y0y, alpha; - - double ki = sqrt(kix*kix+kiy*kiy+kiz*kiz); + + double ki = sqrt (kix * kix + kiy * kiy + kiz * kiz); /* Common factor in coherent cross-section */ - double xsect_factor = pow(2*PI, 5.0/2.0)/(V0*ki*ki); - - for(i = j = 0; i < count; i++) - { - /* Assuming reflections are sorted, stop search when max tau exceeded. */ - if(L[i].tau > tau_max) - break; - /* Check if this reciprocal lattice point is close enough to the - Ewald sphere to make scattering possible. */ - rho_x = kix - L[i].tau_x; - rho_y = kiy - L[i].tau_y; - rho_z = kiz - L[i].tau_z; - rho = sqrt(rho_x*rho_x + rho_y*rho_y + rho_z*rho_z); - diff = fabs(rho - ki); - - /* Check if scattering is possible (cutoff of Gaussian tails). */ - if(diff <= L[i].cutoff) - { - /* Store reflection. */ - T[j].index = i; - /* Get ki vector in local coordinates. */ - kx = kix*L[i].u1x + kiy*L[i].u1y + kiz*L[i].u1z; - ky = kix*L[i].u2x + kiy*L[i].u2y + kiz*L[i].u2z; - kz = kix*L[i].u3x + kiy*L[i].u3y + kiz*L[i].u3z; - T[j].rho_x = kx - L[i].tau; - T[j].rho_y = ky; - T[j].rho_z = kz; - T[j].rho = rho; - /* Compute the tangent plane of the Ewald sphere. */ - nx = T[j].rho_x/T[j].rho; - ny = T[j].rho_y/T[j].rho; - nz = T[j].rho_z/T[j].rho; - ox = (ki - T[j].rho)*nx; - oy = (ki - T[j].rho)*ny; - oz = (ki - T[j].rho)*nz; - T[j].ox = ox; - T[j].oy = oy; - T[j].oz = oz; - /* Compute unit vectors b1 and b2 that span the tangent plane. */ - normal_vec(&b1x, &b1y, &b1z, nx, ny, nz); - vec_prod(b2x, b2y, b2z, nx, ny, nz, b1x, b1y, b1z); - T[j].b1x = b1x; - T[j].b1y = b1y; - T[j].b1z = b1z; - T[j].b2x = b2x; - T[j].b2y = b2y; - T[j].b2z = b2z; - /* Compute the 2D projection of the 3D Gauss of the reflection. */ - /* The symmetric 2x2 matrix N describing the 2D gauss. */ - n11 = L[i].m1*b1x*b1x + L[i].m2*b1y*b1y + L[i].m3*b1z*b1z; - n12 = L[i].m1*b1x*b2x + L[i].m2*b1y*b2y + L[i].m3*b1z*b2z; - n22 = L[i].m1*b2x*b2x + L[i].m2*b2y*b2y + L[i].m3*b2z*b2z; - /* The (symmetric) inverse matrix of N. */ - det_N = n11*n22 - n12*n12; - inv_n11 = n22/det_N; - inv_n12 = -n12/det_N; - inv_n22 = n11/det_N; - /* The Cholesky decomposition of 1/2*inv_n (lower triangular L). */ - l11 = sqrt(inv_n11/2); - l12 = inv_n12/(2*l11); - l22 = sqrt(inv_n22/2 - l12*l12); - T[j].l11 = l11; - T[j].l12 = l12; - T[j].l22 = l22; - det_L = l11*l22; - /* The product B^T D o. */ - Bt_D_O_x = b1x*L[i].m1*ox + b1y*L[i].m2*oy + b1z*L[i].m3*oz; - Bt_D_O_y = b2x*L[i].m1*ox + b2y*L[i].m2*oy + b2z*L[i].m3*oz; - /* Center of 2D Gauss in plane coordinates. */ - y0x = -(Bt_D_O_x*inv_n11 + Bt_D_O_y*inv_n12); - y0y = -(Bt_D_O_x*inv_n12 + Bt_D_O_y*inv_n22); - T[j].y0x = y0x; - T[j].y0y = y0y; - /* Factor alpha for the distance of the 2D Gauss from the origin. */ - alpha = L[i].m1*ox*ox + L[i].m2*oy*oy + L[i].m3*oz*oz - - (y0x*y0x*n11 + y0y*y0y*n22 + 2*y0x*y0y*n12); - T[j].refl = xsect_factor*det_L*exp(-alpha)/L[i].sig123; /* intensity of that Bragg */ - *coh_refl += T[j].refl; /* total scatterable intensity */ - T[j].xsect = T[j].refl*L[i].F2; - *coh_xsect += T[j].xsect; - j++; - } - - } /* end for */ - return (j); // this is 'tau_count', i.e. number of reachable reflections - } /* end hkl_search */ - - int hkl_select_union(struct tau_data_union *T, int tau_count, double coh_refl, double *sum, _class_particle *_particle) { - int j; - double r = rand0max(coh_refl); - *sum = 0; - for(j = 0; j < tau_count; j++) - { - *sum += T[j].refl; - if(*sum > r) break; + double xsect_factor = pow (2 * PI, 5.0 / 2.0) / (V0 * ki * ki); + + for (i = j = 0; i < count; i++) { + /* Assuming reflections are sorted, stop search when max tau exceeded. */ + if (L[i].tau > tau_max) + break; + /* Check if this reciprocal lattice point is close enough to the + Ewald sphere to make scattering possible. */ + rho_x = kix - L[i].tau_x; + rho_y = kiy - L[i].tau_y; + rho_z = kiz - L[i].tau_z; + rho = sqrt (rho_x * rho_x + rho_y * rho_y + rho_z * rho_z); + diff = fabs (rho - ki); + + /* Check if scattering is possible (cutoff of Gaussian tails). */ + if (diff <= L[i].cutoff) { + /* Store reflection. */ + T[j].index = i; + /* Get ki vector in local coordinates. */ + kx = kix * L[i].u1x + kiy * L[i].u1y + kiz * L[i].u1z; + ky = kix * L[i].u2x + kiy * L[i].u2y + kiz * L[i].u2z; + kz = kix * L[i].u3x + kiy * L[i].u3y + kiz * L[i].u3z; + T[j].rho_x = kx - L[i].tau; + T[j].rho_y = ky; + T[j].rho_z = kz; + T[j].rho = rho; + /* Compute the tangent plane of the Ewald sphere. */ + nx = T[j].rho_x / T[j].rho; + ny = T[j].rho_y / T[j].rho; + nz = T[j].rho_z / T[j].rho; + ox = (ki - T[j].rho) * nx; + oy = (ki - T[j].rho) * ny; + oz = (ki - T[j].rho) * nz; + T[j].ox = ox; + T[j].oy = oy; + T[j].oz = oz; + /* Compute unit vectors b1 and b2 that span the tangent plane. */ + normal_vec (&b1x, &b1y, &b1z, nx, ny, nz); + vec_prod (b2x, b2y, b2z, nx, ny, nz, b1x, b1y, b1z); + T[j].b1x = b1x; + T[j].b1y = b1y; + T[j].b1z = b1z; + T[j].b2x = b2x; + T[j].b2y = b2y; + T[j].b2z = b2z; + /* Compute the 2D projection of the 3D Gauss of the reflection. */ + /* The symmetric 2x2 matrix N describing the 2D gauss. */ + n11 = L[i].m1 * b1x * b1x + L[i].m2 * b1y * b1y + L[i].m3 * b1z * b1z; + n12 = L[i].m1 * b1x * b2x + L[i].m2 * b1y * b2y + L[i].m3 * b1z * b2z; + n22 = L[i].m1 * b2x * b2x + L[i].m2 * b2y * b2y + L[i].m3 * b2z * b2z; + /* The (symmetric) inverse matrix of N. */ + det_N = n11 * n22 - n12 * n12; + inv_n11 = n22 / det_N; + inv_n12 = -n12 / det_N; + inv_n22 = n11 / det_N; + /* The Cholesky decomposition of 1/2*inv_n (lower triangular L). */ + l11 = sqrt (inv_n11 / 2); + l12 = inv_n12 / (2 * l11); + l22 = sqrt (inv_n22 / 2 - l12 * l12); + T[j].l11 = l11; + T[j].l12 = l12; + T[j].l22 = l22; + det_L = l11 * l22; + /* The product B^T D o. */ + Bt_D_O_x = b1x * L[i].m1 * ox + b1y * L[i].m2 * oy + b1z * L[i].m3 * oz; + Bt_D_O_y = b2x * L[i].m1 * ox + b2y * L[i].m2 * oy + b2z * L[i].m3 * oz; + /* Center of 2D Gauss in plane coordinates. */ + y0x = -(Bt_D_O_x * inv_n11 + Bt_D_O_y * inv_n12); + y0y = -(Bt_D_O_x * inv_n12 + Bt_D_O_y * inv_n22); + T[j].y0x = y0x; + T[j].y0y = y0y; + /* Factor alpha for the distance of the 2D Gauss from the origin. */ + alpha = L[i].m1 * ox * ox + L[i].m2 * oy * oy + L[i].m3 * oz * oz - (y0x * y0x * n11 + y0y * y0y * n22 + 2 * y0x * y0y * n12); + T[j].refl = xsect_factor * det_L * exp (-alpha) / L[i].sig123; /* intensity of that Bragg */ + *coh_refl += T[j].refl; /* total scatterable intensity */ + T[j].xsect = T[j].refl * L[i].F2; + *coh_xsect += T[j].xsect; + j++; } - return j; - } - /* Functions for "reorientation", powder and PG modes */ - /* Powder, forward */ - void randrotate_union(double *nx, double *ny, double *nz, double a, double b, double c) { - double x1, y1, z1, x2, y2, z2; - rotate(x1, y1, z1, *nx,*ny,*nz, a, 1, 0, 0); /* <1> = rot(,a) */ - rotate(x2, y2, z2, x1, y1, z1, b, 0, 1, 0); /* <2> = rot(<1>,b) */ - rotate(*nx,*ny,*nz, x2, y2, z2, c, 0, 0, 1); /* = rot(<2>,c) */ - } - /* Powder, back */ - void randderotate_union(double *nx, double *ny, double *nz, double a, double b, double c) { - double x1, y1, z1, x2, y2, z2; - rotate(x1, y1, z1, *nx,*ny,*nz, -c, 0,0,1); - rotate(x2, y2, z2, x1, y1, z1, -b, 0,1,0); - rotate(*nx,*ny,*nz, x2, y2, z2, -a, 1,0,0); - } - /* PG, forward */ - void PGrotate_union(double *nx, double *ny, double *nz, double a, double csx, double csy, double csz) { - /* Currently assumes c-axis along 'x', ought to be generalized... */ - double nvx, nvy, nvz; - rotate(nvx,nvy,nvz, *nx, *ny, *nz, a, csx, csy, csz); - *nx = nvx; *ny = nvy; *nz = nvz; - } - /* PG, back */ - void PGderotate_union(double *nx, double *ny, double *nz, double a, double csx, double csy, double csz) { - /* Currently assumes c-axis along 'x', ought to be generalized... */ - double nvx, nvy, nvz; - rotate(nvx,nvy,nvz, *nx, *ny, *nz, -a, csx, csy, csz); - *nx = nvx; *ny = nvy; *nz = nvz; + } /* end for */ + return (j); // this is 'tau_count', i.e. number of reachable reflections + } /* end hkl_search */ + + int + hkl_select_union (struct tau_data_union* T, int tau_count, double coh_refl, double* sum, _class_particle* _particle) { + int j; + double r = rand0max (coh_refl); + *sum = 0; + for (j = 0; j < tau_count; j++) { + *sum += T[j].refl; + if (*sum > r) + break; } + return j; + } + /* Functions for "reorientation", powder and PG modes */ + /* Powder, forward */ + void + randrotate_union (double* nx, double* ny, double* nz, double a, double b, double c) { + double x1, y1, z1, x2, y2, z2; + rotate (x1, y1, z1, *nx, *ny, *nz, a, 1, 0, 0); /* <1> = rot(,a) */ + rotate (x2, y2, z2, x1, y1, z1, b, 0, 1, 0); /* <2> = rot(<1>,b) */ + rotate (*nx, *ny, *nz, x2, y2, z2, c, 0, 0, 1); /* = rot(<2>,c) */ + } + /* Powder, back */ + void + randderotate_union (double* nx, double* ny, double* nz, double a, double b, double c) { + double x1, y1, z1, x2, y2, z2; + rotate (x1, y1, z1, *nx, *ny, *nz, -c, 0, 0, 1); + rotate (x2, y2, z2, x1, y1, z1, -b, 0, 1, 0); + rotate (*nx, *ny, *nz, x2, y2, z2, -a, 1, 0, 0); + } + /* PG, forward */ + void + PGrotate_union (double* nx, double* ny, double* nz, double a, double csx, double csy, double csz) { + /* Currently assumes c-axis along 'x', ought to be generalized... */ + double nvx, nvy, nvz; + rotate (nvx, nvy, nvz, *nx, *ny, *nz, a, csx, csy, csz); + *nx = nvx; + *ny = nvy; + *nz = nvz; + } + /* PG, back */ + void + PGderotate_union (double* nx, double* ny, double* nz, double a, double csx, double csy, double csz) { + /* Currently assumes c-axis along 'x', ought to be generalized... */ + double nvx, nvy, nvz; + rotate (nvx, nvy, nvz, *nx, *ny, *nz, -a, csx, csy, csz); + *nx = nvx; + *ny = nvy; + *nz = nvz; + } -#endif /* !SINGLE_CRYSTAL_PROCESS_DECL */ + #endif /* !SINGLE_CRYSTAL_PROCESS_DECL */ -// Very important to add a pointer to this struct in the union-lib.c file -struct Single_crystal_physics_storage_struct{ + // Very important to add a pointer to this struct in the union-lib.c file + struct Single_crystal_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + // Avoid duplicates of output parameters and setting parameters in naming double PG_setting; // 0 if PG mode is diabled, 1 if enabled. Values between apporximates texture? double powder_setting; // 0 if powder mode is disabled, 1 if enabled. Values between approximates texture? double Alpha; // random angle between 0 and 2*Pi*powder double Beta; // random angle between -Pi/2 and Pi/2 - double Gamma; // random angle between -Pi and Pi - - struct hkl_info_struct_union *hkl_info_storage; // struct containing all necessary info for SC - double pack; // packing factor - double barns_setting; // Sets wether barns of fm^2 is used -}; - -// Function for calculating my, the inverse penetration depth (for only this scattering process). -// The input for this function and its order may not be changed, but the names may be updated. -int Single_crystal_physics_my(double *my, double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + double Gamma; // random angle between -Pi and Pi + + struct hkl_info_struct_union* hkl_info_storage; // struct containing all necessary info for SC + double pack; // packing factor + double barns_setting; // Sets wether barns of fm^2 is used + }; + + // Function for calculating my, the inverse penetration depth (for only this scattering process). + // The input for this function and its order may not be changed, but the names may be updated. + int + Single_crystal_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { // *k_initial is a pointer to a simple vector with 3 doubles, k[0], k[1], k[2] which describes the wavevector - double kix = k_initial[0],kiy = k_initial[1],kiz = k_initial[2]; - double ki = sqrt(k_initial[0]*k_initial[0]+k_initial[1]*k_initial[1]+k_initial[2]*k_initial[2]); - - struct hkl_info_struct_union *hkl_info = data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->hkl_info_storage; - + double kix = k_initial[0], kiy = k_initial[1], kiz = k_initial[2]; + double ki = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); + + struct hkl_info_struct_union* hkl_info = data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->hkl_info_storage; + // Taken from Single_crystal and changed hkl_info to a pointer. // The split optimization is less useful here than normally - + if (data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->powder_setting) { - //orientation of crystallite is random - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha = randpm1()*PI*data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->powder_setting; - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Beta = randpm1()*PI/2; - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Gamma = randpm1()*PI; - - randrotate_union(&kix, &kiy, &kiz, - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Beta, - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Gamma); + // orientation of crystallite is random + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha + = randpm1 () * PI * data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->powder_setting; + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Beta = randpm1 () * PI / 2; + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Gamma = randpm1 () * PI; + + randrotate_union (&kix, &kiy, &kiz, data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Beta, + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Gamma); } if (data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->PG_setting) { // orientation of crystallite is random - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha = rand01()*2*PI*data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->PG_setting; - PGrotate_union(&kix, &kiy, &kiz, - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, - hkl_info->csx, hkl_info->csy, hkl_info->csz); + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha + = rand01 () * 2 * PI * data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->PG_setting; + PGrotate_union (&kix, &kiy, &kiz, data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, hkl_info->csx, hkl_info->csy, hkl_info->csz); } - + /* in case we use 'SPLIT' then consecutive neutrons can be identical when entering here and we may skip the hkl_search call */ - if ( fabs(kix - hkl_info->kix) < 1e-6 - && fabs(kiy - hkl_info->kiy) < 1e-6 - && fabs(kiz - hkl_info->kiz) < 1e-6) { - hkl_info->nb_reuses++; - } else { - /* Max possible tau for this ki with 5*sigma delta-d/d cutoff. */ - double tau_max = 2*ki/(1 - 5*hkl_info->m_delta_d_d); - double coh_xsect = 0, coh_refl = 0; - - /* call hkl_search */ - hkl_info->tau_count = hkl_search_union(hkl_info->list, hkl_info->tau_list, hkl_info->count, hkl_info->V0, kix, kiy, kiz, tau_max, &coh_refl, &coh_xsect); /* CPU consuming */ - - // This is problematic as there is no way to know if this is the first scattering in this material or not with the current structure. - // Need to do one of the following: - // remove this optimization - // find a way to set event_counter to 0 when a neutron enters a volume with a SC process - // pass the number of scatterings in this volume to all my functions - // temporary solution: all events are considered the first - int event_counter = 0; - - - /* store ki so that we can check for further SPLIT iterations */ - if (event_counter == 0 ) { /* only for incoming neutron */ - hkl_info->kix = kix; - hkl_info->kiy = kiy; - hkl_info->kiz = kiz; - } - - hkl_info->coh_refl = coh_refl; - hkl_info->coh_xsect = coh_xsect; - hkl_info->nb_refl += hkl_info->tau_count; - hkl_info->nb_refl_count++; + if (fabs (kix - hkl_info->kix) < 1e-6 && fabs (kiy - hkl_info->kiy) < 1e-6 && fabs (kiz - hkl_info->kiz) < 1e-6) { + hkl_info->nb_reuses++; + } else { + /* Max possible tau for this ki with 5*sigma delta-d/d cutoff. */ + double tau_max = 2 * ki / (1 - 5 * hkl_info->m_delta_d_d); + double coh_xsect = 0, coh_refl = 0; + + /* call hkl_search */ + hkl_info->tau_count = hkl_search_union (hkl_info->list, hkl_info->tau_list, hkl_info->count, hkl_info->V0, kix, kiy, kiz, tau_max, &coh_refl, + &coh_xsect); /* CPU consuming */ + + // This is problematic as there is no way to know if this is the first scattering in this material or not with the current structure. + // Need to do one of the following: + // remove this optimization + // find a way to set event_counter to 0 when a neutron enters a volume with a SC process + // pass the number of scatterings in this volume to all my functions + // temporary solution: all events are considered the first + int event_counter = 0; + + /* store ki so that we can check for further SPLIT iterations */ + if (event_counter == 0) { /* only for incoming neutron */ + hkl_info->kix = kix; + hkl_info->kiy = kiy; + hkl_info->kiz = kiz; } - /* (3). Probabilities of the different possible interactions. */ - //tot_xsect = abs_xsect + inc_xsect + hkl_info.coh_xsect; - /* Cross-sections are in barns = 10**-28 m**2, and unit cell volumes are - in AA**3 = 10**-30 m**2. Hence a factor of 100 is used to convert - scattering lengths to m**-1 */ - double coh_xlen = hkl_info->coh_xsect/hkl_info->V0; - if (data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->barns_setting) { - coh_xlen *= 100; - } - - //printf("Single crystal process returned coh_xlen = %E \n",coh_xlen); - *my = coh_xlen*data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->pack; - int iterate; - //if (hkl_info->tau_count == 0) printf("my: ki=%f, no reflections matched \n",ki); - for (iterate=0;iteratetau_count;iterate++) - //printf("my: ki=%f, hkl_info->coh_xsect = %f, T[%d].refl = %f, coh_xlen = %f \n",ki,hkl_info->coh_xsect,iterate,hkl_info->tau_list[iterate].refl,coh_xlen); - // Probably need to rotate back from Powder/PG/curvature mode, as another process than this one could be selected. Would just need to send the used rotation parameters to the process to repeat that rotation. - - return 1; -}; - -// Function that provides description of a basic scattering event. -// Do not change the -int Single_crystal_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { - - int i; /* Index into structure factor list */ - struct hkl_data_union *L; /* Structure factor list */ - int j; /* Index into reflection list */ - struct tau_data_union *T; /* List of reflections close to Ewald sphere */ - //double ox, oy, oz; /* Origin of Ewald sphere tangent plane */ - //double l11, l12, l22; /* Cholesky decomposition L of 1/2*inv(N) */ - double b1x, b1y, b1z; /* First vector spanning tangent plane */ - double b2x, b2y, b2z; /* Second vector spanning tangent plane */ - double z1, z2, y1, y2; /* Temporaries to choose kf from 2D Gauss */ - double adjust, r, sum; /* Temporaries */ - double kfx, kfy, kfz; /* Final wave vector */ - - double kix = k_initial[0],kiy = k_initial[1],kiz = k_initial[2]; - double ki = sqrt(k_initial[0]*k_initial[0]+k_initial[1]*k_initial[1]+k_initial[2]*k_initial[2]); - - struct hkl_info_struct_union *hkl_info = data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->hkl_info_storage; - + hkl_info->coh_refl = coh_refl; + hkl_info->coh_xsect = coh_xsect; + hkl_info->nb_refl += hkl_info->tau_count; + hkl_info->nb_refl_count++; + } + + /* (3). Probabilities of the different possible interactions. */ + // tot_xsect = abs_xsect + inc_xsect + hkl_info.coh_xsect; + /* Cross-sections are in barns = 10**-28 m**2, and unit cell volumes are + in AA**3 = 10**-30 m**2. Hence a factor of 100 is used to convert + scattering lengths to m**-1 */ + double coh_xlen = hkl_info->coh_xsect / hkl_info->V0; + if (data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->barns_setting) { + coh_xlen *= 100; + } + + // printf("Single crystal process returned coh_xlen = %E \n",coh_xlen); + *my = coh_xlen * data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->pack; + int iterate; + // if (hkl_info->tau_count == 0) printf("my: ki=%f, no reflections matched \n",ki); + for (iterate = 0; iterate < hkl_info->tau_count; iterate++) + // printf("my: ki=%f, hkl_info->coh_xsect = %f, T[%d].refl = %f, coh_xlen = %f + // \n",ki,hkl_info->coh_xsect,iterate,hkl_info->tau_list[iterate].refl,coh_xlen); + // Probably need to rotate back from Powder/PG/curvature mode, as another process than this one could be selected. Would just need to send the used rotation + // parameters to the process to repeat that rotation. + + return 1; + }; + + // Function that provides description of a basic scattering event. + // Do not change the + int + Single_crystal_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, + struct focus_data_struct* focus_data, _class_particle* _particle) { + + int i; /* Index into structure factor list */ + struct hkl_data_union* L; /* Structure factor list */ + int j; /* Index into reflection list */ + struct tau_data_union* T; /* List of reflections close to Ewald sphere */ + // double ox, oy, oz; /* Origin of Ewald sphere tangent plane */ + // double l11, l12, l22; /* Cholesky decomposition L of 1/2*inv(N) */ + double b1x, b1y, b1z; /* First vector spanning tangent plane */ + double b2x, b2y, b2z; /* Second vector spanning tangent plane */ + double z1, z2, y1, y2; /* Temporaries to choose kf from 2D Gauss */ + double adjust, r, sum; /* Temporaries */ + double kfx, kfy, kfz; /* Final wave vector */ + + double kix = k_initial[0], kiy = k_initial[1], kiz = k_initial[2]; + double ki = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); + + struct hkl_info_struct_union* hkl_info = data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->hkl_info_storage; + L = hkl_info->list; T = hkl_info->tau_list; - - + // Taken from Single_crystal.comp - if(hkl_info->coh_refl <= 0){ - return 0; // Return 0 will use ABSORB in main component (as it is not allowed in a function) + if (hkl_info->coh_refl <= 0) { + return 0; // Return 0 will use ABSORB in main component (as it is not allowed in a function) } sum = 0; - j = hkl_select_union(T, hkl_info->tau_count, hkl_info->coh_refl, &sum, _particle); - //printf("Selected j = %d with T[%d].refl = %f \n",j,j,T[j].refl); + j = hkl_select_union (T, hkl_info->tau_count, hkl_info->coh_refl, &sum, _particle); + // printf("Selected j = %d with T[%d].refl = %f \n",j,j,T[j].refl); - if(j >= hkl_info->tau_count) - { + if (j >= hkl_info->tau_count) { #ifndef OPENACC if (hkl_info->flag_warning < 100) - fprintf(stderr, "Single_crystal_process: Error: Illegal tau search " - "(r=%g, sum=%g, j=%i, tau_count=%i).\n", r, sum, j , hkl_info->tau_count); + fprintf (stderr, + "Single_crystal_process: Error: Illegal tau search " + "(r=%g, sum=%g, j=%i, tau_count=%i).\n", + r, sum, j, hkl_info->tau_count); #endif hkl_info->flag_warning++; j = hkl_info->tau_count - 1; } i = T[j].index; /* (8). Pick scattered wavevector kf from 2D Gauss distribution. */ - z1 = randnorm(); - z2 = randnorm(); - y1 = T[j].l11*z1 + T[j].y0x; - y2 = T[j].l12*z1 + T[j].l22*z2 + T[j].y0y; - kfx = T[j].rho_x + T[j].ox + T[j].b1x*y1 + T[j].b2x*y2; - kfy = T[j].rho_y + T[j].oy + T[j].b1y*y1 + T[j].b2y*y2; - kfz = T[j].rho_z + T[j].oz + T[j].b1z*y1 + T[j].b2z*y2; + z1 = randnorm (); + z2 = randnorm (); + y1 = T[j].l11 * z1 + T[j].y0x; + y2 = T[j].l12 * z1 + T[j].l22 * z2 + T[j].y0y; + kfx = T[j].rho_x + T[j].ox + T[j].b1x * y1 + T[j].b2x * y2; + kfy = T[j].rho_y + T[j].oy + T[j].b1y * y1 + T[j].b2y * y2; + kfz = T[j].rho_z + T[j].oz + T[j].b1z * y1 + T[j].b2z * y2; /* Normalize kf to length of ki, to account for planer approximation of the Ewald sphere. */ - adjust = ki/sqrt(kfx*kfx + kfy*kfy + kfz*kfz); + adjust = ki / sqrt (kfx * kfx + kfy * kfy + kfz * kfz); kfx *= adjust; kfy *= adjust; kfz *= adjust; /* Adjust neutron weight (see manual for explanation). */ - *weight *= T[j].xsect*hkl_info->coh_refl/(hkl_info->coh_xsect*T[j].refl); - //printf("SCATTERING: hkl_info->coh_refl=%f, hkl_info->coh_xsect = %f, T[%d].refl = %f, hkl_info->tau.count = %d \n",hkl_info->coh_refl,hkl_info->coh_xsect,j,T[j].refl,hkl_info->tau_count); + *weight *= T[j].xsect * hkl_info->coh_refl / (hkl_info->coh_xsect * T[j].refl); + // printf("SCATTERING: hkl_info->coh_refl=%f, hkl_info->coh_xsect = %f, T[%d].refl = %f, hkl_info->tau.count = %d + // \n",hkl_info->coh_refl,hkl_info->coh_xsect,j,T[j].refl,hkl_info->tau_count); // These is the returned final wavevector - k_final[0] = L[i].u1x*kfx + L[i].u2x*kfy + L[i].u3x*kfz; - k_final[1] = L[i].u1y*kfx + L[i].u2y*kfy + L[i].u3y*kfz; - k_final[2] = L[i].u1z*kfx + L[i].u2z*kfy + L[i].u3z*kfz; - + k_final[0] = L[i].u1x * kfx + L[i].u2x * kfy + L[i].u3x * kfz; + k_final[1] = L[i].u1y * kfx + L[i].u2y * kfy + L[i].u3y * kfz; + k_final[2] = L[i].u1z * kfx + L[i].u2z * kfy + L[i].u3z * kfz; + if (data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->powder_setting) { // orientation of crystallite is no longer random - randderotate_union(&k_final[0], &k_final[1], &k_final[2], - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Beta, - data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Gamma); + randderotate_union (&k_final[0], &k_final[1], &k_final[2], data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Beta, + data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Gamma); } if (data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->PG_setting) { // orientation of crystallite is longer random - PGderotate_union(&k_final[0], &k_final[1], &k_final[2], data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, hkl_info->csx, hkl_info->csy, hkl_info->csz); + PGderotate_union (&k_final[0], &k_final[1], &k_final[2], data_transfer.pointer_to_a_Single_crystal_physics_storage_struct->Alpha, hkl_info->csx, + hkl_info->csy, hkl_info->csz); } hkl_info->type = 'c'; - hkl_info->h = L[i].h; - hkl_info->k = L[i].k; - hkl_info->l = L[i].l; + hkl_info->h = L[i].h; + hkl_info->k = L[i].k; + hkl_info->l = L[i].l; return 1; -}; + }; -#ifndef PROCESS_DETECTOR - #define PROCESS_DETECTOR dummy -#endif + #ifndef PROCESS_DETECTOR + #define PROCESS_DETECTOR dummy + #endif -#ifndef PROCESS_SINGLE_CRYSTAL_DETECTOR - #define PROCESS_SINGLE_CRYSTAL_DETECTOR dummy -#endif + #ifndef PROCESS_SINGLE_CRYSTAL_DETECTOR + #define PROCESS_SINGLE_CRYSTAL_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct Single_crystal_physics_storage_struct Single_crystal_storage; + // Declare for this component, to do calculations on the input / store in the transported data + struct Single_crystal_physics_storage_struct Single_crystal_storage; -// Variables needed in initialize of this function. -struct hkl_info_struct_union hkl_info_union; + // Variables needed in initialize of this function. + struct hkl_info_struct_union hkl_info_union; -// Needed for transport to the main component, will be the same for all processes -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Needed for transport to the main component, will be the same for all processes + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; %} INITIALIZE %{ // Single crystal initialize double as, bs, cs; - int i=0; + int i = 0; /* transfer input parameters */ hkl_info_union.m_delta_d_d = delta_d_d; - hkl_info_union.m_a = 0; - hkl_info_union.m_b = 0; - hkl_info_union.m_c = 0; + hkl_info_union.m_a = 0; + hkl_info_union.m_b = 0; + hkl_info_union.m_c = 0; hkl_info_union.m_aa = aa; hkl_info_union.m_bb = bb; hkl_info_union.m_cc = cc; @@ -1002,16 +1034,16 @@ INITIALIZE hkl_info_union.m_cx = cx; hkl_info_union.m_cy = cy; hkl_info_union.m_cz = cz; - //hkl_info_union.sigma_a = sigma_abs; - //hkl_info_union.sigma_i = sigma_inc; - hkl_info_union.recip = recip_cell; + // hkl_info_union.sigma_a = sigma_abs; + // hkl_info_union.sigma_i = sigma_inc; + hkl_info_union.recip = recip_cell; /* default format h,k,l,F,F2 */ - hkl_info_union.column_order[0]=1; - hkl_info_union.column_order[1]=2; - hkl_info_union.column_order[2]=3; - hkl_info_union.column_order[3]=0; - hkl_info_union.column_order[4]=7; + hkl_info_union.column_order[0] = 1; + hkl_info_union.column_order[1] = 2; + hkl_info_union.column_order[2] = 3; + hkl_info_union.column_order[3] = 0; + hkl_info_union.column_order[4] = 7; hkl_info_union.kix = hkl_info_union.kiy = hkl_info_union.kiz = 0; hkl_info_union.nb_reuses = hkl_info_union.nb_refl = hkl_info_union.nb_refl_count = 0; hkl_info_union.tau_count = 0; @@ -1019,72 +1051,82 @@ INITIALIZE /* ought to be cleaned up as mosaic_AB now is a proper vector/array and not a define */ double* mosaic_ABin = mosaic_AB; /* Read in structure factors, and do some pre-calculations. */ - if (!read_hkl_data_union(reflections, &hkl_info_union, mosaic, mosaic_a, mosaic_b, mosaic_c, mosaic_ABin)) { - printf("Single_crystal_process: %s: Error: Aborting.\n", NAME_CURRENT_COMP); - exit(0); + if (!read_hkl_data_union (reflections, &hkl_info_union, mosaic, mosaic_a, mosaic_b, mosaic_c, mosaic_ABin)) { + printf ("Single_crystal_process: %s: Error: Aborting.\n", NAME_CURRENT_COMP); + exit (0); } - - if (hkl_info_union.sigma_a<0) hkl_info_union.sigma_a=0; - if (hkl_info_union.sigma_i<0) hkl_info_union.sigma_i=0; - + + if (hkl_info_union.sigma_a < 0) + hkl_info_union.sigma_a = 0; + if (hkl_info_union.sigma_i < 0) + hkl_info_union.sigma_i = 0; + if (hkl_info_union.count) - printf("Single_crystal_process: %s: Read %d reflections from file '%s'\n", - NAME_CURRENT_COMP, hkl_info_union.count, reflections); - else printf("Single_crystal_process: %s: Using incoherent elastic scattering only sigma=%g.\n", - NAME_CURRENT_COMP, hkl_info_union.sigma_i); - + printf ("Single_crystal_process: %s: Read %d reflections from file '%s'\n", NAME_CURRENT_COMP, hkl_info_union.count, reflections); + else + printf ("Single_crystal_process: %s: Using incoherent elastic scattering only sigma=%g.\n", NAME_CURRENT_COMP, hkl_info_union.sigma_i); + /* hkl_info.shape=-1; // -1:no shape, 0:cyl, 1:box, 2:sphere, 3:any-shape if (geometry && strlen(geometry) && strcmp(geometry, "NULL") && strcmp(geometry, "0")) { - if (off_init(geometry, xwidth, yheight, zdepth, 0, &offdata)) { - hkl_info.shape=3; + if (off_init(geometry, xwidth, yheight, zdepth, 0, &offdata)) { + hkl_info.shape=3; } } else if (xwidth && yheight && zdepth) hkl_info.shape=1; // box else if (radius > 0 && yheight) hkl_info.shape=0; // cylinder else if (radius > 0 && !yheight) hkl_info.shape=2; // sphere - if (hkl_info.shape < 0) + if (hkl_info.shape < 0) exit(fprintf(stderr,"Single_crystal: %s: sample has invalid dimensions.\n" "ERROR Please check parameter values (xwidth, yheight, zdepth, radius).\n", NAME_CURRENT_COMP)); */ - - printf("Single_crystal: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn] reflections=%s\n", - NAME_CURRENT_COMP, hkl_info_union.V0, hkl_info_union.sigma_a, hkl_info_union.sigma_i, - reflections && strlen(reflections) ? reflections : "NULL"); - - if (powder && PG) - exit(fprintf(stderr,"Single_crystal_process: %s: powder and PG modes can not be used together!\n" - "ERROR Please use EITHER powder or PG mode.\n", NAME_CURRENT_COMP)); - - if (powder && !(order==1)) { - fprintf(stderr,"Single_crystal_process: %s: powder mode means implicit choice of no multiple scattering!\n" - "WARNING setting order=1\n", NAME_CURRENT_COMP); - order=1; - } - - if (PG && !(order==1)) { - fprintf(stderr,"Single_crystal_process: %s: PG mode means implicit choice of no multiple scattering!\n" - "WARNING setting order=1\n", NAME_CURRENT_COMP); - order=1; - } + + printf ("Single_crystal: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn] reflections=%s\n", NAME_CURRENT_COMP, hkl_info_union.V0, + hkl_info_union.sigma_a, hkl_info_union.sigma_i, reflections&& strlen (reflections) ? reflections : "NULL"); + + if (powder && PG) + exit (fprintf (stderr, + "Single_crystal_process: %s: powder and PG modes can not be used together!\n" + "ERROR Please use EITHER powder or PG mode.\n", + NAME_CURRENT_COMP)); + + if (powder && !(order == 1)) { + fprintf (stderr, + "Single_crystal_process: %s: powder mode means implicit choice of no multiple scattering!\n" + "WARNING setting order=1\n", + NAME_CURRENT_COMP); + order = 1; + } + + if (PG && !(order == 1)) { + fprintf (stderr, + "Single_crystal_process: %s: PG mode means implicit choice of no multiple scattering!\n" + "WARNING setting order=1\n", + NAME_CURRENT_COMP); + order = 1; + } // Temporary errors untill these features are either added or removed from input - if (powder) - exit(fprintf(stderr,"Single_crystal_process: %s: powder mode not supported yet!\n" - "ERROR Please disable powder mode.\n", NAME_CURRENT_COMP)); - + exit (fprintf (stderr, + "Single_crystal_process: %s: powder mode not supported yet!\n" + "ERROR Please disable powder mode.\n", + NAME_CURRENT_COMP)); if (PG) - exit(fprintf(stderr,"Single_crystal_process: %s: PG mode not supported yet!\n" - "ERROR Please disable PG mode.\n", NAME_CURRENT_COMP)); - + exit (fprintf (stderr, + "Single_crystal_process: %s: PG mode not supported yet!\n" + "ERROR Please disable PG mode.\n", + NAME_CURRENT_COMP)); + if (order) - exit(fprintf(stderr,"Single_crystal_process: %s: Order control not supported yet!\n" - "ERROR Please set order to zero.\n", NAME_CURRENT_COMP)); - + exit (fprintf (stderr, + "Single_crystal_process: %s: Order control not supported yet!\n" + "ERROR Please set order to zero.\n", + NAME_CURRENT_COMP)); + // Initialize done in the component // Added for single crystal Single_crystal_storage.PG_setting = PG; @@ -1093,16 +1135,16 @@ INITIALIZE Single_crystal_storage.pack = packing_factor; Single_crystal_storage.hkl_info_storage = &hkl_info_union; - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic - //This_process.non_isotropic_rot_index = -1; // Yes (powder) - This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = -1; // Yes (powder) + This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No // The type of the process must be saved in the global enum process This_process.eProcess = Single_crystal; @@ -1114,27 +1156,24 @@ INITIALIZE // This will be the same for all process's, and can thus be moved to an include. This_process.process_p_interact = interact_fraction; - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Single_crystal_process:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} - + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Single_crystal_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list, global_process_element); - + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE %{ - // Trace should be empty, the simulation is done in Union_master + // Trace should be empty, the simulation is done in Union_master %} END diff --git a/mcstas-comps/union/Template_process.comp b/mcstas-comps/union/Template_process.comp index 1fff77ce65..0c2e6a4104 100755 --- a/mcstas-comps/union/Template_process.comp +++ b/mcstas-comps/union/Template_process.comp @@ -60,100 +60,104 @@ SETTING PARAMETERS(sigma=5.08,packing_factor=1,unit_cell_volume=13.8,interact_fr SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Template_process component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Template_process component" + #endif -// Very important to add a pointer to this struct in the union-lib.c file -struct Template_physics_storage_struct{ + // Very important to add a pointer to this struct in the union-lib.c file + struct Template_physics_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + // Avoid duplicates of output parameters and setting parameters in naming double my_scattering; -}; + }; -// Function for calculating my, the inverse penetration depth (for only this scattering process). -// The input for this function and its order may not be changed, but the names may be updated. -int Template_physics_my(double *my, double *k_initial, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function for calculating my, the inverse penetration depth (for only this scattering process). + // The input for this function and its order may not be changed, but the names may be updated. + int + Template_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, _class_particle* _particle) { // *k_initial is a pointer to a simple vector with 3 doubles, k[0], k[1], k[2] which describes the wavevector // Simple case, just retrive the parameter saved from initialize *my = data_transfer.pointer_to_a_Template_physics_storage_struct->my_scattering; return 1; -}; + }; -// Function that provides description of a basic scattering event. -// Do not change the -int Template_physics_scattering(double *k_final, double *k_initial, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { + // Function that provides description of a basic scattering event. + // Do not change the + int + Template_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { // k_final and k_initial are passed as pointers to double vector[3] - double k_length = sqrt(k_initial[0]*k_initial[0]+k_initial[1]*k_initial[1]+k_initial[2]*k_initial[2]); + double k_length = sqrt (k_initial[0] * k_initial[0] + k_initial[1] * k_initial[1] + k_initial[2] * k_initial[2]); Coords k_out; // Here is the focusing system in action, get a vector double solid_angle; - focus_data->focusing_function(&k_out,&solid_angle,focus_data); - NORM(k_out.x,k_out.y,k_out.z); - *weight *= solid_angle*0.25/PI; + focus_data->focusing_function (&k_out, &solid_angle, focus_data); + NORM (k_out.x, k_out.y, k_out.z); + *weight *= solid_angle * 0.25 / PI; - k_final[0] = k_out.x*k_length; k_final[1] = k_out.y*k_length; k_final[2] = k_out.z*k_length; + k_final[0] = k_out.x * k_length; + k_final[1] = k_out.y * k_length; + k_final[2] = k_out.z * k_length; // A pointer to k_final is returned, and the wavevector will be set to k_final after a scattering event return 1; // return 1 is sucess, return 0 is failure, and the ray will be absorbed. // failure should not happen, as this function will only be called when // the cross section for the current k_initial is above zero. - + // There is access to the data_transfer from within the scattering function // In this case the only variable is my, but it could be read by: // double my = data_transfer.pointer_to_a_Template_physics_storage_struct->my_scattering; // One can assume that if the scattering function is running, the my fuction was // executed just before and for the same k_initial. - -}; - -// These lines help with future error correction, and tell other Union components -// that at least one process have been defined. -#ifndef PROCESS_DETECTOR - #define PROCESS_DETECTOR dummy -#endif - -#ifndef PROCESS_TEMPLATE_DETECTOR - #define PROCESS_TEMPLATE_DETECTOR dummy -#endif + }; + + // These lines help with future error correction, and tell other Union components + // that at least one process have been defined. + #ifndef PROCESS_DETECTOR + #define PROCESS_DETECTOR dummy + #endif + + #ifndef PROCESS_TEMPLATE_DETECTOR + #define PROCESS_TEMPLATE_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct Template_physics_storage_struct Template_storage; // Replace template with your own name here + // Declare for this component, to do calculations on the input / store in the transported data + struct Template_physics_storage_struct Template_storage; // Replace template with your own name here -// Variables needed in initialize of this function. -double effective_my_scattering; + // Variables needed in initialize of this function. + double effective_my_scattering; -// Needed for transport to the main component, will be the same for all processes -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Needed for transport to the main component, will be the same for all processes + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; %} INITIALIZE %{ // Initialize done in the component - effective_my_scattering = ((packing_factor/unit_cell_volume) * 100 * sigma); + effective_my_scattering = ((packing_factor / unit_cell_volume) * 100 * sigma); Template_storage.my_scattering = effective_my_scattering; - - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic This_process.non_isotropic_rot_index = -1; // Yes (powder) - //This_process.non_isotropic_rot_index = 1; // No (single crystal) - + // This_process.non_isotropic_rot_index = 1; // No (single crystal) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No - + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No + // The type of the process must be saved in the global enum process This_process.eProcess = Template; @@ -163,26 +167,25 @@ INITIALIZE This_process.scattering_function = &Template_physics_scattering; // This will be the same for all process's, and can thus be moved to an include. - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); This_process.process_p_interact = interact_fraction; - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Template_process:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Template_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list,global_process_element); + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE %{ - // Trace should be empty, the simulation is done in Union_master + // Trace should be empty, the simulation is done in Union_master %} END diff --git a/mcstas-comps/union/Template_surface.comp b/mcstas-comps/union/Template_surface.comp index a6da1f19cb..0e01f0373c 100755 --- a/mcstas-comps/union/Template_surface.comp +++ b/mcstas-comps/union/Template_surface.comp @@ -62,119 +62,122 @@ SETTING PARAMETERS(string reflect=0, R0=0.99, Qc=0.0219, alpha=6.07, m=2, W=0.00 SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Template_surface component" -#endif - - -%include "read_table-lib" -%include "ref-lib" - -// Very important to add a pointer to this struct in the union-lib.c file -struct Template_surface_storage_struct{ + #ifndef Union + #error "The Union_init component must be included before this Template_surface component" + #endif + + %include "read_table-lib" + %include "ref-lib" + + // Very important to add a pointer to this struct in the union-lib.c file + struct Template_surface_storage_struct { // Variables that needs to be transfered between any of the following places: // The initialize in this component // The function for calculating my // The function for calculating scattering - + // Avoid duplicates of setting parameters in naming - double par[5]; - t_Table pTable; - int table_present; -}; - -// Function for handling surface physics -// The input for this function and its order may not be changed, but the names may be updated. -int Template_surface_function(union surface_data_transfer_union data_transfer, // data in struct defined above, can have data stored in initialize and other calls to this function - double *weight, double *wavevector, int *continues, // given weight and wavevector, to be updated, and pointer to continues which should be provided by function - double *normal_vector, enum in_or_out inward_or_outward, // normal_vector of surface and information on whether the neutron is going into or out of this surface - _class_particle *_particle) { + double par[5]; + t_Table pTable; + int table_present; + }; + + // Function for handling surface physics + // The input for this function and its order may not be changed, but the names may be updated. + int + Template_surface_function ( + union surface_data_transfer_union data_transfer, // data in struct defined above, can have data stored in initialize and other calls to this function + double* weight, double* wavevector, + int* continues, // given weight and wavevector, to be updated, and pointer to continues which should be provided by function + double* normal_vector, + enum in_or_out inward_or_outward, // normal_vector of surface and information on whether the neutron is going into or out of this surface + _class_particle* _particle) { // wavevector and normal_vector are a pointers to a simple array with 3 doubles, wavevector[0], wavevector[1], wavevector[2] which describes the vector - // Retrieve data storage struct - struct Template_surface_storage_struct *storage; - storage = data_transfer.pointer_to_a_Template_surface_storage_struct; - - double k_n_dot = wavevector[0]*normal_vector[0] + wavevector[1]*normal_vector[1] + wavevector[2]*normal_vector[2]; - - // Calculate q normal - double q_normal = 2.0*fabs(k_n_dot); - - // Calculate or read reflectivity - double reflectivity; - if (storage->table_present == 1) { - TableReflecFunc(q_normal, &storage->pTable, &reflectivity); - } else { - StdReflecFunc(q_normal, storage->par, &reflectivity); - } - - // Take monte carlo choice on whether to be reflected by the mirror or not - if (rand01() > reflectivity) { - *continues = 1; // Tells algorithm the ray goes through this surface - } else { - // mirror ray - wavevector[0] = wavevector[0] - 2.0 * k_n_dot * normal_vector[0]; - wavevector[1] = wavevector[1] - 2.0 * k_n_dot * normal_vector[1]; - wavevector[2] = wavevector[2] - 2.0 * k_n_dot * normal_vector[2]; - - *continues = 0; // Tells algorithm the ray does not go through this surface - } + // Retrieve data storage struct + struct Template_surface_storage_struct* storage; + storage = data_transfer.pointer_to_a_Template_surface_storage_struct; + + double k_n_dot = wavevector[0] * normal_vector[0] + wavevector[1] * normal_vector[1] + wavevector[2] * normal_vector[2]; + + // Calculate q normal + double q_normal = 2.0 * fabs (k_n_dot); + + // Calculate or read reflectivity + double reflectivity; + if (storage->table_present == 1) { + TableReflecFunc (q_normal, &storage->pTable, &reflectivity); + } else { + StdReflecFunc (q_normal, storage->par, &reflectivity); + } + + // Take monte carlo choice on whether to be reflected by the mirror or not + if (rand01 () > reflectivity) { + *continues = 1; // Tells algorithm the ray goes through this surface + } else { + // mirror ray + wavevector[0] = wavevector[0] - 2.0 * k_n_dot * normal_vector[0]; + wavevector[1] = wavevector[1] - 2.0 * k_n_dot * normal_vector[1]; + wavevector[2] = wavevector[2] - 2.0 * k_n_dot * normal_vector[2]; + + *continues = 0; // Tells algorithm the ray does not go through this surface + } return 1; - + // There is access to the data_transfer from within this function: // int table_present = data_transfer.pointer_to_a_Template_physics_storage_struct->table_present; - // Its even possible to write to this data structure and use results for a later ray if relevant -}; - -// These lines help with future error correction, and tell other Union components -// that at least one surface have been defined. -#ifndef SURFACE_DETECTOR - #define SURFACE_DETECTOR dummy -#endif -#ifndef SURFACE_PROCESS_TEMPLATE_DETECTOR - #define SURFACE_PROCESS_TEMPLATE_DETECTOR dummy -#endif + // Its even possible to write to this data structure and use results for a later ray if relevant + }; + + // These lines help with future error correction, and tell other Union components + // that at least one surface have been defined. + #ifndef SURFACE_DETECTOR + #define SURFACE_DETECTOR dummy + #endif + #ifndef SURFACE_PROCESS_TEMPLATE_DETECTOR + #define SURFACE_PROCESS_TEMPLATE_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct Template_surface_storage_struct Template_storage; // Replace template with your own name here + // Declare for this component, to do calculations on the input / store in the transported data + struct Template_surface_storage_struct Template_storage; // Replace template with your own name here -// Needed for transport to the main component, will be the same for all surface processes -struct global_surface_element_struct global_surface_element; -struct surface_process_struct This_surface; + // Needed for transport to the main component, will be the same for all surface processes + struct global_surface_element_struct global_surface_element; + struct surface_process_struct This_surface; %} INITIALIZE %{ // Initialize done in the component - if (reflect && strlen(reflect) && strcmp(reflect,"NULL") && strcmp(reflect,"0")) { - if (Table_Read(&Template_storage.pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */ - exit(fprintf(stderr,"Template_surface: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect)); - Template_storage.table_present=1; + if (reflect && strlen (reflect) && strcmp (reflect, "NULL") && strcmp (reflect, "0")) { + if (Table_Read (&Template_storage.pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */ + exit (fprintf (stderr, "Template_surface: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect)); + Template_storage.table_present = 1; } else { - Template_storage.table_present=0; - if (W < 0 || R0 < 0 || Qc < 0 || m < 0) { - fprintf(stderr,"Template_surface: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP); - exit(-1); - } + Template_storage.table_present = 0; + if (W < 0 || R0 < 0 || Qc < 0 || m < 0) { + fprintf (stderr, "Template_surface: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP); + exit (-1); + } } - + // Insert input parameter to par array as required for the standard reflectivity function Template_storage.par[0] = R0; Template_storage.par[1] = Qc; Template_storage.par[2] = alpha; Template_storage.par[3] = m; - Template_storage.par[4] = W; + Template_storage.par[4] = W; // Will need to do similar system for surfaces // Need to specify if this process is isotropic - //This_process.non_isotropic_rot_index = -1; // Yes (powder) - //This_process.non_isotropic_rot_index = 1; // No (single crystal) - //rot_copy(This_surface.rotation_matrix, ROT_A_CURRENT_COMP); + // This_process.non_isotropic_rot_index = -1; // Yes (powder) + // This_process.non_isotropic_rot_index = 1; // No (single crystal) + // rot_copy(This_surface.rotation_matrix, ROT_A_CURRENT_COMP); // The type of the process must be saved in the global enum process located in union-lib.c This_surface.eSurface = SurfaceTemplate; @@ -183,24 +186,23 @@ INITIALIZE This_surface.data_transfer.pointer_to_a_Template_surface_storage_struct = &Template_storage; // This will be the same for all process's, and can thus be moved to an include. - sprintf(This_surface.name,"%s",NAME_CURRENT_COMP); - sprintf(global_surface_element.name,"%s",NAME_CURRENT_COMP); + sprintf (This_surface.name, "%s", NAME_CURRENT_COMP); + sprintf (global_surface_element.name, "%s", NAME_CURRENT_COMP); global_surface_element.component_index = INDEX_CURRENT_COMP; global_surface_element.p_surface_process = &This_surface; - if (_getcomp_index(init) < 0) { - fprintf(stderr,"Template_surface:%s: Error identifying Union_init component, %s is not a known component name.\n", - NAME_CURRENT_COMP, init); - exit(-1); + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Template_surface:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); } - struct pointer_to_global_surface_list *global_surface_list = COMP_GETPAR3(Union_init, init, global_surface_list); - add_element_to_surface_list(global_surface_list, global_surface_element); + struct pointer_to_global_surface_list* global_surface_list = COMP_GETPAR3 (Union_init, init, global_surface_list); + add_element_to_surface_list (global_surface_list, global_surface_element); %} TRACE %{ - // Trace should be empty, the simulation is perfomed in Union_master + // Trace should be empty, the simulation is perfomed in Union_master %} END diff --git a/mcstas-comps/union/Texture_process.comp b/mcstas-comps/union/Texture_process.comp index 989c69acaa..913269059e 100644 --- a/mcstas-comps/union/Texture_process.comp +++ b/mcstas-comps/union/Texture_process.comp @@ -59,2192 +59,2285 @@ SETTING PARAMETERS(string crystal_fn=0, string fcoef_fn=0, int lmax_user=-1, SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Texture_process component" -#endif - -%include "read_table-lib" -%include "interoff-lib" - -#ifndef TEXTURE_PROCESS_DECL -#define TEXTURE_PROCESS_DECL - -#define nSamplingPoints 120 -#define maxIterReject 3000 -#define tolTexture 1.0e-6 - -double kx_first, ky_first, kz_first; - -struct saveCohMu -{ - double kix, kiy, kiz, cohMu, *XS; - int num_hkl_scatt; -}; - -struct save_hklScattProb -{ - double kix, kiy, kiz; - // Number of reflections hkl taken into account (below cut-off) - int num_hkl_scatt; - //cummulative probablity of scattering by i-th hkl plane - double *cumProb_hkl; -}; - -struct saveScattProb -{ - double kix, kiy, kiz; - double kihx, kihy, kihz; - double t1x, t1y, t1z; - double t2x, t2y, t2z; - double kim, stheta, ctheta; - double dphi; - double maxProb; - double aa[nSamplingPoints], bb[nSamplingPoints]; -}; - -struct fourier_coef -{ - int lmax; - double ***cr, ***ci; -}; - -struct legendre -{ - int lmax; - int **index; - int *l; - int *m; - int *nplm; - double **x; - double **Plm; -}; - -struct hkl_data_texture -{ - int h, k, l; // Indices for this reflection - int mult; // Multiplicity of the line - double F2; // Value of square of structure factor - double Gx, Gy, Gz; // Coordinates in reciprocal space - double uGx, uGy, uGz; // Unit vector in the direction of G - double G, Gct, Gphi; // polar coordinates of G [Gct=cos(theta)] - // to interpolate the total cross section - int lmax; - int *nctk_l, *nphik_l; - double **ctk_l, **phik_l, ***Upsilon_l; - //To obtain cross sections - int numV; - int *lv, *mv; - double *RV, *phiV; - // to sample kprime - // precomputed Q distribution - int nctq, nphiq; - double *ctq, *phiq, **probQ; - // rejection statistics - double numReject, numScatt; - //computed cross sections - double currXS; - //saved scattering parameters - int maxSaved, lastSaved; - struct saveScattProb *savedNeutrons; -}; - -struct hkl_info_struct_texture -{ - // data structures - int num_hkl; // Number of reflections hkl taken into account - int num_hkl_scatt; // Number of possible reflections hkl (below Bragg cutoff) - struct hkl_data_texture *list; // Reflection array - struct legendre *lgdr; // structure with precomputed spherical harmonics - int lmax; // cut-off for the Fourier expansion - - // crystal and physical info - double m_delta_d_d; // Delta-d/d FWHM (not used) - double m_ax,m_ay,m_az; // First unit cell axis (direct space, AA) - double m_bx,m_by,m_bz; // Second unit cell axis - double m_cx,m_cy,m_cz; // Third unit cell axis - double asx,asy,asz; // First reciprocal lattice axis (1/AA) - double bsx,bsy,bsz; // Second reciprocal lattice axis - double csx,csy,csz; // Third reciprocal lattice axis - double m_a, m_b, m_c; // length of lattice parameter lengths - double m_aa, m_bb, m_cc; // lattice angles - double sigma_a, sigma_i; // abs and inc X sect - double at_weight; // atomic weight - double at_nb; // nb of atoms in a cell - double V0; // Unit cell volume (AA**3) - - // precomputed factors - double xs2mu; // cross section to mu (in m^-1) - - // auxiliar info - int column_order[6]; // column signification [h,k,l,F,F2,j] - int recip; // Flag to indicate if recip or direct cell axes given - int flag_warning; // number of warnings - char type; // type of last event: t=transmit,c=coherent or i=incoherent - double numReused; // for reusing statistics - - int new; // 1 if this is a new neutron, 0 if this is a scattered neutron - - // saved info - int h, k, l; // last coherent scattering momentum transfer indices - double cohMu; // last linear attenuation coefficient computed - - // saved for reusing neutrons - int maxSaved, lastCohMuSaved, lastScattSaved; - struct saveCohMu *cohMuSaved; - struct save_hklScattProb *hkl_ScattProbSaved; -}; - -// function declarations - -// legendre -double plgndr(int l, int m, double x); -double plgndr_mod(int l, int m, double x); -struct legendre * initLegendre(int lmax); -// intialization -int initData(char *coef_fn, char *crystal_fn, struct hkl_info_struct_texture *info, int maxSaved); -// cross sections -double total_hkl_XS(double k, double kct, double kphi, struct hkl_data_texture *L, - struct legendre *lgdr); -double total_hkl_XS_interp(double k, double kct, double kphi, - struct hkl_data_texture *L, struct legendre *lgdr); -double computeUpsilon_l(double kct, double kphi, int l, - struct hkl_data_texture *L, struct legendre *lgdr); -int precomputeUpsilon_l(struct hkl_data_texture *L, struct legendre *lgdr); -int computeV(struct fourier_coef *fc, struct legendre *lgdr, struct hkl_data_texture *L); -// sampling -int sampleKprime_hkl(double *kf, double *ki, struct hkl_data_texture *L, struct legendre *lgdr); -double probPhiq(double ctq, double phiq, struct hkl_data_texture *L, struct legendre *lgdr); -double probPhiqImag(double ctq, double phiq, struct hkl_data_texture *L, struct legendre *lgdr); -int precomputeProbPhiq(struct hkl_data_texture *L, struct legendre *lgdr); -// Input - Output -int read_hkl_data_texture(char *SC_file, struct hkl_info_struct_texture *info); -void readFourierCoef(char *filename, struct fourier_coef *c); -void allocateFourierCoef(int lmax, struct fourier_coef *c); -void freeFourierCoef(struct fourier_coef *c); -// Tests -void computePoleFigure(int h, int k, int l, struct fourier_coef *c, - struct hkl_info_struct_texture *data); -void poleFigure(double ctG, double phiG, double ctD, double phiD, - struct fourier_coef *c, struct legendre *lgdr, double *pfr, double *pfi); -// auxiliary -int SX_list_compare_texture (void const *a, void const *b); -double interp(double x, int n, double *xp, double *yp); -double interp2D(double x, double y, int nx, int ny, double *xp, double *yp, double **fp); -// free texture memory -int free_texture(struct hkl_info_struct_texture *hkl_info); -int free_hkl_data_texture(struct hkl_data_texture *list); -int free_legendre(struct legendre *lgdr); - -// end function declarations - -///////////////////// -/// legendre //// -///////////////////// - -double plgndr(int l, int m, double x) -{ - double fact, pll, pmm, pmmp1, somx2; - int i, ll; - - if (m < 0 || m > l || fabs(x) > 1.0) { - printf("Bad arguments in routine plgndr\n"); - printf("m: %d l: %d x: %f\n",m,l,x); - printf("Exiting...\n"); - exit(-1); - } - //Compute Pmm - pmm=1.0; - if (m > 0) { - somx2 = sqrt((1.0-x)*(1.0+x)); - fact = 1.0; - for (i=1;i<=m;i++) { - pmm *= -fact*somx2; - fact += 2.0; + #ifndef Union + #error "The Union_init component must be included before this Texture_process component" + #endif + + %include "read_table-lib" + %include "interoff-lib" + + #ifndef TEXTURE_PROCESS_DECL + #define TEXTURE_PROCESS_DECL + + #define nSamplingPoints 120 + #define maxIterReject 3000 + #define tolTexture 1.0e-6 + + double kx_first, ky_first, kz_first; + + struct saveCohMu { + double kix, kiy, kiz, cohMu, *XS; + int num_hkl_scatt; + }; + + struct save_hklScattProb { + double kix, kiy, kiz; + // Number of reflections hkl taken into account (below cut-off) + int num_hkl_scatt; + // cummulative probablity of scattering by i-th hkl plane + double* cumProb_hkl; + }; + + struct saveScattProb { + double kix, kiy, kiz; + double kihx, kihy, kihz; + double t1x, t1y, t1z; + double t2x, t2y, t2z; + double kim, stheta, ctheta; + double dphi; + double maxProb; + double aa[nSamplingPoints], bb[nSamplingPoints]; + }; + + struct fourier_coef { + int lmax; + double ***cr, ***ci; + }; + + struct legendre { + int lmax; + int** index; + int* l; + int* m; + int* nplm; + double** x; + double** Plm; + }; + + struct hkl_data_texture { + int h, k, l; // Indices for this reflection + int mult; // Multiplicity of the line + double F2; // Value of square of structure factor + double Gx, Gy, Gz; // Coordinates in reciprocal space + double uGx, uGy, uGz; // Unit vector in the direction of G + double G, Gct, Gphi; // polar coordinates of G [Gct=cos(theta)] + // to interpolate the total cross section + int lmax; + int *nctk_l, *nphik_l; + double **ctk_l, **phik_l, ***Upsilon_l; + // To obtain cross sections + int numV; + int *lv, *mv; + double *RV, *phiV; + // to sample kprime + // precomputed Q distribution + int nctq, nphiq; + double *ctq, *phiq, **probQ; + // rejection statistics + double numReject, numScatt; + // computed cross sections + double currXS; + // saved scattering parameters + int maxSaved, lastSaved; + struct saveScattProb* savedNeutrons; + }; + + struct hkl_info_struct_texture { + // data structures + int num_hkl; // Number of reflections hkl taken into account + int num_hkl_scatt; // Number of possible reflections hkl (below Bragg cutoff) + struct hkl_data_texture* list; // Reflection array + struct legendre* lgdr; // structure with precomputed spherical harmonics + int lmax; // cut-off for the Fourier expansion + + // crystal and physical info + double m_delta_d_d; // Delta-d/d FWHM (not used) + double m_ax, m_ay, m_az; // First unit cell axis (direct space, AA) + double m_bx, m_by, m_bz; // Second unit cell axis + double m_cx, m_cy, m_cz; // Third unit cell axis + double asx, asy, asz; // First reciprocal lattice axis (1/AA) + double bsx, bsy, bsz; // Second reciprocal lattice axis + double csx, csy, csz; // Third reciprocal lattice axis + double m_a, m_b, m_c; // length of lattice parameter lengths + double m_aa, m_bb, m_cc; // lattice angles + double sigma_a, sigma_i; // abs and inc X sect + double at_weight; // atomic weight + double at_nb; // nb of atoms in a cell + double V0; // Unit cell volume (AA**3) + + // precomputed factors + double xs2mu; // cross section to mu (in m^-1) + + // auxiliar info + int column_order[6]; // column signification [h,k,l,F,F2,j] + int recip; // Flag to indicate if recip or direct cell axes given + int flag_warning; // number of warnings + char type; // type of last event: t=transmit,c=coherent or i=incoherent + double numReused; // for reusing statistics + + int new; // 1 if this is a new neutron, 0 if this is a scattered neutron + + // saved info + int h, k, l; // last coherent scattering momentum transfer indices + double cohMu; // last linear attenuation coefficient computed + + // saved for reusing neutrons + int maxSaved, lastCohMuSaved, lastScattSaved; + struct saveCohMu* cohMuSaved; + struct save_hklScattProb* hkl_ScattProbSaved; + }; + + // function declarations + + // legendre + double plgndr (int l, int m, double x); + double plgndr_mod (int l, int m, double x); + struct legendre* initLegendre (int lmax); + // intialization + int initData (char* coef_fn, char* crystal_fn, struct hkl_info_struct_texture* info, int maxSaved); + // cross sections + double total_hkl_XS (double k, double kct, double kphi, struct hkl_data_texture* L, struct legendre* lgdr); + double total_hkl_XS_interp (double k, double kct, double kphi, struct hkl_data_texture* L, struct legendre* lgdr); + double computeUpsilon_l (double kct, double kphi, int l, struct hkl_data_texture* L, struct legendre* lgdr); + int precomputeUpsilon_l (struct hkl_data_texture* L, struct legendre* lgdr); + int computeV (struct fourier_coef* fc, struct legendre* lgdr, struct hkl_data_texture* L); + // sampling + int sampleKprime_hkl (double* kf, double* ki, struct hkl_data_texture* L, struct legendre* lgdr); + double probPhiq (double ctq, double phiq, struct hkl_data_texture* L, struct legendre* lgdr); + double probPhiqImag (double ctq, double phiq, struct hkl_data_texture* L, struct legendre* lgdr); + int precomputeProbPhiq (struct hkl_data_texture* L, struct legendre* lgdr); + // Input - Output + int read_hkl_data_texture (char* SC_file, struct hkl_info_struct_texture* info); + void readFourierCoef (char* filename, struct fourier_coef* c); + void allocateFourierCoef (int lmax, struct fourier_coef* c); + void freeFourierCoef (struct fourier_coef* c); + // Tests + void computePoleFigure (int h, int k, int l, struct fourier_coef* c, struct hkl_info_struct_texture* data); + void poleFigure (double ctG, double phiG, double ctD, double phiD, struct fourier_coef* c, struct legendre* lgdr, double* pfr, double* pfi); + // auxiliary + int SX_list_compare_texture (void const* a, void const* b); + double interp (double x, int n, double* xp, double* yp); + double interp2D (double x, double y, int nx, int ny, double* xp, double* yp, double** fp); + // free texture memory + int free_texture (struct hkl_info_struct_texture* hkl_info); + int free_hkl_data_texture (struct hkl_data_texture* list); + int free_legendre (struct legendre* lgdr); + + // end function declarations + + ///////////////////// + /// legendre //// + ///////////////////// + + double + plgndr (int l, int m, double x) { + double fact, pll, pmm, pmmp1, somx2; + int i, ll; + + if (m < 0 || m > l || fabs (x) > 1.0) { + printf ("Bad arguments in routine plgndr\n"); + printf ("m: %d l: %d x: %f\n", m, l, x); + printf ("Exiting...\n"); + exit (-1); } - } - if (l == m) { - return pmm; - } else { - //Compute Pmm+1 - pmmp1 = x*(2*m+1)*pmm; - if (l == (m+1)) - return pmmp1; - else { - //Compute Plm, l > m + 1. - for (ll=m+2;ll<=l;ll++) { - pll = (x*(2*ll-1)*pmmp1-(ll+m-1)*pmm)/(ll-m); - pmm = pmmp1; - pmmp1 = pll; - } - return pll; + // Compute Pmm + pmm = 1.0; + if (m > 0) { + somx2 = sqrt ((1.0 - x) * (1.0 + x)); + fact = 1.0; + for (i = 1; i <= m; i++) { + pmm *= -fact * somx2; + fact += 2.0; + } + } + if (l == m) { + return pmm; + } else { + // Compute Pmm+1 + pmmp1 = x * (2 * m + 1) * pmm; + if (l == (m + 1)) + return pmmp1; + else { + // Compute Plm, l > m + 1. + for (ll = m + 2; ll <= l; ll++) { + pll = (x * (2 * ll - 1) * pmmp1 - (ll + m - 1) * pmm) / (ll - m); + pmm = pmmp1; + pmmp1 = pll; + } + return pll; + } } - } -} - -// legendre associated functions normalized for computations (see notes) -double plgndr_mod(int l, int m, double x) -{ - int k; - int ma = abs(m); - double plm, norm = 1.0; - for(k=l+ma;k>l-ma;k--) { norm /= k; } - plm = sqrt(norm)*plgndr(l,ma,x); - if(m<0 && ma%2) { plm = -plm; } - return plm; -} - -struct legendre * initLegendre(int lmax) -{ - int i, j, k, l, m, ma, nlm; - double x, dx, plm, norm; - struct legendre *lgdr; - FILE *filep; - - if(lmax<0) { - printf("initLegendre: negative lmax = %d\n",lmax); - printf("Exiting...\n"); - fflush(stdout); - exit(-1); } - nlm = (lmax+1)*(lmax+1); - - lgdr = (struct legendre *)malloc(sizeof(struct legendre)); - if (!lgdr) { - fprintf(stderr,"Texture_process: Failed struct malloc() in initLegendre. Exit!\n"); - exit(-1); - } - lgdr->lmax = lmax; - lgdr->index = (int **)malloc((lmax+1)*sizeof(int *)); - lgdr->l = (int *)malloc(nlm*sizeof(int)); - lgdr->m = (int *)malloc(nlm*sizeof(int)); - lgdr->nplm = (int *)malloc(nlm*sizeof(int)); - lgdr->x = (double **)malloc(nlm*sizeof(double *)); - lgdr->Plm = (double **)malloc(nlm*sizeof(double *)); - if (!lgdr->index || !lgdr->l || !lgdr->m || !lgdr->nplm || !lgdr->x || !lgdr->Plm) { - fprintf(stderr,"Texture_process: Failed malloc() in initLegendre. Exit!\n"); - exit(-1); + // legendre associated functions normalized for computations (see notes) + double + plgndr_mod (int l, int m, double x) { + int k; + int ma = abs (m); + double plm, norm = 1.0; + for (k = l + ma; k > l - ma; k--) { + norm /= k; + } + plm = sqrt (norm) * plgndr (l, ma, x); + if (m < 0 && ma % 2) { + plm = -plm; + } + return plm; } - i = -1; - for(l=0;l<=lmax;l++) { - lgdr->index[l] = (int *)malloc((2*l+1)*sizeof(int)); - for(m=-l;m<=l;m++) { - i++; - (lgdr->index)[l][l+m] = i; - (lgdr->l)[i] = l; - (lgdr->m)[i] = m; - (lgdr->nplm)[i] = 100*(l+1); - (lgdr->x)[i] = (double *)malloc(((lgdr->nplm)[i])*sizeof(double)); - (lgdr->Plm)[i] = (double *)malloc(((lgdr->nplm)[i])*sizeof(double)); - dx = 2.0/((lgdr->nplm)[i]-1); - for(j=0;j<(lgdr->nplm)[i]-1;j++) { - x = -1.0 + j*dx; + + struct legendre* + initLegendre (int lmax) { + int i, j, k, l, m, ma, nlm; + double x, dx, plm, norm; + struct legendre* lgdr; + FILE* filep; + + if (lmax < 0) { + printf ("initLegendre: negative lmax = %d\n", lmax); + printf ("Exiting...\n"); + fflush (stdout); + exit (-1); + } + + nlm = (lmax + 1) * (lmax + 1); + + lgdr = (struct legendre*)malloc (sizeof (struct legendre)); + if (!lgdr) { + fprintf (stderr, "Texture_process: Failed struct malloc() in initLegendre. Exit!\n"); + exit (-1); + } + lgdr->lmax = lmax; + lgdr->index = (int**)malloc ((lmax + 1) * sizeof (int*)); + lgdr->l = (int*)malloc (nlm * sizeof (int)); + lgdr->m = (int*)malloc (nlm * sizeof (int)); + lgdr->nplm = (int*)malloc (nlm * sizeof (int)); + lgdr->x = (double**)malloc (nlm * sizeof (double*)); + lgdr->Plm = (double**)malloc (nlm * sizeof (double*)); + if (!lgdr->index || !lgdr->l || !lgdr->m || !lgdr->nplm || !lgdr->x || !lgdr->Plm) { + fprintf (stderr, "Texture_process: Failed malloc() in initLegendre. Exit!\n"); + exit (-1); + } + i = -1; + for (l = 0; l <= lmax; l++) { + lgdr->index[l] = (int*)malloc ((2 * l + 1) * sizeof (int)); + for (m = -l; m <= l; m++) { + i++; + (lgdr->index)[l][l + m] = i; + (lgdr->l)[i] = l; + (lgdr->m)[i] = m; + (lgdr->nplm)[i] = 100 * (l + 1); + (lgdr->x)[i] = (double*)malloc (((lgdr->nplm)[i]) * sizeof (double)); + (lgdr->Plm)[i] = (double*)malloc (((lgdr->nplm)[i]) * sizeof (double)); + dx = 2.0 / ((lgdr->nplm)[i] - 1); + for (j = 0; j < (lgdr->nplm)[i] - 1; j++) { + x = -1.0 + j * dx; + (lgdr->x)[i][j] = x; + (lgdr->Plm)[i][j] = plgndr_mod (l, m, x); + } + j = (lgdr->nplm)[i] - 1; + x = 1.0; (lgdr->x)[i][j] = x; - (lgdr->Plm)[i][j] = plgndr_mod(l,m,x); + (lgdr->Plm)[i][j] = plgndr_mod (l, m, x); } - j = (lgdr->nplm)[i]-1; - x = 1.0; - (lgdr->x)[i][j] = x; - (lgdr->Plm)[i][j] = plgndr_mod(l,m,x); } + + return lgdr; } - return lgdr; -} - -// end legendre - -///////////////////////////// -////// Cross sections /// -///////////////////////////// - -double total_hkl_XS(double k, double kct, double kphi, struct hkl_data_texture *L, - struct legendre *lgdr) -{ - int numV = L->numV; - int *lv = L->lv; - int *mv = L->mv; - double *RV = L->RV; - double *phiV = L->phiV; - double x = (L->G)/(2*k); - double XS, XSi, pl, plm; - int l, m, i, id, n; - FILE *filep; - - if(x>1) { + // end legendre + + ///////////////////////////// + ////// Cross sections /// + ///////////////////////////// + + double + total_hkl_XS (double k, double kct, double kphi, struct hkl_data_texture* L, struct legendre* lgdr) { + int numV = L->numV; + int* lv = L->lv; + int* mv = L->mv; + double* RV = L->RV; + double* phiV = L->phiV; + double x = (L->G) / (2 * k); + double XS, XSi, pl, plm; + int l, m, i, id, n; + FILE* filep; + + if (x > 1) { + XS = 0; + XSi = 0; + return XS; + } + + l = -1; XS = 0; XSi = 0; + for (i = 0; i < numV; i++) { + if (lv[i] != l) { + l = lv[i]; + // l-th legendre polynomial evaluated at x, Pl(x) + id = (lgdr->index)[l][l]; + pl = interp (x, lgdr->nplm[id], lgdr->x[id], lgdr->Plm[id]); + } + m = mv[i]; + // lm-th associated legendre polynomial evaluated at kct, Plm(kct) + id = (lgdr->index)[l][l + m]; + plm = interp (kct, (lgdr->nplm)[id], (lgdr->x)[id], (lgdr->Plm)[id]); + XS += pl * RV[i] * plm * cos (phiV[i] - m * kphi); + XSi += pl * RV[i] * plm * sin (phiV[i] - m * kphi); + } + + if (XS < 0) { + printf ("total_hkl_XS: negative XS: %.6e\n", XS); + // printf("h: %d k: %d l: %d Gx: %.6e Gy: %.6e Gz: %.6e\n",L->h,L->k,L->l,L->Gx,L->Gy,L->Gz); + // printf("Exiting..."); + fflush (stdout); + filep = fopen ("negativeXS.txt", "a"); + if (filep) { + fprintf (filep, "%d %d %d %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", L->h, L->k, L->l, L->Gx, L->Gy, L->Gz, k, kct, kphi, XS); + fclose (filep); + } else { + fprintf (stderr, "Texture_process/routine total_hkl_XS: failed fopen in add mode for file 'negativeXS.txt'. Exit!\n"); + exit (-1); + } + } + + // this is not the cross section. A different name (reflectivity??) would be appropriate + // there is a missed factor N*(2*pi)**3/(v0*k**3), which is a constant and then applied + // only at the end + XS *= (L->mult) * (L->F2) / (4 * x); + return XS; } - - l = -1; - XS = 0; - XSi = 0; - for(i=0;iindex)[l][l]; - pl = interp(x,lgdr->nplm[id],lgdr->x[id],lgdr->Plm[id]); - } - m = mv[i]; - // lm-th associated legendre polynomial evaluated at kct, Plm(kct) - id = (lgdr->index)[l][l+m]; - plm = interp(kct,(lgdr->nplm)[id],(lgdr->x)[id],(lgdr->Plm)[id]); - XS += pl*RV[i]*plm*cos(phiV[i]-m*kphi); - XSi += pl*RV[i]*plm*sin(phiV[i]-m*kphi); + + double + total_hkl_XS_interp (double k, double kct, double kphi, struct hkl_data_texture* L, struct legendre* lgdr) { + int l, id; + double x = (L->G) / (2 * k); + double XS, XSi, pl, Ul; + FILE* filep; + + if (x > 1) { + XS = 0; + XSi = 0; + return XS; + } + + XSi = 0; + XS = 1.0; + for (l = 1; l <= L->lmax; l++) { + // l-th legendre polynomial evaluated at x, Pl(x) + id = (lgdr->index)[l][l]; + pl = interp (x, lgdr->nplm[id], lgdr->x[id], lgdr->Plm[id]); + Ul = interp2D (kct, kphi, (L->nctk_l)[l], (L->nphik_l)[l], (L->ctk_l)[l], (L->phik_l)[l], (L->Upsilon_l)[l]); + XS += pl * Ul; + } + + if (XS < 0) { + printf ("total_hkl_XS: negative XS: %.6e\n", XS); + fflush (stdout); + filep = fopen ("negativeXS.txt", "a"); + if (filep) { + fprintf (filep, "%d %d %d %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", L->h, L->k, L->l, L->Gx, L->Gy, L->Gz, k, kct, kphi, XS); + fclose (filep); + } else { + fprintf (stderr, "Texture_process/total_hkl_XS_interp: failed fopen in add mode for file 'negativeXS.txt'. Exit!\n"); + exit (-1); + } + } + + // this is not the cross section. A different name (reflectivity??) + // would be appropriate + // there is a missed factor N*(2*pi)**3/(v0*k**3), which is a constant + // and then applied only at the end + XS *= (L->mult) * (L->F2) / (4 * x); + + /* + filep = fopen("XS_interp.txt","a"); + fprintf(filep,"%d %d %d %.6e %.6e %.6e %.6e %.6e %.6e %.6e %.16e %.16e\n", + L->h,L->k,L->l,L->Gx,L->Gy,L->Gz,k,kct,kphi,x,XS,XSi); + fclose(filep); + */ + + return XS; } - if(XS<0) { - printf("total_hkl_XS: negative XS: %.6e\n",XS); - //printf("h: %d k: %d l: %d Gx: %.6e Gy: %.6e Gz: %.6e\n",L->h,L->k,L->l,L->Gx,L->Gy,L->Gz); - //printf("Exiting..."); - fflush(stdout); - filep = fopen("negativeXS.txt","a"); - if(filep) { - fprintf(filep,"%d %d %d %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", - L->h,L->k,L->l,L->Gx,L->Gy,L->Gz,k,kct,kphi,XS); + int + precomputeUpsilon_l (struct hkl_data_texture* L, struct legendre* lgdr) { + int i, j, l, lmax; + int *nctk_l, *nphik_l; + double **ctk_l, **phik_l, ***Upsilon_l; + double dctk, dphik; + + char fn[500]; + FILE* filep; + + lmax = L->lmax; + + L->nctk_l = (int*)malloc ((lmax + 1) * sizeof (int)); + L->nphik_l = (int*)malloc ((lmax + 1) * sizeof (int)); + L->ctk_l = (double**)malloc ((lmax + 1) * sizeof (double*)); + L->phik_l = (double**)malloc ((lmax + 1) * sizeof (double*)); + L->Upsilon_l = (double***)malloc ((lmax + 1) * sizeof (double**)); + + nctk_l = L->nctk_l; + nphik_l = L->nphik_l; + ctk_l = L->ctk_l; + phik_l = L->phik_l; + Upsilon_l = L->Upsilon_l; + + for (l = 1; l <= lmax; l++) { + nctk_l[l] = 201; + nphik_l[l] = 601; + ctk_l[l] = (double*)malloc (nctk_l[l] * sizeof (double)); + phik_l[l] = (double*)malloc (nphik_l[l] * sizeof (double)); + Upsilon_l[l] = (double**)malloc (nctk_l[l] * sizeof (double*)); + for (i = 0; i < nctk_l[l]; i++) { + Upsilon_l[l][i] = (double*)malloc (nphik_l[l] * sizeof (double)); + } + + dctk = 2.0 / (nctk_l[l] - 1); + dphik = (2.0 * PI) / (nphik_l[l] - 1); + + for (i = 0; i < nctk_l[l] - 1; i++) { + ctk_l[l][i] = -1.0 + i * dctk; + } + ctk_l[l][nctk_l[l] - 1] = 1.0; + + for (j = 0; j < nphik_l[l] - 1; j++) { + phik_l[l][j] = -PI + j * dphik; + } + phik_l[l][nphik_l[l] - 1] = PI; + + for (i = 0; i < nctk_l[l]; i++) { + for (j = 0; j < nphik_l[l]; j++) { + Upsilon_l[l][i][j] = computeUpsilon_l (ctk_l[l][i], phik_l[l][j], l, L, lgdr); + } + } + + /* + sprintf(fn,"Upsilon_l_precomputed_%d_%d_%d.txt",L->h,L->k,L->l); + filep = fopen(fn,"a"); + for(i=0;imult)*(L->F2)/(4*x); - - return XS; -} - -double total_hkl_XS_interp(double k, double kct, double kphi, struct hkl_data_texture *L, - struct legendre *lgdr) -{ - int l, id; - double x = (L->G)/(2*k); - double XS, XSi, pl, Ul; - FILE *filep; - - if(x>1) { + double + computeUpsilon_l (double kct, double kphi, int l, struct hkl_data_texture* L, struct legendre* lgdr) { + int i, m, id; + double XS, XSi, plm; + int numV = L->numV; + int* lv = L->lv; + int* mv = L->mv; + double* RV = L->RV; + double* phiV = L->phiV; + XS = 0; XSi = 0; + for (i = 0; i < numV; i++) { + if (lv[i] == l) { + m = mv[i]; + // lm-th associated legendre polynomial evaluated at kct, Plm(kct) + id = (lgdr->index)[l][l + m]; + plm = interp (kct, (lgdr->nplm)[id], (lgdr->x)[id], (lgdr->Plm)[id]); + XS += RV[i] * plm * cos (phiV[i] - m * kphi); + XSi += RV[i] * plm * sin (phiV[i] - m * kphi); + } + } + return XS; } - XSi = 0; - XS = 1.0; - for(l=1;l<=L->lmax;l++) { - // l-th legendre polynomial evaluated at x, Pl(x) - id = (lgdr->index)[l][l]; - pl = interp(x,lgdr->nplm[id],lgdr->x[id],lgdr->Plm[id]); - Ul = interp2D(kct,kphi,(L->nctk_l)[l],(L->nphik_l)[l], - (L->ctk_l)[l],(L->phik_l)[l],(L->Upsilon_l)[l]); - XS += pl*Ul; - } - - if(XS<0) { - printf("total_hkl_XS: negative XS: %.6e\n",XS); - fflush(stdout); - filep = fopen("negativeXS.txt","a"); - if(filep) { - fprintf(filep,"%d %d %d %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", - L->h,L->k,L->l,L->Gx,L->Gy,L->Gz,k,kct,kphi,XS); - fclose(filep); - } else { - fprintf(stderr,"Texture_process/total_hkl_XS_interp: failed fopen in add mode for file 'negativeXS.txt'. Exit!\n"); - exit(-1); + int + computeV (struct fourier_coef* fc, struct legendre* lgdr, struct hkl_data_texture* L) { + int i, l, m, n, numV; + double Gct, Gphi, cnp, snp, pln, vr, vi; + double **R, **Phi; + FILE* filep; + + int lmax = fc->lmax; + + if (lmax < 0) { + printf ("computeV: negative lmax = %d\n", lmax); + printf ("Exiting...\n"); + fflush (stdout); + exit (-1); } - } - // this is not the cross section. A different name (reflectivity??) - // would be appropriate - // there is a missed factor N*(2*pi)**3/(v0*k**3), which is a constant - // and then applied only at the end - XS *= (L->mult)*(L->F2)/(4*x); + Gct = L->Gct; + Gphi = L->Gphi; - /* - filep = fopen("XS_interp.txt","a"); - fprintf(filep,"%d %d %d %.6e %.6e %.6e %.6e %.6e %.6e %.6e %.16e %.16e\n", - L->h,L->k,L->l,L->Gx,L->Gy,L->Gz,k,kct,kphi,x,XS,XSi); - fclose(filep); - */ - - return XS; -} - -int precomputeUpsilon_l(struct hkl_data_texture *L, struct legendre *lgdr) -{ - int i, j, l, lmax; - int *nctk_l, *nphik_l; - double **ctk_l, **phik_l, ***Upsilon_l; - double dctk, dphik; - - char fn[500]; - FILE *filep; - - lmax = L->lmax; - - L->nctk_l = (int *)malloc((lmax+1)*sizeof(int)); - L->nphik_l = (int *)malloc((lmax+1)*sizeof(int)); - L->ctk_l = (double **)malloc((lmax+1)*sizeof(double *)); - L->phik_l = (double **)malloc((lmax+1)*sizeof(double *)); - L->Upsilon_l = (double ***)malloc((lmax+1)*sizeof(double **)); - - nctk_l = L->nctk_l; - nphik_l = L->nphik_l; - ctk_l = L->ctk_l; - phik_l = L->phik_l; - Upsilon_l = L->Upsilon_l; - - for(l=1;l<=lmax;l++) { - nctk_l[l] = 201; - nphik_l[l] = 601; - ctk_l[l] = (double *)malloc(nctk_l[l]*sizeof(double)); - phik_l[l] = (double *)malloc(nphik_l[l]*sizeof(double)); - Upsilon_l[l] = (double **)malloc(nctk_l[l]*sizeof(double *)); - for(i=0;icr)[l][l + m][l + n] * cnp - (fc->ci)[l][l + m][l + n] * snp); + vi += pln * ((fc->cr)[l][l + m][l + n] * snp + (fc->ci)[l][l + m][l + n] * cnp); + } + R[l][l + m] = sqrt (vr * vr + vi * vi); + Phi[l][l + m] = atan2 (vi, vr); + if (R[l][l + m] > tolTexture) { + numV++; + } + } } /* - sprintf(fn,"Upsilon_l_precomputed_%d_%d_%d.txt",L->h,L->k,L->l); - filep = fopen(fn,"a"); - for(i=0;inumV; - int *lv = L->lv; - int *mv = L->mv; - double *RV = L->RV; - double *phiV = L->phiV; - - XS = 0; - XSi = 0; - for(i=0;iindex)[l][l+m]; - plm = interp(kct,(lgdr->nplm)[id],(lgdr->x)[id],(lgdr->Plm)[id]); - XS += RV[i]*plm*cos(phiV[i]-m*kphi); - XSi += RV[i]*plm*sin(phiV[i]-m*kphi); - } - } - - return XS; -} - -int computeV(struct fourier_coef *fc, struct legendre *lgdr, struct hkl_data_texture *L) -{ - int i, l, m, n, numV; - double Gct, Gphi, cnp, snp, pln, vr, vi; - double **R, **Phi; - FILE *filep; - - int lmax = fc->lmax; - - if(lmax<0) { - printf("computeV: negative lmax = %d\n",lmax); - printf("Exiting...\n"); - fflush(stdout); - exit(-1); - } - - Gct = L->Gct; - Gphi = L->Gphi; - - R = (double **)malloc((lmax+1)*sizeof(double *)); - for(l=0;l<=lmax;l++) { - R[l] = (double *)malloc((2*l+1)*sizeof(double)); - } - Phi = (double **)malloc((lmax+1)*sizeof(double *)); - for(l=0;l<=lmax;l++) { - Phi[l] = (double *)malloc((2*l+1)*sizeof(double)); - } - // compute V - - numV = 0; - for(l=0;l<=lmax;l++) { - for(m=-l;m<=l;m++) { - vr = 0; - vi = 0; - for(n=-l;n<=l;n++) { - pln = plgndr_mod(l,n,Gct); // this can be interpolated from lgdr - cnp = cos(n*Gphi); - snp = sin(n*Gphi); - vr += pln*((fc->cr)[l][l+m][l+n]*cnp - (fc->ci)[l][l+m][l+n]*snp); - vi += pln*((fc->cr)[l][l+m][l+n]*snp + (fc->ci)[l][l+m][l+n]*cnp); + L->numV = numV; + L->lv = (int*)malloc (numV * sizeof (int)); + L->mv = (int*)malloc (numV * sizeof (int)); + L->RV = (double*)malloc (numV * sizeof (double)); + L->phiV = (double*)malloc (numV * sizeof (double)); + + i = -1; + for (l = 0; l <= lmax; l++) { + for (m = -l; m <= l; m++) { + if (R[l][l + m] > tolTexture) { + i++; + (L->lv)[i] = l; + (L->mv)[i] = m; + (L->RV)[i] = R[l][l + m]; + (L->phiV)[i] = Phi[l][l + m]; + } } - R[l][l+m] = sqrt(vr*vr+vi*vi); - Phi[l][l+m] = atan2(vi,vr); - if(R[l][l+m]>tolTexture) { numV++; } } - } - /* - filep = fopen("V.txt","w"); - for(l=0;l<=lmax;l++) { - for(m=0;m<=l;m++) { - fprintf(filep,"%d %d %.6e %.6e %.6e %.6e\n", - l,m,R[l][l+m],R[l][l-m],Phi[l][l+m],Phi[l][l-m]); + /* + filep = fopen("Vlarge.txt","a"); + fprintf(filep,"# %d\n",L->numV); + for(i=0;inumV;i++) { + fprintf(filep,"%d %d %d %d %d %d %.16e %.16e\n", + L->l,L->h,L->k,i,L->lv[i],L->mv[i],L->RV[i],L->phiV[i]); } - } - fclose(filep); - */ - - L->numV = numV; - L->lv = (int *)malloc(numV*sizeof(int)); - L->mv = (int *)malloc(numV*sizeof(int)); - L->RV = (double *)malloc(numV*sizeof(double)); - L->phiV = (double *)malloc(numV*sizeof(double)); - - i = -1; - for(l=0;l<=lmax;l++) { - for(m=-l;m<=l;m++) { - if(R[l][l+m] > tolTexture) { - i++; - (L->lv)[i] = l; - (L->mv)[i] = m; - (L->RV)[i] = R[l][l+m]; - (L->phiV)[i] = Phi[l][l+m]; + fclose(filep); + */ + + // free memory + for (l = 0; l <= lmax; l++) { + free (R[l]); + free (Phi[l]); + } + free (R); + free (Phi); + + printf ("computeV:"); + printf (" %d %d %d numV = %d \n", L->h, L->k, L->l, numV); + + return 0; + } + + // end cross sections + + //////////////////////////////// + /// Sampling // + //////////////////////////////// + + int + sampleKprime_hkl (double* kf, double* ki, struct hkl_data_texture* L, struct legendre* lgdr) { + int it, i, is, j; + double xi, kdg; + // modulus of ki and local orthonormal basis containing ki, (t1,t2,kih) + double kim, kihx, kihy, kihz, t1x, t1y, t1z, t2x, t2y, t2z; + double stheta, ctheta; + // pre computed probalility + double phipts[nSamplingPoints], probpts[nSamplingPoints]; + double *aa, *bb; + double dphi; + double maxProb; + // cartesian coordinates of kf in the (t1,t2,kih) basis + double kft1, kft2, kfkih; + // azimuthal angle (phi) of kf in the (t1,t2,kih) basis and sine and cosine + double phi, kfsp, kfcp; + // polar coordinates (in the sample coordinate system) of the unitay scattering vector qh + double ctq, phiq; + // coefficientes to get the polar coordinates of q + double ux0, uxc, uxs, uy0, uyc, uys, uz0, uzc, uzs; + // Legendre associated funtion and probability of phi + double p, plm, pimag; + // File pointers + FILE *filep, *filep2; + char fn[1000]; + + int lastSaved = L->lastSaved; + int maxSaved = L->maxSaved; + struct saveScattProb* sp = L->savedNeutrons; + struct saveScattProb* sp_save; + + is = -1; + for (i = lastSaved; i >= 0; i--) { + if (fabs (ki[0] - sp[i].kix) < 1.0e-90 && fabs (ki[1] - sp[i].kiy) < 1.0e-90 && fabs (ki[2] - sp[i].kiz) < 1.0e-90) { + is = i; + break; } } - } - - /* - filep = fopen("Vlarge.txt","a"); - fprintf(filep,"# %d\n",L->numV); - for(i=0;inumV;i++) { - fprintf(filep,"%d %d %d %d %d %d %.16e %.16e\n", - L->l,L->h,L->k,i,L->lv[i],L->mv[i],L->RV[i],L->phiV[i]); - } - fclose(filep); - */ - - // free memory - for(l=0;l<=lmax;l++) { - free(R[l]); - free(Phi[l]); - } - free(R); - free(Phi); - - printf("computeV:"); - printf(" %d %d %d numV = %d \n",L->h,L->k,L->l,numV); - - return 0; -} - -// end cross sections - -//////////////////////////////// -/// Sampling // -//////////////////////////////// - -int sampleKprime_hkl(double *kf, double *ki, struct hkl_data_texture *L, struct legendre *lgdr) -{ - int it, i, is, j; - double xi, kdg; - // modulus of ki and local orthonormal basis containing ki, (t1,t2,kih) - double kim, kihx, kihy, kihz, t1x, t1y, t1z, t2x, t2y, t2z; - double stheta, ctheta; - // pre computed probalility - double phipts[nSamplingPoints], probpts[nSamplingPoints]; - double *aa, *bb; - double dphi; - double maxProb; - // cartesian coordinates of kf in the (t1,t2,kih) basis - double kft1, kft2, kfkih; - // azimuthal angle (phi) of kf in the (t1,t2,kih) basis and sine and cosine - double phi, kfsp, kfcp; - // polar coordinates (in the sample coordinate system) of the unitay scattering vector qh - double ctq, phiq; - // coefficientes to get the polar coordinates of q - double ux0, uxc, uxs, uy0, uyc, uys, uz0, uzc, uzs; - // Legendre associated funtion and probability of phi - double p, plm, pimag; - // File pointers - FILE *filep, *filep2; - char fn[1000]; - - int lastSaved = L->lastSaved; - int maxSaved = L->maxSaved; - struct saveScattProb *sp = L->savedNeutrons; - struct saveScattProb *sp_save; - - is = -1; - for(i=lastSaved;i>=0;i--) { - if( fabs(ki[0]-sp[i].kix)<1.0e-90 && - fabs(ki[1]-sp[i].kiy)<1.0e-90 && - fabs(ki[2]-sp[i].kiz)<1.0e-90 ) { is = i; break; } - } - if(is==-1) { - // continue the search - for(i=maxSaved-1;i>lastSaved;i--) { - if( fabs(ki[0]-sp[i].kix)<1.0e-90 && - fabs(ki[1]-sp[i].kiy)<1.0e-90 && - fabs(ki[2]-sp[i].kiz)<1.0e-90 ) { is = i; break; } + if (is == -1) { + // continue the search + for (i = maxSaved - 1; i > lastSaved; i--) { + if (fabs (ki[0] - sp[i].kix) < 1.0e-90 && fabs (ki[1] - sp[i].kiy) < 1.0e-90 && fabs (ki[2] - sp[i].kiz) < 1.0e-90) { + is = i; + break; + } + } } - } - if( is != -1 ) { - // equal neutron found. reuse - //printf("scatt hkl reuse\n"); - //fflush(stdout); - sp_save = sp + is; - kim = sp_save->kim; - stheta = sp_save->stheta; - ctheta = sp_save->ctheta; - kihx = sp_save->kihx; - kihy = sp_save->kihy; - kihz = sp_save->kihz; - t1x = sp_save->t1x; - t1y = sp_save->t1y; - t1z = sp_save->t1z; - t2x = sp_save->t2x; - t2y = sp_save->t2y; - t2z = sp_save->t2z; - dphi = sp_save->dphi; - maxProb = sp_save->maxProb; - aa = sp_save->aa; - bb = sp_save->bb; - // save scattering parameters - L->lastSaved = is; - } else { - // neutron different from previous. Compute prob. distribution, etc. - //printf("scatt hkl new\n"); - //fflush(stdout); - - // modulus of ki - kim = sqrt(ki[0]*ki[0]+ki[1]*ki[1]+ki[2]*ki[2]); - // unitary vector in the direction of ki - kihx = ki[0]/kim; - kihy = ki[1]/kim; - kihz = ki[2]/kim; - - kdg = kim/(L->G); - - ctheta = 1.0 - 0.5/(kdg*kdg); - stheta = sqrt(1.0 - ctheta*ctheta); - - // right-handed orthonormal triad - if(1.0-kihz*kihz>1.0e-3) { - xi = sqrt(1.0-kihz*kihz); - t1x = kihy/xi; - t1y = -kihx/xi; - t1z = 0; - t2x = kihz*kihx/xi; - t2y = kihz*kihy/xi; - t2z = -xi; - } else if(1.0-kihx*kihx>1.0e-3) { - xi = sqrt(1.0-kihx*kihx); - t1x = 0; - t1y = kihz/xi; - t1z = -kihy/xi; - t2x = -xi; - t2y = kihx*kihy/xi; - t2z = kihx*kihz/xi; + if (is != -1) { + // equal neutron found. reuse + // printf("scatt hkl reuse\n"); + // fflush(stdout); + sp_save = sp + is; + kim = sp_save->kim; + stheta = sp_save->stheta; + ctheta = sp_save->ctheta; + kihx = sp_save->kihx; + kihy = sp_save->kihy; + kihz = sp_save->kihz; + t1x = sp_save->t1x; + t1y = sp_save->t1y; + t1z = sp_save->t1z; + t2x = sp_save->t2x; + t2y = sp_save->t2y; + t2z = sp_save->t2z; + dphi = sp_save->dphi; + maxProb = sp_save->maxProb; + aa = sp_save->aa; + bb = sp_save->bb; + // save scattering parameters + L->lastSaved = is; } else { - xi = sqrt(1.0-kihy*kihy); - t1x = -kihz/xi; - t1y = 0; - t1z = kihx/xi; - t2x = kihy*kihx/xi; - t2y = -xi; - t2z = kihy*kihz/xi; - } - - //coefficients to obtain the polar coordinates of qh = kih - kfh - ux0 = (1.0-ctheta)*kihx; - uxc = -stheta*t1x; - uxs = -stheta*t2x; - uy0 = (1.0-ctheta)*kihy; - uyc = -stheta*t1y; - uys = -stheta*t2y; - uz0 = kdg*(1.0-ctheta)*kihz; - uzc = -kdg*stheta*t1z; - uzs = -kdg*stheta*t2z; - - maxProb = -1.0e99; - dphi = (2.0*PI)/(nSamplingPoints-1); - phi = -PI; - // precompute probability distribution - for(j=0;jnctq,L->nphiq,L->ctq,L->phiq,L->probQ); - if(probpts[j]>maxProb) { maxProb = probpts[j]; } - phi += dphi; - } - phipts[nSamplingPoints-1] = PI; - probpts[nSamplingPoints-1] = probpts[0]; - - // save scattering parameters - lastSaved++; - if(lastSaved>=maxSaved) { lastSaved = 0; } - L->lastSaved = lastSaved; - sp_save = sp + lastSaved; - aa = sp_save->aa; - bb = sp_save->bb; - for(j=0;jkix = ki[0]; - sp_save->kiy = ki[1]; - sp_save->kiz = ki[2]; - sp_save->kim = kim; - sp_save->stheta = stheta; - sp_save->ctheta = ctheta; - sp_save->kihx = kihx; - sp_save->kihy = kihy; - sp_save->kihz = kihz; - sp_save->t1x = t1x; - sp_save->t1y = t1y; - sp_save->t1z = t1z; - sp_save->t2x = t2x; - sp_save->t2y = t2y; - sp_save->t2z = t2z; - sp_save->dphi = dphi; - sp_save->maxProb = maxProb; - } + // neutron different from previous. Compute prob. distribution, etc. + // printf("scatt hkl new\n"); + // fflush(stdout); + + // modulus of ki + kim = sqrt (ki[0] * ki[0] + ki[1] * ki[1] + ki[2] * ki[2]); + // unitary vector in the direction of ki + kihx = ki[0] / kim; + kihy = ki[1] / kim; + kihz = ki[2] / kim; + + kdg = kim / (L->G); + + ctheta = 1.0 - 0.5 / (kdg * kdg); + stheta = sqrt (1.0 - ctheta * ctheta); + + // right-handed orthonormal triad + if (1.0 - kihz * kihz > 1.0e-3) { + xi = sqrt (1.0 - kihz * kihz); + t1x = kihy / xi; + t1y = -kihx / xi; + t1z = 0; + t2x = kihz * kihx / xi; + t2y = kihz * kihy / xi; + t2z = -xi; + } else if (1.0 - kihx * kihx > 1.0e-3) { + xi = sqrt (1.0 - kihx * kihx); + t1x = 0; + t1y = kihz / xi; + t1z = -kihy / xi; + t2x = -xi; + t2y = kihx * kihy / xi; + t2z = kihx * kihz / xi; + } else { + xi = sqrt (1.0 - kihy * kihy); + t1x = -kihz / xi; + t1y = 0; + t1z = kihx / xi; + t2x = kihy * kihx / xi; + t2y = -xi; + t2z = kihy * kihz / xi; + } - // rejection method - for(it=0;itrand01()) { - //printf("rej. it: %d j: %d phi: %f\n",it,j,phi); - kft1 = stheta*cos(phi); - kft2 = stheta*sin(phi); - kfkih = ctheta; - kf[0] = kim*(kft1*t1x + kft2*t2x + kfkih*kihx); - kf[1] = kim*(kft1*t1y + kft2*t2y + kfkih*kihy); - kf[2] = kim*(kft1*t1z + kft2*t2z + kfkih*kihz); + // coefficients to obtain the polar coordinates of qh = kih - kfh + ux0 = (1.0 - ctheta) * kihx; + uxc = -stheta * t1x; + uxs = -stheta * t2x; + uy0 = (1.0 - ctheta) * kihy; + uyc = -stheta * t1y; + uys = -stheta * t2y; + uz0 = kdg * (1.0 - ctheta) * kihz; + uzc = -kdg * stheta * t1z; + uzs = -kdg * stheta * t2z; + + maxProb = -1.0e99; + dphi = (2.0 * PI) / (nSamplingPoints - 1); + phi = -PI; + // precompute probability distribution + for (j = 0; j < nSamplingPoints - 1; j++) { + kfsp = sin (phi); + kfcp = cos (phi); + ctq = uz0 + uzc * kfcp + uzs * kfsp; + phiq = atan2 (uy0 + uyc * kfcp + uys * kfsp, ux0 + uxc * kfcp + uxs * kfsp); + phipts[j] = phi; + // probpts[j] = probPhiq(ctq,phiq,L,lgdr); + // interpolate instead of computing + probpts[j] = interp2D (ctq, phiq, L->nctq, L->nphiq, L->ctq, L->phiq, L->probQ); + if (probpts[j] > maxProb) { + maxProb = probpts[j]; + } + phi += dphi; + } + phipts[nSamplingPoints - 1] = PI; + probpts[nSamplingPoints - 1] = probpts[0]; + + // save scattering parameters + lastSaved++; + if (lastSaved >= maxSaved) { + lastSaved = 0; + } + L->lastSaved = lastSaved; + sp_save = sp + lastSaved; + aa = sp_save->aa; + bb = sp_save->bb; + for (j = 0; j < nSamplingPoints - 1; j++) { + aa[j] = probpts[j] - phipts[j] * (probpts[j + 1] - probpts[j]) / dphi; + bb[j] = (probpts[j + 1] - probpts[j]) / dphi; + } + sp_save->kix = ki[0]; + sp_save->kiy = ki[1]; + sp_save->kiz = ki[2]; + sp_save->kim = kim; + sp_save->stheta = stheta; + sp_save->ctheta = ctheta; + sp_save->kihx = kihx; + sp_save->kihy = kihy; + sp_save->kihz = kihz; + sp_save->t1x = t1x; + sp_save->t1y = t1y; + sp_save->t1z = t1z; + sp_save->t2x = t2x; + sp_save->t2y = t2y; + sp_save->t2z = t2z; + sp_save->dphi = dphi; + sp_save->maxProb = maxProb; + } + + // rejection method + for (it = 0; it < maxIterReject; it++) { + phi = -PI + 2 * PI * rand01 (); + // interpolate + j = (int)((PI + phi) / dphi); + // p = probpts[j] + (phi-phipts[j])*(probpts[j+1]-probpts[j])/dphi; + p = aa[j] + phi * bb[j]; + if (p / maxProb > rand01 ()) { + // printf("rej. it: %d j: %d phi: %f\n",it,j,phi); + kft1 = stheta * cos (phi); + kft2 = stheta * sin (phi); + kfkih = ctheta; + kf[0] = kim * (kft1 * t1x + kft2 * t2x + kfkih * kihx); + kf[1] = kim * (kft1 * t1y + kft2 * t2y + kfkih * kihy); + kf[2] = kim * (kft1 * t1z + kft2 * t2z + kfkih * kihz); /* filep=fopen("sample_return.txt","a"); fprintf(filep,"%.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", - ctheta,kft1,kft2,kfkih,kf[0],kf[1],kf[2]); + ctheta,kft1,kft2,kfkih,kf[0],kf[1],kf[2]); fclose(filep); filep=fopen("sample_basis.txt","a"); fprintf(filep,"%.6e %.6e %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", - t1x,t1y,t1z,t2x,t2y,t2z,kihx,kihy,kihz); + t1x,t1y,t1z,t2x,t2y,t2z,kihx,kihy,kihz); fclose(filep); - */ - /* + */ + /* sprintf(fn,"sampleK_%d%d%d.txt",L->h,L->k,L->l); filep = fopen(fn,"a"); - fprintf(filep,"%.6e %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", - ki[0],ki[1],ki[2],kf[0],kf[1],kf[2],stheta,ctheta); + fprintf(filep,"%.6e %.6e %.6e %.6e %.6e %.6e %.6e %.6e\n", + ki[0],ki[1],ki[2],kf[0],kf[1],kf[2],stheta,ctheta); fclose(filep); - */ - L->numReject += it + 1; - L->numScatt += 1; + */ + L->numReject += it + 1; + L->numScatt += 1; return 0; - } - } - - /* - filep = fopen("probQ_precomputed.txt","a"); - for(i=0;inctq;i++) { - for(j=0;jnphiq;j++) { - fprintf(filep,"%f %f %.6e\n",(L->ctq)[i],(L->phiq)[j],(L->probQ)[i][j]); - } - } - fclose(filep); - */ + } + } - printf("sampleKprime_hkl: too many iterations in rejection method\n"); - printf("find distribution probability in file sampleKprime_hkl_fail.txt\n"); - //sprintf(fn,"probPhiQ_%d%d%d.txt",L->h,L->k,L->l); - filep = fopen("sampleKprime_hkl_fail.txt","w"); - if(!filep) { - fprintf(stderr,"Texture_process/sampleKprime_hkl: failed fopen write mode for file 'sampleKprime_hkl_fail.txt'. Exit!\n"); - exit(-1); - } - //filep = fopen(fn,"a"); - fprintf(filep,"#Plane hkl: %d %d %d\n",L->h,L->k,L->l); - fprintf(filep,"#Incoming neutron:\n"); - fprintf(filep,"#kx: %.6e ky: %.6e kz: %.6e\n",ki[0],ki[1],ki[2]); - for(j=0;jnumV; - int *lv = L->lv; - int *mv = L->mv; - double *RV = L->RV; - double *phiV = L->phiV; - - int *nplm = lgdr->nplm; - double **x = lgdr->x; - double **Plm = lgdr->Plm; - - double p = 0; - for(i=0;i<(L->numV);i++) { - l = lv[i]; - m = mv[i]; - id = (lgdr->index)[l][l+m]; - plm = interp(ctq,nplm[id],x[id],Plm[id]); - p += RV[i]*plm*cos(phiV[i]-m*phiq); - } + /* + filep = fopen("probQ_precomputed.txt","a"); + for(i=0;inctq;i++) { + for(j=0;jnphiq;j++) { + fprintf(filep,"%f %f %.6e\n",(L->ctq)[i],(L->phiq)[j],(L->probQ)[i][j]); + } + } + fclose(filep); + */ - return p; -} - -double probPhiqImag(double ctq, double phiq, struct hkl_data_texture *L, struct legendre *lgdr) -{ - int i, l, m, id; - double plm; - - int numV = L->numV; - int *lv = L->lv; - int *mv = L->mv; - double *RV = L->RV; - double *phiV = L->phiV; - - int *nplm = lgdr->nplm; - double **x = lgdr->x; - double **Plm = lgdr->Plm; - - double p = 0; - for(i=0;i<(L->numV);i++) { - l = lv[i]; - m = mv[i]; - id = (lgdr->index)[l][l+m]; - plm = interp(ctq,nplm[id],x[id],Plm[id]); - p += RV[i]*plm*sin(phiV[i]-m*phiq); - } + printf ("sampleKprime_hkl: too many iterations in rejection method\n"); + printf ("find distribution probability in file sampleKprime_hkl_fail.txt\n"); + // sprintf(fn,"probPhiQ_%d%d%d.txt",L->h,L->k,L->l); + filep = fopen ("sampleKprime_hkl_fail.txt", "w"); + if (!filep) { + fprintf (stderr, "Texture_process/sampleKprime_hkl: failed fopen write mode for file 'sampleKprime_hkl_fail.txt'. Exit!\n"); + exit (-1); + } + // filep = fopen(fn,"a"); + fprintf (filep, "#Plane hkl: %d %d %d\n", L->h, L->k, L->l); + fprintf (filep, "#Incoming neutron:\n"); + fprintf (filep, "#kx: %.6e ky: %.6e kz: %.6e\n", ki[0], ki[1], ki[2]); + for (j = 0; j < nSamplingPoints - 1; j++) { + phi = -PI + j * dphi; + fprintf (filep, "%f %.6e %.6e %.6e %.6e\n", phi, aa[j] + phi * bb[j], phipts[j], probpts[j], maxProb); + } + fprintf (filep, "\n\n"); + phi = -PI; + while (phi < PI) { + kfsp = sin (phi); + kfcp = cos (phi); + ctq = uz0 + uzc * kfcp + uzs * kfsp; + phiq = atan2 (uy0 + uyc * kfcp + uys * kfsp, ux0 + uxc * kfcp + uxs * kfsp); + p = probPhiq (ctq, phiq, L, lgdr); + fprintf (filep, "%f %.6e %.6e\n", phi, p, maxProb); + phi += 0.001; + } + fclose (filep); + printf ("Exiting\n"); + fflush (stdout); + exit (-1); + } + + double + probPhiq (double ctq, double phiq, struct hkl_data_texture* L, struct legendre* lgdr) { + int i, l, m, id; + double plm; + + int numV = L->numV; + int* lv = L->lv; + int* mv = L->mv; + double* RV = L->RV; + double* phiV = L->phiV; + + int* nplm = lgdr->nplm; + double** x = lgdr->x; + double** Plm = lgdr->Plm; + + double p = 0; + for (i = 0; i < (L->numV); i++) { + l = lv[i]; + m = mv[i]; + id = (lgdr->index)[l][l + m]; + plm = interp (ctq, nplm[id], x[id], Plm[id]); + p += RV[i] * plm * cos (phiV[i] - m * phiq); + } - return p; -} - -int precomputeProbPhiq(struct hkl_data_texture *L, struct legendre *lgdr) -{ - int i, j, nctq, nphiq; - double dctq, dphiq; - double *ctq, *phiq, **probQ; - char fn[500]; - FILE *filep; - - nctq = L->nctq; - nphiq = L->nphiq; - ctq = (double *)malloc(nctq*sizeof(double)); - phiq = (double *)malloc(nphiq*sizeof(double)); - probQ = (double **)malloc(nctq*sizeof(double *)); - for(i=0;ih,L->k,L->l); - filep = fopen(fn,"a"); - for(i=0;ictq = ctq; - L->phiq = phiq; - L->probQ = probQ; - - return 0; -} - -// end sampling - -/////////////////////////// -//// Input - Output // -/////////////////////////// - -int read_hkl_data_texture(char *SC_file, struct hkl_info_struct_texture *info) -{ - struct hkl_data_texture *list = NULL; - int size = 0; - t_Table sTable; // - int i = 0; - double tmp_x, tmp_y, tmp_z; - char **parsing; - char flag = 0; - double nb_atoms = 1; - double h = 0, k = 0, l = 0, F2 = 0; - int mult = -1; - double b1[3], b2[3]; - FILE *filep; - - if ( !SC_file || !strlen(SC_file) || !strcmp(SC_file,"NULL") || !strcmp(SC_file,"0") ) { - info->num_hkl = 0; - flag = 1; - } + double + probPhiqImag (double ctq, double phiq, struct hkl_data_texture* L, struct legendre* lgdr) { + int i, l, m, id; + double plm; - if (flag) { return -1; } + int numV = L->numV; + int* lv = L->lv; + int* mv = L->mv; + double* RV = L->RV; + double* phiV = L->phiV; - // Read the table + int* nplm = lgdr->nplm; + double** x = lgdr->x; + double** Plm = lgdr->Plm; - Table_Read(&sTable, SC_file, 1); // read 1st block data from SC_file into sTable - if (sTable.columns < 5) { - fprintf(stderr, "Texture: Error: The number of columns in %s should be",SC_file); - fprintf(stderr," at least %d for [h,k,l,F2,j]\n",5); - return(0); - } - if (!sTable.rows) { - fprintf(stderr, "Texture: Error: The number of rows in %s should be at least %d\n", - SC_file, 1); - return 0; - } else { size = sTable.rows; } - - // parsing of header - parsing = Table_ParseHeader(sTable.header, - "sigma_abs","sigma_a ", - "sigma_inc","sigma_i ", - "column_h", - "column_k", - "column_l", - "column_F ", - "column_F2", - "column_j", - "Delta_d/d", - "lattice_a ", - "lattice_b ", - "lattice_c ", - "lattice_aa", - "lattice_bb", - "lattice_cc", - "nb_atoms", - "multiplicity", - NULL); - - printf("l0\n"); - fflush(stderr); - - if (parsing) { - if (parsing[0] && !info->sigma_a) info->sigma_a=atof(parsing[0]); - if (parsing[1] && !info->sigma_a) info->sigma_a=atof(parsing[1]); - if (parsing[2] && !info->sigma_i) info->sigma_i=atof(parsing[2]); - if (parsing[3] && !info->sigma_i) info->sigma_i=atof(parsing[3]); - if (parsing[4]) info->column_order[0]=atoi(parsing[4]); - if (parsing[5]) info->column_order[1]=atoi(parsing[5]); - if (parsing[6]) info->column_order[2]=atoi(parsing[6]); - if (parsing[7]) info->column_order[3]=atoi(parsing[7]); - if (parsing[8]) info->column_order[4]=atoi(parsing[8]); - if (parsing[9]) info->column_order[5]=atoi(parsing[9]); - if (parsing[10] && info->m_delta_d_d <0) info->m_delta_d_d=atof(parsing[10]); - if (parsing[11] && !info->m_a) info->m_a =atof(parsing[11]); - if (parsing[12] && !info->m_b) info->m_b =atof(parsing[12]); - if (parsing[13] && !info->m_c) info->m_c =atof(parsing[13]); - if (parsing[14] && !info->m_aa) info->m_aa=atof(parsing[14]); - if (parsing[15] && !info->m_bb) info->m_bb=atof(parsing[15]); - if (parsing[16] && !info->m_cc) info->m_cc=atof(parsing[16]); - if (parsing[17]) nb_atoms=atof(parsing[17]); - if (parsing[18]) nb_atoms=atof(parsing[18]); - for (i=0; i<=18; i++) { if (parsing[i]) { free(parsing[i]); } } - free(parsing); - } + double p = 0; + for (i = 0; i < (L->numV); i++) { + l = lv[i]; + m = mv[i]; + id = (lgdr->index)[l][l + m]; + plm = interp (ctq, nplm[id], x[id], Plm[id]); + p += RV[i] * plm * sin (phiV[i] - m * phiq); + } - printf("l1\n"); - fflush(stderr); - - if (nb_atoms > 1) { info->sigma_a *= nb_atoms; info->sigma_i *= nb_atoms; } - - //special cases for the structure definition (means we specify by hand the vectors) - if (info->m_ax || info->m_ay || info->m_az) { info->m_a = 0; } - if (info->m_bx || info->m_by || info->m_bz) { info->m_b = 0; } - if (info->m_cx || info->m_cy || info->m_cz) { info->m_c = 0; } - - //compute the norm from vector a if missing - if (info->m_ax || info->m_ay || info->m_az) { - double as = sqrt(info->m_ax*info->m_ax+info->m_ay*info->m_ay+info->m_az*info->m_az); - if (!info->m_bx && !info->m_by && !info->m_bz) { info->m_a = info->m_b = as; } - if (!info->m_cx && !info->m_cy && !info->m_cz) { info->m_a = info->m_c = as; } - } - if (info->m_a && !info->m_b) { info->m_b = info->m_a; } - if (info->m_b && !info->m_c) { info->m_c = info->m_b; } - - //compute the lattice angles if not set from data file. Not used when in vector mode. - if (info->m_a && !info->m_aa) { info->m_aa = 90; } - if (info->m_aa && !info->m_bb) { info->m_bb = info->m_aa; } - if (info->m_bb && !info->m_cc) { info->m_cc = info->m_bb; } - - //parameters consistency checks - if (!info->m_ax && !info->m_ay && !info->m_az && !info->m_a) { - fprintf(stderr,"Texture: Error: Wrong a lattice vector definition\n"); - return(0); - } - if (!info->m_bx && !info->m_by && !info->m_bz && !info->m_b) { - fprintf(stderr,"Texture: Error: Wrong b lattice vector definition\n"); - return(0); - } - if (!info->m_cx && !info->m_cy && !info->m_cz && !info->m_c) { - fprintf(stderr,"Texture: Error: Wrong c lattice vector definition\n"); - return(0); - } - if (info->m_aa && info->m_bb && info->m_cc && info->recip) { - fprintf(stderr,"Texture: Error: Selecting reciprocal cell and angles is unmeaningful\n"); - return(0); + return p; } - printf("l2\n"); - fflush(stderr); - - //when lengths a,b,c + angles are given (instead of vectors a,b,c) - if (info->m_aa && info->m_bb && info->m_cc) { - double as,bs,cs; - if (info->m_a) { - as = info->m_a; - } else { - as = sqrt(info->m_ax*info->m_ax+info->m_ay*info->m_ay+info->m_az*info->m_az); - } - if (info->m_b) { - bs = info->m_b; - } else { - bs = sqrt(info->m_bx*info->m_bx+info->m_by*info->m_by+info->m_bz*info->m_bz); - } - if (info->m_c) { - cs = info->m_c; - } else { - cs = sqrt(info->m_cx*info->m_cx+info->m_cy*info->m_cy+info->m_cz*info->m_cz); - } - /* - info->m_bz = as; info->m_by = 0; info->m_bx = 0; - info->m_az = bs*cos(info->m_cc*DEG2RAD); - info->m_ay = bs*sin(info->m_cc*DEG2RAD); - info->m_ax = 0; - info->m_cz = cs*cos(info->m_bb*DEG2RAD); - info->m_cy = cs*(cos(info->m_aa*DEG2RAD)-cos(info->m_cc*DEG2RAD)*cos(info->m_bb*DEG2RAD)) - /sin(info->m_cc*DEG2RAD); - info->m_cx = sqrt(cs*cs - info->m_cz*info->m_cz - info->m_cy*info->m_cy); - */ - - /* - // victor 1 - info->m_ax = as; - info->m_ay = 0; - info->m_az = 0; - info->m_bx = as*cos(info->m_cc*DEG2RAD); - info->m_by = as*sin(info->m_cc*DEG2RAD); - info->m_bz = 0; - info->m_cx = 0; - info->m_cy = 0; - info->m_cz = cs; - */ - /* - // victor 2 - info->m_ax = as*cos(0.5*info->m_cc*DEG2RAD); - info->m_ay = -as*sin(0.5*info->m_cc*DEG2RAD); - info->m_az = 0; - info->m_bx = as*cos(0.5*info->m_cc*DEG2RAD); - info->m_by = as*sin(0.5*info->m_cc*DEG2RAD); - info->m_bz = 0; - info->m_cx = 0; - info->m_cy = 0; - info->m_cz = cs; - */ - - // miguel - info->m_ax = as*sin(0.5*info->m_cc*DEG2RAD); - info->m_ay = as*cos(0.5*info->m_cc*DEG2RAD); - info->m_az = 0; - info->m_bx = -as*sin(0.5*info->m_cc*DEG2RAD); - info->m_by = as*cos(0.5*info->m_cc*DEG2RAD); - info->m_bz = 0; - info->m_cx = 0; - info->m_cy = 0; - info->m_cz = cs; - - printf("l3\n"); - fflush(stderr); - - printf("Texture: %s structure a=%g b=%g c=%g aa=%g bb=%g cc=%g ", - (flag ? "INC" : SC_file), as, bs, cs, info->m_aa, info->m_bb, info->m_cc); - } else { - if (!info->recip) { - printf("Texture: %s structure a=[%g,%g,%g] b=[%g,%g,%g] c=[%g,%g,%g] ", - (flag ? "INC" : SC_file), info->m_ax ,info->m_ay ,info->m_az, - info->m_bx ,info->m_by ,info->m_bz, - info->m_cx ,info->m_cy ,info->m_cz); - } else { - printf("Texture: %s structure a*=[%g,%g,%g] b*=[%g,%g,%g] c*=[%g,%g,%g] ", - (flag ? "INC" : SC_file), info->m_ax ,info->m_ay ,info->m_az, - info->m_bx ,info->m_by ,info->m_bz, - info->m_cx ,info->m_cy ,info->m_cz); - } - } + int + precomputeProbPhiq (struct hkl_data_texture* L, struct legendre* lgdr) { + int i, j, nctq, nphiq; + double dctq, dphiq; + double *ctq, *phiq, **probQ; + char fn[500]; + FILE* filep; - //Compute reciprocal or direct lattice vectors. - if (!info->recip) { - vec_prod(tmp_x, tmp_y, tmp_z, - info->m_bx, info->m_by, info->m_bz, - info->m_cx, info->m_cy, info->m_cz); - info->V0 = fabs(scalar_prod(info->m_ax, info->m_ay, info->m_az, - tmp_x, tmp_y, tmp_z)); - printf("V0=%g\n", info->V0); - info->asx = 2*PI/info->V0*tmp_x; - info->asy = 2*PI/info->V0*tmp_y; - info->asz = 2*PI/info->V0*tmp_z; - - vec_prod(tmp_x, tmp_y, tmp_z, info->m_cx, info->m_cy, info->m_cz, - info->m_ax, info->m_ay, info->m_az); - info->bsx = 2*PI/info->V0*tmp_x; - info->bsy = 2*PI/info->V0*tmp_y; - info->bsz = 2*PI/info->V0*tmp_z; - - vec_prod(tmp_x, tmp_y, tmp_z, info->m_ax, info->m_ay, info->m_az, - info->m_bx, info->m_by, info->m_bz); - info->csx = 2*PI/info->V0*tmp_x; - info->csy = 2*PI/info->V0*tmp_y; - info->csz = 2*PI/info->V0*tmp_z; - } else { - info->asx = info->m_ax; - info->asy = info->m_ay; - info->asz = info->m_az; - info->bsx = info->m_bx; - info->bsy = info->m_by; - info->bsz = info->m_bz; - info->csx = info->m_cx; - info->csy = info->m_cy; - info->csz = info->m_cz; - - vec_prod(tmp_x, tmp_y, tmp_z, - info->bsx/(2*PI), info->bsy/(2*PI), info->bsz/(2*PI), - info->csx/(2*PI), info->csy/(2*PI), info->csz/(2*PI)); - info->V0 = 1/fabs(scalar_prod(info->asx/(2*PI), info->asy/(2*PI), - info->asz/(2*PI), tmp_x, tmp_y, tmp_z)); - printf("V0=%g\n", info->V0); - - //compute the direct cell parameters, for completeness - info->m_ax = tmp_x*info->V0; - info->m_ay = tmp_y*info->V0; - info->m_az = tmp_z*info->V0; - vec_prod(tmp_x, tmp_y, tmp_z,info->csx/(2*PI), info->csy/(2*PI), info->csz/(2*PI), - info->asx/(2*PI), info->asy/(2*PI), info->asz/(2*PI)); - - info->m_bx = tmp_x*info->V0; - info->m_by = tmp_y*info->V0; - info->m_bz = tmp_z*info->V0; - vec_prod(tmp_x, tmp_y, tmp_z,info->asx/(2*PI), info->asy/(2*PI), info->asz/(2*PI), - info->bsx/(2*PI), info->bsy/(2*PI), info->bsz/(2*PI)); - - info->m_cx = tmp_x*info->V0; - info->m_cy = tmp_y*info->V0; - info->m_cz = tmp_z*info->V0; - } + nctq = L->nctq; + nphiq = L->nphiq; + ctq = (double*)malloc (nctq * sizeof (double)); + phiq = (double*)malloc (nphiq * sizeof (double)); + probQ = (double**)malloc (nctq * sizeof (double*)); + for (i = 0; i < nctq; i++) { + probQ[i] = (double*)malloc (nphiq * sizeof (double)); + } - if (!info->column_order[0] || !info->column_order[1] || !info->column_order[2]) { - fprintf(stderr,"Texture: Error: Wrong h,k,l column definition\n"); - return(0); - } - if (!info->column_order[3] && !info->column_order[4]) { - fprintf(stderr,"Texture: Error: Wrong F,F2 column definition\n"); - return(0); - } + dctq = 2.0 / (nctq - 1); + dphiq = (2.0 * PI) / (nphiq - 1); - // print crystal info - filep = fopen("crystal.txt","w"); - if(!filep) { - fprintf(stderr,"Texture_process: failed fopen write mode for file 'crystal.txt'. Exit!\n"); - exit(-1); - } - fprintf(filep,"Direct lattice:\n"); - fprintf(filep,"a: %f %f %f\n",info->m_ax,info->m_ay,info->m_az); - fprintf(filep,"b: %f %f %f\n",info->m_bx,info->m_by,info->m_bz); - fprintf(filep,"c: %f %f %f\n",info->m_cx,info->m_cy,info->m_cz); - fprintf(filep,"Reciprocal lattice:\n"); - fprintf(filep,"a: %f %f %f\n",info->asx,info->asy,info->asz); - fprintf(filep,"b: %f %f %f\n",info->bsx,info->bsy,info->bsz); - fprintf(filep,"c: %f %f %f\n",info->csx,info->csy,info->csz); - fclose(filep); - - //allocate hkl_data array - list = (struct hkl_data_texture*)malloc(size*sizeof(struct hkl_data_texture)); - - //write the data to data structures - for (i=0; icolumn_order[0]-1); - k = Table_Index(sTable, i, info->column_order[1]-1); - l = Table_Index(sTable, i, info->column_order[2]-1); - if (info->column_order[3]) { - F2= Table_Index(sTable, i, info->column_order[3]-1); F2 *= F2; - } else if (info->column_order[4]) { - F2= Table_Index(sTable, i, info->column_order[4]-1); - } - mult = Table_Index(sTable, i, info->column_order[5]-1); - list[i].h = h; - list[i].k = k; - list[i].l = l; - list[i].F2 = F2; - list[i].mult = mult; - //Precompute some values - list[i].Gx = h*info->asx + k*info->bsx + l*info->csx; - list[i].Gy = h*info->asy + k*info->bsy + l*info->csy; - list[i].Gz = h*info->asz + k*info->bsz + l*info->csz; - list[i].G = sqrt(list[i].Gx*list[i].Gx + - list[i].Gy*list[i].Gy + - list[i].Gz*list[i].Gz); - list[i].uGx = list[i].Gx/list[i].G; - list[i].uGy = list[i].Gy/list[i].G; - list[i].uGz = list[i].Gz/list[i].G; - list[i].Gct = list[i].uGz; - list[i].Gphi = atan2(list[i].uGy,list[i].uGx); - - // print read information - printf("%d: %d %d %d %f %d %f %f %f\n", - i+1,list[i].h,list[i].k,list[i].l,list[i].F2,list[i].mult, - list[i].G,list[i].Gct,list[i].Gphi); - fflush(stdout); - - //Find two arbitrary axes perpendicular to G and each other. - normal_vec(&b1[0], &b1[1], &b1[2], - list[i].uGx, list[i].uGy, list[i].uGz); - vec_prod(b2[0], b2[1], b2[2], - list[i].uGx, list[i].uGy, list[i].uGz, - b1[0], b1[1], b1[2]); - } - - Table_Free(&sTable); - - //sort the list with increasing G - qsort(list, i, sizeof(struct hkl_data_texture), SX_list_compare_texture); - - info->list = list; - info->num_hkl = i; - - printf("size: %d i: %d info->num_hkl: %d\n",size,i,info->num_hkl); - - return info->num_hkl; -} // read_hkl_data - - -void readFourierCoef(char *filename, struct fourier_coef *c) -{ - int nread, nlines, lmax, i, l, m, n, np, smn, sg; - double x1, x2, x3, x4, x5, rmax, fmn; - struct fourier_coef *ctemp; - char str[100]; - FILE *filep; - - // Note: if the coeeficients have been obtained from mtex - // with l2-normalization option, they have to be multiplied - // by sqrt(2*l+1) - - printf("readCoef: %s\n",filename); - - filep = fopen(filename,"r"); - if(!filep) { - printf("readFourierCoef: fourier coefficient file\n"); - printf("%s\n",filename); - printf("not found. Exiting...\n"); - fflush(stdout); - exit(-1); - } + for (i = 0; i < nctq - 1; i++) { + ctq[i] = -1.0 + i * dctq; + } + ctq[nctq - 1] = 1.0; + for (j = 0; j < nphiq - 1; j++) { + phiq[j] = -PI + j * dphiq; + } + phiq[nphiq - 1] = PI; - str[0]=0; - while(strcmp(str,"#COEFFICIENTS:")!=0) { - nread = fscanf(filep,"%s",str); - if(nread==EOF) { break; } - } - printf("readFourierCoef: %s found\n",str); - lmax = -1; - nlines = 0; - while(1) { - nread = fscanf(filep,"%lf %lf %lf %lf %lf",&x1,&x2,&x3,&x4,&x5); - //printf("nread: %d\n",nread); - if(nread != 5) { break; } - nlines++; - lmax = (int)round(x1); - //printf("lmax: %d\n",lmax); - } + for (i = 0; i < nctq; i++) { + for (j = 0; j < nphiq; j++) { + probQ[i][j] = probPhiq (ctq[i], phiq[j], L, lgdr); + } + } - printf("readCoef: lmax = %d\n",lmax); - - if(lmax < 0) { - printf("readCoef: lmax < 0.\n"); - printf("lmax = %d\n",lmax); - printf("Probably coef file\n %s\nis wrong\n",filename); - printf("Check if the line\n"); - printf("#COEFFICIENTS:\n"); - printf("with no spaces or other characters) is exactly"); - printf(" present just above the data\n"); - printf("Exiting...\n"); - exit(-1); - } + /* + sprintf(fn,"probQ_precomputed_%d_%d_%d.txt",L->h,L->k,L->l); + filep = fopen(fn,"a"); + for(i=0;ictq = ctq; + L->phiq = phiq; + L->probQ = probQ; + + return 0; + } + + // end sampling + + /////////////////////////// + //// Input - Output // + /////////////////////////// + + int + read_hkl_data_texture (char* SC_file, struct hkl_info_struct_texture* info) { + struct hkl_data_texture* list = NULL; + int size = 0; + t_Table sTable; // + int i = 0; + double tmp_x, tmp_y, tmp_z; + char** parsing; + char flag = 0; + double nb_atoms = 1; + double h = 0, k = 0, l = 0, F2 = 0; + int mult = -1; + double b1[3], b2[3]; + FILE* filep; + + if (!SC_file || !strlen (SC_file) || !strcmp (SC_file, "NULL") || !strcmp (SC_file, "0")) { + info->num_hkl = 0; + flag = 1; + } - if(np != nlines) { - printf("readCoef: number of lines in coef file\n %s\n",filename); - printf("different than expected\n"); - printf("lmax: %d np: %d nlines: %d\n",lmax,np,nlines); - printf("Exiting...\n"); - exit(-1); - } + if (flag) { + return -1; + } - printf("readFourierCoef: lmax: %d np: %d nlines: %d\n",lmax,np,nlines); + // Read the table - if(c->lmax>=0) { - printf("readCoef: using lmax = %d provided by the user\n",c->lmax); - if(lmax>c->lmax) { - lmax = c->lmax; + Table_Read (&sTable, SC_file, 1); // read 1st block data from SC_file into sTable + if (sTable.columns < 5) { + fprintf (stderr, "Texture: Error: The number of columns in %s should be", SC_file); + fprintf (stderr, " at least %d for [h,k,l,F2,j]\n", 5); + return (0); + } + if (!sTable.rows) { + fprintf (stderr, "Texture: Error: The number of rows in %s should be at least %d\n", SC_file, 1); + return 0; } else { - printf("readCoef: lmax = %d from file smaller than required lmax = %d\n", - lmax,c->lmax); - printf("readCoef: using lmax from file\n"); + size = sTable.rows; } - } - - allocateFourierCoef(lmax,c); - printf("readCoef: using lmax = %d\n",c->lmax); + // parsing of header + parsing = Table_ParseHeader (sTable.header, "sigma_abs", "sigma_a ", "sigma_inc", "sigma_i ", "column_h", "column_k", "column_l", "column_F ", "column_F2", + "column_j", "Delta_d/d", "lattice_a ", "lattice_b ", "lattice_c ", "lattice_aa", "lattice_bb", "lattice_cc", "nb_atoms", + "multiplicity", NULL); + + printf ("l0\n"); + fflush (stderr); + + if (parsing) { + if (parsing[0] && !info->sigma_a) + info->sigma_a = atof (parsing[0]); + if (parsing[1] && !info->sigma_a) + info->sigma_a = atof (parsing[1]); + if (parsing[2] && !info->sigma_i) + info->sigma_i = atof (parsing[2]); + if (parsing[3] && !info->sigma_i) + info->sigma_i = atof (parsing[3]); + if (parsing[4]) + info->column_order[0] = atoi (parsing[4]); + if (parsing[5]) + info->column_order[1] = atoi (parsing[5]); + if (parsing[6]) + info->column_order[2] = atoi (parsing[6]); + if (parsing[7]) + info->column_order[3] = atoi (parsing[7]); + if (parsing[8]) + info->column_order[4] = atoi (parsing[8]); + if (parsing[9]) + info->column_order[5] = atoi (parsing[9]); + if (parsing[10] && info->m_delta_d_d < 0) + info->m_delta_d_d = atof (parsing[10]); + if (parsing[11] && !info->m_a) + info->m_a = atof (parsing[11]); + if (parsing[12] && !info->m_b) + info->m_b = atof (parsing[12]); + if (parsing[13] && !info->m_c) + info->m_c = atof (parsing[13]); + if (parsing[14] && !info->m_aa) + info->m_aa = atof (parsing[14]); + if (parsing[15] && !info->m_bb) + info->m_bb = atof (parsing[15]); + if (parsing[16] && !info->m_cc) + info->m_cc = atof (parsing[16]); + if (parsing[17]) + nb_atoms = atof (parsing[17]); + if (parsing[18]) + nb_atoms = atof (parsing[18]); + for (i = 0; i <= 18; i++) { + if (parsing[i]) { + free (parsing[i]); + } + } + free (parsing); + } - np = 0; - for(l=0;l<=lmax;l++) { - np += (2*l+1)*(2*l+1); - } + printf ("l1\n"); + fflush (stderr); + if (nb_atoms > 1) { + info->sigma_a *= nb_atoms; + info->sigma_i *= nb_atoms; + } - rewind(filep); - str[0]=0; - while(strcmp(str,"#COEFFICIENTS:")!=0) { - nread = fscanf(filep,"%s",str); - if(nread==EOF) { break; } - } - printf("readFourierCoef: %s found\n",str); - for(i=1;i<=np;i++) { - nread=fscanf(filep,"%lf %lf %lf %lf %lf",&x1,&x2,&x3,&x4,&x5); - l = (int)round(x1); - n = (int)round(x2); // TRANSPOSEE - m = (int)round(x3); // TRANSPOSEE - x5 = -x5; // conjugate - if(m>=0 && n>=0) { - smn = 1; - } else if (m>=0 && n<0) { - if((-n)%2) { smn = -1; } else { smn = 1; } - } else if (m<0 && n>=0) { - if((-m)%2) { smn = -1; } else { smn = 1; } + // special cases for the structure definition (means we specify by hand the vectors) + if (info->m_ax || info->m_ay || info->m_az) { + info->m_a = 0; + } + if (info->m_bx || info->m_by || info->m_bz) { + info->m_b = 0; + } + if (info->m_cx || info->m_cy || info->m_cz) { + info->m_c = 0; + } + + // compute the norm from vector a if missing + if (info->m_ax || info->m_ay || info->m_az) { + double as = sqrt (info->m_ax * info->m_ax + info->m_ay * info->m_ay + info->m_az * info->m_az); + if (!info->m_bx && !info->m_by && !info->m_bz) { + info->m_a = info->m_b = as; + } + if (!info->m_cx && !info->m_cy && !info->m_cz) { + info->m_a = info->m_c = as; + } + } + if (info->m_a && !info->m_b) { + info->m_b = info->m_a; + } + if (info->m_b && !info->m_c) { + info->m_c = info->m_b; + } + + // compute the lattice angles if not set from data file. Not used when in vector mode. + if (info->m_a && !info->m_aa) { + info->m_aa = 90; + } + if (info->m_aa && !info->m_bb) { + info->m_bb = info->m_aa; + } + if (info->m_bb && !info->m_cc) { + info->m_cc = info->m_bb; + } + + // parameters consistency checks + if (!info->m_ax && !info->m_ay && !info->m_az && !info->m_a) { + fprintf (stderr, "Texture: Error: Wrong a lattice vector definition\n"); + return (0); + } + if (!info->m_bx && !info->m_by && !info->m_bz && !info->m_b) { + fprintf (stderr, "Texture: Error: Wrong b lattice vector definition\n"); + return (0); + } + if (!info->m_cx && !info->m_cy && !info->m_cz && !info->m_c) { + fprintf (stderr, "Texture: Error: Wrong c lattice vector definition\n"); + return (0); + } + if (info->m_aa && info->m_bb && info->m_cc && info->recip) { + fprintf (stderr, "Texture: Error: Selecting reciprocal cell and angles is unmeaningful\n"); + return (0); + } + + printf ("l2\n"); + fflush (stderr); + + // when lengths a,b,c + angles are given (instead of vectors a,b,c) + if (info->m_aa && info->m_bb && info->m_cc) { + double as, bs, cs; + if (info->m_a) { + as = info->m_a; + } else { + as = sqrt (info->m_ax * info->m_ax + info->m_ay * info->m_ay + info->m_az * info->m_az); + } + if (info->m_b) { + bs = info->m_b; + } else { + bs = sqrt (info->m_bx * info->m_bx + info->m_by * info->m_by + info->m_bz * info->m_bz); + } + if (info->m_c) { + cs = info->m_c; + } else { + cs = sqrt (info->m_cx * info->m_cx + info->m_cy * info->m_cy + info->m_cz * info->m_cz); + } + /* + info->m_bz = as; info->m_by = 0; info->m_bx = 0; + info->m_az = bs*cos(info->m_cc*DEG2RAD); + info->m_ay = bs*sin(info->m_cc*DEG2RAD); + info->m_ax = 0; + info->m_cz = cs*cos(info->m_bb*DEG2RAD); + info->m_cy = cs*(cos(info->m_aa*DEG2RAD)-cos(info->m_cc*DEG2RAD)*cos(info->m_bb*DEG2RAD)) + /sin(info->m_cc*DEG2RAD); + info->m_cx = sqrt(cs*cs - info->m_cz*info->m_cz - info->m_cy*info->m_cy); + */ + + /* + // victor 1 + info->m_ax = as; + info->m_ay = 0; + info->m_az = 0; + info->m_bx = as*cos(info->m_cc*DEG2RAD); + info->m_by = as*sin(info->m_cc*DEG2RAD); + info->m_bz = 0; + info->m_cx = 0; + info->m_cy = 0; + info->m_cz = cs; + */ + /* + // victor 2 + info->m_ax = as*cos(0.5*info->m_cc*DEG2RAD); + info->m_ay = -as*sin(0.5*info->m_cc*DEG2RAD); + info->m_az = 0; + info->m_bx = as*cos(0.5*info->m_cc*DEG2RAD); + info->m_by = as*sin(0.5*info->m_cc*DEG2RAD); + info->m_bz = 0; + info->m_cx = 0; + info->m_cy = 0; + info->m_cz = cs; + */ + + // miguel + info->m_ax = as * sin (0.5 * info->m_cc * DEG2RAD); + info->m_ay = as * cos (0.5 * info->m_cc * DEG2RAD); + info->m_az = 0; + info->m_bx = -as * sin (0.5 * info->m_cc * DEG2RAD); + info->m_by = as * cos (0.5 * info->m_cc * DEG2RAD); + info->m_bz = 0; + info->m_cx = 0; + info->m_cy = 0; + info->m_cz = cs; + + printf ("l3\n"); + fflush (stderr); + + printf ("Texture: %s structure a=%g b=%g c=%g aa=%g bb=%g cc=%g ", (flag ? "INC" : SC_file), as, bs, cs, info->m_aa, info->m_bb, info->m_cc); } else { - if((-m-n)%2) { smn = -1; } else { smn = 1; } + if (!info->recip) { + printf ("Texture: %s structure a=[%g,%g,%g] b=[%g,%g,%g] c=[%g,%g,%g] ", (flag ? "INC" : SC_file), info->m_ax, info->m_ay, info->m_az, info->m_bx, + info->m_by, info->m_bz, info->m_cx, info->m_cy, info->m_cz); + } else { + printf ("Texture: %s structure a*=[%g,%g,%g] b*=[%g,%g,%g] c*=[%g,%g,%g] ", (flag ? "INC" : SC_file), info->m_ax, info->m_ay, info->m_az, info->m_bx, + info->m_by, info->m_bz, info->m_cx, info->m_cy, info->m_cz); + } } - //fmn = smn*sqrt(2.*l+1.); // with l2-normalization - fmn = smn; // without l2-normalization - (c->cr)[l][l+m][l+n] = fmn*x4; - (c->ci)[l][l+m][l+n] = fmn*x5; - } - fclose(filep); - - // check reality of ODF - filep = fopen("coef_original.txt","w"); - if(!filep) { - printf("readFourierCoef: fourier coefficient file\n"); - printf("%s\n",filename); - printf("not found. Exiting...\n"); - fflush(stdout); - exit(-1); - } - rmax = 0; - for(l=0;l<=lmax;l++) { - for(m=-l;m<=l;m++) { - for(n=-l;n<=l;n++) { - x1 = (c->cr)[l][l+m][l+n]; - x2 = (c->ci)[l][l+m][l+n]; - x3 = (c->cr)[l][l-m][l-n]; - x4 = (c->ci)[l][l-m][l-n]; - if(abs(m-n)%2) { x3 = -x3; x4 = -x4; } - x5 = sqrt(pow(x1-x3,2)+pow(-x2-x4,2)); - //fprintf(filep,"%d %d %d %.6e %.6e %.6e %.6e %.6e\n", - // l,m,n,x1,x2,x3,x4,x5); - if(x5>rmax) { rmax = x5; } + + // Compute reciprocal or direct lattice vectors. + if (!info->recip) { + vec_prod (tmp_x, tmp_y, tmp_z, info->m_bx, info->m_by, info->m_bz, info->m_cx, info->m_cy, info->m_cz); + info->V0 = fabs (scalar_prod (info->m_ax, info->m_ay, info->m_az, tmp_x, tmp_y, tmp_z)); + printf ("V0=%g\n", info->V0); + info->asx = 2 * PI / info->V0 * tmp_x; + info->asy = 2 * PI / info->V0 * tmp_y; + info->asz = 2 * PI / info->V0 * tmp_z; + + vec_prod (tmp_x, tmp_y, tmp_z, info->m_cx, info->m_cy, info->m_cz, info->m_ax, info->m_ay, info->m_az); + info->bsx = 2 * PI / info->V0 * tmp_x; + info->bsy = 2 * PI / info->V0 * tmp_y; + info->bsz = 2 * PI / info->V0 * tmp_z; + + vec_prod (tmp_x, tmp_y, tmp_z, info->m_ax, info->m_ay, info->m_az, info->m_bx, info->m_by, info->m_bz); + info->csx = 2 * PI / info->V0 * tmp_x; + info->csy = 2 * PI / info->V0 * tmp_y; + info->csz = 2 * PI / info->V0 * tmp_z; + } else { + info->asx = info->m_ax; + info->asy = info->m_ay; + info->asz = info->m_az; + info->bsx = info->m_bx; + info->bsy = info->m_by; + info->bsz = info->m_bz; + info->csx = info->m_cx; + info->csy = info->m_cy; + info->csz = info->m_cz; + + vec_prod (tmp_x, tmp_y, tmp_z, info->bsx / (2 * PI), info->bsy / (2 * PI), info->bsz / (2 * PI), info->csx / (2 * PI), info->csy / (2 * PI), + info->csz / (2 * PI)); + info->V0 = 1 / fabs (scalar_prod (info->asx / (2 * PI), info->asy / (2 * PI), info->asz / (2 * PI), tmp_x, tmp_y, tmp_z)); + printf ("V0=%g\n", info->V0); + + // compute the direct cell parameters, for completeness + info->m_ax = tmp_x * info->V0; + info->m_ay = tmp_y * info->V0; + info->m_az = tmp_z * info->V0; + vec_prod (tmp_x, tmp_y, tmp_z, info->csx / (2 * PI), info->csy / (2 * PI), info->csz / (2 * PI), info->asx / (2 * PI), info->asy / (2 * PI), + info->asz / (2 * PI)); + + info->m_bx = tmp_x * info->V0; + info->m_by = tmp_y * info->V0; + info->m_bz = tmp_z * info->V0; + vec_prod (tmp_x, tmp_y, tmp_z, info->asx / (2 * PI), info->asy / (2 * PI), info->asz / (2 * PI), info->bsx / (2 * PI), info->bsy / (2 * PI), + info->bsz / (2 * PI)); + + info->m_cx = tmp_x * info->V0; + info->m_cy = tmp_y * info->V0; + info->m_cz = tmp_z * info->V0; + } + + if (!info->column_order[0] || !info->column_order[1] || !info->column_order[2]) { + fprintf (stderr, "Texture: Error: Wrong h,k,l column definition\n"); + return (0); + } + if (!info->column_order[3] && !info->column_order[4]) { + fprintf (stderr, "Texture: Error: Wrong F,F2 column definition\n"); + return (0); + } + + // print crystal info + filep = fopen ("crystal.txt", "w"); + if (!filep) { + fprintf (stderr, "Texture_process: failed fopen write mode for file 'crystal.txt'. Exit!\n"); + exit (-1); + } + fprintf (filep, "Direct lattice:\n"); + fprintf (filep, "a: %f %f %f\n", info->m_ax, info->m_ay, info->m_az); + fprintf (filep, "b: %f %f %f\n", info->m_bx, info->m_by, info->m_bz); + fprintf (filep, "c: %f %f %f\n", info->m_cx, info->m_cy, info->m_cz); + fprintf (filep, "Reciprocal lattice:\n"); + fprintf (filep, "a: %f %f %f\n", info->asx, info->asy, info->asz); + fprintf (filep, "b: %f %f %f\n", info->bsx, info->bsy, info->bsz); + fprintf (filep, "c: %f %f %f\n", info->csx, info->csy, info->csz); + fclose (filep); + + // allocate hkl_data array + list = (struct hkl_data_texture*)malloc (size * sizeof (struct hkl_data_texture)); + + // write the data to data structures + for (i = 0; i < size; i++) { + h = Table_Index (sTable, i, info->column_order[0] - 1); + k = Table_Index (sTable, i, info->column_order[1] - 1); + l = Table_Index (sTable, i, info->column_order[2] - 1); + if (info->column_order[3]) { + F2 = Table_Index (sTable, i, info->column_order[3] - 1); + F2 *= F2; + } else if (info->column_order[4]) { + F2 = Table_Index (sTable, i, info->column_order[4] - 1); } + mult = Table_Index (sTable, i, info->column_order[5] - 1); + list[i].h = h; + list[i].k = k; + list[i].l = l; + list[i].F2 = F2; + list[i].mult = mult; + // Precompute some values + list[i].Gx = h * info->asx + k * info->bsx + l * info->csx; + list[i].Gy = h * info->asy + k * info->bsy + l * info->csy; + list[i].Gz = h * info->asz + k * info->bsz + l * info->csz; + list[i].G = sqrt (list[i].Gx * list[i].Gx + list[i].Gy * list[i].Gy + list[i].Gz * list[i].Gz); + list[i].uGx = list[i].Gx / list[i].G; + list[i].uGy = list[i].Gy / list[i].G; + list[i].uGz = list[i].Gz / list[i].G; + list[i].Gct = list[i].uGz; + list[i].Gphi = atan2 (list[i].uGy, list[i].uGx); + + // print read information + printf ("%d: %d %d %d %f %d %f %f %f\n", i + 1, list[i].h, list[i].k, list[i].l, list[i].F2, list[i].mult, list[i].G, list[i].Gct, list[i].Gphi); + fflush (stdout); + + // Find two arbitrary axes perpendicular to G and each other. + normal_vec (&b1[0], &b1[1], &b1[2], list[i].uGx, list[i].uGy, list[i].uGz); + vec_prod (b2[0], b2[1], b2[2], list[i].uGx, list[i].uGy, list[i].uGz, b1[0], b1[1], b1[2]); } - } - fprintf(filep,"#diff max: %.6e\n",rmax); - fclose(filep); - if(rmax>1.0e-6) { - printf("Fourier coefficients do not satisfy the reality condition of ODF\n"); - printf("with sufficient accuracy: %.6e\n",rmax); - printf("Imposing it\n"); + Table_Free (&sTable); - ctemp = (struct fourier_coef *)malloc(sizeof(struct fourier_coef)); - allocateFourierCoef(lmax,ctemp); - for(l=0;l<=lmax;l++) { - for(m=-l;m<=l;m++) { - for(n=-l;n<=l;n++) { - (ctemp->cr)[l][l+m][l+n] = -sqrt(-1.0); - (ctemp->ci)[l][l+m][l+n] = -sqrt(-1.0); + // sort the list with increasing G + qsort (list, i, sizeof (struct hkl_data_texture), SX_list_compare_texture); + + info->list = list; + info->num_hkl = i; + + printf ("size: %d i: %d info->num_hkl: %d\n", size, i, info->num_hkl); + + return info->num_hkl; + } // read_hkl_data + + void + readFourierCoef (char* filename, struct fourier_coef* c) { + int nread, nlines, lmax, i, l, m, n, np, smn, sg; + double x1, x2, x3, x4, x5, rmax, fmn; + struct fourier_coef* ctemp; + char str[100]; + FILE* filep; + + // Note: if the coeeficients have been obtained from mtex + // with l2-normalization option, they have to be multiplied + // by sqrt(2*l+1) + + printf ("readCoef: %s\n", filename); + + filep = fopen (filename, "r"); + if (!filep) { + printf ("readFourierCoef: fourier coefficient file\n"); + printf ("%s\n", filename); + printf ("not found. Exiting...\n"); + fflush (stdout); + exit (-1); + } + + str[0] = 0; + while (strcmp (str, "#COEFFICIENTS:") != 0) { + nread = fscanf (filep, "%s", str); + if (nread == EOF) { + break; + } + } + printf ("readFourierCoef: %s found\n", str); + lmax = -1; + nlines = 0; + while (1) { + nread = fscanf (filep, "%lf %lf %lf %lf %lf", &x1, &x2, &x3, &x4, &x5); + // printf("nread: %d\n",nread); + if (nread != 5) { + break; + } + nlines++; + lmax = (int)round (x1); + // printf("lmax: %d\n",lmax); + } + + printf ("readCoef: lmax = %d\n", lmax); + + if (lmax < 0) { + printf ("readCoef: lmax < 0.\n"); + printf ("lmax = %d\n", lmax); + printf ("Probably coef file\n %s\nis wrong\n", filename); + printf ("Check if the line\n"); + printf ("#COEFFICIENTS:\n"); + printf ("with no spaces or other characters) is exactly"); + printf (" present just above the data\n"); + printf ("Exiting...\n"); + exit (-1); + } + + np = 0; + for (l = 0; l <= lmax; l++) { + np += (2 * l + 1) * (2 * l + 1); + } + + if (np != nlines) { + printf ("readCoef: number of lines in coef file\n %s\n", filename); + printf ("different than expected\n"); + printf ("lmax: %d np: %d nlines: %d\n", lmax, np, nlines); + printf ("Exiting...\n"); + exit (-1); + } + + printf ("readFourierCoef: lmax: %d np: %d nlines: %d\n", lmax, np, nlines); + + if (c->lmax >= 0) { + printf ("readCoef: using lmax = %d provided by the user\n", c->lmax); + if (lmax > c->lmax) { + lmax = c->lmax; + } else { + printf ("readCoef: lmax = %d from file smaller than required lmax = %d\n", lmax, c->lmax); + printf ("readCoef: using lmax from file\n"); + } + } + + allocateFourierCoef (lmax, c); + + printf ("readCoef: using lmax = %d\n", c->lmax); + + np = 0; + for (l = 0; l <= lmax; l++) { + np += (2 * l + 1) * (2 * l + 1); + } + + rewind (filep); + str[0] = 0; + while (strcmp (str, "#COEFFICIENTS:") != 0) { + nread = fscanf (filep, "%s", str); + if (nread == EOF) { + break; + } + } + printf ("readFourierCoef: %s found\n", str); + for (i = 1; i <= np; i++) { + nread = fscanf (filep, "%lf %lf %lf %lf %lf", &x1, &x2, &x3, &x4, &x5); + l = (int)round (x1); + n = (int)round (x2); // TRANSPOSEE + m = (int)round (x3); // TRANSPOSEE + x5 = -x5; // conjugate + if (m >= 0 && n >= 0) { + smn = 1; + } else if (m >= 0 && n < 0) { + if ((-n) % 2) { + smn = -1; + } else { + smn = 1; + } + } else if (m < 0 && n >= 0) { + if ((-m) % 2) { + smn = -1; + } else { + smn = 1; + } + } else { + if ((-m - n) % 2) { + smn = -1; + } else { + smn = 1; } } + // fmn = smn*sqrt(2.*l+1.); // with l2-normalization + fmn = smn; // without l2-normalization + (c->cr)[l][l + m][l + n] = fmn * x4; + (c->ci)[l][l + m][l + n] = fmn * x5; } - for(l=0;l<=lmax;l++) { - for(m=l;m>=-l;m--) { - for(n=l;n>=-l;n--) { - if( isnan( (ctemp->cr)[l][l+m][l+n] ) ) { - (ctemp->cr)[l][l+m][l+n] = (c->cr)[l][l+m][l+n]; - (ctemp->ci)[l][l+m][l+n] = (c->ci)[l][l+m][l+n]; - if( abs(m-n)%2 ) { sg = -1; } else { sg = 1; } - (ctemp->cr)[l][l-m][l-n] = sg*(ctemp->cr)[l][l+m][l+n]; - (ctemp->ci)[l][l-m][l-n] = -sg*(ctemp->ci)[l][l+m][l+n]; + fclose (filep); + + // check reality of ODF + filep = fopen ("coef_original.txt", "w"); + if (!filep) { + printf ("readFourierCoef: fourier coefficient file\n"); + printf ("%s\n", filename); + printf ("not found. Exiting...\n"); + fflush (stdout); + exit (-1); + } + rmax = 0; + for (l = 0; l <= lmax; l++) { + for (m = -l; m <= l; m++) { + for (n = -l; n <= l; n++) { + x1 = (c->cr)[l][l + m][l + n]; + x2 = (c->ci)[l][l + m][l + n]; + x3 = (c->cr)[l][l - m][l - n]; + x4 = (c->ci)[l][l - m][l - n]; + if (abs (m - n) % 2) { + x3 = -x3; + x4 = -x4; + } + x5 = sqrt (pow (x1 - x3, 2) + pow (-x2 - x4, 2)); + // fprintf(filep,"%d %d %d %.6e %.6e %.6e %.6e %.6e\n", + // l,m,n,x1,x2,x3,x4,x5); + if (x5 > rmax) { + rmax = x5; } } } } - for(l=0;l<=lmax;l++) { - for(m=-l;m<=l;m++) { - for(n=-l;n<=l;n++) { - (c->cr)[l][l+m][l+n] = (ctemp->cr)[l][l+m][l+n]; - (c->ci)[l][l+m][l+n] = (ctemp->ci)[l][l+m][l+n]; - if(m==0 && n==0) { (c->ci)[l][l+m][l+n] = 0; } // this has to be real + fprintf (filep, "#diff max: %.6e\n", rmax); + fclose (filep); + + if (rmax > 1.0e-6) { + printf ("Fourier coefficients do not satisfy the reality condition of ODF\n"); + printf ("with sufficient accuracy: %.6e\n", rmax); + printf ("Imposing it\n"); + + ctemp = (struct fourier_coef*)malloc (sizeof (struct fourier_coef)); + allocateFourierCoef (lmax, ctemp); + for (l = 0; l <= lmax; l++) { + for (m = -l; m <= l; m++) { + for (n = -l; n <= l; n++) { + (ctemp->cr)[l][l + m][l + n] = -sqrt (-1.0); + (ctemp->ci)[l][l + m][l + n] = -sqrt (-1.0); + } } } + for (l = 0; l <= lmax; l++) { + for (m = l; m >= -l; m--) { + for (n = l; n >= -l; n--) { + if (isnan ((ctemp->cr)[l][l + m][l + n])) { + (ctemp->cr)[l][l + m][l + n] = (c->cr)[l][l + m][l + n]; + (ctemp->ci)[l][l + m][l + n] = (c->ci)[l][l + m][l + n]; + if (abs (m - n) % 2) { + sg = -1; + } else { + sg = 1; + } + (ctemp->cr)[l][l - m][l - n] = sg * (ctemp->cr)[l][l + m][l + n]; + (ctemp->ci)[l][l - m][l - n] = -sg * (ctemp->ci)[l][l + m][l + n]; + } + } + } + } + for (l = 0; l <= lmax; l++) { + for (m = -l; m <= l; m++) { + for (n = -l; n <= l; n++) { + (c->cr)[l][l + m][l + n] = (ctemp->cr)[l][l + m][l + n]; + (c->ci)[l][l + m][l + n] = (ctemp->ci)[l][l + m][l + n]; + if (m == 0 && n == 0) { + (c->ci)[l][l + m][l + n] = 0; + } // this has to be real + } + } + } + freeFourierCoef (ctemp); + free (ctemp); + + // print new coefficients + rmax = 0; + filep = fopen ("coef_modified.txt", "w"); + if (!filep) { + fprintf (stderr, "Texture_process: failed fopen write mode for file 'coef_modified.txt'. Exit!\n"); + exit (-1); + } + for (l = 0; l <= lmax; l++) { + for (m = -l; m <= l; m++) { + for (n = -l; n <= l; n++) { + x1 = (c->cr)[l][l + m][l + n]; + x2 = (c->ci)[l][l + m][l + n]; + x3 = (c->cr)[l][l - m][l - n]; + x4 = (c->ci)[l][l - m][l - n]; + if (abs (m - n) % 2) { + x3 = -x3; + x4 = -x4; + } + x5 = sqrt (pow (x1 - x3, 2) + pow (-x2 - x4, 2)); + fprintf (filep, "%d %d %d %.6e %.6e %.6e %.6e %.6e\n", l, m, n, x1, x2, x3, x4, x5); + if (x5 > rmax) { + rmax = x5; + } + } + } + } + fprintf (filep, "#diff max: %.6e\n", rmax); + fclose (filep); } - freeFourierCoef(ctemp); - free(ctemp); - - // print new coefficients - rmax = 0; - filep = fopen("coef_modified.txt","w"); - if(!filep) { - fprintf(stderr,"Texture_process: failed fopen write mode for file 'coef_modified.txt'. Exit!\n"); - exit(-1); - } - for(l=0;l<=lmax;l++) { - for(m=-l;m<=l;m++) { - for(n=-l;n<=l;n++) { - x1 = (c->cr)[l][l+m][l+n]; - x2 = (c->ci)[l][l+m][l+n]; - x3 = (c->cr)[l][l-m][l-n]; - x4 = (c->ci)[l][l-m][l-n]; - if( abs(m-n)%2 ) { x3 = -x3; x4 = -x4; } - x5 = sqrt(pow(x1-x3,2)+pow(-x2-x4,2)); - fprintf(filep,"%d %d %d %.6e %.6e %.6e %.6e %.6e\n", - l,m,n,x1,x2,x3,x4,x5); - if(x5>rmax) { rmax = x5; } + } // readFourierCoef + + void + allocateFourierCoef (int lmax, struct fourier_coef* c) { + int l, m; + if (lmax >= 0) { + c->lmax = lmax; + c->cr = (double***)malloc ((lmax + 1) * sizeof (double)); + c->ci = (double***)malloc ((lmax + 1) * sizeof (double)); + for (l = 0; l <= lmax; l++) { + (c->cr)[l] = (double**)malloc ((2 * l + 1) * sizeof (double)); + (c->ci)[l] = (double**)malloc ((2 * l + 1) * sizeof (double)); + for (m = -l; m <= l; m++) { + (c->cr)[l][m + l] = (double*)malloc ((2 * l + 1) * sizeof (double)); + (c->ci)[l][m + l] = (double*)malloc ((2 * l + 1) * sizeof (double)); } } + } else { + c->lmax = -1; + c->cr = NULL; + c->ci = NULL; } - fprintf(filep,"#diff max: %.6e\n",rmax); - fclose(filep); - } -} // readFourierCoef - -void allocateFourierCoef(int lmax, struct fourier_coef *c) -{ - int l, m; - if(lmax >= 0) { - c->lmax = lmax; - c->cr = (double ***)malloc((lmax+1)*sizeof(double)); - c->ci = (double ***)malloc((lmax+1)*sizeof(double)); - for(l=0;l<=lmax;l++) { - (c->cr)[l] = (double **)malloc((2*l+1)*sizeof(double)); - (c->ci)[l] = (double **)malloc((2*l+1)*sizeof(double)); - for(m=-l;m<=l;m++) { - (c->cr)[l][m+l] = (double *)malloc((2*l+1)*sizeof(double)); - (c->ci)[l][m+l] = (double *)malloc((2*l+1)*sizeof(double)); + } // allocateFourierCoef + + void + freeFourierCoef (struct fourier_coef* c) { + int l, m; + if (c->cr != NULL) { + for (l = 0; l <= (c->lmax); l++) { + for (m = -l; m <= l; m++) { + free (c->cr[l][m + l]); + free (c->ci[l][m + l]); + } + free (c->cr[l]); + free (c->ci[l]); } + free (c->cr); + free (c->ci); } - } else { - c->lmax = -1; - c->cr = NULL; - c->ci = NULL; - } -} // allocateFourierCoef - -void freeFourierCoef(struct fourier_coef *c) -{ - int l, m; - if(c->cr != NULL) { - for(l=0;l<=(c->lmax);l++) { - for(m=-l;m<=l;m++) { - free(c->cr[l][m+l]); - free(c->ci[l][m+l]); - } - free(c->cr[l]); - free(c->ci[l]); - } - free(c->cr); - free(c->ci); - } -} // freeFourierCoef - -// end Input - Output - -///////////////////////////////////////// -// auxiliary functions -////////////////////////////////////////// - -int SX_list_compare_texture (void const *a, void const *b) -{ - struct hkl_data_texture const *pa = a; - struct hkl_data_texture const *pb = b; - double s = pa->G - pb->G; - - if (!s) { return 0; } else { return (s < 0 ? -1 : 1); } -} // SX_list_compare - -double interp(double x, int n, double *xp, double *yp) -{ - int i, i1, i2; - if(xxp[n-1]) { - printf("interp: x ouside range\n"); - printf("x[0] = %.16e\n",xp[0]); - printf(" x = %.16e\n",x); - printf("x[n-1] = %.16e\n",xp[n-1]); - printf("Exiting...\n"); - fflush(stdout); - exit(-1); - } - i1 = 0; - i2 = n-1; - while(i2-i1>1) { - i = (i1+i2)/2; - if(xp[i]<=x) { i1 = i; } else { i2 = i; } - } - if(i2-i1!=1) { - printf("interp: i2-i1 > 1\n"); - printf("i1: %d i2: %d\n",i1,i2); - printf("x[0] = %.16e\n",xp[0]); - printf(" x = %.16e\n",x); - printf("x[1] = %.16e\n",xp[1]); - printf("Exiting...\n"); - fflush(stdout); - exit(-1); - } - return yp[i1]+((x-xp[i1])/(xp[i2]-xp[i1]))*(yp[i2]-yp[i1]); -} + } // freeFourierCoef + + // end Input - Output -double interp2D(double x, double y, int nx, int ny, double *xp, double *yp, double **fp) -{ - int i, j; - double t, u, f1, f2, f3, f4; + ///////////////////////////////////////// + // auxiliary functions + ////////////////////////////////////////// - i = (int) ((x-xp[0])/(xp[1]-xp[0])); - j = (int) ((y-yp[0])/(yp[1]-yp[0])); + int + SX_list_compare_texture (void const* a, void const* b) { + struct hkl_data_texture const* pa = a; + struct hkl_data_texture const* pb = b; + double s = pa->G - pb->G; - if(i<0 || i>=nx-1) { - if(i==nx-1 && fabs(x-xp[i])<1.0e-6) { - i = i-1; + if (!s) { + return 0; } else { - printf("interp2D: bad i: %d, nx: %d x: %.16e y: %.16e\n",i,nx,x,y); - fflush(stdout); - exit(-1); + return (s < 0 ? -1 : 1); } - } else if(i>0 && x=ny-1) { - if(j==ny-1 && fabs(y-yp[j])<1.0e-6) { - j = j-1; - } else { - printf("interp2D: bad j: %d, ny: %d x: %.16e y: %.16e\n",j,ny,x,y); - fflush(stdout); - exit(-1); - } - } else if(j>0 && y1) { - printf("interp2D: bad t: %.6e, u: %.6e x: %f y: %f i: %d nx: %d\n",t,u,x,y,i,nx); - printf("%f %f %f\n",x,xp[i],xp[i+1]); - fflush(stdout); - //exit(-1); - } - if(u<0 || u>1) { - printf("interp2D: bad u: %.6e, t: %.6e x: %f y: %f j: %d ny: %d\n",u,t,x,y,j,ny); - printf("%f %f %f\n",y,yp[j],yp[j+1]); - printf("\n"); - for(i=0;i xp[n - 1]) { + printf ("interp: x ouside range\n"); + printf ("x[0] = %.16e\n", xp[0]); + printf (" x = %.16e\n", x); + printf ("x[n-1] = %.16e\n", xp[n - 1]); + printf ("Exiting...\n"); + fflush (stdout); + exit (-1); + } + i1 = 0; + i2 = n - 1; + while (i2 - i1 > 1) { + i = (i1 + i2) / 2; + if (xp[i] <= x) { + i1 = i; + } else { + i2 = i; + } + } + if (i2 - i1 != 1) { + printf ("interp: i2-i1 > 1\n"); + printf ("i1: %d i2: %d\n", i1, i2); + printf ("x[0] = %.16e\n", xp[0]); + printf (" x = %.16e\n", x); + printf ("x[1] = %.16e\n", xp[1]); + printf ("Exiting...\n"); + fflush (stdout); + exit (-1); + } + return yp[i1] + ((x - xp[i1]) / (xp[i2] - xp[i1])) * (yp[i2] - yp[i1]); } - return (1-t)*(1-u)*f1 + t*(1-u)*f2 + t*u*f3 + (1-t)*u*f4; -} + double + interp2D (double x, double y, int nx, int ny, double* xp, double* yp, double** fp) { + int i, j; + double t, u, f1, f2, f3, f4; -//////////////////////////////////////// -////// initialization ////// -//////////////////////////////////////// + i = (int)((x - xp[0]) / (xp[1] - xp[0])); + j = (int)((y - yp[0]) / (yp[1] - yp[0])); -int initData(char *coef_fn, char *crystal_fn, struct hkl_info_struct_texture *info, int maxSaved) -{ - int i, j, jj, nread; - int hm, km, lm; // miller indices - char c; - struct fourier_coef *fc; - struct hkl_data_texture *L, *Li; - FILE *filep; + if (i < 0 || i >= nx - 1) { + if (i == nx - 1 && fabs (x - xp[i]) < 1.0e-6) { + i = i - 1; + } else { + printf ("interp2D: bad i: %d, nx: %d x: %.16e y: %.16e\n", i, nx, x, y); + fflush (stdout); + exit (-1); + } + } else if (i > 0 && x < xp[i]) { + i = i - 1; + } - // get fourier coefficients of texture - fc = (struct fourier_coef *)malloc(sizeof(struct fourier_coef)); - fc->lmax = info->lmax; - readFourierCoef(coef_fn,fc); + if (j < 0 || j >= ny - 1) { + if (j == ny - 1 && fabs (y - yp[j]) < 1.0e-6) { + j = j - 1; + } else { + printf ("interp2D: bad j: %d, ny: %d x: %.16e y: %.16e\n", j, ny, x, y); + fflush (stdout); + exit (-1); + } + } else if (j > 0 && y < yp[j]) { + j = j - 1; + } - printf("victor: fourier read. lmax: %d\n",fc->lmax); - fflush(stdout); + f1 = fp[i][j]; + f2 = fp[i + 1][j]; + f3 = fp[i + 1][j + 1]; + f4 = fp[i][j + 1]; - // precompute legendre associated functions - info->lgdr = initLegendre(fc->lmax); + t = (x - xp[i]) / (xp[i + 1] - xp[i]); + u = (y - yp[j]) / (yp[j + 1] - yp[j]); - // crystallographic data - if ( !read_hkl_data_texture(crystal_fn,info) ) { - printf("initData: read_hkl_data_texture returns error\n"); - return 1; - } + if (t < 0 || t > 1) { + printf ("interp2D: bad t: %.6e, u: %.6e x: %f y: %f i: %d nx: %d\n", t, u, x, y, i, nx); + printf ("%f %f %f\n", x, xp[i], xp[i + 1]); + fflush (stdout); + // exit(-1); + } + if (u < 0 || u > 1) { + printf ("interp2D: bad u: %.6e, t: %.6e x: %f y: %f j: %d ny: %d\n", u, t, x, y, j, ny); + printf ("%f %f %f\n", y, yp[j], yp[j + 1]); + printf ("\n"); + for (i = 0; i < nx; i++) { + printf ("%f\n", xp[i]); + } + printf ("\n"); + for (j = 0; j < ny; j++) { + printf ("%f\n", yp[j]); + } + fflush (stdout); + exit (-1); + } - // allocate memory for reusing neutrons - info->maxSaved = maxSaved; - info->cohMuSaved = (struct saveCohMu *)malloc(maxSaved*sizeof(struct saveCohMu)); - for(j=0;jcohMuSaved)[j].kix = 0; - (info->cohMuSaved)[j].kiy = 0; - (info->cohMuSaved)[j].kiz = 0; - (info->cohMuSaved)[j].XS = (double *)malloc((info->num_hkl)*sizeof(double)); + return (1 - t) * (1 - u) * f1 + t * (1 - u) * f2 + t * u * f3 + (1 - t) * u * f4; } - info->lastCohMuSaved = 0; - - info->hkl_ScattProbSaved = (struct save_hklScattProb *)malloc(maxSaved*sizeof(struct save_hklScattProb)); - for(j=0;jhkl_ScattProbSaved)[j].kix = 0; - (info->hkl_ScattProbSaved)[j].kiy = 0; - (info->hkl_ScattProbSaved)[j].kiz = 0; - // allocate memory for saved cummulative probability for scattering by i-th hkl plane - (info->hkl_ScattProbSaved)[j].cumProb_hkl = (double *)malloc((info->num_hkl)*sizeof(double)); - } - info->lastScattSaved = 0; - // initialize reusing statistics and variables - info->numReused = 0; + //////////////////////////////////////// + ////// initialization ////// + //////////////////////////////////////// - L = info->list; - // initialize rejection statistics - for(i=0;inum_hkl;i++) { - L[i].numReject = 0; - L[i].numScatt = 0; - } - // initialize reuse saved neutrons - for(i=0;inum_hkl;i++) { - L[i].lastSaved = 0; - L[i].maxSaved = maxSaved; - L[i].savedNeutrons = (struct saveScattProb *)malloc(maxSaved*sizeof(struct saveScattProb)); - for(j=0;jlmax = info->lmax; + readFourierCoef (coef_fn, fc); + + printf ("victor: fourier read. lmax: %d\n", fc->lmax); + fflush (stdout); + + // precompute legendre associated functions + info->lgdr = initLegendre (fc->lmax); + + // crystallographic data + if (!read_hkl_data_texture (crystal_fn, info)) { + printf ("initData: read_hkl_data_texture returns error\n"); + return 1; } - } - printf("start computing V\n"); - fflush(stdout); - - // V matrices for cross sections - L = info->list; - filep = fopen("Vlarge.txt","r"); - if(filep != NULL) { - for(i=0;inum_hkl;i++) { - Li = L + i; - c = 0; - while(c!='#') { nread = fscanf(filep,"%c",&c); } - nread = fscanf(filep,"%d",&(Li->numV)); - if(Li->numV <= 0) { - printf("Vlarge.txt: bad file, non positive numV\n"); - printf("i: %d nread: %d\n",i,nread); - printf("c: %c Li->numV: %d\n",c,Li->numV); - printf("Exiting...\n"); - fclose(filep); - fflush(stdout); - exit(-1); - } - Li->lv = (int *)malloc((Li->numV)*sizeof(int)); - Li->mv = (int *)malloc((Li->numV)*sizeof(int)); - Li->RV = (double *)malloc((Li->numV)*sizeof(double)); - Li->phiV = (double *)malloc((Li->numV)*sizeof(double)); - if (!Li->lv || !Li->mv || !Li->RV || !Li->phiV) { - fprintf(stderr,"Texture_process / initData: Failed malloc(s). Exit!\n"); - exit(-1); - } - for(j=0;jnumV;j++) { - fscanf(filep,"%d %d %d %d %d %d %lf %lf", - &lm,&hm,&km,&jj,(Li->lv)+j,(Li->mv)+j,(Li->RV)+j,(Li->phiV)+j); - if(hm != Li->h || km != Li->k || lm != Li->l) { - printf("Vlarge.txt: bad file\n"); - printf("i: %d\n",i); - printf("h: %d Li->h: %d\n",hm,Li->h); - printf("k: %d Li->k: %d\n",km,Li->k); - printf("l: %d Li->l: %d\n",lm,Li->l); - printf("Exiting...\n"); - fclose(filep); - fflush(stdout); - exit(-1); + // allocate memory for reusing neutrons + info->maxSaved = maxSaved; + info->cohMuSaved = (struct saveCohMu*)malloc (maxSaved * sizeof (struct saveCohMu)); + for (j = 0; j < maxSaved; j++) { + (info->cohMuSaved)[j].kix = 0; + (info->cohMuSaved)[j].kiy = 0; + (info->cohMuSaved)[j].kiz = 0; + (info->cohMuSaved)[j].XS = (double*)malloc ((info->num_hkl) * sizeof (double)); + } + info->lastCohMuSaved = 0; + + info->hkl_ScattProbSaved = (struct save_hklScattProb*)malloc (maxSaved * sizeof (struct save_hklScattProb)); + for (j = 0; j < maxSaved; j++) { + (info->hkl_ScattProbSaved)[j].kix = 0; + (info->hkl_ScattProbSaved)[j].kiy = 0; + (info->hkl_ScattProbSaved)[j].kiz = 0; + // allocate memory for saved cummulative probability for scattering by i-th hkl plane + (info->hkl_ScattProbSaved)[j].cumProb_hkl = (double*)malloc ((info->num_hkl) * sizeof (double)); + } + info->lastScattSaved = 0; + + // initialize reusing statistics and variables + info->numReused = 0; + + L = info->list; + // initialize rejection statistics + for (i = 0; i < info->num_hkl; i++) { + L[i].numReject = 0; + L[i].numScatt = 0; + } + // initialize reuse saved neutrons + for (i = 0; i < info->num_hkl; i++) { + L[i].lastSaved = 0; + L[i].maxSaved = maxSaved; + L[i].savedNeutrons = (struct saveScattProb*)malloc (maxSaved * sizeof (struct saveScattProb)); + for (j = 0; j < maxSaved; j++) { + (L[i].savedNeutrons)[j].kix = 0; + (L[i].savedNeutrons)[j].kiy = 0; + (L[i].savedNeutrons)[j].kiz = 0; + } + } + + printf ("start computing V\n"); + fflush (stdout); + + // V matrices for cross sections + L = info->list; + filep = fopen ("Vlarge.txt", "r"); + if (filep != NULL) { + for (i = 0; i < info->num_hkl; i++) { + Li = L + i; + c = 0; + while (c != '#') { + nread = fscanf (filep, "%c", &c); + } + nread = fscanf (filep, "%d", &(Li->numV)); + if (Li->numV <= 0) { + printf ("Vlarge.txt: bad file, non positive numV\n"); + printf ("i: %d nread: %d\n", i, nread); + printf ("c: %c Li->numV: %d\n", c, Li->numV); + printf ("Exiting...\n"); + fclose (filep); + fflush (stdout); + exit (-1); + } + Li->lv = (int*)malloc ((Li->numV) * sizeof (int)); + Li->mv = (int*)malloc ((Li->numV) * sizeof (int)); + Li->RV = (double*)malloc ((Li->numV) * sizeof (double)); + Li->phiV = (double*)malloc ((Li->numV) * sizeof (double)); + if (!Li->lv || !Li->mv || !Li->RV || !Li->phiV) { + fprintf (stderr, "Texture_process / initData: Failed malloc(s). Exit!\n"); + exit (-1); + } + for (j = 0; j < Li->numV; j++) { + fscanf (filep, "%d %d %d %d %d %d %lf %lf", &lm, &hm, &km, &jj, (Li->lv) + j, (Li->mv) + j, (Li->RV) + j, (Li->phiV) + j); + if (hm != Li->h || km != Li->k || lm != Li->l) { + printf ("Vlarge.txt: bad file\n"); + printf ("i: %d\n", i); + printf ("h: %d Li->h: %d\n", hm, Li->h); + printf ("k: %d Li->k: %d\n", km, Li->k); + printf ("l: %d Li->l: %d\n", lm, Li->l); + printf ("Exiting...\n"); + fclose (filep); + fflush (stdout); + exit (-1); + } } } + fclose (filep); + } else { + for (i = 0; i < info->num_hkl; i++) { + printf ("calling computeV for line %d\n", i); + fflush (stdout); + computeV (fc, info->lgdr, L + i); + } } - fclose(filep); - } else { - for(i=0;inum_hkl;i++) { - printf("calling computeV for line %d\n",i); - fflush(stdout); - computeV(fc,info->lgdr,L+i); + + // precompute the probability distribution of Q + L = info->list; + for (i = 0; i < info->num_hkl; i++) { + printf ("precomputing probQ %d\n", i + 1); + fflush (stdout); + L[i].nctq = 201; + L[i].nphiq = 601; + precomputeProbPhiq (L + i, info->lgdr); } - } - // precompute the probability distribution of Q - L = info->list; - for(i=0;inum_hkl;i++) { - printf("precomputing probQ %d\n",i+1); - fflush(stdout); - L[i].nctq = 201; - L[i].nphiq = 601; - precomputeProbPhiq(L+i,info->lgdr); - } + // precompute Upsilon_l + L = info->list; + for (i = 0; i < info->num_hkl; i++) { + printf ("precomputing Upsilon_l %d\n", i + 1); + fflush (stdout); + L[i].lmax = info->lmax; + precomputeUpsilon_l (L + i, info->lgdr); + } - // precompute Upsilon_l - L = info->list; - for(i=0;inum_hkl;i++) { - printf("precomputing Upsilon_l %d\n",i+1); - fflush(stdout); - L[i].lmax = info->lmax; - precomputeUpsilon_l(L+i,info->lgdr); - } + // free memory of fourier coefficient, not needed anymore + freeFourierCoef (fc); - // free memory of fourier coefficient, not needed anymore - freeFourierCoef(fc); + return 0; + } - return 0; -} + // end initialization -// end initialization + //////////////////////////////////// + /// free memory //// + //////////////////////////////////// -//////////////////////////////////// -/// free memory //// -//////////////////////////////////// + int + free_texture (struct hkl_info_struct_texture* hkl_info) { + int i; -int free_texture(struct hkl_info_struct_texture *hkl_info) -{ - int i; + if (hkl_info == NULL) { + return 0; + } - if(hkl_info == NULL) { return 0; } + free_legendre (hkl_info->lgdr); + free (hkl_info->lgdr); + for (i = 0; i < hkl_info->num_hkl; i++) { + free_hkl_data_texture (hkl_info->list + i); + } + free (hkl_info->list); - free_legendre(hkl_info->lgdr); - free(hkl_info->lgdr); - for(i=0;inum_hkl;i++) { - free_hkl_data_texture(hkl_info->list+i); + return 0; } - free(hkl_info->list); - return 0; -} + int + free_legendre (struct legendre* lgdr) { + int l, lmax, i, npt; -int free_legendre(struct legendre *lgdr) -{ - int l, lmax, i, npt; - - if(lgdr == NULL) { return 0; } + if (lgdr == NULL) { + return 0; + } - lmax = lgdr->lmax; - npt = (lmax+1)*(lmax+1); + lmax = lgdr->lmax; + npt = (lmax + 1) * (lmax + 1); - free(lgdr->l); - free(lgdr->m); - for(l=0;l<=lmax;l++) { free((lgdr->index)[l]); } - free(lgdr->index); + free (lgdr->l); + free (lgdr->m); + for (l = 0; l <= lmax; l++) { + free ((lgdr->index)[l]); + } + free (lgdr->index); - free(lgdr->nplm); - for(i=0;ix)[i]); } - free(lgdr->x); - for(i=0;iPlm)[i]); } - free(lgdr->Plm); + free (lgdr->nplm); + for (i = 0; i < npt; i++) { + free ((lgdr->x)[i]); + } + free (lgdr->x); + for (i = 0; i < npt; i++) { + free ((lgdr->Plm)[i]); + } + free (lgdr->Plm); - return 0; -} + return 0; + } -int free_hkl_data_texture(struct hkl_data_texture *L) -{ - int i; + int + free_hkl_data_texture (struct hkl_data_texture* L) { + int i; - if(L == NULL) { return 0; } + if (L == NULL) { + return 0; + } - free(L->lv); - free(L->mv); - free(L->RV); - free(L->phiV); + free (L->lv); + free (L->mv); + free (L->RV); + free (L->phiV); - if(L->ctq != NULL) { free(L->ctq); } - if(L->phiq != NULL) { free(L->phiq); } - if(L->probQ != NULL) { - for(i=0;inctq;i++) { free((L->probQ)[i]); } - free(L->probQ); - } - - return 0; -} - -// end free memory - -/* - // McStas function to rotate a vector: - // rotate(*nx, *ny, *nz, nvx,nvy,nvz, angle, axis1, axis2, axis3); -*/ - -#endif /* !TEXTURE_PROCESS_DECL */ - -// Very important to add a pointer to this struct in the union-lib.c file -struct Texture_physics_storage_struct { - // Variables that needs to be transfered between any of the following places: - // The initialize in this component - // The function for calculating my - // The function for calculating scattering - - // Avoid duplicates of output parameters and setting parameters in naming - - struct hkl_info_struct_texture *hkl_info_storage; // struct containing all necessary info for SC - double pack; // packing factor - double barns_setting; // Sets wether barns of fm^2 is used -}; - -// Function for calculating my, the inverse penetration depth (for only this scattering process). -// The input for this function and its order may not be changed, but the names may be updated. -int Texture_physics_my(double *my, double *k_initial, union data_transfer_union data_transfer, - struct focus_data_struct *focus_data, _class_particle *_particle) -{ - int i, is; - // k_initial is a pointer to a simple vector with 3 doubles, k[0], k[1], k[2] (wavevector) - double kix = k_initial[0]; - double kiy = k_initial[1]; - double kiz = k_initial[2]; - double ki, kict, kiphi, Gmax; - int num_hkl_scatt = -1; - FILE *filep; - - struct hkl_info_struct_texture *hkl_info = - data_transfer.pointer_to_a_Texture_physics_storage_struct->hkl_info_storage; - struct hkl_data_texture *L = hkl_info->list; - struct legendre *lgdr = hkl_info->lgdr; - - double cohXS = -1; - - // in case we use 'SPLIT' then consecutive neutrons can be identical when entering here and - // we may skip the cross section computations - - is = -1; - for(i=hkl_info->lastCohMuSaved;i>=0;i--) { - if ( fabs(kix-(hkl_info->cohMuSaved)[i].kix)<1e-90 && - fabs(kiy-(hkl_info->cohMuSaved)[i].kiy)<1e-90 && - fabs(kiz-(hkl_info->cohMuSaved)[i].kiz)<1e-90 ) { is = i; break; } - } - if(is==-1) { - for(i=hkl_info->maxSaved-1;i>hkl_info->lastCohMuSaved;i--) { - if ( fabs(kix-(hkl_info->cohMuSaved)[i].kix)<1e-90 && - fabs(kiy-(hkl_info->cohMuSaved)[i].kiy)<1e-90 && - fabs(kiz-(hkl_info->cohMuSaved)[i].kiz)<1e-90 ) { is = i; break; } + if (L->ctq != NULL) { + free (L->ctq); } + if (L->phiq != NULL) { + free (L->phiq); + } + if (L->probQ != NULL) { + for (i = 0; i < L->nctq; i++) { + free ((L->probQ)[i]); + } + free (L->probQ); + } + + return 0; } - if (is!=-1) { - // neutron found. reuse cross section - //printf("my reused\n"); - //fflush(stdout); - hkl_info->numReused += 1; - hkl_info->num_hkl_scatt = (hkl_info->cohMuSaved)[is].num_hkl_scatt; - hkl_info->cohMu = (hkl_info->cohMuSaved)[is].cohMu; - for(i=0;inum_hkl_scatt;i++) { - L[i].currXS = (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].XS[i]; - } - // save the neutron scattering parameters - hkl_info->lastCohMuSaved = is; - } else { - //printf("my new\n"); - //fflush(stdout); - // polar coordinates of wavevector - ki = sqrt(kix*kix + kiy*kiy + kiz*kiz); - kict = kiz/ki; - kiphi = atan2(kiy,kix); - - //Max possible G for this ki with 5*sigma delta-d/d cutoff. - //double Gmax = 2*ki/(1 - 5*hkl_info->m_delta_d_d); // no strain taken into acount for the moment - Gmax = 2*ki; - - num_hkl_scatt = -1; - cohXS = 0; - for(i=0;inum_hkl;i++) { - if(L[i].G > Gmax) { break; } // Bragg cutoff - num_hkl_scatt = i; - //L[i].currXS = total_hkl_XS(ki,kict,kiphi,L+i,lgdr); - L[i].currXS = total_hkl_XS_interp(ki,kict,kiphi,L+i,lgdr); - cohXS += L[i].currXS; - } - - // number of reflections below Bragg cut-off - hkl_info->num_hkl_scatt = num_hkl_scatt; - - // multiply by the appropriate factors to get the linear attenuation coefficient cohMu (in m^-1) - hkl_info->cohMu = cohXS*(hkl_info->xs2mu)*pow((2*PI)/ki,3)/(hkl_info->V0); - - // save the neutron scattering parameters - hkl_info->lastCohMuSaved++; - if(hkl_info->lastCohMuSaved>=hkl_info->maxSaved) { hkl_info->lastCohMuSaved = 0; }; - (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].kix = kix; - (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].kiy = kiy; - (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].kiz = kiz; - (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].num_hkl_scatt = hkl_info->num_hkl_scatt; - (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].cohMu = hkl_info->cohMu; - for(i=0;icohMuSaved)[hkl_info->lastCohMuSaved].XS[i] = L[i].currXS; + // end free memory + + /* + // McStas function to rotate a vector: + // rotate(*nx, *ny, *nz, nvx,nvy,nvz, angle, axis1, axis2, axis3); + */ + + #endif /* !TEXTURE_PROCESS_DECL */ + + // Very important to add a pointer to this struct in the union-lib.c file + struct Texture_physics_storage_struct { + // Variables that needs to be transfered between any of the following places: + // The initialize in this component + // The function for calculating my + // The function for calculating scattering + + // Avoid duplicates of output parameters and setting parameters in naming + + struct hkl_info_struct_texture* hkl_info_storage; // struct containing all necessary info for SC + double pack; // packing factor + double barns_setting; // Sets wether barns of fm^2 is used + }; + + // Function for calculating my, the inverse penetration depth (for only this scattering process). + // The input for this function and its order may not be changed, but the names may be updated. + int + Texture_physics_my (double* my, double* k_initial, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, _class_particle* _particle) { + int i, is; + // k_initial is a pointer to a simple vector with 3 doubles, k[0], k[1], k[2] (wavevector) + double kix = k_initial[0]; + double kiy = k_initial[1]; + double kiz = k_initial[2]; + double ki, kict, kiphi, Gmax; + int num_hkl_scatt = -1; + FILE* filep; + + struct hkl_info_struct_texture* hkl_info = data_transfer.pointer_to_a_Texture_physics_storage_struct->hkl_info_storage; + struct hkl_data_texture* L = hkl_info->list; + struct legendre* lgdr = hkl_info->lgdr; + + double cohXS = -1; + + // in case we use 'SPLIT' then consecutive neutrons can be identical when entering here and + // we may skip the cross section computations + + is = -1; + for (i = hkl_info->lastCohMuSaved; i >= 0; i--) { + if (fabs (kix - (hkl_info->cohMuSaved)[i].kix) < 1e-90 && fabs (kiy - (hkl_info->cohMuSaved)[i].kiy) < 1e-90 + && fabs (kiz - (hkl_info->cohMuSaved)[i].kiz) < 1e-90) { + is = i; + break; + } + } + if (is == -1) { + for (i = hkl_info->maxSaved - 1; i > hkl_info->lastCohMuSaved; i--) { + if (fabs (kix - (hkl_info->cohMuSaved)[i].kix) < 1e-90 && fabs (kiy - (hkl_info->cohMuSaved)[i].kiy) < 1e-90 + && fabs (kiz - (hkl_info->cohMuSaved)[i].kiz) < 1e-90) { + is = i; + break; + } + } } - } - *my = hkl_info->cohMu; - //printf("my: %.6e\n",*my); - - return 1; -}; - -// Function that provides description of a basic scattering event. -int Texture_physics_scattering(double *k_final, double *k_initial, double *weight, - union data_transfer_union data_transfer, - struct focus_data_struct *focus_data, _class_particle *_particle) -{ - int i, is, j, num_hkl_scatt; - double r, sum, accum, *cumProb_hkl; /* Locals */ - double kf[3]; /* Final wave vector (local) */ - FILE *filep; - - struct hkl_info_struct_texture *hkl_info - = data_transfer.pointer_to_a_Texture_physics_storage_struct->hkl_info_storage; - - struct hkl_data_texture *L = hkl_info->list; // hkl list - struct legendre *lgdr = hkl_info->lgdr; // precomputed legendre associated functions - - double G = L->G; - - // This can be removed, since this component deals only with coherent scattering - // (instead here the Bragg cutoff may be implemented) - if(hkl_info->num_hkl_scatt < 0 || hkl_info->cohMu <= 0) { - printf("No scattering: %d %d %.6e\n", hkl_info->num_hkl_scatt, hkl_info->num_hkl, hkl_info->cohMu); - k_final[0] = k_initial[0]; - k_final[1] = k_initial[1]; - k_final[2] = k_initial[2]; - return 0; // Return 0 will use ABSORB in main component (as it is not allowed in a function) - } + if (is != -1) { + // neutron found. reuse cross section + // printf("my reused\n"); + // fflush(stdout); + hkl_info->numReused += 1; + hkl_info->num_hkl_scatt = (hkl_info->cohMuSaved)[is].num_hkl_scatt; + hkl_info->cohMu = (hkl_info->cohMuSaved)[is].cohMu; + for (i = 0; i < hkl_info->num_hkl_scatt; i++) { + L[i].currXS = (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].XS[i]; + } + // save the neutron scattering parameters + hkl_info->lastCohMuSaved = is; + } else { + // printf("my new\n"); + // fflush(stdout); + // polar coordinates of wavevector + ki = sqrt (kix * kix + kiy * kiy + kiz * kiz); + kict = kiz / ki; + kiphi = atan2 (kiy, kix); + + // Max possible G for this ki with 5*sigma delta-d/d cutoff. + // double Gmax = 2*ki/(1 - 5*hkl_info->m_delta_d_d); // no strain taken into acount for the moment + Gmax = 2 * ki; + + num_hkl_scatt = -1; + cohXS = 0; + for (i = 0; i < hkl_info->num_hkl; i++) { + if (L[i].G > Gmax) { + break; + } // Bragg cutoff + num_hkl_scatt = i; + // L[i].currXS = total_hkl_XS(ki,kict,kiphi,L+i,lgdr); + L[i].currXS = total_hkl_XS_interp (ki, kict, kiphi, L + i, lgdr); + cohXS += L[i].currXS; + } - is = -1; - for(i=hkl_info->lastScattSaved;i>=0;i--) { - if ( fabs(k_initial[0]-(hkl_info->hkl_ScattProbSaved)[i].kix)<1e-90 && - fabs(k_initial[1]-(hkl_info->hkl_ScattProbSaved)[i].kiy)<1e-90 && - fabs(k_initial[2]-(hkl_info->hkl_ScattProbSaved)[i].kiz)<1e-90 ) { is = i; break; } - } - if(is==-1) { - for(i=hkl_info->maxSaved-1;i>hkl_info->lastScattSaved;i--) { - if ( fabs(k_initial[0]-(hkl_info->hkl_ScattProbSaved)[i].kix)<1e-90 && - fabs(k_initial[1]-(hkl_info->hkl_ScattProbSaved)[i].kiy)<1e-90 && - fabs(k_initial[2]-(hkl_info->hkl_ScattProbSaved)[i].kiz)<1e-90 ) { is = i; break; } + // number of reflections below Bragg cut-off + hkl_info->num_hkl_scatt = num_hkl_scatt; + + // multiply by the appropriate factors to get the linear attenuation coefficient cohMu (in m^-1) + hkl_info->cohMu = cohXS * (hkl_info->xs2mu) * pow ((2 * PI) / ki, 3) / (hkl_info->V0); + + // save the neutron scattering parameters + hkl_info->lastCohMuSaved++; + if (hkl_info->lastCohMuSaved >= hkl_info->maxSaved) { + hkl_info->lastCohMuSaved = 0; + }; + (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].kix = kix; + (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].kiy = kiy; + (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].kiz = kiz; + (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].num_hkl_scatt = hkl_info->num_hkl_scatt; + (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].cohMu = hkl_info->cohMu; + for (i = 0; i < num_hkl_scatt; i++) { + (hkl_info->cohMuSaved)[hkl_info->lastCohMuSaved].XS[i] = L[i].currXS; + } } - } - if(is!=-1) { - //printf("scatt reused\n"); - //fflush(stdout); - num_hkl_scatt = (hkl_info->hkl_ScattProbSaved)[is].num_hkl_scatt; - cumProb_hkl = (hkl_info->hkl_ScattProbSaved)[is].cumProb_hkl; - // save neutron parameters - (hkl_info->lastScattSaved) = is; - } else { - // new neutron. Compute necessary things. select the hkl planes that scatter - //printf("scatt new\n"); - //fflush(stdout); + *my = hkl_info->cohMu; + // printf("my: %.6e\n",*my); + + return 1; + }; + + // Function that provides description of a basic scattering event. + int + Texture_physics_scattering (double* k_final, double* k_initial, double* weight, union data_transfer_union data_transfer, struct focus_data_struct* focus_data, + _class_particle* _particle) { + int i, is, j, num_hkl_scatt; + double r, sum, accum, *cumProb_hkl; /* Locals */ + double kf[3]; /* Final wave vector (local) */ + FILE* filep; + + struct hkl_info_struct_texture* hkl_info = data_transfer.pointer_to_a_Texture_physics_storage_struct->hkl_info_storage; + + struct hkl_data_texture* L = hkl_info->list; // hkl list + struct legendre* lgdr = hkl_info->lgdr; // precomputed legendre associated functions + + double G = L->G; + + // This can be removed, since this component deals only with coherent scattering + // (instead here the Bragg cutoff may be implemented) + if (hkl_info->num_hkl_scatt < 0 || hkl_info->cohMu <= 0) { + printf ("No scattering: %d %d %.6e\n", hkl_info->num_hkl_scatt, hkl_info->num_hkl, hkl_info->cohMu); + k_final[0] = k_initial[0]; + k_final[1] = k_initial[1]; + k_final[2] = k_initial[2]; + return 0; // Return 0 will use ABSORB in main component (as it is not allowed in a function) + } + + is = -1; + for (i = hkl_info->lastScattSaved; i >= 0; i--) { + if (fabs (k_initial[0] - (hkl_info->hkl_ScattProbSaved)[i].kix) < 1e-90 && fabs (k_initial[1] - (hkl_info->hkl_ScattProbSaved)[i].kiy) < 1e-90 + && fabs (k_initial[2] - (hkl_info->hkl_ScattProbSaved)[i].kiz) < 1e-90) { + is = i; + break; + } + } + if (is == -1) { + for (i = hkl_info->maxSaved - 1; i > hkl_info->lastScattSaved; i--) { + if (fabs (k_initial[0] - (hkl_info->hkl_ScattProbSaved)[i].kix) < 1e-90 && fabs (k_initial[1] - (hkl_info->hkl_ScattProbSaved)[i].kiy) < 1e-90 + && fabs (k_initial[2] - (hkl_info->hkl_ScattProbSaved)[i].kiz) < 1e-90) { + is = i; + break; + } + } + } - num_hkl_scatt = hkl_info->num_hkl_scatt; + if (is != -1) { + // printf("scatt reused\n"); + // fflush(stdout); + num_hkl_scatt = (hkl_info->hkl_ScattProbSaved)[is].num_hkl_scatt; + cumProb_hkl = (hkl_info->hkl_ScattProbSaved)[is].cumProb_hkl; + // save neutron parameters + (hkl_info->lastScattSaved) = is; + } else { + // new neutron. Compute necessary things. select the hkl planes that scatter + // printf("scatt new\n"); + // fflush(stdout); - (hkl_info->lastScattSaved)++; - if(hkl_info->lastScattSaved >= hkl_info->maxSaved) { hkl_info->lastScattSaved = 0; } + num_hkl_scatt = hkl_info->num_hkl_scatt; - (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].num_hkl_scatt = hkl_info->num_hkl_scatt; + (hkl_info->lastScattSaved)++; + if (hkl_info->lastScattSaved >= hkl_info->maxSaved) { + hkl_info->lastScattSaved = 0; + } - (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].kix = k_initial[0]; - (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].kiy = k_initial[1]; - (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].kiz = k_initial[2]; + (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].num_hkl_scatt = hkl_info->num_hkl_scatt; - cumProb_hkl = (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].cumProb_hkl; + (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].kix = k_initial[0]; + (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].kiy = k_initial[1]; + (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].kiz = k_initial[2]; - sum = 0; - for(i=0;i<=num_hkl_scatt;i++) { - // hkl_info->num_hkl_scatt implements Bragg cutoff - sum += L[i].currXS; + cumProb_hkl = (hkl_info->hkl_ScattProbSaved)[hkl_info->lastScattSaved].cumProb_hkl; + + sum = 0; + for (i = 0; i <= num_hkl_scatt; i++) { + // hkl_info->num_hkl_scatt implements Bragg cutoff + sum += L[i].currXS; + } + accum = 0; + for (i = 0; i <= num_hkl_scatt; i++) { + // hkl_info->num_hkl_scatt implements Bragg cutoff + accum += L[i].currXS / sum; + cumProb_hkl[i] = accum; + } } - accum = 0; - for(i=0;i<=num_hkl_scatt;i++) { + + j = -1; + r = rand01 (); + for (i = 0; i <= num_hkl_scatt; i++) { // hkl_info->num_hkl_scatt implements Bragg cutoff - accum += L[i].currXS/sum; - cumProb_hkl[i] = accum; - } - } - - j = -1; - r = rand01(); - for(i=0;i<=num_hkl_scatt;i++) { - // hkl_info->num_hkl_scatt implements Bragg cutoff - if(rcoh_refl/(hkl_info->cohMu*T[j].refl); - //printf("SCATTERING: hkl_info->coh_refl=%f, hkl_info->cohMu = %f, T[%d].refl = %f\n", - // hkl_info->coh_refl,hkl_info->cohMu,j,T[j].refl); - // No weight adjusting here - - // save some information - hkl_info->type = 'c'; - hkl_info->h = L[i].h; - hkl_info->k = L[i].k; - hkl_info->l = L[i].l; - - // return the scattered wave vector - k_final[0] = kf[0]; - k_final[1] = kf[1]; - k_final[2] = kf[2]; - - return 1; -}; - -#ifndef PROCESS_DETECTOR - #define PROCESS_DETECTOR dummy -#endif - -#ifndef PROCESS_TEXTURE_DETECTOR - #define PROCESS_TEXTURE_DETECTOR dummy -#endif + + // sampling kprime + sampleKprime_hkl (kf, k_initial, L + j, lgdr); + + /* Adjust neutron weight (see manual for explanation). */ + //*weight *= T[j].xsect*hkl_info->coh_refl/(hkl_info->cohMu*T[j].refl); + // printf("SCATTERING: hkl_info->coh_refl=%f, hkl_info->cohMu = %f, T[%d].refl = %f\n", + // hkl_info->coh_refl,hkl_info->cohMu,j,T[j].refl); + // No weight adjusting here + + // save some information + hkl_info->type = 'c'; + hkl_info->h = L[i].h; + hkl_info->k = L[i].k; + hkl_info->l = L[i].l; + + // return the scattered wave vector + k_final[0] = kf[0]; + k_final[1] = kf[1]; + k_final[2] = kf[2]; + + return 1; + }; + + #ifndef PROCESS_DETECTOR + #define PROCESS_DETECTOR dummy + #endif + + #ifndef PROCESS_TEXTURE_DETECTOR + #define PROCESS_TEXTURE_DETECTOR dummy + #endif %} DECLARE %{ -// Declare for this component, to do calculations on the input / store in the transported data -struct Texture_physics_storage_struct Texture_storage; + // Declare for this component, to do calculations on the input / store in the transported data + struct Texture_physics_storage_struct Texture_storage; -// Variables needed in initialize of this function. -struct hkl_info_struct_texture hkl_info_texture; + // Variables needed in initialize of this function. + struct hkl_info_struct_texture hkl_info_texture; -// Needed for transport to the main component, will be the same for all processes -struct global_process_element_struct global_process_element; -struct scattering_process_struct This_process; + // Needed for transport to the main component, will be the same for all processes + struct global_process_element_struct global_process_element; + struct scattering_process_struct This_process; %} INITIALIZE %{ // Texture initialize - //double as, bs, cs; - //double lambda, k, kct, kst, kphi, ki[3], kf[3]; - //int l, m, j, i=0; - //FILE *filep; + // double as, bs, cs; + // double lambda, k, kct, kst, kphi, ki[3], kf[3]; + // int l, m, j, i=0; + // FILE *filep; /* kx_first = kx_in; ky_first = ky_in; kz_first = kz_in; */ - + /* default format h,k,l,F,F2 */ hkl_info_texture.column_order[0] = 1; hkl_info_texture.column_order[1] = 2; @@ -2255,48 +2348,51 @@ INITIALIZE // cut-off for l. If negative, take the cut-off provided in the Fourier coeff file hkl_info_texture.lmax = lmax_user; - + // first neutron is new hkl_info_texture.new = 1; // initialize data - if ( initData(fcoef_fn, crystal_fn, &hkl_info_texture, maxNeutronSaved) ) { - printf("Texture_process: %s: Error in initData: Aborting.\n", NAME_CURRENT_COMP); - fflush(stdout); - exit(-1); + if (initData (fcoef_fn, crystal_fn, &hkl_info_texture, maxNeutronSaved)) { + printf ("Texture_process: %s: Error in initData: Aborting.\n", NAME_CURRENT_COMP); + fflush (stdout); + exit (-1); } // precomputed factors - hkl_info_texture.xs2mu = packing_factor/hkl_info_texture.V0; + hkl_info_texture.xs2mu = packing_factor / hkl_info_texture.V0; // Cross-sections are in barns = 10**-28 m**2, and unit cell volumes are // in AA**3 = 10**-30 m**3. Hence a factor of 100 is used to convert // scattering lengths to m**-1 if (barns) { - hkl_info_texture.xs2mu *= 100; + hkl_info_texture.xs2mu *= 100; + } + printf ("xs2mu = %.6e\n", hkl_info_texture.xs2mu); + fflush (stdout); + + if (hkl_info_texture.sigma_a < 0) { + hkl_info_texture.sigma_a = 0; } - printf("xs2mu = %.6e\n",hkl_info_texture.xs2mu); - fflush(stdout); - - if (hkl_info_texture.sigma_a<0) { hkl_info_texture.sigma_a = 0; } - if (hkl_info_texture.sigma_i<0) { hkl_info_texture.sigma_i = 0; } - + if (hkl_info_texture.sigma_i < 0) { + hkl_info_texture.sigma_i = 0; + } + if (hkl_info_texture.num_hkl) { - printf("Texture_process: %s: Read %d reflections from file '%s'\n", - NAME_CURRENT_COMP, hkl_info_texture.num_hkl, crystal_fn); + printf ("Texture_process: %s: Read %d reflections from file '%s'\n", NAME_CURRENT_COMP, hkl_info_texture.num_hkl, crystal_fn); } else { - printf("Texture_process: %s: No reflections read from file. No scattering will take place.\n", - NAME_CURRENT_COMP); + printf ("Texture_process: %s: No reflections read from file. No scattering will take place.\n", NAME_CURRENT_COMP); } - - printf("Texture: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn] reflections=%s\n", - NAME_CURRENT_COMP, hkl_info_texture.V0, hkl_info_texture.sigma_a, hkl_info_texture.sigma_i, - crystal_fn && strlen(crystal_fn) ? crystal_fn : "NULL"); + + printf ("Texture: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn] reflections=%s\n", NAME_CURRENT_COMP, hkl_info_texture.V0, hkl_info_texture.sigma_a, + hkl_info_texture.sigma_i, crystal_fn&& strlen (crystal_fn) ? crystal_fn : "NULL"); // Temporary errors until these features are either added or removed from input - + if (order) { - exit(fprintf(stderr,"Texture_process: %s: Order control not supported yet!\n" - "ERROR Please set order to zero.\n", NAME_CURRENT_COMP)); + exit (fprintf (stderr, + "Texture_process: %s: Order control not supported yet!\n" + "ERROR Please set order to zero.\n", + NAME_CURRENT_COMP)); } // Initialize done in the component @@ -2304,16 +2400,16 @@ INITIALIZE Texture_storage.pack = packing_factor; Texture_storage.hkl_info_storage = &hkl_info_texture; - //First initialise This_process with default values: - scattering_process_struct_init(&This_process); + // First initialise This_process with default values: + scattering_process_struct_init (&This_process); // Need to specify if this process is isotropic - //This_process.non_isotropic_rot_index = -1; // Yes (powder) - This_process.non_isotropic_rot_index = 1; // No (single crystal or texture) - + // This_process.non_isotropic_rot_index = -1; // Yes (powder) + This_process.non_isotropic_rot_index = 1; // No (single crystal or texture) + // Need to specify if this process need to use focusing in calculation of inverse penetration depth (physics_my) - //This_process.needs_cross_section_focus = 1; // Yes - This_process.needs_cross_section_focus = -1; // No + // This_process.needs_cross_section_focus = 1; // Yes + This_process.needs_cross_section_focus = -1; // No // The type of the process must be saved in the global enum process This_process.eProcess = Texture; @@ -2325,46 +2421,44 @@ INITIALIZE // This will be the same for all process's, and can thus be moved to an include. This_process.process_p_interact = interact_fraction; - sprintf(This_process.name,"%s",NAME_CURRENT_COMP); - rot_copy(This_process.rotation_matrix,ROT_A_CURRENT_COMP); - sprintf(global_process_element.name,"%s",NAME_CURRENT_COMP); + sprintf (This_process.name, "%s", NAME_CURRENT_COMP); + rot_copy (This_process.rotation_matrix, ROT_A_CURRENT_COMP); + sprintf (global_process_element.name, "%s", NAME_CURRENT_COMP); global_process_element.component_index = INDEX_CURRENT_COMP; global_process_element.p_scattering_process = &This_process; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Texture_process:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Texture_process:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - add_element_to_process_list(global_process_list,global_process_element); + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + add_element_to_process_list (global_process_list, global_process_element); %} TRACE %{ - // Trace should be empty, the simulation is done in Union_master + // Trace should be empty, the simulation is done in Union_master %} FINALLY %{ -int i; -struct hkl_info_struct_texture *hkl_info - = This_process.data_transfer.pointer_to_a_Texture_physics_storage_struct->hkl_info_storage; -printf("numReused: %.6e\n",hkl_info->numReused); -// print rejection statistics -FILE *filep = fopen("rejectioStatistics.txt","w"); -if (!filep) { - struct hkl_data_texture *L = hkl_info->list; - for(i=0;inum_hkl;i++) { - fprintf(filep,"%d %d %d %.6e %.6e\n",L[i].h,L[i].k,L[i].l,L[i].numReject,L[i].numScatt); + int i; + struct hkl_info_struct_texture* hkl_info = This_process.data_transfer.pointer_to_a_Texture_physics_storage_struct->hkl_info_storage; + printf ("numReused: %.6e\n", hkl_info->numReused); + // print rejection statistics + FILE* filep = fopen ("rejectioStatistics.txt", "w"); + if (!filep) { + struct hkl_data_texture* L = hkl_info->list; + for (i = 0; i < hkl_info->num_hkl; i++) { + fprintf (filep, "%d %d %d %.6e %.6e\n", L[i].h, L[i].k, L[i].l, L[i].numReject, L[i].numScatt); + } + fclose (filep); + } else { + fprintf (stderr, "Texture_process %s WARNING: Failed to open file 'rejectioStatistics.txt' in write mode. No data saved!\n", NAME_CURRENT_COMP); } - fclose(filep); - } else { - fprintf(stderr,"Texture_process %s WARNING: Failed to open file 'rejectioStatistics.txt' in write mode. No data saved!\n", NAME_CURRENT_COMP); - } -// deallocate allocated memory, etc. -free_texture(hkl_info); + // deallocate allocated memory, etc. + free_texture (hkl_info); %} END diff --git a/mcstas-comps/union/Union_abs_logger_1D_space.comp b/mcstas-comps/union/Union_abs_logger_1D_space.comp index 8046ce160d..2a92299d03 100644 --- a/mcstas-comps/union/Union_abs_logger_1D_space.comp +++ b/mcstas-comps/union/Union_abs_logger_1D_space.comp @@ -88,277 +88,284 @@ SETTING PARAMETERS(string target_geometry="NULL", SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_abs_logger_1D_space component" -#endif - -struct temp_1D_abs_data_element_struct { - int index; - double weight; -}; - -struct temp_1D_abs_data_struct { - int num_elements; - int allocated_elements; - struct temp_1D_abs_data_element_struct *elements; -}; - -struct a_1D_abs_storage_struct { - struct Detector_1D_struct Detector_1D; - struct temp_1D_abs_data_struct temp_1D_abs_data; - //some type - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_1D_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - struct a_1D_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_abs_logger_1D_space component" + #endif + + struct temp_1D_abs_data_element_struct { + int index; + double weight; + }; + + struct temp_1D_abs_data_struct { + int num_elements; + int allocated_elements; + struct temp_1D_abs_data_element_struct* elements; + }; + + struct a_1D_abs_storage_struct { + struct Detector_1D_struct Detector_1D; + struct temp_1D_abs_data_struct temp_1D_abs_data; + // some type + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_1D_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + struct a_1D_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - int i; - double value, dummy1, dummy2; - - //value = position.y; // define makes this not work - coords_get(*position, &dummy1, &value, &dummy2); - - // Find bin in histogram - if (value>storage->Detector_1D.min && valueDetector_1D.max) { - i = floor((value - storage->Detector_1D.min)*storage->Detector_1D.bins/(storage->Detector_1D.max - storage->Detector_1D.min)); - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_1D_data.num_elements,storage->temp_1D_data.allocated_elements); - - if (storage->temp_1D_abs_data.num_elements < storage->temp_1D_abs_data.allocated_elements) { - storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements].index = i; - storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_1D_abs_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_1D_abs_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_1D_abs_data_element_struct)); - - for (index=0;indextemp_1D_abs_data.num_elements;index++) { - temporary_storage.elements[index].index = storage->temp_1D_abs_data.elements[index].index; - temporary_storage.elements[index].weight = storage->temp_1D_abs_data.elements[index].weight; - } - - // free current data - free(storage->temp_1D_abs_data.elements); - - // allocate larger array (10 larger) - storage->temp_1D_abs_data.allocated_elements = 10 + storage->temp_1D_abs_data.num_elements; - storage->temp_1D_abs_data.elements = malloc(storage->temp_1D_abs_data.allocated_elements*sizeof(struct temp_1D_abs_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_1D_abs_data.num_elements;index++) { - storage->temp_1D_abs_data.elements[index].index = temporary_storage.elements[index].index; - storage->temp_1D_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + int i; + double value, dummy1, dummy2; + + // value = position.y; // define makes this not work + coords_get (*position, &dummy1, &value, &dummy2); + + // Find bin in histogram + if (value > storage->Detector_1D.min && value < storage->Detector_1D.max) { + i = floor ((value - storage->Detector_1D.min) * storage->Detector_1D.bins / (storage->Detector_1D.max - storage->Detector_1D.min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_1D_data.num_elements,storage->temp_1D_data.allocated_elements); + + if (storage->temp_1D_abs_data.num_elements < storage->temp_1D_abs_data.allocated_elements) { + storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements].index = i; + storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_1D_abs_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_1D_abs_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_1D_abs_data_element_struct)); + + for (index = 0; index < storage->temp_1D_abs_data.num_elements; index++) { + temporary_storage.elements[index].index = storage->temp_1D_abs_data.elements[index].index; + temporary_storage.elements[index].weight = storage->temp_1D_abs_data.elements[index].weight; + } + + // free current data + free (storage->temp_1D_abs_data.elements); + + // allocate larger array (10 larger) + storage->temp_1D_abs_data.allocated_elements = 10 + storage->temp_1D_abs_data.num_elements; + storage->temp_1D_abs_data.elements = malloc (storage->temp_1D_abs_data.allocated_elements * sizeof (struct temp_1D_abs_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_1D_abs_data.num_elements; index++) { + storage->temp_1D_abs_data.elements[index].index = temporary_storage.elements[index].index; + storage->temp_1D_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements].index = i; + storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements].index = i; - storage->temp_1D_abs_data.elements[storage->temp_1D_abs_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_1D_abs_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_1D_abs_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array,abs_logger); } } - -} - -// clear_temp -void clear_temp_1D_abs(union abs_logger_data_union *data_union) { - data_union->p_1D_abs_storage->temp_1D_abs_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_1D_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_1D_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_1D_abs (union abs_logger_data_union* data_union) { + data_union->p_1D_abs_storage->temp_1D_abs_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - - int i; - double value, dummy1, dummy2; - - //value = position.y; // define makes this not work - coords_get(*position, &dummy1, &value, &dummy2); - - // Find bin in histogram - if (value>storage->Detector_1D.min && valueDetector_1D.max) { - - i = floor((value - storage->Detector_1D.min)*(double)storage->Detector_1D.bins/(storage->Detector_1D.max - storage->Detector_1D.min)); - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_1D.Array_N[i]++; - storage->Detector_1D.Array_p[i] += p; - storage->Detector_1D.Array_p2[i] += p*p; - + // record_to_perm + void + record_to_perm_1D_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_1D_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + + int i; + double value, dummy1, dummy2; + + // value = position.y; // define makes this not work + coords_get (*position, &dummy1, &value, &dummy2); + + // Find bin in histogram + if (value > storage->Detector_1D.min && value < storage->Detector_1D.max) { + + i = floor ((value - storage->Detector_1D.min) * (double)storage->Detector_1D.bins / (storage->Detector_1D.max - storage->Detector_1D.min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_1D.Array_N[i]++; + storage->Detector_1D.Array_p[i] += p; + storage->Detector_1D.Array_p2[i] += p * p; + } } } -} + // write_temp_to_perm + void + write_temp_to_perm_1D_abs (union abs_logger_data_union* data_union) { + + struct a_1D_abs_storage_struct* storage; + storage = data_union->p_1D_abs_storage; -// write_temp_to_perm -void write_temp_to_perm_1D_abs(union abs_logger_data_union *data_union) { + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_abs_data.num_elements; index++) { + storage->Detector_1D.Array_N[storage->temp_1D_abs_data.elements[index].index]++; - struct a_1D_abs_storage_struct *storage; - storage = data_union->p_1D_abs_storage; + storage->Detector_1D.Array_p[storage->temp_1D_abs_data.elements[index].index] += storage->temp_1D_abs_data.elements[index].weight; - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_abs_data.num_elements;index++) { - storage->Detector_1D.Array_N[storage->temp_1D_abs_data.elements[index].index]++; - - storage->Detector_1D.Array_p[storage->temp_1D_abs_data.elements[index].index] += storage->temp_1D_abs_data.elements[index].weight; - - storage->Detector_1D.Array_p2[storage->temp_1D_abs_data.elements[index].index] += storage->temp_1D_abs_data.elements[index].weight*storage->temp_1D_abs_data.elements[index].weight; + storage->Detector_1D.Array_p2[storage->temp_1D_abs_data.elements[index].index] + += storage->temp_1D_abs_data.elements[index].weight * storage->temp_1D_abs_data.elements[index].weight; + } + clear_temp_1D_abs (data_union); } - clear_temp_1D_abs(data_union); -} - -void write_temp_to_perm_final_p_1D_abs(union abs_logger_data_union *data_union, double final_weight) { - - struct a_1D_abs_storage_struct *storage; - storage = data_union->p_1D_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_abs_data.num_elements;index++) { - storage->Detector_1D.Array_N[storage->temp_1D_abs_data.elements[index].index]++; - - storage->Detector_1D.Array_p[storage->temp_1D_abs_data.elements[index].index] += final_weight; - - storage->Detector_1D.Array_p2[storage->temp_1D_abs_data.elements[index].index] += final_weight*final_weight; + + void + write_temp_to_perm_final_p_1D_abs (union abs_logger_data_union* data_union, double final_weight) { + + struct a_1D_abs_storage_struct* storage; + storage = data_union->p_1D_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_abs_data.num_elements; index++) { + storage->Detector_1D.Array_N[storage->temp_1D_abs_data.elements[index].index]++; + + storage->Detector_1D.Array_p[storage->temp_1D_abs_data.elements[index].index] += final_weight; + + storage->Detector_1D.Array_p2[storage->temp_1D_abs_data.elements[index].index] += final_weight * final_weight; + } + clear_temp_1D_abs (data_union); } - clear_temp_1D_abs(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - - // Updates the token - token = strtok(NULL,","); - } -} -#endif + // Updates the token + token = strtok (NULL, ","); + } + } + #endif %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_1D_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_1D_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE @@ -366,132 +373,126 @@ INITIALIZE accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; // Initialize storage from input if (yheight <= 0) { - printf("ERROR, Union abs logger \"%s\" had yheight <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had yheight <= 0.\n", NAME_CURRENT_COMP); + exit (1); } - this_abs_storage.Detector_1D.min = -0.5*yheight; - this_abs_storage.Detector_1D.max = 0.5*yheight; - + this_abs_storage.Detector_1D.min = -0.5 * yheight; + this_abs_storage.Detector_1D.max = 0.5 * yheight; + if (n <= 0) { - printf("ERROR, Union logger \"%s\" had n <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_1D.bins = n; - - + // Remember to take special care when deallocating this array - this_abs_storage.Detector_1D.Array_N = malloc(n*sizeof(double)); - this_abs_storage.Detector_1D.Array_p = malloc(n*sizeof(double)); - this_abs_storage.Detector_1D.Array_p2 = malloc(n*sizeof(double)); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -500,30 +501,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_1D( - this_abs_storage.Detector_1D.title_string, - this_abs_storage.Detector_1D.string_axis, - this_abs_storage.Detector_1D.string_axis_value, - this_abs_storage.Detector_1D.string_axis_short, - this_abs_storage.Detector_1D.min, this_abs_storage.Detector_1D.max, - this_abs_storage.Detector_1D.bins, - &this_abs_storage.Detector_1D.Array_N[0], &this_abs_storage.Detector_1D.Array_p[0], &this_abs_storage.Detector_1D.Array_p2[0], - this_abs_storage.Detector_1D.Filename); + // Write to disk + DETECTOR_OUT_1D (this_abs_storage.Detector_1D.title_string, this_abs_storage.Detector_1D.string_axis, this_abs_storage.Detector_1D.string_axis_value, + this_abs_storage.Detector_1D.string_axis_short, this_abs_storage.Detector_1D.min, this_abs_storage.Detector_1D.max, + this_abs_storage.Detector_1D.bins, &this_abs_storage.Detector_1D.Array_N[0], &this_abs_storage.Detector_1D.Array_p[0], + &this_abs_storage.Detector_1D.Array_p2[0], this_abs_storage.Detector_1D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_abs_storage.temp_1D_abs_data.allocated_elements>0) free(this_abs_storage.temp_1D_abs_data.elements); - -free(this_abs_storage.Detector_1D.Array_N); -free(this_abs_storage.Detector_1D.Array_p); -free(this_abs_storage.Detector_1D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_abs_storage.temp_1D_abs_data.allocated_elements > 0) + free (this_abs_storage.temp_1D_abs_data.elements); + + free (this_abs_storage.Detector_1D.Array_N); + free (this_abs_storage.Detector_1D.Array_p); + free (this_abs_storage.Detector_1D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_abs_logger_1D_space_event.comp b/mcstas-comps/union/Union_abs_logger_1D_space_event.comp index 3f6ae20deb..26769957c7 100644 --- a/mcstas-comps/union/Union_abs_logger_1D_space_event.comp +++ b/mcstas-comps/union/Union_abs_logger_1D_space_event.comp @@ -97,87 +97,89 @@ SETTING PARAMETERS(string target_geometry="NULL", yheight, int n, int fake_event SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_abs_logger_1D_space_event component" -#endif - -// Internally avoids double import -%include "monitor_nd-lib" - -struct temp_abs_1D_event_data_element_struct { - double x_pos; - double y_pos; - double z_pos; - - double x_vel; - double y_vel; - double z_vel; - - double x_pol; - double y_pol; - double z_pol; - - double time; - double weight; -}; - -struct temp_abs_1D_event_data_struct { - int num_elements; - int allocated_elements; - struct temp_abs_1D_event_data_element_struct *elements; -}; - -struct a_1D_event_abs_storage_struct { - MonitornD_Defines_type DEFS; - MonitornD_Variables_type Vars; - - struct temp_abs_1D_event_data_struct temp_abs_1D_event_data; - //some type - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_abs_1D_event(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - struct a_1D_event_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_event_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_abs_logger_1D_space_event component" + #endif + + // Internally avoids double import + %include "monitor_nd-lib" + + struct temp_abs_1D_event_data_element_struct { + double x_pos; + double y_pos; + double z_pos; + + double x_vel; + double y_vel; + double z_vel; + + double x_pol; + double y_pol; + double z_pol; + + double time; + double weight; + }; + + struct temp_abs_1D_event_data_struct { + int num_elements; + int allocated_elements; + struct temp_abs_1D_event_data_element_struct* elements; + }; + + struct a_1D_event_abs_storage_struct { + MonitornD_Defines_type DEFS; + MonitornD_Variables_type Vars; + + struct temp_abs_1D_event_data_struct temp_abs_1D_event_data; + // some type + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_abs_1D_event (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + struct a_1D_event_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_event_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { + if (add_point == 1) { - int i; - double given_x_pos, given_y_pos, given_z_pos; - coords_get(*position, &given_x_pos, &given_y_pos, &given_z_pos); - given_x_pos = 0.0; // 1D monitor, always in center x bin + int i; + double given_x_pos, given_y_pos, given_z_pos; + coords_get (*position, &given_x_pos, &given_y_pos, &given_z_pos); + given_x_pos = 0.0; // 1D monitor, always in center x bin - double given_x_vel, given_y_vel, given_z_vel; - given_x_vel = k[0]*K2V; - given_y_vel = k[1]*K2V; - given_z_vel = k[2]*K2V; + double given_x_vel, given_y_vel, given_z_vel; + given_x_vel = k[0] * K2V; + given_y_vel = k[1] * K2V; + given_z_vel = k[2] * K2V; - if (storage->temp_abs_1D_event_data.num_elements < storage->temp_abs_1D_event_data.allocated_elements) { + if (storage->temp_abs_1D_event_data.num_elements < storage->temp_abs_1D_event_data.allocated_elements) { storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].x_pos = given_x_pos; storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].y_pos = given_y_pos; @@ -190,271 +192,274 @@ void record_to_temp_abs_1D_event(Coords *position, double *k, double p, double t storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].z_pol = 1.0; storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].time = time; storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_abs_1D_event_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_abs_1D_event_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_abs_1D_event_data_element_struct)); - - int index; - for (index=0;indextemp_abs_1D_event_data.num_elements;index++) { - temporary_storage.elements[index].x_pos = storage->temp_abs_1D_event_data.elements[index].x_pos; - temporary_storage.elements[index].y_pos = storage->temp_abs_1D_event_data.elements[index].y_pos; - temporary_storage.elements[index].z_pos = storage->temp_abs_1D_event_data.elements[index].z_pos; - temporary_storage.elements[index].x_vel = storage->temp_abs_1D_event_data.elements[index].x_vel; - temporary_storage.elements[index].y_vel = storage->temp_abs_1D_event_data.elements[index].y_vel; - temporary_storage.elements[index].z_vel = storage->temp_abs_1D_event_data.elements[index].z_vel; - temporary_storage.elements[index].x_pol = storage->temp_abs_1D_event_data.elements[index].x_pol; - temporary_storage.elements[index].y_pol = storage->temp_abs_1D_event_data.elements[index].y_pol; - temporary_storage.elements[index].z_pol = storage->temp_abs_1D_event_data.elements[index].z_pol; - temporary_storage.elements[index].time = storage->temp_abs_1D_event_data.elements[index].time; - temporary_storage.elements[index].weight = storage->temp_abs_1D_event_data.elements[index].weight; - } + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_abs_1D_event_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_abs_1D_event_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_abs_1D_event_data_element_struct)); + + int index; + for (index = 0; index < storage->temp_abs_1D_event_data.num_elements; index++) { + temporary_storage.elements[index].x_pos = storage->temp_abs_1D_event_data.elements[index].x_pos; + temporary_storage.elements[index].y_pos = storage->temp_abs_1D_event_data.elements[index].y_pos; + temporary_storage.elements[index].z_pos = storage->temp_abs_1D_event_data.elements[index].z_pos; + temporary_storage.elements[index].x_vel = storage->temp_abs_1D_event_data.elements[index].x_vel; + temporary_storage.elements[index].y_vel = storage->temp_abs_1D_event_data.elements[index].y_vel; + temporary_storage.elements[index].z_vel = storage->temp_abs_1D_event_data.elements[index].z_vel; + temporary_storage.elements[index].x_pol = storage->temp_abs_1D_event_data.elements[index].x_pol; + temporary_storage.elements[index].y_pol = storage->temp_abs_1D_event_data.elements[index].y_pol; + temporary_storage.elements[index].z_pol = storage->temp_abs_1D_event_data.elements[index].z_pol; + temporary_storage.elements[index].time = storage->temp_abs_1D_event_data.elements[index].time; + temporary_storage.elements[index].weight = storage->temp_abs_1D_event_data.elements[index].weight; + } - // free current data - free(storage->temp_abs_1D_event_data.elements); - - // allocate larger array (10 larger) - storage->temp_abs_1D_event_data.allocated_elements = 10 + storage->temp_abs_1D_event_data.num_elements; - storage->temp_abs_1D_event_data.elements = malloc(storage->temp_abs_1D_event_data.allocated_elements*sizeof(struct temp_abs_1D_event_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_abs_1D_event_data.num_elements;index++) { - storage->temp_abs_1D_event_data.elements[index].x_pos = temporary_storage.elements[index].x_pos; - storage->temp_abs_1D_event_data.elements[index].y_pos = temporary_storage.elements[index].y_pos; - storage->temp_abs_1D_event_data.elements[index].z_pos = temporary_storage.elements[index].z_pos; - storage->temp_abs_1D_event_data.elements[index].x_vel = temporary_storage.elements[index].x_vel; - storage->temp_abs_1D_event_data.elements[index].y_vel = temporary_storage.elements[index].y_vel; - storage->temp_abs_1D_event_data.elements[index].z_vel = temporary_storage.elements[index].z_vel; - storage->temp_abs_1D_event_data.elements[index].x_pol = temporary_storage.elements[index].x_pol; - storage->temp_abs_1D_event_data.elements[index].y_pol = temporary_storage.elements[index].y_pol; - storage->temp_abs_1D_event_data.elements[index].z_pol = temporary_storage.elements[index].z_pol; - storage->temp_abs_1D_event_data.elements[index].time = temporary_storage.elements[index].time; - storage->temp_abs_1D_event_data.elements[index].weight = temporary_storage.elements[index].weight; - } + // free current data + free (storage->temp_abs_1D_event_data.elements); + + // allocate larger array (10 larger) + storage->temp_abs_1D_event_data.allocated_elements = 10 + storage->temp_abs_1D_event_data.num_elements; + storage->temp_abs_1D_event_data.elements + = malloc (storage->temp_abs_1D_event_data.allocated_elements * sizeof (struct temp_abs_1D_event_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_abs_1D_event_data.num_elements; index++) { + storage->temp_abs_1D_event_data.elements[index].x_pos = temporary_storage.elements[index].x_pos; + storage->temp_abs_1D_event_data.elements[index].y_pos = temporary_storage.elements[index].y_pos; + storage->temp_abs_1D_event_data.elements[index].z_pos = temporary_storage.elements[index].z_pos; + storage->temp_abs_1D_event_data.elements[index].x_vel = temporary_storage.elements[index].x_vel; + storage->temp_abs_1D_event_data.elements[index].y_vel = temporary_storage.elements[index].y_vel; + storage->temp_abs_1D_event_data.elements[index].z_vel = temporary_storage.elements[index].z_vel; + storage->temp_abs_1D_event_data.elements[index].x_pol = temporary_storage.elements[index].x_pol; + storage->temp_abs_1D_event_data.elements[index].y_pol = temporary_storage.elements[index].y_pol; + storage->temp_abs_1D_event_data.elements[index].z_pol = temporary_storage.elements[index].z_pol; + storage->temp_abs_1D_event_data.elements[index].time = temporary_storage.elements[index].time; + storage->temp_abs_1D_event_data.elements[index].weight = temporary_storage.elements[index].weight; + } - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].x_pos = given_x_pos; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].y_pos = given_y_pos; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].z_pos = given_z_pos; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].x_vel = given_x_vel; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].y_vel = given_y_vel; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].z_vel = given_z_vel; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].x_pol = 0.0; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].y_pol = 0.0; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].z_pol = 1.0; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].time = time; - storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements++].weight = p; - } + // free temporary data + free (temporary_storage.elements); - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_abs_1D_event_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array,abs_logger); + // add new data point + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].x_pos = given_x_pos; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].y_pos = given_y_pos; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].z_pos = given_z_pos; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].x_vel = given_x_vel; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].y_vel = given_y_vel; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].z_vel = given_z_vel; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].x_pol = 0.0; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].y_pol = 0.0; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].z_pol = 1.0; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements].time = time; + storage->temp_abs_1D_event_data.elements[storage->temp_abs_1D_event_data.num_elements++].weight = p; + } + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_abs_1D_event_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); + } } -} -// clear_temp -void clear_temp_abs_1D_event(union abs_logger_data_union *data_union) { - data_union->p_1D_event_abs_storage->temp_abs_1D_event_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_abs_1D_event(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { + // clear_temp + void + clear_temp_abs_1D_event (union abs_logger_data_union* data_union) { + data_union->p_1D_event_abs_storage->temp_abs_1D_event_data.num_elements = 0; + } - //printf("In record to permanent \n"); - struct a_1D_event_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_event_abs_storage; + // record_to_perm + void + record_to_perm_abs_1D_event (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { - int add_point = 1; + // printf("In record to permanent \n"); + struct a_1D_event_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_event_abs_storage; - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } + int add_point = 1; - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - //printf("storage was set \n"); + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } - double given_x_pos, given_y_pos, given_z_pos; - coords_get(*position, &given_x_pos, &given_y_pos, &given_z_pos); - given_x_pos = 0.0; // 1D monitor, always in center x bin + if (add_point == 1) { + // printf("storage was set \n"); - double given_x_vel, given_y_vel, given_z_vel; - given_x_vel = k[0]*K2V; - given_y_vel = k[1]*K2V; - given_z_vel = k[2]*K2V; + double given_x_pos, given_y_pos, given_z_pos; + coords_get (*position, &given_x_pos, &given_y_pos, &given_z_pos); + given_x_pos = 0.0; // 1D monitor, always in center x bin - _class_particle _localparticle; - _localparticle.x = given_x_pos; - _localparticle.y = given_y_pos; - _localparticle.z = given_z_pos; + double given_x_vel, given_y_vel, given_z_vel; + given_x_vel = k[0] * K2V; + given_y_vel = k[1] * K2V; + given_z_vel = k[2] * K2V; - _localparticle.vx = given_x_vel; - _localparticle.vy = given_y_vel; - _localparticle.vz = given_z_vel; + _class_particle _localparticle; + _localparticle.x = given_x_pos; + _localparticle.y = given_y_pos; + _localparticle.z = given_z_pos; - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; + _localparticle.vx = given_x_vel; + _localparticle.vy = given_y_vel; + _localparticle.vz = given_z_vel; - _localparticle.p = p; - _localparticle.t = time; + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; - int pp; - pp = Monitor_nD_Trace(&(storage->DEFS), &(storage->Vars), &_localparticle); + _localparticle.p = p; + _localparticle.t = time; + int pp; + pp = Monitor_nD_Trace (&(storage->DEFS), &(storage->Vars), &_localparticle); + } } -} - -// write_temp_to_perm -void write_temp_to_perm_abs_1D_event(union abs_logger_data_union *data_union) { - - struct a_1D_event_abs_storage_struct *storage; - storage = data_union->p_1D_event_abs_storage; + // write_temp_to_perm + void + write_temp_to_perm_abs_1D_event (union abs_logger_data_union* data_union) { - int index; - // Add all data points to the histogram, they are saved as index / weight combinations - for (index=0;indextemp_abs_1D_event_data.num_elements;index++) { + struct a_1D_event_abs_storage_struct* storage; + storage = data_union->p_1D_event_abs_storage; - _class_particle _localparticle; + int index; + // Add all data points to the histogram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_abs_1D_event_data.num_elements; index++) { - _localparticle.x = storage->temp_abs_1D_event_data.elements[index].x_pos; - _localparticle.y = storage->temp_abs_1D_event_data.elements[index].y_pos; - _localparticle.z = storage->temp_abs_1D_event_data.elements[index].z_pos; + _class_particle _localparticle; - _localparticle.vx = storage->temp_abs_1D_event_data.elements[index].x_vel; - _localparticle.vy = storage->temp_abs_1D_event_data.elements[index].y_vel; - _localparticle.vz = storage->temp_abs_1D_event_data.elements[index].z_vel; + _localparticle.x = storage->temp_abs_1D_event_data.elements[index].x_pos; + _localparticle.y = storage->temp_abs_1D_event_data.elements[index].y_pos; + _localparticle.z = storage->temp_abs_1D_event_data.elements[index].z_pos; - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; + _localparticle.vx = storage->temp_abs_1D_event_data.elements[index].x_vel; + _localparticle.vy = storage->temp_abs_1D_event_data.elements[index].y_vel; + _localparticle.vz = storage->temp_abs_1D_event_data.elements[index].z_vel; - _localparticle.p = storage->temp_abs_1D_event_data.elements[index].weight; - _localparticle.t = storage->temp_abs_1D_event_data.elements[index].time; + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; - int pp; - pp = Monitor_nD_Trace(&(storage->DEFS), &(storage->Vars), &_localparticle); + _localparticle.p = storage->temp_abs_1D_event_data.elements[index].weight; + _localparticle.t = storage->temp_abs_1D_event_data.elements[index].time; + int pp; + pp = Monitor_nD_Trace (&(storage->DEFS), &(storage->Vars), &_localparticle); + } + clear_temp_abs_1D_event (data_union); } - clear_temp_abs_1D_event(data_union); -} -void write_temp_to_perm_final_p_abs_1D_event(union abs_logger_data_union *data_union, double final_weight) { + void + write_temp_to_perm_final_p_abs_1D_event (union abs_logger_data_union* data_union, double final_weight) { - struct a_1D_event_abs_storage_struct *storage; - storage = data_union->p_1D_event_abs_storage; + struct a_1D_event_abs_storage_struct* storage; + storage = data_union->p_1D_event_abs_storage; - int index; - // Add all data points to the histogram, they are saved as index / weight combinations - for (index=0;indextemp_abs_1D_event_data.num_elements;index++) { + int index; + // Add all data points to the histogram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_abs_1D_event_data.num_elements; index++) { - _class_particle _localparticle; + _class_particle _localparticle; - _localparticle.x = storage->temp_abs_1D_event_data.elements[index].x_pos; - _localparticle.y = storage->temp_abs_1D_event_data.elements[index].y_pos; - _localparticle.z = storage->temp_abs_1D_event_data.elements[index].z_pos; + _localparticle.x = storage->temp_abs_1D_event_data.elements[index].x_pos; + _localparticle.y = storage->temp_abs_1D_event_data.elements[index].y_pos; + _localparticle.z = storage->temp_abs_1D_event_data.elements[index].z_pos; - _localparticle.vx = storage->temp_abs_1D_event_data.elements[index].x_vel; - _localparticle.vy = storage->temp_abs_1D_event_data.elements[index].y_vel; - _localparticle.vz = storage->temp_abs_1D_event_data.elements[index].z_vel; + _localparticle.vx = storage->temp_abs_1D_event_data.elements[index].x_vel; + _localparticle.vy = storage->temp_abs_1D_event_data.elements[index].y_vel; + _localparticle.vz = storage->temp_abs_1D_event_data.elements[index].z_vel; - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; - _localparticle.p = final_weight; - _localparticle.t = storage->temp_abs_1D_event_data.elements[index].time; + _localparticle.p = final_weight; + _localparticle.t = storage->temp_abs_1D_event_data.elements[index].time; - int pp; - pp = Monitor_nD_Trace(&(storage->DEFS), &(storage->Vars), &_localparticle); + int pp; + pp = Monitor_nD_Trace (&(storage->DEFS), &(storage->Vars), &_localparticle); + } + clear_temp_abs_1D_event (data_union); } - clear_temp_abs_1D_event(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indices of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indices of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurrence of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } // Updates the token - token = strtok(NULL,","); - } -} - -#endif + token = strtok (NULL, ","); + } + } + #endif %} DECLARE %{ -int loop_index; -int found_process; -int specified_processes; -//char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + // char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_1D_event_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_1D_event_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; -double bufsize; + double bufsize; %} INITIALIZE @@ -470,69 +475,69 @@ INITIALIZE // Input sanitation for filename apparently done in 1D_detector_out - long element_size=85; /* mean size per neutron for ascii storing */ + long element_size = 85; /* mean size per neutron for ascii storing */ - strcpy(this_abs_storage.Vars.compcurname, NAME_CURRENT_COMP); + strcpy (this_abs_storage.Vars.compcurname, NAME_CURRENT_COMP); char option_string_part[256]; - sprintf(this_abs_storage.Vars.option, "mantid square x limits=[-0.0005,0.0005] bins=3 y limits=[%f %f] bins=%i", -0.5*yheight, 0.5*yheight, n); + sprintf (this_abs_storage.Vars.option, "mantid square x limits=[-0.0005,0.0005] bins=3 y limits=[%f %f] bins=%i", -0.5 * yheight, 0.5 * yheight, n); -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_abs_logger_1D_space_event:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_abs_logger_1D_space_event:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -// Need to tell the monitor from what integer its pixel id range starts, and it necessary to avoid overlaps. + // Need to tell the monitor from what integer its pixel id range starts, and it necessary to avoid overlaps. // global_mantid_min_pixel_id is initialized as 0, and each monitor adds its number of pixels to avoid overlap. - int global_mantid_min_pixel_id = (int)COMP_GETPAR3(Union_init, init, global_mantid_min_pixel_id); - sprintf(option_string_part,", neutron pixel min=%i t, list all neutrons", global_mantid_min_pixel_id); - global_mantid_min_pixel_id += 3*n; + int global_mantid_min_pixel_id = (int)COMP_GETPAR3 (Union_init, init, global_mantid_min_pixel_id); + sprintf (option_string_part, ", neutron pixel min=%i t, list all neutrons", global_mantid_min_pixel_id); + global_mantid_min_pixel_id += 3 * n; - strcat(this_abs_storage.Vars.option, option_string_part); // hardcoded min=0 for now - printf("Monitor_nD option string: %s\n", this_abs_storage.Vars.option); + strcat (this_abs_storage.Vars.option, option_string_part); // hardcoded min=0 for now + printf ("Monitor_nD option string: %s\n", this_abs_storage.Vars.option); - Monitor_nD_Init(&this_abs_storage.DEFS, &this_abs_storage.Vars, 0.001, yheight, 0, 0,0,0,0,0,0,0); /* dims for mcdisplay */ + Monitor_nD_Init (&this_abs_storage.DEFS, &this_abs_storage.Vars, 0.001, yheight, 0, 0, 0, 0, 0, 0, 0, 0); /* dims for mcdisplay */ this_abs_storage.Vars.compcurpos = POS_A_CURRENT_COMP; - if (filename && strlen(filename) && strcmp(filename,"NULL") && strcmp(filename,"0")) - strncpy(this_abs_storage.Vars.Mon_File, filename, 128); + if (filename && strlen (filename) && strcmp (filename, "NULL") && strcmp (filename, "0")) + strncpy (this_abs_storage.Vars.Mon_File, filename, 128); if (bufsize > 0) - printf("Warning: Virtual_output: %s: buffer size=%g not recommended\n", NAME_CURRENT_COMP, bufsize); - if (bufsize > 0) printf( - "Virtual_output: %s: Beware virtual output generated file size (max %g Mo)\n" - "WARNING Memory required is %g Mo\n", NAME_CURRENT_COMP, - bufsize*element_size/1e6, bufsize*sizeof(double)/1e6); + printf ("Warning: Virtual_output: %s: buffer size=%g not recommended\n", NAME_CURRENT_COMP, bufsize); + if (bufsize > 0) + printf ("Virtual_output: %s: Beware virtual output generated file size (max %g Mo)\n" + "WARNING Memory required is %g Mo\n", + NAME_CURRENT_COMP, bufsize* element_size / 1e6, bufsize * sizeof (double) / 1e6); this_abs_storage.order = order_total; this_abs_storage.order_in_this_volume = order_volume; - this_abs_storage.temp_abs_1D_event_data.num_elements=0; + this_abs_storage.temp_abs_1D_event_data.num_elements = 0; this_abs_storage.temp_abs_1D_event_data.allocated_elements = 10; - this_abs_storage.temp_abs_1D_event_data.elements = malloc(this_abs_storage.temp_abs_1D_event_data.allocated_elements*sizeof(struct temp_abs_1D_event_data_element_struct)); + this_abs_storage.temp_abs_1D_event_data.elements + = malloc (this_abs_storage.temp_abs_1D_event_data.allocated_elements * sizeof (struct temp_abs_1D_event_data_element_struct)); - struct global_positions_to_transform_list_struct *global_positions_to_transform_list = COMP_GETPAR3(Union_init, init, global_positions_to_transform_list); - struct global_rotations_to_transform_list_struct *global_rotations_to_transform_list = COMP_GETPAR3(Union_init, init, global_rotations_to_transform_list); + struct global_positions_to_transform_list_struct* global_positions_to_transform_list = COMP_GETPAR3 (Union_init, init, global_positions_to_transform_list); + struct global_rotations_to_transform_list_struct* global_rotations_to_transform_list = COMP_GETPAR3 (Union_init, init, global_rotations_to_transform_list); // Test position and rotation stored in a data storage, and pointers assigned to transform lists this_abs_logger.position = POS_A_CURRENT_COMP; - add_position_pointer_to_list(global_positions_to_transform_list, &this_abs_logger.position); + add_position_pointer_to_list (global_positions_to_transform_list, &this_abs_logger.position); - rot_copy(this_abs_logger.rotation,ROT_A_CURRENT_COMP); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_abs_logger.rotation); + rot_copy (this_abs_logger.rotation, ROT_A_CURRENT_COMP); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_abs_logger.rotation); - rot_transpose(ROT_A_CURRENT_COMP,this_abs_logger.t_rotation); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_abs_logger.t_rotation); + rot_transpose (ROT_A_CURRENT_COMP, this_abs_logger.t_rotation); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_abs_logger.t_rotation); // Adding fake event to combat MPI writing bug if (fake_event) { _class_particle _localparticle; - _localparticle.x = 0.0; - _localparticle.y = 0.0; - _localparticle.z = -1.0; + _localparticle.x = 0.0; + _localparticle.y = 0.0; + _localparticle.z = -1.0; _localparticle.vx = 0.0; _localparticle.vy = 0.0; @@ -542,21 +547,19 @@ exit(-1); _localparticle.sy = 0.0; _localparticle.sz = 1.0; - _localparticle.p = 0.0; - _localparticle.t = 0.0; + _localparticle.p = 0.0; + _localparticle.t = 0.0; int pp; - pp = Monitor_nD_Trace(&(this_abs_storage.DEFS), &(this_abs_storage.Vars), &_localparticle); + pp = Monitor_nD_Trace (&(this_abs_storage.DEFS), &(this_abs_storage.Vars), &_localparticle); } - - // Book keeping this_abs_logger.abs_logger_extend_index = logger_conditional_extend_index; - this_abs_logger.function_pointers.active_record_function = &record_to_perm_abs_1D_event; // Assume no conditional + this_abs_logger.function_pointers.active_record_function = &record_to_perm_abs_1D_event; // Assume no conditional this_abs_logger.function_pointers.inactive_record_function = &record_to_temp_abs_1D_event; // If an assume is present, these two pointers are switched // Temp to perm functions, and standard identifier - //this_abs_logger.function_pointers.select_t_to_p = 1; // 1: temp_to_perm, 2: temp_to_perm_final_p // Not relevant for abs + // this_abs_logger.function_pointers.select_t_to_p = 1; // 1: temp_to_perm, 2: temp_to_perm_final_p // Not relevant for abs this_abs_logger.function_pointers.temp_to_perm = &write_temp_to_perm_abs_1D_event; this_abs_logger.function_pointers.temp_to_perm_final_p = &write_temp_to_perm_final_p_abs_1D_event; this_abs_logger.function_pointers.clear_temp = &clear_temp_abs_1D_event; @@ -565,39 +568,36 @@ exit(-1); this_abs_logger.conditional_list.num_elements = 0; this_abs_logger.data_union.p_1D_event_abs_storage = &this_abs_storage; - sprintf(this_abs_logger.name,"%s",NAME_CURRENT_COMP); - sprintf(abs_logger_list_element.name,"%s",NAME_CURRENT_COMP); + sprintf (this_abs_logger.name, "%s", NAME_CURRENT_COMP); + sprintf (abs_logger_list_element.name, "%s", NAME_CURRENT_COMP); abs_logger_list_element.component_index = INDEX_CURRENT_COMP; abs_logger_list_element.abs_logger = &this_abs_logger; - struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); - struct pointer_to_global_abs_logger_list *global_specific_volumes_abs_logger_list = COMP_GETPAR3(Union_init, init, global_specific_volumes_abs_logger_list); + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + struct pointer_to_global_abs_logger_list* global_specific_volumes_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_specific_volumes_abs_logger_list); // In order to run the logger at the right times, pointers to this logger is stored in each volume it logs, // and additionally for each available process. If a process is not logged, the pointer is simply not stored. int process_index; // Need to find the volumes for which the processes should have a reference to this logger - if (target_geometry && strlen(target_geometry) && strcmp(target_geometry,"NULL") && strcmp(target_geometry, "0")) { + if (target_geometry && strlen (target_geometry) && strcmp (target_geometry, "NULL") && strcmp (target_geometry, "0")) { // Certain volumes were selected, find the indices in the global_geometry_list - manual_linking_function_abs_logger_volumes(target_geometry, global_geometry_list, &accepted_volumes, NAME_CURRENT_COMP); + manual_linking_function_abs_logger_volumes (target_geometry, global_geometry_list, &accepted_volumes, NAME_CURRENT_COMP); // Add this logger to the global_specific_volumes_logger_list (so that conditionals can affect it) - add_element_to_abs_logger_list(global_specific_volumes_abs_logger_list, abs_logger_list_element); + add_element_to_abs_logger_list (global_specific_volumes_abs_logger_list, abs_logger_list_element); - for (loop_index=0;loop_indexelements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -606,34 +606,35 @@ TRACE SAVE %{ - Monitor_nD_Save(&(this_abs_storage.DEFS), &(this_abs_storage.Vars)); + Monitor_nD_Save (&(this_abs_storage.DEFS), &(this_abs_storage.Vars)); %} FINALLY %{ -/* free pointers */ - Monitor_nD_Finally(&this_abs_storage.DEFS, &this_abs_storage.Vars); + /* free pointers */ + Monitor_nD_Finally (&this_abs_storage.DEFS, &this_abs_storage.Vars); if (bufsize) { - printf("Virtual_output: %s: Saved %llu events (from buffer) in file %s\n", - NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); + printf ("Virtual_output: %s: Saved %llu events (from buffer) in file %s\n", NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); if (bufsize < this_abs_storage.Vars.Nsum) - printf("WARNING When using this source, intensities must be multiplied\n" - " by a factor %g\n", (double)this_abs_storage.Vars.Nsum/(double)bufsize); - } else printf("Virtual_output: %s: Saved %llu events (all) in file %s\n", NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); - -// Remember to clean up allocated lists -if (this_abs_storage.temp_abs_1D_event_data.allocated_elements>0) free(this_abs_storage.temp_abs_1D_event_data.elements); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - - - + printf ("WARNING When using this source, intensities must be multiplied\n" + " by a factor %g\n", + (double)this_abs_storage.Vars.Nsum / (double)bufsize); + } else + printf ("Virtual_output: %s: Saved %llu events (all) in file %s\n", NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); + + // Remember to clean up allocated lists + if (this_abs_storage.temp_abs_1D_event_data.allocated_elements > 0) + free (this_abs_storage.temp_abs_1D_event_data.elements); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} MCDISPLAY %{ - Monitor_nD_McDisplay(&(this_abs_storage.DEFS), &(this_abs_storage.Vars)); + Monitor_nD_McDisplay (&(this_abs_storage.DEFS), &(this_abs_storage.Vars)); %} END diff --git a/mcstas-comps/union/Union_abs_logger_1D_space_tof.comp b/mcstas-comps/union/Union_abs_logger_1D_space_tof.comp index 51abdddd4f..a2dcb4afd5 100644 --- a/mcstas-comps/union/Union_abs_logger_1D_space_tof.comp +++ b/mcstas-comps/union/Union_abs_logger_1D_space_tof.comp @@ -92,313 +92,327 @@ SETTING PARAMETERS(string target_geometry="NULL", SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_abs_logger_1D_space_tof component" -#endif - -struct temp_1D_time_abs_data_element_struct { - int index_1; - int index_2; - double weight; -}; - -struct temp_1D_time_abs_data_struct { - int num_elements; - int allocated_elements; - struct temp_1D_time_abs_data_element_struct *elements; -}; - -struct a_1D_time_abs_storage_struct { - struct Detector_2D_struct Detector_2D; - struct temp_1D_time_abs_data_struct temp_1D_time_abs_data; - int order; - int order_in_this_volume; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_1D_time_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - struct a_1D_time_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_time_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_abs_logger_1D_space_tof component" + #endif + + struct temp_1D_time_abs_data_element_struct { + int index_1; + int index_2; + double weight; + }; + + struct temp_1D_time_abs_data_struct { + int num_elements; + int allocated_elements; + struct temp_1D_time_abs_data_element_struct* elements; + }; + + struct a_1D_time_abs_storage_struct { + struct Detector_2D_struct Detector_2D; + struct temp_1D_time_abs_data_struct temp_1D_time_abs_data; + int order; + int order_in_this_volume; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_1D_time_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + struct a_1D_time_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_time_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - double p1,p2; - - double dummy1, dummy2; - - //value = position.y; // define makes this not work - coords_get(*position, &dummy1, &p1, &dummy2); - p2 = time; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - i = floor((p1 - storage->Detector_2D.D1min)*storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_1D_time_abs_data.num_elements,storage->temp_1D_time_abs_data.allocated_elements); - - if (storage->temp_1D_time_abs_data.num_elements < storage->temp_1D_time_abs_data.allocated_elements) { - storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_1 = i; - storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_2 = j; - storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_1D_time_abs_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_1D_time_abs_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_1D_time_abs_data_element_struct)); - - for (index=0;indextemp_1D_time_abs_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_1D_time_abs_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_1D_time_abs_data.elements[index].index_2; - temporary_storage.elements[index].weight = storage->temp_1D_time_abs_data.elements[index].weight; - } - - // free current data - free(storage->temp_1D_time_abs_data.elements); - - // allocate larger array (10 larger) - storage->temp_1D_time_abs_data.allocated_elements = 10 + storage->temp_1D_time_abs_data.num_elements; - storage->temp_1D_time_abs_data.elements = malloc(storage->temp_1D_time_abs_data.allocated_elements*sizeof(struct temp_1D_time_abs_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_1D_time_abs_data.num_elements;index++) { - storage->temp_1D_time_abs_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_1D_time_abs_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_1D_time_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double p1, p2; + + double dummy1, dummy2; + + // value = position.y; // define makes this not work + coords_get (*position, &dummy1, &p1, &dummy2); + p2 = time; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + i = floor ((p1 - storage->Detector_2D.D1min) * storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_1D_time_abs_data.num_elements,storage->temp_1D_time_abs_data.allocated_elements); + + if (storage->temp_1D_time_abs_data.num_elements < storage->temp_1D_time_abs_data.allocated_elements) { + storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_1 = i; + storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_2 = j; + storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_1D_time_abs_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_1D_time_abs_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_1D_time_abs_data_element_struct)); + + for (index = 0; index < storage->temp_1D_time_abs_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_1D_time_abs_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_1D_time_abs_data.elements[index].index_2; + temporary_storage.elements[index].weight = storage->temp_1D_time_abs_data.elements[index].weight; + } + + // free current data + free (storage->temp_1D_time_abs_data.elements); + + // allocate larger array (10 larger) + storage->temp_1D_time_abs_data.allocated_elements = 10 + storage->temp_1D_time_abs_data.num_elements; + storage->temp_1D_time_abs_data.elements + = malloc (storage->temp_1D_time_abs_data.allocated_elements * sizeof (struct temp_1D_time_abs_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_1D_time_abs_data.num_elements; index++) { + storage->temp_1D_time_abs_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_1D_time_abs_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_1D_time_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_1 = i; + storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_2 = j; + storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_1 = i; - storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements].index_2 = j; - storage->temp_1D_time_abs_data.elements[storage->temp_1D_time_abs_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_1D_time_abs_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_1D_time_abs_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array, abs_logger); - } } - -} - -// clear_temp -void clear_temp_1D_time_abs(union abs_logger_data_union *data_union) { - data_union->p_1D_time_abs_storage->temp_1D_time_abs_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_1D_time_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_1D_time_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_time_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_1D_time_abs (union abs_logger_data_union* data_union) { + data_union->p_1D_time_abs_storage->temp_1D_time_abs_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double p1, p2; - - double dummy1, dummy2; - - //value = position.y; // define makes this not work - coords_get(*position, &dummy1, &p1, &dummy2); - p2 = time; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - - i = floor((p1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_2D.Array_N[i][j]++; - storage->Detector_2D.Array_p[i][j] += p; - storage->Detector_2D.Array_p2[i][j] += p*p; - + // record_to_perm + void + record_to_perm_1D_time_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_1D_time_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_time_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double p1, p2; + + double dummy1, dummy2; + + // value = position.y; // define makes this not work + coords_get (*position, &dummy1, &p1, &dummy2); + p2 = time; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + + i = floor ((p1 - storage->Detector_2D.D1min) * (double)storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * (double)storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_2D.Array_N[i][j]++; + storage->Detector_2D.Array_p[i][j] += p; + storage->Detector_2D.Array_p2[i][j] += p * p; + } } } -} - -// write_temp_to_perm -void write_temp_to_perm_1D_time_abs(union abs_logger_data_union *data_union) { - struct a_1D_time_abs_storage_struct *storage; - storage = data_union->p_1D_time_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_time_abs_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] += storage->temp_1D_time_abs_data.elements[index].weight; - - storage->Detector_2D.Array_p2[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] += storage->temp_1D_time_abs_data.elements[index].weight*storage->temp_1D_time_abs_data.elements[index].weight; + // write_temp_to_perm + void + write_temp_to_perm_1D_time_abs (union abs_logger_data_union* data_union) { + struct a_1D_time_abs_storage_struct* storage; + storage = data_union->p_1D_time_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_time_abs_data.num_elements; index++) { + + storage->Detector_2D.Array_N[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] + += storage->temp_1D_time_abs_data.elements[index].weight; + + storage->Detector_2D.Array_p2[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] + += storage->temp_1D_time_abs_data.elements[index].weight * storage->temp_1D_time_abs_data.elements[index].weight; + } + + clear_temp_1D_time_abs (data_union); } - - clear_temp_1D_time_abs(data_union); -} - -// write_temp_to_perm_final_p -void write_temp_to_perm_final_p_1D_time_abs(union abs_logger_data_union *data_union, double final_weight) { - struct a_1D_time_abs_storage_struct *storage; - storage = data_union->p_1D_time_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_time_abs_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] += final_weight; - - storage->Detector_2D.Array_p2[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] += final_weight*final_weight; + + // write_temp_to_perm_final_p + void + write_temp_to_perm_final_p_1D_time_abs (union abs_logger_data_union* data_union, double final_weight) { + struct a_1D_time_abs_storage_struct* storage; + storage = data_union->p_1D_time_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_time_abs_data.num_elements; index++) { + + storage->Detector_2D.Array_N[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] + += final_weight; + + storage->Detector_2D.Array_p2[storage->temp_1D_time_abs_data.elements[index].index_1][storage->temp_1D_time_abs_data.elements[index].index_2] + += final_weight * final_weight; + } + + clear_temp_1D_time_abs (data_union); } - - clear_temp_1D_time_abs(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif + token = strtok (NULL, ","); + } + } + #endif -double** allocate2Ddouble_1D_time_abs(int count_x, int count_y) { + double** + allocate2Ddouble_1D_time_abs (int count_x, int count_y) { // This function is needed to dynamically declare an array // that has continous data as a static array would have, // as that is the format expected by DETECTOR_OUT_2D. int i; // allocate space for actual data - //double *data = malloc(sizeof(double) * count_x * count_y); - double *data = malloc(sizeof(double) * (count_x+1) * (count_y+1)); + // double *data = malloc(sizeof(double) * count_x * count_y); + double* data = malloc (sizeof (double) * (count_x + 1) * (count_y + 1)); // create array or pointers to first elem in each 2D row - //double **ptr_array = malloc(sizeof(double*) * count_x); - double **ptr_array = malloc(sizeof(double*) * (count_x+1)); + // double **ptr_array = malloc(sizeof(double*) * count_x); + double** ptr_array = malloc (sizeof (double*) * (count_x + 1)); for (i = 0; i < count_x; i++) { - ptr_array[i] = data + (i*count_y); + ptr_array[i] = data + (i * count_y); } return ptr_array; -} - -void free2Ddouble_1D_time_abs(double** ptr_array) { - if (!ptr_array) return; - if (ptr_array[0]) free(ptr_array[0]); - free(ptr_array); -} + } + void + free2Ddouble_1D_time_abs (double** ptr_array) { + if (!ptr_array) + return; + if (ptr_array[0]) + free (ptr_array[0]); + free (ptr_array); + } %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -int loop_index; -int found_process; -int specified_processes; -//char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + // char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_1D_time_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_1D_time_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE @@ -406,146 +420,140 @@ INITIALIZE accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; // Initialize storage from input if (yheight <= 0) { - printf("ERROR, Union abs logger \"%s\" had yheight <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had yheight <= 0.\n", NAME_CURRENT_COMP); + exit (1); } - - this_abs_storage.Detector_2D.D1min = -0.5*yheight; - this_abs_storage.Detector_2D.D1max = 0.5*yheight; - + + this_abs_storage.Detector_2D.D1min = -0.5 * yheight; + this_abs_storage.Detector_2D.D1max = 0.5 * yheight; + if (n <= 0) { - printf("ERROR, Union logger \"%s\" had n <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_2D.bins_1 = n; - + if (time_min >= time_max) { - printf("ERROR, Union abs logger \"%s\" had time_min larger than time_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had time_min larger than time_max.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_2D.D2min = time_min; this_abs_storage.Detector_2D.D2max = time_max; - + if (time_bins <= 0) { - printf("ERROR, Union logger \"%s\" had time_bins <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had time_bins <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_2D.bins_2 = time_bins; - - //printf("past input sanitation \n"); - - + + // printf("past input sanitation \n"); + // Remember to take special care when deallocating this array, use free2Ddouble - this_abs_storage.Detector_2D.Array_N = allocate2Ddouble_1D_time_abs(n, time_bins); - this_abs_storage.Detector_2D.Array_p = allocate2Ddouble_1D_time_abs(n, time_bins); - this_abs_storage.Detector_2D.Array_p2 = allocate2Ddouble_1D_time_abs(n, time_bins); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -554,31 +562,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_2D( - this_abs_storage.Detector_2D.title_string, - this_abs_storage.Detector_2D.string_axis_1, - this_abs_storage.Detector_2D.string_axis_2, - this_abs_storage.Detector_2D.D1min, this_abs_storage.Detector_2D.D1max, - this_abs_storage.Detector_2D.D2min, this_abs_storage.Detector_2D.D2max, - this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2, - *this_abs_storage.Detector_2D.Array_N, *this_abs_storage.Detector_2D.Array_p, *this_abs_storage.Detector_2D.Array_p2, - this_abs_storage.Detector_2D.Filename); - + // Write to disk + DETECTOR_OUT_2D (this_abs_storage.Detector_2D.title_string, this_abs_storage.Detector_2D.string_axis_1, this_abs_storage.Detector_2D.string_axis_2, + this_abs_storage.Detector_2D.D1min, this_abs_storage.Detector_2D.D1max, this_abs_storage.Detector_2D.D2min, this_abs_storage.Detector_2D.D2max, + this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2, *this_abs_storage.Detector_2D.Array_N, + *this_abs_storage.Detector_2D.Array_p, *this_abs_storage.Detector_2D.Array_p2, this_abs_storage.Detector_2D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_abs_storage.temp_1D_time_abs_data.allocated_elements>0) free(this_abs_storage.temp_1D_time_abs_data.elements); - -free2Ddouble_1D_time_abs(this_abs_storage.Detector_2D.Array_N); -free2Ddouble_1D_time_abs(this_abs_storage.Detector_2D.Array_p); -free2Ddouble_1D_time_abs(this_abs_storage.Detector_2D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_abs_storage.temp_1D_time_abs_data.allocated_elements > 0) + free (this_abs_storage.temp_1D_time_abs_data.elements); + + free2Ddouble_1D_time_abs (this_abs_storage.Detector_2D.Array_N); + free2Ddouble_1D_time_abs (this_abs_storage.Detector_2D.Array_p); + free2Ddouble_1D_time_abs (this_abs_storage.Detector_2D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_abs_logger_1D_space_tof_to_lambda.comp b/mcstas-comps/union/Union_abs_logger_1D_space_tof_to_lambda.comp index f363c54f0b..25082cff5a 100644 --- a/mcstas-comps/union/Union_abs_logger_1D_space_tof_to_lambda.comp +++ b/mcstas-comps/union/Union_abs_logger_1D_space_tof_to_lambda.comp @@ -126,385 +126,403 @@ SETTING PARAMETERS(string target_geometry="NULL", SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_abs_logger_1D_space_tof_to_lambda component" -#endif - -struct temp_1D_time_to_lambda_abs_data_element_struct { - int index_1; - int index_2; - double weight; -}; - -struct temp_1D_time_to_lambda_abs_data_struct { - int num_elements; - int allocated_elements; - struct temp_1D_time_to_lambda_abs_data_element_struct *elements; -}; - -struct a_1D_time_to_lambda_abs_storage_struct { - struct Detector_2D_struct Detector_2D; - struct temp_1D_time_to_lambda_abs_data_struct temp_1D_time_to_lambda_abs_data; - int order; - int order_in_this_volume; - double y_min; - double y_max; - double y_bins; - Coords sample_pos; - int transformed; - //Coords *logger_position; - Coords logger_position; - Rotation *logger_rotation; - double source_to_sample_dist; - int relative; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_1D_time_to_lambda_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - struct a_1D_time_to_lambda_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_time_to_lambda_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) + #ifndef Union + #error "The Union_init component must be included before this Union_abs_logger_1D_space_tof_to_lambda component" + #endif + + struct temp_1D_time_to_lambda_abs_data_element_struct { + int index_1; + int index_2; + double weight; + }; + + struct temp_1D_time_to_lambda_abs_data_struct { + int num_elements; + int allocated_elements; + struct temp_1D_time_to_lambda_abs_data_element_struct* elements; + }; + + struct a_1D_time_to_lambda_abs_storage_struct { + struct Detector_2D_struct Detector_2D; + struct temp_1D_time_to_lambda_abs_data_struct temp_1D_time_to_lambda_abs_data; + int order; + int order_in_this_volume; + double y_min; + double y_max; + double y_bins; + Coords sample_pos; + int transformed; + // Coords *logger_position; + Coords logger_position; + Rotation* logger_rotation; + double source_to_sample_dist; + int relative; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_1D_time_to_lambda_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + struct a_1D_time_to_lambda_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_time_to_lambda_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + // Bin y_position + int y_bin; + double dummy1, y_pos, dummy2; + coords_get (*position, &dummy1, &y_pos, &dummy2); + + if (y_pos > storage->y_min && y_pos < storage->y_max) { add_point = 1; - else + y_bin = floor ((y_pos - storage->y_min) * storage->y_bins / (storage->y_max - storage->y_min)); + y_pos = (y_bin + 0.5) * (storage->y_max - storage->y_min) / storage->y_bins + storage->y_min; // Now binned y_pos + } else { add_point = 0; - } - - - // Bin y_position - int y_bin; - double dummy1, y_pos, dummy2; - coords_get(*position, &dummy1, &y_pos, &dummy2); - - if (y_pos > storage->y_min && y_pos < storage->y_max) { - add_point = 1; - y_bin = floor((y_pos - storage->y_min)*storage->y_bins/(storage->y_max - storage->y_min)); - y_pos = (y_bin + 0.5)*(storage->y_max - storage->y_min)/storage->y_bins + storage->y_min; // Now binned y_pos - } else { - add_point = 0; - } - - if (add_point == 1) { - - double p1,p2; - - // Wavelength from velocity - double k_length = sqrt(k[0]*k[0]+k[1]*k[1]+k[2]*k[2]); - p1 = 2.0*PI/k_length; - - // Transform sample_pos to logger coordinate system - if (storage->transformed == 0) { - //storage->sample_pos = coords_sub(storage->sample_pos, *(storage->logger_position)); - storage->sample_pos = coords_sub(storage->sample_pos, storage->logger_position); - storage->sample_pos = rot_apply(*(storage->logger_rotation), storage->sample_pos); - storage->transformed = 1; } - double distance, speed; - // Wavelength from tof - distance = sqrt( (storage->sample_pos.x - 0.0)*(storage->sample_pos.x - 0.0) - + (storage->sample_pos.y - y_pos)*(storage->sample_pos.y - y_pos) - + (storage->sample_pos.z - 0.0)*(storage->sample_pos.z - 0.0) ); - distance += storage->source_to_sample_dist; - speed = distance/time; - p2 = 2.0*PI/(speed*V2K); - - if (storage->relative == 1) p2 /= p1; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - i = floor((p1 - storage->Detector_2D.D1min)*storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_1D_time_to_lambda_abs_data.num_elements,storage->temp_1D_time_to_lambda_abs_data.allocated_elements); - - if (storage->temp_1D_time_to_lambda_abs_data.num_elements < storage->temp_1D_time_to_lambda_abs_data.allocated_elements) { - storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_1 = i; - storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_2 = j; - storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_1D_time_to_lambda_abs_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_1D_time_to_lambda_abs_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_1D_time_to_lambda_abs_data_element_struct)); - - for (index=0;indextemp_1D_time_to_lambda_abs_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2; - temporary_storage.elements[index].weight = storage->temp_1D_time_to_lambda_abs_data.elements[index].weight; - } - - // free current data - free(storage->temp_1D_time_to_lambda_abs_data.elements); - - // allocate larger array (10 larger) - storage->temp_1D_time_to_lambda_abs_data.allocated_elements = 10 + storage->temp_1D_time_to_lambda_abs_data.num_elements; - storage->temp_1D_time_to_lambda_abs_data.elements = malloc(storage->temp_1D_time_to_lambda_abs_data.allocated_elements*sizeof(struct temp_1D_time_to_lambda_abs_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_1D_time_to_lambda_abs_data.num_elements;index++) { - storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_1D_time_to_lambda_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + if (add_point == 1) { + + double p1, p2; + + // Wavelength from velocity + double k_length = sqrt (k[0] * k[0] + k[1] * k[1] + k[2] * k[2]); + p1 = 2.0 * PI / k_length; + + // Transform sample_pos to logger coordinate system + if (storage->transformed == 0) { + // storage->sample_pos = coords_sub(storage->sample_pos, *(storage->logger_position)); + storage->sample_pos = coords_sub (storage->sample_pos, storage->logger_position); + storage->sample_pos = rot_apply (*(storage->logger_rotation), storage->sample_pos); + storage->transformed = 1; + } + + double distance, speed; + // Wavelength from tof + distance = sqrt ((storage->sample_pos.x - 0.0) * (storage->sample_pos.x - 0.0) + (storage->sample_pos.y - y_pos) * (storage->sample_pos.y - y_pos) + + (storage->sample_pos.z - 0.0) * (storage->sample_pos.z - 0.0)); + distance += storage->source_to_sample_dist; + speed = distance / time; + p2 = 2.0 * PI / (speed * V2K); + + if (storage->relative == 1) + p2 /= p1; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + i = floor ((p1 - storage->Detector_2D.D1min) * storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_1D_time_to_lambda_abs_data.num_elements,storage->temp_1D_time_to_lambda_abs_data.allocated_elements); + + if (storage->temp_1D_time_to_lambda_abs_data.num_elements < storage->temp_1D_time_to_lambda_abs_data.allocated_elements) { + storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_1 = i; + storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_2 = j; + storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_1D_time_to_lambda_abs_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_1D_time_to_lambda_abs_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_1D_time_to_lambda_abs_data_element_struct)); + + for (index = 0; index < storage->temp_1D_time_to_lambda_abs_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2; + temporary_storage.elements[index].weight = storage->temp_1D_time_to_lambda_abs_data.elements[index].weight; + } + + // free current data + free (storage->temp_1D_time_to_lambda_abs_data.elements); + + // allocate larger array (10 larger) + storage->temp_1D_time_to_lambda_abs_data.allocated_elements = 10 + storage->temp_1D_time_to_lambda_abs_data.num_elements; + storage->temp_1D_time_to_lambda_abs_data.elements + = malloc (storage->temp_1D_time_to_lambda_abs_data.allocated_elements * sizeof (struct temp_1D_time_to_lambda_abs_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_1D_time_to_lambda_abs_data.num_elements; index++) { + storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_1D_time_to_lambda_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_1 = i; + storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_2 = j; + storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_1 = i; - storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements].index_2 = j; - storage->temp_1D_time_to_lambda_abs_data.elements[storage->temp_1D_time_to_lambda_abs_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_1D_time_to_lambda_abs_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_1D_time_to_lambda_abs_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array, abs_logger); - } } - -} -// clear_temp -void clear_temp_1D_time_to_lambda_abs(union abs_logger_data_union *data_union) { - data_union->p_1D_time_to_lambda_abs_storage->temp_1D_time_to_lambda_abs_data.num_elements = 0; -} + // clear_temp + void + clear_temp_1D_time_to_lambda_abs (union abs_logger_data_union* data_union) { + data_union->p_1D_time_to_lambda_abs_storage->temp_1D_time_to_lambda_abs_data.num_elements = 0; + } -// record_to_perm -void record_to_perm_1D_time_to_lambda_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_1D_time_to_lambda_abs_storage_struct *storage; - storage = abs_logger->data_union.p_1D_time_to_lambda_abs_storage; + // record_to_perm + void + record_to_perm_1D_time_to_lambda_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { - int add_point = 1; + // printf("In record to permanent \n"); + struct a_1D_time_to_lambda_abs_storage_struct* storage; + storage = abs_logger->data_union.p_1D_time_to_lambda_abs_storage; - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + // Bin y_position + int y_bin; + double dummy1, y_pos, dummy2; + coords_get (*position, &dummy1, &y_pos, &dummy2); + + if (y_pos > storage->y_min && y_pos < storage->y_max) { add_point = 1; - else + y_bin = floor ((y_pos - storage->y_min) * storage->y_bins / (storage->y_max - storage->y_min)); + y_pos = (y_bin + 0.5) * (storage->y_max - storage->y_min) / storage->y_bins + storage->y_min; // Now binned y_pos + } else { add_point = 0; - } + } - // Bin y_position - int y_bin; - double dummy1, y_pos, dummy2; - coords_get(*position, &dummy1, &y_pos, &dummy2); - - if (y_pos > storage->y_min && y_pos < storage->y_max) { - add_point = 1; - y_bin = floor((y_pos - storage->y_min)*storage->y_bins/(storage->y_max - storage->y_min)); - y_pos = (y_bin + 0.5)*(storage->y_max - storage->y_min)/storage->y_bins + storage->y_min; // Now binned y_pos - } else { - add_point = 0; - } + if (add_point == 1) { - if (add_point == 1) { - - double p1,p2; - - // Wavelength from velocity - double k_length = sqrt(k[0]*k[0]+k[1]*k[1]+k[2]*k[2]); - p1 = 2.0*PI/k_length; - - // Transform sample_pos to logger coordinate system - if (storage->transformed == 0) { - //storage->sample_pos = coords_sub(storage->sample_pos, *(storage->logger_position)); - storage->sample_pos = coords_sub(storage->sample_pos, storage->logger_position); - storage->sample_pos = rot_apply(*(storage->logger_rotation), storage->sample_pos); - storage->transformed = 1; - } + double p1, p2; + + // Wavelength from velocity + double k_length = sqrt (k[0] * k[0] + k[1] * k[1] + k[2] * k[2]); + p1 = 2.0 * PI / k_length; + + // Transform sample_pos to logger coordinate system + if (storage->transformed == 0) { + // storage->sample_pos = coords_sub(storage->sample_pos, *(storage->logger_position)); + storage->sample_pos = coords_sub (storage->sample_pos, storage->logger_position); + storage->sample_pos = rot_apply (*(storage->logger_rotation), storage->sample_pos); + storage->transformed = 1; + } + + double distance, speed; + // Wavelength from tof + distance = sqrt ((storage->sample_pos.x - 0.0) * (storage->sample_pos.x - 0.0) + (storage->sample_pos.y - y_pos) * (storage->sample_pos.y - y_pos) + + (storage->sample_pos.z - 0.0) * (storage->sample_pos.z - 0.0)); + distance += storage->source_to_sample_dist; + speed = distance / time; + p2 = 2.0 * PI / (speed * V2K); + + if (storage->relative == 1) + p2 /= p1; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + + i = floor ((p1 - storage->Detector_2D.D1min) * (double)storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * (double)storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - double distance, speed; - // Wavelength from tof - distance = sqrt( (storage->sample_pos.x - 0.0)*(storage->sample_pos.x - 0.0) - + (storage->sample_pos.y - y_pos)*(storage->sample_pos.y - y_pos) - + (storage->sample_pos.z - 0.0)*(storage->sample_pos.z - 0.0) ); - distance += storage->source_to_sample_dist; - speed = distance/time; - p2 = 2.0*PI/(speed*V2K); - - if (storage->relative == 1) p2 /= p1; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - - i = floor((p1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_2D.Array_N[i][j]++; - storage->Detector_2D.Array_p[i][j] += p; - storage->Detector_2D.Array_p2[i][j] += p*p; - + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_2D.Array_N[i][j]++; + storage->Detector_2D.Array_p[i][j] += p; + storage->Detector_2D.Array_p2[i][j] += p * p; + } } } -} - -// write_temp_to_perm -void write_temp_to_perm_1D_time_to_lambda_abs(union abs_logger_data_union *data_union) { - struct a_1D_time_to_lambda_abs_storage_struct *storage; - storage = data_union->p_1D_time_to_lambda_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_time_to_lambda_abs_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] += storage->temp_1D_time_to_lambda_abs_data.elements[index].weight; - - storage->Detector_2D.Array_p2[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] += storage->temp_1D_time_to_lambda_abs_data.elements[index].weight*storage->temp_1D_time_to_lambda_abs_data.elements[index].weight; + // write_temp_to_perm + void + write_temp_to_perm_1D_time_to_lambda_abs (union abs_logger_data_union* data_union) { + struct a_1D_time_to_lambda_abs_storage_struct* storage; + storage = data_union->p_1D_time_to_lambda_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_time_to_lambda_abs_data.num_elements; index++) { + + storage->Detector_2D + .Array_N[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2]++; + + storage->Detector_2D + .Array_p[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] + += storage->temp_1D_time_to_lambda_abs_data.elements[index].weight; + + storage->Detector_2D + .Array_p2[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] + += storage->temp_1D_time_to_lambda_abs_data.elements[index].weight * storage->temp_1D_time_to_lambda_abs_data.elements[index].weight; + } + + clear_temp_1D_time_to_lambda_abs (data_union); } - - clear_temp_1D_time_to_lambda_abs(data_union); -} - -// write_temp_to_perm_final_p -void write_temp_to_perm_final_p_1D_time_to_lambda_abs(union abs_logger_data_union *data_union, double final_weight) { - struct a_1D_time_to_lambda_abs_storage_struct *storage; - storage = data_union->p_1D_time_to_lambda_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_time_to_lambda_abs_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] += final_weight; - - storage->Detector_2D.Array_p2[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] += final_weight*final_weight; + + // write_temp_to_perm_final_p + void + write_temp_to_perm_final_p_1D_time_to_lambda_abs (union abs_logger_data_union* data_union, double final_weight) { + struct a_1D_time_to_lambda_abs_storage_struct* storage; + storage = data_union->p_1D_time_to_lambda_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_time_to_lambda_abs_data.num_elements; index++) { + + storage->Detector_2D + .Array_N[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2]++; + + storage->Detector_2D + .Array_p[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] + += final_weight; + + storage->Detector_2D + .Array_p2[storage->temp_1D_time_to_lambda_abs_data.elements[index].index_1][storage->temp_1D_time_to_lambda_abs_data.elements[index].index_2] + += final_weight * final_weight; + } + + clear_temp_1D_time_to_lambda_abs (data_union); } - - clear_temp_1D_time_to_lambda_abs(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif + token = strtok (NULL, ","); + } + } + #endif -double** allocate2Ddouble_1D_time_to_lambda_abs(int count_x, int count_y) { + double** + allocate2Ddouble_1D_time_to_lambda_abs (int count_x, int count_y) { // This function is needed to dynamically declare an array // that has continous data as a static array would have, // as that is the format expected by DETECTOR_OUT_2D. int i; // allocate space for actual data - double *data = malloc(sizeof(double) * (count_x+1) * (count_y+1)); + double* data = malloc (sizeof (double) * (count_x + 1) * (count_y + 1)); // create array or pointers to first elem in each 2D row - double **ptr_array = malloc(sizeof(double*) * count_x); - //double **ptr_array = malloc(sizeof(double*) * (count_x+1)); + double** ptr_array = malloc (sizeof (double*) * count_x); + // double **ptr_array = malloc(sizeof(double*) * (count_x+1)); for (i = 0; i < count_x; i++) { - ptr_array[i] = data + (i*count_y); + ptr_array[i] = data + (i * count_y); } return ptr_array; -} - -void free2Ddouble_1D_time_to_lambda_abs(double** ptr_array) { - if (!ptr_array) return; - if (ptr_array[0]) free(ptr_array[0]); - free(ptr_array); -} + } + void + free2Ddouble_1D_time_to_lambda_abs (double** ptr_array) { + if (!ptr_array) + return; + if (ptr_array[0]) + free (ptr_array[0]); + free (ptr_array); + } %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -int loop_index; -int found_process; -int specified_processes; -//char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + // char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_1D_time_to_lambda_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_1D_time_to_lambda_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE @@ -512,232 +530,233 @@ INITIALIZE accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; // Initialize storage from input if (yheight <= 0) { - printf("ERROR, Union abs logger \"%s\" had yheight <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had yheight <= 0.\n", NAME_CURRENT_COMP); + exit (1); } - - this_abs_storage.y_min = -0.5*yheight; - this_abs_storage.y_max = 0.5*yheight; - + + this_abs_storage.y_min = -0.5 * yheight; + this_abs_storage.y_max = 0.5 * yheight; + if (yn <= 0) { - printf("ERROR, Union abs logger \"%s\" had yn <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had yn <= 0.\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.y_bins = yn; - + if (relative_measured == 0) this_abs_storage.relative = 0; else this_abs_storage.relative = 1; - + double lambda_m_min_used, lambda_t_min_used; lambda_m_min_used = lambda_min; lambda_t_min_used = lambda_min; - + double lambda_m_max_used, lambda_t_max_used; lambda_m_max_used = lambda_max; lambda_t_max_used = lambda_max; - + double lambda_m_bins_used, lambda_t_bins_used; lambda_m_bins_used = lambda_bins; lambda_t_bins_used = lambda_bins; - - if (lambda_m_min >= 0) lambda_m_min_used = lambda_m_min; - if (lambda_t_min >= 0) lambda_t_min_used = lambda_t_min; - if (lambda_m_max >= 0) lambda_m_max_used = lambda_m_max; - if (lambda_t_max >= 0) lambda_t_max_used = lambda_t_max; - if (lambda_t_bins >= 0) lambda_t_bins_used = lambda_t_bins; - if (lambda_m_bins >= 0) lambda_m_bins_used = lambda_m_bins; - - + + if (lambda_m_min >= 0) + lambda_m_min_used = lambda_m_min; + if (lambda_t_min >= 0) + lambda_t_min_used = lambda_t_min; + if (lambda_m_max >= 0) + lambda_m_max_used = lambda_m_max; + if (lambda_t_max >= 0) + lambda_t_max_used = lambda_t_max; + if (lambda_t_bins >= 0) + lambda_t_bins_used = lambda_t_bins; + if (lambda_m_bins >= 0) + lambda_m_bins_used = lambda_m_bins; + if (lambda_t_min_used < 0) { - printf("ERROR, Union abs logger \"%s\" had lambda_t_min < 0. Set either lambda_t_min or lambda_min!\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had lambda_t_min < 0. Set either lambda_t_min or lambda_min!\n", NAME_CURRENT_COMP); + exit (1); } - + if (lambda_t_max_used <= 0) { - printf("ERROR, Union abs logger \"%s\" had lambda_t_max <= 0. Set either lambda_t_max or lambda_max!\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had lambda_t_max <= 0. Set either lambda_t_max or lambda_max!\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.Detector_2D.D1min = lambda_t_min_used; this_abs_storage.Detector_2D.D1max = lambda_t_max_used; - - + if (lambda_m_min_used < 0) { - printf("ERROR, Union abs logger \"%s\" had lambda_m_min < 0. Set either lambda_m_min or lambda_min!\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had lambda_m_min < 0. Set either lambda_m_min or lambda_min!\n", NAME_CURRENT_COMP); + exit (1); } - + if (lambda_m_max_used <= 0) { - printf("ERROR, Union abs logger \"%s\" had lambda_m_max <= 0. Set either lambda_m_max or lambda_max!\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had lambda_m_max <= 0. Set either lambda_m_max or lambda_max!\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.Detector_2D.D2min = lambda_m_min_used; this_abs_storage.Detector_2D.D2max = lambda_m_max_used; - + if (lambda_t_bins_used <= 0) { - printf("ERROR, Union abs logger \"%s\" had lambda_t_bins <= 0. Set either lambda_t_bins or lambda_bins!\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had lambda_t_bins <= 0. Set either lambda_t_bins or lambda_bins!\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.Detector_2D.bins_1 = lambda_t_bins_used; - + if (lambda_m_bins_used <= 0) { - printf("ERROR, Union abs logger \"%s\" had lambda_m_bins <= 0. Set either lambda_m_bins or lambda_bins!\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had lambda_m_bins <= 0. Set either lambda_m_bins or lambda_bins!\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.Detector_2D.bins_2 = lambda_m_bins_used; this_abs_storage.source_to_sample_dist = source_sample_dist; if (this_abs_storage.relative == 1) { if (relative_min < 0) { - printf("ERROR, Union abs logger \"%s\" had relative_min < 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had relative_min < 0.\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.Detector_2D.D2min = relative_min; - + if (relative_min <= 0) { - printf("ERROR, Union abs logger \"%s\" had relative_min <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had relative_min <= 0.\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.Detector_2D.D2max = relative_max; - + if (relative_bins <= 0) { - printf("ERROR, Union abs logger \"%s\" had relative_bins <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had relative_bins <= 0.\n", NAME_CURRENT_COMP); + exit (1); } - + this_abs_storage.Detector_2D.bins_2 = relative_bins; - } - + // Set up storage for main data histogram // Remember to take special care when deallocating this array, use free2Ddouble - this_abs_storage.Detector_2D.Array_N = allocate2Ddouble_1D_time_to_lambda_abs(this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2); - this_abs_storage.Detector_2D.Array_p = allocate2Ddouble_1D_time_to_lambda_abs(this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2); - this_abs_storage.Detector_2D.Array_p2 = allocate2Ddouble_1D_time_to_lambda_abs(this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -746,31 +765,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_2D( - this_abs_storage.Detector_2D.title_string, - this_abs_storage.Detector_2D.string_axis_1, - this_abs_storage.Detector_2D.string_axis_2, - this_abs_storage.Detector_2D.D1min, this_abs_storage.Detector_2D.D1max, - this_abs_storage.Detector_2D.D2min, this_abs_storage.Detector_2D.D2max, - this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2, - *this_abs_storage.Detector_2D.Array_N, *this_abs_storage.Detector_2D.Array_p, *this_abs_storage.Detector_2D.Array_p2, - this_abs_storage.Detector_2D.Filename); - + // Write to disk + DETECTOR_OUT_2D (this_abs_storage.Detector_2D.title_string, this_abs_storage.Detector_2D.string_axis_1, this_abs_storage.Detector_2D.string_axis_2, + this_abs_storage.Detector_2D.D1min, this_abs_storage.Detector_2D.D1max, this_abs_storage.Detector_2D.D2min, this_abs_storage.Detector_2D.D2max, + this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2, *this_abs_storage.Detector_2D.Array_N, + *this_abs_storage.Detector_2D.Array_p, *this_abs_storage.Detector_2D.Array_p2, this_abs_storage.Detector_2D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_abs_storage.temp_1D_time_to_lambda_abs_data.allocated_elements>0) free(this_abs_storage.temp_1D_time_to_lambda_abs_data.elements); - -free2Ddouble_1D_time_to_lambda_abs(this_abs_storage.Detector_2D.Array_N); -free2Ddouble_1D_time_to_lambda_abs(this_abs_storage.Detector_2D.Array_p); -free2Ddouble_1D_time_to_lambda_abs(this_abs_storage.Detector_2D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_abs_storage.temp_1D_time_to_lambda_abs_data.allocated_elements > 0) + free (this_abs_storage.temp_1D_time_to_lambda_abs_data.elements); + + free2Ddouble_1D_time_to_lambda_abs (this_abs_storage.Detector_2D.Array_N); + free2Ddouble_1D_time_to_lambda_abs (this_abs_storage.Detector_2D.Array_p); + free2Ddouble_1D_time_to_lambda_abs (this_abs_storage.Detector_2D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_abs_logger_1D_time.comp b/mcstas-comps/union/Union_abs_logger_1D_time.comp index 156937f514..fe1cd22cda 100644 --- a/mcstas-comps/union/Union_abs_logger_1D_time.comp +++ b/mcstas-comps/union/Union_abs_logger_1D_time.comp @@ -92,275 +92,282 @@ OUTPUT PARAMETERS () SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_abs_logger_1D_time component" -#endif - -struct temp_time_abs_data_element_struct { - int index; - double weight; -}; - -struct temp_time_abs_data_struct { - int num_elements; - int allocated_elements; - struct temp_time_abs_data_element_struct *elements; -}; - -struct a_time_abs_storage_struct { - struct Detector_1D_struct Detector_1D; - struct temp_time_abs_data_struct temp_time_abs_data; - //some type - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_time_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - struct a_time_abs_storage_struct *storage; - storage = abs_logger->data_union.p_time_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_abs_logger_1D_time component" + #endif + + struct temp_time_abs_data_element_struct { + int index; + double weight; + }; + + struct temp_time_abs_data_struct { + int num_elements; + int allocated_elements; + struct temp_time_abs_data_element_struct* elements; + }; + + struct a_time_abs_storage_struct { + struct Detector_1D_struct Detector_1D; + struct temp_time_abs_data_struct temp_time_abs_data; + // some type + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_time_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + struct a_time_abs_storage_struct* storage; + storage = abs_logger->data_union.p_time_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { + if (add_point == 1) { - int i; - double value, dummy1, dummy2; + int i; + double value, dummy1, dummy2; - value = time; + value = time; - // Find bin in histogram - if (value>storage->Detector_1D.min && valueDetector_1D.max) { - i = floor((value - storage->Detector_1D.min)*storage->Detector_1D.bins/(storage->Detector_1D.max - storage->Detector_1D.min)); + // Find bin in histogram + if (value > storage->Detector_1D.min && value < storage->Detector_1D.max) { + i = floor ((value - storage->Detector_1D.min) * storage->Detector_1D.bins / (storage->Detector_1D.max - storage->Detector_1D.min)); - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_1D_data.num_elements,storage->temp_1D_data.allocated_elements); + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_1D_data.num_elements,storage->temp_1D_data.allocated_elements); - if (storage->temp_time_abs_data.num_elements < storage->temp_time_abs_data.allocated_elements) { - storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements].index = i; - storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + if (storage->temp_time_abs_data.num_elements < storage->temp_time_abs_data.allocated_elements) { + storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements].index = i; + storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - // copy current data to temp - struct temp_time_abs_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_time_abs_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_time_abs_data_element_struct)); + // copy current data to temp + struct temp_time_abs_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_time_abs_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_time_abs_data_element_struct)); - for (index=0;indextemp_time_abs_data.num_elements;index++) { - temporary_storage.elements[index].index = storage->temp_time_abs_data.elements[index].index; - temporary_storage.elements[index].weight = storage->temp_time_abs_data.elements[index].weight; - } + for (index = 0; index < storage->temp_time_abs_data.num_elements; index++) { + temporary_storage.elements[index].index = storage->temp_time_abs_data.elements[index].index; + temporary_storage.elements[index].weight = storage->temp_time_abs_data.elements[index].weight; + } - // free current data - free(storage->temp_time_abs_data.elements); + // free current data + free (storage->temp_time_abs_data.elements); - // allocate larger array (10 larger) - storage->temp_time_abs_data.allocated_elements = 10 + storage->temp_time_abs_data.num_elements; - storage->temp_time_abs_data.elements = malloc(storage->temp_time_abs_data.allocated_elements*sizeof(struct temp_time_abs_data_element_struct)); + // allocate larger array (10 larger) + storage->temp_time_abs_data.allocated_elements = 10 + storage->temp_time_abs_data.num_elements; + storage->temp_time_abs_data.elements = malloc (storage->temp_time_abs_data.allocated_elements * sizeof (struct temp_time_abs_data_element_struct)); - // copy back from temp - for (index=0;indextemp_time_abs_data.num_elements;index++) { - storage->temp_time_abs_data.elements[index].index = temporary_storage.elements[index].index; - storage->temp_time_abs_data.elements[index].weight = temporary_storage.elements[index].weight; - } + // copy back from temp + for (index = 0; index < storage->temp_time_abs_data.num_elements; index++) { + storage->temp_time_abs_data.elements[index].index = temporary_storage.elements[index].index; + storage->temp_time_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + } - // free temporary data - free(temporary_storage.elements); + // free temporary data + free (temporary_storage.elements); - // add new data point - storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements].index = i; - storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements++].weight = p; - } + // add new data point + storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements].index = i; + storage->temp_time_abs_data.elements[storage->temp_time_abs_data.num_elements++].weight = p; + } - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_time_abs_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array,abs_logger); + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_time_abs_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); + } } } -} - -// clear_temp -void clear_temp_time_abs(union abs_logger_data_union *data_union) { - data_union->p_time_abs_storage->temp_time_abs_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_time_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { + // clear_temp + void + clear_temp_time_abs (union abs_logger_data_union* data_union) { + data_union->p_time_abs_storage->temp_time_abs_data.num_elements = 0; + } - //printf("In record to permanent \n"); - struct a_time_abs_storage_struct *storage; - storage = abs_logger->data_union.p_time_abs_storage; + // record_to_perm + void + record_to_perm_time_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { - int add_point = 1; + // printf("In record to permanent \n"); + struct a_time_abs_storage_struct* storage; + storage = abs_logger->data_union.p_time_abs_storage; - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } + int add_point = 1; - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - //printf("storage was set \n"); + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } - int i; - double value, dummy1, dummy2; + if (add_point == 1) { + // printf("storage was set \n"); - value = time; + int i; + double value, dummy1, dummy2; - // Find bin in histogram - if (value>storage->Detector_1D.min && valueDetector_1D.max) { + value = time; - i = floor((value - storage->Detector_1D.min)*(double)storage->Detector_1D.bins/(storage->Detector_1D.max - storage->Detector_1D.min)); + // Find bin in histogram + if (value > storage->Detector_1D.min && value < storage->Detector_1D.max) { - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indices found\n"); + i = floor ((value - storage->Detector_1D.min) * (double)storage->Detector_1D.bins / (storage->Detector_1D.max - storage->Detector_1D.min)); - storage->Detector_1D.Array_N[i]++; - storage->Detector_1D.Array_p[i] += p; - storage->Detector_1D.Array_p2[i] += p*p; + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indices found\n"); + storage->Detector_1D.Array_N[i]++; + storage->Detector_1D.Array_p[i] += p; + storage->Detector_1D.Array_p2[i] += p * p; + } } } -} + // write_temp_to_perm + void + write_temp_to_perm_time_abs (union abs_logger_data_union* data_union) { -// write_temp_to_perm -void write_temp_to_perm_time_abs(union abs_logger_data_union *data_union) { + struct a_time_abs_storage_struct* storage; + storage = data_union->p_time_abs_storage; - struct a_time_abs_storage_struct *storage; - storage = data_union->p_time_abs_storage; + int index; + // Add all data points to the histogram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_time_abs_data.num_elements; index++) { + storage->Detector_1D.Array_N[storage->temp_time_abs_data.elements[index].index]++; - int index; - // Add all data points to the histogram, they are saved as index / weight combinations - for (index=0;indextemp_time_abs_data.num_elements;index++) { - storage->Detector_1D.Array_N[storage->temp_time_abs_data.elements[index].index]++; + storage->Detector_1D.Array_p[storage->temp_time_abs_data.elements[index].index] += storage->temp_time_abs_data.elements[index].weight; - storage->Detector_1D.Array_p[storage->temp_time_abs_data.elements[index].index] += storage->temp_time_abs_data.elements[index].weight; - - storage->Detector_1D.Array_p2[storage->temp_time_abs_data.elements[index].index] += storage->temp_time_abs_data.elements[index].weight*storage->temp_time_abs_data.elements[index].weight; + storage->Detector_1D.Array_p2[storage->temp_time_abs_data.elements[index].index] + += storage->temp_time_abs_data.elements[index].weight * storage->temp_time_abs_data.elements[index].weight; + } + clear_temp_time_abs (data_union); } - clear_temp_time_abs(data_union); -} -void write_temp_to_perm_final_p_time_abs(union abs_logger_data_union *data_union, double final_weight) { + void + write_temp_to_perm_final_p_time_abs (union abs_logger_data_union* data_union, double final_weight) { - struct a_time_abs_storage_struct *storage; - storage = data_union->p_time_abs_storage; + struct a_time_abs_storage_struct* storage; + storage = data_union->p_time_abs_storage; - int index; - // Add all data points to the histogram, they are saved as index / weight combinations - for (index=0;indextemp_time_abs_data.num_elements;index++) { - storage->Detector_1D.Array_N[storage->temp_time_abs_data.elements[index].index]++; + int index; + // Add all data points to the histogram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_time_abs_data.num_elements; index++) { + storage->Detector_1D.Array_N[storage->temp_time_abs_data.elements[index].index]++; - storage->Detector_1D.Array_p[storage->temp_time_abs_data.elements[index].index] += final_weight; + storage->Detector_1D.Array_p[storage->temp_time_abs_data.elements[index].index] += final_weight; - storage->Detector_1D.Array_p2[storage->temp_time_abs_data.elements[index].index] += final_weight*final_weight; + storage->Detector_1D.Array_p2[storage->temp_time_abs_data.elements[index].index] += final_weight * final_weight; + } + clear_temp_time_abs (data_union); } - clear_temp_time_abs(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indices of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indices of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurrence of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } // Updates the token - token = strtok(NULL,","); - } -} - -#endif + token = strtok (NULL, ","); + } + } + #endif %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_time_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_time_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE @@ -374,126 +381,121 @@ INITIALIZE // Initialize storage from input if (time_min >= time_max) { - printf("ERROR, Union abs logger \"%s\" had time_min larger than time_max.\n", NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union abs logger \"%s\" had time_min larger than time_max.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_1D.min = time_min; this_abs_storage.Detector_1D.max = time_max; if (n <= 0) { - printf("ERROR, Union logger \"%s\" had n <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_1D.bins = n; - // Remember to take special care when deallocating this array - this_abs_storage.Detector_1D.Array_N = malloc(n*sizeof(double)); - this_abs_storage.Detector_1D.Array_p = malloc(n*sizeof(double)); - this_abs_storage.Detector_1D.Array_p2 = malloc(n*sizeof(double)); + this_abs_storage.Detector_1D.Array_N = malloc (n * sizeof (double)); + this_abs_storage.Detector_1D.Array_p = malloc (n * sizeof (double)); + this_abs_storage.Detector_1D.Array_p2 = malloc (n * sizeof (double)); - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -502,30 +504,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_1D( - this_abs_storage.Detector_1D.title_string, - this_abs_storage.Detector_1D.string_axis, - this_abs_storage.Detector_1D.string_axis_value, - this_abs_storage.Detector_1D.string_axis_short, - this_abs_storage.Detector_1D.min, this_abs_storage.Detector_1D.max, - this_abs_storage.Detector_1D.bins, - &this_abs_storage.Detector_1D.Array_N[0], &this_abs_storage.Detector_1D.Array_p[0], &this_abs_storage.Detector_1D.Array_p2[0], - this_abs_storage.Detector_1D.Filename); + // Write to disk + DETECTOR_OUT_1D (this_abs_storage.Detector_1D.title_string, this_abs_storage.Detector_1D.string_axis, this_abs_storage.Detector_1D.string_axis_value, + this_abs_storage.Detector_1D.string_axis_short, this_abs_storage.Detector_1D.min, this_abs_storage.Detector_1D.max, + this_abs_storage.Detector_1D.bins, &this_abs_storage.Detector_1D.Array_N[0], &this_abs_storage.Detector_1D.Array_p[0], + &this_abs_storage.Detector_1D.Array_p2[0], this_abs_storage.Detector_1D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_abs_storage.temp_time_abs_data.allocated_elements>0) free(this_abs_storage.temp_time_abs_data.elements); - -free(this_abs_storage.Detector_1D.Array_N); -free(this_abs_storage.Detector_1D.Array_p); -free(this_abs_storage.Detector_1D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_abs_storage.temp_time_abs_data.allocated_elements > 0) + free (this_abs_storage.temp_time_abs_data.elements); + + free (this_abs_storage.Detector_1D.Array_N); + free (this_abs_storage.Detector_1D.Array_p); + free (this_abs_storage.Detector_1D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_abs_logger_2D_space.comp b/mcstas-comps/union/Union_abs_logger_2D_space.comp index 22164cd7e1..74ce4c19f7 100644 --- a/mcstas-comps/union/Union_abs_logger_2D_space.comp +++ b/mcstas-comps/union/Union_abs_logger_2D_space.comp @@ -99,349 +99,361 @@ SETTING PARAMETERS(string target_geometry="NULL", SHARE %{ -#ifndef Union -#define Union $Revision: 0.8 $ -#error "The Union_init component must be included before this Union_abs_logger_2D_space component" -#endif - -struct temp_2D_abs_data_element_struct { - int index_1; - int index_2; - double weight; -}; - -struct temp_2D_abs_data_struct { - int num_elements; - int allocated_elements; - struct temp_2D_abs_data_element_struct *elements; -}; - -struct a_2D_abs_storage_struct { - struct Detector_2D_struct Detector_2D; - struct temp_2D_abs_data_struct temp_2D_abs_data; - int dim_1_choice; - int dim_2_choice; - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_2D_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - struct a_2D_abs_storage_struct *storage; - storage = abs_logger->data_union.p_2D_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #define Union $Revision: 0.8 $ + #error "The Union_init component must be included before this Union_abs_logger_2D_space component" + #endif + + struct temp_2D_abs_data_element_struct { + int index_1; + int index_2; + double weight; + }; + + struct temp_2D_abs_data_struct { + int num_elements; + int allocated_elements; + struct temp_2D_abs_data_element_struct* elements; + }; + + struct a_2D_abs_storage_struct { + struct Detector_2D_struct Detector_2D; + struct temp_2D_abs_data_struct temp_2D_abs_data; + int dim_1_choice; + int dim_2_choice; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_2D_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + struct a_2D_abs_storage_struct* storage; + storage = abs_logger->data_union.p_2D_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - double p1,p2; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - if (storage->dim_1_choice == 0) - //p1 = position->x - storage->position.x; - p1 = position->x; - else if (storage->dim_1_choice == 1) - //p1 = position->y; - p1 = position->y - storage->position.y; - else if (storage->dim_1_choice == 2) - //p1 = position->z - storage->position.z; - p1 = position->z; - - if (storage->dim_2_choice == 0) - //p2 = position->x - storage->position.x; - p2 = position->x; - else if (storage->dim_2_choice == 1) - //p2 = position->y - storage->position.y; - p2 = position->y; - else if (storage->dim_2_choice == 2) - //p2 = position->z - storage->position.z; - p2 = position->z; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - i = floor((p1 - storage->Detector_2D.D1min)*storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_2D_abs_data.num_elements,storage->temp_2D_abs_data.allocated_elements); - - if (storage->temp_2D_abs_data.num_elements < storage->temp_2D_abs_data.allocated_elements) { - storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_1 = i; - storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_2 = j; - storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_2D_abs_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_2D_abs_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_2D_abs_data_element_struct)); - - for (index=0;indextemp_2D_abs_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_2D_abs_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_2D_abs_data.elements[index].index_2; - temporary_storage.elements[index].weight = storage->temp_2D_abs_data.elements[index].weight; - } - - // free current data - free(storage->temp_2D_abs_data.elements); - - // allocate larger array (10 larger) - storage->temp_2D_abs_data.allocated_elements = 10 + storage->temp_2D_abs_data.num_elements; - storage->temp_2D_abs_data.elements = malloc(storage->temp_2D_abs_data.allocated_elements*sizeof(struct temp_2D_abs_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_2D_abs_data.num_elements;index++) { - storage->temp_2D_abs_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_2D_abs_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_2D_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double p1, p2; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + if (storage->dim_1_choice == 0) + // p1 = position->x - storage->position.x; + p1 = position->x; + else if (storage->dim_1_choice == 1) + // p1 = position->y; + p1 = position->y - storage->position.y; + else if (storage->dim_1_choice == 2) + // p1 = position->z - storage->position.z; + p1 = position->z; + + if (storage->dim_2_choice == 0) + // p2 = position->x - storage->position.x; + p2 = position->x; + else if (storage->dim_2_choice == 1) + // p2 = position->y - storage->position.y; + p2 = position->y; + else if (storage->dim_2_choice == 2) + // p2 = position->z - storage->position.z; + p2 = position->z; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + i = floor ((p1 - storage->Detector_2D.D1min) * storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_2D_abs_data.num_elements,storage->temp_2D_abs_data.allocated_elements); + + if (storage->temp_2D_abs_data.num_elements < storage->temp_2D_abs_data.allocated_elements) { + storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_1 = i; + storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_2 = j; + storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_2D_abs_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_2D_abs_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_2D_abs_data_element_struct)); + + for (index = 0; index < storage->temp_2D_abs_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_2D_abs_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_2D_abs_data.elements[index].index_2; + temporary_storage.elements[index].weight = storage->temp_2D_abs_data.elements[index].weight; + } + + // free current data + free (storage->temp_2D_abs_data.elements); + + // allocate larger array (10 larger) + storage->temp_2D_abs_data.allocated_elements = 10 + storage->temp_2D_abs_data.num_elements; + storage->temp_2D_abs_data.elements = malloc (storage->temp_2D_abs_data.allocated_elements * sizeof (struct temp_2D_abs_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_2D_abs_data.num_elements; index++) { + storage->temp_2D_abs_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_2D_abs_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_2D_abs_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_1 = i; + storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_2 = j; + storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_1 = i; - storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements].index_2 = j; - storage->temp_2D_abs_data.elements[storage->temp_2D_abs_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_2D_abs_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_2D_abs_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array, abs_logger); - } } - -} - -// clear_temp -void clear_temp_2D_abs(union abs_logger_data_union *data_union) { - data_union->p_2D_abs_storage->temp_2D_abs_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_2D_abs(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_2D_abs_storage_struct *storage; - storage = abs_logger->data_union.p_2D_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_2D_abs (union abs_logger_data_union* data_union) { + data_union->p_2D_abs_storage->temp_2D_abs_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double p1, p2; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - if (storage->dim_1_choice == 0) - //p1 = position->x - storage->position.x; - p1 = position->x; - else if (storage->dim_1_choice == 1) - //p1 = position->y; - p1 = position->y - storage->position.y; - else if (storage->dim_1_choice == 2) - //p1 = position->z - storage->position.z; - p1 = position->z; - - if (storage->dim_2_choice == 0) - //p2 = position->x - storage->position.x; - p2 = position->x; - else if (storage->dim_2_choice == 1) - //p2 = position->y - storage->position.y; - p2 = position->y; - else if (storage->dim_2_choice == 2) - //p2 = position->z - storage->position.z; - p2 = position->z; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - - i = floor((p1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_2D.Array_N[i][j]++; - storage->Detector_2D.Array_p[i][j] += p; - storage->Detector_2D.Array_p2[i][j] += p*p; - + // record_to_perm + void + record_to_perm_2D_abs (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_2D_abs_storage_struct* storage; + storage = abs_logger->data_union.p_2D_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double p1, p2; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + if (storage->dim_1_choice == 0) + // p1 = position->x - storage->position.x; + p1 = position->x; + else if (storage->dim_1_choice == 1) + // p1 = position->y; + p1 = position->y - storage->position.y; + else if (storage->dim_1_choice == 2) + // p1 = position->z - storage->position.z; + p1 = position->z; + + if (storage->dim_2_choice == 0) + // p2 = position->x - storage->position.x; + p2 = position->x; + else if (storage->dim_2_choice == 1) + // p2 = position->y - storage->position.y; + p2 = position->y; + else if (storage->dim_2_choice == 2) + // p2 = position->z - storage->position.z; + p2 = position->z; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + + i = floor ((p1 - storage->Detector_2D.D1min) * (double)storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * (double)storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_2D.Array_N[i][j]++; + storage->Detector_2D.Array_p[i][j] += p; + storage->Detector_2D.Array_p2[i][j] += p * p; + } } } -} - -// write_temp_to_perm -void write_temp_to_perm_2D_abs(union abs_logger_data_union *data_union) { - struct a_2D_abs_storage_struct *storage; - storage = data_union->p_2D_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2D_abs_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] += storage->temp_2D_abs_data.elements[index].weight; - - storage->Detector_2D.Array_p2[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] += storage->temp_2D_abs_data.elements[index].weight*storage->temp_2D_abs_data.elements[index].weight; + // write_temp_to_perm + void + write_temp_to_perm_2D_abs (union abs_logger_data_union* data_union) { + struct a_2D_abs_storage_struct* storage; + storage = data_union->p_2D_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2D_abs_data.num_elements; index++) { + + storage->Detector_2D.Array_N[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] + += storage->temp_2D_abs_data.elements[index].weight; + + storage->Detector_2D.Array_p2[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] + += storage->temp_2D_abs_data.elements[index].weight * storage->temp_2D_abs_data.elements[index].weight; + } + + clear_temp_2D_abs (data_union); } - - clear_temp_2D_abs(data_union); -} - -// write_temp_to_perm_final_p -void write_temp_to_perm_final_p_2D_abs(union abs_logger_data_union *data_union, double final_weight) { - struct a_2D_abs_storage_struct *storage; - storage = data_union->p_2D_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2D_abs_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] += final_weight; - - storage->Detector_2D.Array_p2[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] += final_weight*final_weight; + + // write_temp_to_perm_final_p + void + write_temp_to_perm_final_p_2D_abs (union abs_logger_data_union* data_union, double final_weight) { + struct a_2D_abs_storage_struct* storage; + storage = data_union->p_2D_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2D_abs_data.num_elements; index++) { + + storage->Detector_2D.Array_N[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] += final_weight; + + storage->Detector_2D.Array_p2[storage->temp_2D_abs_data.elements[index].index_1][storage->temp_2D_abs_data.elements[index].index_2] + += final_weight * final_weight; + } + + clear_temp_2D_abs (data_union); } - - clear_temp_2D_abs(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif + token = strtok (NULL, ","); + } + } + #endif -double** allocate2Ddouble_2D_abs(int count_x, int count_y) { + double** + allocate2Ddouble_2D_abs (int count_x, int count_y) { // This function is needed to dynamically declare an array // that has continous data as a static array would have, // as that is the format expected by DETECTOR_OUT_2D. int i; // allocate space for actual data - double *data = malloc(sizeof(double) * count_x * count_y); + double* data = malloc (sizeof (double) * count_x * count_y); // create array or pointers to first elem in each 2D row - double **ptr_array = malloc(sizeof(double*) * count_x); + double** ptr_array = malloc (sizeof (double*) * count_x); for (i = 0; i < count_x; i++) { - ptr_array[i] = data + (i*count_y); + ptr_array[i] = data + (i * count_y); } return ptr_array; -} - -void free2Ddouble_2D_abs(double** ptr_array) { - if (!ptr_array) return; - if (ptr_array[0]) free(ptr_array[0]); - free(ptr_array); -} + } + void + free2Ddouble_2D_abs (double** ptr_array) { + if (!ptr_array) + return; + if (ptr_array[0]) + free (ptr_array[0]); + free (ptr_array); + } %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_2D_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_2D_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE @@ -449,181 +461,176 @@ INITIALIZE accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; // Initialize storage from input if (D1_min >= D1_max) { - printf("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_2D.D1min = D1_min; this_abs_storage.Detector_2D.D1max = D1_max; - + if (D2_min >= D2_max) { - printf("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_2D.D2min = D2_min; this_abs_storage.Detector_2D.D2max = D2_max; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_2D.bins_1 = n1; - + if (n2 <= 0) { - printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n2 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_abs_storage.Detector_2D.bins_2 = n2; - - //printf("past input sanitation \n"); - - + + // printf("past input sanitation \n"); + // Remember to take special care when deallocating this array, use free2Ddouble - this_abs_storage.Detector_2D.Array_N = allocate2Ddouble_2D_abs(n1,n2); // Here the n1 double is cast to an int - this_abs_storage.Detector_2D.Array_p = allocate2Ddouble_2D_abs(n1,n2); - this_abs_storage.Detector_2D.Array_p2 = allocate2Ddouble_2D_abs(n1,n2); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -632,31 +639,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_2D( - this_abs_storage.Detector_2D.title_string, - this_abs_storage.Detector_2D.string_axis_1, - this_abs_storage.Detector_2D.string_axis_2, - this_abs_storage.Detector_2D.D1min, this_abs_storage.Detector_2D.D1max, - this_abs_storage.Detector_2D.D2min, this_abs_storage.Detector_2D.D2max, - this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2, - *this_abs_storage.Detector_2D.Array_N, *this_abs_storage.Detector_2D.Array_p, *this_abs_storage.Detector_2D.Array_p2, - this_abs_storage.Detector_2D.Filename); - + // Write to disk + DETECTOR_OUT_2D (this_abs_storage.Detector_2D.title_string, this_abs_storage.Detector_2D.string_axis_1, this_abs_storage.Detector_2D.string_axis_2, + this_abs_storage.Detector_2D.D1min, this_abs_storage.Detector_2D.D1max, this_abs_storage.Detector_2D.D2min, this_abs_storage.Detector_2D.D2max, + this_abs_storage.Detector_2D.bins_1, this_abs_storage.Detector_2D.bins_2, *this_abs_storage.Detector_2D.Array_N, + *this_abs_storage.Detector_2D.Array_p, *this_abs_storage.Detector_2D.Array_p2, this_abs_storage.Detector_2D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_abs_storage.temp_2D_abs_data.allocated_elements>0) free(this_abs_storage.temp_2D_abs_data.elements); - -free2Ddouble_2D_abs(this_abs_storage.Detector_2D.Array_N); -free2Ddouble_2D_abs(this_abs_storage.Detector_2D.Array_p); -free2Ddouble_2D_abs(this_abs_storage.Detector_2D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_abs_storage.temp_2D_abs_data.allocated_elements > 0) + free (this_abs_storage.temp_2D_abs_data.elements); + + free2Ddouble_2D_abs (this_abs_storage.Detector_2D.Array_N); + free2Ddouble_2D_abs (this_abs_storage.Detector_2D.Array_p); + free2Ddouble_2D_abs (this_abs_storage.Detector_2D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_abs_logger_event.comp b/mcstas-comps/union/Union_abs_logger_event.comp index 4459aa6f61..3387a27bc6 100644 --- a/mcstas-comps/union/Union_abs_logger_event.comp +++ b/mcstas-comps/union/Union_abs_logger_event.comp @@ -94,148 +94,151 @@ SETTING PARAMETERS(string target_geometry="NULL", string filename="NULL", SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_abs_logger_event component" -#endif - -// Internally avoids double import -%include "monitor_nd-lib" - -struct temp_abs_event_data_element_struct { - double x_pos; - double y_pos; - double z_pos; - - double x_vel; - double y_vel; - double z_vel; - - double x_pol; - double y_pol; - double z_pol; - - double time; - double weight; -}; - -struct temp_abs_event_data_struct { - int num_elements; - int allocated_elements; - struct temp_abs_event_data_element_struct *elements; -}; - -struct a_event_abs_storage_struct { - MonitornD_Defines_type DEFS; - MonitornD_Variables_type Vars; - - struct temp_abs_event_data_struct temp_abs_event_data; - //some type - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - double stored_xwidth; - double stored_yheight; - double stored_zdepth; - - int stored_xbins; - int stored_ybins; - int stored_zbins; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -double round_to_nearest_bin(double value, double w, int N) { + #ifndef Union + #error "The Union_init component must be included before this Union_abs_logger_event component" + #endif + + // Internally avoids double import + %include "monitor_nd-lib" + + struct temp_abs_event_data_element_struct { + double x_pos; + double y_pos; + double z_pos; + + double x_vel; + double y_vel; + double z_vel; + + double x_pol; + double y_pol; + double z_pol; + + double time; + double weight; + }; + + struct temp_abs_event_data_struct { + int num_elements; + int allocated_elements; + struct temp_abs_event_data_element_struct* elements; + }; + + struct a_event_abs_storage_struct { + MonitornD_Defines_type DEFS; + MonitornD_Variables_type Vars; + + struct temp_abs_event_data_struct temp_abs_event_data; + // some type + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + double stored_xwidth; + double stored_yheight; + double stored_zdepth; + + int stored_xbins; + int stored_ybins; + int stored_zbins; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + double + round_to_nearest_bin (double value, double w, int N) { // Calculate the width of each bin double bin_width = w / N; // Calculate the index of the nearest bin - int bin_index = round((value + w / 2) / bin_width); + int bin_index = round ((value + w / 2) / bin_width); // Calculate the center of the nearest bin double bin_center = (bin_index * bin_width) - (w / 2) + (bin_width / 2); return bin_center; -} + } -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_abs_event(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_abs_event (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { - struct a_event_abs_storage_struct *storage; - storage = abs_logger->data_union.p_event_abs_storage; + struct a_event_abs_storage_struct* storage; + storage = abs_logger->data_union.p_event_abs_storage; - int add_point = 1; + int add_point = 1; - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } - if (storage->stored_xwidth != 0) { - if (position->x < 0.5*storage->stored_xwidth && position->x > -0.5*storage->stored_xwidth) - add_point = 1; - else - add_point = 0; - } + if (storage->stored_xwidth != 0) { + if (position->x < 0.5 * storage->stored_xwidth && position->x > -0.5 * storage->stored_xwidth) + add_point = 1; + else + add_point = 0; + } - if (storage->stored_yheight != 0) { - if (position->y < 0.5*storage->stored_yheight && position->y > -0.5*storage->stored_yheight) - add_point = 1; - else - add_point = 0; - } + if (storage->stored_yheight != 0) { + if (position->y < 0.5 * storage->stored_yheight && position->y > -0.5 * storage->stored_yheight) + add_point = 1; + else + add_point = 0; + } - if (storage->stored_zdepth != 0) { - if (position->z < 0.5*storage->stored_zdepth && position->z > -0.5*storage->stored_xwidth) - add_point = 1; - else - add_point = 0; - } + if (storage->stored_zdepth != 0) { + if (position->z < 0.5 * storage->stored_zdepth && position->z > -0.5 * storage->stored_xwidth) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { + if (add_point == 1) { - int i; - double given_x_pos, given_y_pos, given_z_pos; - double used_x_pos, used_y_pos, used_z_pos; - coords_get(*position, &given_x_pos, &given_y_pos, &given_z_pos); + int i; + double given_x_pos, given_y_pos, given_z_pos; + double used_x_pos, used_y_pos, used_z_pos; + coords_get (*position, &given_x_pos, &given_y_pos, &given_z_pos); - if (storage->stored_xbins != 0) { - used_x_pos = round_to_nearest_bin(given_x_pos, storage->stored_xwidth, storage->stored_xbins); - } else { + if (storage->stored_xbins != 0) { + used_x_pos = round_to_nearest_bin (given_x_pos, storage->stored_xwidth, storage->stored_xbins); + } else { used_x_pos = given_x_pos; - } + } - if (storage->stored_ybins != 0) { - used_y_pos = round_to_nearest_bin(given_y_pos, storage->stored_yheight, storage->stored_ybins); - } else { + if (storage->stored_ybins != 0) { + used_y_pos = round_to_nearest_bin (given_y_pos, storage->stored_yheight, storage->stored_ybins); + } else { used_y_pos = given_y_pos; - } + } - if (storage->stored_zbins != 0) { - used_z_pos = round_to_nearest_bin(given_z_pos, storage->stored_zdepth, storage->stored_zbins); - } else { + if (storage->stored_zbins != 0) { + used_z_pos = round_to_nearest_bin (given_z_pos, storage->stored_zdepth, storage->stored_zbins); + } else { used_z_pos = given_z_pos; - } - - double given_x_vel, given_y_vel, given_z_vel; - given_x_vel = k[0]*K2V; - given_y_vel = k[1]*K2V; - given_z_vel = k[2]*K2V; - - if (storage->temp_abs_event_data.num_elements < storage->temp_abs_event_data.allocated_elements) { - + } + + double given_x_vel, given_y_vel, given_z_vel; + given_x_vel = k[0] * K2V; + given_y_vel = k[1] * K2V; + given_z_vel = k[2] * K2V; + + if (storage->temp_abs_event_data.num_elements < storage->temp_abs_event_data.allocated_elements) { + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].x_pos = used_x_pos; storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].y_pos = used_y_pos; storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_pos = used_z_pos; @@ -247,311 +250,313 @@ void record_to_temp_abs_event(Coords *position, double *k, double p, double time storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_pol = 1.0; storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].time = time; storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_abs_event_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_abs_event_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_abs_event_data_element_struct)); - - int index; - for (index=0;indextemp_abs_event_data.num_elements;index++) { - temporary_storage.elements[index].x_pos = storage->temp_abs_event_data.elements[index].x_pos; - temporary_storage.elements[index].y_pos = storage->temp_abs_event_data.elements[index].y_pos; - temporary_storage.elements[index].z_pos = storage->temp_abs_event_data.elements[index].z_pos; - temporary_storage.elements[index].x_vel = storage->temp_abs_event_data.elements[index].x_vel; - temporary_storage.elements[index].y_vel = storage->temp_abs_event_data.elements[index].y_vel; - temporary_storage.elements[index].z_vel = storage->temp_abs_event_data.elements[index].z_vel; - temporary_storage.elements[index].x_pol = storage->temp_abs_event_data.elements[index].x_pol; - temporary_storage.elements[index].y_pol = storage->temp_abs_event_data.elements[index].y_pol; - temporary_storage.elements[index].z_pol = storage->temp_abs_event_data.elements[index].z_pol; - temporary_storage.elements[index].time = storage->temp_abs_event_data.elements[index].time; - temporary_storage.elements[index].weight = storage->temp_abs_event_data.elements[index].weight; - } - - // free current data - free(storage->temp_abs_event_data.elements); - - // allocate larger array (10 larger) - storage->temp_abs_event_data.allocated_elements = 10 + storage->temp_abs_event_data.num_elements; - storage->temp_abs_event_data.elements = malloc(storage->temp_abs_event_data.allocated_elements*sizeof(struct temp_abs_event_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_abs_event_data.num_elements;index++) { - storage->temp_abs_event_data.elements[index].x_pos = temporary_storage.elements[index].x_pos; - storage->temp_abs_event_data.elements[index].y_pos = temporary_storage.elements[index].y_pos; - storage->temp_abs_event_data.elements[index].z_pos = temporary_storage.elements[index].z_pos; - storage->temp_abs_event_data.elements[index].x_vel = temporary_storage.elements[index].x_vel; - storage->temp_abs_event_data.elements[index].y_vel = temporary_storage.elements[index].y_vel; - storage->temp_abs_event_data.elements[index].z_vel = temporary_storage.elements[index].z_vel; - storage->temp_abs_event_data.elements[index].x_pol = temporary_storage.elements[index].x_pol; - storage->temp_abs_event_data.elements[index].y_pol = temporary_storage.elements[index].y_pol; - storage->temp_abs_event_data.elements[index].z_pol = temporary_storage.elements[index].z_pol; - storage->temp_abs_event_data.elements[index].time = temporary_storage.elements[index].time; - storage->temp_abs_event_data.elements[index].weight = temporary_storage.elements[index].weight; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_abs_event_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_abs_event_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_abs_event_data_element_struct)); + + int index; + for (index = 0; index < storage->temp_abs_event_data.num_elements; index++) { + temporary_storage.elements[index].x_pos = storage->temp_abs_event_data.elements[index].x_pos; + temporary_storage.elements[index].y_pos = storage->temp_abs_event_data.elements[index].y_pos; + temporary_storage.elements[index].z_pos = storage->temp_abs_event_data.elements[index].z_pos; + temporary_storage.elements[index].x_vel = storage->temp_abs_event_data.elements[index].x_vel; + temporary_storage.elements[index].y_vel = storage->temp_abs_event_data.elements[index].y_vel; + temporary_storage.elements[index].z_vel = storage->temp_abs_event_data.elements[index].z_vel; + temporary_storage.elements[index].x_pol = storage->temp_abs_event_data.elements[index].x_pol; + temporary_storage.elements[index].y_pol = storage->temp_abs_event_data.elements[index].y_pol; + temporary_storage.elements[index].z_pol = storage->temp_abs_event_data.elements[index].z_pol; + temporary_storage.elements[index].time = storage->temp_abs_event_data.elements[index].time; + temporary_storage.elements[index].weight = storage->temp_abs_event_data.elements[index].weight; + } + + // free current data + free (storage->temp_abs_event_data.elements); + + // allocate larger array (10 larger) + storage->temp_abs_event_data.allocated_elements = 10 + storage->temp_abs_event_data.num_elements; + storage->temp_abs_event_data.elements = malloc (storage->temp_abs_event_data.allocated_elements * sizeof (struct temp_abs_event_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_abs_event_data.num_elements; index++) { + storage->temp_abs_event_data.elements[index].x_pos = temporary_storage.elements[index].x_pos; + storage->temp_abs_event_data.elements[index].y_pos = temporary_storage.elements[index].y_pos; + storage->temp_abs_event_data.elements[index].z_pos = temporary_storage.elements[index].z_pos; + storage->temp_abs_event_data.elements[index].x_vel = temporary_storage.elements[index].x_vel; + storage->temp_abs_event_data.elements[index].y_vel = temporary_storage.elements[index].y_vel; + storage->temp_abs_event_data.elements[index].z_vel = temporary_storage.elements[index].z_vel; + storage->temp_abs_event_data.elements[index].x_pol = temporary_storage.elements[index].x_pol; + storage->temp_abs_event_data.elements[index].y_pol = temporary_storage.elements[index].y_pol; + storage->temp_abs_event_data.elements[index].z_pol = temporary_storage.elements[index].z_pol; + storage->temp_abs_event_data.elements[index].time = temporary_storage.elements[index].time; + storage->temp_abs_event_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].x_pos = given_x_pos; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].y_pos = given_y_pos; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_pos = given_z_pos; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].x_vel = given_x_vel; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].y_vel = given_y_vel; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_vel = given_z_vel; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].x_pol = 0.0; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].y_pol = 0.0; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_pol = 1.0; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].time = time; + storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements++].weight = p; } - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].x_pos = given_x_pos; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].y_pos = given_y_pos; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_pos = given_z_pos; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].x_vel = given_x_vel; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].y_vel = given_y_vel; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_vel = given_z_vel; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].x_pol = 0.0; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].y_pol = 0.0; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].z_pol = 1.0; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements].time = time; - storage->temp_abs_event_data.elements[storage->temp_abs_event_data.num_elements++].weight = p; + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_abs_event_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_abs_event_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array,abs_logger); - - } -} - -// clear_temp -void clear_temp_abs_event(union abs_logger_data_union *data_union) { - data_union->p_event_abs_storage->temp_abs_event_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_abs_event(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_event_abs_storage_struct *storage; - storage = abs_logger->data_union.p_event_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; } - if (storage->stored_xwidth != 0) { - if (position->x < 0.5*storage->stored_xwidth && position->x > -0.5*storage->stored_xwidth) - add_point = 1; - else - add_point = 0; + // clear_temp + void + clear_temp_abs_event (union abs_logger_data_union* data_union) { + data_union->p_event_abs_storage->temp_abs_event_data.num_elements = 0; } - if (storage->stored_yheight != 0) { - if (position->y < 0.5*storage->stored_yheight && position->y > -0.5*storage->stored_yheight) - add_point = 1; - else - add_point = 0; - } + // record_to_perm + void + record_to_perm_abs_event (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { - if (storage->stored_zdepth != 0) { - if (position->z < 0.5*storage->stored_zdepth && position->z > -0.5*storage->stored_xwidth) - add_point = 1; - else - add_point = 0; - } + // printf("In record to permanent \n"); + struct a_event_abs_storage_struct* storage; + storage = abs_logger->data_union.p_event_abs_storage; - if (add_point == 1) { - //printf("storage was set \n"); - - double given_x_pos, given_y_pos, given_z_pos; - double used_x_pos, used_y_pos, used_z_pos; - coords_get(*position, &given_x_pos, &given_y_pos, &given_z_pos); + int add_point = 1; - if (storage->stored_xbins != 0) { - used_x_pos = round_to_nearest_bin(given_x_pos, storage->stored_xwidth, storage->stored_xbins); - } else { - used_x_pos = given_x_pos; + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; } - if (storage->stored_ybins != 0) { - used_y_pos = round_to_nearest_bin(given_y_pos, storage->stored_yheight, storage->stored_ybins); - } else { - used_y_pos = given_y_pos; + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; } - if (storage->stored_zbins != 0) { - used_z_pos = round_to_nearest_bin(given_z_pos, storage->stored_zdepth, storage->stored_zbins); - } else { - used_z_pos = given_z_pos; + if (storage->stored_xwidth != 0) { + if (position->x < 0.5 * storage->stored_xwidth && position->x > -0.5 * storage->stored_xwidth) + add_point = 1; + else + add_point = 0; } - double given_x_vel, given_y_vel, given_z_vel; - given_x_vel = k[0]*K2V; - given_y_vel = k[1]*K2V; - given_z_vel = k[2]*K2V; - - _class_particle _localparticle; - - _localparticle.x = used_x_pos; - _localparticle.y = used_y_pos; - _localparticle.z = used_z_pos; - - _localparticle.vx = given_x_vel; - _localparticle.vy = given_y_vel; - _localparticle.vz = given_z_vel; - - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; - - _localparticle.p = p; - _localparticle.t = time; - - int pp; - pp = Monitor_nD_Trace(&(storage->DEFS), &(storage->Vars), &_localparticle); - + if (storage->stored_yheight != 0) { + if (position->y < 0.5 * storage->stored_yheight && position->y > -0.5 * storage->stored_yheight) + add_point = 1; + else + add_point = 0; + } + + if (storage->stored_zdepth != 0) { + if (position->z < 0.5 * storage->stored_zdepth && position->z > -0.5 * storage->stored_xwidth) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + + double given_x_pos, given_y_pos, given_z_pos; + double used_x_pos, used_y_pos, used_z_pos; + coords_get (*position, &given_x_pos, &given_y_pos, &given_z_pos); + + if (storage->stored_xbins != 0) { + used_x_pos = round_to_nearest_bin (given_x_pos, storage->stored_xwidth, storage->stored_xbins); + } else { + used_x_pos = given_x_pos; + } + + if (storage->stored_ybins != 0) { + used_y_pos = round_to_nearest_bin (given_y_pos, storage->stored_yheight, storage->stored_ybins); + } else { + used_y_pos = given_y_pos; + } + + if (storage->stored_zbins != 0) { + used_z_pos = round_to_nearest_bin (given_z_pos, storage->stored_zdepth, storage->stored_zbins); + } else { + used_z_pos = given_z_pos; + } + + double given_x_vel, given_y_vel, given_z_vel; + given_x_vel = k[0] * K2V; + given_y_vel = k[1] * K2V; + given_z_vel = k[2] * K2V; + + _class_particle _localparticle; + + _localparticle.x = used_x_pos; + _localparticle.y = used_y_pos; + _localparticle.z = used_z_pos; + + _localparticle.vx = given_x_vel; + _localparticle.vy = given_y_vel; + _localparticle.vz = given_z_vel; + + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; + + _localparticle.p = p; + _localparticle.t = time; + + int pp; + pp = Monitor_nD_Trace (&(storage->DEFS), &(storage->Vars), &_localparticle); + } } -} - -// write_temp_to_perm -void write_temp_to_perm_abs_event(union abs_logger_data_union *data_union) { - - struct a_event_abs_storage_struct *storage; - storage = data_union->p_event_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_abs_event_data.num_elements;index++) { - - _class_particle _localparticle; - - _localparticle.x = storage->temp_abs_event_data.elements[index].x_pos; - _localparticle.y = storage->temp_abs_event_data.elements[index].y_pos; - _localparticle.z = storage->temp_abs_event_data.elements[index].z_pos; - - _localparticle.vx = storage->temp_abs_event_data.elements[index].x_vel; - _localparticle.vy = storage->temp_abs_event_data.elements[index].y_vel; - _localparticle.vz = storage->temp_abs_event_data.elements[index].z_vel; - - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; - - _localparticle.p = storage->temp_abs_event_data.elements[index].weight; - _localparticle.t = storage->temp_abs_event_data.elements[index].time; - - int pp; - pp = Monitor_nD_Trace(&(storage->DEFS), &(storage->Vars), &_localparticle); - + // write_temp_to_perm + void + write_temp_to_perm_abs_event (union abs_logger_data_union* data_union) { + + struct a_event_abs_storage_struct* storage; + storage = data_union->p_event_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_abs_event_data.num_elements; index++) { + + _class_particle _localparticle; + + _localparticle.x = storage->temp_abs_event_data.elements[index].x_pos; + _localparticle.y = storage->temp_abs_event_data.elements[index].y_pos; + _localparticle.z = storage->temp_abs_event_data.elements[index].z_pos; + + _localparticle.vx = storage->temp_abs_event_data.elements[index].x_vel; + _localparticle.vy = storage->temp_abs_event_data.elements[index].y_vel; + _localparticle.vz = storage->temp_abs_event_data.elements[index].z_vel; + + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; + + _localparticle.p = storage->temp_abs_event_data.elements[index].weight; + _localparticle.t = storage->temp_abs_event_data.elements[index].time; + + int pp; + pp = Monitor_nD_Trace (&(storage->DEFS), &(storage->Vars), &_localparticle); + } + clear_temp_abs_event (data_union); } - clear_temp_abs_event(data_union); -} - -void write_temp_to_perm_final_p_abs_event(union abs_logger_data_union *data_union, double final_weight) { - - struct a_event_abs_storage_struct *storage; - storage = data_union->p_event_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_abs_event_data.num_elements;index++) { - - _class_particle _localparticle; - - _localparticle.x = storage->temp_abs_event_data.elements[index].x_pos; - _localparticle.y = storage->temp_abs_event_data.elements[index].y_pos; - _localparticle.z = storage->temp_abs_event_data.elements[index].z_pos; - - _localparticle.vx = storage->temp_abs_event_data.elements[index].x_vel; - _localparticle.vy = storage->temp_abs_event_data.elements[index].y_vel; - _localparticle.vz = storage->temp_abs_event_data.elements[index].z_vel; - - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; - - _localparticle.p = final_weight; - _localparticle.t = storage->temp_abs_event_data.elements[index].time; - - int pp; - pp = Monitor_nD_Trace(&(storage->DEFS), &(storage->Vars), &_localparticle); + + void + write_temp_to_perm_final_p_abs_event (union abs_logger_data_union* data_union, double final_weight) { + + struct a_event_abs_storage_struct* storage; + storage = data_union->p_event_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_abs_event_data.num_elements; index++) { + + _class_particle _localparticle; + + _localparticle.x = storage->temp_abs_event_data.elements[index].x_pos; + _localparticle.y = storage->temp_abs_event_data.elements[index].y_pos; + _localparticle.z = storage->temp_abs_event_data.elements[index].z_pos; + + _localparticle.vx = storage->temp_abs_event_data.elements[index].x_vel; + _localparticle.vy = storage->temp_abs_event_data.elements[index].y_vel; + _localparticle.vz = storage->temp_abs_event_data.elements[index].z_vel; + + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; + + _localparticle.p = final_weight; + _localparticle.t = storage->temp_abs_event_data.elements[index].time; + + int pp; + pp = Monitor_nD_Trace (&(storage->DEFS), &(storage->Vars), &_localparticle); + } + clear_temp_abs_event (data_union); } - clear_temp_abs_event(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - - // Updates the token - token = strtok(NULL,","); - } -} -#endif + // Updates the token + token = strtok (NULL, ","); + } + } + #endif %} DECLARE %{ -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_event_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_event_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; -double bufsize; + double bufsize; %} INITIALIZE @@ -561,118 +566,115 @@ INITIALIZE accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; - + // Input sanitation for filename apparently done in 1D_detector_out - - long element_size=85; /* mean size per neutron for ascii storing */ - strcpy(this_abs_storage.Vars.compcurname, NAME_CURRENT_COMP); + long element_size = 85; /* mean size per neutron for ascii storing */ - if (bufsize > 0) sprintf(this_abs_storage.Vars.option, "list=%g borders", bufsize); - else strcpy(this_abs_storage.Vars.option, "list all borders"); + strcpy (this_abs_storage.Vars.compcurname, NAME_CURRENT_COMP); - strcat(this_abs_storage.Vars.option,", x y z vx vy vz t"); - //strcat(this_abs_storage.Vars.option,", y t"); - Monitor_nD_Init(&this_abs_storage.DEFS, &this_abs_storage.Vars, 0.1, 0.1, 0, 0,0,0,0,0,0,0); /* dims for mcdisplay */ + if (bufsize > 0) + sprintf (this_abs_storage.Vars.option, "list=%g borders", bufsize); + else + strcpy (this_abs_storage.Vars.option, "list all borders"); + + strcat (this_abs_storage.Vars.option, ", x y z vx vy vz t"); + // strcat(this_abs_storage.Vars.option,", y t"); + Monitor_nD_Init (&this_abs_storage.DEFS, &this_abs_storage.Vars, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0, 0); /* dims for mcdisplay */ this_abs_storage.Vars.compcurpos = POS_A_CURRENT_COMP; - if (filename && strlen(filename) && strcmp(filename,"NULL") && strcmp(filename,"0")) - strncpy(this_abs_storage.Vars.Mon_File, filename, 128); + if (filename && strlen (filename) && strcmp (filename, "NULL") && strcmp (filename, "0")) + strncpy (this_abs_storage.Vars.Mon_File, filename, 128); if (bufsize > 0) - printf("Warning: Virtual_output: %s: buffer size=%g not recommended\n", NAME_CURRENT_COMP, bufsize); - if (bufsize > 0) printf( - "Virtual_output: %s: Beware virtual output generated file size (max %g Mo)\n" - "WARNING Memory required is %g Mo\n", NAME_CURRENT_COMP, - bufsize*element_size/1e6, bufsize*sizeof(double)/1e6); - + printf ("Warning: Virtual_output: %s: buffer size=%g not recommended\n", NAME_CURRENT_COMP, bufsize); + if (bufsize > 0) + printf ("Virtual_output: %s: Beware virtual output generated file size (max %g Mo)\n" + "WARNING Memory required is %g Mo\n", + NAME_CURRENT_COMP, bufsize* element_size / 1e6, bufsize * sizeof (double) / 1e6); + this_abs_storage.order = order_total; this_abs_storage.order_in_this_volume = order_volume; - + this_abs_storage.stored_xwidth = xwidth; - this_abs_storage.stored_xbins = (int) xbins; + this_abs_storage.stored_xbins = (int)xbins; this_abs_storage.stored_yheight = yheight; - this_abs_storage.stored_ybins = (int) ybins; + this_abs_storage.stored_ybins = (int)ybins; this_abs_storage.stored_zdepth = zdepth; - this_abs_storage.stored_zbins = (int) zbins; + this_abs_storage.stored_zbins = (int)zbins; - this_abs_storage.temp_abs_event_data.num_elements=0; + this_abs_storage.temp_abs_event_data.num_elements = 0; this_abs_storage.temp_abs_event_data.allocated_elements = 10; - this_abs_storage.temp_abs_event_data.elements = malloc(this_abs_storage.temp_abs_event_data.allocated_elements*sizeof(struct temp_abs_event_data_element_struct)); + this_abs_storage.temp_abs_event_data.elements + = malloc (this_abs_storage.temp_abs_event_data.allocated_elements * sizeof (struct temp_abs_event_data_element_struct)); -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_abs_logger_event:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_abs_logger_event:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct global_positions_to_transform_list_struct *global_positions_to_transform_list = COMP_GETPAR3(Union_init, init, global_positions_to_transform_list); - struct global_rotations_to_transform_list_struct *global_rotations_to_transform_list = COMP_GETPAR3(Union_init, init, global_rotations_to_transform_list); + struct global_positions_to_transform_list_struct* global_positions_to_transform_list = COMP_GETPAR3 (Union_init, init, global_positions_to_transform_list); + struct global_rotations_to_transform_list_struct* global_rotations_to_transform_list = COMP_GETPAR3 (Union_init, init, global_rotations_to_transform_list); // Test position and rotation stored in a data storage, and pointers assigned to transform lists this_abs_logger.position = POS_A_CURRENT_COMP; - add_position_pointer_to_list(global_positions_to_transform_list, &this_abs_logger.position); - - rot_copy(this_abs_logger.rotation,ROT_A_CURRENT_COMP); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_abs_logger.rotation); - - rot_transpose(ROT_A_CURRENT_COMP,this_abs_logger.t_rotation); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_abs_logger.t_rotation); - - - + add_position_pointer_to_list (global_positions_to_transform_list, &this_abs_logger.position); + + rot_copy (this_abs_logger.rotation, ROT_A_CURRENT_COMP); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_abs_logger.rotation); + + rot_transpose (ROT_A_CURRENT_COMP, this_abs_logger.t_rotation); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_abs_logger.t_rotation); + // Book keeping this_abs_logger.abs_logger_extend_index = logger_conditional_extend_index; - this_abs_logger.function_pointers.active_record_function = &record_to_perm_abs_event; // Assume no conditional + this_abs_logger.function_pointers.active_record_function = &record_to_perm_abs_event; // Assume no conditional this_abs_logger.function_pointers.inactive_record_function = &record_to_temp_abs_event; // If an assume is present, these two pointers are switched // Temp to perm functions, and standard identifier - //this_abs_logger.function_pointers.select_t_to_p = 1; // 1: temp_to_perm, 2: temp_to_perm_final_p // Not relevant for abs + // this_abs_logger.function_pointers.select_t_to_p = 1; // 1: temp_to_perm, 2: temp_to_perm_final_p // Not relevant for abs this_abs_logger.function_pointers.temp_to_perm = &write_temp_to_perm_abs_event; this_abs_logger.function_pointers.temp_to_perm_final_p = &write_temp_to_perm_final_p_abs_event; this_abs_logger.function_pointers.clear_temp = &clear_temp_abs_event; - + // Initializing for conditional this_abs_logger.conditional_list.num_elements = 0; - + this_abs_logger.data_union.p_event_abs_storage = &this_abs_storage; - sprintf(this_abs_logger.name,"%s",NAME_CURRENT_COMP); - sprintf(abs_logger_list_element.name,"%s",NAME_CURRENT_COMP); + sprintf (this_abs_logger.name, "%s", NAME_CURRENT_COMP); + sprintf (abs_logger_list_element.name, "%s", NAME_CURRENT_COMP); abs_logger_list_element.component_index = INDEX_CURRENT_COMP; abs_logger_list_element.abs_logger = &this_abs_logger; - - struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); - struct pointer_to_global_abs_logger_list *global_specific_volumes_abs_logger_list = COMP_GETPAR3(Union_init, init, global_specific_volumes_abs_logger_list); + + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + struct pointer_to_global_abs_logger_list* global_specific_volumes_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_specific_volumes_abs_logger_list); // In order to run the logger at the right times, pointers to this logger is stored in each volume it logs, // and additionally for each avaiable process. If a process is not logged, the pointer is simply not stored. int process_index; // Need to find the volumes for which the processes should have a reference to this logger - if (target_geometry && strlen(target_geometry) && strcmp(target_geometry,"NULL") && strcmp(target_geometry, "0")) { + if (target_geometry && strlen (target_geometry) && strcmp (target_geometry, "NULL") && strcmp (target_geometry, "0")) { // Certain volumes were selected, find the indicies in the global_geometry_list - manual_linking_function_abs_logger_volumes(target_geometry, global_geometry_list, &accepted_volumes, NAME_CURRENT_COMP); + manual_linking_function_abs_logger_volumes (target_geometry, global_geometry_list, &accepted_volumes, NAME_CURRENT_COMP); // Add this logger to the global_specific_volumes_logger_list (so that conditionals can affect it) - add_element_to_abs_logger_list(global_specific_volumes_abs_logger_list, abs_logger_list_element); - - for (loop_index=0;loop_indexelements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -681,29 +683,30 @@ TRACE SAVE %{ - Monitor_nD_Save(&this_abs_storage.DEFS, &this_abs_storage.Vars); + Monitor_nD_Save (&this_abs_storage.DEFS, &this_abs_storage.Vars); %} FINALLY %{ -/* free pointers */ - Monitor_nD_Finally(&this_abs_storage.DEFS, &this_abs_storage.Vars); + /* free pointers */ + Monitor_nD_Finally (&this_abs_storage.DEFS, &this_abs_storage.Vars); if (bufsize) { - printf("Virtual_output: %s: Saved %llu events (from buffer) in file %s\n", - NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); + printf ("Virtual_output: %s: Saved %llu events (from buffer) in file %s\n", NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); if (bufsize < this_abs_storage.Vars.Nsum) - printf("WARNING When using this source, intensities must be multiplied\n" - " by a factor %g\n", (double)this_abs_storage.Vars.Nsum/(double)bufsize); - } else printf("Virtual_output: %s: Saved %llu events (all) in file %s\n", NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); - -// Remember to clean up allocated lists -if (this_abs_storage.temp_abs_event_data.allocated_elements>0) free(this_abs_storage.temp_abs_event_data.elements); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - - - + printf ("WARNING When using this source, intensities must be multiplied\n" + " by a factor %g\n", + (double)this_abs_storage.Vars.Nsum / (double)bufsize); + } else + printf ("Virtual_output: %s: Saved %llu events (all) in file %s\n", NAME_CURRENT_COMP, this_abs_storage.Vars.Nsum, this_abs_storage.Vars.Mon_File); + + // Remember to clean up allocated lists + if (this_abs_storage.temp_abs_event_data.allocated_elements > 0) + free (this_abs_storage.temp_abs_event_data.elements); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_abs_logger_nD.comp b/mcstas-comps/union/Union_abs_logger_nD.comp index 31a0236e43..9675d4bc3b 100644 --- a/mcstas-comps/union/Union_abs_logger_nD.comp +++ b/mcstas-comps/union/Union_abs_logger_nD.comp @@ -116,88 +116,90 @@ OUTPUT PARAMETERS () SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_abs_logger_nD component" -#endif - -%include "monitor_nd-lib" // Internally avoids double import -%include "read_table-lib" -%include "interoff-lib" - -struct temp_abs_nD_data_element_struct { - double x_pos; - double y_pos; - double z_pos; - - double x_vel; - double y_vel; - double z_vel; - - double x_pol; - double y_pol; - double z_pol; - - double time; - double weight; -}; - -struct temp_abs_nD_data_struct { - int num_elements; - int allocated_elements; - struct temp_abs_nD_data_element_struct *elements; -}; - -struct a_nD_abs_storage_struct { - MonitornD_Defines_type *p_DEFS; - MonitornD_Variables_type *p_Vars; - - struct temp_abs_nD_data_struct temp_abs_nD_data; - //some type - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_abs_nD(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - struct a_nD_abs_storage_struct *storage; - storage = abs_logger->data_union.p_nD_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_abs_logger_nD component" + #endif + + %include "monitor_nd-lib" // Internally avoids double import + %include "read_table-lib" + %include "interoff-lib" + + struct temp_abs_nD_data_element_struct { + double x_pos; + double y_pos; + double z_pos; + + double x_vel; + double y_vel; + double z_vel; + + double x_pol; + double y_pol; + double z_pol; + + double time; + double weight; + }; + + struct temp_abs_nD_data_struct { + int num_elements; + int allocated_elements; + struct temp_abs_nD_data_element_struct* elements; + }; + + struct a_nD_abs_storage_struct { + MonitornD_Defines_type* p_DEFS; + MonitornD_Variables_type* p_Vars; + + struct temp_abs_nD_data_struct temp_abs_nD_data; + // some type + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_abs_nD (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + struct a_nD_abs_storage_struct* storage; + storage = abs_logger->data_union.p_nD_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + int i; + double given_x_pos, given_y_pos, given_z_pos; + coords_get (*position, &given_x_pos, &given_y_pos, &given_z_pos); + + double given_x_vel, given_y_vel, given_z_vel; + given_x_vel = k[0] * K2V; + given_y_vel = k[1] * K2V; + given_z_vel = k[2] * K2V; + + if (storage->temp_abs_nD_data.num_elements < storage->temp_abs_nD_data.allocated_elements) { - if (add_point == 1) { - - int i; - double given_x_pos, given_y_pos, given_z_pos; - coords_get(*position, &given_x_pos, &given_y_pos, &given_z_pos); - - double given_x_vel, given_y_vel, given_z_vel; - given_x_vel = k[0]*K2V; - given_y_vel = k[1]*K2V; - given_z_vel = k[2]*K2V; - - if (storage->temp_abs_nD_data.num_elements < storage->temp_abs_nD_data.allocated_elements) { - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].x_pos = given_x_pos; storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].y_pos = given_y_pos; storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_pos = given_z_pos; @@ -209,361 +211,358 @@ void record_to_temp_abs_nD(Coords *position, double *k, double p, double time, i storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_pol = 1.0; storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].time = time; storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_abs_nD_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_abs_nD_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_abs_nD_data_element_struct)); - - int index; - for (index=0;indextemp_abs_nD_data.num_elements;index++) { - temporary_storage.elements[index].x_pos = storage->temp_abs_nD_data.elements[index].x_pos; - temporary_storage.elements[index].y_pos = storage->temp_abs_nD_data.elements[index].y_pos; - temporary_storage.elements[index].z_pos = storage->temp_abs_nD_data.elements[index].z_pos; - temporary_storage.elements[index].x_vel = storage->temp_abs_nD_data.elements[index].x_vel; - temporary_storage.elements[index].y_vel = storage->temp_abs_nD_data.elements[index].y_vel; - temporary_storage.elements[index].z_vel = storage->temp_abs_nD_data.elements[index].z_vel; - temporary_storage.elements[index].x_pol = storage->temp_abs_nD_data.elements[index].x_pol; - temporary_storage.elements[index].y_pol = storage->temp_abs_nD_data.elements[index].y_pol; - temporary_storage.elements[index].z_pol = storage->temp_abs_nD_data.elements[index].z_pol; - temporary_storage.elements[index].time = storage->temp_abs_nD_data.elements[index].time; - temporary_storage.elements[index].weight = storage->temp_abs_nD_data.elements[index].weight; - } - - // free current data - free(storage->temp_abs_nD_data.elements); - - // allocate larger array (10 larger) - storage->temp_abs_nD_data.allocated_elements = 10 + storage->temp_abs_nD_data.num_elements; - storage->temp_abs_nD_data.elements = malloc(storage->temp_abs_nD_data.allocated_elements*sizeof(struct temp_abs_nD_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_abs_nD_data.num_elements;index++) { - storage->temp_abs_nD_data.elements[index].x_pos = temporary_storage.elements[index].x_pos; - storage->temp_abs_nD_data.elements[index].y_pos = temporary_storage.elements[index].y_pos; - storage->temp_abs_nD_data.elements[index].z_pos = temporary_storage.elements[index].z_pos; - storage->temp_abs_nD_data.elements[index].x_vel = temporary_storage.elements[index].x_vel; - storage->temp_abs_nD_data.elements[index].y_vel = temporary_storage.elements[index].y_vel; - storage->temp_abs_nD_data.elements[index].z_vel = temporary_storage.elements[index].z_vel; - storage->temp_abs_nD_data.elements[index].x_pol = temporary_storage.elements[index].x_pol; - storage->temp_abs_nD_data.elements[index].y_pol = temporary_storage.elements[index].y_pol; - storage->temp_abs_nD_data.elements[index].z_pol = temporary_storage.elements[index].z_pol; - storage->temp_abs_nD_data.elements[index].time = temporary_storage.elements[index].time; - storage->temp_abs_nD_data.elements[index].weight = temporary_storage.elements[index].weight; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_abs_nD_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_abs_nD_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_abs_nD_data_element_struct)); + + int index; + for (index = 0; index < storage->temp_abs_nD_data.num_elements; index++) { + temporary_storage.elements[index].x_pos = storage->temp_abs_nD_data.elements[index].x_pos; + temporary_storage.elements[index].y_pos = storage->temp_abs_nD_data.elements[index].y_pos; + temporary_storage.elements[index].z_pos = storage->temp_abs_nD_data.elements[index].z_pos; + temporary_storage.elements[index].x_vel = storage->temp_abs_nD_data.elements[index].x_vel; + temporary_storage.elements[index].y_vel = storage->temp_abs_nD_data.elements[index].y_vel; + temporary_storage.elements[index].z_vel = storage->temp_abs_nD_data.elements[index].z_vel; + temporary_storage.elements[index].x_pol = storage->temp_abs_nD_data.elements[index].x_pol; + temporary_storage.elements[index].y_pol = storage->temp_abs_nD_data.elements[index].y_pol; + temporary_storage.elements[index].z_pol = storage->temp_abs_nD_data.elements[index].z_pol; + temporary_storage.elements[index].time = storage->temp_abs_nD_data.elements[index].time; + temporary_storage.elements[index].weight = storage->temp_abs_nD_data.elements[index].weight; + } + + // free current data + free (storage->temp_abs_nD_data.elements); + + // allocate larger array (10 larger) + storage->temp_abs_nD_data.allocated_elements = 10 + storage->temp_abs_nD_data.num_elements; + storage->temp_abs_nD_data.elements = malloc (storage->temp_abs_nD_data.allocated_elements * sizeof (struct temp_abs_nD_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_abs_nD_data.num_elements; index++) { + storage->temp_abs_nD_data.elements[index].x_pos = temporary_storage.elements[index].x_pos; + storage->temp_abs_nD_data.elements[index].y_pos = temporary_storage.elements[index].y_pos; + storage->temp_abs_nD_data.elements[index].z_pos = temporary_storage.elements[index].z_pos; + storage->temp_abs_nD_data.elements[index].x_vel = temporary_storage.elements[index].x_vel; + storage->temp_abs_nD_data.elements[index].y_vel = temporary_storage.elements[index].y_vel; + storage->temp_abs_nD_data.elements[index].z_vel = temporary_storage.elements[index].z_vel; + storage->temp_abs_nD_data.elements[index].x_pol = temporary_storage.elements[index].x_pol; + storage->temp_abs_nD_data.elements[index].y_pol = temporary_storage.elements[index].y_pol; + storage->temp_abs_nD_data.elements[index].z_pol = temporary_storage.elements[index].z_pol; + storage->temp_abs_nD_data.elements[index].time = temporary_storage.elements[index].time; + storage->temp_abs_nD_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].x_pos = given_x_pos; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].y_pos = given_y_pos; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_pos = given_z_pos; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].x_vel = given_x_vel; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].y_vel = given_y_vel; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_vel = given_z_vel; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].x_pol = 0.0; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].y_pol = 0.0; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_pol = 1.0; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].time = time; + storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements++].weight = p; } - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].x_pos = given_x_pos; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].y_pos = given_y_pos; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_pos = given_z_pos; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].x_vel = given_x_vel; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].y_vel = given_y_vel; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_vel = given_z_vel; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].x_pol = 0.0; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].y_pol = 0.0; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].z_pol = 1.0; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements].time = time; - storage->temp_abs_nD_data.elements[storage->temp_abs_nD_data.num_elements++].weight = p; + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_abs_nD_data.num_elements == 1) + add_to_abs_logger_with_data (abs_logger_with_data_array, abs_logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_abs_nD_data.num_elements == 1) - add_to_abs_logger_with_data(abs_logger_with_data_array,abs_logger); - } -} - -// clear_temp -void clear_temp_abs_nD(union abs_logger_data_union *data_union) { - data_union->p_nD_abs_storage->temp_abs_nD_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_abs_nD(Coords *position, double *k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, struct abs_logger_struct *abs_logger, struct abs_logger_with_data_struct *abs_logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_nD_abs_storage_struct *storage; - storage = abs_logger->data_union.p_nD_abs_storage; - - int add_point = 1; - - if (storage->order != -1) { - if (storage->order == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != -1) { - if (storage->order_in_this_volume == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_abs_nD (union abs_logger_data_union* data_union) { + data_union->p_nD_abs_storage->temp_abs_nD_data.num_elements = 0; } - if (add_point == 1) { - - double given_x_pos, given_y_pos, given_z_pos; - coords_get(*position, &given_x_pos, &given_y_pos, &given_z_pos); - - double given_x_vel, given_y_vel, given_z_vel; - given_x_vel = k[0]*K2V; - given_y_vel = k[1]*K2V; - given_z_vel = k[2]*K2V; - - _class_particle _localparticle; - - _localparticle.x = given_x_pos; - _localparticle.y = given_y_pos; - _localparticle.z = given_z_pos; - - _localparticle.vx = given_x_vel; - _localparticle.vy = given_y_vel; - _localparticle.vz = given_z_vel; - - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; - - _localparticle.p = p; - _localparticle.t = time; - - int pp; - pp = Monitor_nD_Trace(storage->p_DEFS, storage->p_Vars, &_localparticle); - + // record_to_perm + void + record_to_perm_abs_nD (Coords* position, double* k, double p, double time, int scattered_in_this_volume, int total_number_of_scattering_events, + struct abs_logger_struct* abs_logger, struct abs_logger_with_data_struct* abs_logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_nD_abs_storage_struct* storage; + storage = abs_logger->data_union.p_nD_abs_storage; + + int add_point = 1; + + if (storage->order != -1) { + if (storage->order == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != -1) { + if (storage->order_in_this_volume == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double given_x_pos, given_y_pos, given_z_pos; + coords_get (*position, &given_x_pos, &given_y_pos, &given_z_pos); + + double given_x_vel, given_y_vel, given_z_vel; + given_x_vel = k[0] * K2V; + given_y_vel = k[1] * K2V; + given_z_vel = k[2] * K2V; + + _class_particle _localparticle; + + _localparticle.x = given_x_pos; + _localparticle.y = given_y_pos; + _localparticle.z = given_z_pos; + + _localparticle.vx = given_x_vel; + _localparticle.vy = given_y_vel; + _localparticle.vz = given_z_vel; + + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; + + _localparticle.p = p; + _localparticle.t = time; + + int pp; + pp = Monitor_nD_Trace (storage->p_DEFS, storage->p_Vars, &_localparticle); + } } -} - -// write_temp_to_perm -void write_temp_to_perm_abs_nD(union abs_logger_data_union *data_union) { - - struct a_nD_abs_storage_struct *storage; - storage = data_union->p_nD_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_abs_nD_data.num_elements;index++) { - - _class_particle _localparticle; - - _localparticle.x = storage->temp_abs_nD_data.elements[index].x_pos; - _localparticle.y = storage->temp_abs_nD_data.elements[index].y_pos; - _localparticle.z = storage->temp_abs_nD_data.elements[index].z_pos; - - _localparticle.vx = storage->temp_abs_nD_data.elements[index].x_vel; - _localparticle.vy = storage->temp_abs_nD_data.elements[index].y_vel; - _localparticle.vz = storage->temp_abs_nD_data.elements[index].z_vel; - - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; - - _localparticle.p = storage->temp_abs_nD_data.elements[index].weight; - _localparticle.t = storage->temp_abs_nD_data.elements[index].time; - - int pp; - pp = Monitor_nD_Trace(storage->p_DEFS, storage->p_Vars, &_localparticle); - + // write_temp_to_perm + void + write_temp_to_perm_abs_nD (union abs_logger_data_union* data_union) { + + struct a_nD_abs_storage_struct* storage; + storage = data_union->p_nD_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_abs_nD_data.num_elements; index++) { + + _class_particle _localparticle; + + _localparticle.x = storage->temp_abs_nD_data.elements[index].x_pos; + _localparticle.y = storage->temp_abs_nD_data.elements[index].y_pos; + _localparticle.z = storage->temp_abs_nD_data.elements[index].z_pos; + + _localparticle.vx = storage->temp_abs_nD_data.elements[index].x_vel; + _localparticle.vy = storage->temp_abs_nD_data.elements[index].y_vel; + _localparticle.vz = storage->temp_abs_nD_data.elements[index].z_vel; + + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; + + _localparticle.p = storage->temp_abs_nD_data.elements[index].weight; + _localparticle.t = storage->temp_abs_nD_data.elements[index].time; + + int pp; + pp = Monitor_nD_Trace (storage->p_DEFS, storage->p_Vars, &_localparticle); + } + clear_temp_abs_nD (data_union); } - clear_temp_abs_nD(data_union); -} - -void write_temp_to_perm_final_p_abs_nD(union abs_logger_data_union *data_union, double final_weight) { - - struct a_nD_abs_storage_struct *storage; - storage = data_union->p_nD_abs_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_abs_nD_data.num_elements;index++) { - - _class_particle _localparticle; - - _localparticle.x = storage->temp_abs_nD_data.elements[index].x_pos; - _localparticle.y = storage->temp_abs_nD_data.elements[index].y_pos; - _localparticle.z = storage->temp_abs_nD_data.elements[index].z_pos; - - _localparticle.vx = storage->temp_abs_nD_data.elements[index].x_vel; - _localparticle.vy = storage->temp_abs_nD_data.elements[index].y_vel; - _localparticle.vz = storage->temp_abs_nD_data.elements[index].z_vel; - - _localparticle.sx = 0.0; - _localparticle.sy = 0.0; - _localparticle.sz = 1.0; - - _localparticle.p = final_weight; - _localparticle.t = storage->temp_abs_nD_data.elements[index].time; - - int pp; - pp = Monitor_nD_Trace(storage->p_DEFS, storage->p_Vars, &_localparticle); + + void + write_temp_to_perm_final_p_abs_nD (union abs_logger_data_union* data_union, double final_weight) { + + struct a_nD_abs_storage_struct* storage; + storage = data_union->p_nD_abs_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_abs_nD_data.num_elements; index++) { + + _class_particle _localparticle; + + _localparticle.x = storage->temp_abs_nD_data.elements[index].x_pos; + _localparticle.y = storage->temp_abs_nD_data.elements[index].y_pos; + _localparticle.z = storage->temp_abs_nD_data.elements[index].z_pos; + + _localparticle.vx = storage->temp_abs_nD_data.elements[index].x_vel; + _localparticle.vy = storage->temp_abs_nD_data.elements[index].y_vel; + _localparticle.vz = storage->temp_abs_nD_data.elements[index].z_vel; + + _localparticle.sx = 0.0; + _localparticle.sy = 0.0; + _localparticle.sz = 1.0; + + _localparticle.p = final_weight; + _localparticle.t = storage->temp_abs_nD_data.elements[index].time; + + int pp; + pp = Monitor_nD_Trace (storage->p_DEFS, storage->p_Vars, &_localparticle); + } + clear_temp_abs_nD (data_union); } - clear_temp_abs_nD(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_ABS_LOGGER -#define UNION_ABS_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_abs_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_ABS_LOGGER + #define UNION_ABS_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_abs_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - - // Updates the token - token = strtok(NULL,","); - } -} -#endif + // Updates the token + token = strtok (NULL, ","); + } + } + #endif %} DECLARE %{ -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_abs_logger_element_struct abs_logger_list_element; + struct global_abs_logger_element_struct abs_logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct abs_logger_struct this_abs_logger; -struct a_nD_abs_storage_struct this_abs_storage; + struct abs_logger_struct this_abs_logger; + struct a_nD_abs_storage_struct this_abs_storage; -struct abs_loggers_struct *abs_loggers_on_target_volume; -struct Volume_struct *target_volume; + struct abs_loggers_struct* abs_loggers_on_target_volume; + struct Volume_struct* target_volume; -MonitornD_Defines_type DEFS; -MonitornD_Variables_type Vars; -MCDETECTOR detector; -off_struct offdata; + MonitornD_Defines_type DEFS; + MonitornD_Variables_type Vars; + MCDETECTOR detector; + off_struct offdata; %} INITIALIZE INHERIT Monitor_nD EXTEND %{ // input sanitation, provide error if commands used in options that are not supported in Union context // capture, 3He_pressure, slit, absorb - if (strstr(Vars.option, "capture") || strstr(Vars.option, "3He_pressure") || strstr(Vars.option, "slit") || strstr(Vars.option, "absorb")) - exit(printf("Abs_logger_nD: %s Union version does not support following options. Aborting (capture, 3He_pressure, slit, absorb).\n", NAME_CURRENT_COMP)); + if (strstr (Vars.option, "capture") || strstr (Vars.option, "3He_pressure") || strstr (Vars.option, "slit") || strstr (Vars.option, "absorb")) + exit (printf ("Abs_logger_nD: %s Union version does not support following options. Aborting (capture, 3He_pressure, slit, absorb).\n", NAME_CURRENT_COMP)); + + // May need to manipulate options string for: min pixel ID (if auto_pixel_ID) and previous - // May need to manipulate options string for: min pixel ID (if auto_pixel_ID) and previous - this_abs_storage.p_DEFS = &DEFS; // Grab DEFS prepared by Monitor_nD initialization this_abs_storage.p_Vars = &Vars; // Grab Vars prepared by Monitor_nD initialization this_abs_storage.order = order_total; this_abs_storage.order_in_this_volume = order_volume; - - this_abs_storage.temp_abs_nD_data.num_elements=0; - + + this_abs_storage.temp_abs_nD_data.num_elements = 0; + this_abs_storage.temp_abs_nD_data.allocated_elements = 10; - this_abs_storage.temp_abs_nD_data.elements = malloc(this_abs_storage.temp_abs_nD_data.allocated_elements*sizeof(struct temp_abs_nD_data_element_struct)); + this_abs_storage.temp_abs_nD_data.elements = malloc (this_abs_storage.temp_abs_nD_data.allocated_elements * sizeof (struct temp_abs_nD_data_element_struct)); - if (_getcomp_index(init) < 0) { - fprintf(stderr,"Union_abs_logger_nD:%s: Error identifying Union_init component, %s is not a known component name.\n", - NAME_CURRENT_COMP, init); - exit(-1); + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_abs_logger_nD:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); } - struct global_positions_to_transform_list_struct *global_positions_to_transform_list = COMP_GETPAR3(Union_init, init, global_positions_to_transform_list); - struct global_rotations_to_transform_list_struct *global_rotations_to_transform_list = COMP_GETPAR3(Union_init, init, global_rotations_to_transform_list); + struct global_positions_to_transform_list_struct* global_positions_to_transform_list = COMP_GETPAR3 (Union_init, init, global_positions_to_transform_list); + struct global_rotations_to_transform_list_struct* global_rotations_to_transform_list = COMP_GETPAR3 (Union_init, init, global_rotations_to_transform_list); // Test position and rotation stored in a data storage, and pointers assigned to transform lists this_abs_logger.position = POS_A_CURRENT_COMP; - add_position_pointer_to_list(global_positions_to_transform_list, &this_abs_logger.position); - - rot_copy(this_abs_logger.rotation,ROT_A_CURRENT_COMP); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_abs_logger.rotation); - - rot_transpose(ROT_A_CURRENT_COMP,this_abs_logger.t_rotation); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_abs_logger.t_rotation); - - + add_position_pointer_to_list (global_positions_to_transform_list, &this_abs_logger.position); + + rot_copy (this_abs_logger.rotation, ROT_A_CURRENT_COMP); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_abs_logger.rotation); + + rot_transpose (ROT_A_CURRENT_COMP, this_abs_logger.t_rotation); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_abs_logger.t_rotation); + // Book keeping this_abs_logger.abs_logger_extend_index = logger_conditional_extend_index; - this_abs_logger.function_pointers.active_record_function = &record_to_perm_abs_nD; // Assume no conditional + this_abs_logger.function_pointers.active_record_function = &record_to_perm_abs_nD; // Assume no conditional this_abs_logger.function_pointers.inactive_record_function = &record_to_temp_abs_nD; // If an assume is present, these two pointers are switched // Temp to perm functions, and standard identifier - //this_abs_logger.function_pointers.select_t_to_p = 1; // 1: temp_to_perm, 2: temp_to_perm_final_p // Not relevant for abs + // this_abs_logger.function_pointers.select_t_to_p = 1; // 1: temp_to_perm, 2: temp_to_perm_final_p // Not relevant for abs this_abs_logger.function_pointers.temp_to_perm = &write_temp_to_perm_abs_nD; this_abs_logger.function_pointers.temp_to_perm_final_p = &write_temp_to_perm_final_p_abs_nD; this_abs_logger.function_pointers.clear_temp = &clear_temp_abs_nD; - + // Initializing for conditional this_abs_logger.conditional_list.num_elements = 0; - + this_abs_logger.data_union.p_nD_abs_storage = &this_abs_storage; - sprintf(this_abs_logger.name,"%s",NAME_CURRENT_COMP); - sprintf(abs_logger_list_element.name,"%s",NAME_CURRENT_COMP); + sprintf (this_abs_logger.name, "%s", NAME_CURRENT_COMP); + sprintf (abs_logger_list_element.name, "%s", NAME_CURRENT_COMP); abs_logger_list_element.component_index = INDEX_CURRENT_COMP; abs_logger_list_element.abs_logger = &this_abs_logger; - - struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); - struct pointer_to_global_abs_logger_list *global_specific_volumes_abs_logger_list = COMP_GETPAR3(Union_init, init, global_specific_volumes_abs_logger_list); + + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + struct pointer_to_global_abs_logger_list* global_specific_volumes_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_specific_volumes_abs_logger_list); // In order to run the logger at the right times, pointers to this logger is stored in each volume it logs, // and additionally for each avaiable process. If a process is not logged, the pointer is simply not stored. int process_index; // Need to find the volumes for which the processes should have a reference to this logger - if (target_geometry && strlen(target_geometry) && strcmp(target_geometry,"NULL") && strcmp(target_geometry, "0")) { + if (target_geometry && strlen (target_geometry) && strcmp (target_geometry, "NULL") && strcmp (target_geometry, "0")) { // Certain volumes were selected, find the indicies in the global_geometry_list - manual_linking_function_abs_logger_volumes(target_geometry, global_geometry_list, &accepted_volumes, NAME_CURRENT_COMP); + manual_linking_function_abs_logger_volumes (target_geometry, global_geometry_list, &accepted_volumes, NAME_CURRENT_COMP); // Add this logger to the global_specific_volumes_logger_list (so that conditionals can affect it) - add_element_to_abs_logger_list(global_specific_volumes_abs_logger_list, abs_logger_list_element); - - for (loop_index=0;loop_indexelements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its abs_logger list - - add_initialized_abs_logger_in_volume(&target_volume->abs_loggers); - target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements-1] = &this_abs_logger; - + + add_initialized_abs_logger_in_volume (&target_volume->abs_loggers); + target_volume->abs_loggers.p_abs_logger[target_volume->abs_loggers.num_elements - 1] = &this_abs_logger; } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - add_element_to_abs_logger_list(global_all_volume_abs_logger_list, abs_logger_list_element); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + add_element_to_abs_logger_list (global_all_volume_abs_logger_list, abs_logger_list_element); } - - %} TRACE @@ -574,11 +573,14 @@ SAVE INHERIT Monitor_nD FINALLY INHERIT Monitor_nD EXTEND %{ -// Remember to clean up allocated lists -if (this_abs_storage.temp_abs_nD_data.allocated_elements>0) free(this_abs_storage.temp_abs_nD_data.elements); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); + // Remember to clean up allocated lists + if (this_abs_storage.temp_abs_nD_data.allocated_elements > 0) + free (this_abs_storage.temp_abs_nD_data.elements); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} MCDISPLAY INHERIT Monitor_nD diff --git a/mcstas-comps/union/Union_box.comp b/mcstas-comps/union/Union_box.comp index 2d51aceeec..7f70657b9e 100755 --- a/mcstas-comps/union/Union_box.comp +++ b/mcstas-comps/union/Union_box.comp @@ -87,410 +87,420 @@ SETTING PARAMETERS(string material_string=0, priority, SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_box component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Union_box component" + #endif -void mcdisplay_box_function(struct lines_to_draw *lines_to_draw_output,int index, struct geometry_struct **Geometries,int number_of_volumes) { + void + mcdisplay_box_function (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { // Function to call in mcdisplay section of the sample component for this volume // One can assume that Volumes[index] refers to a volume with the geometry described in this file - + double depth = Geometries[index]->geometry_parameters.p_box_storage->z_depth; double width1 = Geometries[index]->geometry_parameters.p_box_storage->x_width1; double width2 = Geometries[index]->geometry_parameters.p_box_storage->x_width2; double height1 = Geometries[index]->geometry_parameters.p_box_storage->y_height1; double height2 = Geometries[index]->geometry_parameters.p_box_storage->y_height2; - + Coords x_vector = Geometries[index]->geometry_parameters.p_box_storage->x_vector; Coords y_vector = Geometries[index]->geometry_parameters.p_box_storage->y_vector; Coords z_vector = Geometries[index]->geometry_parameters.p_box_storage->z_vector; - + Coords center = Geometries[index]->center; - - Coords square1[4],square2[4]; - - square1[0] = coords_add(coords_add(coords_add(center,coords_scalar_mult(z_vector,-0.5*depth)),coords_scalar_mult(x_vector,-0.5*width1)),coords_scalar_mult(y_vector,-0.5*height1)); - - square1[1] = coords_add(square1[0],coords_scalar_mult(x_vector,width1)); - square1[2] = coords_add(square1[1],coords_scalar_mult(y_vector,height1)); - square1[3] = coords_add(square1[0],coords_scalar_mult(y_vector,height1)); - - square2[0] = coords_add(coords_add(coords_add(center,coords_scalar_mult(z_vector,0.5*depth)),coords_scalar_mult(x_vector,-0.5*width2)),coords_scalar_mult(y_vector,-0.5*height2)); - - square2[1] = coords_add(square2[0],coords_scalar_mult(x_vector,width2)); - square2[2] = coords_add(square2[1],coords_scalar_mult(y_vector,height2)); - square2[3] = coords_add(square2[0],coords_scalar_mult(y_vector,height2)); - + + Coords square1[4], square2[4]; + + square1[0] = coords_add (coords_add (coords_add (center, coords_scalar_mult (z_vector, -0.5 * depth)), coords_scalar_mult (x_vector, -0.5 * width1)), + coords_scalar_mult (y_vector, -0.5 * height1)); + + square1[1] = coords_add (square1[0], coords_scalar_mult (x_vector, width1)); + square1[2] = coords_add (square1[1], coords_scalar_mult (y_vector, height1)); + square1[3] = coords_add (square1[0], coords_scalar_mult (y_vector, height1)); + + square2[0] = coords_add (coords_add (coords_add (center, coords_scalar_mult (z_vector, 0.5 * depth)), coords_scalar_mult (x_vector, -0.5 * width2)), + coords_scalar_mult (y_vector, -0.5 * height2)); + + square2[1] = coords_add (square2[0], coords_scalar_mult (x_vector, width2)); + square2[2] = coords_add (square2[1], coords_scalar_mult (y_vector, height2)); + square2[3] = coords_add (square2[0], coords_scalar_mult (y_vector, height2)); + struct lines_to_draw lines_to_draw_temp; lines_to_draw_temp.number_of_lines = 0; - + int iterate; - for (iterate=0;iterate<3;iterate++) { - lines_to_draw_temp = draw_line_with_highest_priority(square1[iterate],square1[iterate+1],index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); + for (iterate = 0; iterate < 3; iterate++) { + lines_to_draw_temp = draw_line_with_highest_priority (square1[iterate], square1[iterate + 1], index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); } - lines_to_draw_temp = draw_line_with_highest_priority(square1[3],square1[0],index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); + lines_to_draw_temp = draw_line_with_highest_priority (square1[3], square1[0], index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); - for (iterate=0;iterate<3;iterate++) { - lines_to_draw_temp = draw_line_with_highest_priority(square2[iterate],square2[iterate+1],index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); + for (iterate = 0; iterate < 3; iterate++) { + lines_to_draw_temp = draw_line_with_highest_priority (square2[iterate], square2[iterate + 1], index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); } - lines_to_draw_temp = draw_line_with_highest_priority(square2[3],square2[0],index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); + lines_to_draw_temp = draw_line_with_highest_priority (square2[3], square2[0], index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); - for (iterate=0;iterate<4;iterate++) { - lines_to_draw_temp = draw_line_with_highest_priority(square1[iterate],square2[iterate],index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); + for (iterate = 0; iterate < 4; iterate++) { + lines_to_draw_temp = draw_line_with_highest_priority (square1[iterate], square2[iterate], index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); } -}; + }; -void initialize_box_geometry_from_main_component(struct geometry_struct *box) { + void + initialize_box_geometry_from_main_component (struct geometry_struct* box) { // Function to be called in initialize of the main component // This is done as the rotation matrix needs to be relative to the main component instead of global // Everything done in initialize in this component file has the rotation matrix relative to global - Coords simple_vector = coords_set(1,0,0); + Coords simple_vector = coords_set (1, 0, 0); Coords rotated_vector; - - rotated_vector = rot_apply(box->rotation_matrix,simple_vector); - NORM(rotated_vector.x,rotated_vector.y,rotated_vector.z); + + rotated_vector = rot_apply (box->rotation_matrix, simple_vector); + NORM (rotated_vector.x, rotated_vector.y, rotated_vector.z); box->geometry_parameters.p_box_storage->x_vector = rotated_vector; - - simple_vector = coords_set(0,1,0); - rotated_vector = rot_apply(box->rotation_matrix,simple_vector); - NORM(rotated_vector.x,rotated_vector.y,rotated_vector.z); + + simple_vector = coords_set (0, 1, 0); + rotated_vector = rot_apply (box->rotation_matrix, simple_vector); + NORM (rotated_vector.x, rotated_vector.y, rotated_vector.z); box->geometry_parameters.p_box_storage->y_vector = rotated_vector; - - simple_vector = coords_set(0,0,1); - rotated_vector = rot_apply(box->rotation_matrix,simple_vector); - NORM(rotated_vector.x,rotated_vector.y,rotated_vector.z); + + simple_vector = coords_set (0, 0, 1); + rotated_vector = rot_apply (box->rotation_matrix, simple_vector); + NORM (rotated_vector.x, rotated_vector.y, rotated_vector.z); box->geometry_parameters.p_box_storage->z_vector = rotated_vector; -}; - -struct pointer_to_1d_coords_list box_shell_points(struct geometry_struct *geometry,int max_number_of_points) { - // This function returns an array of corner positions for the box in the main coordinate system. - // Normally one would limit it to a maximum number of points, but as there are only 8 for the box, - // it is hardcoded to 8. Other geometries can be approximated with a variable number of points. - - struct pointer_to_1d_coords_list corner_points; - corner_points.elements = malloc(8*sizeof(Coords)); - corner_points.num_elements = 8; - - double depth = geometry->geometry_parameters.p_box_storage->z_depth; - double width1 = geometry->geometry_parameters.p_box_storage->x_width1; - double width2 = geometry->geometry_parameters.p_box_storage->x_width2; - double height1 = geometry->geometry_parameters.p_box_storage->y_height1; - double height2 = geometry->geometry_parameters.p_box_storage->y_height2; - - Coords x_vector = geometry->geometry_parameters.p_box_storage->x_vector; - Coords y_vector = geometry->geometry_parameters.p_box_storage->y_vector; - Coords z_vector = geometry->geometry_parameters.p_box_storage->z_vector; - - Coords center = geometry->center; - - corner_points.elements[0] = coords_add(coords_add(coords_add(center,coords_scalar_mult(z_vector,-0.5*depth)),coords_scalar_mult(x_vector,-0.5*width1)),coords_scalar_mult(y_vector,-0.5*height1)); - - corner_points.elements[1] = coords_add(corner_points.elements[0],coords_scalar_mult(x_vector,width1)); - corner_points.elements[2] = coords_add(corner_points.elements[1],coords_scalar_mult(y_vector,height1)); - corner_points.elements[3] = coords_add(corner_points.elements[0],coords_scalar_mult(y_vector,height1)); - - corner_points.elements[4] = coords_add(coords_add(coords_add(center,coords_scalar_mult(z_vector,0.5*depth)),coords_scalar_mult(x_vector,-0.5*width2)),coords_scalar_mult(y_vector,-0.5*height2)); - - corner_points.elements[5] = coords_add(corner_points.elements[4],coords_scalar_mult(x_vector,width2)); - corner_points.elements[6] = coords_add(corner_points.elements[5],coords_scalar_mult(y_vector,height2)); - corner_points.elements[7] = coords_add(corner_points.elements[4],coords_scalar_mult(y_vector,height2)); - - return corner_points; - -} - -#ifndef ANY_GEOMETRY_DETECTOR_DECLARE - #define ANY_GEOMETRY_DETECTOR_DECLARE dummy -#endif + }; + + struct pointer_to_1d_coords_list + box_shell_points (struct geometry_struct* geometry, int max_number_of_points) { + // This function returns an array of corner positions for the box in the main coordinate system. + // Normally one would limit it to a maximum number of points, but as there are only 8 for the box, + // it is hardcoded to 8. Other geometries can be approximated with a variable number of points. + + struct pointer_to_1d_coords_list corner_points; + corner_points.elements = malloc (8 * sizeof (Coords)); + corner_points.num_elements = 8; + + double depth = geometry->geometry_parameters.p_box_storage->z_depth; + double width1 = geometry->geometry_parameters.p_box_storage->x_width1; + double width2 = geometry->geometry_parameters.p_box_storage->x_width2; + double height1 = geometry->geometry_parameters.p_box_storage->y_height1; + double height2 = geometry->geometry_parameters.p_box_storage->y_height2; + + Coords x_vector = geometry->geometry_parameters.p_box_storage->x_vector; + Coords y_vector = geometry->geometry_parameters.p_box_storage->y_vector; + Coords z_vector = geometry->geometry_parameters.p_box_storage->z_vector; + Coords center = geometry->center; + + corner_points.elements[0] + = coords_add (coords_add (coords_add (center, coords_scalar_mult (z_vector, -0.5 * depth)), coords_scalar_mult (x_vector, -0.5 * width1)), + coords_scalar_mult (y_vector, -0.5 * height1)); + + corner_points.elements[1] = coords_add (corner_points.elements[0], coords_scalar_mult (x_vector, width1)); + corner_points.elements[2] = coords_add (corner_points.elements[1], coords_scalar_mult (y_vector, height1)); + corner_points.elements[3] = coords_add (corner_points.elements[0], coords_scalar_mult (y_vector, height1)); + + corner_points.elements[4] + = coords_add (coords_add (coords_add (center, coords_scalar_mult (z_vector, 0.5 * depth)), coords_scalar_mult (x_vector, -0.5 * width2)), + coords_scalar_mult (y_vector, -0.5 * height2)); + + corner_points.elements[5] = coords_add (corner_points.elements[4], coords_scalar_mult (x_vector, width2)); + corner_points.elements[6] = coords_add (corner_points.elements[5], coords_scalar_mult (y_vector, height2)); + corner_points.elements[7] = coords_add (corner_points.elements[4], coords_scalar_mult (y_vector, height2)); + + return corner_points; + } + + #ifndef ANY_GEOMETRY_DETECTOR_DECLARE + #define ANY_GEOMETRY_DETECTOR_DECLARE dummy + #endif %} DECLARE %{ -// Needed for transport to the main component -struct global_geometry_element_struct global_geometry_element; + // Needed for transport to the main component + struct global_geometry_element_struct global_geometry_element; -int loop_index; + int loop_index; -double x_component; -double y_component; -double z_component; + double x_component; + double y_component; + double z_component; -struct Volume_struct this_box_volume; -struct box_storage this_box_storage; + struct Volume_struct this_box_volume; + struct box_storage this_box_storage; -struct surface_stack_struct plus_x_surface_stack; -struct surface_stack_struct minus_x_surface_stack; -struct surface_stack_struct plus_y_surface_stack; -struct surface_stack_struct minus_y_surface_stack; -struct surface_stack_struct plus_z_surface_stack; -struct surface_stack_struct minus_z_surface_stack; -struct surface_stack_struct cut_surface_stack; + struct surface_stack_struct plus_x_surface_stack; + struct surface_stack_struct minus_x_surface_stack; + struct surface_stack_struct plus_y_surface_stack; + struct surface_stack_struct minus_y_surface_stack; + struct surface_stack_struct plus_z_surface_stack; + struct surface_stack_struct minus_z_surface_stack; + struct surface_stack_struct cut_surface_stack; %} INITIALIZE %{ -// Initialize this Volume -geometry_struct_init(&(this_box_volume.geometry)); -// Initializes the focusing system for this volume including input sanitation. -focus_initialize(&this_box_volume.geometry, POS_A_COMP_INDEX(INDEX_CURRENT_COMP+target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, target_x, target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); - -// Input sanitation for this geometry -if (xwidth <= 0) { - printf("\nERROR in Union_box named %s, the xwidth is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} -if (yheight <= 0) { - printf("\nERROR in Union_box named %s, yheight is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} -if (zdepth <= 0) { - printf("\nERROR in Union_box named %s, zdepth is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} -if (xwidth2 <= 0 && xwidth2 != -1) { - printf("\nERROR in Union_box named %s, the xwidth2 is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} -if (yheight2 <= 0 && yheight2 != -1) { - printf("\nERROR in Union_box named %s, yheight2 is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} - -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_box:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} - -struct pointer_to_global_material_list *global_material_list = COMP_GETPAR3(Union_init, init, global_material_list); -// Use sanitation -if (global_material_list->num_elements == 0) { - printf("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); - printf(" %s was defined before first use of Union_make_material.\n", NAME_CURRENT_COMP); - exit(1); -} - -this_box_volume.geometry.is_masked_volume = 0; -this_box_volume.geometry.is_exit_volume = 0; -this_box_volume.geometry.is_mask_volume = 0; -struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); -// check if the volume is a mask, if it is the material string is irelevant. -if (mask_string && strlen(mask_string) && strcmp(mask_string, "NULL") && strcmp(mask_string, "0")) { + // Initialize this Volume + geometry_struct_init (&(this_box_volume.geometry)); + // Initializes the focusing system for this volume including input sanitation. + focus_initialize (&this_box_volume.geometry, POS_A_COMP_INDEX (INDEX_CURRENT_COMP + target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, + target_x, target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); + + // Input sanitation for this geometry + if (xwidth <= 0) { + printf ("\nERROR in Union_box named %s, the xwidth is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + if (yheight <= 0) { + printf ("\nERROR in Union_box named %s, yheight is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + if (zdepth <= 0) { + printf ("\nERROR in Union_box named %s, zdepth is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + if (xwidth2 <= 0 && xwidth2 != -1) { + printf ("\nERROR in Union_box named %s, the xwidth2 is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + if (yheight2 <= 0 && yheight2 != -1) { + printf ("\nERROR in Union_box named %s, yheight2 is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_box:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } + + struct pointer_to_global_material_list* global_material_list = COMP_GETPAR3 (Union_init, init, global_material_list); + // Use sanitation + if (global_material_list->num_elements == 0) { + printf ("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); + printf (" %s was defined before first use of Union_make_material.\n", NAME_CURRENT_COMP); + exit (1); + } + + this_box_volume.geometry.is_masked_volume = 0; + this_box_volume.geometry.is_exit_volume = 0; + this_box_volume.geometry.is_mask_volume = 0; + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + // check if the volume is a mask, if it is the material string is irelevant. + if (mask_string && strlen (mask_string) && strcmp (mask_string, "NULL") && strcmp (mask_string, "0")) { // A mask volume is used to limit the extend of other volumes, called the masked volumes. These are specified in the mask_string. // In order for a ray to enter a masked volume, it needs to be both in the region covered by that volume AND the mask volume. // When more than this_box_volume.geometry.mask_mode = 1; // Default is mask mode is ALL - if (mask_setting && strlen(mask_setting) && strcmp(mask_setting, "NULL") && strcmp(mask_setting, "0")) { - if (strcmp(mask_setting,"ALL") == 0 || strcmp(mask_setting,"All") == 0) this_box_volume.geometry.mask_mode = 1; - else if (strcmp(mask_setting,"ANY") == 0 || strcmp(mask_setting,"Any") == 0) this_box_volume.geometry.mask_mode = 2; - else { - printf("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n",NAME_CURRENT_COMP,mask_setting); - exit(1); - } + if (mask_setting && strlen (mask_setting) && strcmp (mask_setting, "NULL") && strcmp (mask_setting, "0")) { + if (strcmp (mask_setting, "ALL") == 0 || strcmp (mask_setting, "All") == 0) + this_box_volume.geometry.mask_mode = 1; + else if (strcmp (mask_setting, "ANY") == 0 || strcmp (mask_setting, "Any") == 0) + this_box_volume.geometry.mask_mode = 2; + else { + printf ("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n", NAME_CURRENT_COMP, mask_setting); + exit (1); + } } - + int found_geometries = 0; - for (loop_index=0;loop_indexnum_elements;loop_index++) { - // Add mask list - if (1 == manual_linking_function(global_geometry_list->elements[loop_index].name,mask_string)) { - add_element_to_int_list(&this_box_volume.geometry.mask_list,global_geometry_list->elements[loop_index].component_index); - add_element_to_int_list(&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list,INDEX_CURRENT_COMP); - global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; - if (this_box_volume.geometry.mask_mode == 2) - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; - if (this_box_volume.geometry.mask_mode == 1) { - if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) - // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; - } - - found_geometries = 1; + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + // Add mask list + if (1 == manual_linking_function (global_geometry_list->elements[loop_index].name, mask_string)) { + add_element_to_int_list (&this_box_volume.geometry.mask_list, global_geometry_list->elements[loop_index].component_index); + add_element_to_int_list (&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list, INDEX_CURRENT_COMP); + global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; + if (this_box_volume.geometry.mask_mode == 2) + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; + if (this_box_volume.geometry.mask_mode == 1) { + if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 + && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) + // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; } + + found_geometries = 1; + } } if (found_geometries == 0) { - printf("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n",NAME_CURRENT_COMP,mask_string); - exit(1); + printf ("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n", NAME_CURRENT_COMP, mask_string); + exit (1); } - this_box_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_box_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum - this_box_volume.p_physics->number_of_processes = (int) 0; // Should not be used. - this_box_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_box_volume.p_physics->name,"Mask"); + this_box_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_box_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum + this_box_volume.p_physics->number_of_processes = (int)0; // Should not be used. + this_box_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_box_volume.p_physics->name, "Mask"); this_box_volume.geometry.is_mask_volume = 1; - - -// Read the material input, or if it lacks, use automatic linking. -} else if (material_string && strlen(material_string) && strcmp(material_string, "NULL") && strcmp(material_string, "0")) { + + // Read the material input, or if it lacks, use automatic linking. + } else if (material_string && strlen (material_string) && strcmp (material_string, "NULL") && strcmp (material_string, "0")) { // A geometry string was given, use it to determine which material - if (0 == strcmp(material_string,"vacuum") || 0 == strcmp(material_string,"Vacuum")) { - // One could have a global physics struct for vacuum instead of creating one for each - this_box_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_box_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_box_volume.p_physics->number_of_processes = (int) 0; // Should not be used. - this_box_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_box_volume.p_physics->name,"Vacuum"); - } else if (0 == strcmp(material_string,"exit") || 0 == strcmp(material_string,"Exit")) { - // One could have a global physics struct for vacuum instead of creating one for each - this_box_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_box_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_box_volume.p_physics->number_of_processes = (int) 0; // Should not be used. - this_box_volume.p_physics->my_a = 0; // Should not be used. - this_box_volume.geometry.is_exit_volume = 1; - sprintf(this_box_volume.p_physics->name,"Exit"); + if (0 == strcmp (material_string, "vacuum") || 0 == strcmp (material_string, "Vacuum")) { + // One could have a global physics struct for vacuum instead of creating one for each + this_box_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_box_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_box_volume.p_physics->number_of_processes = (int)0; // Should not be used. + this_box_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_box_volume.p_physics->name, "Vacuum"); + } else if (0 == strcmp (material_string, "exit") || 0 == strcmp (material_string, "Exit")) { + // One could have a global physics struct for vacuum instead of creating one for each + this_box_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_box_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_box_volume.p_physics->number_of_processes = (int)0; // Should not be used. + this_box_volume.p_physics->my_a = 0; // Should not be used. + this_box_volume.geometry.is_exit_volume = 1; + sprintf (this_box_volume.p_physics->name, "Exit"); } else { - #ifndef MATERIAL_DETECTOR - printf("Need to define a material before refering to it in a geometry %s.\n",NAME_CURRENT_COMP); - exit(1); - #endif - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (0 == strcmp(material_string,global_material_list->elements[loop_index].name)) { - this_box_volume.p_physics = global_material_list->elements[loop_index].physics; - break; - } - if (loop_index == global_material_list->num_elements-1) { - printf("\n"); - printf("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n",material_string,NAME_CURRENT_COMP); - printf(" The materials available at this point (need to be defined before the geometry): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_material_list->elements[loop_index].name); - printf("\n"); - printf(" It is also possible to use one of the defualt materials avaiable: \n"); - printf(" Vacuum (for a Volume without scattering or absorption)\n"); - printf(" Exit (for a Volume where the ray exits the component if it enters)\n"); - printf(" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); - exit(1); - } + #ifndef MATERIAL_DETECTOR + printf ("Need to define a material before refering to it in a geometry %s.\n", NAME_CURRENT_COMP); + exit (1); + #endif + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) { + if (0 == strcmp (material_string, global_material_list->elements[loop_index].name)) { + this_box_volume.p_physics = global_material_list->elements[loop_index].physics; + break; } + if (loop_index == global_material_list->num_elements - 1) { + printf ("\n"); + printf ("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n", material_string, NAME_CURRENT_COMP); + printf (" The materials available at this point (need to be defined before the geometry): \n"); + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) + printf (" %s\n", global_material_list->elements[loop_index].name); + printf ("\n"); + printf (" It is also possible to use one of the defualt materials avaiable: \n"); + printf (" Vacuum (for a Volume without scattering or absorption)\n"); + printf (" Exit (for a Volume where the ray exits the component if it enters)\n"); + printf (" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); + exit (1); + } + } } -} else { + } else { // Automatic linking, simply using the last defined material. #ifndef MATERIAL_DETECTOR - printf("Need to define a material before the geometry to use automatic linking %s.\n",NAME_CURRENT_COMP); - exit(1); + printf ("Need to define a material before the geometry to use automatic linking %s.\n", NAME_CURRENT_COMP); + exit (1); #endif - this_box_volume.p_physics = global_material_list->elements[global_material_list->num_elements-1].physics; -} - - -sprintf(this_box_volume.name,"%s",NAME_CURRENT_COMP); -sprintf(this_box_volume.geometry.shape,"box"); -this_box_volume.geometry.eShape = box; -this_box_volume.geometry.priority_value = priority; -this_box_volume.geometry.geometry_p_interact = p_interact; -// Currently the coordinates will be in absolute space. -this_box_volume.geometry.center = POS_A_CURRENT_COMP; - -this_box_storage.z_depth = zdepth; -this_box_storage.x_width1 = xwidth; -this_box_storage.y_height1 = yheight; - -this_box_storage.is_rectangle = 0; -if (xwidth2 < 0 && yheight2 < 0) this_box_storage.is_rectangle = 1; -if (xwidth == xwidth2 && yheight == yheight2) this_box_storage.is_rectangle = 1; - -if (xwidth2 < 0) { + this_box_volume.p_physics = global_material_list->elements[global_material_list->num_elements - 1].physics; + } + + sprintf (this_box_volume.name, "%s", NAME_CURRENT_COMP); + sprintf (this_box_volume.geometry.shape, "box"); + this_box_volume.geometry.eShape = box; + this_box_volume.geometry.priority_value = priority; + this_box_volume.geometry.geometry_p_interact = p_interact; + // Currently the coordinates will be in absolute space. + this_box_volume.geometry.center = POS_A_CURRENT_COMP; + + this_box_storage.z_depth = zdepth; + this_box_storage.x_width1 = xwidth; + this_box_storage.y_height1 = yheight; + + this_box_storage.is_rectangle = 0; + if (xwidth2 < 0 && yheight2 < 0) + this_box_storage.is_rectangle = 1; + if (xwidth == xwidth2 && yheight == yheight2) + this_box_storage.is_rectangle = 1; + + if (xwidth2 < 0) { this_box_storage.x_width2 = xwidth; xwidth2 = xwidth; -} else this_box_storage.x_width2 = xwidth2; + } else + this_box_storage.x_width2 = xwidth2; -if (yheight2 < 0) { + if (yheight2 < 0) { this_box_storage.y_height2 = yheight; yheight2 = yheight; -} else this_box_storage.y_height2 = yheight2; - - -this_box_storage.normal_vectors[0] = coords_set(0,0,1); -this_box_storage.normal_vectors[1] = coords_set(0,0,1); - -// for sides with y component = 0 -x_component = 2.0*zdepth/sqrt((xwidth-xwidth2)*(xwidth-xwidth2)+4.0*zdepth*zdepth); -z_component = (xwidth-xwidth2)/sqrt(4.0*zdepth*zdepth+(xwidth-xwidth2)*(xwidth-xwidth2)); - -this_box_storage.normal_vectors[2] = coords_set(x_component,0.0,z_component); -this_box_storage.normal_vectors[3] = coords_set(-x_component,0.0,z_component); - -// for sides with x component = 0 -y_component = 2.0*zdepth/sqrt((yheight-yheight2)*(yheight-yheight2)+4.0*zdepth*zdepth); -z_component = (yheight-yheight2)/sqrt(4.0*zdepth*zdepth+(yheight-yheight2)*(yheight-yheight2)); - -this_box_storage.normal_vectors[4] = coords_set(0,y_component,z_component); -this_box_storage.normal_vectors[5] = coords_set(0,-y_component,z_component); - -this_box_volume.geometry.visualization_on = visualize; - -this_box_volume.geometry.geometry_parameters.p_box_storage = &this_box_storage; - -// Assign pointers to functions for intersection with the shape, checking if a point is inside the shape -if (this_box_storage.is_rectangle == 1) { -this_box_volume.geometry.intersect_function = &sample_box_intersect_simple; -this_box_volume.geometry.within_function = &r_within_box_simple; -} -else { -this_box_volume.geometry.intersect_function = &sample_box_intersect_advanced; -this_box_volume.geometry.within_function = &r_within_box_advanced; -} - -this_box_volume.geometry.shell_points = &box_shell_points; -this_box_volume.geometry.mcdisplay_function = &mcdisplay_box_function; -this_box_volume.geometry.initialize_from_main_function = &initialize_box_geometry_from_main_component; -this_box_volume.geometry.process_rot_allocated = 0; - -this_box_volume.geometry.copy_geometry_parameters = &allocate_box_storage_copy; - -rot_copy(this_box_volume.geometry.rotation_matrix,ROT_A_CURRENT_COMP); //check how ROT_R_CURRENT_COMP would work -rot_transpose(ROT_A_CURRENT_COMP,this_box_volume.geometry.transpose_rotation_matrix); - -// Handle surface input -if (all_face_surface && strlen(all_face_surface) && strcmp(all_face_surface, "NULL") && strcmp(all_face_surface, "0")) { - // Overwrite all other surfaces that have no input (if one wants a surface left without anything, None can be used) - overwrite_if_empty(plus_x_surface, all_face_surface); - overwrite_if_empty(minus_x_surface, all_face_surface); - overwrite_if_empty(plus_y_surface, all_face_surface); - overwrite_if_empty(minus_y_surface, all_face_surface); - overwrite_if_empty(plus_z_surface, all_face_surface); - overwrite_if_empty(minus_z_surface, all_face_surface); -} - -this_box_volume.geometry.number_of_faces = 6; -this_box_volume.geometry.surface_stack_for_each_face = malloc(this_box_volume.geometry.number_of_faces*sizeof(struct surface_stack_struct*)); - -// This could be inserted into the fill_surface_stack function -this_box_volume.geometry.surface_stack_for_each_face[0] = &minus_z_surface_stack; -this_box_volume.geometry.surface_stack_for_each_face[1] = &plus_z_surface_stack; -this_box_volume.geometry.surface_stack_for_each_face[2] = &plus_x_surface_stack; -this_box_volume.geometry.surface_stack_for_each_face[3] = &minus_x_surface_stack; -this_box_volume.geometry.surface_stack_for_each_face[4] = &plus_y_surface_stack; -this_box_volume.geometry.surface_stack_for_each_face[5] = &minus_y_surface_stack; -this_box_volume.geometry.internal_cut_surface_stack = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume - -struct pointer_to_global_surface_list *global_surface_list = COMP_GETPAR3(Union_init, init, global_surface_list); -fill_surface_stack(plus_x_surface, global_surface_list, NAME_CURRENT_COMP, &plus_x_surface_stack); -fill_surface_stack(minus_x_surface, global_surface_list, NAME_CURRENT_COMP, &minus_x_surface_stack); -fill_surface_stack(plus_y_surface, global_surface_list, NAME_CURRENT_COMP, &plus_y_surface_stack); -fill_surface_stack(minus_y_surface, global_surface_list, NAME_CURRENT_COMP, &minus_y_surface_stack); -fill_surface_stack(plus_z_surface, global_surface_list, NAME_CURRENT_COMP, &plus_z_surface_stack); -fill_surface_stack(minus_z_surface, global_surface_list, NAME_CURRENT_COMP, &minus_z_surface_stack); -fill_surface_stack(cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); - -// Initialize loggers -this_box_volume.loggers.num_elements = 0; -this_box_volume.abs_loggers.num_elements = 0; - -// packing the information into the global_geometry_element, which is then included in the global_geometry_list. -sprintf(global_geometry_element.name,"%s",NAME_CURRENT_COMP); -global_geometry_element.activation_counter = number_of_activations; -global_geometry_element.component_index = INDEX_CURRENT_COMP; -global_geometry_element.Volume = &this_box_volume; // Would be nicer if this m was a pointer, now we have the (small) data two places -//char *test_component; -//char *sigma_name; -//COMP_GETPAR(test_component, sigma_name); -add_element_to_geometry_list(global_geometry_list, global_geometry_element); + } else + this_box_storage.y_height2 = yheight2; + + this_box_storage.normal_vectors[0] = coords_set (0, 0, 1); + this_box_storage.normal_vectors[1] = coords_set (0, 0, 1); + + // for sides with y component = 0 + x_component = 2.0 * zdepth / sqrt ((xwidth - xwidth2) * (xwidth - xwidth2) + 4.0 * zdepth * zdepth); + z_component = (xwidth - xwidth2) / sqrt (4.0 * zdepth * zdepth + (xwidth - xwidth2) * (xwidth - xwidth2)); + + this_box_storage.normal_vectors[2] = coords_set (x_component, 0.0, z_component); + this_box_storage.normal_vectors[3] = coords_set (-x_component, 0.0, z_component); + + // for sides with x component = 0 + y_component = 2.0 * zdepth / sqrt ((yheight - yheight2) * (yheight - yheight2) + 4.0 * zdepth * zdepth); + z_component = (yheight - yheight2) / sqrt (4.0 * zdepth * zdepth + (yheight - yheight2) * (yheight - yheight2)); + + this_box_storage.normal_vectors[4] = coords_set (0, y_component, z_component); + this_box_storage.normal_vectors[5] = coords_set (0, -y_component, z_component); + + this_box_volume.geometry.visualization_on = visualize; + + this_box_volume.geometry.geometry_parameters.p_box_storage = &this_box_storage; + + // Assign pointers to functions for intersection with the shape, checking if a point is inside the shape + if (this_box_storage.is_rectangle == 1) { + this_box_volume.geometry.intersect_function = &sample_box_intersect_simple; + this_box_volume.geometry.within_function = &r_within_box_simple; + } else { + this_box_volume.geometry.intersect_function = &sample_box_intersect_advanced; + this_box_volume.geometry.within_function = &r_within_box_advanced; + } + + this_box_volume.geometry.shell_points = &box_shell_points; + this_box_volume.geometry.mcdisplay_function = &mcdisplay_box_function; + this_box_volume.geometry.initialize_from_main_function = &initialize_box_geometry_from_main_component; + this_box_volume.geometry.process_rot_allocated = 0; + + this_box_volume.geometry.copy_geometry_parameters = &allocate_box_storage_copy; + + rot_copy (this_box_volume.geometry.rotation_matrix, ROT_A_CURRENT_COMP); // check how ROT_R_CURRENT_COMP would work + rot_transpose (ROT_A_CURRENT_COMP, this_box_volume.geometry.transpose_rotation_matrix); + + // Handle surface input + if (all_face_surface && strlen (all_face_surface) && strcmp (all_face_surface, "NULL") && strcmp (all_face_surface, "0")) { + // Overwrite all other surfaces that have no input (if one wants a surface left without anything, None can be used) + overwrite_if_empty (plus_x_surface, all_face_surface); + overwrite_if_empty (minus_x_surface, all_face_surface); + overwrite_if_empty (plus_y_surface, all_face_surface); + overwrite_if_empty (minus_y_surface, all_face_surface); + overwrite_if_empty (plus_z_surface, all_face_surface); + overwrite_if_empty (minus_z_surface, all_face_surface); + } + + this_box_volume.geometry.number_of_faces = 6; + this_box_volume.geometry.surface_stack_for_each_face = malloc (this_box_volume.geometry.number_of_faces * sizeof (struct surface_stack_struct*)); + + // This could be inserted into the fill_surface_stack function + this_box_volume.geometry.surface_stack_for_each_face[0] = &minus_z_surface_stack; + this_box_volume.geometry.surface_stack_for_each_face[1] = &plus_z_surface_stack; + this_box_volume.geometry.surface_stack_for_each_face[2] = &plus_x_surface_stack; + this_box_volume.geometry.surface_stack_for_each_face[3] = &minus_x_surface_stack; + this_box_volume.geometry.surface_stack_for_each_face[4] = &plus_y_surface_stack; + this_box_volume.geometry.surface_stack_for_each_face[5] = &minus_y_surface_stack; + this_box_volume.geometry.internal_cut_surface_stack = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume + + struct pointer_to_global_surface_list* global_surface_list = COMP_GETPAR3 (Union_init, init, global_surface_list); + fill_surface_stack (plus_x_surface, global_surface_list, NAME_CURRENT_COMP, &plus_x_surface_stack); + fill_surface_stack (minus_x_surface, global_surface_list, NAME_CURRENT_COMP, &minus_x_surface_stack); + fill_surface_stack (plus_y_surface, global_surface_list, NAME_CURRENT_COMP, &plus_y_surface_stack); + fill_surface_stack (minus_y_surface, global_surface_list, NAME_CURRENT_COMP, &minus_y_surface_stack); + fill_surface_stack (plus_z_surface, global_surface_list, NAME_CURRENT_COMP, &plus_z_surface_stack); + fill_surface_stack (minus_z_surface, global_surface_list, NAME_CURRENT_COMP, &minus_z_surface_stack); + fill_surface_stack (cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); + + // Initialize loggers + this_box_volume.loggers.num_elements = 0; + this_box_volume.abs_loggers.num_elements = 0; + + // packing the information into the global_geometry_element, which is then included in the global_geometry_list. + sprintf (global_geometry_element.name, "%s", NAME_CURRENT_COMP); + global_geometry_element.activation_counter = number_of_activations; + global_geometry_element.component_index = INDEX_CURRENT_COMP; + global_geometry_element.Volume = &this_box_volume; // Would be nicer if this m was a pointer, now we have the (small) data two places + // char *test_component; + // char *sigma_name; + // COMP_GETPAR(test_component, sigma_name); + add_element_to_geometry_list (global_geometry_list, global_geometry_element); %} TRACE diff --git a/mcstas-comps/union/Union_conditional_PSD.comp b/mcstas-comps/union/Union_conditional_PSD.comp index 3d262f72b4..f52d57478e 100644 --- a/mcstas-comps/union/Union_conditional_PSD.comp +++ b/mcstas-comps/union/Union_conditional_PSD.comp @@ -81,142 +81,148 @@ SETTING PARAMETERS(string target_loggers="NULL", int master_tagging=0, int taggi SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_conditional_PSD component" -#endif - -int conditional_function_PSD(union conditional_data_union *data_union, Coords *position, Coords *velocity, double *weight, double *time, int *current_volume, int *total_number_of_scattering, int *number_of_scattering_per_volume, int **number_of_scattering_per_volume_process) { - - // Transform to this coordinate system - Coords local_position = transform_position(*position,data_union->p_PSD->PSD_position,data_union->p_PSD->PSD_rotation); - Coords local_velocity = rot_apply(data_union->p_PSD->PSD_rotation,*velocity); - - // Prop_Z0 - if (local_velocity.z == 0) return 0; - double dt = -local_position.z/local_velocity.z; - if (dt<0) return 0; - local_position.x = local_position.x + dt*local_velocity.x; - local_position.y = local_position.y + dt*local_velocity.y; - - double detect_time = *time + dt; - - if (data_union->p_PSD->T_limit == 1) { - if (detect_time < data_union->p_PSD->Tmin || detect_time > data_union->p_PSD->Tmax) + #ifndef Union + #error "The Union_init component must be included before this Union_conditional_PSD component" + #endif + + int + conditional_function_PSD (union conditional_data_union* data_union, Coords* position, Coords* velocity, double* weight, double* time, int* current_volume, + int* total_number_of_scattering, int* number_of_scattering_per_volume, int** number_of_scattering_per_volume_process) { + + // Transform to this coordinate system + Coords local_position = transform_position (*position, data_union->p_PSD->PSD_position, data_union->p_PSD->PSD_rotation); + Coords local_velocity = rot_apply (data_union->p_PSD->PSD_rotation, *velocity); + + // Prop_Z0 + if (local_velocity.z == 0) + return 0; + double dt = -local_position.z / local_velocity.z; + if (dt < 0) + return 0; + local_position.x = local_position.x + dt * local_velocity.x; + local_position.y = local_position.y + dt * local_velocity.y; + + double detect_time = *time + dt; + + if (data_union->p_PSD->T_limit == 1) { + if (detect_time < data_union->p_PSD->Tmin || detect_time > data_union->p_PSD->Tmax) + return 0; + } + + if (local_position.x > data_union->p_PSD->PSD_half_xwidth) + return 0; + if (local_position.x < -data_union->p_PSD->PSD_half_xwidth) return 0; + if (local_position.y > data_union->p_PSD->PSD_half_yheight) + return 0; + if (local_position.y < -data_union->p_PSD->PSD_half_yheight) + return 0; + + // All conditions fulfilled + return 1; } - - if (local_position.x > data_union->p_PSD->PSD_half_xwidth) return 0; - if (local_position.x < -data_union->p_PSD->PSD_half_xwidth) return 0; - if (local_position.y > data_union->p_PSD->PSD_half_yheight) return 0; - if (local_position.y < -data_union->p_PSD->PSD_half_yheight) return 0; - - - // All conditions fulfilled - return 1; - -} - -// Only need to define linking function for conditionals once. -// Does not need to redefine functions from: make_material / loggers, as one of each needs to be defined before. -#ifndef UNION_CONDITIONAL -#define UNION_CONDITIONAL Dummy -// Linking function for loggers, finds the indicies of the specified loggers on global_logger_lists -int manual_linking_logger_function_conditional(char *input_string, struct pointer_to_global_logger_list *global_logger_list, struct pointer_to_1d_int_list *accepted_loggers) { + + // Only need to define linking function for conditionals once. + // Does not need to redefine functions from: make_material / loggers, as one of each needs to be defined before. + #ifndef UNION_CONDITIONAL + #define UNION_CONDITIONAL Dummy + // Linking function for loggers, finds the indicies of the specified loggers on global_logger_lists + int + manual_linking_logger_function_conditional (char* input_string, struct pointer_to_global_logger_list* global_logger_list, + struct pointer_to_1d_int_list* accepted_loggers) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[1024]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_logger_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_loggers,loop_index); + char* token; + int loop_index; + char local_string[1024]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_logger_list->num_elements; loop_index++) { + if (strcmp (token, global_logger_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_loggers, loop_index); break; } } - + // Updates the token - token = strtok(NULL,","); - } - - return accepted_loggers->num_elements; -} - -int count_commas(char *string) { - int return_value = 0; - - int index; - for (index=0;indexnum_elements; } - - //printf("number_of_commas = %d \n",return_value); - return return_value; -} -int manual_linking_abs_logger_function_conditional(char *input_string, struct pointer_to_global_abs_logger_list *global_abs_logger_list, struct pointer_to_1d_int_list *accepted_abs_loggers) { + int + count_commas (char* string) { + int return_value = 0; + + int index; + for (index = 0; index < strlen (string); index++) { + // printf("%c \n",string[index]); + if (string[index] == ',') + return_value++; + } + + // printf("number_of_commas = %d \n",return_value); + return return_value; + } + + int + manual_linking_abs_logger_function_conditional (char* input_string, struct pointer_to_global_abs_logger_list* global_abs_logger_list, + struct pointer_to_1d_int_list* accepted_abs_loggers) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_abs_logger_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_abs_loggers,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_abs_logger_list->num_elements; loop_index++) { + if (strcmp (token, global_abs_logger_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_abs_loggers, loop_index); break; } } - - // Updates the token - token = strtok(NULL,","); - } - - return accepted_abs_loggers->num_elements; -} -#endif - + // Updates the token + token = strtok (NULL, ","); + } + return accepted_abs_loggers->num_elements; + } + #endif %} DECLARE %{ -int loop_index; + int loop_index; -// This function pointer is used to switch the logger function pointers for active and inactive logger functions. -// Need to have the same input (defined in logger_pointer_set_struct in union-lib.c) -//void (*temp_function_pointer)(Coords*, double*, double*, double, double, double, int, int, int, struct logger_struct*, struct logger_with_data_struct*); -int return_value; -struct pointer_to_1d_int_list accepted_loggers_all; -struct pointer_to_1d_int_list accepted_loggers_specific; -struct pointer_to_1d_int_list accepted_abs_loggers_all; -struct pointer_to_1d_int_list accepted_abs_loggers_specific; -//struct pointer_to_1d_int_list accepted_tagging = {0,NULL}; + // This function pointer is used to switch the logger function pointers for active and inactive logger functions. + // Need to have the same input (defined in logger_pointer_set_struct in union-lib.c) + // void (*temp_function_pointer)(Coords*, double*, double*, double, double, double, int, int, int, struct logger_struct*, struct logger_with_data_struct*); + int return_value; + struct pointer_to_1d_int_list accepted_loggers_all; + struct pointer_to_1d_int_list accepted_loggers_specific; + struct pointer_to_1d_int_list accepted_abs_loggers_all; + struct pointer_to_1d_int_list accepted_abs_loggers_specific; + // struct pointer_to_1d_int_list accepted_tagging = {0,NULL}; -struct logger_struct *found_logger; -struct abs_logger_struct *found_abs_logger; + struct logger_struct* found_logger; + struct abs_logger_struct* found_abs_logger; -struct conditional_PSD_struct this_conditional_data; -union conditional_data_union this_data_union; - -struct global_tagging_conditional_element_struct *new_tagging_element; + struct conditional_PSD_struct this_conditional_data; + union conditional_data_union this_data_union; + struct global_tagging_conditional_element_struct* new_tagging_element; %} INITIALIZE @@ -230,205 +236,209 @@ INITIALIZE accepted_abs_loggers_specific.elements = NULL; accepted_abs_loggers_specific.num_elements = 0; - printf("starded conditional initialize \n"); - + printf ("starded conditional initialize \n"); + // If time range is set, use it if (time_min == time_max) this_conditional_data.T_limit = 0; else this_conditional_data.T_limit = 1; - + this_conditional_data.Tmin = time_min; this_conditional_data.Tmax = time_max; - + if (xwidth < 0) { - printf("ERROR: In Union conditional %s xwidth is less than 0!\n",NAME_CURRENT_COMP); + printf ("ERROR: In Union conditional %s xwidth is less than 0!\n", NAME_CURRENT_COMP); } - this_conditional_data.PSD_half_xwidth = 0.5*xwidth; - + this_conditional_data.PSD_half_xwidth = 0.5 * xwidth; + if (yheight < 0) { - printf("ERROR: In Union conditional %s yheight is less than 0!\n",NAME_CURRENT_COMP); + printf ("ERROR: In Union conditional %s yheight is less than 0!\n", NAME_CURRENT_COMP); } - this_conditional_data.PSD_half_yheight = 0.5*yheight; + this_conditional_data.PSD_half_yheight = 0.5 * yheight; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_conditional_PSD:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_conditional_PSD:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct global_positions_to_transform_list_struct *global_positions_to_transform_list = COMP_GETPAR3(Union_init, init, global_positions_to_transform_list); - struct global_rotations_to_transform_list_struct *global_rotations_to_transform_list = COMP_GETPAR3(Union_init, init, global_rotations_to_transform_list); + struct global_positions_to_transform_list_struct* global_positions_to_transform_list = COMP_GETPAR3 (Union_init, init, global_positions_to_transform_list); + struct global_rotations_to_transform_list_struct* global_rotations_to_transform_list = COMP_GETPAR3 (Union_init, init, global_rotations_to_transform_list); // Test position and rotation stored in a data storage, and pointers assigned to transform lists this_conditional_data.PSD_position = POS_A_CURRENT_COMP; - add_position_pointer_to_list(global_positions_to_transform_list, &this_conditional_data.PSD_position); - - rot_copy(this_conditional_data.PSD_rotation,ROT_A_CURRENT_COMP); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_conditional_data.PSD_rotation); - - rot_transpose(ROT_A_CURRENT_COMP,this_conditional_data.PSD_t_rotation); - add_rotation_pointer_to_list(global_rotations_to_transform_list, &this_conditional_data.PSD_t_rotation); - - + add_position_pointer_to_list (global_positions_to_transform_list, &this_conditional_data.PSD_position); + + rot_copy (this_conditional_data.PSD_rotation, ROT_A_CURRENT_COMP); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_conditional_data.PSD_rotation); + + rot_transpose (ROT_A_CURRENT_COMP, this_conditional_data.PSD_t_rotation); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_conditional_data.PSD_t_rotation); + // Set the data union to be for this specific type of conditional, and supply it with a pointer to its static data this_data_union.p_PSD = &this_conditional_data; - - struct global_tagging_conditional_list_struct *global_tagging_conditional_list = COMP_GETPAR3(Union_init, init, global_tagging_conditional_list); - + + struct global_tagging_conditional_list_struct* global_tagging_conditional_list = COMP_GETPAR3 (Union_init, init, global_tagging_conditional_list); + if (master_tagging == 1) { // Apply this conditional to the next master components tagging system // When a master is encountered, the current_index is increased, meaning it is always the next master that gets the additional conditional if (global_tagging_conditional_list->num_elements < global_tagging_conditional_list->current_index + 1) { - //printf("allocating new element for global_tagging_conditional_list \n"); - // New element needs to be allocated first - new_tagging_element = malloc(sizeof(struct global_tagging_conditional_element_struct)); + // printf("allocating new element for global_tagging_conditional_list \n"); + // New element needs to be allocated first + new_tagging_element = malloc (sizeof (struct global_tagging_conditional_element_struct)); new_tagging_element->extend_index = tagging_extend_index; new_tagging_element->conditional_list.num_elements = 0; - strcpy(new_tagging_element->name,NAME_CURRENT_COMP); - - //printf("adding new element to global_tagging_conditional_list \n"); - add_element_to_tagging_conditional_list(global_tagging_conditional_list, *new_tagging_element); - //printf("added new element to global_tagging_conditional_list \n"); - + strcpy (new_tagging_element->name, NAME_CURRENT_COMP); + + // printf("adding new element to global_tagging_conditional_list \n"); + add_element_to_tagging_conditional_list (global_tagging_conditional_list, *new_tagging_element); + // printf("added new element to global_tagging_conditional_list \n"); + } else { // Making the name reflect all the conditionals used - strcat(global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name,"-"); - strcat(global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name,NAME_CURRENT_COMP); + strcat (global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name, "-"); + strcat (global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name, NAME_CURRENT_COMP); } - // Add the conditional element to the current list - add_function_to_conditional_list(&global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].conditional_list, &conditional_function_PSD, &this_data_union); + // Add the conditional element to the current list + add_function_to_conditional_list (&global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].conditional_list, + &conditional_function_PSD, &this_data_union); } - - struct pointer_to_global_logger_list *global_specific_volumes_logger_list = COMP_GETPAR3(Union_init, init, global_specific_volumes_logger_list); - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - struct pointer_to_global_abs_logger_list *global_specific_volumes_abs_logger_list = COMP_GETPAR3(Union_init, init, global_specific_volumes_abs_logger_list); - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - + + struct pointer_to_global_logger_list* global_specific_volumes_logger_list = COMP_GETPAR3 (Union_init, init, global_specific_volumes_logger_list); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + struct pointer_to_global_abs_logger_list* global_specific_volumes_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_specific_volumes_abs_logger_list); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + // Need to find the loggers which need to have this conditional applied - if (target_loggers && strlen(target_loggers) && strcmp(target_loggers,"NULL") && strcmp(target_loggers, "0")) { + if (target_loggers && strlen (target_loggers) && strcmp (target_loggers, "NULL") && strcmp (target_loggers, "0")) { // Certain loggers were selected, find the indicies in the global_specific_volumes_logger_list / global_all_volume_list // Create accepted_loggers_specific / accepted_loggers_all - - //printf("Reached target logger section \n"); - - return_value = manual_linking_logger_function_conditional(target_loggers, global_all_volume_logger_list, &accepted_loggers_all); - return_value += manual_linking_logger_function_conditional(target_loggers, global_specific_volumes_logger_list, &accepted_loggers_specific); - return_value += manual_linking_abs_logger_function_conditional(target_loggers, global_all_volume_abs_logger_list, &accepted_abs_loggers_all); - return_value += manual_linking_abs_logger_function_conditional(target_loggers, global_specific_volumes_abs_logger_list, &accepted_abs_loggers_specific); - - //return_value += manual_linking_tagging_function_conditional(target_loggers, &global_tagging_conditional_list, &accepted_tagging); - + + // printf("Reached target logger section \n"); + + return_value = manual_linking_logger_function_conditional (target_loggers, global_all_volume_logger_list, &accepted_loggers_all); + return_value += manual_linking_logger_function_conditional (target_loggers, global_specific_volumes_logger_list, &accepted_loggers_specific); + return_value += manual_linking_abs_logger_function_conditional (target_loggers, global_all_volume_abs_logger_list, &accepted_abs_loggers_all); + return_value += manual_linking_abs_logger_function_conditional (target_loggers, global_specific_volumes_abs_logger_list, &accepted_abs_loggers_specific); + + // return_value += manual_linking_tagging_function_conditional(target_loggers, &global_tagging_conditional_list, &accepted_tagging); + // Need to find a list over tokens that were not taken by either all_volume or specific_volumes - - if (return_value < count_commas(target_loggers) + 1) { + + if (return_value < count_commas (target_loggers) + 1) { // Fewer links than tokens were made - printf("Union conditional component named \"%s\" did not find all loggers in it's target_logger string \"%s\". \n",NAME_CURRENT_COMP,target_loggers); - printf(" A conditional component needs to be linked to a logger in order to function. \n"); - printf(" The Union logger component must be defined before the conditional that tries to link to it. \n"); - printf(" A comma separated list of Union logger component names can be given if the conditional should affect many loggers. \n"); - - exit(1); + printf ("Union conditional component named \"%s\" did not find all loggers in it's target_logger string \"%s\". \n", NAME_CURRENT_COMP, target_loggers); + printf (" A conditional component needs to be linked to a logger in order to function. \n"); + printf (" The Union logger component must be defined before the conditional that tries to link to it. \n"); + printf (" A comma separated list of Union logger component names can be given if the conditional should affect many loggers. \n"); + + exit (1); } - + // This function pointer is used to switch the logger function pointers for active and inactive logger functions. // Need to have the same input (defined in logger_pointer_set_struct in union-lib.c) - void (*temp_function_pointer)(Coords*, double*, double*, double, double, double, int, int, int, struct logger_struct*, struct logger_with_data_struct*); - void (*temp_abs_function_pointer)(Coords*, double*, double, double, int, int, struct abs_logger_struct*, struct abs_logger_with_data_struct*); - for (loop_index=0;loop_indexelements[accepted_loggers_all.elements[loop_index]].logger; - + if (found_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_function_pointer = found_logger->function_pointers.active_record_function; found_logger->function_pointers.active_record_function = found_logger->function_pointers.inactive_record_function; found_logger->function_pointers.inactive_record_function = temp_function_pointer; } - + if (overwrite_logger_weight == 1) found_logger->function_pointers.select_t_to_p = 2; - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_logger->conditional_list,&conditional_function_PSD,&this_data_union); + add_function_to_conditional_list (&found_logger->conditional_list, &conditional_function_PSD, &this_data_union); } - for (loop_index=0;loop_indexelements[accepted_loggers_specific.elements[loop_index]].logger; - + if (found_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_function_pointer = found_logger->function_pointers.active_record_function; found_logger->function_pointers.active_record_function = found_logger->function_pointers.inactive_record_function; found_logger->function_pointers.inactive_record_function = temp_function_pointer; } - + if (overwrite_logger_weight == 1) found_logger->function_pointers.select_t_to_p = 2; - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_logger->conditional_list,&conditional_function_PSD,&this_data_union); + add_function_to_conditional_list (&found_logger->conditional_list, &conditional_function_PSD, &this_data_union); } - for (loop_index=0;loop_indexelements[accepted_abs_loggers_all.elements[loop_index]].abs_logger; - + if (found_abs_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_abs_function_pointer = found_abs_logger->function_pointers.active_record_function; found_abs_logger->function_pointers.active_record_function = found_abs_logger->function_pointers.inactive_record_function; found_abs_logger->function_pointers.inactive_record_function = temp_abs_function_pointer; } - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_abs_logger->conditional_list, &conditional_function_PSD, &this_data_union); + add_function_to_conditional_list (&found_abs_logger->conditional_list, &conditional_function_PSD, &this_data_union); } - for (loop_index=0;loop_indexelements[accepted_abs_loggers_specific.elements[loop_index]].abs_logger; - + if (found_abs_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_abs_function_pointer = found_abs_logger->function_pointers.active_record_function; found_abs_logger->function_pointers.active_record_function = found_abs_logger->function_pointers.inactive_record_function; found_abs_logger->function_pointers.inactive_record_function = temp_abs_function_pointer; } - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_logger->conditional_list,&conditional_function_PSD,&this_data_union); + add_function_to_conditional_list (&found_logger->conditional_list, &conditional_function_PSD, &this_data_union); } - + } else { // What to do if no target_logger string given? Apply to all loggers? Apply to overall tagging system? Apply to former logger? // Give error. if (master_tagging == 0) { - printf("ERROR: Union conditional component named \"%s\" need the target_logger string, or to be applied to the next master using master_tagging=1. \n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR: Union conditional component named \"%s\" need the target_logger string, or to be applied to the next master using master_tagging=1. \n", + NAME_CURRENT_COMP); + exit (1); } } - - //printf("completed conditional initialize \n"); + + // printf("completed conditional initialize \n"); %} TRACE @@ -441,11 +451,12 @@ SAVE FINALLY %{ -// Remember to clean up allocated lists -if (accepted_loggers_specific.num_elements > 0) free(accepted_loggers_specific.elements); -if (accepted_loggers_all.num_elements > 0) free(accepted_loggers_all.elements); -//if (accepted_tagging.num_elements > 0) free(accepted_tagging.elements); - + // Remember to clean up allocated lists + if (accepted_loggers_specific.num_elements > 0) + free (accepted_loggers_specific.elements); + if (accepted_loggers_all.num_elements > 0) + free (accepted_loggers_all.elements); + // if (accepted_tagging.num_elements > 0) free(accepted_tagging.elements); %} END diff --git a/mcstas-comps/union/Union_conditional_standard.comp b/mcstas-comps/union/Union_conditional_standard.comp index c42bf22aa3..109cbb81e0 100644 --- a/mcstas-comps/union/Union_conditional_standard.comp +++ b/mcstas-comps/union/Union_conditional_standard.comp @@ -77,182 +77,182 @@ SETTING PARAMETERS(string target_loggers="NULL", int master_tagging=0, int taggi SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_conditional_standard component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Union_conditional_standard component" + #endif -int conditional_function_standard(union conditional_data_union *data_union, Coords *position, Coords *velocity, double *weight, double *time, int *current_volume, int *total_number_of_scattering, int *number_of_scattering_per_volume, int **number_of_scattering_per_volume_process) { + int + conditional_function_standard (union conditional_data_union* data_union, Coords* position, Coords* velocity, double* weight, double* time, int* current_volume, + int* total_number_of_scattering, int* number_of_scattering_per_volume, int** number_of_scattering_per_volume_process) { - //printf(" Inside conditional function \n"); - if (data_union->p_standard->T_limit == 1) { - if (*time < data_union->p_standard->Tmin || *time > data_union->p_standard->Tmax) - return 0; - } - - if (data_union->p_standard->E_limit == 1) { - // VS2E = 5.22704E-6 m_n / 2e - double E = 5.22704E-6*(velocity->x*velocity->x + velocity->y*velocity->y + velocity->z*velocity->z); - if (E < data_union->p_standard->Emin || E > data_union->p_standard->Emax) - return 0; - } - - if (data_union->p_standard->Total_scat_limit == 1) { - if (*total_number_of_scattering < data_union->p_standard->Total_scat_min || *total_number_of_scattering > data_union->p_standard->Total_scat_max) - return 0; - } - - if (data_union->p_standard->volume_index != -1) { - if (*current_volume != data_union->p_standard->volume_index) - return 0; + // printf(" Inside conditional function \n"); + if (data_union->p_standard->T_limit == 1) { + if (*time < data_union->p_standard->Tmin || *time > data_union->p_standard->Tmax) + return 0; + } + + if (data_union->p_standard->E_limit == 1) { + // VS2E = 5.22704E-6 m_n / 2e + double E = 5.22704E-6 * (velocity->x * velocity->x + velocity->y * velocity->y + velocity->z * velocity->z); + if (E < data_union->p_standard->Emin || E > data_union->p_standard->Emax) + return 0; + } + + if (data_union->p_standard->Total_scat_limit == 1) { + if (*total_number_of_scattering < data_union->p_standard->Total_scat_min || *total_number_of_scattering > data_union->p_standard->Total_scat_max) + return 0; + } + + if (data_union->p_standard->volume_index != -1) { + if (*current_volume != data_union->p_standard->volume_index) + return 0; + } + + // All conditions fulfilled + return 1; } - - // All conditions fulfilled - return 1; - -} - -// Only need to define linking function for conditionals once. -// Does not need to redefine functions from: make_material / loggers, as one of each needs to be defined before. -#ifndef UNION_CONDITIONAL -#define UNION_CONDITIONAL Dummy -// Linking function for loggers, finds the indicies of the specified loggers on global_logger_lists -int manual_linking_logger_function_conditional(char *input_string, struct pointer_to_global_logger_list *global_logger_list, struct pointer_to_1d_int_list *accepted_loggers) { + + // Only need to define linking function for conditionals once. + // Does not need to redefine functions from: make_material / loggers, as one of each needs to be defined before. + #ifndef UNION_CONDITIONAL + #define UNION_CONDITIONAL Dummy + // Linking function for loggers, finds the indicies of the specified loggers on global_logger_lists + int + manual_linking_logger_function_conditional (char* input_string, struct pointer_to_global_logger_list* global_logger_list, + struct pointer_to_1d_int_list* accepted_loggers) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_logger_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_loggers,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_logger_list->num_elements; loop_index++) { + if (strcmp (token, global_logger_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_loggers, loop_index); break; } } - + // Updates the token - token = strtok(NULL,","); - } - - return accepted_loggers->num_elements; -} + token = strtok (NULL, ","); + } + + return accepted_loggers->num_elements; + } -int manual_linking_abs_logger_function_conditional(char *input_string, struct pointer_to_global_abs_logger_list *global_abs_logger_list, struct pointer_to_1d_int_list *accepted_abs_loggers) { + int + manual_linking_abs_logger_function_conditional (char* input_string, struct pointer_to_global_abs_logger_list* global_abs_logger_list, + struct pointer_to_1d_int_list* accepted_abs_loggers) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_abs_logger_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_abs_loggers,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_abs_logger_list->num_elements; loop_index++) { + if (strcmp (token, global_abs_logger_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_abs_loggers, loop_index); break; } } - + // Updates the token - token = strtok(NULL,","); - } - - return accepted_abs_loggers->num_elements; -} - -/* -// Linking function for masters, finds the indicies of the specified masters on the global_master_list -int manual_linking_tagging_function_conditional(char *input_string, struct global_tagging_conditional_list_struct *global_tagging_list, struct pointer_to_1d_int_list *accepted_tagging) { - // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index,found; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - found = 0; - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_tagging_list->elements[loop_index].name) == 0) { + token = strtok (NULL, ","); + } + + return accepted_abs_loggers->num_elements; + } + + /* + // Linking function for masters, finds the indicies of the specified masters on the global_master_list + int manual_linking_tagging_function_conditional(char *input_string, struct global_tagging_conditional_list_struct *global_tagging_list, struct + pointer_to_1d_int_list *accepted_tagging) { + // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. + char *token; + int loop_index,found; + char local_string[512]; + + strcpy(local_string,input_string); + // get the first token + token = strtok(local_string,","); + + // walk through other tokens + while( token != NULL ) + { + found = 0; + for (loop_index=0;loop_indexnum_elements;loop_index++) { + if (strcmp(token,global_tagging_list->elements[loop_index].name) == 0) { + add_element_to_int_list(accepted_tagging,loop_index); + found = 1; + break; + } + } + + if (found == 0) { add_element_to_int_list(accepted_tagging,loop_index); - found = 1; - break; + add_element_to_tagging_conditional_list( + + add_function_to_conditional_list(global_tagging_list.elements[accepted_tagging.elements[loop_index]].conditional_list,&conditional_function_standard,&this_data_union); } - } - - if (found == 0) { - add_element_to_int_list(accepted_tagging,loop_index); - add_element_to_tagging_conditional_list( - - add_function_to_conditional_list(global_tagging_list.elements[accepted_tagging.elements[loop_index]].conditional_list,&conditional_function_standard,&this_data_union); - } - - // Updates the token - token = strtok(NULL,","); - } - - return accepted_tagging->num_elements; -} -*/ - -int count_commas(char *string) { - int return_value = 0; - - int index; - for (index=0;indexnum_elements; + } + */ + int + count_commas (char* string) { + int return_value = 0; + int index; + for (index = 0; index < strlen (string); index++) { + // printf("%c \n",string[index]); + if (string[index] == ',') + return_value++; + } + // printf("number_of_commas = %d \n",return_value); + return return_value; + } + #endif %} DECLARE %{ -int loop_index; + int loop_index; -// This function pointer is used to switch the logger function pointers for active and inactive logger functions. -// Need to have the same input (defined in logger_pointer_set_struct in union-lib.c) -//void (*temp_function_pointer)(Coords*, double*, double*, double, double, double, int, int, int, struct logger_struct*, struct logger_with_data_struct*); -int return_value; -struct pointer_to_1d_int_list accepted_loggers_all; -struct pointer_to_1d_int_list accepted_loggers_specific; -struct pointer_to_1d_int_list accepted_abs_loggers_all; -struct pointer_to_1d_int_list accepted_abs_loggers_specific; -//struct pointer_to_1d_int_list accepted_tagging = {0,NULL}; + // This function pointer is used to switch the logger function pointers for active and inactive logger functions. + // Need to have the same input (defined in logger_pointer_set_struct in union-lib.c) + // void (*temp_function_pointer)(Coords*, double*, double*, double, double, double, int, int, int, struct logger_struct*, struct logger_with_data_struct*); + int return_value; + struct pointer_to_1d_int_list accepted_loggers_all; + struct pointer_to_1d_int_list accepted_loggers_specific; + struct pointer_to_1d_int_list accepted_abs_loggers_all; + struct pointer_to_1d_int_list accepted_abs_loggers_specific; + // struct pointer_to_1d_int_list accepted_tagging = {0,NULL}; -struct logger_struct *found_logger; -struct abs_logger_struct *found_abs_logger; + struct logger_struct* found_logger; + struct abs_logger_struct* found_abs_logger; -struct conditional_standard_struct this_conditional_data; -union conditional_data_union this_data_union; - -struct global_tagging_conditional_element_struct *new_tagging_element; + struct conditional_standard_struct this_conditional_data; + union conditional_data_union this_data_union; + struct global_tagging_conditional_element_struct* new_tagging_element; %} INITIALIZE @@ -266,216 +266,218 @@ INITIALIZE accepted_abs_loggers_specific.elements = NULL; accepted_abs_loggers_specific.num_elements = 0; - //printf("starded conditional initialize \n"); - // Check if an E range has been set + // printf("starded conditional initialize \n"); + // Check if an E range has been set if (E_min == E_max) // If not, do not check the final energy this_conditional_data.E_limit = 0; else // If it has, check the final energy this_conditional_data.E_limit = 1; - + // Likewise for time if (time_min == time_max) this_conditional_data.T_limit = 0; else this_conditional_data.T_limit = 1; - + this_conditional_data.Tmin = time_min; this_conditional_data.Tmax = time_max; - + if (last_volume_index != -1) this_conditional_data.volume_index = last_volume_index; - + // Initialize storage from input if (E_min < 0) { - printf("ERROR, Union logger \"%s\" had E_min < 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had E_min < 0.\n", NAME_CURRENT_COMP); + exit (1); } this_conditional_data.Emin = E_min; // The names need to be different to avoid defines ruining the day - + // Initialize storage from input if (E_max < 0) { - printf("ERROR, Union logger \"%s\" had E_max < 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had E_max < 0.\n", NAME_CURRENT_COMP); + exit (1); } this_conditional_data.Emax = E_max; // The names need to be different to avoid defines ruining the day - - + if (total_order_max != 0) this_conditional_data.Total_scat_limit = 1; else this_conditional_data.Total_scat_limit = 0; - + if (total_order_max < total_order_min) { - printf("ERROR, Union logger \"%s\" had total_order_max < total_oder_min.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had total_order_max < total_oder_min.\n", NAME_CURRENT_COMP); + exit (1); } this_conditional_data.Total_scat_max = total_order_max; this_conditional_data.Total_scat_min = total_order_min; -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_conditional_standard:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_conditional_standard:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } -struct global_positions_to_transform_list_struct *global_positions_to_transform_list = COMP_GETPAR3(Union_init, init, global_positions_to_transform_list); - struct global_rotations_to_transform_list_struct *global_rotations_to_transform_list = COMP_GETPAR3(Union_init, init, global_rotations_to_transform_list); + struct global_positions_to_transform_list_struct* global_positions_to_transform_list = COMP_GETPAR3 (Union_init, init, global_positions_to_transform_list); + struct global_rotations_to_transform_list_struct* global_rotations_to_transform_list = COMP_GETPAR3 (Union_init, init, global_rotations_to_transform_list); // Test position and rotation stored in a data storage, and pointers assigned to transform lists this_conditional_data.test_position = POS_A_CURRENT_COMP; - add_position_pointer_to_list(global_positions_to_transform_list,&this_conditional_data.test_position); - - rot_copy(this_conditional_data.test_rotation,ROT_A_CURRENT_COMP); - add_rotation_pointer_to_list(global_rotations_to_transform_list,&this_conditional_data.test_rotation); - - rot_transpose(ROT_A_CURRENT_COMP,this_conditional_data.test_t_rotation); - add_rotation_pointer_to_list(global_rotations_to_transform_list,&this_conditional_data.test_t_rotation); - - + add_position_pointer_to_list (global_positions_to_transform_list, &this_conditional_data.test_position); + + rot_copy (this_conditional_data.test_rotation, ROT_A_CURRENT_COMP); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_conditional_data.test_rotation); + + rot_transpose (ROT_A_CURRENT_COMP, this_conditional_data.test_t_rotation); + add_rotation_pointer_to_list (global_rotations_to_transform_list, &this_conditional_data.test_t_rotation); + // Set the data union to be for this specific type of conditional, and supply it with a pointer to its static data this_data_union.p_standard = &this_conditional_data; - - struct global_tagging_conditional_list_struct *global_tagging_conditional_list = COMP_GETPAR3(Union_init, init, global_tagging_conditional_list); - + + struct global_tagging_conditional_list_struct* global_tagging_conditional_list = COMP_GETPAR3 (Union_init, init, global_tagging_conditional_list); + if (master_tagging == 1) { // Apply this conditional to the next master components tagging system // When a master is encountered, the current_index is increased, meaning it is always the next master that gets the additional conditional if (global_tagging_conditional_list->num_elements < global_tagging_conditional_list->current_index + 1) { - //printf("allocating new element for global_tagging_conditional_list \n"); - // New element needs to be allocated first - new_tagging_element = malloc(sizeof(struct global_tagging_conditional_element_struct)); + // printf("allocating new element for global_tagging_conditional_list \n"); + // New element needs to be allocated first + new_tagging_element = malloc (sizeof (struct global_tagging_conditional_element_struct)); new_tagging_element->extend_index = tagging_extend_index; new_tagging_element->conditional_list.num_elements = 0; - strcpy(new_tagging_element->name,NAME_CURRENT_COMP); - - //printf("adding new element to global_tagging_conditional_list \n"); - add_element_to_tagging_conditional_list(global_tagging_conditional_list, *new_tagging_element); - //printf("added new element to global_tagging_conditional_list \n"); - + strcpy (new_tagging_element->name, NAME_CURRENT_COMP); + + // printf("adding new element to global_tagging_conditional_list \n"); + add_element_to_tagging_conditional_list (global_tagging_conditional_list, *new_tagging_element); + // printf("added new element to global_tagging_conditional_list \n"); + } else { // Making the name reflect all the conditionals used - strcat(global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name,"-"); - strcat(global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name,NAME_CURRENT_COMP); + strcat (global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name, "-"); + strcat (global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].name, NAME_CURRENT_COMP); } - // Add the conditional element to the current list - add_function_to_conditional_list(&global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].conditional_list,&conditional_function_standard,&this_data_union); + // Add the conditional element to the current list + add_function_to_conditional_list (&global_tagging_conditional_list->elements[global_tagging_conditional_list->current_index].conditional_list, + &conditional_function_standard, &this_data_union); } - - struct pointer_to_global_logger_list *global_specific_volumes_logger_list = COMP_GETPAR3(Union_init, init, global_specific_volumes_logger_list); - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - struct pointer_to_global_abs_logger_list *global_specific_volumes_abs_logger_list = COMP_GETPAR3(Union_init, init, global_specific_volumes_abs_logger_list); - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - + + struct pointer_to_global_logger_list* global_specific_volumes_logger_list = COMP_GETPAR3 (Union_init, init, global_specific_volumes_logger_list); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + struct pointer_to_global_abs_logger_list* global_specific_volumes_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_specific_volumes_abs_logger_list); + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + // Need to find the loggers which need to have this conditional applied - if (target_loggers && strlen(target_loggers) && strcmp(target_loggers,"NULL") && strcmp(target_loggers, "0")) { + if (target_loggers && strlen (target_loggers) && strcmp (target_loggers, "NULL") && strcmp (target_loggers, "0")) { // Certain loggers were selected, find the indicies in the global_specific_volumes_logger_list / global_all_volume_list // Create accepted_loggers_specific / accepted_loggers_all - - return_value = manual_linking_logger_function_conditional(target_loggers, global_all_volume_logger_list, &accepted_loggers_all); - return_value += manual_linking_logger_function_conditional(target_loggers, global_specific_volumes_logger_list, &accepted_loggers_specific); - return_value += manual_linking_abs_logger_function_conditional(target_loggers, global_all_volume_abs_logger_list, &accepted_abs_loggers_all); - return_value += manual_linking_abs_logger_function_conditional(target_loggers, global_specific_volumes_abs_logger_list, &accepted_abs_loggers_specific); - - //return_value += manual_linking_tagging_function_conditional(target_loggers, &global_tagging_conditional_list, &accepted_tagging); - + + return_value = manual_linking_logger_function_conditional (target_loggers, global_all_volume_logger_list, &accepted_loggers_all); + return_value += manual_linking_logger_function_conditional (target_loggers, global_specific_volumes_logger_list, &accepted_loggers_specific); + return_value += manual_linking_abs_logger_function_conditional (target_loggers, global_all_volume_abs_logger_list, &accepted_abs_loggers_all); + return_value += manual_linking_abs_logger_function_conditional (target_loggers, global_specific_volumes_abs_logger_list, &accepted_abs_loggers_specific); + + // return_value += manual_linking_tagging_function_conditional(target_loggers, &global_tagging_conditional_list, &accepted_tagging); + // Need to find a list over tokens that were not taken by either all_volume or specific_volumes - - if (return_value < count_commas(target_loggers) + 1) { + + if (return_value < count_commas (target_loggers) + 1) { // Fewer links than tokens were made - printf("Union conditional component named \"%s\" did not find all loggers in it's target_logger string \"%s\". \n",NAME_CURRENT_COMP,target_loggers); - printf(" A conditional component needs to be linked to a logger in order to function. \n"); - printf(" The Union logger component must be defined before the conditional that tries to link to it. \n"); - printf(" A comma separated list of Union logger component names can be given if the conditional should affect many loggers. \n"); - - exit(1); + printf ("Union conditional component named \"%s\" did not find all loggers in it's target_logger string \"%s\". \n", NAME_CURRENT_COMP, target_loggers); + printf (" A conditional component needs to be linked to a logger in order to function. \n"); + printf (" The Union logger component must be defined before the conditional that tries to link to it. \n"); + printf (" A comma separated list of Union logger component names can be given if the conditional should affect many loggers. \n"); + + exit (1); } - - void (*temp_function_pointer)(Coords*, double*, double*, double, double, double, int, int, int, struct logger_struct*, struct logger_with_data_struct*); - void (*temp_abs_function_pointer)(Coords*, double*, double, double, int, int, struct abs_logger_struct*, struct abs_logger_with_data_struct*); - for (loop_index=0;loop_indexelements[accepted_loggers_all.elements[loop_index]].logger; - + if (found_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_function_pointer = found_logger->function_pointers.active_record_function; found_logger->function_pointers.active_record_function = found_logger->function_pointers.inactive_record_function; found_logger->function_pointers.inactive_record_function = temp_function_pointer; } - + if (overwrite_logger_weight == 1) found_logger->function_pointers.select_t_to_p = 2; - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_logger->conditional_list,&conditional_function_standard,&this_data_union); + add_function_to_conditional_list (&found_logger->conditional_list, &conditional_function_standard, &this_data_union); } - for (loop_index=0;loop_indexelements[accepted_loggers_specific.elements[loop_index]].logger; - + if (found_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_function_pointer = found_logger->function_pointers.active_record_function; found_logger->function_pointers.active_record_function = found_logger->function_pointers.inactive_record_function; found_logger->function_pointers.inactive_record_function = temp_function_pointer; } - + if (overwrite_logger_weight == 1) found_logger->function_pointers.select_t_to_p = 2; - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_logger->conditional_list,&conditional_function_standard,&this_data_union); + add_function_to_conditional_list (&found_logger->conditional_list, &conditional_function_standard, &this_data_union); } - for (loop_index=0;loop_indexelements[accepted_abs_loggers_all.elements[loop_index]].abs_logger; - + if (found_abs_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_abs_function_pointer = found_abs_logger->function_pointers.active_record_function; found_abs_logger->function_pointers.active_record_function = found_abs_logger->function_pointers.inactive_record_function; found_abs_logger->function_pointers.inactive_record_function = temp_abs_function_pointer; } - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_abs_logger->conditional_list, &conditional_function_standard, &this_data_union); + add_function_to_conditional_list (&found_abs_logger->conditional_list, &conditional_function_standard, &this_data_union); } - for (loop_index=0;loop_indexelements[accepted_abs_loggers_specific.elements[loop_index]].abs_logger; - + if (found_abs_logger->conditional_list.num_elements == 0) { // Switching function pointers, only necessary for the first application of a conditional - // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the permanent storage. + // This makes the logger record to a temporary storage that is transfered to the permanent in case the conditional is true istead of directly to the + // permanent storage. temp_abs_function_pointer = found_abs_logger->function_pointers.active_record_function; found_abs_logger->function_pointers.active_record_function = found_abs_logger->function_pointers.inactive_record_function; found_abs_logger->function_pointers.inactive_record_function = temp_abs_function_pointer; } - + // Add a pointer to this conditional function to the list of conditionals for this logger - add_function_to_conditional_list(&found_logger->conditional_list,&conditional_function_standard,&this_data_union); + add_function_to_conditional_list (&found_logger->conditional_list, &conditional_function_standard, &this_data_union); } /* for (loop_index=0;loop_indexelements[accepted_tagging.elements[loop_index]].conditional_list,&conditional_function_standard,&this_data_union); } */ - + } else { // What to do if no target_logger string given? Apply to all loggers? Apply to overall tagging system? Apply to former logger? // Give error. if (master_tagging == 0) { - printf("ERROR: Union conditional component named \"%s\" need the target_logger string, or to be applied to the next master using master_tagging=1. \n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR: Union conditional component named \"%s\" need the target_logger string, or to be applied to the next master using master_tagging=1. \n", + NAME_CURRENT_COMP); + exit (1); } } - - //printf("completed conditional initialize \n"); + + // printf("completed conditional initialize \n"); %} TRACE @@ -507,13 +510,16 @@ SAVE FINALLY %{ -// Remember to clean up allocated lists -if (accepted_loggers_specific.num_elements > 0) free(accepted_loggers_specific.elements); -if (accepted_loggers_all.num_elements > 0) free(accepted_loggers_all.elements); -if (accepted_abs_loggers_specific.num_elements > 0) free(accepted_abs_loggers_specific.elements); -if (accepted_abs_loggers_all.num_elements > 0) free(accepted_abs_loggers_all.elements); -//if (accepted_tagging.num_elements > 0) free(accepted_tagging.elements); - + // Remember to clean up allocated lists + if (accepted_loggers_specific.num_elements > 0) + free (accepted_loggers_specific.elements); + if (accepted_loggers_all.num_elements > 0) + free (accepted_loggers_all.elements); + if (accepted_abs_loggers_specific.num_elements > 0) + free (accepted_abs_loggers_specific.elements); + if (accepted_abs_loggers_all.num_elements > 0) + free (accepted_abs_loggers_all.elements); + // if (accepted_tagging.num_elements > 0) free(accepted_tagging.elements); %} END diff --git a/mcstas-comps/union/Union_cone.comp b/mcstas-comps/union/Union_cone.comp index df9a573099..557a9b6b3b 100644 --- a/mcstas-comps/union/Union_cone.comp +++ b/mcstas-comps/union/Union_cone.comp @@ -82,378 +82,374 @@ SETTING PARAMETERS(string material_string=0, priority, radius=0,radius_top=0,rad SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_cone component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Union_cone component" + #endif -void mcdisplay_cone_function(struct lines_to_draw *lines_to_draw_output,int index, struct geometry_struct **Geometries,int number_of_volumes) { + void + mcdisplay_cone_function (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { // Function to call in mcdisplay section of the sample component for this volume // One can assume that Geometries[index] refers to a geometry as described in this file // The 4 lines describin the cylinders side are aligned to the local frame of the cylinder, // it would be nicer to have them alligned with the global frame so that they show up nicely in // pgplotters on mcdisplay. // One could get the current global rotation and use this to counteract this effect. - + double height = Geometries[index]->geometry_parameters.p_cone_storage->height; double radius_top = Geometries[index]->geometry_parameters.p_cone_storage->cone_radius_top; double radius_bottom = Geometries[index]->geometry_parameters.p_cone_storage->cone_radius_bottom; - //int is_cylinder = Geometries[index]->geometry_parameters.p_cone_storage->is_cylinder; - //Coords cone_tip = Geometries[index]->geometry_parameters.p_cone_storage->cone_tip; + // int is_cylinder = Geometries[index]->geometry_parameters.p_cone_storage->is_cylinder; + // Coords cone_tip = Geometries[index]->geometry_parameters.p_cone_storage->cone_tip; Coords direction = Geometries[index]->geometry_parameters.p_cone_storage->direction_vector; Coords center = Geometries[index]->center; - - Coords bottom_point = coords_add(center,coords_scalar_mult(direction,-0.5*height)); - Coords top_point = coords_add(center,coords_scalar_mult(direction,0.5*height)); + Coords bottom_point = coords_add (center, coords_scalar_mult (direction, -0.5 * height)); + Coords top_point = coords_add (center, coords_scalar_mult (direction, 0.5 * height)); struct lines_to_draw lines_to_draw_temp; lines_to_draw_temp.number_of_lines = 0; - - lines_to_draw_temp = draw_circle_with_highest_priority(top_point,direction,radius_top,index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - - lines_to_draw_temp = draw_circle_with_highest_priority(bottom_point,direction,radius_bottom,index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - - Coords point1,point2; - int iterate,number_of_points=4; - - for (iterate=0;iteraterotation_matrix,simple_vector); - NORM(cone_vector.x,cone_vector.y,cone_vector.z); + cone_vector = rot_apply (cone->rotation_matrix, simple_vector); + NORM (cone_vector.x, cone_vector.y, cone_vector.z); cone->geometry_parameters.p_cone_storage->direction_vector.x = cone_vector.x; cone->geometry_parameters.p_cone_storage->direction_vector.y = cone_vector.y; cone->geometry_parameters.p_cone_storage->direction_vector.z = cone_vector.z; // if (verbal == 1) printf("Cords vector1 = (%f,%f,%f)\n",cone_vector.x,cone_vector.y, -} - -struct pointer_to_1d_coords_list shell_points(struct geometry_struct *geometry,int max_number_of_points) { - // Function that returns a number (less than max) of points on the geometry surface - // If used, remember to free the space allocated. - int points_per_circle = floor(max_number_of_points/2); - - struct pointer_to_1d_coords_list cone_shell_array; - cone_shell_array.elements = malloc(2*points_per_circle*sizeof(Coords)); - cone_shell_array.num_elements = 2*points_per_circle; - - - Coords cone_direction = geometry->geometry_parameters.p_cone_storage->direction_vector; - Coords center = geometry->center; - double radius_top = geometry->geometry_parameters.p_cone_storage->cone_radius_top; - double radius_bottom = geometry->geometry_parameters.p_cone_storage->cone_radius_bottom; - double height = geometry->geometry_parameters.p_cone_storage->height; - int number_of_points_in_array = 0; - //int is_cylinder = geometry->geometry_parameters.p_cone_storage->is_cylinder; - //Coords cone_tip = geometry->geometry_parameters.p_cone_storage->cone_tip; - - Coords cone_top_point = coords_add(center,coords_scalar_mult(cone_direction,0.5*height)); - Coords cone_bottom_point = coords_add(center,coords_scalar_mult(cone_direction,-0.5*height)); - - if (radius_top != 0){ - points_on_circle(cone_shell_array.elements,cone_top_point,cone_direction,radius_top,points_per_circle); - //printf("\nAdded point on top cone as index %i - %i\n",number_of_points_in_array,number_of_points_in_array + points_per_circle); - number_of_points_in_array += points_per_circle; -} else { - // If this radius is 0 then add a single point instead of a circle - cone_shell_array.elements[0] = cone_top_point; - //printf("\nAdded point on top cone as index %i\n",0); - number_of_points_in_array += 1; -} - // Need to verify this pointer arithimatic works as intended - //points_on_circle(cone_shell_array.elements+points_per_circle,cone_bottom_point,cone_direction,radius_bottom,points_per_circle); - - if (radius_bottom != 0){ - points_on_circle(cone_shell_array.elements + number_of_points_in_array,cone_bottom_point,cone_direction,radius_bottom,points_per_circle); - //printf("\nAdded point on bottom cone as index %i - %i\n",number_of_points_in_array,number_of_points_in_array + points_per_circle); - number_of_points_in_array += points_per_circle; - } else { - // If this radius is 0 then add a single point instead of a circle - cone_shell_array.elements[number_of_points_in_array] = cone_bottom_point; - //printf("\nAdded point on bottom cone as index %i\n",number_of_points_in_array); - number_of_points_in_array += 1; } - cone_shell_array.num_elements = number_of_points_in_array; - return cone_shell_array; -} - -#ifndef ANY_GEOMETRY_DETECTOR_DECLARE - #define ANY_GEOMETRY_DETECTOR_DECLARE dummy - //struct pointer_to_global_geometry_list global_geometry_list = {0,NULL}; -#endif + + struct pointer_to_1d_coords_list + shell_points (struct geometry_struct* geometry, int max_number_of_points) { + // Function that returns a number (less than max) of points on the geometry surface + // If used, remember to free the space allocated. + int points_per_circle = floor (max_number_of_points / 2); + + struct pointer_to_1d_coords_list cone_shell_array; + cone_shell_array.elements = malloc (2 * points_per_circle * sizeof (Coords)); + cone_shell_array.num_elements = 2 * points_per_circle; + + Coords cone_direction = geometry->geometry_parameters.p_cone_storage->direction_vector; + Coords center = geometry->center; + double radius_top = geometry->geometry_parameters.p_cone_storage->cone_radius_top; + double radius_bottom = geometry->geometry_parameters.p_cone_storage->cone_radius_bottom; + double height = geometry->geometry_parameters.p_cone_storage->height; + int number_of_points_in_array = 0; + // int is_cylinder = geometry->geometry_parameters.p_cone_storage->is_cylinder; + // Coords cone_tip = geometry->geometry_parameters.p_cone_storage->cone_tip; + + Coords cone_top_point = coords_add (center, coords_scalar_mult (cone_direction, 0.5 * height)); + Coords cone_bottom_point = coords_add (center, coords_scalar_mult (cone_direction, -0.5 * height)); + + if (radius_top != 0) { + points_on_circle (cone_shell_array.elements, cone_top_point, cone_direction, radius_top, points_per_circle); + // printf("\nAdded point on top cone as index %i - %i\n",number_of_points_in_array,number_of_points_in_array + points_per_circle); + number_of_points_in_array += points_per_circle; + } else { + // If this radius is 0 then add a single point instead of a circle + cone_shell_array.elements[0] = cone_top_point; + // printf("\nAdded point on top cone as index %i\n",0); + number_of_points_in_array += 1; + } + // Need to verify this pointer arithimatic works as intended + // points_on_circle(cone_shell_array.elements+points_per_circle,cone_bottom_point,cone_direction,radius_bottom,points_per_circle); + + if (radius_bottom != 0) { + points_on_circle (cone_shell_array.elements + number_of_points_in_array, cone_bottom_point, cone_direction, radius_bottom, points_per_circle); + // printf("\nAdded point on bottom cone as index %i - %i\n",number_of_points_in_array,number_of_points_in_array + points_per_circle); + number_of_points_in_array += points_per_circle; + } else { + // If this radius is 0 then add a single point instead of a circle + cone_shell_array.elements[number_of_points_in_array] = cone_bottom_point; + // printf("\nAdded point on bottom cone as index %i\n",number_of_points_in_array); + number_of_points_in_array += 1; + } + cone_shell_array.num_elements = number_of_points_in_array; + return cone_shell_array; + } + + #ifndef ANY_GEOMETRY_DETECTOR_DECLARE + #define ANY_GEOMETRY_DETECTOR_DECLARE dummy + // struct pointer_to_global_geometry_list global_geometry_list = {0,NULL}; + #endif %} DECLARE %{ -// Needed for transport to the main component -struct global_geometry_element_struct global_geometry_element; + // Needed for transport to the main component + struct global_geometry_element_struct global_geometry_element; -int loop_index; -int loop_2_index; -int material_index; + int loop_index; + int loop_2_index; + int material_index; -struct Volume_struct this_cone_volume; -struct cone_storage this_cone_storage; + struct Volume_struct this_cone_volume; + struct cone_storage this_cone_storage; -struct surface_stack_struct curved_surface_stack; -struct surface_stack_struct top_surface_stack; -struct surface_stack_struct bottom_surface_stack; -struct surface_stack_struct cut_surface_stack; + struct surface_stack_struct curved_surface_stack; + struct surface_stack_struct top_surface_stack; + struct surface_stack_struct bottom_surface_stack; + struct surface_stack_struct cut_surface_stack; %} INITIALIZE %{ -geometry_struct_init(&(this_cone_volume.geometry)); -// Initializes the focusing system for this volume including input sanitation. -focus_initialize(&this_cone_volume.geometry, POS_A_COMP_INDEX(INDEX_CURRENT_COMP+target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, target_x, target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); - - -// Input sanitation for this geometry -/* Disabled because radius might be 0 on cone -if (radius <= 0) { - printf("\nERROR in Union_cylinder named %s, the radius is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} -*/ - -if (radius > 0){ - radius_top = radius; - radius_bottom = radius; -} - -if (yheight <= 0) { - printf("\nERROR in Union_cone named %s, yheight is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} - -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_cone:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} - -struct pointer_to_global_material_list *global_material_list = COMP_GETPAR3(Union_init, init, global_material_list); -// Use sanitation -#ifdef MATERIAL_DETECTOR -if (global_material_list->num_elements == 0) { - // Here if the user have defined a material, but only after this material - printf("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); - printf(" %s was defined before first use of Union_make_material.\n",NAME_CURRENT_COMP); - exit(1); -} -#endif -#ifndef MATERIAL_DETECTOR - printf("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); - exit(1); -#endif - - -this_cone_volume.geometry.is_masked_volume = 0; -this_cone_volume.geometry.is_exit_volume = 0; -this_cone_volume.geometry.is_mask_volume = 0; -struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); - -// Read the material input, or if it lacks, use automatic linking. -if (mask_string && strlen(mask_string) && strcmp(mask_string, "NULL") && strcmp(mask_string, "0")) { + geometry_struct_init (&(this_cone_volume.geometry)); + // Initializes the focusing system for this volume including input sanitation. + focus_initialize (&this_cone_volume.geometry, POS_A_COMP_INDEX (INDEX_CURRENT_COMP + target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, + target_x, target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); + + // Input sanitation for this geometry + /* Disabled because radius might be 0 on cone + if (radius <= 0) { + printf("\nERROR in Union_cylinder named %s, the radius is <= 0. \n",NAME_CURRENT_COMP); + exit(1); + } + */ + + if (radius > 0) { + radius_top = radius; + radius_bottom = radius; + } + + if (yheight <= 0) { + printf ("\nERROR in Union_cone named %s, yheight is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_cone:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } + + struct pointer_to_global_material_list* global_material_list = COMP_GETPAR3 (Union_init, init, global_material_list); + // Use sanitation + #ifdef MATERIAL_DETECTOR + if (global_material_list->num_elements == 0) { + // Here if the user have defined a material, but only after this material + printf ("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); + printf (" %s was defined before first use of Union_make_material.\n", NAME_CURRENT_COMP); + exit (1); + } + #endif + #ifndef MATERIAL_DETECTOR + printf ("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); + exit (1); + #endif + + this_cone_volume.geometry.is_masked_volume = 0; + this_cone_volume.geometry.is_exit_volume = 0; + this_cone_volume.geometry.is_mask_volume = 0; + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + + // Read the material input, or if it lacks, use automatic linking. + if (mask_string && strlen (mask_string) && strcmp (mask_string, "NULL") && strcmp (mask_string, "0")) { // A mask volume is used to limit the extend of other volumes, called the masked volumes. These are specified in the mask_string. // In order for a ray to enter a masked volume, it needs to be both in the region covered by that volume AND the mask volume. // When more than this_cone_volume.geometry.mask_mode = 1; // Default mask mode is ALL - if (mask_setting && strlen(mask_setting) && strcmp(mask_setting, "NULL") && strcmp(mask_setting, "0")) { - if (strcmp(mask_setting,"ALL") == 0 || strcmp(mask_setting,"All") == 0) this_cone_volume.geometry.mask_mode = 1; - else if (strcmp(mask_setting,"ANY") == 0 || strcmp(mask_setting,"Any") == 0) this_cone_volume.geometry.mask_mode = 2; - else { - printf("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n",NAME_CURRENT_COMP,mask_setting); - exit(1); - } + if (mask_setting && strlen (mask_setting) && strcmp (mask_setting, "NULL") && strcmp (mask_setting, "0")) { + if (strcmp (mask_setting, "ALL") == 0 || strcmp (mask_setting, "All") == 0) + this_cone_volume.geometry.mask_mode = 1; + else if (strcmp (mask_setting, "ANY") == 0 || strcmp (mask_setting, "Any") == 0) + this_cone_volume.geometry.mask_mode = 2; + else { + printf ("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n", NAME_CURRENT_COMP, mask_setting); + exit (1); + } } - + int found_geometries = 0; - for (loop_index=0;loop_indexnum_elements;loop_index++) { - // Add mask list - if (1 == manual_linking_function(global_geometry_list->elements[loop_index].name,mask_string)) { - add_element_to_int_list(&this_cone_volume.geometry.mask_list,global_geometry_list->elements[loop_index].component_index); - add_element_to_int_list(&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list,INDEX_CURRENT_COMP); - global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; - if (this_cone_volume.geometry.mask_mode == 2) - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; - if (this_cone_volume.geometry.mask_mode == 1) { - if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) - // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; - } - - found_geometries = 1; + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + // Add mask list + if (1 == manual_linking_function (global_geometry_list->elements[loop_index].name, mask_string)) { + add_element_to_int_list (&this_cone_volume.geometry.mask_list, global_geometry_list->elements[loop_index].component_index); + add_element_to_int_list (&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list, INDEX_CURRENT_COMP); + global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; + if (this_cone_volume.geometry.mask_mode == 2) + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; + if (this_cone_volume.geometry.mask_mode == 1) { + if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 + && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) + // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; } + + found_geometries = 1; + } } if (found_geometries == 0) { - printf("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n",NAME_CURRENT_COMP,mask_string); - exit(1); + printf ("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n", NAME_CURRENT_COMP, mask_string); + exit (1); } - this_cone_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_cone_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum - this_cone_volume.p_physics->number_of_processes = (int) 0; // Should not be used. - this_cone_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_cone_volume.p_physics->name,"Mask"); + this_cone_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_cone_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum + this_cone_volume.p_physics->number_of_processes = (int)0; // Should not be used. + this_cone_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_cone_volume.p_physics->name, "Mask"); this_cone_volume.geometry.is_mask_volume = 1; - - -// Read the material input, or if it lacks, use automatic linking. -} else if (material_string && strlen(material_string) && strcmp(material_string, "NULL") && strcmp(material_string, "0")) { + + // Read the material input, or if it lacks, use automatic linking. + } else if (material_string && strlen (material_string) && strcmp (material_string, "NULL") && strcmp (material_string, "0")) { // A geometry string was given, use it to determine which material - if (0 == strcmp(material_string,"vacuum") || 0 == strcmp(material_string,"Vacuum")) { - // One could have a global physics struct for vacuum instead of creating one for each - this_cone_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_cone_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_cone_volume.p_physics->number_of_processes = (int) 0; - this_cone_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_cone_volume.p_physics->name,"Vacuum"); - } else if (0 == strcmp(material_string,"exit") || 0 == strcmp(material_string,"Exit")) { - // One could have a global physics struct for exit instead of creating one for each - this_cone_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_cone_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_cone_volume.p_physics->number_of_processes = (int) 0; - this_cone_volume.p_physics->my_a = 0; // Should not be used. - this_cone_volume.geometry.is_exit_volume = 1; - sprintf(this_cone_volume.p_physics->name,"Exit"); + if (0 == strcmp (material_string, "vacuum") || 0 == strcmp (material_string, "Vacuum")) { + // One could have a global physics struct for vacuum instead of creating one for each + this_cone_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_cone_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_cone_volume.p_physics->number_of_processes = (int)0; + this_cone_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_cone_volume.p_physics->name, "Vacuum"); + } else if (0 == strcmp (material_string, "exit") || 0 == strcmp (material_string, "Exit")) { + // One could have a global physics struct for exit instead of creating one for each + this_cone_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_cone_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_cone_volume.p_physics->number_of_processes = (int)0; + this_cone_volume.p_physics->my_a = 0; // Should not be used. + this_cone_volume.geometry.is_exit_volume = 1; + sprintf (this_cone_volume.p_physics->name, "Exit"); } else { - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (0 == strcmp(material_string,global_material_list->elements[loop_index].name)) { - this_cone_volume.p_physics = global_material_list->elements[loop_index].physics; - break; - } - if (loop_index == global_material_list->num_elements-1) { - printf("\n"); - printf("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n",material_string,NAME_CURRENT_COMP); - printf(" The materials available at this point (need to be defined before the geometry): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_material_list->elements[loop_index].name); - printf("\n"); - printf(" It is also possible to use one of the defualt materials avaiable: \n"); - printf(" Vacuum (for a Volume without scattering or absorption)\n"); - printf(" Exit (for a Volume where the ray exits the component if it enters)\n"); - printf(" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); - exit(1); - } + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) { + if (0 == strcmp (material_string, global_material_list->elements[loop_index].name)) { + this_cone_volume.p_physics = global_material_list->elements[loop_index].physics; + break; + } + if (loop_index == global_material_list->num_elements - 1) { + printf ("\n"); + printf ("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n", material_string, NAME_CURRENT_COMP); + printf (" The materials available at this point (need to be defined before the geometry): \n"); + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) + printf (" %s\n", global_material_list->elements[loop_index].name); + printf ("\n"); + printf (" It is also possible to use one of the defualt materials avaiable: \n"); + printf (" Vacuum (for a Volume without scattering or absorption)\n"); + printf (" Exit (for a Volume where the ray exits the component if it enters)\n"); + printf (" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); + exit (1); } + } } -} else { + } else { // Automatic linking, simply using the last defined material. #ifndef MATERIAL_DETECTOR - printf("Need to define a material before the geometry to use automatic linking %s.\n",NAME_CURRENT_COMP); - exit(1); + printf ("Need to define a material before the geometry to use automatic linking %s.\n", NAME_CURRENT_COMP); + exit (1); #endif - this_cone_volume.p_physics = global_material_list->elements[global_material_list->num_elements-1].physics; -} - - - -// Handle surface input -if (all_face_surface && strlen(all_face_surface) && strcmp(all_face_surface, "NULL") && strcmp(all_face_surface, "0")) { - // Overwrite all other surfaces that have no input (if one wants a surface left without anything, None can be used) - overwrite_if_empty(curved_surface, all_face_surface); - overwrite_if_empty(top_surface, all_face_surface); - overwrite_if_empty(bottom_surface, all_face_surface); -} - -this_cone_volume.geometry.number_of_faces = 3; -this_cone_volume.geometry.surface_stack_for_each_face = malloc(this_cone_volume.geometry.number_of_faces*sizeof(struct surface_stack_struct*)); - -// This could be inserted into the fill_surface_stack function -this_cone_volume.geometry.surface_stack_for_each_face[0] = &curved_surface_stack; -this_cone_volume.geometry.surface_stack_for_each_face[1] = &top_surface_stack; -this_cone_volume.geometry.surface_stack_for_each_face[2] = &bottom_surface_stack; -this_cone_volume.geometry.internal_cut_surface_stack = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume - -struct pointer_to_global_surface_list *global_surface_list = COMP_GETPAR3(Union_init, init, global_surface_list); -fill_surface_stack(curved_surface, global_surface_list, NAME_CURRENT_COMP, &curved_surface_stack); -fill_surface_stack(top_surface, global_surface_list, NAME_CURRENT_COMP, &top_surface_stack); -fill_surface_stack(bottom_surface, global_surface_list, NAME_CURRENT_COMP, &bottom_surface_stack); -fill_surface_stack(cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); - - -// check if this is a cylinder and add coordinates of tip if it is a cone - -/* -Coords center = POS_A_CURRENT_COMP; -Coords cone_direction = ROT_A_CURRENT_COMP; -Coords cone_top_point = coords_add(center,coords_scalar_mult(cone_direction,0.5*yheight)); -Coords cone_bottom_point = coords_add(center,coords_scalar_mult(cone_direction,-0.5*yheight)); -*/ -//double cone_gradient = (radius_bottom-radius_top)/yheight; - -int is_cylinder = 0; -if (radius_top==radius_bottom){ + this_cone_volume.p_physics = global_material_list->elements[global_material_list->num_elements - 1].physics; + } + + // Handle surface input + if (all_face_surface && strlen (all_face_surface) && strcmp (all_face_surface, "NULL") && strcmp (all_face_surface, "0")) { + // Overwrite all other surfaces that have no input (if one wants a surface left without anything, None can be used) + overwrite_if_empty (curved_surface, all_face_surface); + overwrite_if_empty (top_surface, all_face_surface); + overwrite_if_empty (bottom_surface, all_face_surface); + } + + this_cone_volume.geometry.number_of_faces = 3; + this_cone_volume.geometry.surface_stack_for_each_face = malloc (this_cone_volume.geometry.number_of_faces * sizeof (struct surface_stack_struct*)); + + // This could be inserted into the fill_surface_stack function + this_cone_volume.geometry.surface_stack_for_each_face[0] = &curved_surface_stack; + this_cone_volume.geometry.surface_stack_for_each_face[1] = &top_surface_stack; + this_cone_volume.geometry.surface_stack_for_each_face[2] = &bottom_surface_stack; + this_cone_volume.geometry.internal_cut_surface_stack = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume + + struct pointer_to_global_surface_list* global_surface_list = COMP_GETPAR3 (Union_init, init, global_surface_list); + fill_surface_stack (curved_surface, global_surface_list, NAME_CURRENT_COMP, &curved_surface_stack); + fill_surface_stack (top_surface, global_surface_list, NAME_CURRENT_COMP, &top_surface_stack); + fill_surface_stack (bottom_surface, global_surface_list, NAME_CURRENT_COMP, &bottom_surface_stack); + fill_surface_stack (cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); + + // check if this is a cylinder and add coordinates of tip if it is a cone + + /* + Coords center = POS_A_CURRENT_COMP; + Coords cone_direction = ROT_A_CURRENT_COMP; + Coords cone_top_point = coords_add(center,coords_scalar_mult(cone_direction,0.5*yheight)); + Coords cone_bottom_point = coords_add(center,coords_scalar_mult(cone_direction,-0.5*yheight)); + */ + // double cone_gradient = (radius_bottom-radius_top)/yheight; + + int is_cylinder = 0; + if (radius_top == radius_bottom) { is_cylinder = 1; -} -/* -double cone_tip_yheight = 0; -double theta = 0; -if (is_cylinder == 0){ - cone_tip_yheight = 0.5*yheight+1/cone_gradient*radius_top; - theta = asin(cone_gradient)*(180/3.14159265359)/2; - printf("\nTheta = %2.2f \n",theta); -} -*/ - -this_cone_storage.cone_radius_top = radius_top; -this_cone_storage.cone_radius_bottom = radius_bottom; -//this_cone_storage.is_cylinder = is_cylinder; -//this_cone_storage.cone_tip_yheight = cone_tip_yheight; -this_cone_storage.height = yheight; -//this_cone_storage.theta = theta; - - -sprintf(this_cone_volume.name,"%s",NAME_CURRENT_COMP); -sprintf(this_cone_volume.geometry.shape,"cone"); -this_cone_volume.geometry.eShape = cone; -this_cone_volume.geometry.priority_value = priority; -// Currently the coordinates will be in absolute space. -this_cone_volume.geometry.center = POS_A_CURRENT_COMP; - -this_cone_volume.geometry.geometry_p_interact = p_interact; - -this_cone_volume.geometry.visualization_on = visualize; -this_cone_volume.geometry.geometry_parameters.p_cone_storage = &this_cone_storage; -this_cone_volume.geometry.within_function = &r_within_cone; -this_cone_volume.geometry.intersect_function = &sample_cone_intersect; -this_cone_volume.geometry.mcdisplay_function = &mcdisplay_cone_function; -this_cone_volume.geometry.shell_points = &shell_points; -this_cone_volume.geometry.initialize_from_main_function = &initialize_cone_geometry_from_main_component; -this_cone_volume.geometry.process_rot_allocated = 0; -this_cone_volume.geometry.copy_geometry_parameters = &allocate_cone_storage_copy; -rot_copy(this_cone_volume.geometry.rotation_matrix,ROT_A_CURRENT_COMP); -rot_transpose(ROT_A_CURRENT_COMP,this_cone_volume.geometry.transpose_rotation_matrix); - - -// Initialize loggers -this_cone_volume.loggers.num_elements = 0; -this_cone_volume.abs_loggers.num_elements = 0; - -// packing the information into the global_geometry_element, which is then included in the global_geometry_list. -sprintf(global_geometry_element.name,"%s",NAME_CURRENT_COMP); -global_geometry_element.activation_counter = number_of_activations; -global_geometry_element.component_index = INDEX_CURRENT_COMP; -global_geometry_element.Volume = &this_cone_volume; // Would be nicer if this m was a pointer, now we have the (small) data two places -add_element_to_geometry_list(global_geometry_list,global_geometry_element); + } + /* + double cone_tip_yheight = 0; + double theta = 0; + if (is_cylinder == 0){ + cone_tip_yheight = 0.5*yheight+1/cone_gradient*radius_top; + theta = asin(cone_gradient)*(180/3.14159265359)/2; + printf("\nTheta = %2.2f \n",theta); + } + */ + + this_cone_storage.cone_radius_top = radius_top; + this_cone_storage.cone_radius_bottom = radius_bottom; + // this_cone_storage.is_cylinder = is_cylinder; + // this_cone_storage.cone_tip_yheight = cone_tip_yheight; + this_cone_storage.height = yheight; + // this_cone_storage.theta = theta; + + sprintf (this_cone_volume.name, "%s", NAME_CURRENT_COMP); + sprintf (this_cone_volume.geometry.shape, "cone"); + this_cone_volume.geometry.eShape = cone; + this_cone_volume.geometry.priority_value = priority; + // Currently the coordinates will be in absolute space. + this_cone_volume.geometry.center = POS_A_CURRENT_COMP; + + this_cone_volume.geometry.geometry_p_interact = p_interact; + + this_cone_volume.geometry.visualization_on = visualize; + this_cone_volume.geometry.geometry_parameters.p_cone_storage = &this_cone_storage; + this_cone_volume.geometry.within_function = &r_within_cone; + this_cone_volume.geometry.intersect_function = &sample_cone_intersect; + this_cone_volume.geometry.mcdisplay_function = &mcdisplay_cone_function; + this_cone_volume.geometry.shell_points = &shell_points; + this_cone_volume.geometry.initialize_from_main_function = &initialize_cone_geometry_from_main_component; + this_cone_volume.geometry.process_rot_allocated = 0; + this_cone_volume.geometry.copy_geometry_parameters = &allocate_cone_storage_copy; + rot_copy (this_cone_volume.geometry.rotation_matrix, ROT_A_CURRENT_COMP); + rot_transpose (ROT_A_CURRENT_COMP, this_cone_volume.geometry.transpose_rotation_matrix); + + // Initialize loggers + this_cone_volume.loggers.num_elements = 0; + this_cone_volume.abs_loggers.num_elements = 0; + + // packing the information into the global_geometry_element, which is then included in the global_geometry_list. + sprintf (global_geometry_element.name, "%s", NAME_CURRENT_COMP); + global_geometry_element.activation_counter = number_of_activations; + global_geometry_element.component_index = INDEX_CURRENT_COMP; + global_geometry_element.Volume = &this_cone_volume; // Would be nicer if this m was a pointer, now we have the (small) data two places + add_element_to_geometry_list (global_geometry_list, global_geometry_element); %} TRACE diff --git a/mcstas-comps/union/Union_cylinder.comp b/mcstas-comps/union/Union_cylinder.comp index e0a49acedf..1c9a394e94 100755 --- a/mcstas-comps/union/Union_cylinder.comp +++ b/mcstas-comps/union/Union_cylinder.comp @@ -79,308 +79,312 @@ SETTING PARAMETERS(string material_string=0, priority, radius, yheight, visualiz SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_cylinder component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Union_cylinder component" + #endif - -void mcdisplay_cylinder_function(struct lines_to_draw *lines_to_draw_output,int index, struct geometry_struct **Geometries,int number_of_volumes) { + void + mcdisplay_cylinder_function (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { // Function to call in mcdisplay section of the sample component for this volume // One can assume that Geometries[index] refers to a geometry as described in this file // The 4 lines describin the cylinders side are aligned to the local frame of the cylinder, // it would be nicer to have them alligned with the global frame so that they show up nicely in // pgplotters on mcdisplay. // One could get the current global rotation and use this to counteract this effect. - + double height = Geometries[index]->geometry_parameters.p_cylinder_storage->height; double radius = Geometries[index]->geometry_parameters.p_cylinder_storage->cyl_radius; Coords direction = Geometries[index]->geometry_parameters.p_cylinder_storage->direction_vector; Coords center = Geometries[index]->center; - - Coords bottom_point = coords_add(center,coords_scalar_mult(direction,0.5*height)); - Coords top_point = coords_add(center,coords_scalar_mult(direction,-0.5*height)); - + + Coords bottom_point = coords_add (center, coords_scalar_mult (direction, 0.5 * height)); + Coords top_point = coords_add (center, coords_scalar_mult (direction, -0.5 * height)); + struct lines_to_draw lines_to_draw_temp; lines_to_draw_temp.number_of_lines = 0; - - lines_to_draw_temp = draw_circle_with_highest_priority(top_point,direction,radius,index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - - lines_to_draw_temp = draw_circle_with_highest_priority(bottom_point,direction,radius,index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - - Coords point1,point2; - int iterate,number_of_points=4; - - for (iterate=0;iteraterotation_matrix,simple_vector); - NORM(cyl_vector.x,cyl_vector.y,cyl_vector.z); + cyl_vector = rot_apply (cylinder->rotation_matrix, simple_vector); + NORM (cyl_vector.x, cyl_vector.y, cyl_vector.z); cylinder->geometry_parameters.p_cylinder_storage->direction_vector.x = cyl_vector.x; cylinder->geometry_parameters.p_cylinder_storage->direction_vector.y = cyl_vector.y; cylinder->geometry_parameters.p_cylinder_storage->direction_vector.z = cyl_vector.z; // if (verbal == 1) printf("Cords vector1 = (%f,%f,%f)\n",cyl_vector.x,cyl_vector.y, -} - -struct pointer_to_1d_coords_list cylinder_shell_points(struct geometry_struct *geometry,int max_number_of_points) { - // Function that returns a number (less than max) of points on the geometry surface - // If used, remember to free the space allocated. - int points_per_circle = floor(max_number_of_points/2.0); - - struct pointer_to_1d_coords_list cylinder_shell_array; - cylinder_shell_array.elements = malloc(2*points_per_circle*sizeof(Coords)); - cylinder_shell_array.num_elements = 2*points_per_circle; - - Coords cyl_direction = geometry->geometry_parameters.p_cylinder_storage->direction_vector; - Coords center = geometry->center; - double radius = geometry->geometry_parameters.p_cylinder_storage->cyl_radius; - double height = geometry->geometry_parameters.p_cylinder_storage->height; - - Coords cyl_top_point = coords_add(center,coords_scalar_mult(cyl_direction,0.5*height)); - Coords cyl_bottom_point = coords_add(center,coords_scalar_mult(cyl_direction,-0.5*height)); - - points_on_circle(cylinder_shell_array.elements,cyl_top_point,cyl_direction,radius,points_per_circle); - // Need to verify this pointer arithimatic works as intended - points_on_circle(cylinder_shell_array.elements+points_per_circle,cyl_bottom_point,cyl_direction,radius,points_per_circle); - - return cylinder_shell_array; -} - -#ifndef ANY_GEOMETRY_DETECTOR_DECLARE - #define ANY_GEOMETRY_DETECTOR_DECLARE dummy - //struct pointer_to_global_geometry_list global_geometry_list = {0,NULL}; -#endif + } + + struct pointer_to_1d_coords_list + cylinder_shell_points (struct geometry_struct* geometry, int max_number_of_points) { + // Function that returns a number (less than max) of points on the geometry surface + // If used, remember to free the space allocated. + int points_per_circle = floor (max_number_of_points / 2.0); + + struct pointer_to_1d_coords_list cylinder_shell_array; + cylinder_shell_array.elements = malloc (2 * points_per_circle * sizeof (Coords)); + cylinder_shell_array.num_elements = 2 * points_per_circle; + + Coords cyl_direction = geometry->geometry_parameters.p_cylinder_storage->direction_vector; + Coords center = geometry->center; + double radius = geometry->geometry_parameters.p_cylinder_storage->cyl_radius; + double height = geometry->geometry_parameters.p_cylinder_storage->height; + + Coords cyl_top_point = coords_add (center, coords_scalar_mult (cyl_direction, 0.5 * height)); + Coords cyl_bottom_point = coords_add (center, coords_scalar_mult (cyl_direction, -0.5 * height)); + + points_on_circle (cylinder_shell_array.elements, cyl_top_point, cyl_direction, radius, points_per_circle); + // Need to verify this pointer arithimatic works as intended + points_on_circle (cylinder_shell_array.elements + points_per_circle, cyl_bottom_point, cyl_direction, radius, points_per_circle); + + return cylinder_shell_array; + } + + #ifndef ANY_GEOMETRY_DETECTOR_DECLARE + #define ANY_GEOMETRY_DETECTOR_DECLARE dummy + // struct pointer_to_global_geometry_list global_geometry_list = {0,NULL}; + #endif %} DECLARE %{ -// Needed for transport to the main component -struct global_geometry_element_struct global_geometry_element; + // Needed for transport to the main component + struct global_geometry_element_struct global_geometry_element; -int loop_index; -int loop_2_index; -int material_index; + int loop_index; + int loop_2_index; + int material_index; -struct Volume_struct this_cylinder_volume; -struct cylinder_storage this_cylinder_storage; + struct Volume_struct this_cylinder_volume; + struct cylinder_storage this_cylinder_storage; -struct surface_stack_struct curved_surface_stack; -struct surface_stack_struct top_surface_stack; -struct surface_stack_struct bottom_surface_stack; -struct surface_stack_struct cut_surface_stack; + struct surface_stack_struct curved_surface_stack; + struct surface_stack_struct top_surface_stack; + struct surface_stack_struct bottom_surface_stack; + struct surface_stack_struct cut_surface_stack; %} INITIALIZE %{ -geometry_struct_init(&(this_cylinder_volume.geometry)); -// Initializes the focusing system for this volume including input sanitation. -focus_initialize(&this_cylinder_volume.geometry, POS_A_COMP_INDEX(INDEX_CURRENT_COMP+target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, target_x, target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); - -// Input sanitation for this geometry -if (radius <= 0) { - printf("\nERROR in Union_cylinder named %s, the radius is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} - -if (yheight <= 0) { - printf("\nERROR in Union_cylinder named %s, yheight is <= 0. \n",NAME_CURRENT_COMP); - exit(1); -} - -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_cylinder:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} - -struct pointer_to_global_material_list *global_material_list = COMP_GETPAR3(Union_init, init, global_material_list); -// Use sanitation -#ifdef MATERIAL_DETECTOR -if (global_material_list->num_elements == 0) { - // Here if the user have defined a material, but only after this material - printf("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); - printf(" %s was defined before first use of Union_make_material.\n",NAME_CURRENT_COMP); - exit(1); -} -#endif -#ifndef MATERIAL_DETECTOR - printf("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); - exit(1); -#endif - - -this_cylinder_volume.geometry.is_masked_volume = 0; -this_cylinder_volume.geometry.is_exit_volume = 0; -this_cylinder_volume.geometry.is_mask_volume = 0; -struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); - -// Read the material input, or if it lacks, use automatic linking. -if (mask_string && strlen(mask_string) && strcmp(mask_string, "NULL") && strcmp(mask_string, "0")) { + geometry_struct_init (&(this_cylinder_volume.geometry)); + // Initializes the focusing system for this volume including input sanitation. + focus_initialize (&this_cylinder_volume.geometry, POS_A_COMP_INDEX (INDEX_CURRENT_COMP + target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, + target_x, target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); + + // Input sanitation for this geometry + if (radius <= 0) { + printf ("\nERROR in Union_cylinder named %s, the radius is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + + if (yheight <= 0) { + printf ("\nERROR in Union_cylinder named %s, yheight is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_cylinder:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } + + struct pointer_to_global_material_list* global_material_list = COMP_GETPAR3 (Union_init, init, global_material_list); + // Use sanitation + #ifdef MATERIAL_DETECTOR + if (global_material_list->num_elements == 0) { + // Here if the user have defined a material, but only after this material + printf ("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); + printf (" %s was defined before first use of Union_make_material.\n", NAME_CURRENT_COMP); + exit (1); + } + #endif + #ifndef MATERIAL_DETECTOR + printf ("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); + exit (1); + #endif + + this_cylinder_volume.geometry.is_masked_volume = 0; + this_cylinder_volume.geometry.is_exit_volume = 0; + this_cylinder_volume.geometry.is_mask_volume = 0; + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + + // Read the material input, or if it lacks, use automatic linking. + if (mask_string && strlen (mask_string) && strcmp (mask_string, "NULL") && strcmp (mask_string, "0")) { // A mask volume is used to limit the extend of other volumes, called the masked volumes. These are specified in the mask_string. // In order for a ray to enter a masked volume, it needs to be both in the region covered by that volume AND the mask volume. // When more than this_cylinder_volume.geometry.mask_mode = 1; // Default is mask mode is ALL - if (mask_setting && strlen(mask_setting) && strcmp(mask_setting, "NULL") && strcmp(mask_setting, "0")) { - if (strcmp(mask_setting,"ALL") == 0 || strcmp(mask_setting,"All") == 0) this_cylinder_volume.geometry.mask_mode = 1; - else if (strcmp(mask_setting,"ANY") == 0 || strcmp(mask_setting,"Any") == 0) this_cylinder_volume.geometry.mask_mode = 2; - else { - printf("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n",NAME_CURRENT_COMP,mask_setting); - exit(1); - } + if (mask_setting && strlen (mask_setting) && strcmp (mask_setting, "NULL") && strcmp (mask_setting, "0")) { + if (strcmp (mask_setting, "ALL") == 0 || strcmp (mask_setting, "All") == 0) + this_cylinder_volume.geometry.mask_mode = 1; + else if (strcmp (mask_setting, "ANY") == 0 || strcmp (mask_setting, "Any") == 0) + this_cylinder_volume.geometry.mask_mode = 2; + else { + printf ("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n", NAME_CURRENT_COMP, mask_setting); + exit (1); + } } - + int found_geometries = 0; - for (loop_index=0;loop_indexnum_elements;loop_index++) { - // Add mask list - if (1 == manual_linking_function(global_geometry_list->elements[loop_index].name,mask_string)) { - add_element_to_int_list(&this_cylinder_volume.geometry.mask_list,global_geometry_list->elements[loop_index].component_index); - add_element_to_int_list(&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list,INDEX_CURRENT_COMP); - global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; - if (this_cylinder_volume.geometry.mask_mode == 2) - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; - if (this_cylinder_volume.geometry.mask_mode == 1) { - if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) - // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; - } - - found_geometries = 1; + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + // Add mask list + if (1 == manual_linking_function (global_geometry_list->elements[loop_index].name, mask_string)) { + add_element_to_int_list (&this_cylinder_volume.geometry.mask_list, global_geometry_list->elements[loop_index].component_index); + add_element_to_int_list (&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list, INDEX_CURRENT_COMP); + global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; + if (this_cylinder_volume.geometry.mask_mode == 2) + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; + if (this_cylinder_volume.geometry.mask_mode == 1) { + if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 + && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) + // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; } + + found_geometries = 1; + } } if (found_geometries == 0) { - printf("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n",NAME_CURRENT_COMP,mask_string); - exit(1); + printf ("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n", NAME_CURRENT_COMP, mask_string); + exit (1); } - this_cylinder_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_cylinder_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum - this_cylinder_volume.p_physics->number_of_processes = (int) 0; // Should not be used. - this_cylinder_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_cylinder_volume.p_physics->name,"Mask"); + this_cylinder_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_cylinder_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum + this_cylinder_volume.p_physics->number_of_processes = (int)0; // Should not be used. + this_cylinder_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_cylinder_volume.p_physics->name, "Mask"); this_cylinder_volume.geometry.is_mask_volume = 1; - - -// Read the material input, or if it lacks, use automatic linking. -} else if (material_string && strlen(material_string) && strcmp(material_string, "NULL") && strcmp(material_string, "0")) { + + // Read the material input, or if it lacks, use automatic linking. + } else if (material_string && strlen (material_string) && strcmp (material_string, "NULL") && strcmp (material_string, "0")) { // A geometry string was given, use it to determine which material - if (0 == strcmp(material_string,"vacuum") || 0 == strcmp(material_string,"Vacuum")) { - // One could have a global physics struct for vacuum instead of creating one for each - this_cylinder_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_cylinder_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_cylinder_volume.p_physics->number_of_processes = (int) 0; - this_cylinder_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_cylinder_volume.p_physics->name,"Vacuum"); - } else if (0 == strcmp(material_string,"exit") || 0 == strcmp(material_string,"Exit")) { - // One could have a global physics struct for exit instead of creating one for each - this_cylinder_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_cylinder_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_cylinder_volume.p_physics->number_of_processes = (int) 0; - this_cylinder_volume.p_physics->my_a = 0; // Should not be used. - this_cylinder_volume.geometry.is_exit_volume = 1; - sprintf(this_cylinder_volume.p_physics->name,"Exit"); + if (0 == strcmp (material_string, "vacuum") || 0 == strcmp (material_string, "Vacuum")) { + // One could have a global physics struct for vacuum instead of creating one for each + this_cylinder_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_cylinder_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_cylinder_volume.p_physics->number_of_processes = (int)0; + this_cylinder_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_cylinder_volume.p_physics->name, "Vacuum"); + } else if (0 == strcmp (material_string, "exit") || 0 == strcmp (material_string, "Exit")) { + // One could have a global physics struct for exit instead of creating one for each + this_cylinder_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_cylinder_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_cylinder_volume.p_physics->number_of_processes = (int)0; + this_cylinder_volume.p_physics->my_a = 0; // Should not be used. + this_cylinder_volume.geometry.is_exit_volume = 1; + sprintf (this_cylinder_volume.p_physics->name, "Exit"); } else { - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (0 == strcmp(material_string,global_material_list->elements[loop_index].name)) { - this_cylinder_volume.p_physics = global_material_list->elements[loop_index].physics; - break; - } - if (loop_index == global_material_list->num_elements-1) { - printf("\n"); - printf("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n",material_string,NAME_CURRENT_COMP); - printf(" The materials available at this point (need to be defined before the geometry): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_material_list->elements[loop_index].name); - printf("\n"); - printf(" It is also possible to use one of the defualt materials avaiable: \n"); - printf(" Vacuum (for a Volume without scattering or absorption)\n"); - printf(" Exit (for a Volume where the ray exits the component if it enters)\n"); - printf(" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); - exit(1); - } + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) { + if (0 == strcmp (material_string, global_material_list->elements[loop_index].name)) { + this_cylinder_volume.p_physics = global_material_list->elements[loop_index].physics; + break; + } + if (loop_index == global_material_list->num_elements - 1) { + printf ("\n"); + printf ("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n", material_string, NAME_CURRENT_COMP); + printf (" The materials available at this point (need to be defined before the geometry): \n"); + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) + printf (" %s\n", global_material_list->elements[loop_index].name); + printf ("\n"); + printf (" It is also possible to use one of the defualt materials avaiable: \n"); + printf (" Vacuum (for a Volume without scattering or absorption)\n"); + printf (" Exit (for a Volume where the ray exits the component if it enters)\n"); + printf (" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); + exit (1); } + } } -} else { + } else { // Automatic linking, simply using the last defined material. #ifndef MATERIAL_DETECTOR - printf("Need to define a material before the geometry to use automatic linking %s.\n",NAME_CURRENT_COMP); - exit(1); + printf ("Need to define a material before the geometry to use automatic linking %s.\n", NAME_CURRENT_COMP); + exit (1); #endif - this_cylinder_volume.p_physics = global_material_list->elements[global_material_list->num_elements-1].physics; -} - -// Handle surface input -if (all_face_surface && strlen(all_face_surface) && strcmp(all_face_surface, "NULL") && strcmp(all_face_surface, "0")) { - // Overwrite all other surfaces that have no input (if one wants a surface left without anything, None can be used) - overwrite_if_empty(curved_surface, all_face_surface); - overwrite_if_empty(top_surface, all_face_surface); - overwrite_if_empty(bottom_surface, all_face_surface); -} - -this_cylinder_volume.geometry.number_of_faces = 3; -this_cylinder_volume.geometry.surface_stack_for_each_face = malloc(this_cylinder_volume.geometry.number_of_faces*sizeof(struct surface_stack_struct*)); - -// This could be inserted into the fill_surface_stack function -this_cylinder_volume.geometry.surface_stack_for_each_face[0] = &curved_surface_stack; -this_cylinder_volume.geometry.surface_stack_for_each_face[1] = &top_surface_stack; -this_cylinder_volume.geometry.surface_stack_for_each_face[2] = &bottom_surface_stack; -this_cylinder_volume.geometry.internal_cut_surface_stack = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume - -struct pointer_to_global_surface_list *global_surface_list = COMP_GETPAR3(Union_init, init, global_surface_list); -fill_surface_stack(curved_surface, global_surface_list, NAME_CURRENT_COMP, &curved_surface_stack); -fill_surface_stack(top_surface, global_surface_list, NAME_CURRENT_COMP, &top_surface_stack); -fill_surface_stack(bottom_surface, global_surface_list, NAME_CURRENT_COMP, &bottom_surface_stack); -fill_surface_stack(cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); - -sprintf(this_cylinder_volume.name,"%s",NAME_CURRENT_COMP); -sprintf(this_cylinder_volume.geometry.shape,"cylinder"); -this_cylinder_volume.geometry.eShape = cylinder; -this_cylinder_volume.geometry.priority_value = priority; -// Currently the coordinates will be in absolute space. -this_cylinder_volume.geometry.center = POS_A_CURRENT_COMP; - -this_cylinder_volume.geometry.geometry_p_interact = p_interact; -this_cylinder_storage.cyl_radius = radius; -this_cylinder_storage.height = yheight; -this_cylinder_volume.geometry.visualization_on = visualize; -this_cylinder_volume.geometry.geometry_parameters.p_cylinder_storage = &this_cylinder_storage; -this_cylinder_volume.geometry.within_function = &r_within_cylinder; -this_cylinder_volume.geometry.intersect_function = &sample_cylinder_intersect; -this_cylinder_volume.geometry.mcdisplay_function = &mcdisplay_cylinder_function; -this_cylinder_volume.geometry.shell_points = &cylinder_shell_points; -this_cylinder_volume.geometry.initialize_from_main_function = &initialize_cylinder_geometry_from_main_component; -this_cylinder_volume.geometry.process_rot_allocated = 0; -this_cylinder_volume.geometry.copy_geometry_parameters = &allocate_cylinder_storage_copy; - -rot_copy(this_cylinder_volume.geometry.rotation_matrix,ROT_A_CURRENT_COMP); -rot_transpose(ROT_A_CURRENT_COMP,this_cylinder_volume.geometry.transpose_rotation_matrix); - -// Initialize loggers -this_cylinder_volume.loggers.num_elements = 0; -this_cylinder_volume.abs_loggers.num_elements = 0; - -// packing the information into the global_geometry_element, which is then included in the global_geometry_list. -sprintf(global_geometry_element.name,"%s",NAME_CURRENT_COMP); -global_geometry_element.activation_counter = number_of_activations; -global_geometry_element.component_index = INDEX_CURRENT_COMP; -global_geometry_element.Volume = &this_cylinder_volume; // Would be nicer if this m was a pointer, now we have the (small) data two places -add_element_to_geometry_list(global_geometry_list,global_geometry_element); + this_cylinder_volume.p_physics = global_material_list->elements[global_material_list->num_elements - 1].physics; + } + + // Handle surface input + if (all_face_surface && strlen (all_face_surface) && strcmp (all_face_surface, "NULL") && strcmp (all_face_surface, "0")) { + // Overwrite all other surfaces that have no input (if one wants a surface left without anything, None can be used) + overwrite_if_empty (curved_surface, all_face_surface); + overwrite_if_empty (top_surface, all_face_surface); + overwrite_if_empty (bottom_surface, all_face_surface); + } + + this_cylinder_volume.geometry.number_of_faces = 3; + this_cylinder_volume.geometry.surface_stack_for_each_face = malloc (this_cylinder_volume.geometry.number_of_faces * sizeof (struct surface_stack_struct*)); + + // This could be inserted into the fill_surface_stack function + this_cylinder_volume.geometry.surface_stack_for_each_face[0] = &curved_surface_stack; + this_cylinder_volume.geometry.surface_stack_for_each_face[1] = &top_surface_stack; + this_cylinder_volume.geometry.surface_stack_for_each_face[2] = &bottom_surface_stack; + this_cylinder_volume.geometry.internal_cut_surface_stack + = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume + + struct pointer_to_global_surface_list* global_surface_list = COMP_GETPAR3 (Union_init, init, global_surface_list); + fill_surface_stack (curved_surface, global_surface_list, NAME_CURRENT_COMP, &curved_surface_stack); + fill_surface_stack (top_surface, global_surface_list, NAME_CURRENT_COMP, &top_surface_stack); + fill_surface_stack (bottom_surface, global_surface_list, NAME_CURRENT_COMP, &bottom_surface_stack); + fill_surface_stack (cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); + + sprintf (this_cylinder_volume.name, "%s", NAME_CURRENT_COMP); + sprintf (this_cylinder_volume.geometry.shape, "cylinder"); + this_cylinder_volume.geometry.eShape = cylinder; + this_cylinder_volume.geometry.priority_value = priority; + // Currently the coordinates will be in absolute space. + this_cylinder_volume.geometry.center = POS_A_CURRENT_COMP; + + this_cylinder_volume.geometry.geometry_p_interact = p_interact; + this_cylinder_storage.cyl_radius = radius; + this_cylinder_storage.height = yheight; + this_cylinder_volume.geometry.visualization_on = visualize; + this_cylinder_volume.geometry.geometry_parameters.p_cylinder_storage = &this_cylinder_storage; + this_cylinder_volume.geometry.within_function = &r_within_cylinder; + this_cylinder_volume.geometry.intersect_function = &sample_cylinder_intersect; + this_cylinder_volume.geometry.mcdisplay_function = &mcdisplay_cylinder_function; + this_cylinder_volume.geometry.shell_points = &cylinder_shell_points; + this_cylinder_volume.geometry.initialize_from_main_function = &initialize_cylinder_geometry_from_main_component; + this_cylinder_volume.geometry.process_rot_allocated = 0; + this_cylinder_volume.geometry.copy_geometry_parameters = &allocate_cylinder_storage_copy; + + rot_copy (this_cylinder_volume.geometry.rotation_matrix, ROT_A_CURRENT_COMP); + rot_transpose (ROT_A_CURRENT_COMP, this_cylinder_volume.geometry.transpose_rotation_matrix); + + // Initialize loggers + this_cylinder_volume.loggers.num_elements = 0; + this_cylinder_volume.abs_loggers.num_elements = 0; + + // packing the information into the global_geometry_element, which is then included in the global_geometry_list. + sprintf (global_geometry_element.name, "%s", NAME_CURRENT_COMP); + global_geometry_element.activation_counter = number_of_activations; + global_geometry_element.component_index = INDEX_CURRENT_COMP; + global_geometry_element.Volume = &this_cylinder_volume; // Would be nicer if this m was a pointer, now we have the (small) data two places + add_element_to_geometry_list (global_geometry_list, global_geometry_element); %} TRACE diff --git a/mcstas-comps/union/Union_init.comp b/mcstas-comps/union/Union_init.comp index 4b4f2055b1..1b9dfd4849 100755 --- a/mcstas-comps/union/Union_init.comp +++ b/mcstas-comps/union/Union_init.comp @@ -53,101 +53,101 @@ SETTING PARAMETERS() SHARE %{ -#ifdef Union -#error "The Union_init component needs to be the first Union component!" -//printf("ERROR: The Union_init component needs to be the first Union component!\n"); -//exit(1); -#else -#define Union $Revision: 0.8 $ -%include "union-lib.c" -#endif + #ifdef Union + #error "The Union_init component needs to be the first Union component!" + // printf("ERROR: The Union_init component needs to be the first Union component!\n"); + // exit(1); + #else + #define Union $Revision: 0.8 $ + %include "union-lib.c" + #endif %} DECLARE %{ -// Initialize global positions / rotations to transform lists + // Initialize global positions / rotations to transform lists // These are lists of pointers to positons / rotations, that will be updated from global frame // to the frame of the master component that uses them in that masters initialize section. struct global_positions_to_transform_list_struct global_positions_to_transform_list; struct global_rotations_to_transform_list_struct global_rotations_to_transform_list; -// Initialize global_process_list + // Initialize global_process_list // Used to facilitate communication between processes and the other types of Union components struct pointer_to_global_process_list global_process_list; -// Initialize global_material_list + // Initialize global_material_list // Used to facilitate communication between materials and the other types of Union components struct pointer_to_global_material_list global_material_list; -// Initialize global_surface_list + // Initialize global_surface_list // Used to facilitate communication between surface components and other types of Union components struct pointer_to_global_surface_list global_surface_list; -// Initialize global_geometry_list + // Initialize global_geometry_list // Used to facilitate communication between geometries and the other types of Union components struct pointer_to_global_geometry_list global_geometry_list; -// Initialize global_logger_lists + // Initialize global_logger_lists // Used to facilitate communication between loggers and the other types of Union components struct pointer_to_global_logger_list global_all_volume_logger_list; struct pointer_to_global_logger_list global_specific_volumes_logger_list; -// Initialize global_abs_logger_lists + // Initialize global_abs_logger_lists struct pointer_to_global_abs_logger_list global_all_volume_abs_logger_list; struct pointer_to_global_abs_logger_list global_specific_volumes_abs_logger_list; -// Initialize global_tagging_conditional_list + // Initialize global_tagging_conditional_list // Used to facilitate communication between conditionals and the other types of Union components struct global_tagging_conditional_list_struct global_tagging_conditional_list; -// Initialize global_master_list + // Initialize global_master_list // Used to facilitate communication between Master components (mainly for deallocation) struct pointer_to_global_master_list global_master_list; -// Initialize global_mantid_min_pixel_id + // Initialize global_mantid_min_pixel_id // Used for ensuring pixel id's on Mantid monitors do not overlap int global_mantid_min_pixel_id; %} INITIALIZE %{ -global_positions_to_transform_list.num_elements = 0; -global_positions_to_transform_list.positions = NULL; + global_positions_to_transform_list.num_elements = 0; + global_positions_to_transform_list.positions = NULL; -global_rotations_to_transform_list.num_elements = 0; -global_rotations_to_transform_list.rotations = NULL; + global_rotations_to_transform_list.num_elements = 0; + global_rotations_to_transform_list.rotations = NULL; -global_process_list.num_elements = 0; -global_process_list.elements = NULL; + global_process_list.num_elements = 0; + global_process_list.elements = NULL; -global_material_list.num_elements = 0; -global_material_list.elements = NULL; + global_material_list.num_elements = 0; + global_material_list.elements = NULL; -global_surface_list.num_elements = 0; -global_surface_list.elements = NULL; + global_surface_list.num_elements = 0; + global_surface_list.elements = NULL; -global_geometry_list.num_elements = 0; -global_geometry_list.elements = NULL; + global_geometry_list.num_elements = 0; + global_geometry_list.elements = NULL; -global_all_volume_logger_list.num_elements = 0; -global_all_volume_logger_list.elements = NULL; + global_all_volume_logger_list.num_elements = 0; + global_all_volume_logger_list.elements = NULL; -global_specific_volumes_logger_list.num_elements = 0; -global_specific_volumes_logger_list.elements = NULL; + global_specific_volumes_logger_list.num_elements = 0; + global_specific_volumes_logger_list.elements = NULL; -global_all_volume_abs_logger_list.num_elements = 0; -global_all_volume_abs_logger_list.elements = NULL; + global_all_volume_abs_logger_list.num_elements = 0; + global_all_volume_abs_logger_list.elements = NULL; -global_specific_volumes_abs_logger_list.num_elements = 0; -global_specific_volumes_abs_logger_list.elements = NULL; + global_specific_volumes_abs_logger_list.num_elements = 0; + global_specific_volumes_abs_logger_list.elements = NULL; -global_tagging_conditional_list.num_elements = 0; -global_tagging_conditional_list.elements = NULL; + global_tagging_conditional_list.num_elements = 0; + global_tagging_conditional_list.elements = NULL; -global_master_list.num_elements = 0; -global_master_list.elements = NULL; + global_master_list.num_elements = 0; + global_master_list.elements = NULL; -global_mantid_min_pixel_id = 0; + global_mantid_min_pixel_id = 0; %} TRACE diff --git a/mcstas-comps/union/Union_logger_1D.comp b/mcstas-comps/union/Union_logger_1D.comp index dfa6b96cfe..dd205baa6d 100644 --- a/mcstas-comps/union/Union_logger_1D.comp +++ b/mcstas-comps/union/Union_logger_1D.comp @@ -77,336 +77,347 @@ SETTING PARAMETERS(string target_geometry="NULL", string target_process="NULL", SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_logger_1D component" -#endif - -struct temp_1D_data_element_struct { - int index; - double weight; -}; - -struct temp_1D_data_struct { - int num_elements; - int allocated_elements; - struct temp_1D_data_element_struct *elements; -}; - -struct a_1D_storage_struct { - struct Detector_1D_struct Detector_1D; - struct temp_1D_data_struct temp_1D_data; - //some type - int variable_identifier; - int order; - int order_in_this_volume; - int order_process_in_this_volume; - -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_1D(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - struct a_1D_storage_struct *storage; - storage = logger->data_union.p_1D_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_logger_1D component" + #endif + + struct temp_1D_data_element_struct { + int index; + double weight; + }; + + struct temp_1D_data_struct { + int num_elements; + int allocated_elements; + struct temp_1D_data_element_struct* elements; + }; + + struct a_1D_storage_struct { + struct Detector_1D_struct Detector_1D; + struct temp_1D_data_struct temp_1D_data; + // some type + int variable_identifier; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_1D (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + struct a_1D_storage_struct* storage; + storage = logger->data_union.p_1D_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } - int i; - double value; - - if (storage->variable_identifier == 1) { - value = time; - } else if (storage->variable_identifier == 2) { - value = sqrt( (k_new[0]-k_old[0])*(k_new[0]-k_old[0]) + (k_new[1]-k_old[1])*(k_new[1]-k_old[1]) + (k_new[2]-k_old[2])*(k_new[2]-k_old[2])); + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; } - - // Find bin in histogram - if (value>storage->Detector_1D.min && valueDetector_1D.max) { - i = floor((value - storage->Detector_1D.min)*storage->Detector_1D.bins/(storage->Detector_1D.max - storage->Detector_1D.min)); - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_1D_data.num_elements,storage->temp_1D_data.allocated_elements); - - if (storage->temp_1D_data.num_elements < storage->temp_1D_data.allocated_elements) { - storage->temp_1D_data.elements[storage->temp_1D_data.num_elements].index = i; - storage->temp_1D_data.elements[storage->temp_1D_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_1D_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_1D_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_1D_data_element_struct)); - - for (index=0;indextemp_1D_data.num_elements;index++) { - temporary_storage.elements[index].index = storage->temp_1D_data.elements[index].index; - temporary_storage.elements[index].weight = storage->temp_1D_data.elements[index].weight; - } - - // free current data - free(storage->temp_1D_data.elements); - - // allocate larger array (10 larger) - storage->temp_1D_data.allocated_elements = 10 + storage->temp_1D_data.num_elements; - storage->temp_1D_data.elements = malloc(storage->temp_1D_data.allocated_elements*sizeof(struct temp_1D_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_1D_data.num_elements;index++) { - storage->temp_1D_data.elements[index].index = temporary_storage.elements[index].index; - storage->temp_1D_data.elements[index].weight = temporary_storage.elements[index].weight; + + if (add_point == 1) { + + int i; + double value; + + if (storage->variable_identifier == 1) { + value = time; + } else if (storage->variable_identifier == 2) { + value = sqrt ((k_new[0] - k_old[0]) * (k_new[0] - k_old[0]) + (k_new[1] - k_old[1]) * (k_new[1] - k_old[1]) + + (k_new[2] - k_old[2]) * (k_new[2] - k_old[2])); + } + + // Find bin in histogram + if (value > storage->Detector_1D.min && value < storage->Detector_1D.max) { + i = floor ((value - storage->Detector_1D.min) * storage->Detector_1D.bins / (storage->Detector_1D.max - storage->Detector_1D.min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_1D_data.num_elements,storage->temp_1D_data.allocated_elements); + + if (storage->temp_1D_data.num_elements < storage->temp_1D_data.allocated_elements) { + storage->temp_1D_data.elements[storage->temp_1D_data.num_elements].index = i; + storage->temp_1D_data.elements[storage->temp_1D_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_1D_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_1D_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_1D_data_element_struct)); + + for (index = 0; index < storage->temp_1D_data.num_elements; index++) { + temporary_storage.elements[index].index = storage->temp_1D_data.elements[index].index; + temporary_storage.elements[index].weight = storage->temp_1D_data.elements[index].weight; + } + + // free current data + free (storage->temp_1D_data.elements); + + // allocate larger array (10 larger) + storage->temp_1D_data.allocated_elements = 10 + storage->temp_1D_data.num_elements; + storage->temp_1D_data.elements = malloc (storage->temp_1D_data.allocated_elements * sizeof (struct temp_1D_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_1D_data.num_elements; index++) { + storage->temp_1D_data.elements[index].index = temporary_storage.elements[index].index; + storage->temp_1D_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_1D_data.elements[storage->temp_1D_data.num_elements].index = i; + storage->temp_1D_data.elements[storage->temp_1D_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_1D_data.elements[storage->temp_1D_data.num_elements].index = i; - storage->temp_1D_data.elements[storage->temp_1D_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_1D_data.num_elements == 1) + add_to_logger_with_data (logger_with_data_array, logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_1D_data.num_elements == 1) - add_to_logger_with_data(logger_with_data_array,logger); } } - -} - -// clear_temp -void clear_temp_1D(union logger_data_union *data_union) { - data_union->p_1D_storage->temp_1D_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_1D(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_1D_storage_struct *storage; - storage = logger->data_union.p_1D_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_1D (union logger_data_union* data_union) { + data_union->p_1D_storage->temp_1D_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - - int i; - double value; - - if (storage->variable_identifier == 1) { - value = time; - } else if (storage->variable_identifier == 2) { - value = sqrt( (k_new[0]-k_old[0])*(k_new[0]-k_old[0]) + (k_new[1]-k_old[1])*(k_new[1]-k_old[1]) + (k_new[2]-k_old[2])*(k_new[2]-k_old[2])); + // record_to_perm + void + record_to_perm_1D (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_1D_storage_struct* storage; + storage = logger->data_union.p_1D_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; } - - - // Find bin in histogram - if (value>storage->Detector_1D.min && valueDetector_1D.max) { - - i = floor((value - storage->Detector_1D.min)*(double)storage->Detector_1D.bins/(storage->Detector_1D.max - storage->Detector_1D.min)); - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_1D.Array_N[i]++; - storage->Detector_1D.Array_p[i] += p; - storage->Detector_1D.Array_p2[i] += p*p; - + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + + int i; + double value; + + if (storage->variable_identifier == 1) { + value = time; + } else if (storage->variable_identifier == 2) { + value = sqrt ((k_new[0] - k_old[0]) * (k_new[0] - k_old[0]) + (k_new[1] - k_old[1]) * (k_new[1] - k_old[1]) + + (k_new[2] - k_old[2]) * (k_new[2] - k_old[2])); + } + + // Find bin in histogram + if (value > storage->Detector_1D.min && value < storage->Detector_1D.max) { + + i = floor ((value - storage->Detector_1D.min) * (double)storage->Detector_1D.bins / (storage->Detector_1D.max - storage->Detector_1D.min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_1D.Array_N[i]++; + storage->Detector_1D.Array_p[i] += p; + storage->Detector_1D.Array_p2[i] += p * p; + } } } -} + // write_temp_to_perm + void + write_temp_to_perm_1D (union logger_data_union* data_union) { -// write_temp_to_perm -void write_temp_to_perm_1D(union logger_data_union *data_union) { + struct a_1D_storage_struct* storage; + storage = data_union->p_1D_storage; - struct a_1D_storage_struct *storage; - storage = data_union->p_1D_storage; + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_data.num_elements; index++) { + storage->Detector_1D.Array_N[storage->temp_1D_data.elements[index].index]++; - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_data.num_elements;index++) { - storage->Detector_1D.Array_N[storage->temp_1D_data.elements[index].index]++; - - storage->Detector_1D.Array_p[storage->temp_1D_data.elements[index].index] += storage->temp_1D_data.elements[index].weight; - - storage->Detector_1D.Array_p2[storage->temp_1D_data.elements[index].index] += storage->temp_1D_data.elements[index].weight*storage->temp_1D_data.elements[index].weight; + storage->Detector_1D.Array_p[storage->temp_1D_data.elements[index].index] += storage->temp_1D_data.elements[index].weight; + + storage->Detector_1D.Array_p2[storage->temp_1D_data.elements[index].index] + += storage->temp_1D_data.elements[index].weight * storage->temp_1D_data.elements[index].weight; + } + clear_temp_1D (data_union); } - clear_temp_1D(data_union); -} - -void write_temp_to_perm_final_p_1D(union logger_data_union *data_union, double final_weight) { - - struct a_1D_storage_struct *storage; - storage = data_union->p_1D_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_1D_data.num_elements;index++) { - storage->Detector_1D.Array_N[storage->temp_1D_data.elements[index].index]++; - - storage->Detector_1D.Array_p[storage->temp_1D_data.elements[index].index] += final_weight; - - storage->Detector_1D.Array_p2[storage->temp_1D_data.elements[index].index] += final_weight*final_weight; + + void + write_temp_to_perm_final_p_1D (union logger_data_union* data_union, double final_weight) { + + struct a_1D_storage_struct* storage; + storage = data_union->p_1D_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_1D_data.num_elements; index++) { + storage->Detector_1D.Array_N[storage->temp_1D_data.elements[index].index]++; + + storage->Detector_1D.Array_p[storage->temp_1D_data.elements[index].index] += final_weight; + + storage->Detector_1D.Array_p2[storage->temp_1D_data.elements[index].index] += final_weight * final_weight; + } + clear_temp_1D (data_union); } - clear_temp_1D(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_LOGGER -#define UNION_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_LOGGER + #define UNION_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { + void + manual_linking_function_logger_processes (char* input_string, struct physics_struct* p_physics, struct pointer_to_1d_int_list* accepted_processes, + char* component_name, char* Volume_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) { - if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes,loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) { + if (strcmp (token, p_physics->p_scattering_array[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == p_physics->number_of_processes - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) - printf(" %s\n",p_physics->p_scattering_array[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume " + "\"%s\". \n", + input_string, component_name, Volume_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n", p_physics->name, Volume_name); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) + printf (" %s\n", p_physics->p_scattering_array[loop_index].name); + exit (1); } } - - // Updates the token - token = strtok(NULL,","); - } -} -#endif + // Updates the token + token = strtok (NULL, ","); + } + } + #endif %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; - -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -struct global_logger_element_struct logger_list_element; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct pointer_to_1d_int_list accepted_volumes; + struct global_logger_element_struct logger_list_element; -struct logger_struct this_logger; -struct a_1D_storage_struct this_storage; + struct pointer_to_1d_int_list accepted_volumes; -struct loggers_struct *loggers_on_target_volume; -struct Volume_struct *target_volume; + struct logger_struct this_logger; + struct a_1D_storage_struct this_storage; -char temp_string[2]; + struct loggers_struct* loggers_on_target_volume; + struct Volume_struct* target_volume; + char temp_string[2]; %} INITIALIZE @@ -414,75 +425,73 @@ INITIALIZE // Initialize 1d_int_lists accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; // Initialize storage from input if (min_value >= max_value) { - printf("ERROR, Union logger \"%s\" had min_value >= max_value.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had min_value >= max_value.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_1D.min = min_value; this_storage.Detector_1D.max = max_value; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_1D.bins = n1; - + // Remember to take special care when deallocating this array - this_storage.Detector_1D.Array_N = malloc(n1*sizeof(double)); - this_storage.Detector_1D.Array_p = malloc(n1*sizeof(double)); - this_storage.Detector_1D.Array_p2 = malloc(n1*sizeof(double)); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its logger list - add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); - + add_initialized_logger_in_volume (&target_volume->loggers, target_volume->p_physics->number_of_processes); + int process_index; - if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { + if (target_process && strlen (target_process) && strcmp (target_process, "NULL") && strcmp (target_process, "0")) { // Unused process pointers should point to NULL - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = NULL; } // A target_process was set, find it within the volume structure (can be many processes) - manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); - for (process_index=0;process_indexp_physics, &accepted_processes, NAME_CURRENT_COMP, target_volume->name); + for (process_index = 0; process_index < accepted_processes.num_elements; process_index++) { // Add pointer to this logger for all the accepted processes in this newly added loggers element - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[accepted_processes.elements[process_index]] + = &this_logger; } } else { // No target_process was set, attatch the logger to all processes - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = &this_logger; } } } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - add_element_to_logger_list(global_all_volume_logger_list,logger_list_element); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + add_element_to_logger_list (global_all_volume_logger_list, logger_list_element); } - %} TRACE @@ -566,31 +573,28 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_1D( - this_storage.Detector_1D.title_string, - this_storage.Detector_1D.string_axis, - this_storage.Detector_1D.string_axis_value, - this_storage.Detector_1D.string_axis_short, - this_storage.Detector_1D.min, this_storage.Detector_1D.max, - this_storage.Detector_1D.bins, - &this_storage.Detector_1D.Array_N[0], &this_storage.Detector_1D.Array_p[0], &this_storage.Detector_1D.Array_p2[0], - this_storage.Detector_1D.Filename); + // Write to disk + DETECTOR_OUT_1D (this_storage.Detector_1D.title_string, this_storage.Detector_1D.string_axis, this_storage.Detector_1D.string_axis_value, + this_storage.Detector_1D.string_axis_short, this_storage.Detector_1D.min, this_storage.Detector_1D.max, this_storage.Detector_1D.bins, + &this_storage.Detector_1D.Array_N[0], &this_storage.Detector_1D.Array_p[0], &this_storage.Detector_1D.Array_p2[0], + this_storage.Detector_1D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_storage.temp_1D_data.allocated_elements>0) free(this_storage.temp_1D_data.elements); - -free(this_storage.Detector_1D.Array_N); -free(this_storage.Detector_1D.Array_p); -free(this_storage.Detector_1D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_storage.temp_1D_data.allocated_elements > 0) + free (this_storage.temp_1D_data.elements); + + free (this_storage.Detector_1D.Array_N); + free (this_storage.Detector_1D.Array_p); + free (this_storage.Detector_1D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_logger_2DQ.comp b/mcstas-comps/union/Union_logger_2DQ.comp index 67e60d0b6d..0641e44ee7 100644 --- a/mcstas-comps/union/Union_logger_2DQ.comp +++ b/mcstas-comps/union/Union_logger_2DQ.comp @@ -83,365 +83,382 @@ SETTING PARAMETERS(string target_geometry="NULL",string target_process="NULL", SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_logger_2DQ component" -#endif - -struct temp_2DQ_data_element_struct { - int index_1; - int index_2; - double weight; -}; - -struct temp_2DQ_data_struct { - int num_elements; - int allocated_elements; - struct temp_2DQ_data_element_struct *elements; -}; - -struct a_2DQ_storage_struct { - struct Detector_2D_struct Detector_2D; - struct temp_2DQ_data_struct temp_2DQ_data; - int dim_1_choice; - int dim_2_choice; - int order; - int order_in_this_volume; - int order_process_in_this_volume; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_2DQ(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - struct a_2DQ_storage_struct *storage; - storage = logger->data_union.p_2DQ_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_logger_2DQ component" + #endif + + struct temp_2DQ_data_element_struct { + int index_1; + int index_2; + double weight; + }; + + struct temp_2DQ_data_struct { + int num_elements; + int allocated_elements; + struct temp_2DQ_data_element_struct* elements; + }; + + struct a_2DQ_storage_struct { + struct Detector_2D_struct Detector_2D; + struct temp_2DQ_data_struct temp_2DQ_data; + int dim_1_choice; + int dim_2_choice; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_2DQ (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + struct a_2DQ_storage_struct* storage; + storage = logger->data_union.p_2DQ_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - double q1,q2; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - q1 = k_old[storage->dim_1_choice] - k_new[storage->dim_1_choice]; - q2 = k_old[storage->dim_2_choice] - k_new[storage->dim_2_choice]; - - int i,j; - - // Find bin in histogram - if (q1>storage->Detector_2D.D1min && q1Detector_2D.D1max && q2>storage->Detector_2D.D2min && q2Detector_2D.D2max) { - i = floor((q1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((q2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_2DQ_data.num_elements,storage->temp_2DQ_data.allocated_elements); - - if (storage->temp_2DQ_data.num_elements < storage->temp_2DQ_data.allocated_elements) { - storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_1 = i; - storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_2 = j; - storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_2DQ_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_2DQ_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_2DQ_data_element_struct)); - - for (index=0;indextemp_2DQ_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_2DQ_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_2DQ_data.elements[index].index_2; - temporary_storage.elements[index].weight = storage->temp_2DQ_data.elements[index].weight; - } - - // free current data - free(storage->temp_2DQ_data.elements); - - // allocate larger array (10 larger) - storage->temp_2DQ_data.allocated_elements = 10 + storage->temp_2DQ_data.num_elements; - storage->temp_2DQ_data.elements = malloc(storage->temp_2DQ_data.allocated_elements*sizeof(struct temp_2DQ_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_2DQ_data.num_elements;index++) { - storage->temp_2DQ_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_2DQ_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_2DQ_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double q1, q2; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + q1 = k_old[storage->dim_1_choice] - k_new[storage->dim_1_choice]; + q2 = k_old[storage->dim_2_choice] - k_new[storage->dim_2_choice]; + + int i, j; + + // Find bin in histogram + if (q1 > storage->Detector_2D.D1min && q1 < storage->Detector_2D.D1max && q2 > storage->Detector_2D.D2min && q2 < storage->Detector_2D.D2max) { + i = floor ((q1 - storage->Detector_2D.D1min) * (double)storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((q2 - storage->Detector_2D.D2min) * (double)storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_2DQ_data.num_elements,storage->temp_2DQ_data.allocated_elements); + + if (storage->temp_2DQ_data.num_elements < storage->temp_2DQ_data.allocated_elements) { + storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_1 = i; + storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_2 = j; + storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_2DQ_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_2DQ_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_2DQ_data_element_struct)); + + for (index = 0; index < storage->temp_2DQ_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_2DQ_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_2DQ_data.elements[index].index_2; + temporary_storage.elements[index].weight = storage->temp_2DQ_data.elements[index].weight; + } + + // free current data + free (storage->temp_2DQ_data.elements); + + // allocate larger array (10 larger) + storage->temp_2DQ_data.allocated_elements = 10 + storage->temp_2DQ_data.num_elements; + storage->temp_2DQ_data.elements = malloc (storage->temp_2DQ_data.allocated_elements * sizeof (struct temp_2DQ_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_2DQ_data.num_elements; index++) { + storage->temp_2DQ_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_2DQ_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_2DQ_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_1 = i; + storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_2 = j; + storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_1 = i; - storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_2 = j; - storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_2DQ_data.num_elements == 1) + add_to_logger_with_data (logger_with_data_array, logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_2DQ_data.num_elements == 1) - add_to_logger_with_data(logger_with_data_array,logger); } } - -} - -// clear_temp -void clear_temp_2DQ(union logger_data_union *data_union) { - data_union->p_2DQ_storage->temp_2DQ_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_2DQ(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_2DQ_storage_struct *storage; - storage = logger->data_union.p_2DQ_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_2DQ (union logger_data_union* data_union) { + data_union->p_2DQ_storage->temp_2DQ_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double q1,q2; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input "x" "y" "z". - q1 = k_old[storage->dim_1_choice] - k_new[storage->dim_1_choice]; - q2 = k_old[storage->dim_2_choice] - k_new[storage->dim_2_choice]; - - int i,j; - - // Find bin in histogram - if (q1>storage->Detector_2D.D1min && q1Detector_2D.D1max && q2>storage->Detector_2D.D2min && q2Detector_2D.D2max) { - - i = floor((q1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((q2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_2D.Array_N[i][j]++; - storage->Detector_2D.Array_p[i][j] += p; - storage->Detector_2D.Array_p2[i][j] += p*p; - + // record_to_perm + void + record_to_perm_2DQ (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_2DQ_storage_struct* storage; + storage = logger->data_union.p_2DQ_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double q1, q2; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input "x" "y" "z". + q1 = k_old[storage->dim_1_choice] - k_new[storage->dim_1_choice]; + q2 = k_old[storage->dim_2_choice] - k_new[storage->dim_2_choice]; + + int i, j; + + // Find bin in histogram + if (q1 > storage->Detector_2D.D1min && q1 < storage->Detector_2D.D1max && q2 > storage->Detector_2D.D2min && q2 < storage->Detector_2D.D2max) { + + i = floor ((q1 - storage->Detector_2D.D1min) * (double)storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((q2 - storage->Detector_2D.D2min) * (double)storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_2D.Array_N[i][j]++; + storage->Detector_2D.Array_p[i][j] += p; + storage->Detector_2D.Array_p2[i][j] += p * p; + } } } -} + // write_temp_to_perm + void + write_temp_to_perm_2DQ (union logger_data_union* data_union) { -// write_temp_to_perm -void write_temp_to_perm_2DQ(union logger_data_union *data_union) { + struct a_2DQ_storage_struct* storage; + storage = data_union->p_2DQ_storage; - struct a_2DQ_storage_struct *storage; - storage = data_union->p_2DQ_storage; + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2DQ_data.num_elements; index++) { + storage->Detector_2D.Array_N[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2]++; - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2DQ_data.num_elements;index++) { - storage->Detector_2D.Array_N[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] += storage->temp_2DQ_data.elements[index].weight; - - storage->Detector_2D.Array_p2[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] += storage->temp_2DQ_data.elements[index].weight*storage->temp_2DQ_data.elements[index].weight; + storage->Detector_2D.Array_p[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] + += storage->temp_2DQ_data.elements[index].weight; + + storage->Detector_2D.Array_p2[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] + += storage->temp_2DQ_data.elements[index].weight * storage->temp_2DQ_data.elements[index].weight; + } + clear_temp_2DQ (data_union); } - clear_temp_2DQ(data_union); -} - -void write_temp_to_perm_final_p_2DQ(union logger_data_union *data_union, double final_weight) { - - struct a_2DQ_storage_struct *storage; - storage = data_union->p_2DQ_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2DQ_data.num_elements;index++) { - storage->Detector_2D.Array_N[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] += final_weight; - - storage->Detector_2D.Array_p2[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] += final_weight*final_weight; + + void + write_temp_to_perm_final_p_2DQ (union logger_data_union* data_union, double final_weight) { + + struct a_2DQ_storage_struct* storage; + storage = data_union->p_2DQ_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2DQ_data.num_elements; index++) { + storage->Detector_2D.Array_N[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] += final_weight; + + storage->Detector_2D.Array_p2[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] + += final_weight * final_weight; + } + clear_temp_2DQ (data_union); } - clear_temp_2DQ(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_LOGGER -#define UNION_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_LOGGER + #define UNION_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { + void + manual_linking_function_logger_processes (char* input_string, struct physics_struct* p_physics, struct pointer_to_1d_int_list* accepted_processes, + char* component_name, char* Volume_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) { - if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes,loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) { + if (strcmp (token, p_physics->p_scattering_array[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == p_physics->number_of_processes - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) - printf(" %s\n",p_physics->p_scattering_array[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume " + "\"%s\". \n", + input_string, component_name, Volume_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n", p_physics->name, Volume_name); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) + printf (" %s\n", p_physics->p_scattering_array[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif + token = strtok (NULL, ","); + } + } + #endif -double** allocate2Ddouble(int count_x, int count_y) { + double** + allocate2Ddouble (int count_x, int count_y) { // This function is needed to dynamically declare an array // that has continous data as a static array would have, // as that is the format expected by DETECTOR_OUT_2D. int i; // allocate space for actual data - double *data = malloc(sizeof(double) * count_x * count_y); + double* data = malloc (sizeof (double) * count_x * count_y); // create array or pointers to first elem in each 2D row - double **ptr_array = malloc(sizeof(double*) * count_x); - if (data == NULL || ptr_array == NULL){ - free(data); - free(ptr_array); - printf("\nERROR: ptr array or data not allocated in Union_logger_2DQ\n"); - exit(1); + double** ptr_array = malloc (sizeof (double*) * count_x); + if (data == NULL || ptr_array == NULL) { + free (data); + free (ptr_array); + printf ("\nERROR: ptr array or data not allocated in Union_logger_2DQ\n"); + exit (1); } for (i = 0; i < count_x; i++) { - ptr_array[i] = data + (i*count_y); + ptr_array[i] = data + (i * count_y); } return ptr_array; -} - -void free2Ddouble(double** ptr_array) { - if (!ptr_array) return; - if (ptr_array[0]) free(ptr_array[0]); - free(ptr_array); -} + } + void + free2Ddouble (double** ptr_array) { + if (!ptr_array) + return; + if (ptr_array[0]) + free (ptr_array[0]); + free (ptr_array); + } %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_logger_element_struct logger_list_element; + struct global_logger_element_struct logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct logger_struct this_logger; -struct a_2DQ_storage_struct this_storage; - -struct loggers_struct *loggers_on_target_volume; -struct Volume_struct *target_volume; + struct logger_struct this_logger; + struct a_2DQ_storage_struct this_storage; + struct loggers_struct* loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE @@ -454,104 +471,103 @@ INITIALIZE // Initialize storage from input if (Q1_min >= Q1_max) { - printf("ERROR, Union logger \"%s\" had Q1_min >= Q1_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had Q1_min >= Q1_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.D1min = Q1_min; this_storage.Detector_2D.D1max = Q1_max; - + if (Q2_min >= Q2_max) { - printf("ERROR, Union logger \"%s\" had Q2_min >= Q2_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had Q2_min >= Q2_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.D2min = Q2_min; this_storage.Detector_2D.D2max = Q2_max; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.bins_1 = n1; - + if (n2 <= 0) { - printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n2 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.bins_2 = n2; - - //printf("past input sanitation \n"); - + + // printf("past input sanitation \n"); + // Remember to take special care when deallocating this array, use free2Ddouble - this_storage.Detector_2D.Array_N = allocate2Ddouble(n1,n2); // Here the n1 double is cast to an int - this_storage.Detector_2D.Array_p = allocate2Ddouble(n1,n2); - this_storage.Detector_2D.Array_p2 = allocate2Ddouble(n1,n2); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its logger list - add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); - - if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { + add_initialized_logger_in_volume (&target_volume->loggers, target_volume->p_physics->number_of_processes); + + if (target_process && strlen (target_process) && strcmp (target_process, "NULL") && strcmp (target_process, "0")) { // Unused process pointers should point to NULL - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = NULL; } // A target_process was set, find it within the volume structure (can be many processes) - manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); - for (process_index=0;process_indexp_physics, &accepted_processes, NAME_CURRENT_COMP, target_volume->name); + for (process_index = 0; process_index < accepted_processes.num_elements; process_index++) { // Add pointer to this logger for all the accepted processes in this newly added loggers element - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[accepted_processes.elements[process_index]] + = &this_logger; } } else { // No target_process was set, attatch the logger to all processes - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = &this_logger; } } } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - add_element_to_logger_list(global_all_volume_logger_list,logger_list_element); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + add_element_to_logger_list (global_all_volume_logger_list, logger_list_element); } - - %} TRACE @@ -628,31 +642,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_2D( - this_storage.Detector_2D.title_string, - this_storage.Detector_2D.string_axis_1, - this_storage.Detector_2D.string_axis_2, - this_storage.Detector_2D.D1min, this_storage.Detector_2D.D1max, - this_storage.Detector_2D.D2min, this_storage.Detector_2D.D2max, - this_storage.Detector_2D.bins_1, this_storage.Detector_2D.bins_2, - *this_storage.Detector_2D.Array_N, *this_storage.Detector_2D.Array_p, *this_storage.Detector_2D.Array_p2, - this_storage.Detector_2D.Filename); - + // Write to disk + DETECTOR_OUT_2D (this_storage.Detector_2D.title_string, this_storage.Detector_2D.string_axis_1, this_storage.Detector_2D.string_axis_2, + this_storage.Detector_2D.D1min, this_storage.Detector_2D.D1max, this_storage.Detector_2D.D2min, this_storage.Detector_2D.D2max, + this_storage.Detector_2D.bins_1, this_storage.Detector_2D.bins_2, *this_storage.Detector_2D.Array_N, *this_storage.Detector_2D.Array_p, + *this_storage.Detector_2D.Array_p2, this_storage.Detector_2D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_storage.temp_2DQ_data.allocated_elements>0) free(this_storage.temp_2DQ_data.elements); - -free2Ddouble(this_storage.Detector_2D.Array_N); -free2Ddouble(this_storage.Detector_2D.Array_p); -free2Ddouble(this_storage.Detector_2D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_storage.temp_2DQ_data.allocated_elements > 0) + free (this_storage.temp_2DQ_data.elements); + + free2Ddouble (this_storage.Detector_2D.Array_N); + free2Ddouble (this_storage.Detector_2D.Array_p); + free2Ddouble (this_storage.Detector_2D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_logger_2D_kf.comp b/mcstas-comps/union/Union_logger_2D_kf.comp index 1ebedaad77..b6be29e97f 100644 --- a/mcstas-comps/union/Union_logger_2D_kf.comp +++ b/mcstas-comps/union/Union_logger_2D_kf.comp @@ -80,471 +80,484 @@ SETTING PARAMETERS(string target_geometry="NULL",string target_process="NULL", Q SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_logger_2D_kf component" -#endif - -struct temp_2D_kf_data_element_struct { - int index_1; - int index_2; - double weight; -}; - -struct temp_2D_kf_data_struct { - int num_elements; - int allocated_elements; - struct temp_2D_kf_data_element_struct *elements; -}; - -struct a_2D_kf_storage_struct { - struct Detector_2D_struct Detector_2D; - struct temp_2D_kf_data_struct temp_2D_kf_data; - int dim_1_choice; - int dim_2_choice; - int order; - int order_in_this_volume; - int order_process_in_this_volume; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_2D_kf(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - struct a_2D_kf_storage_struct *storage; - storage = logger->data_union.p_2D_kf_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_logger_2D_kf component" + #endif + + struct temp_2D_kf_data_element_struct { + int index_1; + int index_2; + double weight; + }; + + struct temp_2D_kf_data_struct { + int num_elements; + int allocated_elements; + struct temp_2D_kf_data_element_struct* elements; + }; + + struct a_2D_kf_storage_struct { + struct Detector_2D_struct Detector_2D; + struct temp_2D_kf_data_struct temp_2D_kf_data; + int dim_1_choice; + int dim_2_choice; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_2D_kf (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + struct a_2D_kf_storage_struct* storage; + storage = logger->data_union.p_2D_kf_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - double q1,q2; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - q1 = k_new[storage->dim_1_choice]; - q2 = k_new[storage->dim_2_choice]; - - int i,j; - - // Find bin in histogram - if (q1>storage->Detector_2D.D1min && q1Detector_2D.D1max && q2>storage->Detector_2D.D2min && q2Detector_2D.D2max) { - i = floor((q1 - storage->Detector_2D.D1min)*storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((q2 - storage->Detector_2D.D2min)*storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_2D_kf_data.num_elements,storage->temp_2D_kf_data.allocated_elements); - - if (storage->temp_2D_kf_data.num_elements < storage->temp_2D_kf_data.allocated_elements) { - storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_1 = i; - storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_2 = j; - storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_2D_kf_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_2D_kf_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_2D_kf_data_element_struct)); - - for (index=0;indextemp_2D_kf_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_2D_kf_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_2D_kf_data.elements[index].index_2; - temporary_storage.elements[index].weight = storage->temp_2D_kf_data.elements[index].weight; - } - - // free current data - free(storage->temp_2D_kf_data.elements); - - // allocate larger array (10 larger) - storage->temp_2D_kf_data.allocated_elements = 10 + storage->temp_2D_kf_data.num_elements; - storage->temp_2D_kf_data.elements = malloc(storage->temp_2D_kf_data.allocated_elements*sizeof(struct temp_2D_kf_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_2D_kf_data.num_elements;index++) { - storage->temp_2D_kf_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_2D_kf_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_2D_kf_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double q1, q2; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + q1 = k_new[storage->dim_1_choice]; + q2 = k_new[storage->dim_2_choice]; + + int i, j; + + // Find bin in histogram + if (q1 > storage->Detector_2D.D1min && q1 < storage->Detector_2D.D1max && q2 > storage->Detector_2D.D2min && q2 < storage->Detector_2D.D2max) { + i = floor ((q1 - storage->Detector_2D.D1min) * storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((q2 - storage->Detector_2D.D2min) * storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_2D_kf_data.num_elements,storage->temp_2D_kf_data.allocated_elements); + + if (storage->temp_2D_kf_data.num_elements < storage->temp_2D_kf_data.allocated_elements) { + storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_1 = i; + storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_2 = j; + storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_2D_kf_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_2D_kf_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_2D_kf_data_element_struct)); + + for (index = 0; index < storage->temp_2D_kf_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_2D_kf_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_2D_kf_data.elements[index].index_2; + temporary_storage.elements[index].weight = storage->temp_2D_kf_data.elements[index].weight; + } + + // free current data + free (storage->temp_2D_kf_data.elements); + + // allocate larger array (10 larger) + storage->temp_2D_kf_data.allocated_elements = 10 + storage->temp_2D_kf_data.num_elements; + storage->temp_2D_kf_data.elements = malloc (storage->temp_2D_kf_data.allocated_elements * sizeof (struct temp_2D_kf_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_2D_kf_data.num_elements; index++) { + storage->temp_2D_kf_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_2D_kf_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_2D_kf_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_1 = i; + storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_2 = j; + storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_1 = i; - storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements].index_2 = j; - storage->temp_2D_kf_data.elements[storage->temp_2D_kf_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_2D_kf_data.num_elements == 1) + add_to_logger_with_data (logger_with_data_array, logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_2D_kf_data.num_elements == 1) - add_to_logger_with_data(logger_with_data_array,logger); } } - -} - -// clear_temp -void clear_temp_2D_kf(union logger_data_union *data_union) { - data_union->p_2D_kf_storage->temp_2D_kf_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_2D_kf(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_2D_kf_storage_struct *storage; - storage = logger->data_union.p_2D_kf_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_2D_kf (union logger_data_union* data_union) { + data_union->p_2D_kf_storage->temp_2D_kf_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double q1,q2; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input "x" "y" "z". - q1 = k_new[storage->dim_1_choice]; - q2 = k_new[storage->dim_2_choice]; - - int i,j; - - // Find bin in histogram - if (q1>storage->Detector_2D.D1min && q1Detector_2D.D1max && q2>storage->Detector_2D.D2min && q2Detector_2D.D2max) { - - i = floor((q1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((q2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_2D.Array_N[i][j]++; - storage->Detector_2D.Array_p[i][j] += p; - storage->Detector_2D.Array_p2[i][j] += p*p; - + // record_to_perm + void + record_to_perm_2D_kf (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_2D_kf_storage_struct* storage; + storage = logger->data_union.p_2D_kf_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double q1, q2; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input "x" "y" "z". + q1 = k_new[storage->dim_1_choice]; + q2 = k_new[storage->dim_2_choice]; + + int i, j; + + // Find bin in histogram + if (q1 > storage->Detector_2D.D1min && q1 < storage->Detector_2D.D1max && q2 > storage->Detector_2D.D2min && q2 < storage->Detector_2D.D2max) { + + i = floor ((q1 - storage->Detector_2D.D1min) * (double)storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((q2 - storage->Detector_2D.D2min) * (double)storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_2D.Array_N[i][j]++; + storage->Detector_2D.Array_p[i][j] += p; + storage->Detector_2D.Array_p2[i][j] += p * p; + } } } -} + // write_temp_to_perm + void + write_temp_to_perm_2D_kf (union logger_data_union* data_union) { -// write_temp_to_perm -void write_temp_to_perm_2D_kf(union logger_data_union *data_union) { + struct a_2D_kf_storage_struct* storage; + storage = data_union->p_2D_kf_storage; - struct a_2D_kf_storage_struct *storage; - storage = data_union->p_2D_kf_storage; + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2D_kf_data.num_elements; index++) { + storage->Detector_2D.Array_N[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2]++; - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2D_kf_data.num_elements;index++) { - storage->Detector_2D.Array_N[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] += storage->temp_2D_kf_data.elements[index].weight; - - storage->Detector_2D.Array_p2[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] += storage->temp_2D_kf_data.elements[index].weight*storage->temp_2D_kf_data.elements[index].weight; + storage->Detector_2D.Array_p[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] + += storage->temp_2D_kf_data.elements[index].weight; + + storage->Detector_2D.Array_p2[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] + += storage->temp_2D_kf_data.elements[index].weight * storage->temp_2D_kf_data.elements[index].weight; + } + clear_temp_2D_kf (data_union); } - clear_temp_2D_kf(data_union); -} - -void write_temp_to_perm_final_p_2D_kf(union logger_data_union *data_union, double final_weight) { - - struct a_2D_kf_storage_struct *storage; - storage = data_union->p_2D_kf_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2D_kf_data.num_elements;index++) { - storage->Detector_2D.Array_N[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] += final_weight; - - storage->Detector_2D.Array_p2[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] += final_weight*final_weight; + + void + write_temp_to_perm_final_p_2D_kf (union logger_data_union* data_union, double final_weight) { + + struct a_2D_kf_storage_struct* storage; + storage = data_union->p_2D_kf_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2D_kf_data.num_elements; index++) { + storage->Detector_2D.Array_N[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] += final_weight; + + storage->Detector_2D.Array_p2[storage->temp_2D_kf_data.elements[index].index_1][storage->temp_2D_kf_data.elements[index].index_2] + += final_weight * final_weight; + } + clear_temp_2D_kf (data_union); } - clear_temp_2D_kf(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_LOGGER -#define UNION_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_LOGGER + #define UNION_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { + void + manual_linking_function_logger_processes (char* input_string, struct physics_struct* p_physics, struct pointer_to_1d_int_list* accepted_processes, + char* component_name, char* Volume_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) { - if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes,loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) { + if (strcmp (token, p_physics->p_scattering_array[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == p_physics->number_of_processes - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) - printf(" %s\n",p_physics->p_scattering_array[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume " + "\"%s\". \n", + input_string, component_name, Volume_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n", p_physics->name, Volume_name); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) + printf (" %s\n", p_physics->p_scattering_array[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif + token = strtok (NULL, ","); + } + } + #endif -double** allocate2Ddouble_2D_kf(int count_x, int count_y) { + double** + allocate2Ddouble_2D_kf (int count_x, int count_y) { // This function is needed to dynamically declare an array // that has continous data as a static array would have, // as that is the format expected by DETECTOR_OUT_2D. int i; // allocate space for actual data - double *data = malloc(sizeof(double) * count_x * count_y); + double* data = malloc (sizeof (double) * count_x * count_y); // create array or pointers to first elem in each 2D row - double **ptr_array = malloc(sizeof(double*) * count_x); + double** ptr_array = malloc (sizeof (double*) * count_x); for (i = 0; i < count_x; i++) { - ptr_array[i] = data + (i*count_y); + ptr_array[i] = data + (i * count_y); } return ptr_array; -} - -void free2Ddouble_2D_kf(double** ptr_array) { - if (!ptr_array) return; - if (ptr_array[0]) free(ptr_array[0]); - free(ptr_array); -} + } + void + free2Ddouble_2D_kf (double** ptr_array) { + if (!ptr_array) + return; + if (ptr_array[0]) + free (ptr_array[0]); + free (ptr_array); + } %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; - -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -struct global_logger_element_struct logger_list_element; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct pointer_to_1d_int_list accepted_volumes; + struct global_logger_element_struct logger_list_element; -struct logger_struct this_logger; -struct a_2D_kf_storage_struct this_storage; + struct pointer_to_1d_int_list accepted_volumes; -struct loggers_struct *loggers_on_target_volume; -struct Volume_struct *target_volume; + struct logger_struct this_logger; + struct a_2D_kf_storage_struct this_storage; + struct loggers_struct* loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE %{ accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; - // Initialize storage from input if (Q1_min >= Q1_max) { - printf("ERROR, Union logger \"%s\" had Q1_min >= Q1_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had Q1_min >= Q1_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.D1min = Q1_min; this_storage.Detector_2D.D1max = Q1_max; - + if (Q2_min >= Q2_max) { - printf("ERROR, Union logger \"%s\" had Q2_min >= Q2_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had Q2_min >= Q2_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.D2min = Q2_min; this_storage.Detector_2D.D2max = Q2_max; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.bins_1 = n1; - + if (n2 <= 0) { - printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n2 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.bins_2 = n2; - - //printf("past input sanitation \n"); - + + // printf("past input sanitation \n"); + // Remember to take special care when deallocating this array, use free2Ddouble - this_storage.Detector_2D.Array_N = allocate2Ddouble_2D_kf(n1,n2); // Here the n1 double is cast to an int - this_storage.Detector_2D.Array_p = allocate2Ddouble_2D_kf(n1,n2); - this_storage.Detector_2D.Array_p2 = allocate2Ddouble_2D_kf(n1,n2); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its logger list - add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); - - if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { + add_initialized_logger_in_volume (&target_volume->loggers, target_volume->p_physics->number_of_processes); + + if (target_process && strlen (target_process) && strcmp (target_process, "NULL") && strcmp (target_process, "0")) { // Unused process pointers should point to NULL - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = NULL; } // A target_process was set, find it within the volume structure (can be many processes) - manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); - for (process_index=0;process_indexp_physics, &accepted_processes, NAME_CURRENT_COMP, target_volume->name); + for (process_index = 0; process_index < accepted_processes.num_elements; process_index++) { // Add pointer to this logger for all the accepted processes in this newly added loggers element - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[accepted_processes.elements[process_index]] + = &this_logger; } } else { // No target_process was set, attatch the logger to all processes - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = &this_logger; } } } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - add_element_to_logger_list(global_all_volume_logger_list,logger_list_element); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + add_element_to_logger_list (global_all_volume_logger_list, logger_list_element); } - %} TRACE @@ -627,31 +639,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_2D( - this_storage.Detector_2D.title_string, - this_storage.Detector_2D.string_axis_1, - this_storage.Detector_2D.string_axis_2, - this_storage.Detector_2D.D1min, this_storage.Detector_2D.D1max, - this_storage.Detector_2D.D2min, this_storage.Detector_2D.D2max, - this_storage.Detector_2D.bins_1, this_storage.Detector_2D.bins_2, - *this_storage.Detector_2D.Array_N, *this_storage.Detector_2D.Array_p, *this_storage.Detector_2D.Array_p2, - this_storage.Detector_2D.Filename); - + // Write to disk + DETECTOR_OUT_2D (this_storage.Detector_2D.title_string, this_storage.Detector_2D.string_axis_1, this_storage.Detector_2D.string_axis_2, + this_storage.Detector_2D.D1min, this_storage.Detector_2D.D1max, this_storage.Detector_2D.D2min, this_storage.Detector_2D.D2max, + this_storage.Detector_2D.bins_1, this_storage.Detector_2D.bins_2, *this_storage.Detector_2D.Array_N, *this_storage.Detector_2D.Array_p, + *this_storage.Detector_2D.Array_p2, this_storage.Detector_2D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_storage.temp_2D_kf_data.allocated_elements>0) free(this_storage.temp_2D_kf_data.elements); - -free2Ddouble_2D_kf(this_storage.Detector_2D.Array_N); -free2Ddouble_2D_kf(this_storage.Detector_2D.Array_p); -free2Ddouble_2D_kf(this_storage.Detector_2D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_storage.temp_2D_kf_data.allocated_elements > 0) + free (this_storage.temp_2D_kf_data.elements); + + free2Ddouble_2D_kf (this_storage.Detector_2D.Array_N); + free2Ddouble_2D_kf (this_storage.Detector_2D.Array_p); + free2Ddouble_2D_kf (this_storage.Detector_2D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_logger_2D_kf_time.comp b/mcstas-comps/union/Union_logger_2D_kf_time.comp index 08d6a4e1f4..e3d370374c 100644 --- a/mcstas-comps/union/Union_logger_2D_kf_time.comp +++ b/mcstas-comps/union/Union_logger_2D_kf_time.comp @@ -84,530 +84,547 @@ SETTING PARAMETERS(string target_geometry="NULL",string target_process="NULL", Q SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_logger_2D_kf_time component" -#endif - -struct temp_2D_kf_t_data_element_struct { - int index_1; - int index_2; - int index_3; - double weight; -}; - -struct temp_2D_kf_t_data_struct { - int num_elements; - int allocated_elements; - struct temp_2D_kf_t_data_element_struct *elements; -}; - -struct a_2D_kf_t_storage_struct { - struct Detector_3D_struct Detector_3D; - struct temp_2D_kf_t_data_struct temp_2D_kf_t_data; - int dim_1_choice; - int dim_2_choice; - int dim_3_choice; - int order; - int order_in_this_volume; - int order_process_in_this_volume; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_2D_kf_t(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - struct a_2D_kf_t_storage_struct *storage; - storage = logger->data_union.p_2D_kf_t_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_logger_2D_kf_time component" + #endif + + struct temp_2D_kf_t_data_element_struct { + int index_1; + int index_2; + int index_3; + double weight; + }; + + struct temp_2D_kf_t_data_struct { + int num_elements; + int allocated_elements; + struct temp_2D_kf_t_data_element_struct* elements; + }; + + struct a_2D_kf_t_storage_struct { + struct Detector_3D_struct Detector_3D; + struct temp_2D_kf_t_data_struct temp_2D_kf_t_data; + int dim_1_choice; + int dim_2_choice; + int dim_3_choice; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_2D_kf_t (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + struct a_2D_kf_t_storage_struct* storage; + storage = logger->data_union.p_2D_kf_t_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { - double p1,p2; + double p1, p2; - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". p1 = k_new[storage->dim_1_choice]; p2 = k_new[storage->dim_2_choice]; - - int i,j,k; - - // Find bin in histogram - if (p1>storage->Detector_3D.D1min && p1Detector_3D.D1max && p2>storage->Detector_3D.D2min && p2Detector_3D.D2max && time>storage->Detector_3D.D3min && timeDetector_3D.D3max) { - i = floor((p1 - storage->Detector_3D.D1min)*storage->Detector_3D.bins_1/(storage->Detector_3D.D1max - storage->Detector_3D.D1min)); - j = floor((p2 - storage->Detector_3D.D2min)*storage->Detector_3D.bins_2/(storage->Detector_3D.D2max - storage->Detector_3D.D2min)); - k = floor((time - storage->Detector_3D.D3min)*storage->Detector_3D.bins_3/(storage->Detector_3D.D3max - storage->Detector_3D.D3min)); - - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_2D_kf_t_data.num_elements,storage->temp_2D_kf_t_data.allocated_elements); - - if (storage->temp_2D_kf_t_data.num_elements < storage->temp_2D_kf_t_data.allocated_elements) { - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_1 = k; - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_2 = i; - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_3 = j; - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_2D_kf_t_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_2D_kf_t_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_2D_kf_t_data_element_struct)); - - for (index=0;indextemp_2D_kf_t_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_2D_kf_t_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_2D_kf_t_data.elements[index].index_2; - temporary_storage.elements[index].index_3 = storage->temp_2D_kf_t_data.elements[index].index_3; - temporary_storage.elements[index].weight = storage->temp_2D_kf_t_data.elements[index].weight; - } - - // free current data - free(storage->temp_2D_kf_t_data.elements); - - // allocate larger array (10 larger) - storage->temp_2D_kf_t_data.allocated_elements = 10 + storage->temp_2D_kf_t_data.num_elements; - storage->temp_2D_kf_t_data.elements = malloc(storage->temp_2D_kf_t_data.allocated_elements*sizeof(struct temp_2D_kf_t_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_2D_kf_t_data.num_elements;index++) { - storage->temp_2D_kf_t_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_2D_kf_t_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_2D_kf_t_data.elements[index].index_3 = temporary_storage.elements[index].index_3; - storage->temp_2D_kf_t_data.elements[index].weight = temporary_storage.elements[index].weight; + + int i, j, k; + + // Find bin in histogram + if (p1 > storage->Detector_3D.D1min && p1 < storage->Detector_3D.D1max && p2 > storage->Detector_3D.D2min && p2 < storage->Detector_3D.D2max + && time > storage->Detector_3D.D3min && time < storage->Detector_3D.D3max) { + i = floor ((p1 - storage->Detector_3D.D1min) * storage->Detector_3D.bins_1 / (storage->Detector_3D.D1max - storage->Detector_3D.D1min)); + j = floor ((p2 - storage->Detector_3D.D2min) * storage->Detector_3D.bins_2 / (storage->Detector_3D.D2max - storage->Detector_3D.D2min)); + k = floor ((time - storage->Detector_3D.D3min) * storage->Detector_3D.bins_3 / (storage->Detector_3D.D3max - storage->Detector_3D.D3min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_2D_kf_t_data.num_elements,storage->temp_2D_kf_t_data.allocated_elements); + + if (storage->temp_2D_kf_t_data.num_elements < storage->temp_2D_kf_t_data.allocated_elements) { + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_1 = k; + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_2 = i; + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_3 = j; + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_2D_kf_t_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_2D_kf_t_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_2D_kf_t_data_element_struct)); + + for (index = 0; index < storage->temp_2D_kf_t_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_2D_kf_t_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_2D_kf_t_data.elements[index].index_2; + temporary_storage.elements[index].index_3 = storage->temp_2D_kf_t_data.elements[index].index_3; + temporary_storage.elements[index].weight = storage->temp_2D_kf_t_data.elements[index].weight; + } + + // free current data + free (storage->temp_2D_kf_t_data.elements); + + // allocate larger array (10 larger) + storage->temp_2D_kf_t_data.allocated_elements = 10 + storage->temp_2D_kf_t_data.num_elements; + storage->temp_2D_kf_t_data.elements = malloc (storage->temp_2D_kf_t_data.allocated_elements * sizeof (struct temp_2D_kf_t_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_2D_kf_t_data.num_elements; index++) { + storage->temp_2D_kf_t_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_2D_kf_t_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_2D_kf_t_data.elements[index].index_3 = temporary_storage.elements[index].index_3; + storage->temp_2D_kf_t_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_1 = k; + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_2 = i; + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_3 = j; + storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_1 = k; - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_2 = i; - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements].index_3 = j; - storage->temp_2D_kf_t_data.elements[storage->temp_2D_kf_t_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_2D_kf_t_data.num_elements == 1) + add_to_logger_with_data (logger_with_data_array, logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_2D_kf_t_data.num_elements == 1) - add_to_logger_with_data(logger_with_data_array,logger); - } } - -} - -// clear_temp -void clear_temp_2D_kf_t(union logger_data_union *data_union) { - data_union->p_2D_kf_t_storage->temp_2D_kf_t_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_2D_kf_t(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_2D_kf_t_storage_struct *storage; - storage = logger->data_union.p_2D_kf_t_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_2D_kf_t (union logger_data_union* data_union) { + data_union->p_2D_kf_t_storage->temp_2D_kf_t_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double p1,p2; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - p1 = k_new[storage->dim_1_choice]; - p2 = k_new[storage->dim_2_choice]; - - int i,j,k; - - // Find bin in histogram - if (p1>storage->Detector_3D.D1min && p1Detector_3D.D1max && p2>storage->Detector_3D.D2min && p2Detector_3D.D2max && time>storage->Detector_3D.D3min && timeDetector_3D.D3max) { - i = floor((p1 - storage->Detector_3D.D1min)*storage->Detector_3D.bins_1/(storage->Detector_3D.D1max - storage->Detector_3D.D1min)); - j = floor((p2 - storage->Detector_3D.D2min)*storage->Detector_3D.bins_2/(storage->Detector_3D.D2max - storage->Detector_3D.D2min)); - k = floor((time - storage->Detector_3D.D3min)*storage->Detector_3D.bins_3/(storage->Detector_3D.D3max - storage->Detector_3D.D3min)); - - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - // because of the order in which the elements are laid out in memory, the k index must be first. - storage->Detector_3D.Array_N[k][i][j]++; - storage->Detector_3D.Array_p[k][i][j] += p; - storage->Detector_3D.Array_p2[k][i][j] += p*p; + // record_to_perm + void + record_to_perm_2D_kf_t (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_2D_kf_t_storage_struct* storage; + storage = logger->data_union.p_2D_kf_t_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double p1, p2; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + p1 = k_new[storage->dim_1_choice]; + p2 = k_new[storage->dim_2_choice]; + + int i, j, k; + + // Find bin in histogram + if (p1 > storage->Detector_3D.D1min && p1 < storage->Detector_3D.D1max && p2 > storage->Detector_3D.D2min && p2 < storage->Detector_3D.D2max + && time > storage->Detector_3D.D3min && time < storage->Detector_3D.D3max) { + i = floor ((p1 - storage->Detector_3D.D1min) * storage->Detector_3D.bins_1 / (storage->Detector_3D.D1max - storage->Detector_3D.D1min)); + j = floor ((p2 - storage->Detector_3D.D2min) * storage->Detector_3D.bins_2 / (storage->Detector_3D.D2max - storage->Detector_3D.D2min)); + k = floor ((time - storage->Detector_3D.D3min) * storage->Detector_3D.bins_3 / (storage->Detector_3D.D3max - storage->Detector_3D.D3min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + // because of the order in which the elements are laid out in memory, the k index must be first. + storage->Detector_3D.Array_N[k][i][j]++; + storage->Detector_3D.Array_p[k][i][j] += p; + storage->Detector_3D.Array_p2[k][i][j] += p * p; + } } } -} + // write_temp_to_perm + void + write_temp_to_perm_2D_kf_t (union logger_data_union* data_union) { + + struct a_2D_kf_t_storage_struct* storage; + storage = data_union->p_2D_kf_t_storage; -// write_temp_to_perm -void write_temp_to_perm_2D_kf_t(union logger_data_union *data_union) { + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2D_kf_t_data.num_elements; index++) { + storage->Detector_3D.Array_N[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2] + [storage->temp_2D_kf_t_data.elements[index].index_3]++; - struct a_2D_kf_t_storage_struct *storage; - storage = data_union->p_2D_kf_t_storage; + storage->Detector_3D.Array_p[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2] + [storage->temp_2D_kf_t_data.elements[index].index_3] + += storage->temp_2D_kf_t_data.elements[index].weight; - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2D_kf_t_data.num_elements;index++) { - storage->Detector_3D.Array_N[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2][storage->temp_2D_kf_t_data.elements[index].index_3]++; - - storage->Detector_3D.Array_p[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2][storage->temp_2D_kf_t_data.elements[index].index_3] += storage->temp_2D_kf_t_data.elements[index].weight; - - storage->Detector_3D.Array_p2[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2][storage->temp_2D_kf_t_data.elements[index].index_3] += storage->temp_2D_kf_t_data.elements[index].weight*storage->temp_2D_kf_t_data.elements[index].weight; + storage->Detector_3D.Array_p2[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2] + [storage->temp_2D_kf_t_data.elements[index].index_3] + += storage->temp_2D_kf_t_data.elements[index].weight * storage->temp_2D_kf_t_data.elements[index].weight; + } + clear_temp_2D_kf_t (data_union); } - clear_temp_2D_kf_t(data_union); -} - -// write_temp_to_perm -void write_temp_to_perm_final_p_2D_kf_t(union logger_data_union *data_union, double final_weight) { - - struct a_2D_kf_t_storage_struct *storage; - storage = data_union->p_2D_kf_t_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2D_kf_t_data.num_elements;index++) { - storage->Detector_3D.Array_N[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2][storage->temp_2D_kf_t_data.elements[index].index_3]++; - - storage->Detector_3D.Array_p[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2][storage->temp_2D_kf_t_data.elements[index].index_3] += final_weight; - - storage->Detector_3D.Array_p2[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2][storage->temp_2D_kf_t_data.elements[index].index_3] += final_weight*final_weight; + + // write_temp_to_perm + void + write_temp_to_perm_final_p_2D_kf_t (union logger_data_union* data_union, double final_weight) { + + struct a_2D_kf_t_storage_struct* storage; + storage = data_union->p_2D_kf_t_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2D_kf_t_data.num_elements; index++) { + storage->Detector_3D.Array_N[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2] + [storage->temp_2D_kf_t_data.elements[index].index_3]++; + + storage->Detector_3D.Array_p[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2] + [storage->temp_2D_kf_t_data.elements[index].index_3] + += final_weight; + + storage->Detector_3D.Array_p2[storage->temp_2D_kf_t_data.elements[index].index_1][storage->temp_2D_kf_t_data.elements[index].index_2] + [storage->temp_2D_kf_t_data.elements[index].index_3] + += final_weight * final_weight; + } + clear_temp_2D_kf_t (data_union); } - clear_temp_2D_kf_t(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_LOGGER -#define UNION_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_LOGGER + #define UNION_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { + void + manual_linking_function_logger_processes (char* input_string, struct physics_struct* p_physics, struct pointer_to_1d_int_list* accepted_processes, + char* component_name, char* Volume_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) { - if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes,loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) { + if (strcmp (token, p_physics->p_scattering_array[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == p_physics->number_of_processes - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) - printf(" %s\n",p_physics->p_scattering_array[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume " + "\"%s\". \n", + input_string, component_name, Volume_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n", p_physics->name, Volume_name); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) + printf (" %s\n", p_physics->p_scattering_array[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif - -double*** allocate3Ddouble_2D_kf_t(int count_x, int count_y, int count_z, double *storage) { - //double *storage = malloc(count_x * count_y * count_z * sizeof(double)); - storage = malloc(count_x * count_y * count_z * sizeof(double)); - double *alloc = storage; - double ***x; - int i,j; - x = malloc(count_x * sizeof(*x)); - for (i = 0; i < count_x; i++) { - x[i] = malloc(count_y * sizeof(**x)); - for (j = 0; j < count_y; j++) { - x[i][j] = alloc; - alloc += count_z; - } - } - return x; - } - -void free3Ddouble_2D_kf_t(double*** ptr_array, int count_x, double *storage) { - if (!ptr_array) return; - int x; - - free(storage); - for (x=0;x= Q1_max) { - printf("ERROR, Union logger \"%s\" had Q1_min >= Q1_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had Q1_min >= Q1_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D1min = Q1_min; this_storage.Detector_3D.D1max = Q1_max; - + if (Q2_min >= Q2_max) { - printf("ERROR, Union logger \"%s\" had Q2_min >= Q2_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had Q2_min >= Q2_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D2min = Q2_min; this_storage.Detector_3D.D2max = Q2_max; - + if (time_min >= time_max) { - printf("ERROR, Union logger \"%s\" had time_min >= time_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had time_min >= time_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D3min = time_min; this_storage.Detector_3D.D3max = time_max; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_1 = n1; - + if (n2 <= 0) { - printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n2 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_2 = n2; - + if (time_bins <= 0) { - printf("ERROR, Union logger \"%s\" had time_bins <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had time_bins <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_3 = time_bins; - - //printf("past input sanitation \n"); - - - printf("Allocating 3D arrays \n"); + + // printf("past input sanitation \n"); + + printf ("Allocating 3D arrays \n"); // Remember to take special care when deallocating this array, use free3Ddouble - + /* this_storage.Detector_3D.Array_N = allocate3Ddouble_2D_kf_t(n1,n2,time_bins); // Here the n1 double is cast to an int this_storage.Detector_3D.Array_p = allocate3Ddouble_2D_kf_t(n1,n2,time_bins); this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2D_kf_t(n1,n2,time_bins); */ // D3 is in poisition 1, because that gives continous memory in XY plane for easy plotting - - - this_storage.Detector_3D.Array_N = allocate3Ddouble_2D_kf_t(time_bins,n1,n2, storage_N); // Here the n1 double is cast to an int - this_storage.Detector_3D.Array_p = allocate3Ddouble_2D_kf_t(time_bins,n1,n2, storage_p); - this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2D_kf_t(time_bins,n1,n2, storage_2p); - + + this_storage.Detector_3D.Array_N = allocate3Ddouble_2D_kf_t (time_bins, n1, n2, storage_N); // Here the n1 double is cast to an int + this_storage.Detector_3D.Array_p = allocate3Ddouble_2D_kf_t (time_bins, n1, n2, storage_p); + this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2D_kf_t (time_bins, n1, n2, storage_2p); + /* // Error in the order? this_storage.Detector_3D.Array_N = allocate3Ddouble_2D_kf_t(n1,time_bins,n2); // Here the n1 double is cast to an int this_storage.Detector_3D.Array_p = allocate3Ddouble_2D_kf_t(n1,time_bins,n2); this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2D_kf_t(n1,time_bins,n2); */ - - int l1,l2,l3; - //printf("Allocated 3D arrays \n"); - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its logger list - add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); - - if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { + add_initialized_logger_in_volume (&target_volume->loggers, target_volume->p_physics->number_of_processes); + + if (target_process && strlen (target_process) && strcmp (target_process, "NULL") && strcmp (target_process, "0")) { // Unused process pointers should point to NULL - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = NULL; } // A target_process was set, find it within the volume structure (can be many processes) - manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); - for (process_index=0;process_indexp_physics, &accepted_processes, NAME_CURRENT_COMP, target_volume->name); + for (process_index = 0; process_index < accepted_processes.num_elements; process_index++) { // Add pointer to this logger for all the accepted processes in this newly added loggers element - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[accepted_processes.elements[process_index]] + = &this_logger; } } else { // No target_process was set, attatch the logger to all processes - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = &this_logger; } } } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - add_element_to_logger_list(global_all_volume_logger_list,logger_list_element); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + add_element_to_logger_list (global_all_volume_logger_list, logger_list_element); } - - %} TRACE @@ -691,37 +706,33 @@ TRACE SAVE %{ -// Write to disk - -for (loop_index=0;loop_index0) free(this_storage.temp_2D_kf_t_data.elements); - -free3Ddouble_2D_kf_t(this_storage.Detector_3D.Array_N,time_bins, storage_N); -free3Ddouble_2D_kf_t(this_storage.Detector_3D.Array_p,time_bins, storage_p); -free3Ddouble_2D_kf_t(this_storage.Detector_3D.Array_p2,time_bins, storage_2p); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_storage.temp_2D_kf_t_data.allocated_elements > 0) + free (this_storage.temp_2D_kf_t_data.elements); + + free3Ddouble_2D_kf_t (this_storage.Detector_3D.Array_N, time_bins, storage_N); + free3Ddouble_2D_kf_t (this_storage.Detector_3D.Array_p, time_bins, storage_p); + free3Ddouble_2D_kf_t (this_storage.Detector_3D.Array_p2, time_bins, storage_2p); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_logger_2D_space.comp b/mcstas-comps/union/Union_logger_2D_space.comp index ed25e52455..eabd95406f 100644 --- a/mcstas-comps/union/Union_logger_2D_space.comp +++ b/mcstas-comps/union/Union_logger_2D_space.comp @@ -84,402 +84,419 @@ SETTING PARAMETERS(string target_geometry="NULL", string target_process="NULL", SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_logger_2D_space component" -#endif - -struct temp_2DS_data_element_struct { - int index_1; - int index_2; - double weight; -}; - -struct temp_2DS_data_struct { - int num_elements; - int allocated_elements; - struct temp_2DS_data_element_struct *elements; -}; - -struct a_2DS_storage_struct { - struct Detector_2D_struct Detector_2D; - struct temp_2DS_data_struct temp_2DS_data; - int dim_1_choice; - int dim_2_choice; - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_2DS(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - struct a_2DS_storage_struct *storage; - storage = logger->data_union.p_2DS_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_logger_2D_space component" + #endif + + struct temp_2DS_data_element_struct { + int index_1; + int index_2; + double weight; + }; + + struct temp_2DS_data_struct { + int num_elements; + int allocated_elements; + struct temp_2DS_data_element_struct* elements; + }; + + struct a_2DS_storage_struct { + struct Detector_2D_struct Detector_2D; + struct temp_2DS_data_struct temp_2DS_data; + int dim_1_choice; + int dim_2_choice; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_2DS (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + struct a_2DS_storage_struct* storage; + storage = logger->data_union.p_2DS_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - double p1,p2; - p1=p2=0; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - if (storage->dim_1_choice == 0) - p1 = position->x - storage->position.x; - else if (storage->dim_1_choice == 1) - p1 = position->y - storage->position.y; - else if (storage->dim_1_choice == 2) - p1 = position->z - storage->position.z; - - if (storage->dim_2_choice == 0) - p2 = position->x - storage->position.x; - else if (storage->dim_2_choice == 1) - p2 = position->y - storage->position.y; - else if (storage->dim_2_choice == 2) - p2 = position->z - storage->position.z; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - i = floor((p1 - storage->Detector_2D.D1min)*storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_2DS_data.num_elements,storage->temp_2DS_data.allocated_elements); - - if (storage->temp_2DS_data.num_elements < storage->temp_2DS_data.allocated_elements) { - storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_1 = i; - storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_2 = j; - storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_2DS_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_2DS_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_2DS_data_element_struct)); - - for (index=0;indextemp_2DS_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_2DS_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_2DS_data.elements[index].index_2; - temporary_storage.elements[index].weight = storage->temp_2DS_data.elements[index].weight; - } - - // free current data - free(storage->temp_2DS_data.elements); - - // allocate larger array (10 larger) - storage->temp_2DS_data.allocated_elements = 10 + storage->temp_2DS_data.num_elements; - storage->temp_2DS_data.elements = malloc(storage->temp_2DS_data.allocated_elements*sizeof(struct temp_2DS_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_2DS_data.num_elements;index++) { - storage->temp_2DS_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_2DS_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_2DS_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double p1, p2; + p1 = p2 = 0; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + if (storage->dim_1_choice == 0) + p1 = position->x - storage->position.x; + else if (storage->dim_1_choice == 1) + p1 = position->y - storage->position.y; + else if (storage->dim_1_choice == 2) + p1 = position->z - storage->position.z; + + if (storage->dim_2_choice == 0) + p2 = position->x - storage->position.x; + else if (storage->dim_2_choice == 1) + p2 = position->y - storage->position.y; + else if (storage->dim_2_choice == 2) + p2 = position->z - storage->position.z; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + i = floor ((p1 - storage->Detector_2D.D1min) * storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_2DS_data.num_elements,storage->temp_2DS_data.allocated_elements); + + if (storage->temp_2DS_data.num_elements < storage->temp_2DS_data.allocated_elements) { + storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_1 = i; + storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_2 = j; + storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_2DS_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_2DS_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_2DS_data_element_struct)); + + for (index = 0; index < storage->temp_2DS_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_2DS_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_2DS_data.elements[index].index_2; + temporary_storage.elements[index].weight = storage->temp_2DS_data.elements[index].weight; + } + + // free current data + free (storage->temp_2DS_data.elements); + + // allocate larger array (10 larger) + storage->temp_2DS_data.allocated_elements = 10 + storage->temp_2DS_data.num_elements; + storage->temp_2DS_data.elements = malloc (storage->temp_2DS_data.allocated_elements * sizeof (struct temp_2DS_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_2DS_data.num_elements; index++) { + storage->temp_2DS_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_2DS_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_2DS_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_1 = i; + storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_2 = j; + storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_1 = i; - storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements].index_2 = j; - storage->temp_2DS_data.elements[storage->temp_2DS_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_2DS_data.num_elements == 1) + add_to_logger_with_data (logger_with_data_array, logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_2DS_data.num_elements == 1) - add_to_logger_with_data(logger_with_data_array,logger); - } } - -} - -// clear_temp -void clear_temp_2DS(union logger_data_union *data_union) { - data_union->p_2DS_storage->temp_2DS_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_2DS(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_2DS_storage_struct *storage; - storage = logger->data_union.p_2DS_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_2DS (union logger_data_union* data_union) { + data_union->p_2DS_storage->temp_2DS_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double p1,p2; - p1=p2=0; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input "x" "y" "z". - if (storage->dim_1_choice == 0) - p1 = position->x - storage->position.x; - //p1 = position->x; - else if (storage->dim_1_choice == 1) - p1 = position->y - storage->position.y; - //p1 = position->y; - else if (storage->dim_1_choice == 2) - p1 = position->z - storage->position.z; - //p1 = position->z; - - if (storage->dim_2_choice == 0) - p2 = position->x - storage->position.x; - //p2 = position->x; - else if (storage->dim_2_choice == 1) - p2 = position->y - storage->position.y; - //p2 = position->y; - else if (storage->dim_2_choice == 2) - p2 = position->z - storage->position.z; - //p2 = position->z; - - int i,j; - - // Find bin in histogram - if (p1>storage->Detector_2D.D1min && p1Detector_2D.D1max && p2>storage->Detector_2D.D2min && p2Detector_2D.D2max) { - - i = floor((p1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); - j = floor((p2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - storage->Detector_2D.Array_N[i][j]++; - storage->Detector_2D.Array_p[i][j] += p; - storage->Detector_2D.Array_p2[i][j] += p*p; - + // record_to_perm + void + record_to_perm_2DS (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_2DS_storage_struct* storage; + storage = logger->data_union.p_2DS_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double p1, p2; + p1 = p2 = 0; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input "x" "y" "z". + if (storage->dim_1_choice == 0) + p1 = position->x - storage->position.x; + // p1 = position->x; + else if (storage->dim_1_choice == 1) + p1 = position->y - storage->position.y; + // p1 = position->y; + else if (storage->dim_1_choice == 2) + p1 = position->z - storage->position.z; + // p1 = position->z; + + if (storage->dim_2_choice == 0) + p2 = position->x - storage->position.x; + // p2 = position->x; + else if (storage->dim_2_choice == 1) + p2 = position->y - storage->position.y; + // p2 = position->y; + else if (storage->dim_2_choice == 2) + p2 = position->z - storage->position.z; + // p2 = position->z; + + int i, j; + + // Find bin in histogram + if (p1 > storage->Detector_2D.D1min && p1 < storage->Detector_2D.D1max && p2 > storage->Detector_2D.D2min && p2 < storage->Detector_2D.D2max) { + + i = floor ((p1 - storage->Detector_2D.D1min) * (double)storage->Detector_2D.bins_1 / (storage->Detector_2D.D1max - storage->Detector_2D.D1min)); + j = floor ((p2 - storage->Detector_2D.D2min) * (double)storage->Detector_2D.bins_2 / (storage->Detector_2D.D2max - storage->Detector_2D.D2min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + storage->Detector_2D.Array_N[i][j]++; + storage->Detector_2D.Array_p[i][j] += p; + storage->Detector_2D.Array_p2[i][j] += p * p; + } } } -} - -// write_temp_to_perm -void write_temp_to_perm_2DS(union logger_data_union *data_union) { - struct a_2DS_storage_struct *storage; - storage = data_union->p_2DS_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2DS_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] += storage->temp_2DS_data.elements[index].weight; - - storage->Detector_2D.Array_p2[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] += storage->temp_2DS_data.elements[index].weight*storage->temp_2DS_data.elements[index].weight; + // write_temp_to_perm + void + write_temp_to_perm_2DS (union logger_data_union* data_union) { + struct a_2DS_storage_struct* storage; + storage = data_union->p_2DS_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2DS_data.num_elements; index++) { + + storage->Detector_2D.Array_N[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] + += storage->temp_2DS_data.elements[index].weight; + + storage->Detector_2D.Array_p2[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] + += storage->temp_2DS_data.elements[index].weight * storage->temp_2DS_data.elements[index].weight; + } + + clear_temp_2DS (data_union); } - - clear_temp_2DS(data_union); -} - -// write_temp_to_perm_final_p -void write_temp_to_perm_final_p_2DS(union logger_data_union *data_union, double final_weight) { - struct a_2DS_storage_struct *storage; - storage = data_union->p_2DS_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2DS_data.num_elements;index++) { - - storage->Detector_2D.Array_N[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2]++; - - storage->Detector_2D.Array_p[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] += final_weight; - - storage->Detector_2D.Array_p2[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] += final_weight*final_weight; + + // write_temp_to_perm_final_p + void + write_temp_to_perm_final_p_2DS (union logger_data_union* data_union, double final_weight) { + struct a_2DS_storage_struct* storage; + storage = data_union->p_2DS_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2DS_data.num_elements; index++) { + + storage->Detector_2D.Array_N[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2]++; + + storage->Detector_2D.Array_p[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] += final_weight; + + storage->Detector_2D.Array_p2[storage->temp_2DS_data.elements[index].index_1][storage->temp_2DS_data.elements[index].index_2] + += final_weight * final_weight; + } + + clear_temp_2DS (data_union); } - - clear_temp_2DS(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_LOGGER -#define UNION_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_LOGGER + #define UNION_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { + void + manual_linking_function_logger_processes (char* input_string, struct physics_struct* p_physics, struct pointer_to_1d_int_list* accepted_processes, + char* component_name, char* Volume_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) { - if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes,loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) { + if (strcmp (token, p_physics->p_scattering_array[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == p_physics->number_of_processes - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) - printf(" %s\n",p_physics->p_scattering_array[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume " + "\"%s\". \n", + input_string, component_name, Volume_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n", p_physics->name, Volume_name); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) + printf (" %s\n", p_physics->p_scattering_array[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif + token = strtok (NULL, ","); + } + } + #endif -double** allocate2Ddouble_2DS(int count_x, int count_y) { + double** + allocate2Ddouble_2DS (int count_x, int count_y) { // This function is needed to dynamically declare an array // that has continous data as a static array would have, // as that is the format expected by DETECTOR_OUT_2D. int i; // allocate space for actual data - double *data = malloc(sizeof(double) * count_x * count_y); + double* data = malloc (sizeof (double) * count_x * count_y); // create array or pointers to first elem in each 2D row - double **ptr_array = malloc(sizeof(double*) * count_x); - if (data == NULL || ptr_array == NULL){ - free(data); - free(ptr_array); - printf("\nERROR: ptr array or data not allocated in Union_logger_2D_space\n"); - exit(1); + double** ptr_array = malloc (sizeof (double*) * count_x); + if (data == NULL || ptr_array == NULL) { + free (data); + free (ptr_array); + printf ("\nERROR: ptr array or data not allocated in Union_logger_2D_space\n"); + exit (1); } for (i = 0; i < count_x; i++) { - ptr_array[i] = data + (i*count_y); + ptr_array[i] = data + (i * count_y); } return ptr_array; -} - -void free2Ddouble_2DS(double** ptr_array) { - if (!ptr_array) return; - if (ptr_array[0]) free(ptr_array[0]); - free(ptr_array); -} + } + void + free2Ddouble_2DS (double** ptr_array) { + if (!ptr_array) + return; + if (ptr_array[0]) + free (ptr_array[0]); + free (ptr_array); + } %} DECLARE %{ -// From make material -// Needed for transport to the main component -//struct global_material_element_struct global_material_element; -//struct physics_struct this_material; + // From make material + // Needed for transport to the main component + // struct global_material_element_struct global_material_element; + // struct physics_struct this_material; -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Reused for logger -struct pointer_to_1d_int_list accepted_processes; + // Reused for logger + struct pointer_to_1d_int_list accepted_processes; -struct global_logger_element_struct logger_list_element; + struct global_logger_element_struct logger_list_element; -struct pointer_to_1d_int_list accepted_volumes; + struct pointer_to_1d_int_list accepted_volumes; -struct logger_struct this_logger; -struct a_2DS_storage_struct this_storage; + struct logger_struct this_logger; + struct a_2DS_storage_struct this_storage; -struct loggers_struct *loggers_on_target_volume; -struct Volume_struct *target_volume; + struct loggers_struct* loggers_on_target_volume; + struct Volume_struct* target_volume; %} INITIALIZE @@ -487,130 +504,126 @@ INITIALIZE accepted_processes.elements = NULL; accepted_processes.num_elements = 0; - + accepted_volumes.elements = NULL; accepted_volumes.num_elements = 0; // Initialize storage from input if (D1_min >= D1_max) { - printf("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.D1min = D1_min; this_storage.Detector_2D.D1max = D1_max; - + if (D2_min >= D2_max) { - printf("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.D2min = D2_min; this_storage.Detector_2D.D2max = D2_max; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.bins_1 = n1; - + if (n2 <= 0) { - printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n2 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_2D.bins_2 = n2; - - //printf("past input sanitation \n"); - - + + // printf("past input sanitation \n"); + // Remember to take special care when deallocating this array, use free2Ddouble - this_storage.Detector_2D.Array_N = allocate2Ddouble_2DS(n1,n2); // Here the n1 double is cast to an int - this_storage.Detector_2D.Array_p = allocate2Ddouble_2DS(n1,n2); - this_storage.Detector_2D.Array_p2 = allocate2Ddouble_2DS(n1,n2); - - int l1,l2; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its logger list - add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); - - if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { + add_initialized_logger_in_volume (&target_volume->loggers, target_volume->p_physics->number_of_processes); + + if (target_process && strlen (target_process) && strcmp (target_process, "NULL") && strcmp (target_process, "0")) { // Unused process pointers should point to NULL - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = NULL; } // A target_process was set, find it within the volume structure (can be many processes) - manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); - for (process_index=0;process_indexp_physics, &accepted_processes, NAME_CURRENT_COMP, target_volume->name); + for (process_index = 0; process_index < accepted_processes.num_elements; process_index++) { // Add pointer to this logger for all the accepted processes in this newly added loggers element - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[accepted_processes.elements[process_index]] + = &this_logger; } } else { // No target_process was set, attatch the logger to all processes - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = &this_logger; } } } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - add_element_to_logger_list(global_all_volume_logger_list,logger_list_element); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + add_element_to_logger_list (global_all_volume_logger_list, logger_list_element); } - - %} TRACE @@ -689,31 +700,27 @@ TRACE SAVE %{ -// Write to disk -DETECTOR_OUT_2D( - this_storage.Detector_2D.title_string, - this_storage.Detector_2D.string_axis_1, - this_storage.Detector_2D.string_axis_2, - this_storage.Detector_2D.D1min, this_storage.Detector_2D.D1max, - this_storage.Detector_2D.D2min, this_storage.Detector_2D.D2max, - this_storage.Detector_2D.bins_1, this_storage.Detector_2D.bins_2, - *this_storage.Detector_2D.Array_N, *this_storage.Detector_2D.Array_p, *this_storage.Detector_2D.Array_p2, - this_storage.Detector_2D.Filename); - + // Write to disk + DETECTOR_OUT_2D (this_storage.Detector_2D.title_string, this_storage.Detector_2D.string_axis_1, this_storage.Detector_2D.string_axis_2, + this_storage.Detector_2D.D1min, this_storage.Detector_2D.D1max, this_storage.Detector_2D.D2min, this_storage.Detector_2D.D2max, + this_storage.Detector_2D.bins_1, this_storage.Detector_2D.bins_2, *this_storage.Detector_2D.Array_N, *this_storage.Detector_2D.Array_p, + *this_storage.Detector_2D.Array_p2, this_storage.Detector_2D.Filename); %} FINALLY %{ -// Remember to clean up allocated lists -if (this_storage.temp_2DS_data.allocated_elements>0) free(this_storage.temp_2DS_data.elements); - -free2Ddouble_2DS(this_storage.Detector_2D.Array_N); -free2Ddouble_2DS(this_storage.Detector_2D.Array_p); -free2Ddouble_2DS(this_storage.Detector_2D.Array_p2); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_storage.temp_2DS_data.allocated_elements > 0) + free (this_storage.temp_2DS_data.elements); + + free2Ddouble_2DS (this_storage.Detector_2D.Array_N); + free2Ddouble_2DS (this_storage.Detector_2D.Array_p); + free2Ddouble_2DS (this_storage.Detector_2D.Array_p2); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_logger_2D_space_time.comp b/mcstas-comps/union/Union_logger_2D_space_time.comp index 5d998d8ff6..a206d578b2 100644 --- a/mcstas-comps/union/Union_logger_2D_space_time.comp +++ b/mcstas-comps/union/Union_logger_2D_space_time.comp @@ -84,418 +84,440 @@ SETTING PARAMETERS(string target_geometry="NULL",string target_process="NULL",D1 SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_logger_2D_space_time component" -#endif - -struct temp_2DS_t_data_element_struct { - int index_1; - int index_2; - int index_3; - double weight; -}; - -struct temp_2DS_t_data_struct { - int num_elements; - int allocated_elements; - struct temp_2DS_t_data_element_struct *elements; -}; - -struct a_2DS_t_storage_struct { - struct Detector_3D_struct Detector_3D; - struct temp_2DS_t_data_struct temp_2DS_t_data; - int dim_1_choice; - int dim_2_choice; - int dim_3_choice; - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_2DS_t(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - struct a_2DS_t_storage_struct *storage; - storage = logger->data_union.p_2DS_t_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_logger_2D_space_time component" + #endif + + struct temp_2DS_t_data_element_struct { + int index_1; + int index_2; + int index_3; + double weight; + }; + + struct temp_2DS_t_data_struct { + int num_elements; + int allocated_elements; + struct temp_2DS_t_data_element_struct* elements; + }; + + struct a_2DS_t_storage_struct { + struct Detector_3D_struct Detector_3D; + struct temp_2DS_t_data_struct temp_2DS_t_data; + int dim_1_choice; + int dim_2_choice; + int dim_3_choice; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_2DS_t (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + struct a_2DS_t_storage_struct* storage; + storage = logger->data_union.p_2DS_t_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - double p1,p2; - p1=p2=0; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - if (storage->dim_1_choice == 0) - p1 = position->x - storage->position.x; - else if (storage->dim_1_choice == 1) - p1 = position->y - storage->position.y; - else if (storage->dim_1_choice == 2) - p1 = position->z - storage->position.z; - - if (storage->dim_2_choice == 0) - p2 = position->x - storage->position.x; - else if (storage->dim_2_choice == 1) - p2 = position->y - storage->position.y; - else if (storage->dim_2_choice == 2) - p2 = position->z - storage->position.z; - - int i,j,k; - - // Find bin in histogram - if (p1>storage->Detector_3D.D1min && p1Detector_3D.D1max && p2>storage->Detector_3D.D2min && p2Detector_3D.D2max && time>storage->Detector_3D.D3min && timeDetector_3D.D3max) { - i = floor((p1 - storage->Detector_3D.D1min)*storage->Detector_3D.bins_1/(storage->Detector_3D.D1max - storage->Detector_3D.D1min)); - j = floor((p2 - storage->Detector_3D.D2min)*storage->Detector_3D.bins_2/(storage->Detector_3D.D2max - storage->Detector_3D.D2min)); - k = floor((time - storage->Detector_3D.D3min)*storage->Detector_3D.bins_3/(storage->Detector_3D.D3max - storage->Detector_3D.D3min)); - - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_2DS_t_data.num_elements,storage->temp_2DS_t_data.allocated_elements); - - if (storage->temp_2DS_t_data.num_elements < storage->temp_2DS_t_data.allocated_elements) { - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_1 = k; - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_2 = i; - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_3 = j; - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_2DS_t_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_2DS_t_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_2DS_t_data_element_struct)); - - for (index=0;indextemp_2DS_t_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_2DS_t_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_2DS_t_data.elements[index].index_2; - temporary_storage.elements[index].index_3 = storage->temp_2DS_t_data.elements[index].index_3; - temporary_storage.elements[index].weight = storage->temp_2DS_t_data.elements[index].weight; - } - - // free current data - free(storage->temp_2DS_t_data.elements); - - // allocate larger array (10 larger) - storage->temp_2DS_t_data.allocated_elements = 10 + storage->temp_2DS_t_data.num_elements; - storage->temp_2DS_t_data.elements = malloc(storage->temp_2DS_t_data.allocated_elements*sizeof(struct temp_2DS_t_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_2DS_t_data.num_elements;index++) { - storage->temp_2DS_t_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_2DS_t_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_2DS_t_data.elements[index].index_3 = temporary_storage.elements[index].index_3; - storage->temp_2DS_t_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double p1, p2; + p1 = p2 = 0; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + if (storage->dim_1_choice == 0) + p1 = position->x - storage->position.x; + else if (storage->dim_1_choice == 1) + p1 = position->y - storage->position.y; + else if (storage->dim_1_choice == 2) + p1 = position->z - storage->position.z; + + if (storage->dim_2_choice == 0) + p2 = position->x - storage->position.x; + else if (storage->dim_2_choice == 1) + p2 = position->y - storage->position.y; + else if (storage->dim_2_choice == 2) + p2 = position->z - storage->position.z; + + int i, j, k; + + // Find bin in histogram + if (p1 > storage->Detector_3D.D1min && p1 < storage->Detector_3D.D1max && p2 > storage->Detector_3D.D2min && p2 < storage->Detector_3D.D2max + && time > storage->Detector_3D.D3min && time < storage->Detector_3D.D3max) { + i = floor ((p1 - storage->Detector_3D.D1min) * storage->Detector_3D.bins_1 / (storage->Detector_3D.D1max - storage->Detector_3D.D1min)); + j = floor ((p2 - storage->Detector_3D.D2min) * storage->Detector_3D.bins_2 / (storage->Detector_3D.D2max - storage->Detector_3D.D2min)); + k = floor ((time - storage->Detector_3D.D3min) * storage->Detector_3D.bins_3 / (storage->Detector_3D.D3max - storage->Detector_3D.D3min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_2DS_t_data.num_elements,storage->temp_2DS_t_data.allocated_elements); + + if (storage->temp_2DS_t_data.num_elements < storage->temp_2DS_t_data.allocated_elements) { + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_1 = k; + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_2 = i; + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_3 = j; + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_2DS_t_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_2DS_t_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_2DS_t_data_element_struct)); + + for (index = 0; index < storage->temp_2DS_t_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_2DS_t_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_2DS_t_data.elements[index].index_2; + temporary_storage.elements[index].index_3 = storage->temp_2DS_t_data.elements[index].index_3; + temporary_storage.elements[index].weight = storage->temp_2DS_t_data.elements[index].weight; + } + + // free current data + free (storage->temp_2DS_t_data.elements); + + // allocate larger array (10 larger) + storage->temp_2DS_t_data.allocated_elements = 10 + storage->temp_2DS_t_data.num_elements; + storage->temp_2DS_t_data.elements = malloc (storage->temp_2DS_t_data.allocated_elements * sizeof (struct temp_2DS_t_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_2DS_t_data.num_elements; index++) { + storage->temp_2DS_t_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_2DS_t_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_2DS_t_data.elements[index].index_3 = temporary_storage.elements[index].index_3; + storage->temp_2DS_t_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_1 = k; + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_2 = i; + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_3 = j; + storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_1 = k; - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_2 = i; - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements].index_3 = j; - storage->temp_2DS_t_data.elements[storage->temp_2DS_t_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_2DS_t_data.num_elements == 1) + add_to_logger_with_data (logger_with_data_array, logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_2DS_t_data.num_elements == 1) - add_to_logger_with_data(logger_with_data_array,logger); - } } - -} - -// clear_temp -void clear_temp_2DS_t(union logger_data_union *data_union) { - data_union->p_2DS_t_storage->temp_2DS_t_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_2DS_t(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_2DS_t_storage_struct *storage; - storage = logger->data_union.p_2DS_t_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_2DS_t (union logger_data_union* data_union) { + data_union->p_2DS_t_storage->temp_2DS_t_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double p1,p2; - p1=p2=0; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - if (storage->dim_1_choice == 0) - p1 = position->x - storage->position.x; - //p1 = position->x; - else if (storage->dim_1_choice == 1) - p1 = position->y - storage->position.y; - //p1 = position->y; - else if (storage->dim_1_choice == 2) - p1 = position->z - storage->position.z; - //p1 = position->z; - - if (storage->dim_2_choice == 0) - p2 = position->x - storage->position.x; - //p2 = position->x; - else if (storage->dim_2_choice == 1) - p2 = position->y - storage->position.y; - //p2 = position->y; - else if (storage->dim_2_choice == 2) - p2 = position->z - storage->position.z; - //p2 = position->z; - - - int i,j,k; - - // Find bin in histogram - if (p1>storage->Detector_3D.D1min && p1Detector_3D.D1max && p2>storage->Detector_3D.D2min && p2Detector_3D.D2max && time>storage->Detector_3D.D3min && timeDetector_3D.D3max) { - i = floor((p1 - storage->Detector_3D.D1min)*storage->Detector_3D.bins_1/(storage->Detector_3D.D1max - storage->Detector_3D.D1min)); - j = floor((p2 - storage->Detector_3D.D2min)*storage->Detector_3D.bins_2/(storage->Detector_3D.D2max - storage->Detector_3D.D2min)); - k = floor((time - storage->Detector_3D.D3min)*storage->Detector_3D.bins_3/(storage->Detector_3D.D3max - storage->Detector_3D.D3min)); - - - //printf("Added to statistics for monitor [%d] [%d] \n",i,j); - //printf("indicies found\n"); - - // because of the order in which the elements are laid out in memory, the k index must be first. - storage->Detector_3D.Array_N[k][i][j]++; - storage->Detector_3D.Array_p[k][i][j] += p; - storage->Detector_3D.Array_p2[k][i][j] += p*p; + // record_to_perm + void + record_to_perm_2DS_t (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_2DS_t_storage_struct* storage; + storage = logger->data_union.p_2DS_t_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double p1, p2; + p1 = p2 = 0; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + if (storage->dim_1_choice == 0) + p1 = position->x - storage->position.x; + // p1 = position->x; + else if (storage->dim_1_choice == 1) + p1 = position->y - storage->position.y; + // p1 = position->y; + else if (storage->dim_1_choice == 2) + p1 = position->z - storage->position.z; + // p1 = position->z; + + if (storage->dim_2_choice == 0) + p2 = position->x - storage->position.x; + // p2 = position->x; + else if (storage->dim_2_choice == 1) + p2 = position->y - storage->position.y; + // p2 = position->y; + else if (storage->dim_2_choice == 2) + p2 = position->z - storage->position.z; + // p2 = position->z; + + int i, j, k; + + // Find bin in histogram + if (p1 > storage->Detector_3D.D1min && p1 < storage->Detector_3D.D1max && p2 > storage->Detector_3D.D2min && p2 < storage->Detector_3D.D2max + && time > storage->Detector_3D.D3min && time < storage->Detector_3D.D3max) { + i = floor ((p1 - storage->Detector_3D.D1min) * storage->Detector_3D.bins_1 / (storage->Detector_3D.D1max - storage->Detector_3D.D1min)); + j = floor ((p2 - storage->Detector_3D.D2min) * storage->Detector_3D.bins_2 / (storage->Detector_3D.D2max - storage->Detector_3D.D2min)); + k = floor ((time - storage->Detector_3D.D3min) * storage->Detector_3D.bins_3 / (storage->Detector_3D.D3max - storage->Detector_3D.D3min)); + + // printf("Added to statistics for monitor [%d] [%d] \n",i,j); + // printf("indicies found\n"); + + // because of the order in which the elements are laid out in memory, the k index must be first. + storage->Detector_3D.Array_N[k][i][j]++; + storage->Detector_3D.Array_p[k][i][j] += p; + storage->Detector_3D.Array_p2[k][i][j] += p * p; + } } } -} + // write_temp_to_perm + void + write_temp_to_perm_2DS_t (union logger_data_union* data_union) { + + struct a_2DS_t_storage_struct* storage; + storage = data_union->p_2DS_t_storage; -// write_temp_to_perm -void write_temp_to_perm_2DS_t(union logger_data_union *data_union) { + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2DS_t_data.num_elements; index++) { + storage->Detector_3D.Array_N[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2] + [storage->temp_2DS_t_data.elements[index].index_3]++; - struct a_2DS_t_storage_struct *storage; - storage = data_union->p_2DS_t_storage; + storage->Detector_3D.Array_p[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2] + [storage->temp_2DS_t_data.elements[index].index_3] + += storage->temp_2DS_t_data.elements[index].weight; - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2DS_t_data.num_elements;index++) { - storage->Detector_3D.Array_N[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2][storage->temp_2DS_t_data.elements[index].index_3]++; - - storage->Detector_3D.Array_p[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2][storage->temp_2DS_t_data.elements[index].index_3] += storage->temp_2DS_t_data.elements[index].weight; - - storage->Detector_3D.Array_p2[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2][storage->temp_2DS_t_data.elements[index].index_3] += storage->temp_2DS_t_data.elements[index].weight*storage->temp_2DS_t_data.elements[index].weight; + storage->Detector_3D.Array_p2[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2] + [storage->temp_2DS_t_data.elements[index].index_3] + += storage->temp_2DS_t_data.elements[index].weight * storage->temp_2DS_t_data.elements[index].weight; + } + clear_temp_2DS_t (data_union); } - clear_temp_2DS_t(data_union); -} - -// write_temp_to_perm -void write_temp_to_perm_final_p_2DS_t(union logger_data_union *data_union, double final_weight) { - - struct a_2DS_t_storage_struct *storage; - storage = data_union->p_2DS_t_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_2DS_t_data.num_elements;index++) { - storage->Detector_3D.Array_N[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2][storage->temp_2DS_t_data.elements[index].index_3]++; - - storage->Detector_3D.Array_p[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2][storage->temp_2DS_t_data.elements[index].index_3] += final_weight; - - storage->Detector_3D.Array_p2[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2][storage->temp_2DS_t_data.elements[index].index_3] += final_weight; + + // write_temp_to_perm + void + write_temp_to_perm_final_p_2DS_t (union logger_data_union* data_union, double final_weight) { + + struct a_2DS_t_storage_struct* storage; + storage = data_union->p_2DS_t_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_2DS_t_data.num_elements; index++) { + storage->Detector_3D.Array_N[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2] + [storage->temp_2DS_t_data.elements[index].index_3]++; + + storage->Detector_3D.Array_p[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2] + [storage->temp_2DS_t_data.elements[index].index_3] + += final_weight; + + storage->Detector_3D.Array_p2[storage->temp_2DS_t_data.elements[index].index_1][storage->temp_2DS_t_data.elements[index].index_2] + [storage->temp_2DS_t_data.elements[index].index_3] + += final_weight; + } + clear_temp_2DS_t (data_union); } - clear_temp_2DS_t(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_LOGGER -#define UNION_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_LOGGER + #define UNION_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { + void + manual_linking_function_logger_processes (char* input_string, struct physics_struct* p_physics, struct pointer_to_1d_int_list* accepted_processes, + char* component_name, char* Volume_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) { - if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes,loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) { + if (strcmp (token, p_physics->p_scattering_array[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == p_physics->number_of_processes - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) - printf(" %s\n",p_physics->p_scattering_array[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume " + "\"%s\". \n", + input_string, component_name, Volume_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n", p_physics->name, Volume_name); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) + printf (" %s\n", p_physics->p_scattering_array[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif - -double*** allocate3Ddouble_2DS_t(int count_x, int count_y, int count_z, double *storage) { - //double *storage = malloc(count_x * count_y * count_z * sizeof(double)); - storage = malloc(count_x * count_y * count_z * sizeof(double)); - double *alloc = storage; - double ***x; - int i,j; - x = malloc(count_x * sizeof(*x)); - for (i = 0; i < count_x; i++) { - x[i] = malloc(count_y * sizeof(**x)); - for (j = 0; j < count_y; j++) { - x[i][j] = alloc; - alloc += count_z; - } - } - return x; - } - -void free3Ddouble_2DS_t(double*** ptr_array, int count_x, double *storage) { - if (!ptr_array) return; - int x; - - free(storage); - for (x=0;x= D1_max) { - printf("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D1min = D1_min; this_storage.Detector_3D.D1max = D1_max; - + if (D2_min >= D2_max) { - printf("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D2min = D2_min; this_storage.Detector_3D.D2max = D2_max; - + if (time_min >= time_max) { - printf("ERROR, Union logger \"%s\" had time_min >= time_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had time_min >= time_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D3min = time_min; this_storage.Detector_3D.D3max = time_max; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_1 = n1; - + if (n2 <= 0) { - printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n2 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_2 = n2; - + if (time_bins <= 0) { - printf("ERROR, Union logger \"%s\" had time_bins <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had time_bins <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_3 = time_bins; - - //printf("past input sanitation \n"); - - - printf("Allocating 3D arrays \n"); + + // printf("past input sanitation \n"); + + printf ("Allocating 3D arrays \n"); // Remember to take special care when deallocating this array, use free3Ddouble - + /* this_storage.Detector_3D.Array_N = allocate3Ddouble_2DS_t(n1,n2,time_bins); // Here the n1 double is cast to an int this_storage.Detector_3D.Array_p = allocate3Ddouble_2DS_t(n1,n2,time_bins); this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2DS_t(n1,n2,time_bins); */ // D3 is in poisition 1, because that gives continous memory in XY plane for easy plotting - - - this_storage.Detector_3D.Array_N = allocate3Ddouble_2DS_t(time_bins,n1,n2,storage_N); // Here the n1 double is cast to an int - this_storage.Detector_3D.Array_p = allocate3Ddouble_2DS_t(time_bins,n1,n2,storage_p); - this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2DS_t(time_bins,n1,n2,storage_2p); - + + this_storage.Detector_3D.Array_N = allocate3Ddouble_2DS_t (time_bins, n1, n2, storage_N); // Here the n1 double is cast to an int + this_storage.Detector_3D.Array_p = allocate3Ddouble_2DS_t (time_bins, n1, n2, storage_p); + this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2DS_t (time_bins, n1, n2, storage_2p); + /* // Error in the order? this_storage.Detector_3D.Array_N = allocate3Ddouble_2DS_t(n1,time_bins,n2); // Here the n1 double is cast to an int this_storage.Detector_3D.Array_p = allocate3Ddouble_2DS_t(n1,time_bins,n2); this_storage.Detector_3D.Array_p2 = allocate3Ddouble_2DS_t(n1,time_bins,n2); */ - - - //printf("Allocated 3D arrays \n"); - int l1,l2,l3; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its logger list - add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); - - if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { + add_initialized_logger_in_volume (&target_volume->loggers, target_volume->p_physics->number_of_processes); + + if (target_process && strlen (target_process) && strcmp (target_process, "NULL") && strcmp (target_process, "0")) { // Unused process pointers should point to NULL - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = NULL; } // A target_process was set, find it within the volume structure (can be many processes) - manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); - for (process_index=0;process_indexp_physics, &accepted_processes, NAME_CURRENT_COMP, target_volume->name); + for (process_index = 0; process_index < accepted_processes.num_elements; process_index++) { // Add pointer to this logger for all the accepted processes in this newly added loggers element - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[accepted_processes.elements[process_index]] + = &this_logger; } } else { // No target_process was set, attatch the logger to all processes - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = &this_logger; } } } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - add_element_to_logger_list(global_all_volume_logger_list,logger_list_element); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + add_element_to_logger_list (global_all_volume_logger_list, logger_list_element); } - - %} TRACE @@ -741,37 +753,33 @@ TRACE SAVE %{ -// Write to disk - -for (loop_index=0;loop_index0) free(this_storage.temp_2DS_t_data.elements); - -free3Ddouble_2DS_t(this_storage.Detector_3D.Array_N,time_bins,storage_N); -free3Ddouble_2DS_t(this_storage.Detector_3D.Array_p,time_bins,storage_p); -free3Ddouble_2DS_t(this_storage.Detector_3D.Array_p2,time_bins,storage_2p); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_storage.temp_2DS_t_data.allocated_elements > 0) + free (this_storage.temp_2DS_t_data.elements); + + free3Ddouble_2DS_t (this_storage.Detector_3D.Array_N, time_bins, storage_N); + free3Ddouble_2DS_t (this_storage.Detector_3D.Array_p, time_bins, storage_p); + free3Ddouble_2DS_t (this_storage.Detector_3D.Array_p2, time_bins, storage_2p); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_logger_3D_space.comp b/mcstas-comps/union/Union_logger_3D_space.comp index bbba6e89b6..e71df0acec 100644 --- a/mcstas-comps/union/Union_logger_3D_space.comp +++ b/mcstas-comps/union/Union_logger_3D_space.comp @@ -86,450 +86,473 @@ SETTING PARAMETERS(string target_geometry="NULL",string target_process="NULL",D1 SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_logger_3D_space component" -#endif - -struct temp_3DS_data_element_struct { - int index_1; - int index_2; - int index_3; - double weight; -}; - -struct temp_3DS_data_struct { - int num_elements; - int allocated_elements; - struct temp_3DS_data_element_struct *elements; -}; - -struct a_3DS_storage_struct { - struct Detector_3D_struct Detector_3D; - struct temp_3DS_data_struct temp_3DS_data; - int dim_1_choice; - int dim_2_choice; - int dim_3_choice; - int order; - int order_in_this_volume; - int order_process_in_this_volume; - - Coords position; - Rotation rotation; - Rotation t_rotation; -}; - -// record_to_temp -// Would be nice if x y z, k_new and k_old were all coords -void record_to_temp_3DS(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - struct a_3DS_storage_struct *storage; - storage = logger->data_union.p_3DS_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; - } + #ifndef Union + #error "The Union_init component must be included before this Union_logger_3D_space component" + #endif + + struct temp_3DS_data_element_struct { + int index_1; + int index_2; + int index_3; + double weight; + }; + + struct temp_3DS_data_struct { + int num_elements; + int allocated_elements; + struct temp_3DS_data_element_struct* elements; + }; + + struct a_3DS_storage_struct { + struct Detector_3D_struct Detector_3D; + struct temp_3DS_data_struct temp_3DS_data; + int dim_1_choice; + int dim_2_choice; + int dim_3_choice; + int order; + int order_in_this_volume; + int order_process_in_this_volume; + + Coords position; + Rotation rotation; + Rotation t_rotation; + }; + + // record_to_temp + // Would be nice if x y z, k_new and k_old were all coords + void + record_to_temp_3DS (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + struct a_3DS_storage_struct* storage; + storage = logger->data_union.p_3DS_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } - if (add_point == 1) { - - double p1,p2,p3; - p1=p2=p3=0; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - if (storage->dim_1_choice == 0) - p1 = position->x - storage->position.x; - else if (storage->dim_1_choice == 1) - p1 = position->y - storage->position.y; - else if (storage->dim_1_choice == 2) - p1 = position->z - storage->position.z; - - if (storage->dim_2_choice == 0) - p2 = position->x - storage->position.x; - else if (storage->dim_2_choice == 1) - p2 = position->y - storage->position.y; - else if (storage->dim_2_choice == 2) - p2 = position->z - storage->position.z; - - if (storage->dim_3_choice == 0) - p2 = position->x - storage->position.x; - else if (storage->dim_3_choice == 1) - p2 = position->y - storage->position.y; - else if (storage->dim_3_choice == 2) - p2 = position->z - storage->position.z; - - int i,j,k; - - // Find bin in histogram - if (p1>storage->Detector_3D.D1min && p1Detector_3D.D1max && p2>storage->Detector_3D.D2min && p2Detector_3D.D2max && p3>storage->Detector_3D.D3min && p3Detector_3D.D3max) { - i = floor((p1 - storage->Detector_3D.D1min)*storage->Detector_3D.bins_1/(storage->Detector_3D.D1max - storage->Detector_3D.D1min)); - j = floor((p2 - storage->Detector_3D.D2min)*storage->Detector_3D.bins_2/(storage->Detector_3D.D2max - storage->Detector_3D.D2min)); - k = floor((p3 - storage->Detector_3D.D3min)*storage->Detector_3D.bins_3/(storage->Detector_3D.D3max - storage->Detector_3D.D3min)); - - - // Save bin in histogram to temp (may need to allocate more memory) - int index; - //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_3DS_data.num_elements,storage->temp_3DS_data.allocated_elements); - - if (storage->temp_3DS_data.num_elements < storage->temp_3DS_data.allocated_elements) { - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_1 = k; - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_2 = i; - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_3 = j; - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements++].weight = p; - } else { - // No more space, need to allocate a larger buffer for this logger. Wish I had generics. - - // copy current data to temp - struct temp_3DS_data_struct temporary_storage; - temporary_storage.num_elements = storage->temp_3DS_data.num_elements; - temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_3DS_data_element_struct)); - - for (index=0;indextemp_3DS_data.num_elements;index++) { - temporary_storage.elements[index].index_1 = storage->temp_3DS_data.elements[index].index_1; - temporary_storage.elements[index].index_2 = storage->temp_3DS_data.elements[index].index_2; - temporary_storage.elements[index].index_3 = storage->temp_3DS_data.elements[index].index_3; - temporary_storage.elements[index].weight = storage->temp_3DS_data.elements[index].weight; - } - - // free current data - free(storage->temp_3DS_data.elements); - - // allocate larger array (10 larger) - storage->temp_3DS_data.allocated_elements = 10 + storage->temp_3DS_data.num_elements; - storage->temp_3DS_data.elements = malloc(storage->temp_3DS_data.allocated_elements*sizeof(struct temp_3DS_data_element_struct)); - - // copy back from temp - for (index=0;indextemp_3DS_data.num_elements;index++) { - storage->temp_3DS_data.elements[index].index_1 = temporary_storage.elements[index].index_1; - storage->temp_3DS_data.elements[index].index_2 = temporary_storage.elements[index].index_2; - storage->temp_3DS_data.elements[index].index_3 = temporary_storage.elements[index].index_3; - storage->temp_3DS_data.elements[index].weight = temporary_storage.elements[index].weight; + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + + double p1, p2, p3; + p1 = p2 = p3 = 0; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + if (storage->dim_1_choice == 0) + p1 = position->x - storage->position.x; + else if (storage->dim_1_choice == 1) + p1 = position->y - storage->position.y; + else if (storage->dim_1_choice == 2) + p1 = position->z - storage->position.z; + + if (storage->dim_2_choice == 0) + p2 = position->x - storage->position.x; + else if (storage->dim_2_choice == 1) + p2 = position->y - storage->position.y; + else if (storage->dim_2_choice == 2) + p2 = position->z - storage->position.z; + + if (storage->dim_3_choice == 0) + p2 = position->x - storage->position.x; + else if (storage->dim_3_choice == 1) + p2 = position->y - storage->position.y; + else if (storage->dim_3_choice == 2) + p2 = position->z - storage->position.z; + + int i, j, k; + + // Find bin in histogram + if (p1 > storage->Detector_3D.D1min && p1 < storage->Detector_3D.D1max && p2 > storage->Detector_3D.D2min && p2 < storage->Detector_3D.D2max + && p3 > storage->Detector_3D.D3min && p3 < storage->Detector_3D.D3max) { + i = floor ((p1 - storage->Detector_3D.D1min) * storage->Detector_3D.bins_1 / (storage->Detector_3D.D1max - storage->Detector_3D.D1min)); + j = floor ((p2 - storage->Detector_3D.D2min) * storage->Detector_3D.bins_2 / (storage->Detector_3D.D2max - storage->Detector_3D.D2min)); + k = floor ((p3 - storage->Detector_3D.D3min) * storage->Detector_3D.bins_3 / (storage->Detector_3D.D3max - storage->Detector_3D.D3min)); + + // Save bin in histogram to temp (may need to allocate more memory) + int index; + // printf("number of data points used: %d space allocated for %d data points. + // \n",storage->temp_3DS_data.num_elements,storage->temp_3DS_data.allocated_elements); + + if (storage->temp_3DS_data.num_elements < storage->temp_3DS_data.allocated_elements) { + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_1 = k; + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_2 = i; + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_3 = j; + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements++].weight = p; + } else { + // No more space, need to allocate a larger buffer for this logger. Wish I had generics. + + // copy current data to temp + struct temp_3DS_data_struct temporary_storage; + temporary_storage.num_elements = storage->temp_3DS_data.num_elements; + temporary_storage.elements = malloc (temporary_storage.num_elements * sizeof (struct temp_3DS_data_element_struct)); + + for (index = 0; index < storage->temp_3DS_data.num_elements; index++) { + temporary_storage.elements[index].index_1 = storage->temp_3DS_data.elements[index].index_1; + temporary_storage.elements[index].index_2 = storage->temp_3DS_data.elements[index].index_2; + temporary_storage.elements[index].index_3 = storage->temp_3DS_data.elements[index].index_3; + temporary_storage.elements[index].weight = storage->temp_3DS_data.elements[index].weight; + } + + // free current data + free (storage->temp_3DS_data.elements); + + // allocate larger array (10 larger) + storage->temp_3DS_data.allocated_elements = 10 + storage->temp_3DS_data.num_elements; + storage->temp_3DS_data.elements = malloc (storage->temp_3DS_data.allocated_elements * sizeof (struct temp_3DS_data_element_struct)); + + // copy back from temp + for (index = 0; index < storage->temp_3DS_data.num_elements; index++) { + storage->temp_3DS_data.elements[index].index_1 = temporary_storage.elements[index].index_1; + storage->temp_3DS_data.elements[index].index_2 = temporary_storage.elements[index].index_2; + storage->temp_3DS_data.elements[index].index_3 = temporary_storage.elements[index].index_3; + storage->temp_3DS_data.elements[index].weight = temporary_storage.elements[index].weight; + } + + // free temporary data + free (temporary_storage.elements); + + // add new data point + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_1 = k; + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_2 = i; + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_3 = j; + storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements++].weight = p; } - - // free temporary data - free(temporary_storage.elements); - - // add new data point - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_1 = k; - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_2 = i; - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements].index_3 = j; - storage->temp_3DS_data.elements[storage->temp_3DS_data.num_elements++].weight = p; + + // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm + if (storage->temp_3DS_data.num_elements == 1) + add_to_logger_with_data (logger_with_data_array, logger); } - - // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm - if (storage->temp_3DS_data.num_elements == 1) - add_to_logger_with_data(logger_with_data_array,logger); } } - -} - -// clear_temp -void clear_temp_3DS(union logger_data_union *data_union) { - data_union->p_3DS_storage->temp_3DS_data.num_elements = 0; -} - -// record_to_perm -void record_to_perm_3DS(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { - - //printf("In record to permanent \n"); - struct a_3DS_storage_struct *storage; - storage = logger->data_union.p_3DS_storage; - - int add_point = 1; - - if (storage->order != 0) { - if (storage->order - 1 == total_number_of_scattering_events) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_in_this_volume != 0) { - if (storage->order_in_this_volume - 1 == scattered_in_this_volume) - add_point = 1; - else - add_point = 0; - } - - if (storage->order_process_in_this_volume != 0) { - if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) - add_point = 1; - else - add_point = 0; + + // clear_temp + void + clear_temp_3DS (union logger_data_union* data_union) { + data_union->p_3DS_storage->temp_3DS_data.num_elements = 0; } - if (add_point == 1) { - //printf("storage was set \n"); - double p1,p2,p3; - p1=p2=p3=0; - - // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". - if (storage->dim_1_choice == 0) - p1 = position->x - storage->position.x; - else if (storage->dim_1_choice == 1) - p1 = position->y - storage->position.y; - else if (storage->dim_1_choice == 2) - p1 = position->z - storage->position.z; - - if (storage->dim_2_choice == 0) - p2 = position->x - storage->position.x; - else if (storage->dim_2_choice == 1) - p2 = position->y - storage->position.y; - else if (storage->dim_2_choice == 2) - p2 = position->z - storage->position.z; - - if (storage->dim_3_choice == 0) - p3 = position->x - storage->position.x; - else if (storage->dim_3_choice == 1) - p3 = position->y - storage->position.y; - else if (storage->dim_3_choice == 2) - p3 = position->z - storage->position.z; - - int i,j,k; - - // Find bin in histogram - if (p1>storage->Detector_3D.D1min && p1Detector_3D.D1max && p2>storage->Detector_3D.D2min && p2Detector_3D.D2max && p3>storage->Detector_3D.D3min && p3Detector_3D.D3max) { - i = floor((p1 - storage->Detector_3D.D1min)*storage->Detector_3D.bins_1/(storage->Detector_3D.D1max - storage->Detector_3D.D1min)); - j = floor((p2 - storage->Detector_3D.D2min)*storage->Detector_3D.bins_2/(storage->Detector_3D.D2max - storage->Detector_3D.D2min)); - k = floor((p3 - storage->Detector_3D.D3min)*storage->Detector_3D.bins_3/(storage->Detector_3D.D3max - storage->Detector_3D.D3min)); - - /* - printf("(p1,p2,p3) = (%f,%f,%f)\n",p1,p2,p3); - printf("limits1 = [%f,%f] \n",storage->Detector_3D.D1min,storage->Detector_3D.D1max); - printf("limits2 = [%f,%f] \n",storage->Detector_3D.D2min,storage->Detector_3D.D2max); - printf("limits3 = [%f,%f] \n",storage->Detector_3D.D3min,storage->Detector_3D.D3max); - printf("n bins = [%d,%d,%d] \n",round(storage->Detector_3D.bins_1),round(storage->Detector_3D.bins_2),round(storage->Detector_3D.bins_3)); - printf("Added to statistics for monitor [%d] [%d] [%d] \n",i,j,k); - printf("indicies found\n"); - */ - - /* - storage->Detector_3D.Array_N[i][j][k]++; - storage->Detector_3D.Array_p[i][j][k] += p; - storage->Detector_3D.Array_p2[i][j][k] += p*p; - */ - - - // because of the order in which the elements are laid out in memory, the k index must be first. - storage->Detector_3D.Array_N[k][i][j]++; - storage->Detector_3D.Array_p[k][i][j] += p; - storage->Detector_3D.Array_p2[k][i][j] += p*p; - - + // record_to_perm + void + record_to_perm_3DS (Coords* position, double* k_new, double* k_old, double p, double p_old, double time, int scattered_in_this_volume, + int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct* logger, + struct logger_with_data_struct* logger_with_data_array) { + + // printf("In record to permanent \n"); + struct a_3DS_storage_struct* storage; + storage = logger->data_union.p_3DS_storage; + + int add_point = 1; + + if (storage->order != 0) { + if (storage->order - 1 == total_number_of_scattering_events) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_in_this_volume != 0) { + if (storage->order_in_this_volume - 1 == scattered_in_this_volume) + add_point = 1; + else + add_point = 0; + } + + if (storage->order_process_in_this_volume != 0) { + if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) + add_point = 1; + else + add_point = 0; + } + + if (add_point == 1) { + // printf("storage was set \n"); + double p1, p2, p3; + p1 = p2 = p3 = 0; + + // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". + if (storage->dim_1_choice == 0) + p1 = position->x - storage->position.x; + else if (storage->dim_1_choice == 1) + p1 = position->y - storage->position.y; + else if (storage->dim_1_choice == 2) + p1 = position->z - storage->position.z; + + if (storage->dim_2_choice == 0) + p2 = position->x - storage->position.x; + else if (storage->dim_2_choice == 1) + p2 = position->y - storage->position.y; + else if (storage->dim_2_choice == 2) + p2 = position->z - storage->position.z; + + if (storage->dim_3_choice == 0) + p3 = position->x - storage->position.x; + else if (storage->dim_3_choice == 1) + p3 = position->y - storage->position.y; + else if (storage->dim_3_choice == 2) + p3 = position->z - storage->position.z; + + int i, j, k; + + // Find bin in histogram + if (p1 > storage->Detector_3D.D1min && p1 < storage->Detector_3D.D1max && p2 > storage->Detector_3D.D2min && p2 < storage->Detector_3D.D2max + && p3 > storage->Detector_3D.D3min && p3 < storage->Detector_3D.D3max) { + i = floor ((p1 - storage->Detector_3D.D1min) * storage->Detector_3D.bins_1 / (storage->Detector_3D.D1max - storage->Detector_3D.D1min)); + j = floor ((p2 - storage->Detector_3D.D2min) * storage->Detector_3D.bins_2 / (storage->Detector_3D.D2max - storage->Detector_3D.D2min)); + k = floor ((p3 - storage->Detector_3D.D3min) * storage->Detector_3D.bins_3 / (storage->Detector_3D.D3max - storage->Detector_3D.D3min)); + + /* + printf("(p1,p2,p3) = (%f,%f,%f)\n",p1,p2,p3); + printf("limits1 = [%f,%f] \n",storage->Detector_3D.D1min,storage->Detector_3D.D1max); + printf("limits2 = [%f,%f] \n",storage->Detector_3D.D2min,storage->Detector_3D.D2max); + printf("limits3 = [%f,%f] \n",storage->Detector_3D.D3min,storage->Detector_3D.D3max); + printf("n bins = [%d,%d,%d] \n",round(storage->Detector_3D.bins_1),round(storage->Detector_3D.bins_2),round(storage->Detector_3D.bins_3)); + printf("Added to statistics for monitor [%d] [%d] [%d] \n",i,j,k); + printf("indicies found\n"); + */ + + /* + storage->Detector_3D.Array_N[i][j][k]++; + storage->Detector_3D.Array_p[i][j][k] += p; + storage->Detector_3D.Array_p2[i][j][k] += p*p; + */ + + // because of the order in which the elements are laid out in memory, the k index must be first. + storage->Detector_3D.Array_N[k][i][j]++; + storage->Detector_3D.Array_p[k][i][j] += p; + storage->Detector_3D.Array_p2[k][i][j] += p * p; + } } } -} - -// write_temp_to_perm -void write_temp_to_perm_3DS(union logger_data_union *data_union) { - - struct a_3DS_storage_struct *storage; - storage = data_union->p_3DS_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_3DS_data.num_elements;index++) { - storage->Detector_3D.Array_N[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3]++; - - storage->Detector_3D.Array_p[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3] += storage->temp_3DS_data.elements[index].weight; - - storage->Detector_3D.Array_p2[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3] += storage->temp_3DS_data.elements[index].weight*storage->temp_3DS_data.elements[index].weight; + + // write_temp_to_perm + void + write_temp_to_perm_3DS (union logger_data_union* data_union) { + + struct a_3DS_storage_struct* storage; + storage = data_union->p_3DS_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_3DS_data.num_elements; index++) { + storage->Detector_3D.Array_N[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2] + [storage->temp_3DS_data.elements[index].index_3]++; + + storage->Detector_3D + .Array_p[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3] + += storage->temp_3DS_data.elements[index].weight; + + storage->Detector_3D.Array_p2[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2] + [storage->temp_3DS_data.elements[index].index_3] + += storage->temp_3DS_data.elements[index].weight * storage->temp_3DS_data.elements[index].weight; + } + clear_temp_3DS (data_union); } - clear_temp_3DS(data_union); -} - -void write_temp_to_perm_final_p_3DS(union logger_data_union *data_union, double final_weight) { - - struct a_3DS_storage_struct *storage; - storage = data_union->p_3DS_storage; - - int index; - // Add all data points to the historgram, they are saved as index / weight combinations - for (index=0;indextemp_3DS_data.num_elements;index++) { - storage->Detector_3D.Array_N[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3]++; - - storage->Detector_3D.Array_p[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3] += final_weight; - - storage->Detector_3D.Array_p2[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3] += final_weight*final_weight; + + void + write_temp_to_perm_final_p_3DS (union logger_data_union* data_union, double final_weight) { + + struct a_3DS_storage_struct* storage; + storage = data_union->p_3DS_storage; + + int index; + // Add all data points to the historgram, they are saved as index / weight combinations + for (index = 0; index < storage->temp_3DS_data.num_elements; index++) { + storage->Detector_3D.Array_N[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2] + [storage->temp_3DS_data.elements[index].index_3]++; + + storage->Detector_3D + .Array_p[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2][storage->temp_3DS_data.elements[index].index_3] + += final_weight; + + storage->Detector_3D.Array_p2[storage->temp_3DS_data.elements[index].index_1][storage->temp_3DS_data.elements[index].index_2] + [storage->temp_3DS_data.elements[index].index_3] + += final_weight * final_weight; + } + clear_temp_3DS (data_union); } - clear_temp_3DS(data_union); -} - -// Only need to define linking function for loggers once. -#ifndef UNION_LOGGER -#define UNION_LOGGER Dummy -// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list -void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { + + // Only need to define linking function for loggers once. + #ifndef UNION_LOGGER + #define UNION_LOGGER Dummy + // Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list + void + manual_linking_function_logger_volumes (char* input_string, struct pointer_to_global_geometry_list* global_geometry_list, + struct pointer_to_1d_int_list* accepted_volumes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[512]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_volumes,loop_index); + char* token; + int loop_index; + char local_string[512]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (strcmp (token, global_geometry_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_volumes, loop_index); break; } - + if (loop_index == global_geometry_list->num_elements - 1) { // All possible geometry names have been looked through, and the break was not executed. // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires - printf("\n"); - printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); - printf(" The unrecoignized geometry name was: \"%s\" \n",token); - printf(" The geometries available at this point (need to be defined before the logger): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n", + input_string, component_name); + printf (" The unrecoignized geometry name was: \"%s\" \n", token); + printf (" The geometries available at this point (need to be defined before the logger): \n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { + void + manual_linking_function_logger_processes (char* input_string, struct physics_struct* p_physics, struct pointer_to_1d_int_list* accepted_processes, + char* component_name, char* Volume_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through other tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) { - if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes,loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through other tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) { + if (strcmp (token, p_physics->p_scattering_array[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == p_physics->number_of_processes - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); - for (loop_index=0;loop_indexnumber_of_processes;loop_index++) - printf(" %s\n",p_physics->p_scattering_array[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume " + "\"%s\". \n", + input_string, component_name, Volume_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n", p_physics->name, Volume_name); + for (loop_index = 0; loop_index < p_physics->number_of_processes; loop_index++) + printf (" %s\n", p_physics->p_scattering_array[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} -#endif - -double*** allocate3Ddouble_3DS(int count_x, int count_y, int count_z, double *storage) { - //double *storage = malloc(count_x * count_y * count_z * sizeof(double)); - storage = malloc(count_x * count_y * count_z * sizeof(double)); - if (storage == NULL){ - free(storage); - printf("\nERROR: storage array not allocated in Union_logger_3D_space\n"); - } - double *alloc = storage; - double ***x; - int i,j; - x = malloc(count_x * sizeof(*x)); - if ( x == NULL){ - free(x); - printf("\nERROR: x array not allocated in Union_logger_3D_space\n"); - exit(1); + token = strtok (NULL, ","); } - for (i = 0; i < count_x; i++) { - x[i] = malloc(count_y * sizeof(**x)); - if ( x[i] == NULL){ - free(x[i]); - printf("\nERROR: x[i] array not allocated in Union_logger_3D_space\n"); - exit(1); + } + #endif + + double*** + allocate3Ddouble_3DS (int count_x, int count_y, int count_z, double* storage) { + // double *storage = malloc(count_x * count_y * count_z * sizeof(double)); + storage = malloc (count_x * count_y * count_z * sizeof (double)); + if (storage == NULL) { + free (storage); + printf ("\nERROR: storage array not allocated in Union_logger_3D_space\n"); } - for (j = 0; j < count_y; j++) { - x[i][j] = alloc; - alloc += count_z; - } - } - return x; - } - -void free3Ddouble_3DS(double*** ptr_array, int count_x, double *storage) { - if (!ptr_array) return; - int x; - - free(storage); - for (x=0;x= D1_max) { - printf("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D1_min >= D1_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D1min = D1_min; this_storage.Detector_3D.D1max = D1_max; - + if (D2_min >= D2_max) { - printf("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D2_min >= D2_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D2min = D2_min; this_storage.Detector_3D.D2max = D2_max; - + if (D3_min >= D3_max) { - printf("ERROR, Union logger \"%s\" had D3_min >= D3_max.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had D3_min >= D3_max.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.D3min = D3_min; this_storage.Detector_3D.D3max = D3_max; - + if (n1 <= 0) { - printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n1 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_1 = n1; - + if (n2 <= 0) { - printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n2 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_2 = n2; - + if (n3 <= 0) { - printf("ERROR, Union logger \"%s\" had n3 <= 0.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union logger \"%s\" had n3 <= 0.\n", NAME_CURRENT_COMP); + exit (1); } this_storage.Detector_3D.bins_3 = n3; - - //printf("past input sanitation \n"); - + + // printf("past input sanitation \n"); + // Remember to take special care when deallocating this array, use free3Ddouble - + /* this_storage.Detector_3D.Array_N = allocate3Ddouble_3DS(n1,n2,n3); // Here the n1 double is cast to an int this_storage.Detector_3D.Array_p = allocate3Ddouble_3DS(n1,n2,n3); this_storage.Detector_3D.Array_p2 = allocate3Ddouble_3DS(n1,n2,n3); */ // D3 is in poisition 1, because that gives continous memory in XY plane for easy plotting - - this_storage.Detector_3D.Array_N = allocate3Ddouble_3DS(n3,n1,n2,storage_N); // Here the n1 double is cast to an int - this_storage.Detector_3D.Array_p = allocate3Ddouble_3DS(n3,n1,n2,storage_p); - this_storage.Detector_3D.Array_p2 = allocate3Ddouble_3DS(n3,n1,n2,storage_2p); - + + this_storage.Detector_3D.Array_N = allocate3Ddouble_3DS (n3, n1, n2, storage_N); // Here the n1 double is cast to an int + this_storage.Detector_3D.Array_p = allocate3Ddouble_3DS (n3, n1, n2, storage_p); + this_storage.Detector_3D.Array_p2 = allocate3Ddouble_3DS (n3, n1, n2, storage_2p); + /* // Error in the order? this_storage.Detector_3D.Array_N = allocate3Ddouble_3DS(n1,n3,n2); // Here the n1 double is cast to an int this_storage.Detector_3D.Array_p = allocate3Ddouble_3DS(n1,n3,n2); this_storage.Detector_3D.Array_p2 = allocate3Ddouble_3DS(n1,n3,n2); */ - - - //printf("Allocated 3D arrays \n"); - int l1,l2,l3; - for (l1=0;l1elements[accepted_volumes.elements[loop_index]].Volume; // Add an element to its logger list - add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); - - if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { + add_initialized_logger_in_volume (&target_volume->loggers, target_volume->p_physics->number_of_processes); + + if (target_process && strlen (target_process) && strcmp (target_process, "NULL") && strcmp (target_process, "0")) { // Unused process pointers should point to NULL - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = NULL; } // A target_process was set, find it within the volume structure (can be many processes) - manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); - for (process_index=0;process_indexp_physics, &accepted_processes, NAME_CURRENT_COMP, target_volume->name); + for (process_index = 0; process_index < accepted_processes.num_elements; process_index++) { // Add pointer to this logger for all the accepted processes in this newly added loggers element - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[accepted_processes.elements[process_index]] + = &this_logger; } } else { // No target_process was set, attatch the logger to all processes - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; + for (process_index = 0; process_index < target_volume->p_physics->number_of_processes; process_index++) { + target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements - 1].p_logger_process[process_index] = &this_logger; } } } } else { // Send to global_all_volumes_logger_list // Here there is no system for selecting processes as well - struct pointer_to_global_logger_list *global_all_volume_logger_list = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - add_element_to_logger_list(global_all_volume_logger_list,logger_list_element); + struct pointer_to_global_logger_list* global_all_volume_logger_list = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + add_element_to_logger_list (global_all_volume_logger_list, logger_list_element); } - - %} TRACE @@ -794,37 +810,33 @@ TRACE SAVE %{ -// Write to disk - -for (loop_index=0;loop_index0) free(this_storage.temp_3DS_data.elements); - -free3Ddouble_3DS(this_storage.Detector_3D.Array_N,n3,storage_N); -free3Ddouble_3DS(this_storage.Detector_3D.Array_p,n3,storage_p); -free3Ddouble_3DS(this_storage.Detector_3D.Array_p2,n3,storage_2p); - -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); -if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); - + // Remember to clean up allocated lists + if (this_storage.temp_3DS_data.allocated_elements > 0) + free (this_storage.temp_3DS_data.elements); + + free3Ddouble_3DS (this_storage.Detector_3D.Array_N, n3, storage_N); + free3Ddouble_3DS (this_storage.Detector_3D.Array_p, n3, storage_p); + free3Ddouble_3DS (this_storage.Detector_3D.Array_p2, n3, storage_2p); + + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); + if (accepted_volumes.num_elements > 0) + free (accepted_volumes.elements); %} END diff --git a/mcstas-comps/union/Union_make_material.comp b/mcstas-comps/union/Union_make_material.comp index d11a7d51ee..b78b790102 100755 --- a/mcstas-comps/union/Union_make_material.comp +++ b/mcstas-comps/union/Union_make_material.comp @@ -61,114 +61,122 @@ SETTING PARAMETERS(string process_string="NULL", my_absorption,absorber=0, SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_make_material component" -#endif - + #ifndef Union + #error "The Union_init component must be included before this Union_make_material component" + #endif -// This function checks if global_process_element should be included in this material when using automatic linking, returns 1 if yes, 0 if no. -int automatic_linking_materials_function(struct global_process_element_struct global_process_element, struct pointer_to_global_material_list global_material_list,int current_index) { + // This function checks if global_process_element should be included in this material when using automatic linking, returns 1 if yes, 0 if no. + int + automatic_linking_materials_function (struct global_process_element_struct global_process_element, struct pointer_to_global_material_list global_material_list, + int current_index) { // Remember this function is used before the current material is added to global_material_list // debug info - //MPI_MASTER( - //printf("Checking if process with index %d should be automatically linked to material with index %d\n",global_process_element.component_index,current_index); + // MPI_MASTER( + // printf("Checking if process with index %d should be automatically linked to material with index + // %d\n",global_process_element.component_index,current_index); //) // Check if this is the first make_material, which makes the problem simpler. if (global_material_list.num_elements == 0) { - if (global_process_element.component_index < current_index) return 1; - else return 0; + if (global_process_element.component_index < current_index) + return 1; + else + return 0; } // In case there are more than 1 make_material, global_material_list.elements[global_material_list.num_elements-1].component_index makes sense. - if (global_process_element.component_index < current_index && global_process_element.component_index > global_material_list.elements[global_material_list.num_elements-1].component_index) return 1; - else return 0; -} + if (global_process_element.component_index < current_index + && global_process_element.component_index > global_material_list.elements[global_material_list.num_elements - 1].component_index) + return 1; + else + return 0; + } -void manual_linking_function_material(char *input_string, struct pointer_to_global_process_list *global_process_list, struct pointer_to_1d_int_list *accepted_processes, char *component_name) { + void + manual_linking_function_material (char* input_string, struct pointer_to_global_process_list* global_process_list, + struct pointer_to_1d_int_list* accepted_processes, char* component_name) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int loop_index; - char local_string[256]; - - strcpy(local_string,input_string); - // get the first token - token = strtok(local_string,","); - - // walk through tokens - while( token != NULL ) - { - //printf( " %s\n", token ); - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (strcmp(token,global_process_list->elements[loop_index].name) == 0) { - add_element_to_int_list(accepted_processes, loop_index); + char* token; + int loop_index; + char local_string[256]; + + strcpy (local_string, input_string); + // get the first token + token = strtok (local_string, ","); + + // walk through tokens + while (token != NULL) { + // printf( " %s\n", token ); + for (loop_index = 0; loop_index < global_process_list->num_elements; loop_index++) { + if (strcmp (token, global_process_list->elements[loop_index].name) == 0) { + add_element_to_int_list (accepted_processes, loop_index); break; } - + if (loop_index == global_process_list->num_elements - 1) { // All possible process names have been looked through, and the break was not executed. // Alert the user to this problem by showing the process name that was not found and the currently available processes - printf("\n"); - printf("ERROR: The process string \"%s\" in Union material \"%s\" had an entry that did not match a specified process. \n",input_string,component_name); - printf(" The unrecoignized process name was: \"%s\" \n",token); - printf(" The processes available at this point (need to be defined before the material): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_process_list->elements[loop_index].name); - exit(1); + printf ("\n"); + printf ("ERROR: The process string \"%s\" in Union material \"%s\" had an entry that did not match a specified process. \n", input_string, + component_name); + printf (" The unrecoignized process name was: \"%s\" \n", token); + printf (" The processes available at this point (need to be defined before the material): \n"); + for (loop_index = 0; loop_index < global_process_list->num_elements; loop_index++) + printf (" %s\n", global_process_list->elements[loop_index].name); + exit (1); } } - + // Updates the token - token = strtok(NULL,","); - } -} + token = strtok (NULL, ","); + } + } -// This function is needed in initialize of all geometry components -// Possible to insert these functions in make material, as they are only compiled once instead of many times -int manual_linking_function(char *name, char *input_string) { + // This function is needed in initialize of all geometry components + // Possible to insert these functions in make material, as they are only compiled once instead of many times + int + manual_linking_function (char* name, char* input_string) { // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. - char *token; - int return_integer=0; - char local_string[124]; - - strcpy(local_string,input_string); - /* get the first token */ - token = strtok(local_string,","); - - /* walk through other tokens */ - while( token != NULL ) - { - if (strcmp(token,name) == 0) return_integer=1; - - token = strtok(NULL,","); - } - - return return_integer; -} - -#ifndef MATERIAL_DETECTOR - #define MATERIAL_DETECTOR dummy -#endif + char* token; + int return_integer = 0; + char local_string[124]; + + strcpy (local_string, input_string); + /* get the first token */ + token = strtok (local_string, ","); + + /* walk through other tokens */ + while (token != NULL) { + if (strcmp (token, name) == 0) + return_integer = 1; + + token = strtok (NULL, ","); + } + + return return_integer; + } + #ifndef MATERIAL_DETECTOR + #define MATERIAL_DETECTOR dummy + #endif %} DECLARE %{ -// Needed for transport to the main component -struct global_material_element_struct global_material_element; -struct physics_struct this_material; - -int loop_index; -int found_process; -int specified_processes; -char local_string[256]; + // Needed for transport to the main component + struct global_material_element_struct global_material_element; + struct physics_struct this_material; -struct pointer_to_1d_int_list accepted_processes; + int loop_index; + int found_process; + int specified_processes; + char local_string[256]; -// Add setup for loggers since make_material is called before any volume / master -#ifndef UNION_LOGGER_DECLARE - #define UNION_LOGGER_DECLARE dummy -#endif + struct pointer_to_1d_int_list accepted_processes; + // Add setup for loggers since make_material is called before any volume / master + #ifndef UNION_LOGGER_DECLARE + #define UNION_LOGGER_DECLARE dummy + #endif %} INITIALIZE @@ -176,102 +184,102 @@ INITIALIZE accepted_processes.num_elements = 0; accepted_processes.elements = NULL; - - if (0 == strcmp(NAME_CURRENT_COMP,"vacuum") || 0 == strcmp(NAME_CURRENT_COMP,"Vacuum")) { - printf("ERROR, a Union material may not be called Vacuum. A vacuum volume may be created by material=\"Vacuum\" in a geometry component.\n"); - exit(1); + if (0 == strcmp (NAME_CURRENT_COMP, "vacuum") || 0 == strcmp (NAME_CURRENT_COMP, "Vacuum")) { + printf ("ERROR, a Union material may not be called Vacuum. A vacuum volume may be created by material=\"Vacuum\" in a geometry component.\n"); + exit (1); } - if (0 == strcmp(NAME_CURRENT_COMP,"exit") || 0 == strcmp(NAME_CURRENT_COMP,"Exit")) { - printf("ERROR, a Union material may not be called Exit. A exit volume may be created by material=\"Exit\" in a geometry component.\n"); - exit(1); + if (0 == strcmp (NAME_CURRENT_COMP, "exit") || 0 == strcmp (NAME_CURRENT_COMP, "Exit")) { + printf ("ERROR, a Union material may not be called Exit. A exit volume may be created by material=\"Exit\" in a geometry component.\n"); + exit (1); } if (my_absorption < 0) { - printf("ERROR, Union make material named %s have a negative absorption cross section!.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, Union make material named %s have a negative absorption cross section!.\n", NAME_CURRENT_COMP); + exit (1); } - if (_getcomp_index(init) < 0) { - fprintf(stderr,"Union_make_material:%s: Error identifying Union_init component, %s is not a known component name.\n", - NAME_CURRENT_COMP, init); - exit(-1); + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_make_material:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); } - struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); - struct pointer_to_global_material_list *global_material_list = COMP_GETPAR3(Union_init, init, global_material_list); - + struct pointer_to_global_process_list* global_process_list = COMP_GETPAR3 (Union_init, init, global_process_list); + struct pointer_to_global_material_list* global_material_list = COMP_GETPAR3 (Union_init, init, global_material_list); + if (absorber == 0) { - if (process_string && strlen(process_string) && strcmp(process_string,"NULL") && strcmp(process_string, "0")) { - manual_linking_function_material(process_string, global_process_list, &accepted_processes, NAME_CURRENT_COMP); + if (process_string && strlen (process_string) && strcmp (process_string, "NULL") && strcmp (process_string, "0")) { + manual_linking_function_material (process_string, global_process_list, &accepted_processes, NAME_CURRENT_COMP); } else { - for (loop_index=0;loop_indexnum_elements;loop_index++) { + for (loop_index = 0; loop_index < global_process_list->num_elements; loop_index++) { // printf("Automatic linking chosen [loop index = %d] with process_string = %s \n",loop_index,process_string); // automatic linking // accept a process if index is between current and former index of make_material components - if (1 == automatic_linking_materials_function(global_process_list->elements[loop_index], *global_material_list, INDEX_CURRENT_COMP)) - add_element_to_int_list(&accepted_processes,loop_index); + if (1 == automatic_linking_materials_function (global_process_list->elements[loop_index], *global_material_list, INDEX_CURRENT_COMP)) + add_element_to_int_list (&accepted_processes, loop_index); } } } this_material.number_of_processes = accepted_processes.num_elements; // Add number of processes - this_material.is_vacuum = 0; // This material is not vacuum - + this_material.is_vacuum = 0; // This material is not vacuum + if (this_material.number_of_processes == 0 && my_absorption == 0) { - printf("ERROR, the material named %s has no processes assigned and no absorption cross section, making it eqvialent to vacuum. Vacuums are assigned by setting material=\"Vacuum\" in a geometry component.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR, the material named %s has no processes assigned and no absorption cross section, making it eqvialent to vacuum. Vacuums are assigned by " + "setting material=\"Vacuum\" in a geometry component.\n", + NAME_CURRENT_COMP); + exit (1); } - + this_material.any_process_needs_cross_section_focus = -1; // Assume no process need focusing in cross section calculation // add process element to this_material, building an array of processes called p_scattering_array - if (this_material.number_of_processes > 0) this_material.p_scattering_array = malloc(this_material.number_of_processes * sizeof(struct scattering_process_struct)); - for (loop_index=0;loop_indexelements[accepted_processes.elements[loop_index]].p_scattering_process; - - // Check if each process needs focusing capability in the calculation of cross section / inverse penetration depth - if (this_material.p_scattering_array[loop_index].needs_cross_section_focus == 1) { - this_material.any_process_needs_cross_section_focus = 1; - } + if (this_material.number_of_processes > 0) + this_material.p_scattering_array = malloc (this_material.number_of_processes * sizeof (struct scattering_process_struct)); + for (loop_index = 0; loop_index < accepted_processes.num_elements; loop_index++) { + this_material.p_scattering_array[loop_index] = *global_process_list->elements[accepted_processes.elements[loop_index]].p_scattering_process; + + // Check if each process needs focusing capability in the calculation of cross section / inverse penetration depth + if (this_material.p_scattering_array[loop_index].needs_cross_section_focus == 1) { + this_material.any_process_needs_cross_section_focus = 1; + } } - - this_material.my_a = my_absorption; // add the absorption to this material - sprintf(this_material.name,"%s",NAME_CURRENT_COMP); - + + this_material.my_a = my_absorption; // add the absorption to this material + sprintf (this_material.name, "%s", NAME_CURRENT_COMP); + // Section on refracation information this_material.has_refraction_info = 0; if (refraction_density != 0 || refraction_weight != 0 || refraction_sigma_coh != 0) { - - double refraction_rho, refraction_bc; - if (refraction_density==0 || refraction_weight<=0) - exit(printf("Union_make_material: %s: FATAL: invalid material density or molar weight: density=%g weight=%g\n", - NAME_CURRENT_COMP, refraction_density, refraction_weight)); - - refraction_rho = fabs(refraction_density)*6.02214179*1e23*1e-24/refraction_weight; // per at/Angs^3 - - if (refraction_sigma_coh==0) - exit(printf("Refractor: %s: FATAL: invalid material coherent cross section: sigma_coh=%g\n", - NAME_CURRENT_COMP, refraction_sigma_coh)); - - refraction_bc = sqrt(fabs(refraction_sigma_coh)*100/4/PI)*1e-5; // bound coherent scattering length - if (refraction_sigma_coh<0) refraction_bc *= -1.0; - - this_material.refraction_scattering_length_density = refraction_rho*refraction_bc; - this_material.refraction_Qc = 4*sqrt(PI*refraction_rho*fabs(refraction_bc)); - this_material.has_refraction_info = 1; + + double refraction_rho, refraction_bc; + if (refraction_density == 0 || refraction_weight <= 0) + exit (printf ("Union_make_material: %s: FATAL: invalid material density or molar weight: density=%g weight=%g\n", NAME_CURRENT_COMP, refraction_density, + refraction_weight)); + + refraction_rho = fabs (refraction_density) * 6.02214179 * 1e23 * 1e-24 / refraction_weight; // per at/Angs^3 + + if (refraction_sigma_coh == 0) + exit (printf ("Refractor: %s: FATAL: invalid material coherent cross section: sigma_coh=%g\n", NAME_CURRENT_COMP, refraction_sigma_coh)); + + refraction_bc = sqrt (fabs (refraction_sigma_coh) * 100 / 4 / PI) * 1e-5; // bound coherent scattering length + if (refraction_sigma_coh < 0) + refraction_bc *= -1.0; + + this_material.refraction_scattering_length_density = refraction_rho * refraction_bc; + this_material.refraction_Qc = 4 * sqrt (PI * refraction_rho * fabs (refraction_bc)); + this_material.has_refraction_info = 1; } - + if (refraction_SLD > -1499.0) { // refraction_SLD can be negative, zero or positive, it can however not be this negative, so this is used as input check - this_material.refraction_scattering_length_density = refraction_SLD; - this_material.refraction_Qc = 4.0*sqrt(PI*fabs(refraction_SLD)); - this_material.has_refraction_info = 1; + this_material.refraction_scattering_length_density = refraction_SLD; + this_material.refraction_Qc = 4.0 * sqrt (PI * fabs (refraction_SLD)); + this_material.has_refraction_info = 1; } - + // packing the information into the global_material_element, which is then included in the global_material_list. - sprintf(global_material_element.name,"%s",NAME_CURRENT_COMP); + sprintf (global_material_element.name, "%s", NAME_CURRENT_COMP); global_material_element.component_index = INDEX_CURRENT_COMP; global_material_element.physics = &this_material; - add_element_to_material_list(global_material_list, global_material_element); - + add_element_to_material_list (global_material_list, global_material_element); %} TRACE @@ -280,46 +288,47 @@ TRACE FINALLY %{ -// The elements of the scattering array used static allocation and is thus deallocated automatically -if (this_material.number_of_processes > 0) free(this_material.p_scattering_array); -if (accepted_processes.num_elements > 0) free(accepted_processes.elements); + // The elements of the scattering array used static allocation and is thus deallocated automatically + if (this_material.number_of_processes > 0) + free (this_material.p_scattering_array); + if (accepted_processes.num_elements > 0) + free (accepted_processes.elements); -struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); -struct pointer_to_global_master_list *global_master_list = COMP_GETPAR3(Union_init, init, global_master_list); + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + struct pointer_to_global_master_list* global_master_list = COMP_GETPAR3 (Union_init, init, global_master_list); -// Checking if any Union volumes are defined after the master component -#ifdef MASTER_DETECTOR + // Checking if any Union volumes are defined after the master component + #ifdef MASTER_DETECTOR #ifdef ANY_GEOMETRY_DETECTOR_DECLARE - #ifndef MASTER_DETECTOR_WARNING - - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (global_geometry_list->elements[loop_index].component_index > global_master_list->elements[global_master_list->num_elements-1].component_index) { - printf("WARNING: No Union_master component defined after Union volume named %s, this components did not affect the simulation in any way.\n",global_geometry_list->elements[loop_index].name); - } - } - // Decided to have this as a warning without exiting the simulation - // In order to only show this warning once, the MASTER_DETECTOR_WARNING is defined - #define MASTER_DETECTOR_WARNING dummy - #endif + #ifndef MASTER_DETECTOR_WARNING + + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + if (global_geometry_list->elements[loop_index].component_index > global_master_list->elements[global_master_list->num_elements - 1].component_index) { + printf ("WARNING: No Union_master component defined after Union volume named %s, this components did not affect the simulation in any way.\n", + global_geometry_list->elements[loop_index].name); + } + } + // Decided to have this as a warning without exiting the simulation + // In order to only show this warning once, the MASTER_DETECTOR_WARNING is defined + #define MASTER_DETECTOR_WARNING dummy + #endif + #endif #endif -#endif -// Checking if the user remembered to put in a Union_master -#ifndef MASTER_DETECTOR + // Checking if the user remembered to put in a Union_master + #ifndef MASTER_DETECTOR #ifdef ANY_GEOMETRY_DETECTOR_DECLARE - #ifndef MASTER_DETECTOR_WARNING - printf("\nWARNING: No Union_master component used, these components did not affect the simulation in any way:\n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_geometry_list->elements[loop_index].name); - printf("\n"); - // Decided to have this as a warning without exiting the simulation - // In order to only show this warning once, the MASTER_DETECTOR_WARNING is defined - #define MASTER_DETECTOR_WARNING dummy - #endif + #ifndef MASTER_DETECTOR_WARNING + printf ("\nWARNING: No Union_master component used, these components did not affect the simulation in any way:\n"); + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) + printf (" %s\n", global_geometry_list->elements[loop_index].name); + printf ("\n"); + // Decided to have this as a warning without exiting the simulation + // In order to only show this warning once, the MASTER_DETECTOR_WARNING is defined + #define MASTER_DETECTOR_WARNING dummy + #endif + #endif #endif -#endif - - %} END diff --git a/mcstas-comps/union/Union_master.comp b/mcstas-comps/union/Union_master.comp index 92a4679b7d..98dd5d6a5b 100755 --- a/mcstas-comps/union/Union_master.comp +++ b/mcstas-comps/union/Union_master.comp @@ -73,56 +73,55 @@ NOACC SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_master component" -#endif - -struct logger_with_data_struct loggers_with_data_array; -struct abs_logger_with_data_struct abs_loggers_with_data_array; + #ifndef Union + #error "The Union_init component must be included before this Union_master component" + #endif -#ifndef MASTER_DETECTOR - #define MASTER_DETECTOR dummy -#endif + struct logger_with_data_struct loggers_with_data_array; + struct abs_logger_with_data_struct abs_loggers_with_data_array; + #ifndef MASTER_DETECTOR + #define MASTER_DETECTOR dummy + #endif %} DECLARE %{ // Declare global lists, will be retrieved in INITIALIZE - struct global_positions_to_transform_list_struct *global_positions_to_transform_list_master; - struct global_rotations_to_transform_list_struct *global_rotations_to_transform_list_master; - struct pointer_to_global_process_list *global_process_list_master; - struct pointer_to_global_material_list *global_material_list_master; - struct pointer_to_global_surface_list *global_surface_list_master; - struct pointer_to_global_geometry_list *global_geometry_list_master; - struct pointer_to_global_logger_list *global_all_volume_logger_list_master; - struct pointer_to_global_logger_list *global_specific_volumes_logger_list_master; - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list_master; - struct pointer_to_global_abs_logger_list *global_specific_volumes_abs_logger_list_master; - struct global_tagging_conditional_list_struct *global_tagging_conditional_list_master; - struct pointer_to_global_master_list *global_master_list_master; + struct global_positions_to_transform_list_struct* global_positions_to_transform_list_master; + struct global_rotations_to_transform_list_struct* global_rotations_to_transform_list_master; + struct pointer_to_global_process_list* global_process_list_master; + struct pointer_to_global_material_list* global_material_list_master; + struct pointer_to_global_surface_list* global_surface_list_master; + struct pointer_to_global_geometry_list* global_geometry_list_master; + struct pointer_to_global_logger_list* global_all_volume_logger_list_master; + struct pointer_to_global_logger_list* global_specific_volumes_logger_list_master; + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list_master; + struct pointer_to_global_abs_logger_list* global_specific_volumes_abs_logger_list_master; + struct global_tagging_conditional_list_struct* global_tagging_conditional_list_master; + struct pointer_to_global_master_list* global_master_list_master; // New precompiler settings for verbal / tagging, remove // to include verbal in trace and/or tagging - //#define Union_trace_verbal_setting - //#define Union_enable_tagging_setting + // #define Union_trace_verbal_setting + // #define Union_enable_tagging_setting int starting_volume_warning; // Declare the global variables (not to be in output parameters) struct global_master_element_struct global_master_element; int this_global_master_index; - + // variables used for assigning global information to local variables int previous_master_index; int geometry_list_index; // The main structures used in this component struct intersection_time_table_struct intersection_time_table; - struct Volume_struct **Volumes; - struct geometry_struct **Geometries; - struct Volume_struct **Volume_copies; + struct Volume_struct** Volumes; + struct geometry_struct** Geometries; + struct Volume_struct** Volume_copies; struct starting_lists_struct starting_lists; - + // garbage collection for volume_copies struct pointer_to_1d_int_list Volume_copies_allocated; @@ -134,10 +133,10 @@ DECLARE // Error handling int error_msg; int component_error_msg; - + // For verbal output char string_output[128]; - + // Variables for ray-tracing algorithm int number_of_volumes; int volume_index; @@ -154,12 +153,12 @@ DECLARE int time_found; double intersection_time; double min_intersection_time; - - struct scattering_process_struct *process; - struct scattering_process_struct *process_start; - double *my_trace; - double *p_my_trace; - double *my_trace_fraction_control; + + struct scattering_process_struct* process; + struct scattering_process_struct* process_start; + double* my_trace; + double* p_my_trace; + double* my_trace_fraction_control; double k[3]; double k_new[3]; double k_old[3]; @@ -176,27 +175,27 @@ DECLARE int selected_process; int scattering_event; double time_propagated_without_scattering; - + int a_next_volume_found; int next_volume; double next_volume_priority; - + int done; int current_volume; int previous_volume; int ray_sucseeded; - int *number_of_solutions; + int* number_of_solutions; int number_of_solutions_static; - int *check; - int *start; + int* check; + int* start; int intersection_with_children; int geometry_output; - + // For within_which_volume int tree_next_volume; - int *pre_allocated1; - int *pre_allocated2; - int *pre_allocated3; + int* pre_allocated1; + int* pre_allocated2; + int* pre_allocated3; Coords ray_position; Coords ray_velocity; @@ -205,10 +204,10 @@ DECLARE Coords wavevector; Coords wavevector_rotated; int volume_0_found; - - int *scattered_flag; - int **scattered_flag_VP; - + + int* scattered_flag; + int** scattered_flag_VP; + // For coordinate transformations Rotation master_transposed_rotation_matrix; Rotation temp_rotation_matrix; @@ -216,28 +215,28 @@ DECLARE Coords non_rotated_position; Coords rotated_position; int non_isotropic_found; - + // For tagging struct list_of_tagging_tree_node_pointers master_tagging_node_list; - struct tagging_tree_node_struct *current_tagging_node; - + struct tagging_tree_node_struct* current_tagging_node; + int tagging_leaf_counter; int stop_tagging_ray; int stop_creating_nodes; int number_of_scattering_events; - + // For geometry p interact double real_transmission_probability; double mc_transmission_probability; - + // Process p interact int number_of_process_interacts_set; int index_of_lacking_process; double total_process_interact; - + // Volume nr -> component index struct pointer_to_1d_int_list geometry_component_index_list; - + // Masks struct pointer_to_1d_int_list mask_volume_index_list; int number_of_masks; @@ -246,38 +245,38 @@ DECLARE struct pointer_to_1d_int_list current_mask_intersect_list_status; int mask_index_main; int mask_iterator; - int *mask_start; - int *mask_check; + int* mask_start; + int* mask_check; int need_to_run_within_which_volume; - + // Loggers - //struct logger_with_data_struct loggers_with_data_array; - int *number_of_processes_array; + // struct logger_with_data_struct loggers_with_data_array; + int* number_of_processes_array; double p_old; int log_index; int conditional_status; - struct logger_struct *this_logger; - struct abs_logger_struct *this_abs_logger; + struct logger_struct* this_logger; + struct abs_logger_struct* this_abs_logger; // union detector_pointer_union detector_pointer; - + // Conditionals - struct conditional_list_struct *tagging_conditional_list; - int *logger_conditional_extend_array; - int *abs_logger_conditional_extend_array; + struct conditional_list_struct* tagging_conditional_list; + int* logger_conditional_extend_array; + int* abs_logger_conditional_extend_array; int max_conditional_extend_index; int tagging_conditional_extend; int free_tagging_conditioanl_list; - + // Reliability control // Safty distance is needed to avoid having ray positions closer to a wall than the precision of intersection functions double safety_distance; double safety_distance2; - + // Focusing struct focus_data_struct temporary_focus_data; - struct focus_data_struct *this_focus_data; + struct focus_data_struct* this_focus_data; int focus_data_index; - + // Record absorption double r_old[3]; double initial_weight; @@ -287,14 +286,14 @@ DECLARE int abs_weight_factor_set; double my_abs; struct abs_event absorption_event_data[1000]; - + // Absorption logger Coords abs_position; Coords transformed_abs_position; double t_abs_propagation; double abs_distance; double abs_max_length; - + // Surfaces int longest_surface_stack; struct surface_stack_struct interface_stack; @@ -302,168 +301,193 @@ DECLARE INITIALIZE %{ -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_master:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_master:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } // Unpack global lists - global_positions_to_transform_list_master = COMP_GETPAR3(Union_init, init, global_positions_to_transform_list); - global_rotations_to_transform_list_master = COMP_GETPAR3(Union_init, init, global_rotations_to_transform_list); - global_process_list_master = COMP_GETPAR3(Union_init, init, global_process_list); - global_material_list_master = COMP_GETPAR3(Union_init, init, global_material_list); - global_surface_list_master = COMP_GETPAR3(Union_init, init, global_surface_list); - global_geometry_list_master = COMP_GETPAR3(Union_init, init, global_geometry_list); - global_all_volume_logger_list_master = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - global_specific_volumes_logger_list_master = COMP_GETPAR3(Union_init, init, global_specific_volumes_logger_list); - global_all_volume_abs_logger_list_master = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - global_specific_volumes_abs_logger_list_master = COMP_GETPAR3(Union_init, init, global_specific_volumes_abs_logger_list); - global_tagging_conditional_list_master = COMP_GETPAR3(Union_init, init, global_tagging_conditional_list); - global_master_list_master = COMP_GETPAR3(Union_init, init, global_master_list); + global_positions_to_transform_list_master = COMP_GETPAR3 (Union_init, init, global_positions_to_transform_list); + global_rotations_to_transform_list_master = COMP_GETPAR3 (Union_init, init, global_rotations_to_transform_list); + global_process_list_master = COMP_GETPAR3 (Union_init, init, global_process_list); + global_material_list_master = COMP_GETPAR3 (Union_init, init, global_material_list); + global_surface_list_master = COMP_GETPAR3 (Union_init, init, global_surface_list); + global_geometry_list_master = COMP_GETPAR3 (Union_init, init, global_geometry_list); + global_all_volume_logger_list_master = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + global_specific_volumes_logger_list_master = COMP_GETPAR3 (Union_init, init, global_specific_volumes_logger_list); + global_all_volume_abs_logger_list_master = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + global_specific_volumes_abs_logger_list_master = COMP_GETPAR3 (Union_init, init, global_specific_volumes_abs_logger_list); + global_tagging_conditional_list_master = COMP_GETPAR3 (Union_init, init, global_tagging_conditional_list); + global_master_list_master = COMP_GETPAR3 (Union_init, init, global_master_list); // It is possible to surpress warnings on starting volume by setting this to 1 starting_volume_warning = 0; - + // Start at 0 error messages, quit after 100. component_error_msg = 0; - + // For within_which_volume volume_0_found = 0; - + // For tagging - tagging_leaf_counter=0; - + tagging_leaf_counter = 0; + // For masks number_of_masks = 0; number_of_masked_volumes = 0; - + // For surfaces longest_surface_stack = 0; // Use sanitation #ifndef ANY_GEOMETRY_DETECTOR_DECLARE - printf("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); - exit(1); + printf ("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); + exit (1); #endif #ifdef ANY_GEOMETRY_DETECTOR_DECLARE - if (global_geometry_list_master->num_elements == 0) { - printf("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); - printf(" Union_master component named \"%s\" is before any Volumes in the instrument file. At least one Volume need to be defined before\n",NAME_CURRENT_COMP); - - exit(1); - } + if (global_geometry_list_master->num_elements == 0) { + printf ("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); + printf (" Union_master component named \"%s\" is before any Volumes in the instrument file. At least one Volume need to be defined before\n", + NAME_CURRENT_COMP); + + exit (1); + } #endif - + // Parameters describing the safety distances close to surfaces, as scattering should not occur closer to a surface than the // accuracy of the intersection calculation. safety_distance = 1E-11; - safety_distance2 = safety_distance*2.0; - + safety_distance2 = safety_distance * 2.0; + // Write information to the global_master_list_master about the current Union_master - sprintf(global_master_element.name,"%s",NAME_CURRENT_COMP); + sprintf (global_master_element.name, "%s", NAME_CURRENT_COMP); global_master_element.component_index = INDEX_CURRENT_COMP; - add_element_to_master_list(global_master_list_master, global_master_element); + add_element_to_master_list (global_master_list_master, global_master_element); if (inherit_number_of_scattering_events == 1 && global_master_list_master->num_elements == 1) { - printf("ERROR in Union_master with name %s. Inherit_number_of_scattering_events set to 1 for first Union_master component, but there is no preceeding Union_master component. Aborting.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR in Union_master with name %s. Inherit_number_of_scattering_events set to 1 for first Union_master component, but there is no preceeding " + "Union_master component. Aborting.\n", + NAME_CURRENT_COMP); + exit (1); } this_global_master_index = global_master_list_master->num_elements - 1; // Save the index for this master in global master list - + // Set the component index of the previous Union_master component if one exists - if (global_master_list_master->num_elements == 1) previous_master_index = 0; // no previous index - else previous_master_index = global_master_list_master->elements[global_master_list_master->num_elements-2].component_index; // -2 because of zero indexing and needing the previous index. - //printf("Assigned previous_master_index = %d \n",previous_master_index); - + if (global_master_list_master->num_elements == 1) + previous_master_index = 0; // no previous index + else + previous_master_index = global_master_list_master->elements[global_master_list_master->num_elements - 2] + .component_index; // -2 because of zero indexing and needing the previous index. + // printf("Assigned previous_master_index = %d \n",previous_master_index); + // All volumes in the global_geometry_list_master is being check for activity using the number_of_activations input made for each geometry (default is 1) // In addition it is counted how many volumes, mask volumes and masked volumes are active in this Union_master. - number_of_volumes = 1; // Starting with 1 as the surrounding vacuum is considered a volume - number_of_masks = 0; // Starting with 0 mask volumes + number_of_volumes = 1; // Starting with 1 as the surrounding vacuum is considered a volume + number_of_masks = 0; // Starting with 0 mask volumes number_of_masked_volumes = 0; // Starting with 0 masked volumes - for (iterator=0;iteratornum_elements;iterator++) { - if (global_geometry_list_master->elements[iterator].component_index < INDEX_CURRENT_COMP && global_geometry_list_master->elements[iterator].activation_counter > 0) { - global_geometry_list_master->elements[iterator].active = 1; - global_geometry_list_master->elements[iterator].activation_counter--; - number_of_volumes++; - if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 1) number_of_masks++; - if (global_geometry_list_master->elements[iterator].Volume->geometry.is_masked_volume == 1) number_of_masked_volumes++; - } else global_geometry_list_master->elements[iterator].active = 0; + for (iterator = 0; iterator < global_geometry_list_master->num_elements; iterator++) { + if (global_geometry_list_master->elements[iterator].component_index < INDEX_CURRENT_COMP + && global_geometry_list_master->elements[iterator].activation_counter > 0) { + global_geometry_list_master->elements[iterator].active = 1; + global_geometry_list_master->elements[iterator].activation_counter--; + number_of_volumes++; + if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 1) + number_of_masks++; + if (global_geometry_list_master->elements[iterator].Volume->geometry.is_masked_volume == 1) + number_of_masked_volumes++; + } else + global_geometry_list_master->elements[iterator].active = 0; } - + // Allocation of global lists geometry_component_index_list.num_elements = number_of_volumes; - geometry_component_index_list.elements = malloc( geometry_component_index_list.num_elements * sizeof(int)); + geometry_component_index_list.elements = malloc (geometry_component_index_list.num_elements * sizeof (int)); mask_volume_index_list.num_elements = number_of_masks; - if (number_of_masks >0) mask_volume_index_list.elements = malloc( number_of_masks * sizeof(int)); + if (number_of_masks > 0) + mask_volume_index_list.elements = malloc (number_of_masks * sizeof (int)); mask_status_list.num_elements = number_of_masks; - if (number_of_masks >0) mask_status_list.elements = malloc( number_of_masks * sizeof(int)); + if (number_of_masks > 0) + mask_status_list.elements = malloc (number_of_masks * sizeof (int)); current_mask_intersect_list_status.num_elements = number_of_masked_volumes; - if (number_of_masked_volumes >0) current_mask_intersect_list_status.elements = malloc( number_of_masked_volumes * sizeof(int)); - + if (number_of_masked_volumes > 0) + current_mask_intersect_list_status.elements = malloc (number_of_masked_volumes * sizeof (int)); + // Make a list of component index from each volume index volume_index = 0; - for (iterator=0;iteratornum_elements;iterator++) { + for (iterator = 0; iterator < global_geometry_list_master->num_elements; iterator++) { if (global_geometry_list_master->elements[iterator].active == 1) - geometry_component_index_list.elements[++volume_index] = global_geometry_list_master->elements[iterator].component_index; - + geometry_component_index_list.elements[++volume_index] = global_geometry_list_master->elements[iterator].component_index; } geometry_component_index_list.elements[0] = 0; // Volume 0 is never set in the above code, but should never be used. - + // The input for this component is done through a series of input components // All information needed is stored in global lists, some of which is printed here for an overview to the user. - MPI_MASTER( // MPI_MASTER ensures just one thread output this information to the user - if (verbal == 1) { - printf("---------------------------------------------------------------------\n"); - printf("global_process_list_master->num_elements: %d\n",global_process_list_master->num_elements); - for (iterator=0;iteratornum_elements;iterator++) { - printf("name of process [%d]: %s \n",iterator,global_process_list_master->elements[iterator].name); - printf("component index [%d]: %d \n",iterator,global_process_list_master->elements[iterator].component_index); - } - - printf("---------------------------------------------------------------------\n"); - printf("global_material_list_master->num_elements: %d\n",global_material_list_master->num_elements); - for (iterator=0;iteratornum_elements;iterator++) { - printf("name of material [%d]: %s \n",iterator,global_material_list_master->elements[iterator].name); - printf("component index [%d]: %d \n",iterator,global_material_list_master->elements[iterator].component_index); - printf("my_absoprtion [%d]: %f \n",iterator,global_material_list_master->elements[iterator].physics->my_a); - printf("number of processes [%d]: %d \n",iterator,global_material_list_master->elements[iterator].physics->number_of_processes); - } + MPI_MASTER ( // MPI_MASTER ensures just one thread output this information to the user + if (verbal == 1) { + printf ("---------------------------------------------------------------------\n"); + printf ("global_process_list_master->num_elements: %d\n", global_process_list_master->num_elements); + for (iterator = 0; iterator < global_process_list_master->num_elements; iterator++) { + printf ("name of process [%d]: %s \n", iterator, global_process_list_master->elements[iterator].name); + printf ("component index [%d]: %d \n", iterator, global_process_list_master->elements[iterator].component_index); + } - printf("---------------------------------------------------------------------\n"); - printf("global_geometry_list_master->num_elements: %d\n",global_material_list_master->num_elements); - for (iterator=0;iteratornum_elements;iterator++) { - if (global_geometry_list_master->elements[iterator].active == 1) { - printf("\n"); - printf("name of geometry [%d]: %s \n",iterator,global_geometry_list_master->elements[iterator].name); - printf("component index [%d]: %d \n",iterator,global_geometry_list_master->elements[iterator].component_index); - printf("Volume.name [%d]: %s \n",iterator,global_geometry_list_master->elements[iterator].Volume->name); - if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 0) { - printf("Volume.p_physics.is_vacuum [%d]: %d \n",iterator,global_geometry_list_master->elements[iterator].Volume->p_physics->is_vacuum); - printf("Volume.p_physics.my_absorption [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->p_physics->my_a); - printf("Volume.p_physics.number of processes [%d]: %d \n",iterator,global_geometry_list_master->elements[iterator].Volume->p_physics->number_of_processes); - } - printf("Volume.geometry.shape [%d]: %s \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.shape); - printf("Volume.geometry.center.x [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.center.x); - printf("Volume.geometry.center.y [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.center.y); - printf("Volume.geometry.center.z [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.center.z); - printf("Volume.geometry.rotation_matrix[0] [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][0],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][1],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][2]); - printf("Volume.geometry.rotation_matrix[1] [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][0],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][1],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][2]); - printf("Volume.geometry.rotation_matrix[2] [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][0],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][1],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][2]); - if (strcmp(global_geometry_list_master->elements[iterator].Volume->geometry.shape,"cylinder") == 0) { - printf("Volume.geometry.geometry_parameters.cyl_radius [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->cyl_radius); - printf("Volume.geometry.geometry_parameters.height [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->height); + printf ("---------------------------------------------------------------------\n"); + printf ("global_material_list_master->num_elements: %d\n", global_material_list_master->num_elements); + for (iterator = 0; iterator < global_material_list_master->num_elements; iterator++) { + printf ("name of material [%d]: %s \n", iterator, global_material_list_master->elements[iterator].name); + printf ("component index [%d]: %d \n", iterator, global_material_list_master->elements[iterator].component_index); + printf ("my_absoprtion [%d]: %f \n", iterator, global_material_list_master->elements[iterator].physics->my_a); + printf ("number of processes [%d]: %d \n", iterator, global_material_list_master->elements[iterator].physics->number_of_processes); + } + + printf ("---------------------------------------------------------------------\n"); + printf ("global_geometry_list_master->num_elements: %d\n", global_material_list_master->num_elements); + for (iterator = 0; iterator < global_geometry_list_master->num_elements; iterator++) { + if (global_geometry_list_master->elements[iterator].active == 1) { + printf ("\n"); + printf ("name of geometry [%d]: %s \n", iterator, global_geometry_list_master->elements[iterator].name); + printf ("component index [%d]: %d \n", iterator, global_geometry_list_master->elements[iterator].component_index); + printf ("Volume.name [%d]: %s \n", iterator, global_geometry_list_master->elements[iterator].Volume->name); + if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 0) { + printf ("Volume.p_physics.is_vacuum [%d]: %d \n", iterator, global_geometry_list_master->elements[iterator].Volume->p_physics->is_vacuum); + printf ("Volume.p_physics.my_absorption [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->p_physics->my_a); + printf ("Volume.p_physics.number of processes [%d]: %d \n", iterator, + global_geometry_list_master->elements[iterator].Volume->p_physics->number_of_processes); + } + printf ("Volume.geometry.shape [%d]: %s \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.shape); + printf ("Volume.geometry.center.x [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.center.x); + printf ("Volume.geometry.center.y [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.center.y); + printf ("Volume.geometry.center.z [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.center.z); + printf ("Volume.geometry.rotation_matrix[0] [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][0], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][1], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][2]); + printf ("Volume.geometry.rotation_matrix[1] [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][0], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][1], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][2]); + printf ("Volume.geometry.rotation_matrix[2] [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][0], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][1], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][2]); + if (strcmp (global_geometry_list_master->elements[iterator].Volume->geometry.shape, "cylinder") == 0) { + printf ("Volume.geometry.geometry_parameters.cyl_radius [%d]: %f \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->cyl_radius); + printf ("Volume.geometry.geometry_parameters.height [%d]: %f \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->height); + } + printf ("Volume.geometry.focus_data_array.elements[0].Aim [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.x, + global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.y, + global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.z); } - printf("Volume.geometry.focus_data_array.elements[0].Aim [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.x,global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.y,global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.z); } + printf ("---------------------------------------------------------------------\n"); + printf ("number_of_volumes = %d\n", number_of_volumes); + printf ("number_of_masks = %d\n", number_of_masks); + printf ("number_of_masked_volumes = %d\n", number_of_masked_volumes); } - printf("---------------------------------------------------------------------\n"); - printf("number_of_volumes = %d\n",number_of_volumes); - printf("number_of_masks = %d\n",number_of_masks); - printf("number_of_masked_volumes = %d\n",number_of_masked_volumes); - } - + ); // End MPI_MASTER - - + // --- Initialization tasks independent of volume stucture ----------------------- // Store a pointer to the conditional list and update the current index in that structure @@ -472,120 +496,118 @@ exit(-1); tagging_conditional_list = &global_tagging_conditional_list_master->elements[global_tagging_conditional_list_master->current_index++].conditional_list; free_tagging_conditioanl_list = 0; } else { - tagging_conditional_list = malloc(sizeof(struct conditional_list_struct)); + tagging_conditional_list = malloc (sizeof (struct conditional_list_struct)); tagging_conditional_list->num_elements = 0; free_tagging_conditioanl_list = 1; } - + // Find the maximum logger extend index so that the correct memory allocation can be performed later // Here the loggers applied to all volumes are searched, later this result is compared to volume specific loggers and updated max_conditional_extend_index = -1; - for (iterator=0;iteratornum_elements;iterator++) { + for (iterator = 0; iterator < global_all_volume_logger_list_master->num_elements; iterator++) { if (global_all_volume_logger_list_master->elements[iterator].logger->logger_extend_index > max_conditional_extend_index) { max_conditional_extend_index = global_all_volume_logger_list_master->elements[iterator].logger->logger_extend_index; } } - + // The absolute rotation of this component is saved for use in initialization - rot_transpose(ROT_A_CURRENT_COMP,master_transposed_rotation_matrix); - + rot_transpose (ROT_A_CURRENT_COMP, master_transposed_rotation_matrix); + // Preceeding componnets can add coordinates and rotations to global_positions_to_transform and global_rotations_to_transform // in order to have these transformed into the coordinate system of the next master compoent in the instrument file. // Here these transformations are performed, and the lists are cleared so no transformed information is further altered by // next master components. - + // Position transformation - for (iterator=0;iteratornum_elements;iterator++) { - non_rotated_position = coords_sub(*(global_positions_to_transform_list_master->positions[iterator]),POS_A_CURRENT_COMP); - *(global_positions_to_transform_list_master->positions[iterator]) = rot_apply(ROT_A_CURRENT_COMP,non_rotated_position); + for (iterator = 0; iterator < global_positions_to_transform_list_master->num_elements; iterator++) { + non_rotated_position = coords_sub (*(global_positions_to_transform_list_master->positions[iterator]), POS_A_CURRENT_COMP); + *(global_positions_to_transform_list_master->positions[iterator]) = rot_apply (ROT_A_CURRENT_COMP, non_rotated_position); } if (global_positions_to_transform_list_master->num_elements > 0) { global_positions_to_transform_list_master->num_elements = 0; - free(global_positions_to_transform_list_master->positions); + free (global_positions_to_transform_list_master->positions); } // Rotation transformation - for (iterator=0;iteratornum_elements;iterator++) { - //print_rotation(*(global_rotations_to_transform_list_master->rotations[iterator]),"rotation matrix to be updated"); - rot_mul(master_transposed_rotation_matrix,*(global_rotations_to_transform_list_master->rotations[iterator]),temp_rotation_matrix); - rot_copy(*(global_rotations_to_transform_list_master->rotations[iterator]),temp_rotation_matrix); + for (iterator = 0; iterator < global_rotations_to_transform_list_master->num_elements; iterator++) { + // print_rotation(*(global_rotations_to_transform_list_master->rotations[iterator]),"rotation matrix to be updated"); + rot_mul (master_transposed_rotation_matrix, *(global_rotations_to_transform_list_master->rotations[iterator]), temp_rotation_matrix); + rot_copy (*(global_rotations_to_transform_list_master->rotations[iterator]), temp_rotation_matrix); } if (global_rotations_to_transform_list_master->num_elements > 0) { global_rotations_to_transform_list_master->num_elements = 0; - free(global_rotations_to_transform_list_master->rotations); + free (global_rotations_to_transform_list_master->rotations); } - // --- Definition of volumes and loading of appropriate data ----------------------- - + // The information stored in global lists is to be stored in one array of structures that is allocated here - Volumes = malloc(number_of_volumes * sizeof(struct Volume_struct*)); - scattered_flag = malloc(number_of_volumes*sizeof(int)); - scattered_flag_VP = (int**) malloc(number_of_volumes * sizeof(int*)); - number_of_processes_array = malloc(number_of_volumes*sizeof(int)); - + Volumes = malloc (number_of_volumes * sizeof (struct Volume_struct*)); + scattered_flag = malloc (number_of_volumes * sizeof (int)); + scattered_flag_VP = (int**)malloc (number_of_volumes * sizeof (int*)); + number_of_processes_array = malloc (number_of_volumes * sizeof (int)); + // The mcdisplay functions need access to the other geomtries, but can not use the Volumes struct because of order of definition. // A separate list of pointers to the geometry structures is thus allocated - Geometries = malloc(number_of_volumes * sizeof(struct geometry_struct *)); - + Geometries = malloc (number_of_volumes * sizeof (struct geometry_struct*)); + // When activation counter is used to have several copies of one volume, it can become necessary to have soft copies of volumes // Not all of these will necessarily be allocated or used. - Volume_copies = malloc(number_of_volumes * sizeof(struct Volume_struct *)); + Volume_copies = malloc (number_of_volumes * sizeof (struct Volume_struct*)); Volume_copies_allocated.num_elements = 0; - + // The central structure is called a "Volume", it describes a region in space with certain scattering processes and absorption cross section // --- Volume 0 ------------------------------------------------------------------------------------------------ // Volume 0 is the vacuum surrounding the experiment (infinite, everywhere) and its properties are hardcoded here - Volumes[0] = malloc(sizeof(struct Volume_struct)); - strcpy(Volumes[0]->name,"Surrounding vacuum"); + Volumes[0] = malloc (sizeof (struct Volume_struct)); + strcpy (Volumes[0]->name, "Surrounding vacuum"); // Assign geometry - + // This information is meaningless for volume 0, and is never be acsessed in the logic. Volumes[0]->geometry.priority_value = 0.0; Volumes[0]->geometry.center.x = 0; Volumes[0]->geometry.center.y = 0; Volumes[0]->geometry.center.z = 0; - strcpy(Volumes[0]->geometry.shape,"vacuum"); + strcpy (Volumes[0]->geometry.shape, "vacuum"); Volumes[0]->geometry.eShape = surroundings; Volumes[0]->geometry.within_function = &r_within_surroundings; // Always returns 1 // No physics struct allocated Volumes[0]->p_physics = NULL; number_of_processes_array[volume_index] = 0; - + // These are never used for volume 0, but by setting the length to 0 it is automatically skipped in many forloops without the need for an if statement - Volumes[0]->geometry.children.num_elements=0; - Volumes[0]->geometry.direct_children.num_elements=0; - Volumes[0]->geometry.destinations_list.num_elements=0; - Volumes[0]->geometry.reduced_destinations_list.num_elements=0; - + Volumes[0]->geometry.children.num_elements = 0; + Volumes[0]->geometry.direct_children.num_elements = 0; + Volumes[0]->geometry.destinations_list.num_elements = 0; + Volumes[0]->geometry.reduced_destinations_list.num_elements = 0; + Volumes[0]->geometry.is_exit_volume = 0; Volumes[0]->geometry.masked_by_list.num_elements = 0; Volumes[0]->geometry.mask_list.num_elements = 0; Volumes[0]->geometry.masked_by_mask_index_list.num_elements = 0; - Volumes[0]->geometry.mask_mode=0; - Volumes[0]->geometry.is_mask_volume=0; - Volumes[0]->geometry.is_masked_volume=0; - + Volumes[0]->geometry.mask_mode = 0; + Volumes[0]->geometry.is_mask_volume = 0; + Volumes[0]->geometry.is_masked_volume = 0; + // A pointer to the geometry structure Geometries[0] = &Volumes[0]->geometry; - + // Logging initialization Volumes[0]->loggers.num_elements = 0; Volumes[0]->abs_loggers.num_elements = 0; - - + // --- Loop over user defined volumes ------------------------------------------------------------------------ // Here the user defined volumes are loaded into the volume structure that is used in the ray-tracing // algorithm. Not all user defined volumes are used, some could be used by a previous master, some // could be used by the previous master, this one, and perhaps more. This is controlled by the // activation counter input for geometries, and is here condensed to the active variable. // Volumes that were used before - + max_number_of_processes = 0; // The maximum number of processes in a volume is assumed 0 and updated during the following loop - + volume_index = 0; mask_index_main = 0; - for (geometry_list_index=0;geometry_list_indexnum_elements;geometry_list_index++) { + for (geometry_list_index = 0; geometry_list_index < global_geometry_list_master->num_elements; geometry_list_index++) { if (global_geometry_list_master->elements[geometry_list_index].active == 1) { // Only include the volume if it is active volume_index++; // Connect a volume for each of the geometry.comp instances in the McStas instrument files @@ -594,147 +616,153 @@ exit(-1); Volumes[volume_index] = global_geometry_list_master->elements[geometry_list_index].Volume; } else { // Since this volume is still needed more than this once, we need to make a shallow copy and use instead - - Volume_copies[volume_index] = malloc(sizeof(struct Volume_struct)); + + Volume_copies[volume_index] = malloc (sizeof (struct Volume_struct)); *(Volume_copies[volume_index]) = *global_geometry_list_master->elements[geometry_list_index].Volume; // Makes shallow copy Volumes[volume_index] = Volume_copies[volume_index]; - add_element_to_int_list(&Volume_copies_allocated,volume_index); // Keep track of dynamically allocated volumes in order to free them in FINALLY. - + add_element_to_int_list (&Volume_copies_allocated, volume_index); // Keep track of dynamically allocated volumes in order to free them in FINALLY. + // The geometry storage needs a shallow copy as well (hard copy not necessary for any current geometries), may need changes in future // A simple copy_geometry_parameters function is added to the geometry in each geometry component - Volumes[volume_index]->geometry.geometry_parameters = Volumes[volume_index]->geometry.copy_geometry_parameters(&global_geometry_list_master->elements[geometry_list_index].Volume->geometry.geometry_parameters); - - // Copy focusing data too, it will be modified based on this master components rotation, so should not be reused - copy_focus_data_array(&global_geometry_list_master->elements[geometry_list_index].Volume->geometry.focus_data_array, - &Volumes[volume_index]->geometry.focus_data_array); + Volumes[volume_index]->geometry.geometry_parameters = Volumes[volume_index]->geometry.copy_geometry_parameters ( + &global_geometry_list_master->elements[geometry_list_index].Volume->geometry.geometry_parameters); + // Copy focusing data too, it will be modified based on this master components rotation, so should not be reused + copy_focus_data_array (&global_geometry_list_master->elements[geometry_list_index].Volume->geometry.focus_data_array, + &Volumes[volume_index]->geometry.focus_data_array); } - + // This section identifies the different non isotropic processes in the current volume and give them appropriate transformation matrices // Identify the number of non isotropic processes in a material (this code can be safely executed for the same material many times) // A setting of -1 means no transformation necessary, other settings are assigned a unique identifier instead non_isotropic_found = 0; - for (iterator=0;iteratorp_physics->number_of_processes;iterator++) { + for (iterator = 0; iterator < Volumes[volume_index]->p_physics->number_of_processes; iterator++) { if (Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index != -1) { - Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index = non_isotropic_found; - non_isotropic_found++; + Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index = non_isotropic_found; + non_isotropic_found++; } } - - // Update focusing absolute_rotation before running through processes, then this will be the baseline for nonisotropic processes - //rot_copy(Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation, ROT_A_CURRENT_COMP); - - Volumes[volume_index]->geometry.focus_array_indices.num_elements=0; + + // Update focusing absolute_rotation before running through processes, then this will be the baseline for nonisotropic processes + // rot_copy(Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation, ROT_A_CURRENT_COMP); + + Volumes[volume_index]->geometry.focus_array_indices.num_elements = 0; // For the non_isotropic volumes found, rotation matrices need to be allocated and calculated if (non_isotropic_found > 0) { // Allocation of rotation and transpose rotation matrices if (Volumes[volume_index]->geometry.process_rot_allocated == 0) { - Volumes[volume_index]->geometry.process_rot_matrix_array = malloc(non_isotropic_found * sizeof(Rotation)); - Volumes[volume_index]->geometry.transpose_process_rot_matrix_array = malloc(non_isotropic_found * sizeof(Rotation)); + Volumes[volume_index]->geometry.process_rot_matrix_array = malloc (non_isotropic_found * sizeof (Rotation)); + Volumes[volume_index]->geometry.transpose_process_rot_matrix_array = malloc (non_isotropic_found * sizeof (Rotation)); Volumes[volume_index]->geometry.process_rot_allocated = 1; } - + // Calculation of the appropriate rotation matrices for transformation between Union_master and the process in a given volume. non_isotropic_found = 0; - for (iterator=0;iteratorp_physics->number_of_processes;iterator++) { + for (iterator = 0; iterator < Volumes[volume_index]->p_physics->number_of_processes; iterator++) { if (Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index != -1) { // Transformation for each process / geometry combination - + // The focus vector is given in relation to the geometry and needs to be transformed to the process // Work on temporary_focus_data_element which is added to the focus_data_array_at the end temporary_focus_data = Volumes[volume_index]->geometry.focus_data_array.elements[0]; - + // Correct for process rotation - // Aim - temporary_focus_data.Aim = rot_apply(Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix,temporary_focus_data.Aim); - - // Absolute rotation of focus_data needs to updated using the rotation matrix from this process (before it is combined with the rotation matrix of the geometry) - rot_mul(Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix, temporary_focus_data.absolute_rotation, temp_rotation_matrix); - rot_copy(temporary_focus_data.absolute_rotation, temp_rotation_matrix); - + // Aim + temporary_focus_data.Aim = rot_apply (Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix, temporary_focus_data.Aim); + + // Absolute rotation of focus_data needs to updated using the rotation matrix from this process (before it is combined with the rotation matrix of the + // geometry) + rot_mul (Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix, temporary_focus_data.absolute_rotation, + temp_rotation_matrix); + rot_copy (temporary_focus_data.absolute_rotation, temp_rotation_matrix); + // Add element to focus_array_indices // focus_array_indices refers to the correct element in focus_data_array for this volume/process combination // focus_data_array[0] is the isotropic version in all cases, so the first non_isotropic goes to focus_data_array[1] // and so forth. When a process is isotropic, this array is appended with a zero. // The focus_array_indices maps process numbers to the correct focus_data_array index. - add_element_to_int_list(&Volumes[volume_index]->geometry.focus_array_indices, non_isotropic_found+1); - + add_element_to_int_list (&Volumes[volume_index]->geometry.focus_array_indices, non_isotropic_found + 1); + // Add the new focus_data element to this volumes focus_data_array. - add_element_to_focus_data_array(&Volumes[volume_index]->geometry.focus_data_array, temporary_focus_data); - + add_element_to_focus_data_array (&Volumes[volume_index]->geometry.focus_data_array, temporary_focus_data); + // Quick error check to see the length is correct which indirectly confirms the indices are correct if (Volumes[volume_index]->geometry.focus_data_array.num_elements != non_isotropic_found + 2) { - printf("ERROR, focus_data_array length for volume %s inconsistent with number of non isotropic processes found!\n",Volumes[volume_index]->name); - exit(1); + printf ("ERROR, focus_data_array length for volume %s inconsistent with number of non isotropic processes found!\n", Volumes[volume_index]->name); + exit (1); } - - // Create rotation matrix for this specific volume / process combination to transform from master coordinate system to the non-isotropics process coordinate system - // This is done by multipling the transpose master component roration matrix, the volume rotation, and then the process rotation matrix onto the velocity / wavevector - rot_mul(Volumes[volume_index]->geometry.rotation_matrix,master_transposed_rotation_matrix,temp_rotation_matrix); - rot_mul(Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix,temp_rotation_matrix,Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found]); - + + // Create rotation matrix for this specific volume / process combination to transform from master coordinate system to the non-isotropics process + // coordinate system This is done by multipling the transpose master component roration matrix, the volume rotation, and then the process rotation + // matrix onto the velocity / wavevector + rot_mul (Volumes[volume_index]->geometry.rotation_matrix, master_transposed_rotation_matrix, temp_rotation_matrix); + rot_mul (Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix, temp_rotation_matrix, + Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found]); + // Need to transpose as well to transform back to the master coordinate system - rot_transpose(Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found],Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found]); + rot_transpose (Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found], + Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found]); // Debug print - //print_rotation(Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found],"Process rotation matrix"); - //print_rotation(Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found],"Transpose process rotation matrix"); - + // print_rotation(Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found],"Process rotation matrix"); + // print_rotation(Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found],"Transpose process rotation matrix"); + non_isotropic_found++; } else { // This process can use the standard isotropic focus_data_array which is indexed zero. - add_element_to_int_list(&Volumes[volume_index]->geometry.focus_array_indices,0); + add_element_to_int_list (&Volumes[volume_index]->geometry.focus_array_indices, 0); } } } else { - // No non isotropic volumes found, focus_array_indices should just be a list of 0's of same length as the number of processes. - // In this way all processes use the isotropic focus_data structure - Volumes[volume_index]->geometry.focus_array_indices.elements = malloc(Volumes[volume_index]->p_physics->number_of_processes * sizeof(int)); - for (iterator=0;iteratorp_physics->number_of_processes;iterator++) + // No non isotropic volumes found, focus_array_indices should just be a list of 0's of same length as the number of processes. + // In this way all processes use the isotropic focus_data structure + Volumes[volume_index]->geometry.focus_array_indices.elements = malloc (Volumes[volume_index]->p_physics->number_of_processes * sizeof (int)); + for (iterator = 0; iterator < Volumes[volume_index]->p_physics->number_of_processes; iterator++) Volumes[volume_index]->geometry.focus_array_indices.elements[iterator] = 0; - } - - rot_copy(Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation, ROT_A_CURRENT_COMP); - + + rot_copy (Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation, ROT_A_CURRENT_COMP); + // This component works in its local coordinate system, and thus all information from the input components should be transformed to its coordinate system. // All the input components saved their absolute rotation/position into their Volume structure, and the absolute rotation of the current component is known. // The next section finds the relative rotation and translation of all the volumes and the master component. - + // Transform the rotation matrices for each volume - rot_mul(ROT_A_CURRENT_COMP,Volumes[volume_index]->geometry.transpose_rotation_matrix,temp_rotation_matrix); + rot_mul (ROT_A_CURRENT_COMP, Volumes[volume_index]->geometry.transpose_rotation_matrix, temp_rotation_matrix); // Copy the result back to the volumes structure - rot_copy(Volumes[volume_index]->geometry.rotation_matrix,temp_rotation_matrix); + rot_copy (Volumes[volume_index]->geometry.rotation_matrix, temp_rotation_matrix); // Now update the transpose as well - rot_transpose(Volumes[volume_index]->geometry.rotation_matrix,temp_rotation_matrix); - rot_copy(Volumes[volume_index]->geometry.transpose_rotation_matrix,temp_rotation_matrix); - + rot_transpose (Volumes[volume_index]->geometry.rotation_matrix, temp_rotation_matrix); + rot_copy (Volumes[volume_index]->geometry.transpose_rotation_matrix, temp_rotation_matrix); + // Transform the position for each volume non_rotated_position.x = Volumes[volume_index]->geometry.center.x - POS_A_CURRENT_COMP.x; non_rotated_position.y = Volumes[volume_index]->geometry.center.y - POS_A_CURRENT_COMP.y; non_rotated_position.z = Volumes[volume_index]->geometry.center.z - POS_A_CURRENT_COMP.z; - rot_transpose(ROT_A_CURRENT_COMP,temp_rotation_matrix); // REVIEW LINE - rotated_position = rot_apply(ROT_A_CURRENT_COMP, non_rotated_position); + rot_transpose (ROT_A_CURRENT_COMP, temp_rotation_matrix); // REVIEW LINE + rotated_position = rot_apply (ROT_A_CURRENT_COMP, non_rotated_position); Volumes[volume_index]->geometry.center.x = rotated_position.x; Volumes[volume_index]->geometry.center.y = rotated_position.y; Volumes[volume_index]->geometry.center.z = rotated_position.z; - + // Use same rotation on the aim vector of the isotropic focus_data element - Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim = rot_apply(Volumes[volume_index]->geometry.rotation_matrix, Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim); - + Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim + = rot_apply (Volumes[volume_index]->geometry.rotation_matrix, Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim); + // To allocate enough memory to hold information on all processes, the maximum of these is updated if this volume has more if (Volumes[volume_index]->p_physics->number_of_processes > max_number_of_processes) - max_number_of_processes = Volumes[volume_index]->p_physics->number_of_processes; - + max_number_of_processes = Volumes[volume_index]->p_physics->number_of_processes; + // Allocate memory to scattered_flag_VP (holds statistics for scatterings in each process of the volume) - scattered_flag_VP[volume_index] = malloc(Volumes[volume_index]->p_physics->number_of_processes * sizeof(int)); + scattered_flag_VP[volume_index] = malloc (Volumes[volume_index]->p_physics->number_of_processes * sizeof (int)); number_of_processes_array[volume_index] = Volumes[volume_index]->p_physics->number_of_processes; - + // Normalizing and error checking process interact fraction - number_of_process_interacts_set = 0; total_process_interact=0; - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { + number_of_process_interacts_set = 0; + total_process_interact = 0; + for (process_index = 0; process_index < Volumes[volume_index]->p_physics->number_of_processes; process_index++) { if (Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact != -1) { number_of_process_interacts_set++; total_process_interact += Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact; @@ -742,405 +770,439 @@ exit(-1); index_of_lacking_process = process_index; } } - - if (number_of_process_interacts_set == 0) Volumes[volume_index]->p_physics->interact_control = 0; - else Volumes[volume_index]->p_physics->interact_control = 1; - + + if (number_of_process_interacts_set == 0) + Volumes[volume_index]->p_physics->interact_control = 0; + else + Volumes[volume_index]->p_physics->interact_control = 1; + // If all are set, check if they need renormalization so that the sum is one. if (number_of_process_interacts_set == Volumes[volume_index]->p_physics->number_of_processes) { if (total_process_interact > 1.001 || total_process_interact < 0.999) { - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact = Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact/total_process_interact; + for (process_index = 0; process_index < Volumes[volume_index]->p_physics->number_of_processes; process_index++) { + Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact + = Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact / total_process_interact; } } - } else if ( number_of_process_interacts_set != 0) { - if (number_of_process_interacts_set == Volumes[volume_index]->p_physics->number_of_processes - 1) {// If all but one is set, it is an easy fix + } else if (number_of_process_interacts_set != 0) { + if (number_of_process_interacts_set == Volumes[volume_index]->p_physics->number_of_processes - 1) { // If all but one is set, it is an easy fix Volumes[volume_index]->p_physics->p_scattering_array[index_of_lacking_process].process_p_interact = 1 - total_process_interact; if (total_process_interact >= 1) { - printf("ERROR, material %s has a total interact_fraction above 1 and a process without an interact_fraction. Either set all so they can be renormalized, or have a sum below 1, so that the last can have 1 - sum.\n",Volumes[volume_index]->p_physics->name); - exit(1); + printf ("ERROR, material %s has a total interact_fraction above 1 and a process without an interact_fraction. Either set all so they can be " + "renormalized, or have a sum below 1, so that the last can have 1 - sum.\n", + Volumes[volume_index]->p_physics->name); + exit (1); } } else { - printf("ERROR, material %s needs to have all, all minus one or none of its processes with an interact_fraction \n",Volumes[volume_index]->p_physics->name); - exit(1); + printf ("ERROR, material %s needs to have all, all minus one or none of its processes with an interact_fraction \n", + Volumes[volume_index]->p_physics->name); + exit (1); } } - + // Some initialization can only happen after the rotation matrix relative to the master is known // Such initialization is placed in the geometry component, and executed here through a function pointer - Volumes[volume_index]->geometry.initialize_from_main_function(&Volumes[volume_index]->geometry); - + Volumes[volume_index]->geometry.initialize_from_main_function (&Volumes[volume_index]->geometry); + // Add pointer to geometry to Geometries Geometries[volume_index] = &Volumes[volume_index]->geometry; - + // Initialize mask intersect list Volumes[volume_index]->geometry.mask_intersect_list.num_elements = 0; - + // Here the mask_list and masked_by_list for the volume is updated from component index values to volume indexes - for (iterator=0;iteratorgeometry.mask_list.num_elements;iterator++) - Volumes[volume_index]->geometry.mask_list.elements[iterator] = find_on_int_list(geometry_component_index_list,Volumes[volume_index]->geometry.mask_list.elements[iterator]); - - for (iterator=0;iteratorgeometry.masked_by_list.num_elements;iterator++) - Volumes[volume_index]->geometry.masked_by_list.elements[iterator] = find_on_int_list(geometry_component_index_list,Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); - + for (iterator = 0; iterator < Volumes[volume_index]->geometry.mask_list.num_elements; iterator++) + Volumes[volume_index]->geometry.mask_list.elements[iterator] + = find_on_int_list (geometry_component_index_list, Volumes[volume_index]->geometry.mask_list.elements[iterator]); + + for (iterator = 0; iterator < Volumes[volume_index]->geometry.masked_by_list.num_elements; iterator++) + Volumes[volume_index]->geometry.masked_by_list.elements[iterator] + = find_on_int_list (geometry_component_index_list, Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); + // If the volume is a mask, its volume number is added to the mask_volume_index list so volume index can be converted to mask_index. - if (Volumes[volume_index]->geometry.is_mask_volume == 1) Volumes[volume_index]->geometry.mask_index = mask_index_main; - if (Volumes[volume_index]->geometry.is_mask_volume == 1) mask_volume_index_list.elements[mask_index_main++] = volume_index; - + if (Volumes[volume_index]->geometry.is_mask_volume == 1) + Volumes[volume_index]->geometry.mask_index = mask_index_main; + if (Volumes[volume_index]->geometry.is_mask_volume == 1) + mask_volume_index_list.elements[mask_index_main++] = volume_index; + // Check all loggers assosiated with this volume and update the max_conditional_extend_index if necessary - for (iterator=0;iteratorloggers.num_elements;iterator++) { - for (process_index=0;process_indexloggers.p_logger_volume[iterator].num_elements;process_index++) { + for (iterator = 0; iterator < Volumes[volume_index]->loggers.num_elements; iterator++) { + for (process_index = 0; process_index < Volumes[volume_index]->loggers.p_logger_volume[iterator].num_elements; process_index++) { if (Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process[process_index] != NULL) { if (Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process[process_index]->logger_extend_index > max_conditional_extend_index) max_conditional_extend_index = Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process[process_index]->logger_extend_index; } } } - - // Find longest surface length - int surfaces_in_this_stack; - for (iterator=0;iteratorgeometry.number_of_faces;iterator++) { - surfaces_in_this_stack = Volumes[volume_index]->geometry.surface_stack_for_each_face[iterator]->number_of_surfaces; + + // Find longest surface length + int surfaces_in_this_stack; + for (iterator = 0; iterator < Volumes[volume_index]->geometry.number_of_faces; iterator++) { + surfaces_in_this_stack = Volumes[volume_index]->geometry.surface_stack_for_each_face[iterator]->number_of_surfaces; if (surfaces_in_this_stack > longest_surface_stack) { - longest_surface_stack = surfaces_in_this_stack; + longest_surface_stack = surfaces_in_this_stack; } } - } } // Initialization for each volume done - + // ------- Initialization of ray-tracing algorithm ------------------------------------ - - my_trace = malloc(max_number_of_processes*sizeof(double)); - my_trace_fraction_control = malloc(max_number_of_processes*sizeof(double)); - + + my_trace = malloc (max_number_of_processes * sizeof (double)); + my_trace_fraction_control = malloc (max_number_of_processes * sizeof (double)); + // All geometries can have 2 intersections currently, when this changes the maximum number of solutions need to be reported to the Union_master. number_of_solutions = &number_of_solutions_static; component_error_msg = 0; - + // Pre allocated memory for destination list search - pre_allocated1 = malloc(number_of_volumes * sizeof(int)); - pre_allocated2 = malloc(number_of_volumes * sizeof(int)); - pre_allocated3 = malloc(number_of_volumes * sizeof(int)); - + pre_allocated1 = malloc (number_of_volumes * sizeof (int)); + pre_allocated2 = malloc (number_of_volumes * sizeof (int)); + pre_allocated3 = malloc (number_of_volumes * sizeof (int)); + // Pre allocated memory to fit all surfaces in an interface - interface_stack.number_of_surfaces = 2*longest_surface_stack; - interface_stack.p_surface_array = malloc(interface_stack.number_of_surfaces*sizeof(struct surface_process_struct*)); - - + interface_stack.number_of_surfaces = 2 * longest_surface_stack; + interface_stack.p_surface_array = malloc (interface_stack.number_of_surfaces * sizeof (struct surface_process_struct*)); + // Allocate memory for logger_conditional_extend_array used in the extend section of the master component, if it is needed. if (max_conditional_extend_index > -1) { - logger_conditional_extend_array = malloc((max_conditional_extend_index + 1)*sizeof(int)); + logger_conditional_extend_array = malloc ((max_conditional_extend_index + 1) * sizeof (int)); } - + // In this function different lists of volume indecies are generated. They are the key to the speed of the component and central for the logic. // They use simple set algebra to generate these lists for each volume: // Children list for volume n: Indicies of volumes that are entirely within the set described by volume n // Overlap list for volume n: Indicies of volume that contains some of the set described by volume n (excluding volume n) - // Intersect check list for volume n: Indicies of volumes to check for intersection if a ray originates from volume n (is generated from the children and overlap lists) - // Parents list for volume n: Indicies of volumes that contain the entire set of volume n - // Grandparents lists for volume n: Indicies of volumes that contain the entire set of at least one parent of volume n - // Destination list for volume n: Indicies of volumes that could be the destination volume when a ray leaves volume n - // The overlap, parents and grandparents lists are local variables in the function, and not in the main scope. - - generate_lists(Volumes, &starting_lists, number_of_volumes, list_verbal); - + // Intersect check list for volume n: Indicies of volumes to check for intersection if a ray originates from volume n (is generated from the children and + // overlap lists) Parents list for volume n: Indicies of volumes that contain the entire set of volume n Grandparents lists for volume n: Indicies of volumes + // that contain the entire set of at least one parent of volume n Destination list for volume n: Indicies of volumes that could be the destination volume when a + // ray leaves volume n The overlap, parents and grandparents lists are local variables in the function, and not in the main scope. + + generate_lists (Volumes, &starting_lists, number_of_volumes, list_verbal); + // Generate "safe starting list", which contains all volumes that the ray may enter from other components // These are all volumes without scattering or absorption - + // Updating mask lists from volume index to global_mask_indices // Filling out the masked_by list that uses mask indices - for (volume_index=0;volume_indexgeometry.masked_by_mask_index_list.num_elements = Volumes[volume_index]->geometry.masked_by_list.num_elements; - Volumes[volume_index]->geometry.masked_by_mask_index_list.elements = malloc(Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements * sizeof(int)); - for (iterator=0;iteratorgeometry.masked_by_list.num_elements;iterator++) - Volumes[volume_index]->geometry.masked_by_mask_index_list.elements[iterator] = find_on_int_list(mask_volume_index_list,Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); + Volumes[volume_index]->geometry.masked_by_mask_index_list.elements + = malloc (Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements * sizeof (int)); + for (iterator = 0; iterator < Volumes[volume_index]->geometry.masked_by_list.num_elements; iterator++) + Volumes[volume_index]->geometry.masked_by_mask_index_list.elements[iterator] + = find_on_int_list (mask_volume_index_list, Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); } - - + int volume_index_main; - + // Checking for equal priorities in order to alert the user to a potential input error - for (volume_index_main=0;volume_index_maingeometry.priority_value == Volumes[volume_index]->geometry.priority_value && volume_index_main != volume_index) { - if (Volumes[volume_index_main]->geometry.is_mask_volume == 0 && Volumes[volume_index]->geometry.is_mask_volume == 0) { - // Priority of masks do not matter - printf("ERROR in Union_master with name %s. The volumes named %s and %s have the same priority. Change the priorities so the one present in case of overlap has highest priority.\n",NAME_CURRENT_COMP,Volumes[volume_index_main]->name,Volumes[volume_index]->name); - exit(1); - } - } - } - - // Printing the generated lists for all volumes. - MPI_MASTER( - if (verbal) printf("\n ---- Overview of the lists generated for each volume ---- \n"); - - - if (verbal) printf("List overview for surrounding vacuum\n"); - for (volume_index_main=0;volume_index_maingeometry.is_mask_volume == 0 || - Volumes[volume_index_main]->geometry.is_masked_volume == 0 || - Volumes[volume_index_main]->geometry.is_exit_volume == 0) { - printf("List overview for %s with %s shape made of %s\n", - Volumes[volume_index_main]->name, - Volumes[volume_index_main]->geometry.shape, - Volumes[volume_index_main]->p_physics->name); - } else { - printf("List overview for %s with shape %s\n", - Volumes[volume_index_main]->name, - Volumes[volume_index_main]->geometry.shape); - } + for (volume_index_main = 0; volume_index_main < number_of_volumes; volume_index_main++) { + for (volume_index = 0; volume_index < number_of_volumes; volume_index++) + if (Volumes[volume_index_main]->geometry.priority_value == Volumes[volume_index]->geometry.priority_value && volume_index_main != volume_index) { + if (Volumes[volume_index_main]->geometry.is_mask_volume == 0 && Volumes[volume_index]->geometry.is_mask_volume == 0) { + // Priority of masks do not matter + printf ("ERROR in Union_master with name %s. The volumes named %s and %s have the same priority. Change the priorities so the one present in case of " + "overlap has highest priority.\n", + NAME_CURRENT_COMP, Volumes[volume_index_main]->name, Volumes[volume_index]->name); + exit (1); } } - - if (verbal) sprintf(string_output,"Children for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.children,string_output); - - if (verbal) sprintf(string_output,"Direct_children for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.direct_children,string_output); - - if (verbal) sprintf(string_output,"Intersect_check_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.intersect_check_list,string_output); - - if (verbal) sprintf(string_output,"Mask_intersect_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.mask_intersect_list,string_output); - - if (verbal) sprintf(string_output,"Destinations_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.destinations_list,string_output); - - //if (verbal) sprintf(string_output,"Destinations_logic_list for Volume %d",volume_index_main); - //if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.destinations_logic_list,string_output); - - if (verbal) sprintf(string_output,"Reduced_destinations_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.reduced_destinations_list,string_output); - - if (verbal) sprintf(string_output,"Next_volume_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.next_volume_list,string_output); - - if (verbal) { - if (volume_index_main != 0) - printf(" Is_vacuum for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->p_physics->is_vacuum); - } - if (verbal) { - if (volume_index_main != 0) - printf(" is_mask_volume for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.is_mask_volume); - } - if (verbal) { - if (volume_index_main != 0) - printf(" is_masked_volume for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.is_masked_volume); - } - if (verbal) { - if (volume_index_main != 0) - printf(" is_exit_volume for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.is_exit_volume); - } - - if (verbal) sprintf(string_output,"mask_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.mask_list,string_output); - - if (verbal) sprintf(string_output,"masked_by_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.masked_by_list,string_output); - - if (verbal) sprintf(string_output,"masked_by_mask_index_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.masked_by_mask_index_list,string_output); - - if (verbal) printf(" mask_mode for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.mask_mode); - if (verbal) printf("\n"); } - ) // End of MPI_MASTER - + + // Printing the generated lists for all volumes. + MPI_MASTER (if (verbal) printf ("\n ---- Overview of the lists generated for each volume ---- \n"); + + if (verbal) printf ("List overview for surrounding vacuum\n"); + for (volume_index_main = 0; volume_index_main < number_of_volumes; volume_index_main++) { + if (verbal) { + if (volume_index_main != 0) { + if (Volumes[volume_index_main]->geometry.is_mask_volume == 0 || Volumes[volume_index_main]->geometry.is_masked_volume == 0 + || Volumes[volume_index_main]->geometry.is_exit_volume == 0) { + printf ("List overview for %s with %s shape made of %s\n", Volumes[volume_index_main]->name, Volumes[volume_index_main]->geometry.shape, + Volumes[volume_index_main]->p_physics->name); + } else { + printf ("List overview for %s with shape %s\n", Volumes[volume_index_main]->name, Volumes[volume_index_main]->geometry.shape); + } + } + } + + if (verbal) + sprintf (string_output, "Children for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.children, string_output); + + if (verbal) + sprintf (string_output, "Direct_children for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.direct_children, string_output); + + if (verbal) + sprintf (string_output, "Intersect_check_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.intersect_check_list, string_output); + + if (verbal) + sprintf (string_output, "Mask_intersect_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.mask_intersect_list, string_output); + + if (verbal) + sprintf (string_output, "Destinations_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.destinations_list, string_output); + + // if (verbal) sprintf(string_output,"Destinations_logic_list for Volume %d",volume_index_main); + // if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.destinations_logic_list,string_output); + + if (verbal) + sprintf (string_output, "Reduced_destinations_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.reduced_destinations_list, string_output); + + if (verbal) + sprintf (string_output, "Next_volume_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.next_volume_list, string_output); + + if (verbal) { + if (volume_index_main != 0) + printf (" Is_vacuum for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->p_physics->is_vacuum); + } + if (verbal) { + if (volume_index_main != 0) + printf (" is_mask_volume for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.is_mask_volume); + } + if (verbal) { + if (volume_index_main != 0) + printf (" is_masked_volume for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.is_masked_volume); + } + if (verbal) { + if (volume_index_main != 0) + printf (" is_exit_volume for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.is_exit_volume); + } + + if (verbal) + sprintf (string_output, "mask_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.mask_list, string_output); + + if (verbal) + sprintf (string_output, "masked_by_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.masked_by_list, string_output); + + if (verbal) + sprintf (string_output, "masked_by_mask_index_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.masked_by_mask_index_list, string_output); + + if (verbal) + printf (" mask_mode for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.mask_mode); + if (verbal) + printf ("\n"); + }) // End of MPI_MASTER // Initializing intersection_time_table - // The intersection time table contains all information on intersection times for the current position/direction, and is cleared everytime a ray changes direction. - // Not all entries needs to be calculated, so there is a variable that keeps track of which intersection times have been calculated in order to avoid redoing that. - // When the intersections times are calculated for a volume, all future intersections are kept in the time table. - // Thus the memory allocation have to take into account how many intersections there can be with each volume, but it is currently set to 2, but can easily be changed. This may need to be reported by individual geometry components in the future. - + // The intersection time table contains all information on intersection times for the current position/direction, and is cleared everytime a ray changes + // direction. Not all entries needs to be calculated, so there is a variable that keeps track of which intersection times have been calculated in order to avoid + // redoing that. When the intersections times are calculated for a volume, all future intersections are kept in the time table. Thus the memory allocation have + // to take into account how many intersections there can be with each volume, but it is currently set to 2, but can easily be changed. This may need to be + // reported by individual geometry components in the future. + intersection_time_table.num_volumes = number_of_volumes; - - intersection_time_table.n_elements = (int*) malloc(intersection_time_table.num_volumes * sizeof(int)); - intersection_time_table.calculated = (int*) malloc(intersection_time_table.num_volumes * sizeof(int)); - intersection_time_table.intersection_times = (double**) malloc(intersection_time_table.num_volumes * sizeof(double*)); - intersection_time_table.normal_vector_x = (double**) malloc(intersection_time_table.num_volumes * sizeof(double*)); - intersection_time_table.normal_vector_y = (double**) malloc(intersection_time_table.num_volumes * sizeof(double*)); - intersection_time_table.normal_vector_z = (double**) malloc(intersection_time_table.num_volumes * sizeof(double*)); - intersection_time_table.surface_index = (int**) malloc(intersection_time_table.num_volumes * sizeof(int*)); - - for (iterator = 0;iterator < intersection_time_table.num_volumes;iterator++){ - if (strcmp(Volumes[iterator]->geometry.shape, "mesh") == 0) { - intersection_time_table.n_elements[iterator] = (int) 100; // Meshes can have any number of intersections, here we allocate room for 100 - } else { - intersection_time_table.n_elements[iterator] = (int) 2; // number of intersection for all other geometries - } - if (iterator == 0) intersection_time_table.n_elements[iterator] = (int) 0; // number of intersection solutions - intersection_time_table.calculated[iterator] = (int) 0; // Initializing calculated logic - - if (iterator == 0) { - intersection_time_table.intersection_times[0] = NULL; - } - else { - //printf("allocating memory for volume %d \n", iterator); - intersection_time_table.intersection_times[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double)); - intersection_time_table.normal_vector_x[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double)); - intersection_time_table.normal_vector_y[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double)); - intersection_time_table.normal_vector_z[iterator] = (double*) malloc(intersection_time_table.n_elements[iterator]*sizeof(double)); - intersection_time_table.surface_index[iterator] = (int*) malloc(intersection_time_table.n_elements[iterator]*sizeof(int)); - - for (solutions = 0;solutions < intersection_time_table.n_elements[iterator];solutions++) { - intersection_time_table.intersection_times[iterator][solutions] = -1.0; - intersection_time_table.normal_vector_x[iterator][solutions] = -1.0; - intersection_time_table.normal_vector_y[iterator][solutions] = -1.0; - intersection_time_table.normal_vector_z[iterator][solutions] = -1.0; - intersection_time_table.surface_index[iterator][solutions] = -1; - - } + + intersection_time_table.n_elements = (int*)malloc (intersection_time_table.num_volumes * sizeof (int)); + intersection_time_table.calculated = (int*)malloc (intersection_time_table.num_volumes * sizeof (int)); + intersection_time_table.intersection_times = (double**)malloc (intersection_time_table.num_volumes * sizeof (double*)); + intersection_time_table.normal_vector_x = (double**)malloc (intersection_time_table.num_volumes * sizeof (double*)); + intersection_time_table.normal_vector_y = (double**)malloc (intersection_time_table.num_volumes * sizeof (double*)); + intersection_time_table.normal_vector_z = (double**)malloc (intersection_time_table.num_volumes * sizeof (double*)); + intersection_time_table.surface_index = (int**)malloc (intersection_time_table.num_volumes * sizeof (int*)); + + for (iterator = 0; iterator < intersection_time_table.num_volumes; iterator++) { + if (strcmp (Volumes[iterator]->geometry.shape, "mesh") == 0) { + intersection_time_table.n_elements[iterator] = (int)100; // Meshes can have any number of intersections, here we allocate room for 100 + } else { + intersection_time_table.n_elements[iterator] = (int)2; // number of intersection for all other geometries + } + if (iterator == 0) + intersection_time_table.n_elements[iterator] = (int)0; // number of intersection solutions + intersection_time_table.calculated[iterator] = (int)0; // Initializing calculated logic + + if (iterator == 0) { + intersection_time_table.intersection_times[0] = NULL; + } else { + // printf("allocating memory for volume %d \n", iterator); + intersection_time_table.intersection_times[iterator] = (double*)malloc (intersection_time_table.n_elements[iterator] * sizeof (double)); + intersection_time_table.normal_vector_x[iterator] = (double*)malloc (intersection_time_table.n_elements[iterator] * sizeof (double)); + intersection_time_table.normal_vector_y[iterator] = (double*)malloc (intersection_time_table.n_elements[iterator] * sizeof (double)); + intersection_time_table.normal_vector_z[iterator] = (double*)malloc (intersection_time_table.n_elements[iterator] * sizeof (double)); + intersection_time_table.surface_index[iterator] = (int*)malloc (intersection_time_table.n_elements[iterator] * sizeof (int)); + + for (solutions = 0; solutions < intersection_time_table.n_elements[iterator]; solutions++) { + intersection_time_table.intersection_times[iterator][solutions] = -1.0; + intersection_time_table.normal_vector_x[iterator][solutions] = -1.0; + intersection_time_table.normal_vector_y[iterator][solutions] = -1.0; + intersection_time_table.normal_vector_z[iterator][solutions] = -1.0; + intersection_time_table.surface_index[iterator][solutions] = -1; } + } } - + // If enabled, the tagging system tracks all different histories sampled by the program. // Initialize the tagging tree // Allocate a list of host nodes with the same length as the number of volumes - - stop_creating_nodes = 0; stop_tagging_ray = 0; tagging_leaf_counter = 0; + + stop_creating_nodes = 0; + stop_tagging_ray = 0; + tagging_leaf_counter = 0; if (enable_tagging) { master_tagging_node_list.num_elements = number_of_volumes; - master_tagging_node_list.elements = malloc(master_tagging_node_list.num_elements * sizeof(struct tagging_tree_node_struct*)); - + master_tagging_node_list.elements = malloc (master_tagging_node_list.num_elements * sizeof (struct tagging_tree_node_struct*)); + // Initialize - for (volume_index=0;volume_indexelements[this_global_master_index-1].stored_number_of_scattering_events; - + + if (inherit_number_of_scattering_events == 1) // Continue number of scattering from previous Union_master + number_of_scattering_events = global_master_list_master->elements[this_global_master_index - 1].stored_number_of_scattering_events; + // Zero scattered_flag_VP data - for (volume_index = 1;volume_indexelements[0].component_index == INDEX_CURRENT_COMP) { // If this is the first Union master, clean up logger data for rays that did not make it through Union components - for (log_index=loggers_with_data_array.used_elements-1;log_index>-1;log_index--) { - loggers_with_data_array.logger_pointers[log_index]->function_pointers.clear_temp(&loggers_with_data_array.logger_pointers[log_index]->data_union); + for (log_index = loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { + loggers_with_data_array.logger_pointers[log_index]->function_pointers.clear_temp (&loggers_with_data_array.logger_pointers[log_index]->data_union); } loggers_with_data_array.used_elements = 0; - for (log_index=abs_loggers_with_data_array.used_elements-1;log_index>-1;log_index--) { - abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.clear_temp(&abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); + for (log_index = abs_loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { + abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.clear_temp ( + &abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); } abs_loggers_with_data_array.used_elements = 0; } tagging_conditional_extend = 0; - for (iterator=0;iteratorgeometry.within_function(ray_position,&Volumes[mask_volume_index_list.elements[iterator]]->geometry) == 1) { + // if(Volumes[mask_volume_index_list.elements[iterator]]->geometry.within_function(ray_position,&Volumes[mask_volume_index_list.elements[iterator]]->geometry) + // == 1) { // GPU - if (r_within_function(ray_position, &Volumes[mask_volume_index_list.elements[iterator]]->geometry) == 1) { + if (r_within_function (ray_position, &Volumes[mask_volume_index_list.elements[iterator]]->geometry) == 1) { mask_status_list.elements[iterator] = 1; } else { mask_status_list.elements[iterator] = 0; } } - + #ifdef Union_trace_verbal_setting - print_1d_int_list(mask_status_list,"Initial mask status list"); + print_1d_int_list (mask_status_list, "Initial mask status list"); #endif - + // Now the initial current_volume can be found, which requires the up to date mask_status_list - current_volume = within_which_volume_GPU(ray_position, starting_lists.reduced_start_list, starting_lists.starting_destinations_list, Volumes, &mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); - + current_volume = within_which_volume_GPU (ray_position, starting_lists.reduced_start_list, starting_lists.starting_destinations_list, Volumes, + &mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); + // For excluding closest intersection in search after refraction/reflection ignore_closest = -1; - + // Using the mask_status_list and the current volume, the current_mask_intersect_list_status can be made // it contains the effective mask status of all volumes on the current volumes mask intersect list, which needs to be calculated, // but only when the current volume or mask status changes, not under for example scattering inside the current volume - update_current_mask_intersect_status(¤t_mask_intersect_list_status, &mask_status_list, Volumes, ¤t_volume); - + update_current_mask_intersect_status (¤t_mask_intersect_list_status, &mask_status_list, Volumes, ¤t_volume); + #ifdef Union_trace_verbal_setting - printf("Starting current_volume = %d\n",current_volume); + printf ("Starting current_volume = %d\n", current_volume); #endif - + // Check if the ray appeared in an allowed starting volume, unless this check is disabled by the user for advanced cases if (allow_inside_start == 0 && starting_lists.allowed_starting_volume_logic_list.elements[current_volume] == 0) { - printf("ERROR, ray ''teleported'' into Union component %s, if intentional, set allow_inside_start=1\n", NAME_CURRENT_COMP); + printf ("ERROR, ray ''teleported'' into Union component %s, if intentional, set allow_inside_start=1\n", NAME_CURRENT_COMP); // NEED ERROR FLAG: Need to set an error flag that is read in finally to warn user of problem. - exit(1); + exit (1); } // Warn the user that rays have appeared inside a volume instead of outside as expected if (starting_volume_warning == 0 && current_volume != 0) { - printf("WARNING: Ray started in volume ''%s'' rather than the surrounding vacuum in component %s. This warning is only shown once.\n",Volumes[current_volume]->name,NAME_CURRENT_COMP); - starting_volume_warning = 1; + printf ("WARNING: Ray started in volume ''%s'' rather than the surrounding vacuum in component %s. This warning is only shown once.\n", + Volumes[current_volume]->name, NAME_CURRENT_COMP); + starting_volume_warning = 1; } - + // Placing the new ray at the start of the tagging tree corresponding to current volume // A history limit can be imposed so that no new nodes are created after this limit (may be necessary to fit in memory) // Rays can still follow the nodes created before even when no additional nodes are created, but if a situation that @@ -1149,14 +1211,17 @@ TRACE if (enable_tagging) { current_tagging_node = master_tagging_node_list.elements[current_volume]; stop_tagging_ray = 0; // Allow this ray to be tracked - if (tagging_leaf_counter > history_limit) stop_creating_nodes = 1; + if (tagging_leaf_counter > history_limit) + stop_creating_nodes = 1; } - + #ifdef Union_trace_verbal_setting - if (enable_tagging) printf("current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging) printf("current_tagging_node->number_of_rays = %d \n",current_tagging_node->number_of_rays); + if (enable_tagging) + printf ("current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging) + printf ("current_tagging_node->number_of_rays = %d \n", current_tagging_node->number_of_rays); #endif - + // Propagation loop including scattering // This while loop continues until the ray leaves the ensamble of user defined volumes either through volume 0 // or a dedicated exit volume. The loop is cancelled after a large number of iterations as a failsafe for errors. @@ -1165,259 +1230,281 @@ TRACE limit = 100000; while (done == 0) { limit--; - + #ifdef Union_trace_verbal_setting - printf("----------- START OF WHILE LOOP --------------------------------------\n"); - print_intersection_table(&intersection_time_table); - printf("current_volume = %d \n",current_volume); + printf ("----------- START OF WHILE LOOP --------------------------------------\n"); + print_intersection_table (&intersection_time_table); + printf ("current_volume = %d \n", current_volume); #endif - if (weight_ratio_limit && p < weight_limit) { - #ifdef Union_trace_verbal_setting - printf("Weight reduced more than ratio_limit p=%lf, p0=%lf, (p_limit=%lf, limit=%d)\n", p, start_weight, weight_limit, limit); - #endif - //printf("Weight reduced more than ratio_limit p=%30.28lf, p0=%15.13lf, (p_limit=%15.13lf, scatter=%d)\n", p, start_weight, weight_limit, 100000-limit); - ABSORB; - } - + if (weight_ratio_limit && p < weight_limit) { + #ifdef Union_trace_verbal_setting + printf ("Weight reduced more than ratio_limit p=%lf, p0=%lf, (p_limit=%lf, limit=%d)\n", p, start_weight, weight_limit, limit); + #endif + // printf("Weight reduced more than ratio_limit p=%30.28lf, p0=%15.13lf, (p_limit=%15.13lf, scatter=%d)\n", p, start_weight, weight_limit, 100000-limit); + ABSORB; + } + // Calculating intersections with the necessary volumes. The relevant set of volumes depend on the current volume and the mask status array. // First the volumes on the current volumes intersect list is checked, then its mask interset list. Before checking the volume itself, it is // checked if any children of the current volume is intersected, in which case the intersection calculation with the current volume can be // skipped. - + // Checking intersections for all volumes in the intersect list. - for (start=check=Volumes[current_volume]->geometry.intersect_check_list.elements;check-startgeometry.intersect_check_list.num_elements;check++) { - // This will leave check as a pointer to the intergers in the intersect_check_list and iccrement nicely + for (start = check = Volumes[current_volume]->geometry.intersect_check_list.elements; + check - start < Volumes[current_volume]->geometry.intersect_check_list.num_elements; check++) { + // This will leave check as a pointer to the intergers in the intersect_check_list and iccrement nicely + #ifdef Union_trace_verbal_setting + printf ("Intersect_list = %d being checked \n", *check); + #endif + + if (intersection_time_table.calculated[*check] == 0) { #ifdef Union_trace_verbal_setting - printf("Intersect_list = %d being checked \n",*check); + printf ("running intersection for intersect_list with *check = %d \n", *check); #endif - - if (intersection_time_table.calculated[*check] == 0) { - #ifdef Union_trace_verbal_setting - printf("running intersection for intersect_list with *check = %d \n",*check); - #endif - // Calculate intersections using intersect function imbedded in the relevant volume structure using parameters that are also imbedded in the structure. - #ifdef Union_trace_verbal_setting - printf("surface_index[*check][0] = %d, surface_index[*check][1] = %d\n", - intersection_time_table.surface_index[*check][0], - intersection_time_table.surface_index[*check][1]); - #endif - // GPU Flexible intersect_function call - geometry_output = intersect_function(intersection_time_table.intersection_times[*check], - intersection_time_table.normal_vector_x[*check], - intersection_time_table.normal_vector_y[*check], - intersection_time_table.normal_vector_z[*check], - intersection_time_table.surface_index[*check], - number_of_solutions, r_start, v, &Volumes[*check]->geometry); - - intersection_time_table.calculated[*check] = 1; - #ifdef Union_trace_verbal_setting - printf("finished running intersection for intersect_list with *check = %d \n",*check); - print_intersection_table(&intersection_time_table); - #endif - } + // Calculate intersections using intersect function imbedded in the relevant volume structure using parameters that are also imbedded in the structure. + #ifdef Union_trace_verbal_setting + printf ("surface_index[*check][0] = %d, surface_index[*check][1] = %d\n", intersection_time_table.surface_index[*check][0], + intersection_time_table.surface_index[*check][1]); + #endif + // GPU Flexible intersect_function call + geometry_output = intersect_function (intersection_time_table.intersection_times[*check], intersection_time_table.normal_vector_x[*check], + intersection_time_table.normal_vector_y[*check], intersection_time_table.normal_vector_z[*check], + intersection_time_table.surface_index[*check], number_of_solutions, r_start, v, &Volumes[*check]->geometry); + + intersection_time_table.calculated[*check] = 1; + #ifdef Union_trace_verbal_setting + printf ("finished running intersection for intersect_list with *check = %d \n", *check); + print_intersection_table (&intersection_time_table); + #endif + } } - + // Mask update: add additional loop for checking intersections with masked volumes depending on mask statuses - for (mask_iterator=0;mask_iteratorgeometry.mask_intersect_list.num_elements;mask_iterator++) { + for (mask_iterator = 0; mask_iterator < Volumes[current_volume]->geometry.mask_intersect_list.num_elements; mask_iterator++) { if (current_mask_intersect_list_status.elements[mask_iterator] == 1) { // Only check if the mask is active - #ifdef Union_trace_verbal_setting - printf("Mask Intersect_list = %d being checked \n",Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); + #ifdef Union_trace_verbal_setting + printf ("Mask Intersect_list = %d being checked \n", Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); #endif if (intersection_time_table.calculated[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]] == 0) { #ifdef Union_trace_verbal_setting - printf("running intersection for mask_intersect_list element = %d \n",Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); + printf ("running intersection for mask_intersect_list element = %d \n", Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); // printf("r = (%f,%f,%f) v = (%f,%f,%f) \n",r[0],r[1],r[2],v[0],v[1],v[2]); #endif // Calculate intersections using intersect function imbedded in the relevant volume structure using parameters - // that are also imbedded in the structure. + // that are also imbedded in the structure. // CPU Only - //geometry_output = Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry.intersect_function(intersection_time_table.intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]],number_of_solutions,r_start,v,&Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry); - + // geometry_output = + // Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry.intersect_function(intersection_time_table.intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]],number_of_solutions,r_start,v,&Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry); + // GPU allowed int selected_index; selected_index = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; - geometry_output = intersect_function(intersection_time_table.intersection_times[selected_index], - intersection_time_table.normal_vector_x[selected_index], - intersection_time_table.normal_vector_y[selected_index], - intersection_time_table.normal_vector_z[selected_index], - intersection_time_table.surface_index[selected_index], - number_of_solutions, r_start, v, &Volumes[selected_index]->geometry); - + geometry_output + = intersect_function (intersection_time_table.intersection_times[selected_index], intersection_time_table.normal_vector_x[selected_index], + intersection_time_table.normal_vector_y[selected_index], intersection_time_table.normal_vector_z[selected_index], + intersection_time_table.surface_index[selected_index], number_of_solutions, r_start, v, &Volumes[selected_index]->geometry); + intersection_time_table.calculated[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]] = 1; // if printf("succesfully calculated intersection times for volume *check = %d \n",*check); } } } - - // Checking if there are intersections with children of current volume, which means there is an intersection before current_volume, and thus can be skipped. But only if they have not been overwritten. In case current_volume is 0, there is no need to do this regardless. - if (current_volume != 0 && intersection_time_table.calculated[current_volume] == 0 ) { - #ifdef Union_trace_verbal_setting - printf("Checking if children of current_volume = %d have intersections. \n",current_volume); - #endif - intersection_with_children = 0; - //for (start = check = Volumes[current_volume]->geometry.direct_children.elements;check - start < Volumes[current_volume]->geometry.children.num_elements;check++) { // REVIEW LINE. Caused bug with masks. - if (!Volumes[current_volume]->geometry.skip_hierarchy_optimization){ - for (start = check = Volumes[current_volume]->geometry.children.elements;check - start < Volumes[current_volume]->geometry.children.num_elements;check++) { - #ifdef Union_trace_verbal_setting - printf("Checking if child %d of current_volume = %d have intersections. \n",*check,current_volume); - #endif - // Only check the first of the two results in the intersection table, as they are ordered, and the second is of no interest - if (intersection_time_table.calculated[*check] == 1 && intersection_time_table.intersection_times[*check][0] > time_propagated_without_scattering) { - // If this child is masked, its mask status need to be 1 in order to be taken into account - if (Volumes[*check]->geometry.is_masked_volume == 0) { - #ifdef Union_trace_verbal_setting - printf("Found an child of current_volume with an intersection. Skips calculating for current_volume \n"); - #endif - intersection_with_children = 1; - break; // No need to check more, if there is just one it is not necessary to calculate intersection with current_volume yet - } else { - #ifdef Union_trace_verbal_setting - printf("Found an child of current_volume with an intersection, but it is masked. Check to see if it can skip calculating for current_volume \n"); - #endif - - if (Volumes[*check]->geometry.mask_mode == 2) { // ANY mask mode - tree_next_volume = 0; - for (mask_start=mask_check=Volumes[*check]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.masked_by_mask_index_list.num_elements;mask_check++) { - if (mask_status_list.elements[*mask_check] == 1) { - intersection_with_children = 1; - break; - } - } - } else { // ALL mask mode - intersection_with_children = 1; - for (mask_start=mask_check=Volumes[*check]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.masked_by_mask_index_list.num_elements;mask_check++) { - if (mask_status_list.elements[*mask_check] == 0) { - intersection_with_children = 0; - break; - } - } - } - #ifdef Union_trace_verbal_setting - printf("The mask status was 1, can actually skip intersection calculation for current volume \n"); - #endif - if (intersection_with_children == 1) break; - } - } - } - } - #ifdef Union_trace_verbal_setting - printf("intersection_with_children = %d \n",intersection_with_children); - #endif - if (intersection_with_children == 0) { - // GPU Allowed - geometry_output = intersect_function(intersection_time_table.intersection_times[current_volume], - intersection_time_table.normal_vector_x[current_volume], - intersection_time_table.normal_vector_y[current_volume], - intersection_time_table.normal_vector_z[current_volume], - intersection_time_table.surface_index[current_volume], - number_of_solutions, r_start, v, &Volumes[current_volume]->geometry); - - intersection_time_table.calculated[current_volume] = 1; + + // Checking if there are intersections with children of current volume, which means there is an intersection before current_volume, and thus can be skipped. + // But only if they have not been overwritten. In case current_volume is 0, there is no need to do this regardless. + if (current_volume != 0 && intersection_time_table.calculated[current_volume] == 0) { + #ifdef Union_trace_verbal_setting + printf ("Checking if children of current_volume = %d have intersections. \n", current_volume); + #endif + intersection_with_children = 0; + // for (start = check = Volumes[current_volume]->geometry.direct_children.elements;check - start < + // Volumes[current_volume]->geometry.children.num_elements;check++) { // REVIEW LINE. Caused bug with masks. + if (!Volumes[current_volume]->geometry.skip_hierarchy_optimization) { + for (start = check = Volumes[current_volume]->geometry.children.elements; check - start < Volumes[current_volume]->geometry.children.num_elements; + check++) { + #ifdef Union_trace_verbal_setting + printf ("Checking if child %d of current_volume = %d have intersections. \n", *check, current_volume); + #endif + // Only check the first of the two results in the intersection table, as they are ordered, and the second is of no interest + if (intersection_time_table.calculated[*check] == 1 && intersection_time_table.intersection_times[*check][0] > time_propagated_without_scattering) { + // If this child is masked, its mask status need to be 1 in order to be taken into account + if (Volumes[*check]->geometry.is_masked_volume == 0) { + #ifdef Union_trace_verbal_setting + printf ("Found an child of current_volume with an intersection. Skips calculating for current_volume \n"); + #endif + intersection_with_children = 1; + break; // No need to check more, if there is just one it is not necessary to calculate intersection with current_volume yet + } else { + #ifdef Union_trace_verbal_setting + printf ("Found an child of current_volume with an intersection, but it is masked. Check to see if it can skip calculating for current_volume \n"); + #endif + + if (Volumes[*check]->geometry.mask_mode == 2) { // ANY mask mode + tree_next_volume = 0; + for (mask_start = mask_check = Volumes[*check]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start < Volumes[*check]->geometry.masked_by_mask_index_list.num_elements; mask_check++) { + if (mask_status_list.elements[*mask_check] == 1) { + intersection_with_children = 1; + break; + } + } + } else { // ALL mask mode + intersection_with_children = 1; + for (mask_start = mask_check = Volumes[*check]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start < Volumes[*check]->geometry.masked_by_mask_index_list.num_elements; mask_check++) { + if (mask_status_list.elements[*mask_check] == 0) { + intersection_with_children = 0; + break; + } + } + } + #ifdef Union_trace_verbal_setting + printf ("The mask status was 1, can actually skip intersection calculation for current volume \n"); + #endif + if (intersection_with_children == 1) + break; + } + } } + } + #ifdef Union_trace_verbal_setting + printf ("intersection_with_children = %d \n", intersection_with_children); + #endif + if (intersection_with_children == 0) { + // GPU Allowed + geometry_output + = intersect_function (intersection_time_table.intersection_times[current_volume], intersection_time_table.normal_vector_x[current_volume], + intersection_time_table.normal_vector_y[current_volume], intersection_time_table.normal_vector_z[current_volume], + intersection_time_table.surface_index[current_volume], number_of_solutions, r_start, v, &Volumes[current_volume]->geometry); + + intersection_time_table.calculated[current_volume] = 1; + } } // At this point, intersection_time_table is updated with intersection times of all possible intersections. #ifdef Union_trace_verbal_setting - print_intersection_table(&intersection_time_table); + print_intersection_table (&intersection_time_table); #endif - + // For the closest intersection to volume with index ignore_closest, the scattering with the shortest absolute time should be ignored if (ignore_closest > 0) { - min_intersection_time = 1E9; - min_solution = -1; - for (solution = 0; solutiongeometry.intersect_check_list.elements;check-startgeometry.intersect_check_list.num_elements;check++) { - for (solution = 0;solution time_propagated_without_scattering && intersection_time < min_intersection_time) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = *check; - #ifdef Union_trace_verbal_setting - printf("found A at %i x %i\n",*check,solution); - #endif - } - } else { - if ((intersection_time = intersection_time_table.intersection_times[*check][solution]) > time_propagated_without_scattering) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = *check; - time_found = 1; - #ifdef Union_trace_verbal_setting - printf("found B at %i x %i\n",*check,solution); - #endif - } - } + for (start = check = Volumes[current_volume]->geometry.intersect_check_list.elements; + check - start < Volumes[current_volume]->geometry.intersect_check_list.num_elements; check++) { + for (solution = 0; solution < intersection_time_table.n_elements[*check]; solution++) { + if (time_found) { + if ((intersection_time = intersection_time_table.intersection_times[*check][solution]) > time_propagated_without_scattering + && intersection_time < min_intersection_time) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = *check; + #ifdef Union_trace_verbal_setting + printf ("found A at %i x %i\n", *check, solution); + #endif + } + } else { + if ((intersection_time = intersection_time_table.intersection_times[*check][solution]) > time_propagated_without_scattering) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = *check; + time_found = 1; + #ifdef Union_trace_verbal_setting + printf ("found B at %i x %i\n", *check, solution); + #endif + } } + } } #ifdef Union_trace_verbal_setting - printf("min_intersection_time=%g min_solution=%i\n",min_intersection_time,min_solution); + printf ("min_intersection_time=%g min_solution=%i\n", min_intersection_time, min_solution); #endif // Now check the masked_intersect_list, but only the ones that are currently active - for (mask_iterator=0;mask_iteratorgeometry.mask_intersect_list.num_elements;mask_iterator++) { + for (mask_iterator = 0; mask_iterator < Volumes[current_volume]->geometry.mask_intersect_list.num_elements; mask_iterator++) { if (current_mask_intersect_list_status.elements[mask_iterator] == 1) { - for (solution = 0;solutiongeometry.mask_intersect_list.elements[mask_iterator]];solution++) { - if (time_found) { - if ((intersection_time = intersection_time_table.intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) > time_propagated_without_scattering && intersection_time < min_intersection_time) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; - } - } else { - if ((intersection_time = intersection_time_table.intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) > time_propagated_without_scattering) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; - time_found = 1; - } + for (solution = 0; solution < intersection_time_table.n_elements[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]; + solution++) { + if (time_found) { + if ((intersection_time + = intersection_time_table.intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) + > time_propagated_without_scattering + && intersection_time < min_intersection_time) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; } + } else { + if ((intersection_time + = intersection_time_table.intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) + > time_propagated_without_scattering) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; + time_found = 1; + } + } } } } - + // And check the current_volume - for (solution = 0;solution time_propagated_without_scattering && intersection_time < min_intersection_time) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = current_volume; - } - } else { - if ((intersection_time = intersection_time_table.intersection_times[current_volume][solution]) > time_propagated_without_scattering) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = current_volume; - time_found = 1; - } + for (solution = 0; solution < intersection_time_table.n_elements[current_volume]; solution++) { + if (time_found) { + if ((intersection_time = intersection_time_table.intersection_times[current_volume][solution]) > time_propagated_without_scattering + && intersection_time < min_intersection_time) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = current_volume; } + } else { + if ((intersection_time = intersection_time_table.intersection_times[current_volume][solution]) > time_propagated_without_scattering) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = current_volume; + time_found = 1; + } + } } - + // Reset ingore_closest after one intersection iteration ignore_closest = -1; - + #ifdef Union_trace_verbal_setting - printf("min_intersection_time = %f \n", min_intersection_time); - printf("min_solution = %d \n", min_solution); - printf("min_volume = %d \n", min_volume); - printf("time_found = %d \n", time_found); + printf ("min_intersection_time = %f \n", min_intersection_time); + printf ("min_solution = %d \n", min_solution); + printf ("min_volume = %d \n", min_volume); + printf ("time_found = %d \n", time_found); #endif abs_weight_factor = 1.0; @@ -1426,1319 +1513,1466 @@ TRACE // If a time is found, propagation continues, and it will be checked if a scattering occurs before the next intersection. // If a time is not found, the ray must be leaving the ensamble of volumes and the loop will be concluded if (time_found) { - time_to_boundery = min_intersection_time - time_propagated_without_scattering; // calculate the time remaining before the next intersection - scattering_event = 0; // Assume a scattering event will not occur - - // Check if a scattering event should occur - if (current_volume != 0) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur - if (Volumes[current_volume]->p_physics->number_of_processes == 0) { // If there are no processes, the volume could be vacuum or an absorber - if (Volumes[current_volume]->p_physics->is_vacuum == 0) { - // This volume does not have physical processes but does have an absorption cross section, so the ray weight is reduced accordingly - - my_sum_plus_abs = Volumes[current_volume]->p_physics->my_a*(2200/v_length); - length_to_boundary = time_to_boundery * v_length; - - abs_weight_factor = exp(-Volumes[current_volume]->p_physics->my_a*2200*time_to_boundery); - abs_weight_factor_set = 1; - - #ifdef Union_trace_verbal_setting - printf("name of material: %s \n",Volumes[current_volume]->name); - printf("length to boundery = %f\n",length_to_boundary); - printf("absorption cross section = %f\n",Volumes[current_volume]->p_physics->my_a); - printf("chance to get through this length of absorber: %f %%\n", 100*exp(-Volumes[current_volume]->p_physics->my_a*length_to_boundary)); - #endif - } - } else { - // Since there is a non-zero number of processes in this material, all the scattering cross section for these are calculated - my_sum = 0; k[0] = V2K*vx; k[1] = V2K*vy; k[2] = V2K*vz; - p_my_trace = my_trace; wavevector = coords_set(k[0],k[1],k[2]); - length_to_boundary = time_to_boundery * v_length; - - double forced_length_to_scattering; - Coords ray_position_geometry; - - // If any process in this material needs focusing, sample scattering position and update focus_data accordingly - if (Volumes[current_volume]->p_physics->any_process_needs_cross_section_focus == 1) { - // Sample length_to_scattering in linear manner - forced_length_to_scattering = safety_distance + rand01()*(length_to_boundary - safety_distance2); - - ray_velocity = coords_set(vx,vy,vz); // Test for root cause - // Find location of scattering point in master coordinate system without changing main position / velocity variables - Coords direction = coords_scalar_mult(ray_velocity, 1.0/length_of_position_vector(ray_velocity)); - Coords scattering_displacement = coords_scalar_mult(direction, forced_length_to_scattering); - Coords forced_ray_scattering_point = coords_add(ray_position, scattering_displacement); - ray_position_geometry = coords_sub(forced_ray_scattering_point, Volumes[current_volume]->geometry.center); // ray_position relative to geometry center - - // Calculate the aim for non isotropic processes - this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[0]; - this_focus_data->RayAim = coords_sub(this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray - - #ifdef Union_trace_verbal_setting - printf("Prepared for focus in cross section calculation in volume: %s \n",Volumes[current_volume]->name); - printf("forced_length_to_scattering =%lf \n", forced_length_to_scattering); - print_position(ray_position, "ray_position"); - print_position(direction, "direction"); - print_position(scattering_displacement, "scattering_displacement"); - print_position(forced_ray_scattering_point, "forced_ray_scattering_point"); - print_position(ray_position_geometry, "ray_position_geometry"); - printf("for isotropic processes this RayAim is used \n"); - print_position(this_focus_data->RayAim, "this_focus_data->RayAim"); - #endif - - /* - // update focus data for this ray (could limit this to only update the necessary focus_data element, but there are typically very few) - int f_index; - for (f_index=0; f_index < Volumes[current_volume]->geometry.focus_data_array.num_elements; f_index++) { - this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[f_index]; - // Coords ray_position_geometry_rotated = rot_apply(this_focus_data.absolute_rotation, ray_position_geometry); - this_focus_data->RayAim = coords_sub(this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray - } - - printf("calculated forced_length_to_scattering = %lf, new RayAim \n", forced_length_to_scattering); - print_position(direction, "direction"); - print_position(scattering_displacement, "scattering_displacement"); - print_position(forced_ray_scattering_point, "forced_ray_scattering_point"); - print_position(ray_position_geometry, "ray_position_geometry"); - print_position(this_focus_data->RayAim, "this_focus_data->RayAim"); - */ - - } else { - forced_length_to_scattering = -1.0; // Signals that no forcing needed, could also if on the selected process struct - } - - int p_index; - for (p_index=0; p_index < Volumes[current_volume]->p_physics->number_of_processes; p_index++ ){ // GPU - - // Find correct focus_data_array index for this volume/process - focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[p_index]; - this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[focus_data_index]; - - if (Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index != -1) { - // If the process is not isotropic, the wavevector is transformed into the local coordinate system of the process - int non_isotropic_rot_index = Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index; - wavevector_rotated = rot_apply(Volumes[current_volume]->geometry.process_rot_matrix_array[non_isotropic_rot_index],wavevector); - coords_get(wavevector_rotated,&k_rotated[0],&k_rotated[1],&k_rotated[2]); - - if (Volumes[current_volume]->p_physics->p_scattering_array[p_index].needs_cross_section_focus == 1) { - // Prepare focus data using ray_position_geometry of forced scattering point which will be prepared if any process needs cross_section time focusing - Coords ray_position_geometry_rotated = rot_apply(Volumes[current_volume]->geometry.process_rot_matrix_array[non_isotropic_rot_index], ray_position_geometry); - this_focus_data->RayAim = coords_sub(this_focus_data->Aim, ray_position_geometry_rotated); // Aim vector for this ray - #ifdef Union_trace_verbal_setting - printf("Checking process number : %d, it was not isotropic, so RayAim updated \n",p_index); - print_position(ray_position_geometry, "ray_position_geometry"); - print_position(ray_position_geometry_rotated, "ray_position_geometry_rotated"); - print_position(this_focus_data->RayAim, "this_focus_data->RayAim"); - #endif - - } + time_to_boundery = min_intersection_time - time_propagated_without_scattering; // calculate the time remaining before the next intersection + scattering_event = 0; // Assume a scattering event will not occur - } else { - k_rotated[0] = k[0]; k_rotated[1] = k[1]; k_rotated[2] = k[2]; - // focus_data RayAim already updated for non isotropic processes - } - - // Call the probability for scattering function assighed to this specific procress (the process pointer is updated in the for loop) - process = &Volumes[current_volume]->p_physics->p_scattering_array[p_index]; // GPU Allowed - - int physics_output; - physics_output = physics_my(process->eProcess, p_my_trace, k_rotated, process->data_transfer, this_focus_data, _particle); - - my_sum += *p_my_trace; - #ifdef Union_trace_verbal_setting - printf("my_trace = %f, my_sum = %f\n",*p_my_trace,my_sum); - #endif - // increment the pointers so that it point to the next element (max number of process in any material is allocated) - p_my_trace++; - } - - #ifdef Union_trace_verbal_setting - printf("time_propagated_without_scattering = %f.\n",time_propagated_without_scattering); - printf("v_length = %f.\n",v_length); - printf("exp(- length_to_boundary*my_sum) = %f. length_to_boundary = %f. my_sum = %f.\n",exp(-length_to_boundary*my_sum),length_to_boundary,my_sum); - #endif - - my_sum_plus_abs = my_sum + Volumes[current_volume]->p_physics->my_a*(2200/v_length); - - // New flow:length_to_boundary - - // Calculate if scattering happens based on my_sub_plus_abs - if (my_sum < 1E-18) { - scattering_event = 0; - } else if (length_to_boundary < safety_distance2) { - scattering_event = 0; - } else { - real_transmission_probability = exp(-length_to_boundary*my_sum_plus_abs); - if (Volumes[current_volume]->geometry.geometry_p_interact != 0) { - mc_transmission_probability = (1.0 - Volumes[current_volume]->geometry.geometry_p_interact); - if ((scattering_event = (rand01() > mc_transmission_probability))) { - // Scattering event happens, this is the correction for the weight - p *= (1.0-real_transmission_probability)/(1.0-mc_transmission_probability); - } else { - // Scattering event does not happen, this is the appropriate correction - p *= real_transmission_probability/mc_transmission_probability; - } - } else { - // probability to scatter is the natural value - scattering_event = rand01() > real_transmission_probability; - } - } - - // If scattering happens - if (scattering_event == 1) { - // Select scattering process - - // Adjust weight for absorption - abs_weight_factor *= my_sum/my_sum_plus_abs; - abs_weight_factor_set = 1; - // Safety feature, alert in case of nonsense my results / negative absorption - if (my_sum/my_sum_plus_abs > 1.0) printf("WARNING: Absorption weight factor above 1! Should not happen! \n"); - // Select process - if (Volumes[current_volume]->p_physics->number_of_processes == 1) { // trivial case - // Select the only available process, which will always have index 0 - selected_process = 0; - } else { - if (Volumes[current_volume]->p_physics->interact_control == 1) { - // Interact_fraction is used to influence the choice of process in this material - mc_prop = rand01();culmative_probability=0;total_process_interact=1.0; - - // If any of the processes have probability 0, they are excluded from the selection - for (iterator = 0;iterator < Volumes[current_volume]->p_physics->number_of_processes;iterator++) { - if (my_trace[iterator] < 1E-18) { - // When this happens, the total force probability is corrected and the probability for this particular instance is set to 0 - total_process_interact -= Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; - my_trace_fraction_control[iterator] = 0; - // In cases where my_trace is not zero, the forced fraction is still used. - } else my_trace_fraction_control[iterator] = Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; - } - // Randomly select a process using the weights stored in my_trace_fraction_control divided by total_process_interact - for (iterator = 0;iterator < Volumes[current_volume]->p_physics->number_of_processes;iterator++) { - culmative_probability += my_trace_fraction_control[iterator]/total_process_interact; - if (culmative_probability > mc_prop) { - selected_process = iterator; - p *= (my_trace[iterator]/my_sum)*(total_process_interact/my_trace_fraction_control[iterator]); - break; - } - } - - } else { - // Select a process based on their relative attenuations factors - mc_prop = rand01();culmative_probability=0; - for (iterator = 0;iterator < Volumes[current_volume]->p_physics->number_of_processes;iterator++) { - culmative_probability += my_trace[iterator]/my_sum; - if (culmative_probability > mc_prop) { - selected_process = iterator; - break; - } - } - } - } - - // Select distance to scattering position - if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].needs_cross_section_focus == 1) { - // Respect forced length to scattering chosen by process - length_to_scattering = forced_length_to_scattering; - // Drawing between 0 and L from constant s = 1/L and should have been q = A*exp(-kz). - // Normalizing A*exp(-kz) over 0 to L: A = k/(1-exp(-k*L)) - // Weight correction is ratio between s and q, L*A*exp(-kz) = L*k*exp(-kz)/(1-exp(-Lk)) - p *= length_to_boundary*my_sum_plus_abs*exp(-length_to_scattering*my_sum_plus_abs)/(1.0 - exp(-length_to_boundary*my_sum_plus_abs)); - #ifdef Union_trace_verbal_setting - printf("Used forced length to scattering, %lf \n", length_to_scattering); - #endif - - } else { - // Decided the ray scatters, choose where on truncated exponential from safety_distance to length_to_boundary - safety_distance - length_to_scattering = safety_distance - log(1.0 - rand0max((1.0 - exp(-my_sum_plus_abs*(length_to_boundary-safety_distance2))))) / my_sum_plus_abs; - #ifdef Union_trace_verbal_setting - printf("Sampled length to scattering, %lf \n", length_to_scattering); - #endif - } - - } // Done handling scattering - - } // Done handling situation where there are scattering processes in the material - - } // Done checking for scttering event and in case of scattering selecting a process - - // Record initial weight, absorption weight factor and initial position - - initial_weight = p; - r_old[0] = r[0]; r_old[1] = r[1]; r_old[2] = r[2]; time_old = t; - // Apply absorption - p *= abs_weight_factor; - - // Create event for absorption loggers - // Need to use start position and length travelled to sample that trajectory for absorption event. Could do several, here just one. - - // min length: 0, max length: length_to_scattering if scattering, else length to boundary - - // Avoid logging absorption when the ray is in vacuum. - if (current_volume != 0 && abs_weight_factor_set == 1) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur - if (Volumes[current_volume]->p_physics->is_vacuum == 0) { // No absorption in vacuum - - if (scattering_event == 1) { - // When scattering events occur, place the absoprtion the same place (the total cross section is used to place it) - abs_distance = length_to_scattering; - } else { - // When the ray exits a volume, the absorption position should be exponentially distributed using the total cross section - my_abs = Volumes[current_volume]->p_physics->my_a*(2200/v_length); - abs_distance = -log(1.0 - rand0max(1.0 - exp(-my_sum_plus_abs*length_to_boundary)) ) / my_sum_plus_abs; - } + // Check if a scattering event should occur + if (current_volume != 0) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur + if (Volumes[current_volume]->p_physics->number_of_processes == 0) { // If there are no processes, the volume could be vacuum or an absorber + if (Volumes[current_volume]->p_physics->is_vacuum == 0) { + // This volume does not have physical processes but does have an absorption cross section, so the ray weight is reduced accordingly - t_abs_propagation = abs_distance/v_length; + my_sum_plus_abs = Volumes[current_volume]->p_physics->my_a * (2200 / v_length); + length_to_boundary = time_to_boundery * v_length; + + abs_weight_factor = exp (-Volumes[current_volume]->p_physics->my_a * 2200 * time_to_boundery); + abs_weight_factor_set = 1; - abs_position = coords_set(x + t_abs_propagation*vx, y + t_abs_propagation*vy, z + t_abs_propagation*vz); - - // This info needs to be loaded into the absorption loggers - - // Need to run through relevant absorption loggers here - #ifdef Union_trace_verbal_setting - printf("Running abs_logger system for specific volumes \n"); - #endif - - // Logging for detector components assosiated with this volume - for (log_index=0;log_indexabs_loggers.num_elements;log_index++) { - // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers - transformed_abs_position = coords_sub(abs_position, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->position); - transformed_abs_position = rot_apply(Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->rotation, transformed_abs_position); - - // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis - Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->function_pointers.active_record_function(&transformed_abs_position, k_new, initial_weight*(1.0-abs_weight_factor), t + t_abs_propagation, scattered_flag[current_volume], number_of_scattering_events, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index], &abs_loggers_with_data_array); - // If the logging component have a conditional attatched, the collected data will be written to a temporary place - // At the end of the rays life, it will be checked if the condition is met - // if it is met, the temporary data is transfered to permanent, and temp is cleared. - // if it is not met, the temporary data is cleared. - } - #ifdef Union_trace_verbal_setting - printf("Running abs_logger system for all volumes \n"); + printf ("name of material: %s \n", Volumes[current_volume]->name); + printf ("length to boundery = %f\n", length_to_boundary); + printf ("absorption cross section = %f\n", Volumes[current_volume]->p_physics->my_a); + printf ("chance to get through this length of absorber: %f %%\n", 100 * exp (-Volumes[current_volume]->p_physics->my_a * length_to_boundary)); #endif - for (log_index=0;log_indexnum_elements;log_index++) { - // As above, but on a global scale, meaning scattering in all volumes are logged - - // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components general. - // Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). Weird but not meaningless. - - // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers - transformed_abs_position = coords_sub(abs_position, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->position); - transformed_abs_position = rot_apply(global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->rotation, transformed_abs_position); - - // Above version includes scattered_flag_VP, but selected_process may be undefined at this point. - global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->function_pointers.active_record_function(&transformed_abs_position, k_new, initial_weight*(1.0-abs_weight_factor), t+t_abs_propagation, scattered_flag[current_volume], number_of_scattering_events, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger, &abs_loggers_with_data_array); - } } - } - - if (scattering_event == 1) { - #ifdef Union_trace_verbal_setting - printf("SCATTERING EVENT \n"); - printf("current_volume = %d \n", current_volume); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n", r[0], r[1], r[2], v[0], v[1], v[2]); - #endif - - // Calculate the time to scattering - time_to_scattering = length_to_scattering/v_length; - + } else { + // Since there is a non-zero number of processes in this material, all the scattering cross section for these are calculated + my_sum = 0; + k[0] = V2K * vx; + k[1] = V2K * vy; + k[2] = V2K * vz; + p_my_trace = my_trace; + wavevector = coords_set (k[0], k[1], k[2]); + length_to_boundary = time_to_boundery * v_length; + + double forced_length_to_scattering; + Coords ray_position_geometry; + + // If any process in this material needs focusing, sample scattering position and update focus_data accordingly + if (Volumes[current_volume]->p_physics->any_process_needs_cross_section_focus == 1) { + // Sample length_to_scattering in linear manner + forced_length_to_scattering = safety_distance + rand01 () * (length_to_boundary - safety_distance2); + + ray_velocity = coords_set (vx, vy, vz); // Test for root cause + // Find location of scattering point in master coordinate system without changing main position / velocity variables + Coords direction = coords_scalar_mult (ray_velocity, 1.0 / length_of_position_vector (ray_velocity)); + Coords scattering_displacement = coords_scalar_mult (direction, forced_length_to_scattering); + Coords forced_ray_scattering_point = coords_add (ray_position, scattering_displacement); + ray_position_geometry + = coords_sub (forced_ray_scattering_point, Volumes[current_volume]->geometry.center); // ray_position relative to geometry center + + // Calculate the aim for non isotropic processes + this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[0]; + this_focus_data->RayAim = coords_sub (this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray + #ifdef Union_trace_verbal_setting - printf("time to scattering = %2.20f \n",time_to_scattering); - printf("length to boundery = %f, length to scattering = %f \n",length_to_boundary,length_to_scattering); + printf ("Prepared for focus in cross section calculation in volume: %s \n", Volumes[current_volume]->name); + printf ("forced_length_to_scattering =%lf \n", forced_length_to_scattering); + print_position (ray_position, "ray_position"); + print_position (direction, "direction"); + print_position (scattering_displacement, "scattering_displacement"); + print_position (forced_ray_scattering_point, "forced_ray_scattering_point"); + print_position (ray_position_geometry, "ray_position_geometry"); + printf ("for isotropic processes this RayAim is used \n"); + print_position (this_focus_data->RayAim, "this_focus_data->RayAim"); #endif - - // May be replace by version without gravity - //PROP_DT(time_to_scattering); - - // Reduce the double book keeping done here - x += time_to_scattering*vx; y += time_to_scattering*vy; z += time_to_scattering*vz; t += time_to_scattering; - r_start[0] = x; r_start[1] = y; r_start[2] = z; - r[0] = x; r[1] = y; r[2] = z; - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - - // Safe check that should be unecessary. Used to fine tune how close to the edge of a volume a scattering event is allowed to take place (1E-14 m away currently). - if (r_within_function(ray_position, &Volumes[current_volume]->geometry) == 0) { - printf("\nERROR, propagated out of current volume instead of to a point within!\n"); - printf("length_to_scattering_specified = %2.20f\n length propagated = %2.20f\n length_to_boundary = %2.20f \n current_position = (%lf,%lf,%lf) \n",length_to_scattering,sqrt(time_to_scattering*time_to_scattering*vx*vx+time_to_scattering*time_to_scattering*vy*vy+time_to_scattering*time_to_scattering*vz*vz),length_to_boundary,x,y,z); - - volume_index = within_which_volume_GPU(ray_position,starting_lists.reduced_start_list,starting_lists.starting_destinations_list,Volumes,&mask_status_list,number_of_volumes,pre_allocated1,pre_allocated2,pre_allocated3); - - printf("Debug info: Volumes[current_volume]->name = %s, but now inside volume number %d named %s.\n",Volumes[current_volume]->name,volume_index,Volumes[volume_index]->name); - printf("Ray absorbed \n"); - ABSORB; - } - - // Save information before scattering event needed in logging section - p_old = p; - k_old[0] = k[0];k_old[1] = k[1];k_old[2] = k[2]; - - // Find correct focus_data_array index for this volume/process and correct for ray position - focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[selected_process]; - this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[focus_data_index]; - - Coords ray_position_geometry = coords_sub(ray_position, Volumes[current_volume]->geometry.center); // ray_position relative to geometry center - - this_focus_data->RayAim = coords_sub(this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray - - // Rotation to local process coordinate system (for non isotropic processes) - if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { - ray_velocity_rotated = rot_apply(Volumes[current_volume]->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index],ray_velocity); - - Coords ray_position_geometry_rotated = rot_apply(Volumes[current_volume]->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index],ray_position_geometry); - this_focus_data->RayAim = coords_sub(this_focus_data->Aim, ray_position_geometry_rotated); // Aim vector for this ray - } else { - ray_velocity_rotated = ray_velocity; - this_focus_data->RayAim = coords_sub(this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray + + /* + // update focus data for this ray (could limit this to only update the necessary focus_data element, but there are typically very few) + int f_index; + for (f_index=0; f_index < Volumes[current_volume]->geometry.focus_data_array.num_elements; f_index++) { + this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[f_index]; + // Coords ray_position_geometry_rotated = rot_apply(this_focus_data.absolute_rotation, ray_position_geometry); + this_focus_data->RayAim = coords_sub(this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray } - #ifdef Union_trace_verbal_setting - printf("Kin: %g %g %g, selected_process: %i %i\n",k[0],k[1],k[2],selected_process,current_volume); - coords_print(Volumes[current_volume]->geometry.focus_data_array.elements[0].Aim); - #endif - // test_physics_scattering(double *k_final, double *k_initial, union data_transfer_union data_transfer) { - coords_get(coords_scalar_mult(ray_velocity_rotated,V2K), &k[0], &k[1], &k[2]); - - // I may replace a intial and final k with one instance that serves as both input and output - process = &Volumes[current_volume]->p_physics->p_scattering_array[selected_process]; // CPU Only - if (0 == physics_scattering(process->eProcess, k_new, k, &p, process->data_transfer, this_focus_data, _particle)) { - /* - // PowderN and Single_crystal requires the option of absorbing the neutron, which is weird. If there is a scattering probability, there should be a new direction. - // It can arise from need to simplify sampling process and end up in cases where weight factor is 0, and the ray should be absorbed in these cases - printf("ERROR: Union_master: %s.Absorbed ray because scattering function returned 0 (error/absorb)\n",NAME_CURRENT_COMP); - component_error_msg++; - if (component_error_msg > 100) { - printf("To many errors encountered, exiting. \n"); - exit(1); + + printf("calculated forced_length_to_scattering = %lf, new RayAim \n", forced_length_to_scattering); + print_position(direction, "direction"); + print_position(scattering_displacement, "scattering_displacement"); + print_position(forced_ray_scattering_point, "forced_ray_scattering_point"); + print_position(ray_position_geometry, "ray_position_geometry"); + print_position(this_focus_data->RayAim, "this_focus_data->RayAim"); + */ + + } else { + forced_length_to_scattering = -1.0; // Signals that no forcing needed, could also if on the selected process struct + } + + int p_index; + for (p_index = 0; p_index < Volumes[current_volume]->p_physics->number_of_processes; p_index++) { // GPU + + // Find correct focus_data_array index for this volume/process + focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[p_index]; + this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[focus_data_index]; + + if (Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index != -1) { + // If the process is not isotropic, the wavevector is transformed into the local coordinate system of the process + int non_isotropic_rot_index = Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index; + wavevector_rotated = rot_apply (Volumes[current_volume]->geometry.process_rot_matrix_array[non_isotropic_rot_index], wavevector); + coords_get (wavevector_rotated, &k_rotated[0], &k_rotated[1], &k_rotated[2]); + + if (Volumes[current_volume]->p_physics->p_scattering_array[p_index].needs_cross_section_focus == 1) { + // Prepare focus data using ray_position_geometry of forced scattering point which will be prepared if any process needs cross_section time + // focusing + Coords ray_position_geometry_rotated + = rot_apply (Volumes[current_volume]->geometry.process_rot_matrix_array[non_isotropic_rot_index], ray_position_geometry); + this_focus_data->RayAim = coords_sub (this_focus_data->Aim, ray_position_geometry_rotated); // Aim vector for this ray + #ifdef Union_trace_verbal_setting + printf ("Checking process number : %d, it was not isotropic, so RayAim updated \n", p_index); + print_position (ray_position_geometry, "ray_position_geometry"); + print_position (ray_position_geometry_rotated, "ray_position_geometry_rotated"); + print_position (this_focus_data->RayAim, "this_focus_data->RayAim"); + #endif } - */ - ABSORB; + + } else { + k_rotated[0] = k[0]; + k_rotated[1] = k[1]; + k_rotated[2] = k[2]; + // focus_data RayAim already updated for non isotropic processes } + + // Call the probability for scattering function assighed to this specific procress (the process pointer is updated in the for loop) + process = &Volumes[current_volume]->p_physics->p_scattering_array[p_index]; // GPU Allowed + + int physics_output; + physics_output = physics_my (process->eProcess, p_my_trace, k_rotated, process->data_transfer, this_focus_data, _particle); + + my_sum += *p_my_trace; #ifdef Union_trace_verbal_setting - printf("Kout: %g %g %g\n", k_new[0],k_new[1],k_new[2]); + printf ("my_trace = %f, my_sum = %f\n", *p_my_trace, my_sum); #endif - // Update velocity using k - ray_velocity_rotated = coords_set(K2V*k_new[0],K2V*k_new[1],K2V*k_new[2]); - - // Transformation back to main coordinate system (maybe one should only do this when multiple scattering in that volume was over, especially if there is only one non isotropic frame) - if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { - ray_velocity_final = rot_apply(Volumes[current_volume]->geometry.transpose_process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index],ray_velocity_rotated); + // increment the pointers so that it point to the next element (max number of process in any material is allocated) + p_my_trace++; + } + + #ifdef Union_trace_verbal_setting + printf ("time_propagated_without_scattering = %f.\n", time_propagated_without_scattering); + printf ("v_length = %f.\n", v_length); + printf ("exp(- length_to_boundary*my_sum) = %f. length_to_boundary = %f. my_sum = %f.\n", exp (-length_to_boundary * my_sum), length_to_boundary, + my_sum); + #endif + + my_sum_plus_abs = my_sum + Volumes[current_volume]->p_physics->my_a * (2200 / v_length); + + // New flow:length_to_boundary + + // Calculate if scattering happens based on my_sub_plus_abs + if (my_sum < 1E-18) { + scattering_event = 0; + } else if (length_to_boundary < safety_distance2) { + scattering_event = 0; + } else { + real_transmission_probability = exp (-length_to_boundary * my_sum_plus_abs); + if (Volumes[current_volume]->geometry.geometry_p_interact != 0) { + mc_transmission_probability = (1.0 - Volumes[current_volume]->geometry.geometry_p_interact); + if ((scattering_event = (rand01 () > mc_transmission_probability))) { + // Scattering event happens, this is the correction for the weight + p *= (1.0 - real_transmission_probability) / (1.0 - mc_transmission_probability); + } else { + // Scattering event does not happen, this is the appropriate correction + p *= real_transmission_probability / mc_transmission_probability; + } } else { - ray_velocity_final = ray_velocity_rotated; + // probability to scatter is the natural value + scattering_event = rand01 () > real_transmission_probability; } - #ifdef Union_trace_verbal_setting - printf("Final velocity vector "); coords_print(ray_velocity_final); - #endif - // Write velocity to global variable (temp, only really necessary at final) - coords_get(ray_velocity_final, &vx, &vy, &vz); - - // Write velocity in array format as it is still used by intersect functions (temp, they need to be updated to ray_position / ray_velocity) - v[0] = vx; v[1] = vy; v[2] = vz; - v_length = sqrt(vx*vx+vy*vy+vz*vz); - k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz; - if (verbal) if (v_length < 1) printf("velocity set to less than 1\n"); - ray_velocity = coords_set(vx,vy,vz); - - #ifdef Union_trace_verbal_setting - printf("Running logger system for specific volumes \n"); - #endif - // Logging for detector components assosiated with this volume - for (log_index=0;log_indexloggers.num_elements;log_index++) { - if (Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process] != NULL) { - // Technically the scattering function could edit k, the wavevector before the scattering, even though there would be little point to doing that. - // Could save a secure copy and pass that instead to be certain that no scattering process accidently tampers with the logging. - - // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis - Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process]->function_pointers.active_record_function(&ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], number_of_scattering_events, Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process], &loggers_with_data_array); - // If the logging component have a conditional attatched, the collected data will be written to a temporary place - // At the end of the rays life, it will be checked if the condition is met - // if it is met, the temporary data is transfered to permanent, and temp is cleared. - // if it is not met, the temporary data is cleared. + } + + // If scattering happens + if (scattering_event == 1) { + // Select scattering process + + // Adjust weight for absorption + abs_weight_factor *= my_sum / my_sum_plus_abs; + abs_weight_factor_set = 1; + // Safety feature, alert in case of nonsense my results / negative absorption + if (my_sum / my_sum_plus_abs > 1.0) + printf ("WARNING: Absorption weight factor above 1! Should not happen! \n"); + // Select process + if (Volumes[current_volume]->p_physics->number_of_processes == 1) { // trivial case + // Select the only available process, which will always have index 0 + selected_process = 0; + } else { + if (Volumes[current_volume]->p_physics->interact_control == 1) { + // Interact_fraction is used to influence the choice of process in this material + mc_prop = rand01 (); + culmative_probability = 0; + total_process_interact = 1.0; + + // If any of the processes have probability 0, they are excluded from the selection + for (iterator = 0; iterator < Volumes[current_volume]->p_physics->number_of_processes; iterator++) { + if (my_trace[iterator] < 1E-18) { + // When this happens, the total force probability is corrected and the probability for this particular instance is set to 0 + total_process_interact -= Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; + my_trace_fraction_control[iterator] = 0; + // In cases where my_trace is not zero, the forced fraction is still used. + } else + my_trace_fraction_control[iterator] = Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; + } + // Randomly select a process using the weights stored in my_trace_fraction_control divided by total_process_interact + for (iterator = 0; iterator < Volumes[current_volume]->p_physics->number_of_processes; iterator++) { + culmative_probability += my_trace_fraction_control[iterator] / total_process_interact; + if (culmative_probability > mc_prop) { + selected_process = iterator; + p *= (my_trace[iterator] / my_sum) * (total_process_interact / my_trace_fraction_control[iterator]); + break; + } + } + + } else { + // Select a process based on their relative attenuations factors + mc_prop = rand01 (); + culmative_probability = 0; + for (iterator = 0; iterator < Volumes[current_volume]->p_physics->number_of_processes; iterator++) { + culmative_probability += my_trace[iterator] / my_sum; + if (culmative_probability > mc_prop) { + selected_process = iterator; + break; + } + } } } - - #ifdef Union_trace_verbal_setting - printf("Running logger system for all volumes \n"); - #endif - for (log_index=0;log_indexnum_elements;log_index++) { - // As above, but on a global scale, meaning scattering in all volumes are logged - - // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components general. - // Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). Weird but not meaningless. - global_all_volume_logger_list_master->elements[log_index].logger->function_pointers.active_record_function(&ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], number_of_scattering_events, global_all_volume_logger_list_master->elements[log_index].logger, &loggers_with_data_array); + + // Select distance to scattering position + if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].needs_cross_section_focus == 1) { + // Respect forced length to scattering chosen by process + length_to_scattering = forced_length_to_scattering; + // Drawing between 0 and L from constant s = 1/L and should have been q = A*exp(-kz). + // Normalizing A*exp(-kz) over 0 to L: A = k/(1-exp(-k*L)) + // Weight correction is ratio between s and q, L*A*exp(-kz) = L*k*exp(-kz)/(1-exp(-Lk)) + p *= length_to_boundary * my_sum_plus_abs * exp (-length_to_scattering * my_sum_plus_abs) / (1.0 - exp (-length_to_boundary * my_sum_plus_abs)); + #ifdef Union_trace_verbal_setting + printf ("Used forced length to scattering, %lf \n", length_to_scattering); + #endif + + } else { + // Decided the ray scatters, choose where on truncated exponential from safety_distance to length_to_boundary - safety_distance + length_to_scattering + = safety_distance - log (1.0 - rand0max ((1.0 - exp (-my_sum_plus_abs * (length_to_boundary - safety_distance2))))) / my_sum_plus_abs; + #ifdef Union_trace_verbal_setting + printf ("Sampled length to scattering, %lf \n", length_to_scattering); + #endif } - #ifdef Union_trace_verbal_setting - printf("Outgoing event: %g %g %g // %g %g %g\n",x,y,z,vx,vy,vz); - #endif - SCATTER; - ++number_of_scattering_events; - ++scattered_flag[current_volume]; - ++scattered_flag_VP[current_volume][selected_process]; - - // Clear intersection time lists as the direction of the ray has changed - clear_intersection_table(&intersection_time_table); - time_propagated_without_scattering = 0.0; - #ifdef Union_trace_verbal_setting - printf("SCATTERED SUCSSESFULLY \n"); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n",x,y,z,vx,vy,vz); - - if (enable_tagging && stop_tagging_ray == 0) printf("Before new process node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("Before new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); - #endif - - if (enable_tagging && stop_tagging_ray == 0) - current_tagging_node = goto_process_node(current_tagging_node, selected_process,Volumes[current_volume], &stop_tagging_ray,stop_creating_nodes); - - #ifdef Union_trace_verbal_setting - - if (enable_tagging && stop_tagging_ray == 0) printf("After new process node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("After new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); - #endif - + + } // Done handling scattering + + } // Done handling situation where there are scattering processes in the material + + } // Done checking for scttering event and in case of scattering selecting a process + + // Record initial weight, absorption weight factor and initial position + + initial_weight = p; + r_old[0] = r[0]; + r_old[1] = r[1]; + r_old[2] = r[2]; + time_old = t; + // Apply absorption + p *= abs_weight_factor; + + // Create event for absorption loggers + // Need to use start position and length travelled to sample that trajectory for absorption event. Could do several, here just one. + + // min length: 0, max length: length_to_scattering if scattering, else length to boundary + + // Avoid logging absorption when the ray is in vacuum. + if (current_volume != 0 && abs_weight_factor_set == 1) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur + if (Volumes[current_volume]->p_physics->is_vacuum == 0) { // No absorption in vacuum + + if (scattering_event == 1) { + // When scattering events occur, place the absoprtion the same place (the total cross section is used to place it) + abs_distance = length_to_scattering; + } else { + // When the ray exits a volume, the absorption position should be exponentially distributed using the total cross section + my_abs = Volumes[current_volume]->p_physics->my_a * (2200 / v_length); + abs_distance = -log (1.0 - rand0max (1.0 - exp (-my_sum_plus_abs * length_to_boundary))) / my_sum_plus_abs; + } + + t_abs_propagation = abs_distance / v_length; + + abs_position = coords_set (x + t_abs_propagation * vx, y + t_abs_propagation * vy, z + t_abs_propagation * vz); + + // This info needs to be loaded into the absorption loggers + + // Need to run through relevant absorption loggers here + #ifdef Union_trace_verbal_setting + printf ("Running abs_logger system for specific volumes \n"); + #endif + + // Logging for detector components assosiated with this volume + for (log_index = 0; log_index < Volumes[current_volume]->abs_loggers.num_elements; log_index++) { + // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers + transformed_abs_position = coords_sub (abs_position, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->position); + transformed_abs_position = rot_apply (Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->rotation, transformed_abs_position); + + // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis + Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->function_pointers.active_record_function ( + &transformed_abs_position, k_new, initial_weight * (1.0 - abs_weight_factor), t + t_abs_propagation, scattered_flag[current_volume], + number_of_scattering_events, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index], &abs_loggers_with_data_array); + // If the logging component have a conditional attatched, the collected data will be written to a temporary place + // At the end of the rays life, it will be checked if the condition is met + // if it is met, the temporary data is transfered to permanent, and temp is cleared. + // if it is not met, the temporary data is cleared. + } + + #ifdef Union_trace_verbal_setting + printf ("Running abs_logger system for all volumes \n"); + #endif + for (log_index = 0; log_index < global_all_volume_abs_logger_list_master->num_elements; log_index++) { + // As above, but on a global scale, meaning scattering in all volumes are logged + + // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components + // general. Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). + // Weird but not meaningless. + + // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers + transformed_abs_position = coords_sub (abs_position, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->position); + transformed_abs_position = rot_apply (global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->rotation, transformed_abs_position); + + // Above version includes scattered_flag_VP, but selected_process may be undefined at this point. + global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->function_pointers.active_record_function ( + &transformed_abs_position, k_new, initial_weight * (1.0 - abs_weight_factor), t + t_abs_propagation, scattered_flag[current_volume], + number_of_scattering_events, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger, &abs_loggers_with_data_array); + } + } + } + + if (scattering_event == 1) { + #ifdef Union_trace_verbal_setting + printf ("SCATTERING EVENT \n"); + printf ("current_volume = %d \n", current_volume); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", r[0], r[1], r[2], v[0], v[1], v[2]); + #endif + + // Calculate the time to scattering + time_to_scattering = length_to_scattering / v_length; + + #ifdef Union_trace_verbal_setting + printf ("time to scattering = %2.20f \n", time_to_scattering); + printf ("length to boundery = %f, length to scattering = %f \n", length_to_boundary, length_to_scattering); + #endif + + // May be replace by version without gravity + // PROP_DT(time_to_scattering); + + // Reduce the double book keeping done here + x += time_to_scattering * vx; + y += time_to_scattering * vy; + z += time_to_scattering * vz; + t += time_to_scattering; + r_start[0] = x; + r_start[1] = y; + r_start[2] = z; + r[0] = x; + r[1] = y; + r[2] = z; + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + + // Safe check that should be unecessary. Used to fine tune how close to the edge of a volume a scattering event is allowed to take place (1E-14 m away + // currently). + if (r_within_function (ray_position, &Volumes[current_volume]->geometry) == 0) { + printf ("\nERROR, propagated out of current volume instead of to a point within!\n"); + printf ("length_to_scattering_specified = %2.20f\n length propagated = %2.20f\n length_to_boundary = %2.20f \n " + "current_position = (%lf,%lf,%lf) \n", + length_to_scattering, + sqrt (time_to_scattering * time_to_scattering * vx * vx + time_to_scattering * time_to_scattering * vy * vy + + time_to_scattering * time_to_scattering * vz * vz), + length_to_boundary, x, y, z); + + volume_index = within_which_volume_GPU (ray_position, starting_lists.reduced_start_list, starting_lists.starting_destinations_list, Volumes, + &mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); + + printf ("Debug info: Volumes[current_volume]->name = %s, but now inside volume number %d named %s.\n", Volumes[current_volume]->name, volume_index, + Volumes[volume_index]->name); + printf ("Ray absorbed \n"); + ABSORB; + } + + // Save information before scattering event needed in logging section + p_old = p; + k_old[0] = k[0]; + k_old[1] = k[1]; + k_old[2] = k[2]; + + // Find correct focus_data_array index for this volume/process and correct for ray position + focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[selected_process]; + this_focus_data = &Volumes[current_volume]->geometry.focus_data_array.elements[focus_data_index]; + + Coords ray_position_geometry = coords_sub (ray_position, Volumes[current_volume]->geometry.center); // ray_position relative to geometry center + + this_focus_data->RayAim = coords_sub (this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray + + // Rotation to local process coordinate system (for non isotropic processes) + if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { + ray_velocity_rotated = rot_apply ( + Volumes[current_volume] + ->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index], + ray_velocity); + + Coords ray_position_geometry_rotated = rot_apply ( + Volumes[current_volume] + ->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index], + ray_position_geometry); + this_focus_data->RayAim = coords_sub (this_focus_data->Aim, ray_position_geometry_rotated); // Aim vector for this ray } else { - previous_volume = current_volume; // Record the current volume as previous, as this will change in this branch of the code - - #ifdef Union_trace_verbal_setting - printf("Propagate out of volume %d\n", current_volume); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); - #endif - // Propagate neutron to found minimum time - // PROP_DT(time_to_boundery); - x += time_to_boundery*vx; - y += time_to_boundery*vy; - z += time_to_boundery*vz; - t += time_to_boundery; - r[0] = x; r[1] = y; r[2] = z; - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - - time_propagated_without_scattering = min_intersection_time; - SCATTER; // For debugging purposes + ray_velocity_rotated = ray_velocity; + this_focus_data->RayAim = coords_sub (this_focus_data->Aim, ray_position_geometry); // Aim vector for this ray + } + #ifdef Union_trace_verbal_setting + printf ("Kin: %g %g %g, selected_process: %i %i\n", k[0], k[1], k[2], selected_process, current_volume); + coords_print (Volumes[current_volume]->geometry.focus_data_array.elements[0].Aim); + #endif + // test_physics_scattering(double *k_final, double *k_initial, union data_transfer_union data_transfer) { + coords_get (coords_scalar_mult (ray_velocity_rotated, V2K), &k[0], &k[1], &k[2]); + + // I may replace a intial and final k with one instance that serves as both input and output + process = &Volumes[current_volume]->p_physics->p_scattering_array[selected_process]; // CPU Only + if (0 == physics_scattering (process->eProcess, k_new, k, &p, process->data_transfer, this_focus_data, _particle)) { + /* + // PowderN and Single_crystal requires the option of absorbing the neutron, which is weird. If there is a scattering probability, there should be a new + direction. + // It can arise from need to simplify sampling process and end up in cases where weight factor is 0, and the ray should be absorbed in these cases + printf("ERROR: Union_master: %s.Absorbed ray because scattering function returned 0 (error/absorb)\n",NAME_CURRENT_COMP); + component_error_msg++; + if (component_error_msg > 100) { + printf("To many errors encountered, exiting. \n"); + exit(1); + } + */ + ABSORB; + } + #ifdef Union_trace_verbal_setting + printf ("Kout: %g %g %g\n", k_new[0], k_new[1], k_new[2]); + #endif + // Update velocity using k + ray_velocity_rotated = coords_set (K2V * k_new[0], K2V * k_new[1], K2V * k_new[2]); + + // Transformation back to main coordinate system (maybe one should only do this when multiple scattering in that volume was over, especially if there is + // only one non isotropic frame) + if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { + ray_velocity_final = rot_apply ( + Volumes[current_volume] + ->geometry.transpose_process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index], + ray_velocity_rotated); + } else { + ray_velocity_final = ray_velocity_rotated; + } + #ifdef Union_trace_verbal_setting + printf ("Final velocity vector "); + coords_print (ray_velocity_final); + #endif + // Write velocity to global variable (temp, only really necessary at final) + coords_get (ray_velocity_final, &vx, &vy, &vz); + + // Write velocity in array format as it is still used by intersect functions (temp, they need to be updated to ray_position / ray_velocity) + v[0] = vx; + v[1] = vy; + v[2] = vz; + v_length = sqrt (vx * vx + vy * vy + vz * vz); + k_new[0] = V2K * vx; + k_new[1] = V2K * vy; + k_new[2] = V2K * vz; + if (verbal) + if (v_length < 1) + printf ("velocity set to less than 1\n"); + ray_velocity = coords_set (vx, vy, vz); + + #ifdef Union_trace_verbal_setting + printf ("Running logger system for specific volumes \n"); + #endif + // Logging for detector components assosiated with this volume + for (log_index = 0; log_index < Volumes[current_volume]->loggers.num_elements; log_index++) { + if (Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process] != NULL) { + // Technically the scattering function could edit k, the wavevector before the scattering, even though there would be little point to doing that. + // Could save a secure copy and pass that instead to be certain that no scattering process accidently tampers with the logging. + + // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis + Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process]->function_pointers.active_record_function ( + &ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], + number_of_scattering_events, Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process], + &loggers_with_data_array); + // If the logging component have a conditional attatched, the collected data will be written to a temporary place + // At the end of the rays life, it will be checked if the condition is met + // if it is met, the temporary data is transfered to permanent, and temp is cleared. + // if it is not met, the temporary data is cleared. + } + } + + #ifdef Union_trace_verbal_setting + printf ("Running logger system for all volumes \n"); + #endif + for (log_index = 0; log_index < global_all_volume_logger_list_master->num_elements; log_index++) { + // As above, but on a global scale, meaning scattering in all volumes are logged + + // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components + // general. Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). + // Weird but not meaningless. + global_all_volume_logger_list_master->elements[log_index].logger->function_pointers.active_record_function ( + &ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], + number_of_scattering_events, global_all_volume_logger_list_master->elements[log_index].logger, &loggers_with_data_array); + } + #ifdef Union_trace_verbal_setting + printf ("Outgoing event: %g %g %g // %g %g %g\n", x, y, z, vx, vy, vz); + #endif + SCATTER; + ++number_of_scattering_events; + ++scattered_flag[current_volume]; + ++scattered_flag_VP[current_volume][selected_process]; + + // Clear intersection time lists as the direction of the ray has changed + clear_intersection_table (&intersection_time_table); + time_propagated_without_scattering = 0.0; + #ifdef Union_trace_verbal_setting + printf ("SCATTERED SUCSSESFULLY \n"); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new process node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node = goto_process_node (current_tagging_node, selected_process, Volumes[current_volume], &stop_tagging_ray, stop_creating_nodes); + + #ifdef Union_trace_verbal_setting + + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new process node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + + } else { + previous_volume = current_volume; // Record the current volume as previous, as this will change in this branch of the code + + #ifdef Union_trace_verbal_setting + printf ("Propagate out of volume %d\n", current_volume); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + #endif + // Propagate neutron to found minimum time + // PROP_DT(time_to_boundery); + x += time_to_boundery * vx; + y += time_to_boundery * vy; + z += time_to_boundery * vz; + t += time_to_boundery; + r[0] = x; + r[1] = y; + r[2] = z; + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + + time_propagated_without_scattering = min_intersection_time; + SCATTER; // For debugging purposes + #ifdef Union_trace_verbal_setting + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + #endif + // Remove this entry from the intersection_time_table + intersection_time_table.intersection_times[min_volume][min_solution] = -1; + + // Use destination list for corresponding intersection entry n,i) to find next volume + #ifdef Union_trace_verbal_setting + printf ("PROPAGATION FROM VOLUME %d \n", current_volume); + #endif + if (min_volume == current_volume) { + #ifdef Union_trace_verbal_setting + printf ("min_volume == current_volume \n"); + #endif + // List approach to finding the next volume. + // When the ray intersects the current volume, the next volume must be on the destination list of the current volume + // However, the reduced_destination_list can be investigated first, and depending on the results, the + // direct children of the volumes on the reduced destination list are investigated. + // In the worst case, all direct children are investigated, which is eqvivalent to the entire destination list. + // There is however a certain overhead in the logic needed to set up this tree, avoid duplicates of direct children, and so on. + // This method is only faster than just checking the destination list when there are direct children (nested structures), + // but in general the tree method scales better with complexity, and is only slightly slower in simple cases. + + if (Volumes[current_volume]->geometry.destinations_list.num_elements == 1) + tree_next_volume = Volumes[current_volume]->geometry.destinations_list.elements[0]; + else { + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + tree_next_volume = within_which_volume_GPU (ray_position, Volumes[current_volume]->geometry.reduced_destinations_list, + Volumes[current_volume]->geometry.destinations_list, Volumes, &mask_status_list, number_of_volumes, + pre_allocated1, pre_allocated2, pre_allocated3); + } + + #ifdef Union_trace_verbal_setting + if (enable_tagging) + printf ("tree method moves from %d to %d\n", current_volume, tree_next_volume); + + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new tree volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new tree volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + + #ifdef Union_trace_verbal_setting + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new tree volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new tree volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + + // Set next volume to the solution found in the tree method + current_volume = tree_next_volume; + update_current_mask_intersect_status (¤t_mask_intersect_list_status, &mask_status_list, Volumes, ¤t_volume); + #ifdef Union_trace_verbal_setting + print_1d_int_list (current_mask_intersect_list_status, "Updated current_mask_intersect_list_status"); + #endif + + } else { + #ifdef Union_trace_verbal_setting + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new intersection volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new intersection volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + + // Mask update: If the min_volume is not a mask, things are simple, current_volume = min_volume. + // however, if it is a mask, the mask status will switch. + // if the mask status becomes one, the masked volumes inside may be the next volume (unless they are children of the mask) + // if the mask status becomes zero (and the current volume is masked by min_volume), the destinations list of the mask is searched + // if the mask status becomes zero (and the current volume is NOT masked by min volume), the current volume doesn't change + + if (Volumes[min_volume]->geometry.is_mask_volume == 0) { #ifdef Union_trace_verbal_setting - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n",x,y,z,vx,vy,vz); + printf ("Min volume is not a mask, next volume = min volume\n"); #endif - // Remove this entry from the intersection_time_table - intersection_time_table.intersection_times[min_volume][min_solution] = -1; - - // Use destination list for corresponding intersection entry n,i) to find next volume + if (enable_tagging && stop_tagging_ray == 0) { + current_tagging_node = goto_volume_node (current_tagging_node, current_volume, min_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + } + current_volume = min_volume; + } else { #ifdef Union_trace_verbal_setting - printf("PROPAGATION FROM VOLUME %d \n",current_volume); + printf ("Current volume is not a mask, complex decision tree\n"); #endif - if (min_volume == current_volume) { - #ifdef Union_trace_verbal_setting - printf("min_volume == current_volume \n"); - #endif - // List approach to finding the next volume. - // When the ray intersects the current volume, the next volume must be on the destination list of the current volume - // However, the reduced_destination_list can be investigated first, and depending on the results, the - // direct children of the volumes on the reduced destination list are investigated. - // In the worst case, all direct children are investigated, which is eqvivalent to the entire destination list. - // There is however a certain overhead in the logic needed to set up this tree, avoid duplicates of direct children, and so on. - // This method is only faster than just checking the destination list when there are direct children (nested structures), - // but in general the tree method scales better with complexity, and is only slightly slower in simple cases. - - if (Volumes[current_volume]->geometry.destinations_list.num_elements == 1) - tree_next_volume = Volumes[current_volume]->geometry.destinations_list.elements[0]; - else { - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - tree_next_volume = within_which_volume_GPU(ray_position,Volumes[current_volume]->geometry.reduced_destinations_list,Volumes[current_volume]->geometry.destinations_list,Volumes,&mask_status_list,number_of_volumes,pre_allocated1,pre_allocated2,pre_allocated3); - } - - #ifdef Union_trace_verbal_setting - if (enable_tagging) printf("tree method moves from %d to %d\n",current_volume,tree_next_volume); - - if (enable_tagging && stop_tagging_ray == 0) printf("Before new tree volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("Before new tree volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); - #endif - - if (enable_tagging && stop_tagging_ray == 0) - current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes,&stop_tagging_ray,stop_creating_nodes); - - #ifdef Union_trace_verbal_setting - if (enable_tagging && stop_tagging_ray == 0) printf("After new tree volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("After new tree volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); - #endif - - // Set next volume to the solution found in the tree method - current_volume = tree_next_volume; - update_current_mask_intersect_status(¤t_mask_intersect_list_status, &mask_status_list, Volumes, ¤t_volume); - #ifdef Union_trace_verbal_setting - print_1d_int_list(current_mask_intersect_list_status,"Updated current_mask_intersect_list_status"); - #endif - - } else { + if (mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] == 1) { + // We are leaving the mask, change the status + #ifdef Union_trace_verbal_setting + printf ("mask status changed from 1 to 0 as a mask is left\n"); + #endif + mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 0; + // If the current volume is masked by this mask, run within_which_volume using the masks destination list, otherwise keep the current volume + if (on_int_list (Volumes[current_volume]->geometry.masked_by_list, min_volume) == 1) { #ifdef Union_trace_verbal_setting - if (enable_tagging && stop_tagging_ray == 0) printf("Before new intersection volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("Before new intersection volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); + printf ("The current volume was masked by this mask, and my need updating\n"); #endif - - // Mask update: If the min_volume is not a mask, things are simple, current_volume = min_volume. - // however, if it is a mask, the mask status will switch. - // if the mask status becomes one, the masked volumes inside may be the next volume (unless they are children of the mask) - // if the mask status becomes zero (and the current volume is masked by min_volume), the destinations list of the mask is searched - // if the mask status becomes zero (and the current volume is NOT masked by min volume), the current volume doesn't change - - if (Volumes[min_volume]->geometry.is_mask_volume == 0) { - #ifdef Union_trace_verbal_setting - printf("Min volume is not a mask, next volume = min volume\n"); - #endif - if (enable_tagging && stop_tagging_ray == 0) { - current_tagging_node = goto_volume_node(current_tagging_node, current_volume, min_volume, Volumes,&stop_tagging_ray,stop_creating_nodes); + // In case of ANY mode, need to see if another mask on the masked_by list of the current volume is active, and if so, nothing happens + need_to_run_within_which_volume = 1; + if (Volumes[current_volume]->geometry.mask_mode == 2) { + for (mask_start = mask_check = Volumes[current_volume]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start < Volumes[current_volume]->geometry.masked_by_mask_index_list.num_elements; mask_check++) { + if (mask_status_list.elements[*mask_check] == 1) { + // Nothing needs to be done, the effective mask status of the current volume is still 1 + need_to_run_within_which_volume = 0; + break; + } } - current_volume = min_volume; - } else { + } + if (need_to_run_within_which_volume == 1) { #ifdef Union_trace_verbal_setting - printf("Current volume is not a mask, complex decision tree\n"); + printf ("The current volume was masked by this mask, and does need updating\n"); #endif - if (mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] == 1) { - // We are leaving the mask, change the status + if (Volumes[min_volume]->geometry.destinations_list.num_elements == 1) { #ifdef Union_trace_verbal_setting - printf("mask status changed from 1 to 0 as a mask is left\n"); + printf ("Only one element in the destination tree of the mask\n"); #endif - mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 0; - // If the current volume is masked by this mask, run within_which_volume using the masks destination list, otherwise keep the current volume - if (on_int_list(Volumes[current_volume]->geometry.masked_by_list,min_volume) == 1) { + // If there is only one element on the destinations list (quite common) there is no reason to run within_which_volume + // Instead the mask status is calculated here + if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.is_masked_volume == 1) { #ifdef Union_trace_verbal_setting - printf("The current volume was masked by this mask, and my need updating\n"); + printf ("The one element is however masked, so the mask status need to be calculated\n"); #endif - // In case of ANY mode, need to see if another mask on the masked_by list of the current volume is active, and if so, nothing happens - need_to_run_within_which_volume = 1; - if (Volumes[current_volume]->geometry.mask_mode == 2) { - for (mask_start=mask_check=Volumes[current_volume]->geometry.masked_by_mask_index_list.elements; mask_check-mask_startgeometry.masked_by_mask_index_list.num_elements; mask_check++) { + // figure out the effective mask status of this volume + if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.mask_mode == 2) { // ANY mask mode + tree_next_volume = 0; + for (mask_start = mask_check + = Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start + < Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements; + mask_check++) { if (mask_status_list.elements[*mask_check] == 1) { - // Nothing needs to be done, the effective mask status of the current volume is still 1 - need_to_run_within_which_volume = 0; + tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; break; } } - } - if (need_to_run_within_which_volume == 1) { - #ifdef Union_trace_verbal_setting - printf("The current volume was masked by this mask, and does need updating\n"); - #endif - if (Volumes[min_volume]->geometry.destinations_list.num_elements == 1) { - #ifdef Union_trace_verbal_setting - printf("Only one element in the destination tree of the mask\n"); - #endif - // If there is only one element on the destinations list (quite common) there is no reason to run within_which_volume - // Instead the mask status is calculated here - if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.is_masked_volume == 1) { - #ifdef Union_trace_verbal_setting - printf("The one element is however masked, so the mask status need to be calculated\n"); - #endif - // figure out the effective mask status of this volume - if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.mask_mode == 2) { // ANY mask mode - tree_next_volume = 0; - for (mask_start=mask_check=Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements; mask_check-mask_startgeometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements; mask_check++) { - if (mask_status_list.elements[*mask_check] == 1) { - tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; - break; - } - } - } else { // ALL mask mode - tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; - for (mask_start=mask_check=Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements;mask_check++) { - if (mask_status_list.elements[*mask_check] == 0) { - tree_next_volume = 0; - break; - } - } - } - } else tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; - #ifdef Union_trace_verbal_setting - printf("The method found the next tree volume to be %d\n",tree_next_volume); - #endif - if (enable_tagging && stop_tagging_ray == 0) current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); - current_volume = tree_next_volume; - } else { - #ifdef Union_trace_verbal_setting - printf("Many elements in destinations list, use within_which_volume\n"); - #endif - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - tree_next_volume = within_which_volume_GPU(ray_position, Volumes[min_volume]->geometry.reduced_destinations_list, Volumes[min_volume]->geometry.destinations_list, Volumes, &mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); - - if (enable_tagging && stop_tagging_ray == 0) current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes,&stop_tagging_ray,stop_creating_nodes); - current_volume = tree_next_volume; - #ifdef Union_trace_verbal_setting - printf("Set new new volume to %d\n",tree_next_volume); - #endif + } else { // ALL mask mode + tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; + for (mask_start = mask_check + = Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start + < Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements; + mask_check++) { + if (mask_status_list.elements[*mask_check] == 0) { + tree_next_volume = 0; + break; + } } - } else { - #ifdef Union_trace_verbal_setting - printf("Did not need updating, as another mask was covering the volume\n"); - #endif } - } - + } else + tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; + #ifdef Union_trace_verbal_setting + printf ("The method found the next tree volume to be %d\n", tree_next_volume); + #endif + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node + = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + current_volume = tree_next_volume; } else { - // Here beccause the mask status of the mask that is intersected was 0, and it is thus switched to 1 - mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 1; - // When entering a mask, the new highest priority volume may be one of the masked volumes, if not we keep the current volume - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - // Bug found on the 2/9 2016, the destinations_list of a mask does not contain the volumes inside it. Could make an additional list for this. - // The temporary fix will be to use the mask list for both reduced destinations list and destinations list. - tree_next_volume = within_which_volume_GPU(ray_position, Volumes[min_volume]->geometry.mask_list, Volumes[min_volume]->geometry.mask_list, Volumes, &mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); - // if within_which_volume returns 0, no result was found (volume 0 can not be masked, so it could not be on the mask list) - if (tree_next_volume != 0) { - if (Volumes[tree_next_volume]->geometry.priority_value > Volumes[current_volume]->geometry.priority_value) { - // In case the current volume has a higher priority, nothing happens, otherwise change current volume - if (enable_tagging && stop_tagging_ray == 0) current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); - current_volume = tree_next_volume; - } - } + #ifdef Union_trace_verbal_setting + printf ("Many elements in destinations list, use within_which_volume\n"); + #endif + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + tree_next_volume = within_which_volume_GPU (ray_position, Volumes[min_volume]->geometry.reduced_destinations_list, + Volumes[min_volume]->geometry.destinations_list, Volumes, &mask_status_list, number_of_volumes, + pre_allocated1, pre_allocated2, pre_allocated3); + + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node + = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + current_volume = tree_next_volume; + #ifdef Union_trace_verbal_setting + printf ("Set new new volume to %d\n", tree_next_volume); + #endif } + } else { + #ifdef Union_trace_verbal_setting + printf ("Did not need updating, as another mask was covering the volume\n"); + #endif } - - // Regardless of the outcome of the above code, either the mask status or current volume have changed, and thus a effective mask update is needed. - update_current_mask_intersect_status(¤t_mask_intersect_list_status, &mask_status_list, Volumes, ¤t_volume); - #ifdef Union_trace_verbal_setting - print_1d_int_list(mask_status_list,"Updated mask status list"); - print_1d_int_list(current_mask_intersect_list_status,"Updated current_mask_intersect_list_status"); - if (enable_tagging) printf("After new intersection volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging) printf("After new intersection volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); - #endif - + } + + } else { + // Here beccause the mask status of the mask that is intersected was 0, and it is thus switched to 1 + mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 1; + // When entering a mask, the new highest priority volume may be one of the masked volumes, if not we keep the current volume + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + // Bug found on the 2/9 2016, the destinations_list of a mask does not contain the volumes inside it. Could make an additional list for this. + // The temporary fix will be to use the mask list for both reduced destinations list and destinations list. + tree_next_volume = within_which_volume_GPU (ray_position, Volumes[min_volume]->geometry.mask_list, Volumes[min_volume]->geometry.mask_list, Volumes, + &mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); + // if within_which_volume returns 0, no result was found (volume 0 can not be masked, so it could not be on the mask list) + if (tree_next_volume != 0) { + if (Volumes[tree_next_volume]->geometry.priority_value > Volumes[current_volume]->geometry.priority_value) { + // In case the current volume has a higher priority, nothing happens, otherwise change current volume + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node + = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + current_volume = tree_next_volume; + } + } + } + } + + // Regardless of the outcome of the above code, either the mask status or current volume have changed, and thus a effective mask update is needed. + update_current_mask_intersect_status (¤t_mask_intersect_list_status, &mask_status_list, Volumes, ¤t_volume); + #ifdef Union_trace_verbal_setting + print_1d_int_list (mask_status_list, "Updated mask status list"); + print_1d_int_list (current_mask_intersect_list_status, "Updated current_mask_intersect_list_status"); + if (enable_tagging) + printf ("After new intersection volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging) + printf ("After new intersection volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + } + #ifdef Union_trace_verbal_setting + printf (" TO VOLUME %d \n", current_volume); + #endif + + double n1, n2; + int perform_refraction = 1; + double nx; + double ny; + double nz; + double normal_vector[3]; + + if (previous_volume + != current_volume) { // With masks, it can happen that the ray takes an extra iteration within the same volume, can skip surface / refraction + + double surface_wavevector_before[3]; + double surface_wavevector[3]; + + nx = intersection_time_table.normal_vector_x[min_volume][min_solution]; + ny = intersection_time_table.normal_vector_y[min_volume][min_solution]; + nz = intersection_time_table.normal_vector_z[min_volume][min_solution]; + NORM (nx, ny, nz); + + // loop over surface processes + // Need face index of both the geometry the ray is leaving and entering, only one from scattering + + // List of surfaces from geometry ray is leaving, bottom to top (length n_leaving) + int relevant_surface_index, n_leaving, n_entering; + struct surface_stack_struct* leaving_stack; + struct surface_stack_struct* entering_stack; + + #ifdef Union_trace_verbal_setting + printf (" Creating leaving surface stack %d \n", previous_volume); + #endif + + if (previous_volume == 0) { + n_leaving = 0; // surrounding vacuum has no stack + } else { + if (previous_volume == min_volume) { + // ray left previous volume on a face of that volume, use that for the list + relevant_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; + leaving_stack = Volumes[previous_volume]->geometry.surface_stack_for_each_face[relevant_surface_index]; + } else { + // ray left previous volume through an internal cut of some kind + leaving_stack = Volumes[previous_volume]->geometry.internal_cut_surface_stack; + } + n_leaving = leaving_stack->number_of_surfaces; + } + + #ifdef Union_trace_verbal_setting + printf (" Created leaving surface stack for volume %d with %d effects \n", previous_volume, n_leaving); + #endif + + if (current_volume == 0) { + n_entering = 0; + } else { + + // List of surfaces from geometry ray is entering, top to bottom (length n_entering) + if (current_volume == min_volume) { + // ray entered current volume on a face of that volume, use that for the list + relevant_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; + entering_stack = Volumes[current_volume]->geometry.surface_stack_for_each_face[relevant_surface_index]; + } else { + // ray left previous volume through an internal cut of some kind + entering_stack = Volumes[current_volume]->geometry.internal_cut_surface_stack; } + n_entering = entering_stack->number_of_surfaces; + } + + int n_total = n_leaving + n_entering; + + #ifdef Union_trace_verbal_setting + printf (" Created entering surface stack for volume %d with %d effects. Combining into one surface stack \n", current_volume, n_entering); + #endif + + // Only need to run surface system if there are any surface processes + if (n_total > 0) { + + // Make combined list, leaving bottom to top followed by entering top to bottom + // Stacks are naturally from bottom to top + for (iterator = 0; iterator < n_total; iterator++) { + if (iterator < n_leaving) { + // grab from leaving stack in natural order + interface_stack.p_surface_array[iterator] = leaving_stack->p_surface_array[iterator]; + } else { + // grab from entering stack in reverse order + interface_stack.p_surface_array[iterator] = entering_stack->p_surface_array[n_entering - iterator + n_leaving - 1]; + } + } + + // struct surface_process_struct **surface_list; could do interface_struct like this instead + + int surface_transverse_index = 0; + int surface_direction = 1; + int surface_iterations = 0; + int in_direction; + int continues; + enum in_or_out inward_or_outward; + + struct surface_process_struct* surface_pointer; + + surface_wavevector[0] = V2K * vx; + surface_wavevector[1] = V2K * vy; + surface_wavevector[2] = V2K * vz; + surface_wavevector_before[0] = surface_wavevector[0]; + surface_wavevector_before[1] = surface_wavevector[1]; + surface_wavevector_before[2] = surface_wavevector[2]; + #ifdef Union_trace_verbal_setting - printf(" TO VOLUME %d \n",current_volume); + double dot_product_before = nx * vx + ny * vy + nz * vz; + printf (" Entering surface stack loop \n"); + printf (" - normal dot v = %lf \n", dot_product_before); #endif - - double n1, n2; - int perform_refraction = 1; - double nx; - double ny; - double nz; - double normal_vector[3]; - - if (previous_volume != current_volume) { // With masks, it can happen that the ray takes an extra iteration within the same volume, can skip surface / refraction - - double surface_wavevector_before[3]; - double surface_wavevector[3]; - - - nx = intersection_time_table.normal_vector_x[min_volume][min_solution]; - ny = intersection_time_table.normal_vector_y[min_volume][min_solution]; - nz = intersection_time_table.normal_vector_z[min_volume][min_solution]; - NORM(nx,ny,nz); - - // loop over surface processes - // Need face index of both the geometry the ray is leaving and entering, only one from scattering - - // List of surfaces from geometry ray is leaving, bottom to top (length n_leaving) - int relevant_surface_index, n_leaving, n_entering; - struct surface_stack_struct *leaving_stack; - struct surface_stack_struct *entering_stack; - - #ifdef Union_trace_verbal_setting - printf(" Creating leaving surface stack %d \n",previous_volume); - #endif - - if (previous_volume == 0) { - n_leaving = 0; // surrounding vacuum has no stack - } else { - if (previous_volume == min_volume) { - // ray left previous volume on a face of that volume, use that for the list - relevant_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; - leaving_stack = Volumes[previous_volume]->geometry.surface_stack_for_each_face[relevant_surface_index]; - } else { - // ray left previous volume through an internal cut of some kind - leaving_stack = Volumes[previous_volume]->geometry.internal_cut_surface_stack; - } - n_leaving = leaving_stack->number_of_surfaces; - } - - #ifdef Union_trace_verbal_setting - printf(" Created leaving surface stack for volume %d with %d effects \n",previous_volume, n_leaving); - #endif - - if (current_volume == 0) { - n_entering = 0; - } else { - - // List of surfaces from geometry ray is entering, top to bottom (length n_entering) - if (current_volume == min_volume) { - // ray entered current volume on a face of that volume, use that for the list - relevant_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; - entering_stack = Volumes[current_volume]->geometry.surface_stack_for_each_face[relevant_surface_index]; - } else { - // ray left previous volume through an internal cut of some kind - entering_stack = Volumes[current_volume]->geometry.internal_cut_surface_stack; - } - n_entering = entering_stack->number_of_surfaces; - } - - int n_total = n_leaving + n_entering; - - #ifdef Union_trace_verbal_setting - printf(" Created entering surface stack for volume %d with %d effects. Combining into one surface stack \n",current_volume, n_entering); - #endif - - // Only need to run surface system if there are any surface processes - if (n_total > 0) { - - // Make combined list, leaving bottom to top followed by entering top to bottom - // Stacks are naturally from bottom to top - for (iterator=0; iteratorp_surface_array[iterator]; - } else { - // grab from entering stack in reverse order - interface_stack.p_surface_array[iterator] = entering_stack->p_surface_array[n_entering - iterator + n_leaving - 1]; - } - } - - // struct surface_process_struct **surface_list; could do interface_struct like this instead - - int surface_transverse_index = 0; - int surface_direction = 1; - int surface_iterations = 0; - int in_direction; - int continues; - enum in_or_out inward_or_outward; - - struct surface_process_struct *surface_pointer; - - surface_wavevector[0] = V2K*vx; surface_wavevector[1] = V2K*vy; surface_wavevector[2] = V2K*vz; - surface_wavevector_before[0] = surface_wavevector[0]; - surface_wavevector_before[1] = surface_wavevector[1]; - surface_wavevector_before[2] = surface_wavevector[2]; - - #ifdef Union_trace_verbal_setting - double dot_product_before = nx*vx + ny*vy + nz*vz; - printf(" Entering surface stack loop \n"); - printf(" - normal dot v = %lf \n", dot_product_before); - #endif - - while (1) { - - #ifdef Union_trace_verbal_setting - printf(" Start of surface stack with transverse_index = %d \n", surface_transverse_index); - #endif - - // Escape conditions on each side of stack - if (surface_transverse_index < 0) { - // Escaped from incoming direction - perform_refraction = 0; - current_volume = previous_volume; - - #ifdef Union_trace_verbal_setting - printf(" Left stack to incoming side \n"); - #endif - - break; - } - - if (surface_transverse_index >= n_total) { - // Went through all layers, continue to refraction as normal - #ifdef Union_trace_verbal_setting - printf(" Left stack by going all the way through \n"); - #endif - break; - } - - surface_pointer = interface_stack.p_surface_array[surface_transverse_index]; - - if (surface_transverse_index < n_leaving) in_direction = 1; else in_direction = -1; - if (surface_direction == in_direction) inward_or_outward = inward_bound; else inward_or_outward = outward_bound; - - // fresh normal in case surface function messed with it - normal_vector[0] = nx; normal_vector[1] = ny; normal_vector[2] = nz; - - // p, wavevector and continues updated by surface_function - #ifdef Union_trace_verbal_setting - printf(" Running physics_surface with transverse_index = %d \n", surface_transverse_index); - #endif - physics_surface(surface_pointer, &p, surface_wavevector, &continues, normal_vector, inward_or_outward, _particle); - #ifdef Union_trace_verbal_setting - printf(" physics_surface reported continues = %d \n", continues); - #endif - - // insert logging - - if (!continues) surface_direction = -surface_direction; // Flip stack direction if the ray does not continue - - surface_transverse_index += surface_direction; // Go to next element in stack - surface_iterations += 1; - - if (surface_iterations > 10000) { - printf("ERROR: Ray stuck in surface stack, ABSORBED\n"); - done = 1; - ray_sucseeded = 0; - break; - } - } - - // If velocity was updated, register that to the ray and reset intersection memory - // Hardcoded limit of 1E-10 m/s change in any direction - if (fabs(surface_wavevector_before[0] - surface_wavevector[0]) > 1E-10 || - fabs(surface_wavevector_before[1] - surface_wavevector[1]) > 1E-10 || - fabs(surface_wavevector_before[2] - surface_wavevector[2]) > 1E-10) { - - vx = surface_wavevector[0]*K2V; - vy = surface_wavevector[1]*K2V; - vz = surface_wavevector[2]*K2V; - #ifdef Union_trace_verbal_setting - printf(" ray direction updated by surface stack \n"); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); - printf(" - normal dot v = %lf \n", nx*vx + ny*vy + nz*vz); - if (surface_transverse_index < 0) printf("Should have different sign \n"); - if (surface_transverse_index >= n_total) printf("Should have same sign \n"); - if (dot_product_before * (nx*vx + ny*vy + nz*vz) < 0) { - printf("Sign did change \n"); - } else printf("Sign did not change \n"); - #endif - - // Report new velocity back, - // Update velocity in all ways used in master - v[0] = vx; v[1] = vy; v[2] = vz; - v_length = sqrt(vx*vx + vy*vy + vz*vz); - k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz; - ray_velocity = coords_set(vx, vy, vz); - - ignore_closest = min_volume; - ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; - - // Since velocity is updated, we need to clear the intersection time table - clear_intersection_table(&intersection_time_table); - - // Reset origin point for ray - r_start[0] = x; r_start[1] = y; r_start[2] = z; - time_propagated_without_scattering = 0.0; - } - } - - // Need old and current volume here to compare refraction index - // Need information on normal vector for intersection - // Can then change direction accordingly + + while (1) { #ifdef Union_trace_verbal_setting - printf("Entering refraction system \n"); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); - printf("n = (%f,%f,%f)\n", nx, ny, nz); - double dot_product_before = nx*vx + ny*vy + nz*vz; - printf("normal dot v = %lf \n", dot_product_before); - printf("min_volume = %d, min_solution = %d\n", min_volume, min_solution); + printf (" Start of surface stack with transverse_index = %d \n", surface_transverse_index); #endif - - // Check if the volume intersection was found with returns normal, allowing refraction calculation - // todo will implement differnet solution - //if (Volumes[min_volume]->geometry.returns_intersection_normal == 0) perform_refraction = 0; - - v_length = sqrt(vx*vx+vy*vy+vz*vz); - double lambda = 3956.0032/v_length; - - if (previous_volume == 0) n1 = 1.0; - else { - if (Volumes[previous_volume]->p_physics->has_refraction_info == 0 && Volumes[previous_volume]->p_physics->is_vacuum == 0) { - perform_refraction = 0; - } else { - - if (Volumes[previous_volume]->p_physics->is_vacuum == 1) { - n1 = 1.0; - } else { - n1 = sqrt(1.0-(lambda*lambda*Volumes[previous_volume]->p_physics->refraction_scattering_length_density/PI)); - } - - // If the intersection is found with this volume, it is leaving, and the normal needs to be flipped - if (previous_volume == min_volume) { - nx *= -1; - ny *= -1; - nz *= -1; - - } - } + + // Escape conditions on each side of stack + if (surface_transverse_index < 0) { + // Escaped from incoming direction + perform_refraction = 0; + current_volume = previous_volume; + + #ifdef Union_trace_verbal_setting + printf (" Left stack to incoming side \n"); + #endif + + break; } - - if (current_volume == 0) n2 = 1.0; - else { - if (Volumes[current_volume]->p_physics->has_refraction_info == 0 && Volumes[current_volume]->p_physics->is_vacuum == 0) { - perform_refraction = 0; - } else { - - if (Volumes[current_volume]->p_physics->is_vacuum == 1) { - n2 = 1.0; - } else { - n2 = sqrt(1.0-(lambda*lambda*Volumes[current_volume]->p_physics->refraction_scattering_length_density/PI)); - } - } + + if (surface_transverse_index >= n_total) { + // Went through all layers, continue to refraction as normal + #ifdef Union_trace_verbal_setting + printf (" Left stack by going all the way through \n"); + #endif + break; } - - // Check if the two materials are the same, no need to check for refraction / reflection. - if (perform_refraction == 1 && previous_volume != 0 && current_volume != 0) { - if (strcmp(Volumes[previous_volume]->p_physics->name, Volumes[current_volume]->p_physics->name) == 0 ) { - perform_refraction = 0; - } - } - - if (previous_volume == 0 && current_volume == 0) { - perform_refraction = 0; // Vacuum to vacuum - } else if (previous_volume == 0) { - if (Volumes[current_volume]->p_physics->is_vacuum == 1) perform_refraction = 0; // Vacuum to vacuum - } else if (current_volume == 0) { - if (Volumes[previous_volume]->p_physics->is_vacuum == 1) perform_refraction = 0; // Vacuum to vacuum - } else { - if (Volumes[previous_volume]->p_physics->is_vacuum == 1 && Volumes[current_volume]->p_physics->is_vacuum == 1) perform_refraction = 0; // Vacuum to vacuum - } - + + surface_pointer = interface_stack.p_surface_array[surface_transverse_index]; + + if (surface_transverse_index < n_leaving) + in_direction = 1; + else + in_direction = -1; + if (surface_direction == in_direction) + inward_or_outward = inward_bound; + else + inward_or_outward = outward_bound; + + // fresh normal in case surface function messed with it + normal_vector[0] = nx; + normal_vector[1] = ny; + normal_vector[2] = nz; + + // p, wavevector and continues updated by surface_function #ifdef Union_trace_verbal_setting - if (perform_refraction == 1) - printf("ready to calculate refraction, current_volume = %d, n1=%lf, n2=%lf \n", current_volume, n1, n2); - else - printf("skipping refraction system, current_volume = %d, n1=%lf, n2=%lf \n", current_volume, n1, n2); + printf (" Running physics_surface with transverse_index = %d \n", surface_transverse_index); #endif - - if (perform_refraction == 1) { - - double reflectivity; - - // Skipping roughness - //if (RMS>0) Surface_wavyness(&nx, &ny, &nz, atan(2*RMS/lambda), _particle); - - Coords N = coords_set(nx, ny, nz); // normal vector to surface - Coords V = coords_set(vx, vy, vz); // incoming velocity - Coords I = coords_scale(V, 1/v_length); // normalised ray = v/|v| - - // compute reflectivity - double qc; - double q_normal = fabs(2*coords_sp(V, N)*V2Q); - double q_qc_quadratic_diff; - int use_fresnel; - - use_fresnel = 1; - - /* Reflectivity (see component Guide). */ - //StdReflecFunc(q_normal, par, &reflectivity); - - // Reflectivity calculation - if (n2/n1 < 1.0) { - // qc exists - qc = 4.0*PI*sin(acos(n2/n1))/lambda; - if (q_normal < qc) { - reflectivity = 1.0; - use_fresnel = 0; - } - // NEUTRON REFLECTION: PRINCIPLES AND EXAMPLES OF APPLICATIONS: Robert Cubitt and Giovanna Fragneto - // This expression only works when a qc exists - //q_qc_quadratic_diff = sqrt(q_normal*q_normal - qc*qc) - //reflectivity = pow((q_normal - q_qc_quadratic_diff)/(q_normal + q_qc_quadratic_diff), 2); - } - - if (use_fresnel) { - // Fresnel law for both n1 > n2 and n1 < n2 - double term1, term2, R_perp, R_parallel; - term1 = n1 * sqrt(1.0 - pow(lambda * q_normal / (4.0 * PI * n1), 2)); - term2 = n2 * sqrt(1.0 - pow(lambda * q_normal / (4.0 * PI * n2), 2)); - R_perp = ((term1 - term2) / (term1 + term2))*((term1 - term2) / (term1 + term2)); - R_parallel = ((term2 - term1) / (term2 + term1))*((term2 - term1) / (term2 + term1)); - reflectivity = 0.5*(R_perp + R_parallel); // Unpolarized neutrons - } - - - double theta1, theta2; - // theta1: incident angle to the surface normal - double cos_theta1 = -coords_sp(N,I); // cos(theta1) = -N.I - - if (fabs(cos_theta1) > 1) { - printf("cos_theta1 > 1, Refraction error! Asborbed ray.\n"); - ABSORB; // should never occur... - } - theta1 = acos(cos_theta1)*RAD2DEG; - - // reflected ray: probability R - // reflected beam: I + 2cos(theta1).N - Coords I_reflect = coords_add(I, coords_scale(N, 2.0*cos_theta1)); - // reflected velocity: I_reflect.v - Coords V_reflect = coords_scale(I_reflect, v_length); - - // compute refracted angle theta2... - double sqr_cos_theta2 = 1.0-(n1/n2)*(n1/n2)*(1.0-cos_theta1*cos_theta1); - - // now choose which one to use, and compute outgoing velocity - if (0 < sqr_cos_theta2 && sqr_cos_theta2 < 1.0) { - // refraction is possible - - // theta2: refracted angle to the surface normal - double cos_theta2 = sqrt(sqr_cos_theta2); - - // select reflection (or refraction) from Monte-Carlo choice with probability R - // in this case we expect R to be small (q > Qc) - if (enable_reflection && 0.0 < reflectivity && reflectivity < 1.0 && rand01() < reflectivity) { - - // choose reflection from MC - theta2 = theta1; - coords_get(V_reflect, &vx, &vy, &vz); - - current_volume = previous_volume; // Reflected, stays in current volume - - // Update velocity in all ways used in master - v[0] = vx; v[1] = vy; v[2] = vz; - v_length = sqrt(vx*vx + vy*vy + vz*vz); - k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz; - ray_velocity = coords_set(vx, vy, vz); - - #ifdef Union_trace_verbal_setting - printf(" Refraction system : ray reflected, (branch 1) going back to volume %d\n", previous_volume); - - printf(" normal dot v = %lf \n", nx*vx + ny*vy + nz*vz); - if ((nx*vx + ny*vy + nz*vz)*dot_product_before > 0) printf(" SIGN SHOULD HAVE CHANGED BUT DIDN'T \n"); - #endif - - ignore_closest = min_volume; - ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; - - // Since velocity is updated, we need to clear the intersection time table - clear_intersection_table(&intersection_time_table); - - // Reset origin point for ray - r_start[0] = x; r_start[1] = y; r_start[2] = z; - time_propagated_without_scattering = 0.0; - - } else if (enable_refraction) { - // compute refracted ray - theta2 = acos(cos_theta2)*RAD2DEG; - - Coords I_refract = coords_add(coords_scale(I, n1/n2), - coords_scale(N, n1/n2*cos_theta1 + (cos_theta1 < 0 ? cos_theta2 : -cos_theta2) )); - Coords V_refract = coords_scale(I_refract, v_length); - - coords_get(V_refract, &vx, &vy, &vz); - - - // Update velocity in all ways used in master - v[0] = vx; v[1] = vy; v[2] = vz; - v_length = sqrt(vx*vx + vy*vy + vz*vz); - k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz; - ray_velocity = coords_set(vx, vy, vz); - - #ifdef Union_trace_verbal_setting - printf(" Refraction system : ray refracted, continues to to volume %d\n", current_volume); - - printf(" normal dot v = %lf theta2 = %lf \n", nx*vx + ny*vy + nz*vz, theta2); - if ((nx*vx + ny*vy + nz*vz)*dot_product_before < 0) printf(" SIGN SHOULD NOT HAVE CHANGED BUT DID \n"); - #endif - - // Reflected can ignore some intersections in next geometry iteration - ignore_closest = min_volume; // Ignore closest intersection in next geometry iteration - ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; - - // Since velocity is updated, we need to clear the intersection time table - clear_intersection_table(&intersection_time_table); - - // Reset origin point for ray - r_start[0] = x; r_start[1] = y; r_start[2] = z; - time_propagated_without_scattering = 0.0; - - } - } else if (enable_reflection) { - // only reflection: below total reflection - - theta2 = theta1; - if (0 < reflectivity && reflectivity < 1) p *= reflectivity; // should be R0 - coords_get(V_reflect, &vx, &vy, &vz); - - current_volume = previous_volume; // Reflected, stays in current volume - - // Update velocity in all ways used in master - v[0] = vx; v[1] = vy; v[2] = vz; - v_length = sqrt(vx*vx + vy*vy + vz*vz); - k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz; - ray_velocity = coords_set(vx, vy, vz); - - #ifdef Union_trace_verbal_setting - printf(" Refraction system : ray reflected (branch 3), going back to volume %d\n", previous_volume); - printf(" normal dot v = %lf \n", nx*vx + ny*vy + nz*vz); - if ((nx*vx + ny*vy + nz*vz)*dot_product_before > 0) printf(" SIGN SHOULD HAVE CHANGED BUT DIDN'T \n"); - #endif - - // Reflected can ignore some intersections in next geometry iteration - ignore_closest = min_volume; - ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; - // Since velocity is updated, we need to clear the intersection time table - clear_intersection_table(&intersection_time_table); - - // Reset origin point for ray - r_start[0] = x; r_start[1] = y; r_start[2] = z; - time_propagated_without_scattering = 0.0; - } + physics_surface (surface_pointer, &p, surface_wavevector, &continues, normal_vector, inward_or_outward, _particle); + #ifdef Union_trace_verbal_setting + printf (" physics_surface reported continues = %d \n", continues); + #endif + + // insert logging + + if (!continues) + surface_direction = -surface_direction; // Flip stack direction if the ray does not continue + + surface_transverse_index += surface_direction; // Go to next element in stack + surface_iterations += 1; + + if (surface_iterations > 10000) { + printf ("ERROR: Ray stuck in surface stack, ABSORBED\n"); + done = 1; + ray_sucseeded = 0; + break; } - - // todo: decide how surface on an exit volume should be treated - if (Volumes[current_volume]->geometry.is_exit_volume==1) { - done = 1; // Exit volumes allow the ray to escape the component - ray_sucseeded = 1; // Allows the ray to leave loop + } + + // If velocity was updated, register that to the ray and reset intersection memory + // Hardcoded limit of 1E-10 m/s change in any direction + if (fabs (surface_wavevector_before[0] - surface_wavevector[0]) > 1E-10 || fabs (surface_wavevector_before[1] - surface_wavevector[1]) > 1E-10 + || fabs (surface_wavevector_before[2] - surface_wavevector[2]) > 1E-10) { + + vx = surface_wavevector[0] * K2V; + vy = surface_wavevector[1] * K2V; + vz = surface_wavevector[2] * K2V; + #ifdef Union_trace_verbal_setting + printf (" ray direction updated by surface stack \n"); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + printf (" - normal dot v = %lf \n", nx * vx + ny * vy + nz * vz); + if (surface_transverse_index < 0) + printf ("Should have different sign \n"); + if (surface_transverse_index >= n_total) + printf ("Should have same sign \n"); + if (dot_product_before * (nx * vx + ny * vy + nz * vz) < 0) { + printf ("Sign did change \n"); + } else + printf ("Sign did not change \n"); + #endif + + // Report new velocity back, + // Update velocity in all ways used in master + v[0] = vx; + v[1] = vy; + v[2] = vz; + v_length = sqrt (vx * vx + vy * vy + vz * vz); + k_new[0] = V2K * vx; + k_new[1] = V2K * vy; + k_new[2] = V2K * vz; + ray_velocity = coords_set (vx, vy, vz); + + ignore_closest = min_volume; + ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; + + // Since velocity is updated, we need to clear the intersection time table + clear_intersection_table (&intersection_time_table); + + // Reset origin point for ray + r_start[0] = x; + r_start[1] = y; + r_start[2] = z; + time_propagated_without_scattering = 0.0; + } + } + + // Need old and current volume here to compare refraction index + // Need information on normal vector for intersection + // Can then change direction accordingly + + #ifdef Union_trace_verbal_setting + printf ("Entering refraction system \n"); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + printf ("n = (%f,%f,%f)\n", nx, ny, nz); + double dot_product_before = nx * vx + ny * vy + nz * vz; + printf ("normal dot v = %lf \n", dot_product_before); + printf ("min_volume = %d, min_solution = %d\n", min_volume, min_solution); + #endif + + // Check if the volume intersection was found with returns normal, allowing refraction calculation + // todo will implement differnet solution + // if (Volumes[min_volume]->geometry.returns_intersection_normal == 0) perform_refraction = 0; + + v_length = sqrt (vx * vx + vy * vy + vz * vz); + double lambda = 3956.0032 / v_length; + + if (previous_volume == 0) + n1 = 1.0; + else { + if (Volumes[previous_volume]->p_physics->has_refraction_info == 0 && Volumes[previous_volume]->p_physics->is_vacuum == 0) { + perform_refraction = 0; + } else { + + if (Volumes[previous_volume]->p_physics->is_vacuum == 1) { + n1 = 1.0; + } else { + n1 = sqrt (1.0 - (lambda * lambda * Volumes[previous_volume]->p_physics->refraction_scattering_length_density / PI)); } - - - #ifdef Union_trace_verbal_setting - printf("After refraction system \n"); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); - printf(" - normal_dot_v = %lf \n", nx*vx + ny*vy + nz*vz); - printf("CURRENT_VOLUME = %d \n", current_volume); - #endif - - } // End of if (previous_volume != current_volume) - } // End of scattering or propagation if - - } else { // Here because a shortest time is not found - if (current_volume == 0) { - done = 1; - ray_sucseeded = 1; - - } else { // Check for errors (debugging phase) - if (error_msg == 0) { - component_error_msg++; - ray_sucseeded = 0; - done = 1; // stop the loop - printf("\n----------------------------------------------------------------------------------------------------\n"); - printf("Union_master %s: Somehow reached a situation with no intersection time found, but still inside volume %d instead of 0\n",NAME_CURRENT_COMP,current_volume); - for (volume_index = 1; volume_index < number_of_volumes; volume_index++) { - if (r_within_function(ray_position,&Volumes[volume_index]->geometry) == 1) - printf("The ray is in volume %d\n",volume_index); + + // If the intersection is found with this volume, it is leaving, and the normal needs to be flipped + if (previous_volume == min_volume) { + nx *= -1; + ny *= -1; + nz *= -1; + } + } + } + + if (current_volume == 0) + n2 = 1.0; + else { + if (Volumes[current_volume]->p_physics->has_refraction_info == 0 && Volumes[current_volume]->p_physics->is_vacuum == 0) { + perform_refraction = 0; + } else { + + if (Volumes[current_volume]->p_physics->is_vacuum == 1) { + n2 = 1.0; + } else { + n2 = sqrt (1.0 - (lambda * lambda * Volumes[current_volume]->p_physics->refraction_scattering_length_density / PI)); } - - print_1d_int_list(mask_status_list,"mask status list"); - for (iterator=0;iterator 100) { - printf("To many errors encountered, exiting. \n"); - // need ERROR FLAG to be read in finally which can warn the user of problems! - exit(1); + } + + // Check if the two materials are the same, no need to check for refraction / reflection. + if (perform_refraction == 1 && previous_volume != 0 && current_volume != 0) { + if (strcmp (Volumes[previous_volume]->p_physics->name, Volumes[current_volume]->p_physics->name) == 0) { + perform_refraction = 0; } + } + + if (previous_volume == 0 && current_volume == 0) { + perform_refraction = 0; // Vacuum to vacuum + } else if (previous_volume == 0) { + if (Volumes[current_volume]->p_physics->is_vacuum == 1) + perform_refraction = 0; // Vacuum to vacuum + } else if (current_volume == 0) { + if (Volumes[previous_volume]->p_physics->is_vacuum == 1) + perform_refraction = 0; // Vacuum to vacuum + } else { + if (Volumes[previous_volume]->p_physics->is_vacuum == 1 && Volumes[current_volume]->p_physics->is_vacuum == 1) + perform_refraction = 0; // Vacuum to vacuum + } + + #ifdef Union_trace_verbal_setting + if (perform_refraction == 1) + printf ("ready to calculate refraction, current_volume = %d, n1=%lf, n2=%lf \n", current_volume, n1, n2); + else + printf ("skipping refraction system, current_volume = %d, n1=%lf, n2=%lf \n", current_volume, n1, n2); + #endif + + if (perform_refraction == 1) { + + double reflectivity; + + // Skipping roughness + // if (RMS>0) Surface_wavyness(&nx, &ny, &nz, atan(2*RMS/lambda), _particle); + + Coords N = coords_set (nx, ny, nz); // normal vector to surface + Coords V = coords_set (vx, vy, vz); // incoming velocity + Coords I = coords_scale (V, 1 / v_length); // normalised ray = v/|v| + + // compute reflectivity + double qc; + double q_normal = fabs (2 * coords_sp (V, N) * V2Q); + double q_qc_quadratic_diff; + int use_fresnel; + + use_fresnel = 1; + + /* Reflectivity (see component Guide). */ + // StdReflecFunc(q_normal, par, &reflectivity); + + // Reflectivity calculation + if (n2 / n1 < 1.0) { + // qc exists + qc = 4.0 * PI * sin (acos (n2 / n1)) / lambda; + if (q_normal < qc) { + reflectivity = 1.0; + use_fresnel = 0; + } + // NEUTRON REFLECTION: PRINCIPLES AND EXAMPLES OF APPLICATIONS: Robert Cubitt and Giovanna Fragneto + // This expression only works when a qc exists + // q_qc_quadratic_diff = sqrt(q_normal*q_normal - qc*qc) + // reflectivity = pow((q_normal - q_qc_quadratic_diff)/(q_normal + q_qc_quadratic_diff), 2); + } + + if (use_fresnel) { + // Fresnel law for both n1 > n2 and n1 < n2 + double term1, term2, R_perp, R_parallel; + term1 = n1 * sqrt (1.0 - pow (lambda * q_normal / (4.0 * PI * n1), 2)); + term2 = n2 * sqrt (1.0 - pow (lambda * q_normal / (4.0 * PI * n2), 2)); + R_perp = ((term1 - term2) / (term1 + term2)) * ((term1 - term2) / (term1 + term2)); + R_parallel = ((term2 - term1) / (term2 + term1)) * ((term2 - term1) / (term2 + term1)); + reflectivity = 0.5 * (R_perp + R_parallel); // Unpolarized neutrons + } + + double theta1, theta2; + // theta1: incident angle to the surface normal + double cos_theta1 = -coords_sp (N, I); // cos(theta1) = -N.I + + if (fabs (cos_theta1) > 1) { + printf ("cos_theta1 > 1, Refraction error! Asborbed ray.\n"); + ABSORB; // should never occur... + } + theta1 = acos (cos_theta1) * RAD2DEG; + + // reflected ray: probability R + // reflected beam: I + 2cos(theta1).N + Coords I_reflect = coords_add (I, coords_scale (N, 2.0 * cos_theta1)); + // reflected velocity: I_reflect.v + Coords V_reflect = coords_scale (I_reflect, v_length); + + // compute refracted angle theta2... + double sqr_cos_theta2 = 1.0 - (n1 / n2) * (n1 / n2) * (1.0 - cos_theta1 * cos_theta1); + + // now choose which one to use, and compute outgoing velocity + if (0 < sqr_cos_theta2 && sqr_cos_theta2 < 1.0) { + // refraction is possible + + // theta2: refracted angle to the surface normal + double cos_theta2 = sqrt (sqr_cos_theta2); + + // select reflection (or refraction) from Monte-Carlo choice with probability R + // in this case we expect R to be small (q > Qc) + if (enable_reflection && 0.0 < reflectivity && reflectivity < 1.0 && rand01 () < reflectivity) { + + // choose reflection from MC + theta2 = theta1; + coords_get (V_reflect, &vx, &vy, &vz); + + current_volume = previous_volume; // Reflected, stays in current volume + + // Update velocity in all ways used in master + v[0] = vx; + v[1] = vy; + v[2] = vz; + v_length = sqrt (vx * vx + vy * vy + vz * vz); + k_new[0] = V2K * vx; + k_new[1] = V2K * vy; + k_new[2] = V2K * vz; + ray_velocity = coords_set (vx, vy, vz); + + #ifdef Union_trace_verbal_setting + printf (" Refraction system : ray reflected, (branch 1) going back to volume %d\n", previous_volume); + + printf (" normal dot v = %lf \n", nx * vx + ny * vy + nz * vz); + if ((nx * vx + ny * vy + nz * vz) * dot_product_before > 0) + printf (" SIGN SHOULD HAVE CHANGED BUT DIDN'T \n"); + #endif + + ignore_closest = min_volume; + ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; + + // Since velocity is updated, we need to clear the intersection time table + clear_intersection_table (&intersection_time_table); + + // Reset origin point for ray + r_start[0] = x; + r_start[1] = y; + r_start[2] = z; + time_propagated_without_scattering = 0.0; + + } else if (enable_refraction) { + // compute refracted ray + theta2 = acos (cos_theta2) * RAD2DEG; + + Coords I_refract = coords_add (coords_scale (I, n1 / n2), coords_scale (N, n1 / n2 * cos_theta1 + (cos_theta1 < 0 ? cos_theta2 : -cos_theta2))); + Coords V_refract = coords_scale (I_refract, v_length); + + coords_get (V_refract, &vx, &vy, &vz); + + // Update velocity in all ways used in master + v[0] = vx; + v[1] = vy; + v[2] = vz; + v_length = sqrt (vx * vx + vy * vy + vz * vz); + k_new[0] = V2K * vx; + k_new[1] = V2K * vy; + k_new[2] = V2K * vz; + ray_velocity = coords_set (vx, vy, vz); + + #ifdef Union_trace_verbal_setting + printf (" Refraction system : ray refracted, continues to to volume %d\n", current_volume); + + printf (" normal dot v = %lf theta2 = %lf \n", nx * vx + ny * vy + nz * vz, theta2); + if ((nx * vx + ny * vy + nz * vz) * dot_product_before < 0) + printf (" SIGN SHOULD NOT HAVE CHANGED BUT DID \n"); + #endif + + // Reflected can ignore some intersections in next geometry iteration + ignore_closest = min_volume; // Ignore closest intersection in next geometry iteration + ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; + + // Since velocity is updated, we need to clear the intersection time table + clear_intersection_table (&intersection_time_table); + + // Reset origin point for ray + r_start[0] = x; + r_start[1] = y; + r_start[2] = z; + time_propagated_without_scattering = 0.0; + } + } else if (enable_reflection) { + // only reflection: below total reflection + + theta2 = theta1; + if (0 < reflectivity && reflectivity < 1) + p *= reflectivity; // should be R0 + coords_get (V_reflect, &vx, &vy, &vz); + + current_volume = previous_volume; // Reflected, stays in current volume + + // Update velocity in all ways used in master + v[0] = vx; + v[1] = vy; + v[2] = vz; + v_length = sqrt (vx * vx + vy * vy + vz * vz); + k_new[0] = V2K * vx; + k_new[1] = V2K * vy; + k_new[2] = V2K * vz; + ray_velocity = coords_set (vx, vy, vz); + + #ifdef Union_trace_verbal_setting + printf (" Refraction system : ray reflected (branch 3), going back to volume %d\n", previous_volume); + printf (" normal dot v = %lf \n", nx * vx + ny * vy + nz * vz); + if ((nx * vx + ny * vy + nz * vz) * dot_product_before > 0) + printf (" SIGN SHOULD HAVE CHANGED BUT DIDN'T \n"); + #endif + + // Reflected can ignore some intersections in next geometry iteration + ignore_closest = min_volume; + ignore_surface_index = intersection_time_table.surface_index[min_volume][min_solution]; + // Since velocity is updated, we need to clear the intersection time table + clear_intersection_table (&intersection_time_table); + + // Reset origin point for ray + r_start[0] = x; + r_start[1] = y; + r_start[2] = z; + time_propagated_without_scattering = 0.0; + } + } + + // todo: decide how surface on an exit volume should be treated + if (Volumes[current_volume]->geometry.is_exit_volume == 1) { + done = 1; // Exit volumes allow the ray to escape the component + ray_sucseeded = 1; // Allows the ray to leave loop + } + + #ifdef Union_trace_verbal_setting + printf ("After refraction system \n"); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + printf (" - normal_dot_v = %lf \n", nx * vx + ny * vy + nz * vz); + printf ("CURRENT_VOLUME = %d \n", current_volume); + #endif + + } // End of if (previous_volume != current_volume) + } // End of scattering or propagation if + + } else { // Here because a shortest time is not found + if (current_volume == 0) { + done = 1; + ray_sucseeded = 1; + + } else { // Check for errors (debugging phase) + if (error_msg == 0) { + component_error_msg++; + ray_sucseeded = 0; + done = 1; // stop the loop + printf ("\n----------------------------------------------------------------------------------------------------\n"); + printf ("Union_master %s: Somehow reached a situation with no intersection time found, but still inside volume %d instead of 0\n", NAME_CURRENT_COMP, + current_volume); + for (volume_index = 1; volume_index < number_of_volumes; volume_index++) { + if (r_within_function (ray_position, &Volumes[volume_index]->geometry) == 1) + printf ("The ray is in volume %d\n", volume_index); + } + + print_1d_int_list (mask_status_list, "mask status list"); + for (iterator = 0; iterator < number_of_volumes; iterator++) + printf ("%d:%d - ", iterator, scattered_flag[iterator]); + printf ("\n"); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + + printf ("Trace error number (%d/100) \n", component_error_msg); } + error_msg++; + + if (component_error_msg > 100) { + printf ("To many errors encountered, exiting. \n"); + // need ERROR FLAG to be read in finally which can warn the user of problems! + exit (1); + } + } + } + + if (limit == 0) { + done = 1; + ray_sucseeded = 0; + printf ("Reached limit on number of interactions, and discarded the neutron, was in volume %d\n", current_volume); + ABSORB; } - - if (limit == 0) {done = 1; ray_sucseeded = 0; printf("Reached limit on number of interactions, and discarded the neutron, was in volume %d\n", current_volume); ABSORB;} #ifdef Union_trace_verbal_setting - printf("----------- END OF WHILE LOOP --------------------------------------\n"); + printf ("----------- END OF WHILE LOOP --------------------------------------\n"); #endif - } // Could move all add_statistics and similar to this point, but need to filter for failed rays if (ray_sucseeded == 1) { - + // Ray sucseeded, need to check status of conditionals #ifdef Union_trace_verbal_setting - printf("----------- logger loop --------------------------------------\n"); + printf ("----------- logger loop --------------------------------------\n"); #endif // Loggers attatched to specific volumes need to be handled with care to avoid looping over all loggers for every ray if (enable_conditionals == 1) { - for (log_index=loggers_with_data_array.used_elements-1; log_index>-1; log_index--) { + for (log_index = loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { // Check all conditionals attatched to the current logger this_logger = loggers_with_data_array.logger_pointers[log_index]; conditional_status = 1; - for (iterator=0;iteratorconditional_list.num_elements;iterator++) { + for (iterator = 0; iterator < loggers_with_data_array.logger_pointers[log_index]->conditional_list.num_elements; iterator++) { // Call this particular conditional. If it fails, report the status and break #ifdef Union_trace_verbal_setting - printf("Checking conditional number %d for logger named %s \n",iterator,loggers_with_data_array.logger_pointers[log_index]->name); + printf ("Checking conditional number %d for logger named %s \n", iterator, loggers_with_data_array.logger_pointers[log_index]->name); #endif - if (0 == this_logger->conditional_list.conditional_functions[iterator]( - this_logger->conditional_list.p_data_unions[iterator], - &ray_position, &ray_velocity, &p, &t, ¤t_volume, - &number_of_scattering_events, scattered_flag,scattered_flag_VP)) { + if (0 + == this_logger->conditional_list.conditional_functions[iterator](this_logger->conditional_list.p_data_unions[iterator], &ray_position, + &ray_velocity, &p, &t, ¤t_volume, &number_of_scattering_events, + scattered_flag, scattered_flag_VP)) { conditional_status = 0; break; } } if (conditional_status == 1) { - // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the temp_to_perm function needs to be called - // The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger - + // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the + // temp_to_perm function needs to be called The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger + if (loggers_with_data_array.logger_pointers[log_index]->function_pointers.select_t_to_p == 1) { - loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm(&loggers_with_data_array.logger_pointers[log_index]->data_union); - } - else if (loggers_with_data_array.logger_pointers[log_index]->function_pointers.select_t_to_p == 2) { - loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm_final_p(&loggers_with_data_array.logger_pointers[log_index]->data_union,p); + loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm (&loggers_with_data_array.logger_pointers[log_index]->data_union); + } else if (loggers_with_data_array.logger_pointers[log_index]->function_pointers.select_t_to_p == 2) { + loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm_final_p ( + &loggers_with_data_array.logger_pointers[log_index]->data_union, p); } - - // The user can set a condtional_extend_index, so that the evaluation of this specific conditional can be taken easily from extend + + // The user can set a condtional_extend_index, so that the evaluation of this specific conditional can be taken easily from extend if (loggers_with_data_array.logger_pointers[log_index]->logger_extend_index != -1) { #ifdef Union_trace_verbal_setting - printf("Updating logger_conditional_extend_array[%d] to 1 (max length = %d)\n", loggers_with_data_array.logger_pointers[log_index]->logger_extend_index, max_conditional_extend_index); + printf ("Updating logger_conditional_extend_array[%d] to 1 (max length = %d)\n", + loggers_with_data_array.logger_pointers[log_index]->logger_extend_index, max_conditional_extend_index); #endif logger_conditional_extend_array[loggers_with_data_array.logger_pointers[log_index]->logger_extend_index] = 1; // Can be reached from EXTEND - // Are all reset to 0 for each new ray + // Are all reset to 0 for each new ray #ifdef Union_trace_verbal_setting - printf("Updated extend index sucessfully\n"); + printf ("Updated extend index sucessfully\n"); #endif } - + // Need to remove the current element from logger_with_data as it has been cleared and written to disk // The remaining elements is passed on to the next Union_master as it may fulfill the conditional after that master - if (global_master_list_master->elements[global_master_list_master->num_elements-1].component_index != INDEX_CURRENT_COMP) { + if (global_master_list_master->elements[global_master_list_master->num_elements - 1].component_index != INDEX_CURRENT_COMP) { // Move current logger pointer in logger_with_data to end position - loggers_with_data_array.logger_pointers[log_index] = loggers_with_data_array.logger_pointers[loggers_with_data_array.used_elements-1]; + loggers_with_data_array.logger_pointers[log_index] = loggers_with_data_array.logger_pointers[loggers_with_data_array.used_elements - 1]; // Decrease logger_with_data.used_elements with 1 loggers_with_data_array.used_elements--; } } } - + // Perform the same loop with abs_loggers and their conditionals - for (log_index=abs_loggers_with_data_array.used_elements-1; log_index>-1; log_index--) { + for (log_index = abs_loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { // Check all conditionals attatched to the current logger this_abs_logger = abs_loggers_with_data_array.abs_logger_pointers[log_index]; conditional_status = 1; - for (iterator=0;iteratorconditional_list.num_elements;iterator++) { + for (iterator = 0; iterator < abs_loggers_with_data_array.abs_logger_pointers[log_index]->conditional_list.num_elements; iterator++) { // Call this particular conditional. If it fails, report the status and break #ifdef Union_trace_verbal_setting - printf("Checking conditional number %d for abs logger named %s \n",iterator, abs_loggers_with_data_array.abs_logger_pointers[log_index]->name); + printf ("Checking conditional number %d for abs logger named %s \n", iterator, abs_loggers_with_data_array.abs_logger_pointers[log_index]->name); #endif - if (0 == this_abs_logger->conditional_list.conditional_functions[iterator]( - this_abs_logger->conditional_list.p_data_unions[iterator], - &ray_position, &ray_velocity, &p, &t, ¤t_volume, - &number_of_scattering_events, scattered_flag, scattered_flag_VP)) { + if (0 + == this_abs_logger->conditional_list.conditional_functions[iterator](this_abs_logger->conditional_list.p_data_unions[iterator], &ray_position, + &ray_velocity, &p, &t, ¤t_volume, &number_of_scattering_events, + scattered_flag, scattered_flag_VP)) { conditional_status = 0; break; } } if (conditional_status == 1) { - // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the temp_to_perm function needs to be called - // The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger - abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.temp_to_perm(&abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); - + // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the + // temp_to_perm function needs to be called The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger + abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.temp_to_perm ( + &abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); + // The user can set a condtional_extend_index, so that the evaluation of this specific conditional can be taken easily from extend if (abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index != -1) { #ifdef Union_trace_verbal_setting - printf("Updating logger_conditional_extend_array[%d] to 1 (max length = %d)\n",abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index,max_conditional_extend_index); + printf ("Updating logger_conditional_extend_array[%d] to 1 (max length = %d)\n", + abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index, max_conditional_extend_index); #endif - abs_logger_conditional_extend_array[abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index] = 1; // Can be reached from EXTEND - // Are all reset to 0 for each new ray - #ifdef Union_trace_verbal_setting - printf("Updated extend index sucessfully\n"); + abs_logger_conditional_extend_array[abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index] + = 1; // Can be reached from EXTEND + // Are all reset to 0 for each new ray + #ifdef Union_trace_verbal_setting + printf ("Updated extend index sucessfully\n"); #endif } - + // Need to remove the current element from logger_with_data as it has been cleared and written to disk // The remaining elements is passed on to the next Union_master as it may fulfill the conditional after that master - if (global_master_list_master->elements[global_master_list_master->num_elements-1].component_index != INDEX_CURRENT_COMP) { + if (global_master_list_master->elements[global_master_list_master->num_elements - 1].component_index != INDEX_CURRENT_COMP) { // Move current logger pointer in logger_with_data to end position - abs_loggers_with_data_array.abs_logger_pointers[log_index] = abs_loggers_with_data_array.abs_logger_pointers[abs_loggers_with_data_array.used_elements-1]; + abs_loggers_with_data_array.abs_logger_pointers[log_index] + = abs_loggers_with_data_array.abs_logger_pointers[abs_loggers_with_data_array.used_elements - 1]; // Decrease logger_with_data.used_elements with 1 abs_loggers_with_data_array.used_elements--; } - } } } - + if (enable_tagging && stop_tagging_ray == 0) { conditional_status = 1; - for (iterator=0; iteratornum_elements; iterator++) { + for (iterator = 0; iterator < tagging_conditional_list->num_elements; iterator++) { // Call this particular conditional. If it fails, report the status and break // Since a conditional can work for a logger and master_tagging at the same time, it may be evaluated twice #ifdef Union_trace_verbal_setting - printf("Checking tagging conditional number %d\n",iterator); + printf ("Checking tagging conditional number %d\n", iterator); #endif - if (0 == tagging_conditional_list->conditional_functions[iterator]( - tagging_conditional_list->p_data_unions[iterator], - &ray_position, &ray_velocity, &p, &t, ¤t_volume, - &number_of_scattering_events, scattered_flag,scattered_flag_VP)) { + if (0 + == tagging_conditional_list->conditional_functions[iterator](tagging_conditional_list->p_data_unions[iterator], &ray_position, &ray_velocity, &p, &t, + ¤t_volume, &number_of_scattering_events, scattered_flag, scattered_flag_VP)) { conditional_status = 0; break; } @@ -2746,30 +2980,32 @@ TRACE if (conditional_status == 1) { tagging_conditional_extend = 1; #ifdef Union_trace_verbal_setting - printf("Before adding statistics to node: current_tagging_nodbe->intensity = %f\n",current_tagging_node->intensity); - printf("Before adding statistics to node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); + printf ("Before adding statistics to node: current_tagging_nodbe->intensity = %f\n", current_tagging_node->intensity); + printf ("Before adding statistics to node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); #endif - - add_statistics_to_node(current_tagging_node,&ray_position, &ray_velocity, &p, &tagging_leaf_counter); - + + add_statistics_to_node (current_tagging_node, &ray_position, &ray_velocity, &p, &tagging_leaf_counter); + #ifdef Union_trace_verbal_setting - printf("After adding statistics to node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - printf("After adding statistics to node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); + printf ("After adding statistics to node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + printf ("After adding statistics to node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); #endif } } - + // Move the rays a nano meter away from the surface it left, in case activation counter > 1, this will prevent the ray from starting on a volume boundery - x += vx*1E-9; y += vy*1E-9; z += vz*1E-9; t += 1E-9; - + x += vx * 1E-9; + y += vy * 1E-9; + z += vz * 1E-9; + t += 1E-9; + } else { ABSORB; // Absorb rays that didn't exit correctly for whatever reason // Could error log here } - + // Stores nubmer of scattering events in global master list so that another master with inherit_number_of_scattering_events can continue global_master_list_master->elements[this_global_master_index].stored_number_of_scattering_events = number_of_scattering_events; - %} @@ -2780,210 +3016,266 @@ SAVE FINALLY %{ -// write out histories from tagging system if enabled -if (enable_tagging) { - if (finally_verbal) printf("Writing tagging tree to disk \n"); - if (finally_verbal) printf("Number of leafs = %d \n",tagging_leaf_counter); + // write out histories from tagging system if enabled + if (enable_tagging) { + if (finally_verbal) + printf ("Writing tagging tree to disk \n"); + if (finally_verbal) + printf ("Number of leafs = %d \n", tagging_leaf_counter); // While writing the tagging tree to disk, all the leafs are deallocated - write_tagging_tree(&master_tagging_node_list, Volumes, tagging_leaf_counter, number_of_volumes); -} -if (master_tagging_node_list.num_elements > 0) free(master_tagging_node_list.elements); - - -if (finally_verbal) printf("Freeing variables which are always allocated \n"); -// free allocated arrays specific to this master union component -free(scattered_flag); -free(my_trace); -free(my_trace_fraction_control); -free(pre_allocated1); -free(pre_allocated2); -free(pre_allocated3); -free(number_of_processes_array); -free(Geometries); - -if (finally_verbal) printf("Freeing intersection_time_table \n"); -for (iterator = 1;iterator < intersection_time_table.num_volumes;iterator++){ - free(intersection_time_table.intersection_times[iterator]); - free(intersection_time_table.normal_vector_x[iterator]); - free(intersection_time_table.normal_vector_y[iterator]); - free(intersection_time_table.normal_vector_z[iterator]); - free(intersection_time_table.surface_index[iterator]); -} - -free(intersection_time_table.n_elements); -free(intersection_time_table.calculated); -free(intersection_time_table.intersection_times); -free(intersection_time_table.normal_vector_x); -free(intersection_time_table.normal_vector_y); -free(intersection_time_table.normal_vector_z); -free(intersection_time_table.surface_index); - -if (free_tagging_conditioanl_list == 1) free(tagging_conditional_list); - -if (finally_verbal) printf("Freeing lists for individual volumes \n"); -for (volume_index=0;volume_indexgeometry.intersect_check_list.num_elements > 0) free(Volumes[volume_index]->geometry.intersect_check_list.elements); - if (Volumes[volume_index]->geometry.destinations_list.num_elements > 0) free(Volumes[volume_index]->geometry.destinations_list.elements); - if (Volumes[volume_index]->geometry.reduced_destinations_list.num_elements > 0) free(Volumes[volume_index]->geometry.reduced_destinations_list.elements); - if (Volumes[volume_index]->geometry.children.num_elements > 0) free(Volumes[volume_index]->geometry.children.elements); - if (Volumes[volume_index]->geometry.direct_children.num_elements > 0) free(Volumes[volume_index]->geometry.direct_children.elements); - if (Volumes[volume_index]->geometry.masked_by_list.num_elements > 0) free(Volumes[volume_index]->geometry.masked_by_list.elements); - if (Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements > 0) free(Volumes[volume_index]->geometry.masked_by_mask_index_list.elements); - if (Volumes[volume_index]->geometry.mask_list.num_elements > 0) free(Volumes[volume_index]->geometry.mask_list.elements); - if (Volumes[volume_index]->geometry.mask_intersect_list.num_elements > 0) free(Volumes[volume_index]->geometry.mask_intersect_list.elements); - if (Volumes[volume_index]->geometry.next_volume_list.num_elements > 0) free(Volumes[volume_index]->geometry.next_volume_list.elements); - - if (finally_verbal) printf(" Freeing physics\n"); - if (volume_index > 0) { // Volume 0 does not have physical properties allocated - free(scattered_flag_VP[volume_index]); - if (Volumes[volume_index]->geometry.process_rot_allocated == 1) { - free(Volumes[volume_index]->geometry.process_rot_matrix_array); - free(Volumes[volume_index]->geometry.transpose_process_rot_matrix_array); - Volumes[volume_index]->geometry.process_rot_allocated = 0; + write_tagging_tree (&master_tagging_node_list, Volumes, tagging_leaf_counter, number_of_volumes); + } + if (master_tagging_node_list.num_elements > 0) + free (master_tagging_node_list.elements); + + if (finally_verbal) + printf ("Freeing variables which are always allocated \n"); + // free allocated arrays specific to this master union component + free (scattered_flag); + free (my_trace); + free (my_trace_fraction_control); + free (pre_allocated1); + free (pre_allocated2); + free (pre_allocated3); + free (number_of_processes_array); + free (Geometries); + + if (finally_verbal) + printf ("Freeing intersection_time_table \n"); + for (iterator = 1; iterator < intersection_time_table.num_volumes; iterator++) { + free (intersection_time_table.intersection_times[iterator]); + free (intersection_time_table.normal_vector_x[iterator]); + free (intersection_time_table.normal_vector_y[iterator]); + free (intersection_time_table.normal_vector_z[iterator]); + free (intersection_time_table.surface_index[iterator]); + } + + free (intersection_time_table.n_elements); + free (intersection_time_table.calculated); + free (intersection_time_table.intersection_times); + free (intersection_time_table.normal_vector_x); + free (intersection_time_table.normal_vector_y); + free (intersection_time_table.normal_vector_z); + free (intersection_time_table.surface_index); + + if (free_tagging_conditioanl_list == 1) + free (tagging_conditional_list); + + if (finally_verbal) + printf ("Freeing lists for individual volumes \n"); + for (volume_index = 0; volume_index < number_of_volumes; volume_index++) { + + if (finally_verbal) + printf (" Freeing geometry\n"); + if (Volumes[volume_index]->geometry.intersect_check_list.num_elements > 0) + free (Volumes[volume_index]->geometry.intersect_check_list.elements); + if (Volumes[volume_index]->geometry.destinations_list.num_elements > 0) + free (Volumes[volume_index]->geometry.destinations_list.elements); + if (Volumes[volume_index]->geometry.reduced_destinations_list.num_elements > 0) + free (Volumes[volume_index]->geometry.reduced_destinations_list.elements); + if (Volumes[volume_index]->geometry.children.num_elements > 0) + free (Volumes[volume_index]->geometry.children.elements); + if (Volumes[volume_index]->geometry.direct_children.num_elements > 0) + free (Volumes[volume_index]->geometry.direct_children.elements); + if (Volumes[volume_index]->geometry.masked_by_list.num_elements > 0) + free (Volumes[volume_index]->geometry.masked_by_list.elements); + if (Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements > 0) + free (Volumes[volume_index]->geometry.masked_by_mask_index_list.elements); + if (Volumes[volume_index]->geometry.mask_list.num_elements > 0) + free (Volumes[volume_index]->geometry.mask_list.elements); + if (Volumes[volume_index]->geometry.mask_intersect_list.num_elements > 0) + free (Volumes[volume_index]->geometry.mask_intersect_list.elements); + if (Volumes[volume_index]->geometry.next_volume_list.num_elements > 0) + free (Volumes[volume_index]->geometry.next_volume_list.elements); + + if (finally_verbal) + printf (" Freeing physics\n"); + if (volume_index > 0) { // Volume 0 does not have physical properties allocated + free (scattered_flag_VP[volume_index]); + if (Volumes[volume_index]->geometry.process_rot_allocated == 1) { + free (Volumes[volume_index]->geometry.process_rot_matrix_array); + free (Volumes[volume_index]->geometry.transpose_process_rot_matrix_array); + Volumes[volume_index]->geometry.process_rot_allocated = 0; + } + if (on_int_list (Volume_copies_allocated, volume_index)) { + // This is a local copy of a volume, deallocate that local copy (all the allocated memory attachted to it was just deallocated, so this should not leave + // any leaks) + free (Volumes[volume_index]); + } else { + // Only free p_physics for vacuum volumes for the original at the end (there is a p_physics allocated for each vacuum volume) + if (Volumes[volume_index]->p_physics->is_vacuum == 1) + free (Volumes[volume_index]->p_physics); + } } - if (on_int_list(Volume_copies_allocated,volume_index)) { - // This is a local copy of a volume, deallocate that local copy (all the allocated memory attachted to it was just deallocated, so this should not leave any leaks) - free(Volumes[volume_index]); - } else { - // Only free p_physics for vacuum volumes for the original at the end (there is a p_physics allocated for each vacuum volume) - if (Volumes[volume_index]->p_physics->is_vacuum == 1 ) free(Volumes[volume_index]->p_physics); + + if (finally_verbal) + printf (" Freeing loggers\n"); + if (Volumes[volume_index]->loggers.num_elements > 0) { + for (iterator = 0; iterator < Volumes[volume_index]->loggers.num_elements; iterator++) { + free (Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process); + } + free (Volumes[volume_index]->loggers.p_logger_volume); } - } - - if (finally_verbal) printf(" Freeing loggers\n"); - if (Volumes[volume_index]->loggers.num_elements >0) { - for (iterator=0;iteratorloggers.num_elements;iterator++) { - free(Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process); + + if (finally_verbal) + printf (" Freeing abs_loggers\n"); + if (Volumes[volume_index]->abs_loggers.num_elements > 0) { + free (Volumes[volume_index]->abs_loggers.p_abs_logger); } - free(Volumes[volume_index]->loggers.p_logger_volume); - } - - if (finally_verbal) printf(" Freeing abs_loggers\n"); - if (Volumes[volume_index]->abs_loggers.num_elements > 0) { - free(Volumes[volume_index]->abs_loggers.p_abs_logger); + if (finally_verbal) + printf (" Freeing Volumes[index]\n"); + // free(Volumes[volume_index]); // Not able to free + // if (finally_verbal) printf(" Managed to free Volumes[index]\n"); } - if (finally_verbal) printf(" Freeing Volumes[index]\n"); - //free(Volumes[volume_index]); // Not able to free - //if (finally_verbal) printf(" Managed to free Volumes[index]\n"); -} -free(scattered_flag_VP); + free (scattered_flag_VP); -if (finally_verbal) printf("Freeing starting lists \n"); -if (starting_lists.allowed_starting_volume_logic_list.num_elements > 0) free(starting_lists.allowed_starting_volume_logic_list.elements); -if (starting_lists.reduced_start_list.num_elements > 0) free(starting_lists.reduced_start_list.elements); -if (starting_lists.start_logic_list.num_elements > 0) free(starting_lists.start_logic_list.elements); + if (finally_verbal) + printf ("Freeing starting lists \n"); + if (starting_lists.allowed_starting_volume_logic_list.num_elements > 0) + free (starting_lists.allowed_starting_volume_logic_list.elements); + if (starting_lists.reduced_start_list.num_elements > 0) + free (starting_lists.reduced_start_list.elements); + if (starting_lists.start_logic_list.num_elements > 0) + free (starting_lists.start_logic_list.elements); -if (finally_verbal) printf("Freeing mask lists \n"); -if (mask_status_list.num_elements>0) free(mask_status_list.elements); -if (current_mask_intersect_list_status.num_elements>0) free(current_mask_intersect_list_status.elements); -if (mask_volume_index_list.num_elements>0) free(mask_volume_index_list.elements); + if (finally_verbal) + printf ("Freeing mask lists \n"); + if (mask_status_list.num_elements > 0) + free (mask_status_list.elements); + if (current_mask_intersect_list_status.num_elements > 0) + free (current_mask_intersect_list_status.elements); + if (mask_volume_index_list.num_elements > 0) + free (mask_volume_index_list.elements); -if (finally_verbal) printf("Freeing component index list \n"); -if (geometry_component_index_list.num_elements>0) free(geometry_component_index_list.elements); + if (finally_verbal) + printf ("Freeing component index list \n"); + if (geometry_component_index_list.num_elements > 0) + free (geometry_component_index_list.elements); + if (finally_verbal) + printf ("Freeing Volumes \n"); + free (Volumes); -if (finally_verbal) printf("Freeing Volumes \n"); -free(Volumes); + if (interface_stack.number_of_surfaces > 0) + free (interface_stack.p_surface_array); -if (interface_stack.number_of_surfaces > 0) free(interface_stack.p_surface_array); + // Free global allocated arrays if this is the last master union component in the instrument file -// Free global allocated arrays if this is the last master union component in the instrument file + if (global_master_list_master->elements[global_master_list_master->num_elements - 1].component_index == INDEX_CURRENT_COMP) { + if (finally_verbal) + printf ("Freeing global arrays because this is the last Union master component\n"); -if (global_master_list_master->elements[global_master_list_master->num_elements-1].component_index == INDEX_CURRENT_COMP) { - if (finally_verbal) printf("Freeing global arrays because this is the last Union master component\n"); - // Freeing lists allocated in Union_initialization - - if (finally_verbal) printf("Freeing global process list \n"); - if (global_process_list_master->num_elements > 0) free(global_process_list_master->elements); - - if (finally_verbal) printf("Freeing global material list \n"); - if (global_material_list_master->num_elements > 0) free(global_material_list_master->elements); - - if (finally_verbal) printf("Freeing global surface list \n"); - if (global_surface_list_master->num_elements > 0) free(global_surface_list_master->elements); - - if (finally_verbal) printf("Freeing global geometry list \n"); - if (global_geometry_list_master->num_elements > 0) free(global_geometry_list_master->elements); - - if (finally_verbal) printf("Freeing global master list \n"); - if (global_master_list_master->num_elements > 0) free(global_master_list_master->elements); - - if (finally_verbal) printf("Freeing global logger lists \n"); - for (iterator=0;iteratornum_elements;iterator++) { + + if (finally_verbal) + printf ("Freeing global process list \n"); + if (global_process_list_master->num_elements > 0) + free (global_process_list_master->elements); + + if (finally_verbal) + printf ("Freeing global material list \n"); + if (global_material_list_master->num_elements > 0) + free (global_material_list_master->elements); + + if (finally_verbal) + printf ("Freeing global surface list \n"); + if (global_surface_list_master->num_elements > 0) + free (global_surface_list_master->elements); + + if (finally_verbal) + printf ("Freeing global geometry list \n"); + if (global_geometry_list_master->num_elements > 0) + free (global_geometry_list_master->elements); + + if (finally_verbal) + printf ("Freeing global master list \n"); + if (global_master_list_master->num_elements > 0) + free (global_master_list_master->elements); + + if (finally_verbal) + printf ("Freeing global logger lists \n"); + for (iterator = 0; iterator < global_all_volume_logger_list_master->num_elements; iterator++) { if (global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.num_elements > 0) { - free(global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); - free(global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); + free (global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); + free (global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); } } - if (global_all_volume_logger_list_master->num_elements > 0) free(global_all_volume_logger_list_master->elements); - - for (iterator=0;iteratornum_elements;iterator++) { + if (global_all_volume_logger_list_master->num_elements > 0) + free (global_all_volume_logger_list_master->elements); + + for (iterator = 0; iterator < global_specific_volumes_logger_list_master->num_elements; iterator++) { if (global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.num_elements > 0) { - free(global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); - free(global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); + free (global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); + free (global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); } } - if (global_specific_volumes_logger_list_master->num_elements > 0) free(global_specific_volumes_logger_list_master->elements); - - if (finally_verbal) printf("Freeing global abs logger lists \n"); - for (iterator=0;iteratornum_elements;iterator++) { + if (global_specific_volumes_logger_list_master->num_elements > 0) + free (global_specific_volumes_logger_list_master->elements); + + if (finally_verbal) + printf ("Freeing global abs logger lists \n"); + for (iterator = 0; iterator < global_all_volume_abs_logger_list_master->num_elements; iterator++) { if (global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.num_elements > 0) { - free(global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); - free(global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); + free (global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); + free (global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); } } - if (global_all_volume_abs_logger_list_master->num_elements > 0) free(global_all_volume_abs_logger_list_master->elements); - - for (iterator=0;iteratornum_elements;iterator++) { + if (global_all_volume_abs_logger_list_master->num_elements > 0) + free (global_all_volume_abs_logger_list_master->elements); + + for (iterator = 0; iterator < global_specific_volumes_abs_logger_list_master->num_elements; iterator++) { if (global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.num_elements > 0) { - free(global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); - free(global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); + free (global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); + free (global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); } } - if (global_specific_volumes_abs_logger_list_master->num_elements > 0) free(global_specific_volumes_abs_logger_list_master->elements); + if (global_specific_volumes_abs_logger_list_master->num_elements > 0) + free (global_specific_volumes_abs_logger_list_master->elements); - if (finally_verbal) printf("Freeing global tagging conditional lists \n"); - for (iterator=0;iteratornum_elements;iterator++) { + if (finally_verbal) + printf ("Freeing global tagging conditional lists \n"); + for (iterator = 0; iterator < global_tagging_conditional_list_master->num_elements; iterator++) { if (global_tagging_conditional_list_master->elements[iterator].conditional_list.num_elements > 0) { - free(global_tagging_conditional_list_master->elements[iterator].conditional_list.conditional_functions); - free(global_tagging_conditional_list_master->elements[iterator].conditional_list.p_data_unions); + free (global_tagging_conditional_list_master->elements[iterator].conditional_list.conditional_functions); + free (global_tagging_conditional_list_master->elements[iterator].conditional_list.p_data_unions); } } - if (global_tagging_conditional_list_master->num_elements>0) free(global_tagging_conditional_list_master->elements); -} - + if (global_tagging_conditional_list_master->num_elements > 0) + free (global_tagging_conditional_list_master->elements); + } %} MCDISPLAY %{ - // mcdisplay is handled in the component files for each geometry and called here. The line function is only available in this section, and not through functions, + // mcdisplay is handled in the component files for each geometry and called here. The line function is only available in this section, and not through + // functions, // so all the lines to be drawn for each volume are collected in a structure that is then drawn here. - magnify("xyz"); + magnify ("xyz"); struct lines_to_draw lines_to_draw_master; - for (volume_index=1; volume_indexgeometry.visualization_on == 1) { - lines_to_draw_master.number_of_lines = 0; - - Volumes[volume_index]->geometry.mcdisplay_function(&lines_to_draw_master,volume_index,Geometries,number_of_volumes); - - for (iterator = 0;iterator0) free(lines_to_draw_master.lines); - } - } + for (volume_index = 1; volume_index < number_of_volumes; volume_index++) { + if (Volumes[volume_index]->geometry.visualization_on == 1) { + lines_to_draw_master.number_of_lines = 0; + + Volumes[volume_index]->geometry.mcdisplay_function (&lines_to_draw_master, volume_index, Geometries, number_of_volumes); + + for (iterator = 0; iterator < lines_to_draw_master.number_of_lines; iterator++) { + if (lines_to_draw_master.lines[iterator].number_of_dashes == 1) { + line (lines_to_draw_master.lines[iterator].point1.x, lines_to_draw_master.lines[iterator].point1.y, lines_to_draw_master.lines[iterator].point1.z, + lines_to_draw_master.lines[iterator].point2.x, lines_to_draw_master.lines[iterator].point2.y, lines_to_draw_master.lines[iterator].point2.z); + } else { + dashed_line (lines_to_draw_master.lines[iterator].point1.x, lines_to_draw_master.lines[iterator].point1.y, + lines_to_draw_master.lines[iterator].point1.z, lines_to_draw_master.lines[iterator].point2.x, + lines_to_draw_master.lines[iterator].point2.y, lines_to_draw_master.lines[iterator].point2.z, + lines_to_draw_master.lines[iterator].number_of_dashes); + } + } + if (lines_to_draw_master.number_of_lines > 0) + free (lines_to_draw_master.lines); + } + } %} END diff --git a/mcstas-comps/union/Union_master_GPU.comp b/mcstas-comps/union/Union_master_GPU.comp index c73abd3b26..d27135d9c1 100755 --- a/mcstas-comps/union/Union_master_GPU.comp +++ b/mcstas-comps/union/Union_master_GPU.comp @@ -67,66 +67,65 @@ SETTING PARAMETERS(verbal = 1, SHARE %{ -#ifndef Union -#error "The Union_init component must be included before this Union_master_GPU component" -#endif - -// TEST -struct logger_with_data_struct loggers_with_data_array; -struct abs_logger_with_data_struct abs_loggers_with_data_array; + #ifndef Union + #error "The Union_init component must be included before this Union_master_GPU component" + #endif -#ifndef MASTER_DETECTOR - #define MASTER_DETECTOR dummy -#endif + // TEST + struct logger_with_data_struct loggers_with_data_array; + struct abs_logger_with_data_struct abs_loggers_with_data_array; + #ifndef MASTER_DETECTOR + #define MASTER_DETECTOR dummy + #endif %} DECLARE %{ // Declare global lists, will be retrieved in INITIALIZE - struct global_positions_to_transform_list_struct *global_positions_to_transform_list_master; - struct global_rotations_to_transform_list_struct *global_rotations_to_transform_list_master; - struct pointer_to_global_process_list *global_process_list_master; - struct pointer_to_global_material_list *global_material_list_master; - struct pointer_to_global_geometry_list *global_geometry_list_master; - struct pointer_to_global_logger_list *global_all_volume_logger_list_master; - struct pointer_to_global_logger_list *global_specific_volumes_logger_list_master; - struct pointer_to_global_abs_logger_list *global_all_volume_abs_logger_list_master; - struct pointer_to_global_abs_logger_list *global_specific_volumes_abs_logger_list_master; - struct global_tagging_conditional_list_struct *global_tagging_conditional_list_master; - struct pointer_to_global_master_list *global_master_list_master; + struct global_positions_to_transform_list_struct* global_positions_to_transform_list_master; + struct global_rotations_to_transform_list_struct* global_rotations_to_transform_list_master; + struct pointer_to_global_process_list* global_process_list_master; + struct pointer_to_global_material_list* global_material_list_master; + struct pointer_to_global_geometry_list* global_geometry_list_master; + struct pointer_to_global_logger_list* global_all_volume_logger_list_master; + struct pointer_to_global_logger_list* global_specific_volumes_logger_list_master; + struct pointer_to_global_abs_logger_list* global_all_volume_abs_logger_list_master; + struct pointer_to_global_abs_logger_list* global_specific_volumes_abs_logger_list_master; + struct global_tagging_conditional_list_struct* global_tagging_conditional_list_master; + struct pointer_to_global_master_list* global_master_list_master; // New precompiler settings for verbal / tagging, remove // to include verbal in trace and/or tagging - //#define Union_trace_verbal_setting - //#define Union_enable_tagging_setting + // #define Union_trace_verbal_setting + // #define Union_enable_tagging_setting - //int starting_volume_warning; + // int starting_volume_warning; // Declare the global variables (not to be in output parameters) struct global_master_element_struct global_master_element; int this_global_master_index; - + // variables used for assigning global information to local variables int previous_master_index; int geometry_list_index; // The main structures used in this component - struct intersection_time_table_struct *intersection_time_table; - struct Volume_struct **Volumes; - struct geometry_struct **Geometries; - struct Volume_struct **Volume_copies; + struct intersection_time_table_struct* intersection_time_table; + struct Volume_struct** Volumes; + struct geometry_struct** Geometries; + struct Volume_struct** Volume_copies; struct starting_lists_struct starting_lists; - + // garbage collection for volume_copies struct pointer_to_1d_int_list Volume_copies_allocated; // Error handling - //int error_msg; - //int component_error_msg; - + // int error_msg; + // int component_error_msg; + // For verbal output char string_output[128]; - + // Variables for ray-tracing algorithm int number_of_volumes; int volume_index; @@ -134,25 +133,25 @@ DECLARE int iterator; int solutions; int max_number_of_processes; - //int limit; + // int limit; int number_of_solutions_static; - struct scattering_process_struct *process; - struct scattering_process_struct *process_start; - double *my_trace; - double *p_my_trace; - double *my_trace_fraction_control; - + struct scattering_process_struct* process; + struct scattering_process_struct* process_start; + double* my_trace; + double* p_my_trace; + double* my_trace_fraction_control; + int a_next_volume_found; int next_volume; double next_volume_priority; - + // int done; // int current_volume; int intersection_with_children; - - int *scattered_flag; - int **scattered_flag_VP; - + + int* scattered_flag; + int** scattered_flag_VP; + // For coordinate transformations Rotation master_transposed_rotation_matrix; Rotation temp_rotation_matrix; @@ -160,28 +159,28 @@ DECLARE Coords non_rotated_position; Coords rotated_position; int non_isotropic_found; - + // For tagging struct list_of_tagging_tree_node_pointers master_tagging_node_list; - struct tagging_tree_node_struct *current_tagging_node; - + struct tagging_tree_node_struct* current_tagging_node; + int tagging_leaf_counter; int stop_tagging_ray; int stop_creating_nodes; int number_of_scattering_events; - + // For geometry p interact double real_transmission_probability; double mc_transmission_probability; - + // Process p interact int number_of_process_interacts_set; int index_of_lacking_process; double total_process_interact; - + // Volume nr -> component index struct pointer_to_1d_int_list geometry_component_index_list; - + // Masks struct pointer_to_1d_int_list mask_volume_index_list; int number_of_masks; @@ -190,198 +189,221 @@ DECLARE struct pointer_to_1d_int_list current_mask_intersect_list_status; int mask_index_main; int mask_iterator; - int *mask_start; - int *mask_check; + int* mask_start; + int* mask_check; int need_to_run_within_which_volume; - + // Loggers - //struct logger_with_data_struct loggers_with_data_array; - int *number_of_processes_array; + // struct logger_with_data_struct loggers_with_data_array; + int* number_of_processes_array; double p_old; int log_index; int conditional_status; - struct logger_struct *this_logger; - struct abs_logger_struct *this_abs_logger; + struct logger_struct* this_logger; + struct abs_logger_struct* this_abs_logger; // union detector_pointer_union detector_pointer; - + // Conditionals - struct conditional_list_struct *tagging_conditional_list; - int *logger_conditional_extend_array; - int *abs_logger_conditional_extend_array; + struct conditional_list_struct* tagging_conditional_list; + int* logger_conditional_extend_array; + int* abs_logger_conditional_extend_array; int max_conditional_extend_index; - //int tagging_conditional_extend; + // int tagging_conditional_extend; int free_tagging_conditioanl_list; - + // Reliability control // Safty distance is needed to avoid having ray positions closer to a wall than the precision of intersection functions double safty_distance; double safty_distance2; - + // Focusing struct focus_data_struct temporary_focus_data; int focus_data_index; - %} INITIALIZE %{ -if (_getcomp_index(init) < 0) { -fprintf(stderr,"Union_master_GPU:%s: Error identifying Union_init component, %s is not a known component name.\n", -NAME_CURRENT_COMP, init); -exit(-1); -} + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_master_GPU:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } // Unpack global lists - global_positions_to_transform_list_master = COMP_GETPAR3(Union_init, init, global_positions_to_transform_list); - global_rotations_to_transform_list_master = COMP_GETPAR3(Union_init, init, global_rotations_to_transform_list); - global_process_list_master = COMP_GETPAR3(Union_init, init, global_process_list); - global_material_list_master = COMP_GETPAR3(Union_init, init, global_material_list); - global_geometry_list_master = COMP_GETPAR3(Union_init, init, global_geometry_list); - global_all_volume_logger_list_master = COMP_GETPAR3(Union_init, init, global_all_volume_logger_list); - global_specific_volumes_logger_list_master = COMP_GETPAR3(Union_init, init, global_specific_volumes_logger_list); - global_all_volume_abs_logger_list_master = COMP_GETPAR3(Union_init, init, global_all_volume_abs_logger_list); - global_specific_volumes_abs_logger_list_master = COMP_GETPAR3(Union_init, init, global_specific_volumes_abs_logger_list); - global_tagging_conditional_list_master = COMP_GETPAR3(Union_init, init, global_tagging_conditional_list); - global_master_list_master = COMP_GETPAR3(Union_init, init, global_master_list); - + global_positions_to_transform_list_master = COMP_GETPAR3 (Union_init, init, global_positions_to_transform_list); + global_rotations_to_transform_list_master = COMP_GETPAR3 (Union_init, init, global_rotations_to_transform_list); + global_process_list_master = COMP_GETPAR3 (Union_init, init, global_process_list); + global_material_list_master = COMP_GETPAR3 (Union_init, init, global_material_list); + global_geometry_list_master = COMP_GETPAR3 (Union_init, init, global_geometry_list); + global_all_volume_logger_list_master = COMP_GETPAR3 (Union_init, init, global_all_volume_logger_list); + global_specific_volumes_logger_list_master = COMP_GETPAR3 (Union_init, init, global_specific_volumes_logger_list); + global_all_volume_abs_logger_list_master = COMP_GETPAR3 (Union_init, init, global_all_volume_abs_logger_list); + global_specific_volumes_abs_logger_list_master = COMP_GETPAR3 (Union_init, init, global_specific_volumes_abs_logger_list); + global_tagging_conditional_list_master = COMP_GETPAR3 (Union_init, init, global_tagging_conditional_list); + global_master_list_master = COMP_GETPAR3 (Union_init, init, global_master_list); // It is possible to surpress warnings on starting volume by setting this to 1 - //starting_volume_warning = 0; - + // starting_volume_warning = 0; + // Start at 0 error messages, quit after 100. - //component_error_msg = 0; - + // component_error_msg = 0; + // For tagging - tagging_leaf_counter=0; - + tagging_leaf_counter = 0; + // For masks number_of_masks = 0; number_of_masked_volumes = 0; // Use sanitation #ifndef ANY_GEOMETRY_DETECTOR_DECLARE - printf("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); - exit(1); + printf ("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); + exit (1); #endif #ifdef ANY_GEOMETRY_DETECTOR_DECLARE - if (global_geometry_list_master->num_elements == 0) { - printf("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); - printf(" Union_master component named \"%s\" is before any Volumes in the instrument file. At least one Volume need to be defined before\n",NAME_CURRENT_COMP); - - exit(1); - } + if (global_geometry_list_master->num_elements == 0) { + printf ("\nERROR: Need to define at least one Volume using Union_cylinder or Union_box before using the Union_master component. \n"); + printf (" Union_master component named \"%s\" is before any Volumes in the instrument file. At least one Volume need to be defined before\n", + NAME_CURRENT_COMP); + + exit (1); + } #endif - + // Parameters describing the safety distances close to surfaces, as scattering should not occur closer to a surface than the // accuracy of the intersection calculation. safty_distance = 1E-11; - safty_distance2 = safty_distance*2; - + safty_distance2 = safty_distance * 2; + // Write information to the global_master_list_master about the current Union_master - sprintf(global_master_element.name,"%s",NAME_CURRENT_COMP); + sprintf (global_master_element.name, "%s", NAME_CURRENT_COMP); global_master_element.component_index = INDEX_CURRENT_COMP; - add_element_to_master_list(global_master_list_master, global_master_element); + add_element_to_master_list (global_master_list_master, global_master_element); if (inherit_number_of_scattering_events == 1 && global_master_list_master->num_elements == 1) { - printf("ERROR in Union_master with name %s. Inherit_number_of_scattering_events set to 1 for first Union_master component, but there is no preceeding Union_master component. Aborting.\n",NAME_CURRENT_COMP); - exit(1); + printf ("ERROR in Union_master with name %s. Inherit_number_of_scattering_events set to 1 for first Union_master component, but there is no preceeding " + "Union_master component. Aborting.\n", + NAME_CURRENT_COMP); + exit (1); } this_global_master_index = global_master_list_master->num_elements - 1; // Save the index for this master in global master list - + // Set the component index of the previous Union_master component if one exists - if (global_master_list_master->num_elements == 1) previous_master_index = 0; // no previous index - else previous_master_index = global_master_list_master->elements[global_master_list_master->num_elements-2].component_index; // -2 because of zero indexing and needing the previous index. - //printf("Assigned previous_master_index = %d \n",previous_master_index); - + if (global_master_list_master->num_elements == 1) + previous_master_index = 0; // no previous index + else + previous_master_index = global_master_list_master->elements[global_master_list_master->num_elements - 2] + .component_index; // -2 because of zero indexing and needing the previous index. + // printf("Assigned previous_master_index = %d \n",previous_master_index); + // All volumes in the global_geometry_list_master is being check for activity using the number_of_activations input made for each geometry (default is 1) // In addition it is counted how many volumes, mask volumes and masked volumes are active in this Union_master. - number_of_volumes = 1; // Starting with 1 as the surrounding vacuum is considered a volume - number_of_masks = 0; // Starting with 0 mask volumes + number_of_volumes = 1; // Starting with 1 as the surrounding vacuum is considered a volume + number_of_masks = 0; // Starting with 0 mask volumes number_of_masked_volumes = 0; // Starting with 0 masked volumes - for (iterator=0;iteratornum_elements;iterator++) { - if (global_geometry_list_master->elements[iterator].component_index < INDEX_CURRENT_COMP && global_geometry_list_master->elements[iterator].activation_counter > 0) { - global_geometry_list_master->elements[iterator].active = 1; - global_geometry_list_master->elements[iterator].activation_counter--; - number_of_volumes++; - if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 1) number_of_masks++; - if (global_geometry_list_master->elements[iterator].Volume->geometry.is_masked_volume == 1) number_of_masked_volumes++; - } else global_geometry_list_master->elements[iterator].active = 0; + for (iterator = 0; iterator < global_geometry_list_master->num_elements; iterator++) { + if (global_geometry_list_master->elements[iterator].component_index < INDEX_CURRENT_COMP + && global_geometry_list_master->elements[iterator].activation_counter > 0) { + global_geometry_list_master->elements[iterator].active = 1; + global_geometry_list_master->elements[iterator].activation_counter--; + number_of_volumes++; + if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 1) + number_of_masks++; + if (global_geometry_list_master->elements[iterator].Volume->geometry.is_masked_volume == 1) + number_of_masked_volumes++; + } else + global_geometry_list_master->elements[iterator].active = 0; } - + // Allocation of global lists geometry_component_index_list.num_elements = number_of_volumes; - geometry_component_index_list.elements = malloc( geometry_component_index_list.num_elements * sizeof(int)); + geometry_component_index_list.elements = malloc (geometry_component_index_list.num_elements * sizeof (int)); mask_volume_index_list.num_elements = number_of_masks; - if (number_of_masks >0) mask_volume_index_list.elements = malloc( number_of_masks * sizeof(int)); + if (number_of_masks > 0) + mask_volume_index_list.elements = malloc (number_of_masks * sizeof (int)); mask_status_list.num_elements = number_of_masks; - if (number_of_masks >0) mask_status_list.elements = malloc( number_of_masks * sizeof(int)); + if (number_of_masks > 0) + mask_status_list.elements = malloc (number_of_masks * sizeof (int)); current_mask_intersect_list_status.num_elements = number_of_masked_volumes; - if (number_of_masked_volumes >0) current_mask_intersect_list_status.elements = malloc( number_of_masked_volumes * sizeof(int)); - + if (number_of_masked_volumes > 0) + current_mask_intersect_list_status.elements = malloc (number_of_masked_volumes * sizeof (int)); + // Make a list of component index from each volume index volume_index = 0; - for (iterator=0;iteratornum_elements;iterator++) { + for (iterator = 0; iterator < global_geometry_list_master->num_elements; iterator++) { if (global_geometry_list_master->elements[iterator].active == 1) - geometry_component_index_list.elements[++volume_index] = global_geometry_list_master->elements[iterator].component_index; - + geometry_component_index_list.elements[++volume_index] = global_geometry_list_master->elements[iterator].component_index; } geometry_component_index_list.elements[0] = 0; // Volume 0 is never set in the above code, but should never be used. - + // The input for this component is done through a series of input components // All information needed is stored in global lists, some of which is printed here for an overview to the user. - MPI_MASTER( // MPI_MASTER ensures just one thread output this information to the user - if (verbal == 1) { - printf("---------------------------------------------------------------------\n"); - printf("global_process_list_master->num_elements: %d\n",global_process_list_master->num_elements); - for (iterator=0;iteratornum_elements;iterator++) { - printf("name of process [%d]: %s \n",iterator,global_process_list_master->elements[iterator].name); - printf("component index [%d]: %d \n",iterator,global_process_list_master->elements[iterator].component_index); - } - - printf("---------------------------------------------------------------------\n"); - printf("global_material_list_master->num_elements: %d\n",global_material_list_master->num_elements); - for (iterator=0;iteratornum_elements;iterator++) { - printf("name of material [%d]: %s \n",iterator,global_material_list_master->elements[iterator].name); - printf("component index [%d]: %d \n",iterator,global_material_list_master->elements[iterator].component_index); - printf("my_absoprtion [%d]: %f \n",iterator,global_material_list_master->elements[iterator].physics->my_a); - printf("number of processes [%d]: %d \n",iterator,global_material_list_master->elements[iterator].physics->number_of_processes); - } + MPI_MASTER ( // MPI_MASTER ensures just one thread output this information to the user + if (verbal == 1) { + printf ("---------------------------------------------------------------------\n"); + printf ("global_process_list_master->num_elements: %d\n", global_process_list_master->num_elements); + for (iterator = 0; iterator < global_process_list_master->num_elements; iterator++) { + printf ("name of process [%d]: %s \n", iterator, global_process_list_master->elements[iterator].name); + printf ("component index [%d]: %d \n", iterator, global_process_list_master->elements[iterator].component_index); + } - printf("---------------------------------------------------------------------\n"); - printf("global_geometry_list_master->num_elements: %d\n",global_material_list_master->num_elements); - for (iterator=0;iteratornum_elements;iterator++) { - if (global_geometry_list_master->elements[iterator].active == 1) { - printf("\n"); - printf("name of geometry [%d]: %s \n",iterator,global_geometry_list_master->elements[iterator].name); - printf("component index [%d]: %d \n",iterator,global_geometry_list_master->elements[iterator].component_index); - printf("Volume.name [%d]: %s \n",iterator,global_geometry_list_master->elements[iterator].Volume->name); - if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 0) { - printf("Volume.p_physics.is_vacuum [%d]: %d \n",iterator,global_geometry_list_master->elements[iterator].Volume->p_physics->is_vacuum); - printf("Volume.p_physics.my_absorption [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->p_physics->my_a); - printf("Volume.p_physics.number of processes [%d]: %d \n",iterator,global_geometry_list_master->elements[iterator].Volume->p_physics->number_of_processes); - } - printf("Volume.geometry.shape [%d]: %s \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.shape); - printf("Volume.geometry.center.x [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.center.x); - printf("Volume.geometry.center.y [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.center.y); - printf("Volume.geometry.center.z [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.center.z); - printf("Volume.geometry.rotation_matrix[0] [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][0],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][1],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][2]); - printf("Volume.geometry.rotation_matrix[1] [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][0],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][1],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][2]); - printf("Volume.geometry.rotation_matrix[2] [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][0],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][1],global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][2]); - if (strcmp(global_geometry_list_master->elements[iterator].Volume->geometry.shape,"cylinder") == 0) { - printf("Volume.geometry.geometry_parameters.cyl_radius [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->cyl_radius); - printf("Volume.geometry.geometry_parameters.height [%d]: %f \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->height); + printf ("---------------------------------------------------------------------\n"); + printf ("global_material_list_master->num_elements: %d\n", global_material_list_master->num_elements); + for (iterator = 0; iterator < global_material_list_master->num_elements; iterator++) { + printf ("name of material [%d]: %s \n", iterator, global_material_list_master->elements[iterator].name); + printf ("component index [%d]: %d \n", iterator, global_material_list_master->elements[iterator].component_index); + printf ("my_absoprtion [%d]: %f \n", iterator, global_material_list_master->elements[iterator].physics->my_a); + printf ("number of processes [%d]: %d \n", iterator, global_material_list_master->elements[iterator].physics->number_of_processes); + } + + printf ("---------------------------------------------------------------------\n"); + printf ("global_geometry_list_master->num_elements: %d\n", global_material_list_master->num_elements); + for (iterator = 0; iterator < global_geometry_list_master->num_elements; iterator++) { + if (global_geometry_list_master->elements[iterator].active == 1) { + printf ("\n"); + printf ("name of geometry [%d]: %s \n", iterator, global_geometry_list_master->elements[iterator].name); + printf ("component index [%d]: %d \n", iterator, global_geometry_list_master->elements[iterator].component_index); + printf ("Volume.name [%d]: %s \n", iterator, global_geometry_list_master->elements[iterator].Volume->name); + if (global_geometry_list_master->elements[iterator].Volume->geometry.is_mask_volume == 0) { + printf ("Volume.p_physics.is_vacuum [%d]: %d \n", iterator, global_geometry_list_master->elements[iterator].Volume->p_physics->is_vacuum); + printf ("Volume.p_physics.my_absorption [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->p_physics->my_a); + printf ("Volume.p_physics.number of processes [%d]: %d \n", iterator, + global_geometry_list_master->elements[iterator].Volume->p_physics->number_of_processes); + } + printf ("Volume.geometry.shape [%d]: %s \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.shape); + printf ("Volume.geometry.center.x [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.center.x); + printf ("Volume.geometry.center.y [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.center.y); + printf ("Volume.geometry.center.z [%d]: %f \n", iterator, global_geometry_list_master->elements[iterator].Volume->geometry.center.z); + printf ("Volume.geometry.rotation_matrix[0] [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][0], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][1], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[0][2]); + printf ("Volume.geometry.rotation_matrix[1] [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][0], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][1], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[1][2]); + printf ("Volume.geometry.rotation_matrix[2] [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][0], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][1], + global_geometry_list_master->elements[iterator].Volume->geometry.rotation_matrix[2][2]); + if (strcmp (global_geometry_list_master->elements[iterator].Volume->geometry.shape, "cylinder") == 0) { + printf ("Volume.geometry.geometry_parameters.cyl_radius [%d]: %f \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->cyl_radius); + printf ("Volume.geometry.geometry_parameters.height [%d]: %f \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.geometry_parameters.p_cylinder_storage->height); + } + printf ("Volume.geometry.focus_data_array.elements[0].Aim [%d]: [%f %f %f] \n", iterator, + global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.x, + global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.y, + global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.z); } - printf("Volume.geometry.focus_data_array.elements[0].Aim [%d]: [%f %f %f] \n",iterator,global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.x,global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.y,global_geometry_list_master->elements[iterator].Volume->geometry.focus_data_array.elements[0].Aim.z); } + printf ("---------------------------------------------------------------------\n"); + printf ("number_of_volumes = %d\n", number_of_volumes); + printf ("number_of_masks = %d\n", number_of_masks); + printf ("number_of_masked_volumes = %d\n", number_of_masked_volumes); } - printf("---------------------------------------------------------------------\n"); - printf("number_of_volumes = %d\n",number_of_volumes); - printf("number_of_masks = %d\n",number_of_masks); - printf("number_of_masked_volumes = %d\n",number_of_masked_volumes); - } - + ); // End MPI_MASTER - - + // --- Initialization tasks independent of volume stucture ----------------------- // Store a pointer to the conditional list and update the current index in that structure @@ -390,121 +412,118 @@ exit(-1); tagging_conditional_list = &global_tagging_conditional_list_master->elements[global_tagging_conditional_list_master->current_index++].conditional_list; free_tagging_conditioanl_list = 0; } else { - tagging_conditional_list = malloc(sizeof(struct conditional_list_struct)); + tagging_conditional_list = malloc (sizeof (struct conditional_list_struct)); tagging_conditional_list->num_elements = 0; free_tagging_conditioanl_list = 1; } - + // Find the maximum logger extend index so that the correct memory allocation can be performed later // Here the loggers applied to all volumes are searched, later this result is compared to volume specific loggers and updated max_conditional_extend_index = -1; - for (iterator=0;iteratornum_elements;iterator++) { + for (iterator = 0; iterator < global_all_volume_logger_list_master->num_elements; iterator++) { if (global_all_volume_logger_list_master->elements[iterator].logger->logger_extend_index > max_conditional_extend_index) { max_conditional_extend_index = global_all_volume_logger_list_master->elements[iterator].logger->logger_extend_index; } } - + // The absolute rotation of this component is saved for use in initialization - rot_transpose(ROT_A_CURRENT_COMP,master_transposed_rotation_matrix); - + rot_transpose (ROT_A_CURRENT_COMP, master_transposed_rotation_matrix); + // Preceeding componnets can add coordinates and rotations to global_positions_to_transform and global_rotations_to_transform // in order to have these transformed into the coordinate system of the next master compoent in the instrument file. // Here these transformations are performed, and the lists are cleared so no transformed information is further altered by // next master components. - + // Position transformation - for (iterator=0;iteratornum_elements;iterator++) { - non_rotated_position = coords_sub(*(global_positions_to_transform_list_master->positions[iterator]),POS_A_CURRENT_COMP); - *(global_positions_to_transform_list_master->positions[iterator]) = rot_apply(ROT_A_CURRENT_COMP,non_rotated_position); + for (iterator = 0; iterator < global_positions_to_transform_list_master->num_elements; iterator++) { + non_rotated_position = coords_sub (*(global_positions_to_transform_list_master->positions[iterator]), POS_A_CURRENT_COMP); + *(global_positions_to_transform_list_master->positions[iterator]) = rot_apply (ROT_A_CURRENT_COMP, non_rotated_position); } if (global_positions_to_transform_list_master->num_elements > 0) { global_positions_to_transform_list_master->num_elements = 0; - free(global_positions_to_transform_list_master->positions); + free (global_positions_to_transform_list_master->positions); } // Rotation transformation - for (iterator=0;iteratornum_elements;iterator++) { - //print_rotation(*(global_rotations_to_transform_list_master->rotations[iterator]),"rotation matrix to be updated"); - rot_mul(master_transposed_rotation_matrix,*(global_rotations_to_transform_list_master->rotations[iterator]),temp_rotation_matrix); - rot_copy(*(global_rotations_to_transform_list_master->rotations[iterator]),temp_rotation_matrix); + for (iterator = 0; iterator < global_rotations_to_transform_list_master->num_elements; iterator++) { + // print_rotation(*(global_rotations_to_transform_list_master->rotations[iterator]),"rotation matrix to be updated"); + rot_mul (master_transposed_rotation_matrix, *(global_rotations_to_transform_list_master->rotations[iterator]), temp_rotation_matrix); + rot_copy (*(global_rotations_to_transform_list_master->rotations[iterator]), temp_rotation_matrix); } if (global_rotations_to_transform_list_master->num_elements > 0) { global_rotations_to_transform_list_master->num_elements = 0; - free(global_rotations_to_transform_list_master->rotations); + free (global_rotations_to_transform_list_master->rotations); } - // --- Definition of volumes and loading of appropriate data ----------------------- - + // The information stored in global lists is to be stored in one array of structures that is allocated here - Volumes = malloc(number_of_volumes * sizeof(struct Volume_struct*)); - scattered_flag = malloc(number_of_volumes*sizeof(int)); - scattered_flag_VP = (int**) malloc(number_of_volumes * sizeof(int*)); - number_of_processes_array = malloc(number_of_volumes*sizeof(int)); - + Volumes = malloc (number_of_volumes * sizeof (struct Volume_struct*)); + scattered_flag = malloc (number_of_volumes * sizeof (int)); + scattered_flag_VP = (int**)malloc (number_of_volumes * sizeof (int*)); + number_of_processes_array = malloc (number_of_volumes * sizeof (int)); + // The mcdisplay functions need access to the other geomtries, but can not use the Volumes struct because of order of definition. // A separate list of pointers to the geometry structures is thus allocated - Geometries = malloc(number_of_volumes * sizeof(struct geometry_struct *)); - + Geometries = malloc (number_of_volumes * sizeof (struct geometry_struct*)); + // When activation counter is used to have several copies of one volume, it can become necessary to have soft copies of volumes // Not all of these will necessarily be allocated or used. - Volume_copies = malloc(number_of_volumes * sizeof(struct Volume_struct *)); + Volume_copies = malloc (number_of_volumes * sizeof (struct Volume_struct*)); Volume_copies_allocated.num_elements = 0; - + // The central structure is called a "Volume", it describes a region in space with certain scattering processes and absorption cross section // --- Volume 0 ------------------------------------------------------------------------------------------------ // Volume 0 is the vacuum surrounding the experiment (infinite, everywhere) and its properties are hardcoded here - Volumes[0] = malloc(sizeof(struct Volume_struct)); - strcpy(Volumes[0]->name,"Surrounding vacuum"); + Volumes[0] = malloc (sizeof (struct Volume_struct)); + strcpy (Volumes[0]->name, "Surrounding vacuum"); // Assign geometry - + // This information is meaningless for volume 0, and is never be acsessed in the logic. Volumes[0]->geometry.priority_value = 0.0; Volumes[0]->geometry.center.x = 0; Volumes[0]->geometry.center.y = 0; Volumes[0]->geometry.center.z = 0; - strcpy(Volumes[0]->geometry.shape,"vacuum"); + strcpy (Volumes[0]->geometry.shape, "vacuum"); Volumes[0]->geometry.eShape = surroundings; Volumes[0]->geometry.within_function = &r_within_surroundings; // Always returns 1 // No physics struct allocated Volumes[0]->p_physics = NULL; number_of_processes_array[volume_index] = 0; - + // These are never used for volume 0, but by setting the length to 0 it is automatically skipped in many forloops without the need for an if statement - Volumes[0]->geometry.children.num_elements=0; - Volumes[0]->geometry.direct_children.num_elements=0; - Volumes[0]->geometry.destinations_list.num_elements=0; - Volumes[0]->geometry.reduced_destinations_list.num_elements=0; - + Volumes[0]->geometry.children.num_elements = 0; + Volumes[0]->geometry.direct_children.num_elements = 0; + Volumes[0]->geometry.destinations_list.num_elements = 0; + Volumes[0]->geometry.reduced_destinations_list.num_elements = 0; + Volumes[0]->geometry.is_exit_volume = 0; Volumes[0]->geometry.masked_by_list.num_elements = 0; Volumes[0]->geometry.mask_list.num_elements = 0; Volumes[0]->geometry.masked_by_mask_index_list.num_elements = 0; - Volumes[0]->geometry.mask_mode=0; - Volumes[0]->geometry.is_mask_volume=0; - Volumes[0]->geometry.is_masked_volume=0; - + Volumes[0]->geometry.mask_mode = 0; + Volumes[0]->geometry.is_mask_volume = 0; + Volumes[0]->geometry.is_masked_volume = 0; + // A pointer to the geometry structure Geometries[0] = &Volumes[0]->geometry; - + // Logging initialization Volumes[0]->loggers.num_elements = 0; Volumes[0]->abs_loggers.num_elements = 0; - - + // --- Loop over user defined volumes ------------------------------------------------------------------------ // Here the user defined volumes are loaded into the volume structure that is used in the ray-tracing // algorithm. Not all user defined volumes are used, some could be used by a previous master, some // could be used by the previous master, this one, and perhaps more. This is controlled by the // activation counter input for geometries, and is here condensed to the active variable. // Volumes that were used before - - + max_number_of_processes = 0; // The maximum number of processes in a volume is assumed 0 and updated during the following loop - + volume_index = 0; mask_index_main = 0; - for (geometry_list_index=0;geometry_list_indexnum_elements;geometry_list_index++) { + for (geometry_list_index = 0; geometry_list_index < global_geometry_list_master->num_elements; geometry_list_index++) { if (global_geometry_list_master->elements[geometry_list_index].active == 1) { // Only include the volume if it is active volume_index++; // Connect a volume for each of the geometry.comp instances in the McStas instrument files @@ -513,138 +532,142 @@ exit(-1); Volumes[volume_index] = global_geometry_list_master->elements[geometry_list_index].Volume; } else { // Since this volume is still needed more than this once, we need to make a shallow copy and use instead - - Volume_copies[volume_index] = malloc(sizeof(struct Volume_struct)); + + Volume_copies[volume_index] = malloc (sizeof (struct Volume_struct)); *(Volume_copies[volume_index]) = *global_geometry_list_master->elements[geometry_list_index].Volume; // Makes shallow copy Volumes[volume_index] = Volume_copies[volume_index]; - add_element_to_int_list(&Volume_copies_allocated,volume_index); // Keep track of dynamically allocated volumes in order to free them in FINALLY. - + add_element_to_int_list (&Volume_copies_allocated, volume_index); // Keep track of dynamically allocated volumes in order to free them in FINALLY. + // The geometry storage needs a shallow copy as well (hard copy not necessary for any current geometries), may need changes in future // A simple copy_geometry_parameters function is added to the geometry in each geometry component - Volumes[volume_index]->geometry.geometry_parameters = Volumes[volume_index]->geometry.copy_geometry_parameters(&global_geometry_list_master->elements[geometry_list_index].Volume->geometry.geometry_parameters); - + Volumes[volume_index]->geometry.geometry_parameters = Volumes[volume_index]->geometry.copy_geometry_parameters ( + &global_geometry_list_master->elements[geometry_list_index].Volume->geometry.geometry_parameters); } - + // This section identifies the different non isotropic processes in the current volume and give them appropriate transformation matrices // Identify the number of non isotropic processes in a material (this code can be safely executed for the same material many times) // A setting of -1 means no transformation necessary, other settings are assigned a unique identifier instead non_isotropic_found = 0; - for (iterator=0;iteratorp_physics->number_of_processes;iterator++) { + for (iterator = 0; iterator < Volumes[volume_index]->p_physics->number_of_processes; iterator++) { if (Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index != -1) { - Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index = non_isotropic_found; - non_isotropic_found++; + Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index = non_isotropic_found; + non_isotropic_found++; } } - - Volumes[volume_index]->geometry.focus_array_indices.num_elements=0; + + Volumes[volume_index]->geometry.focus_array_indices.num_elements = 0; // For the non_isotropic volumes found, rotation matrices need to be allocated and calculated if (non_isotropic_found > 0) { // Allocation of rotation and transpose rotation matrices if (Volumes[volume_index]->geometry.process_rot_allocated == 0) { - Volumes[volume_index]->geometry.process_rot_matrix_array = malloc(non_isotropic_found * sizeof(Rotation)); - Volumes[volume_index]->geometry.transpose_process_rot_matrix_array = malloc(non_isotropic_found * sizeof(Rotation)); + Volumes[volume_index]->geometry.process_rot_matrix_array = malloc (non_isotropic_found * sizeof (Rotation)); + Volumes[volume_index]->geometry.transpose_process_rot_matrix_array = malloc (non_isotropic_found * sizeof (Rotation)); Volumes[volume_index]->geometry.process_rot_allocated = 1; } - + // Calculation of the appropriate rotation matrices for transformation between Union_master and the process in a given volume. non_isotropic_found = 0; - for (iterator=0;iteratorp_physics->number_of_processes;iterator++) { + for (iterator = 0; iterator < Volumes[volume_index]->p_physics->number_of_processes; iterator++) { if (Volumes[volume_index]->p_physics->p_scattering_array[iterator].non_isotropic_rot_index != -1) { // Transformation for each process / geometry combination - + // The focus vector is given in relation to the geometry and needs to be transformed to the process // Work on temporary_focus_data_element which is added to the focus_data_array_at the end temporary_focus_data = Volumes[volume_index]->geometry.focus_data_array.elements[0]; - + // Correct for process rotation - temporary_focus_data.Aim = rot_apply(Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix,temporary_focus_data.Aim); - + temporary_focus_data.Aim = rot_apply (Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix, temporary_focus_data.Aim); + // Add element to focus_array_indices // focus_array_indices refers to the correct element in focus_data_array for this volume/process combination // focus_data_array[0] is the isotropic version in all cases, so the first non_isotropic goes to focus_data_array[1] // and so forth. When a process is isotropic, this array is appended with a zero. // The focus_array_indices maps process numbers to the correct focus_data_array index. - add_element_to_int_list(&Volumes[volume_index]->geometry.focus_array_indices,non_isotropic_found+1); - + add_element_to_int_list (&Volumes[volume_index]->geometry.focus_array_indices, non_isotropic_found + 1); + // Add the new focus_data element to this volumes focus_data_array. - add_element_to_focus_data_array(&Volumes[volume_index]->geometry.focus_data_array,temporary_focus_data); - + add_element_to_focus_data_array (&Volumes[volume_index]->geometry.focus_data_array, temporary_focus_data); + // Quick error check to see the length is correct which indirectly confirms the indices are correct if (Volumes[volume_index]->geometry.focus_data_array.num_elements != non_isotropic_found + 2) { - printf("ERROR, focus_data_array length for volume %s inconsistent with number of non isotropic processes found!\n",Volumes[volume_index]->name); - exit(1); + printf ("ERROR, focus_data_array length for volume %s inconsistent with number of non isotropic processes found!\n", Volumes[volume_index]->name); + exit (1); } - - // Create rotation matrix for this specific volume / process combination to transform from master coordinate system to the non-isotropics process coordinate system - // This is done by multipling the transpose master component roration matrix, the volume rotation, and then the process rotation matrix onto the velocity / wavevector - rot_mul(Volumes[volume_index]->geometry.rotation_matrix,master_transposed_rotation_matrix,temp_rotation_matrix); - rot_mul(Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix,temp_rotation_matrix,Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found]); - + + // Create rotation matrix for this specific volume / process combination to transform from master coordinate system to the non-isotropics process + // coordinate system This is done by multipling the transpose master component roration matrix, the volume rotation, and then the process rotation + // matrix onto the velocity / wavevector + rot_mul (Volumes[volume_index]->geometry.rotation_matrix, master_transposed_rotation_matrix, temp_rotation_matrix); + rot_mul (Volumes[volume_index]->p_physics->p_scattering_array[iterator].rotation_matrix, temp_rotation_matrix, + Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found]); + // Need to transpose as well to transform back to the master coordinate system - rot_transpose(Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found],Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found]); + rot_transpose (Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found], + Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found]); // Debug print - //print_rotation(Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found],"Process rotation matrix"); - //print_rotation(Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found],"Transpose process rotation matrix"); - + // print_rotation(Volumes[volume_index]->geometry.process_rot_matrix_array[non_isotropic_found],"Process rotation matrix"); + // print_rotation(Volumes[volume_index]->geometry.transpose_process_rot_matrix_array[non_isotropic_found],"Transpose process rotation matrix"); + non_isotropic_found++; } else { // This process can use the standard isotropic focus_data_array which is indexed zero. - add_element_to_int_list(&Volumes[volume_index]->geometry.focus_array_indices,0); + add_element_to_int_list (&Volumes[volume_index]->geometry.focus_array_indices, 0); } } } else { - // No non isotropic volumes found, focus_array_indices should just be a list of 0's of same length as the number of processes. - // In this way all processes use the isotropic focus_data structure - Volumes[volume_index]->geometry.focus_array_indices.elements = malloc(Volumes[volume_index]->p_physics->number_of_processes * sizeof(int)); - for (iterator=0;iteratorp_physics->number_of_processes;iterator++) + // No non isotropic volumes found, focus_array_indices should just be a list of 0's of same length as the number of processes. + // In this way all processes use the isotropic focus_data structure + Volumes[volume_index]->geometry.focus_array_indices.elements = malloc (Volumes[volume_index]->p_physics->number_of_processes * sizeof (int)); + for (iterator = 0; iterator < Volumes[volume_index]->p_physics->number_of_processes; iterator++) Volumes[volume_index]->geometry.focus_array_indices.elements[iterator] = 0; - } - + // This component works in its local coordinate system, and thus all information from the input components should be transformed to its coordinate system. // All the input components saved their absolute rotation/position into their Volume structure, and the absolute rotation of the current component is known. // The next section finds the relative rotation and translation of all the volumes and the master component. - + // Transform the rotation matrices for each volume - rot_mul(ROT_A_CURRENT_COMP,Volumes[volume_index]->geometry.transpose_rotation_matrix,temp_rotation_matrix); + rot_mul (ROT_A_CURRENT_COMP, Volumes[volume_index]->geometry.transpose_rotation_matrix, temp_rotation_matrix); // Copy the result back to the volumes structure - rot_copy(Volumes[volume_index]->geometry.rotation_matrix,temp_rotation_matrix); + rot_copy (Volumes[volume_index]->geometry.rotation_matrix, temp_rotation_matrix); // Now update the transpose as well - rot_transpose(Volumes[volume_index]->geometry.rotation_matrix,temp_rotation_matrix); - rot_copy(Volumes[volume_index]->geometry.transpose_rotation_matrix,temp_rotation_matrix); - + rot_transpose (Volumes[volume_index]->geometry.rotation_matrix, temp_rotation_matrix); + rot_copy (Volumes[volume_index]->geometry.transpose_rotation_matrix, temp_rotation_matrix); + // Transform the position for each volume non_rotated_position.x = Volumes[volume_index]->geometry.center.x - POS_A_CURRENT_COMP.x; non_rotated_position.y = Volumes[volume_index]->geometry.center.y - POS_A_CURRENT_COMP.y; non_rotated_position.z = Volumes[volume_index]->geometry.center.z - POS_A_CURRENT_COMP.z; - rot_transpose(ROT_A_CURRENT_COMP,temp_rotation_matrix); // REVIEW LINE - rotated_position = rot_apply(ROT_A_CURRENT_COMP, non_rotated_position); + rot_transpose (ROT_A_CURRENT_COMP, temp_rotation_matrix); // REVIEW LINE + rotated_position = rot_apply (ROT_A_CURRENT_COMP, non_rotated_position); Volumes[volume_index]->geometry.center.x = rotated_position.x; Volumes[volume_index]->geometry.center.y = rotated_position.y; Volumes[volume_index]->geometry.center.z = rotated_position.z; - + // The focus_data information need to be updated as well - rot_mul(ROT_A_CURRENT_COMP,Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation,temp_rotation_matrix); + rot_mul (ROT_A_CURRENT_COMP, Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation, temp_rotation_matrix); // Copy the result back to the volumes structure - rot_copy(Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation,temp_rotation_matrix); - + rot_copy (Volumes[volume_index]->geometry.focus_data_array.elements[0].absolute_rotation, temp_rotation_matrix); + // Use same rotation on the aim vector of the isotropic focus_data element - Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim = rot_apply(Volumes[volume_index]->geometry.rotation_matrix,Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim); - + Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim + = rot_apply (Volumes[volume_index]->geometry.rotation_matrix, Volumes[volume_index]->geometry.focus_data_array.elements[0].Aim); + // To allocate enough memory to hold information on all processes, the maximum of these is updated if this volume has more if (Volumes[volume_index]->p_physics->number_of_processes > max_number_of_processes) - max_number_of_processes = Volumes[volume_index]->p_physics->number_of_processes; - + max_number_of_processes = Volumes[volume_index]->p_physics->number_of_processes; + // Allocate memory to scattered_flag_VP (holds statistics for scatterings in each process of the volume) - scattered_flag_VP[volume_index] = malloc(Volumes[volume_index]->p_physics->number_of_processes * sizeof(int)); + scattered_flag_VP[volume_index] = malloc (Volumes[volume_index]->p_physics->number_of_processes * sizeof (int)); number_of_processes_array[volume_index] = Volumes[volume_index]->p_physics->number_of_processes; - + // Normalizing and error checking process interact fraction - number_of_process_interacts_set = 0; total_process_interact=0; - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { + number_of_process_interacts_set = 0; + total_process_interact = 0; + for (process_index = 0; process_index < Volumes[volume_index]->p_physics->number_of_processes; process_index++) { if (Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact != -1) { number_of_process_interacts_set++; total_process_interact += Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact; @@ -652,262 +675,283 @@ exit(-1); index_of_lacking_process = process_index; } } - - if (number_of_process_interacts_set == 0) Volumes[volume_index]->p_physics->interact_control = 0; - else Volumes[volume_index]->p_physics->interact_control = 1; - + + if (number_of_process_interacts_set == 0) + Volumes[volume_index]->p_physics->interact_control = 0; + else + Volumes[volume_index]->p_physics->interact_control = 1; + // If all are set, check if they need renormalization so that the sum is one. if (number_of_process_interacts_set == Volumes[volume_index]->p_physics->number_of_processes) { if (total_process_interact > 1.001 || total_process_interact < 0.999) { - for (process_index=0;process_indexp_physics->number_of_processes;process_index++) { - Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact = Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact/total_process_interact; + for (process_index = 0; process_index < Volumes[volume_index]->p_physics->number_of_processes; process_index++) { + Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact + = Volumes[volume_index]->p_physics->p_scattering_array[process_index].process_p_interact / total_process_interact; } } - } else if ( number_of_process_interacts_set != 0) { - if (number_of_process_interacts_set == Volumes[volume_index]->p_physics->number_of_processes - 1) {// If all but one is set, it is an easy fix + } else if (number_of_process_interacts_set != 0) { + if (number_of_process_interacts_set == Volumes[volume_index]->p_physics->number_of_processes - 1) { // If all but one is set, it is an easy fix Volumes[volume_index]->p_physics->p_scattering_array[index_of_lacking_process].process_p_interact = 1 - total_process_interact; if (total_process_interact >= 1) { - printf("ERROR, material %s has a total interact_fraction above 1 and a process without an interact_fraction. Either set all so they can be renormalized, or have a sum below 1, so that the last can have 1 - sum.\n",Volumes[volume_index]->p_physics->name); - exit(1); + printf ("ERROR, material %s has a total interact_fraction above 1 and a process without an interact_fraction. Either set all so they can be " + "renormalized, or have a sum below 1, so that the last can have 1 - sum.\n", + Volumes[volume_index]->p_physics->name); + exit (1); } } else { - printf("ERROR, material %s needs to have all, all minus one or none of its processes with an interact_fraction \n",Volumes[volume_index]->p_physics->name); - exit(1); + printf ("ERROR, material %s needs to have all, all minus one or none of its processes with an interact_fraction \n", + Volumes[volume_index]->p_physics->name); + exit (1); } } - + // Some initialization can only happen after the rotation matrix relative to the master is known // Such initialization is placed in the geometry component, and executed here through a function pointer - Volumes[volume_index]->geometry.initialize_from_main_function(&Volumes[volume_index]->geometry); - + Volumes[volume_index]->geometry.initialize_from_main_function (&Volumes[volume_index]->geometry); + // Add pointer to geometry to Geometries Geometries[volume_index] = &Volumes[volume_index]->geometry; - + // Initialize mask intersect list Volumes[volume_index]->geometry.mask_intersect_list.num_elements = 0; - + // Here the mask_list and masked_by_list for the volume is updated from component index values to volume indexes - for (iterator=0;iteratorgeometry.mask_list.num_elements;iterator++) - Volumes[volume_index]->geometry.mask_list.elements[iterator] = find_on_int_list(geometry_component_index_list,Volumes[volume_index]->geometry.mask_list.elements[iterator]); - - for (iterator=0;iteratorgeometry.masked_by_list.num_elements;iterator++) - Volumes[volume_index]->geometry.masked_by_list.elements[iterator] = find_on_int_list(geometry_component_index_list,Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); - + for (iterator = 0; iterator < Volumes[volume_index]->geometry.mask_list.num_elements; iterator++) + Volumes[volume_index]->geometry.mask_list.elements[iterator] + = find_on_int_list (geometry_component_index_list, Volumes[volume_index]->geometry.mask_list.elements[iterator]); + + for (iterator = 0; iterator < Volumes[volume_index]->geometry.masked_by_list.num_elements; iterator++) + Volumes[volume_index]->geometry.masked_by_list.elements[iterator] + = find_on_int_list (geometry_component_index_list, Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); + // If the volume is a mask, its volume number is added to the mask_volume_index list so volume index can be converted to mask_index. - if (Volumes[volume_index]->geometry.is_mask_volume == 1) Volumes[volume_index]->geometry.mask_index = mask_index_main; - if (Volumes[volume_index]->geometry.is_mask_volume == 1) mask_volume_index_list.elements[mask_index_main++] = volume_index; - + if (Volumes[volume_index]->geometry.is_mask_volume == 1) + Volumes[volume_index]->geometry.mask_index = mask_index_main; + if (Volumes[volume_index]->geometry.is_mask_volume == 1) + mask_volume_index_list.elements[mask_index_main++] = volume_index; + // Check all loggers assosiated with this volume and update the max_conditional_extend_index if necessary - for (iterator=0;iteratorloggers.num_elements;iterator++) { - for (process_index=0;process_indexloggers.p_logger_volume[iterator].num_elements;process_index++) { + for (iterator = 0; iterator < Volumes[volume_index]->loggers.num_elements; iterator++) { + for (process_index = 0; process_index < Volumes[volume_index]->loggers.p_logger_volume[iterator].num_elements; process_index++) { if (Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process[process_index] != NULL) { if (Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process[process_index]->logger_extend_index > max_conditional_extend_index) max_conditional_extend_index = Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process[process_index]->logger_extend_index; } } } - - } } // Initialization for each volume done - + // ------- Initialization of ray-tracing algorithm ------------------------------------ - - my_trace = malloc(max_number_of_processes*sizeof(double)); - my_trace_fraction_control = malloc(max_number_of_processes*sizeof(double)); - - //component_error_msg = 0; - - + + my_trace = malloc (max_number_of_processes * sizeof (double)); + my_trace_fraction_control = malloc (max_number_of_processes * sizeof (double)); + + // component_error_msg = 0; + // Allocate memory for logger_conditional_extend_array used in the extend section of the master component, if it is needed. if (max_conditional_extend_index > -1) { - logger_conditional_extend_array = malloc((max_conditional_extend_index + 1)*sizeof(int)); + logger_conditional_extend_array = malloc ((max_conditional_extend_index + 1) * sizeof (int)); } - + // In this function different lists of volume indecies are generated. They are the key to the speed of the component and central for the logic. // They use simple set algebra to generate these lists for each volume: // Children list for volume n: Indicies of volumes that are entirely within the set described by volume n // Overlap list for volume n: Indicies of volume that contains some of the set described by volume n (excluding volume n) - // Intersect check list for volume n: Indicies of volumes to check for intersection if a ray originates from volume n (is generated from the children and overlap lists) - // Parents list for volume n: Indicies of volumes that contain the entire set of volume n - // Grandparents lists for volume n: Indicies of volumes that contain the entire set of at least one parent of volume n - // Destination list for volume n: Indicies of volumes that could be the destination volume when a ray leaves volume n - // The overlap, parents and grandparents lists are local variables in the function, and not in the main scope. - - generate_lists(Volumes, &starting_lists, number_of_volumes, list_verbal); - + // Intersect check list for volume n: Indicies of volumes to check for intersection if a ray originates from volume n (is generated from the children and + // overlap lists) Parents list for volume n: Indicies of volumes that contain the entire set of volume n Grandparents lists for volume n: Indicies of volumes + // that contain the entire set of at least one parent of volume n Destination list for volume n: Indicies of volumes that could be the destination volume when a + // ray leaves volume n The overlap, parents and grandparents lists are local variables in the function, and not in the main scope. + + generate_lists (Volumes, &starting_lists, number_of_volumes, list_verbal); + // Generate "safe starting list", which contains all volumes that the ray may enter from other components // These are all volumes without scattering or absorption - + // Updating mask lists from volume index to global_mask_indices // Filling out the masked_by list that uses mask indices - for (volume_index=0;volume_indexgeometry.masked_by_mask_index_list.num_elements = Volumes[volume_index]->geometry.masked_by_list.num_elements; - Volumes[volume_index]->geometry.masked_by_mask_index_list.elements = malloc(Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements * sizeof(int)); - for (iterator=0;iteratorgeometry.masked_by_list.num_elements;iterator++) - Volumes[volume_index]->geometry.masked_by_mask_index_list.elements[iterator] = find_on_int_list(mask_volume_index_list,Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); + Volumes[volume_index]->geometry.masked_by_mask_index_list.elements + = malloc (Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements * sizeof (int)); + for (iterator = 0; iterator < Volumes[volume_index]->geometry.masked_by_list.num_elements; iterator++) + Volumes[volume_index]->geometry.masked_by_mask_index_list.elements[iterator] + = find_on_int_list (mask_volume_index_list, Volumes[volume_index]->geometry.masked_by_list.elements[iterator]); } - + int volume_index_main; - + // Checking for equal priorities in order to alert the user to a potential input error - for (volume_index_main=0;volume_index_maingeometry.priority_value == Volumes[volume_index]->geometry.priority_value && volume_index_main != volume_index) { - if (Volumes[volume_index_main]->geometry.is_mask_volume == 0 && Volumes[volume_index]->geometry.is_mask_volume == 0) { - // Priority of masks do not matter - printf("ERROR in Union_master with name %s. The volumes named %s and %s have the same priority. Change the priorities so the one present in case of overlap has highest priority.\n",NAME_CURRENT_COMP,Volumes[volume_index_main]->name,Volumes[volume_index]->name); - exit(1); - } - } - } - - - // Printing the generated lists for all volumes. - MPI_MASTER( - if (verbal) printf("\n ---- Overview of the lists generated for each volume ---- \n"); - - - printf("List overview for surrounding vacuum\n"); - for (volume_index_main=0;volume_index_maingeometry.is_mask_volume == 0 || - Volumes[volume_index_main]->geometry.is_masked_volume == 0 || - Volumes[volume_index_main]->geometry.is_exit_volume == 0) { - printf("List overview for %s with %s shape made of %s\n", - Volumes[volume_index_main]->name, - Volumes[volume_index_main]->geometry.shape, - Volumes[volume_index_main]->p_physics->name); - } else { - printf("List overview for %s with shape %s\n", - Volumes[volume_index_main]->name, - Volumes[volume_index_main]->geometry.shape); - } + for (volume_index_main = 0; volume_index_main < number_of_volumes; volume_index_main++) { + for (volume_index = 0; volume_index < number_of_volumes; volume_index++) + if (Volumes[volume_index_main]->geometry.priority_value == Volumes[volume_index]->geometry.priority_value && volume_index_main != volume_index) { + if (Volumes[volume_index_main]->geometry.is_mask_volume == 0 && Volumes[volume_index]->geometry.is_mask_volume == 0) { + // Priority of masks do not matter + printf ("ERROR in Union_master with name %s. The volumes named %s and %s have the same priority. Change the priorities so the one present in case of " + "overlap has highest priority.\n", + NAME_CURRENT_COMP, Volumes[volume_index_main]->name, Volumes[volume_index]->name); + exit (1); } } - - if (verbal) sprintf(string_output,"Children for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.children,string_output); - - if (verbal) sprintf(string_output,"Direct_children for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.direct_children,string_output); - - if (verbal) sprintf(string_output,"Intersect_check_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.intersect_check_list,string_output); - - if (verbal) sprintf(string_output,"Mask_intersect_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.mask_intersect_list,string_output); - - if (verbal) sprintf(string_output,"Destinations_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.destinations_list,string_output); - - //if (verbal) sprintf(string_output,"Destinations_logic_list for Volume %d",volume_index_main); - //if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.destinations_logic_list,string_output); - - if (verbal) sprintf(string_output,"Reduced_destinations_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.reduced_destinations_list,string_output); - - if (verbal) sprintf(string_output,"Next_volume_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.next_volume_list,string_output); - - if (verbal) { - if (volume_index_main != 0) - printf(" Is_vacuum for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->p_physics->is_vacuum); - } - if (verbal) { - if (volume_index_main != 0) - printf(" is_mask_volume for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.is_mask_volume); - } - if (verbal) { - if (volume_index_main != 0) - printf(" is_masked_volume for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.is_masked_volume); - } - if (verbal) { - if (volume_index_main != 0) - printf(" is_exit_volume for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.is_exit_volume); - } - - if (verbal) sprintf(string_output,"mask_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.mask_list,string_output); - - if (verbal) sprintf(string_output,"masked_by_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.masked_by_list,string_output); - - if (verbal) sprintf(string_output,"masked_by_mask_index_list for Volume %d",volume_index_main); - if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.masked_by_mask_index_list,string_output); - - if (verbal) printf(" mask_mode for Volume %d = %d\n",volume_index_main,Volumes[volume_index_main]->geometry.mask_mode); - if (verbal) printf("\n"); } - ) // End of MPI_MASTER - + + // Printing the generated lists for all volumes. + MPI_MASTER (if (verbal) printf ("\n ---- Overview of the lists generated for each volume ---- \n"); + + printf ("List overview for surrounding vacuum\n"); for (volume_index_main = 0; volume_index_main < number_of_volumes; volume_index_main++) { + if (verbal) { + if (volume_index_main != 0) { + if (Volumes[volume_index_main]->geometry.is_mask_volume == 0 || Volumes[volume_index_main]->geometry.is_masked_volume == 0 + || Volumes[volume_index_main]->geometry.is_exit_volume == 0) { + printf ("List overview for %s with %s shape made of %s\n", Volumes[volume_index_main]->name, Volumes[volume_index_main]->geometry.shape, + Volumes[volume_index_main]->p_physics->name); + } else { + printf ("List overview for %s with shape %s\n", Volumes[volume_index_main]->name, Volumes[volume_index_main]->geometry.shape); + } + } + } + + if (verbal) + sprintf (string_output, "Children for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.children, string_output); + + if (verbal) + sprintf (string_output, "Direct_children for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.direct_children, string_output); + + if (verbal) + sprintf (string_output, "Intersect_check_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.intersect_check_list, string_output); + + if (verbal) + sprintf (string_output, "Mask_intersect_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.mask_intersect_list, string_output); + + if (verbal) + sprintf (string_output, "Destinations_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.destinations_list, string_output); + + // if (verbal) sprintf(string_output,"Destinations_logic_list for Volume %d",volume_index_main); + // if (verbal) print_1d_int_list(Volumes[volume_index_main]->geometry.destinations_logic_list,string_output); + + if (verbal) + sprintf (string_output, "Reduced_destinations_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.reduced_destinations_list, string_output); + + if (verbal) + sprintf (string_output, "Next_volume_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.next_volume_list, string_output); + + if (verbal) { + if (volume_index_main != 0) + printf (" Is_vacuum for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->p_physics->is_vacuum); + } + if (verbal) { + if (volume_index_main != 0) + printf (" is_mask_volume for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.is_mask_volume); + } + if (verbal) { + if (volume_index_main != 0) + printf (" is_masked_volume for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.is_masked_volume); + } + if (verbal) { + if (volume_index_main != 0) + printf (" is_exit_volume for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.is_exit_volume); + } + + if (verbal) + sprintf (string_output, "mask_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.mask_list, string_output); + + if (verbal) + sprintf (string_output, "masked_by_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.masked_by_list, string_output); + + if (verbal) + sprintf (string_output, "masked_by_mask_index_list for Volume %d", volume_index_main); + if (verbal) + print_1d_int_list (Volumes[volume_index_main]->geometry.masked_by_mask_index_list, string_output); + + if (verbal) + printf (" mask_mode for Volume %d = %d\n", volume_index_main, Volumes[volume_index_main]->geometry.mask_mode); + if (verbal) + printf ("\n"); + }) // End of MPI_MASTER // Initializing intersection_time_table - // The intersection time table contains all information on intersection times for the current position/direction, and is cleared everytime a ray changes direction. - // Not all entries needs to be calculated, so there is a variable that keeps track of which intersection times have been calculated in order to avoid redoing that. - // When the intersections times are calculated for a volume, all future intersections are kept in the time table. - // Thus the memory allocation have to take into account how many intersections there can be with each volume, but it is currently set to 2, but can easily be changed. This may need to be reported by individual geometry components in the future. - - intersection_time_table = malloc(sizeof(struct intersection_time_table_struct)); + // The intersection time table contains all information on intersection times for the current position/direction, and is cleared everytime a ray changes + // direction. Not all entries needs to be calculated, so there is a variable that keeps track of which intersection times have been calculated in order to avoid + // redoing that. When the intersections times are calculated for a volume, all future intersections are kept in the time table. Thus the memory allocation have + // to take into account how many intersections there can be with each volume, but it is currently set to 2, but can easily be changed. This may need to be + // reported by individual geometry components in the future. + + intersection_time_table = malloc (sizeof (struct intersection_time_table_struct)); intersection_time_table->num_volumes = number_of_volumes; - - intersection_time_table->n_elements = (int*) malloc(intersection_time_table->num_volumes * sizeof(int)); - intersection_time_table->calculated = (int*) malloc(intersection_time_table->num_volumes * sizeof(int)); - intersection_time_table->intersection_times = (double**) malloc(intersection_time_table->num_volumes * sizeof(double)); - for (iterator = 0;iterator < intersection_time_table->num_volumes;iterator++){ - if (strcmp(Volumes[iterator]->geometry.shape, "mesh") == 0) { - intersection_time_table->n_elements[iterator] = (int) 100; // Meshes can have any number of intersections, here we allocate room for 100 - } else { - intersection_time_table->n_elements[iterator] = (int) 2; // number of intersection for all other geometries - } - if (iterator == 0) intersection_time_table->n_elements[iterator] = (int) 0; // number of intersection solutions - intersection_time_table->calculated[iterator] = (int) 0; // Initializing calculated logic - - if (iterator == 0) { - intersection_time_table->intersection_times[0] = NULL; - } - else { - intersection_time_table->intersection_times[iterator] = (double*) malloc(intersection_time_table->n_elements[iterator]*sizeof(double)); - for (solutions = 0;solutions < intersection_time_table->n_elements[iterator];solutions++) { - intersection_time_table->intersection_times[iterator][solutions] = -1.0; - } + + intersection_time_table->n_elements = (int*)malloc (intersection_time_table->num_volumes * sizeof (int)); + intersection_time_table->calculated = (int*)malloc (intersection_time_table->num_volumes * sizeof (int)); + intersection_time_table->intersection_times = (double**)malloc (intersection_time_table->num_volumes * sizeof (double)); + for (iterator = 0; iterator < intersection_time_table->num_volumes; iterator++) { + if (strcmp (Volumes[iterator]->geometry.shape, "mesh") == 0) { + intersection_time_table->n_elements[iterator] = (int)100; // Meshes can have any number of intersections, here we allocate room for 100 + } else { + intersection_time_table->n_elements[iterator] = (int)2; // number of intersection for all other geometries + } + if (iterator == 0) + intersection_time_table->n_elements[iterator] = (int)0; // number of intersection solutions + intersection_time_table->calculated[iterator] = (int)0; // Initializing calculated logic + + if (iterator == 0) { + intersection_time_table->intersection_times[0] = NULL; + } else { + intersection_time_table->intersection_times[iterator] = (double*)malloc (intersection_time_table->n_elements[iterator] * sizeof (double)); + for (solutions = 0; solutions < intersection_time_table->n_elements[iterator]; solutions++) { + intersection_time_table->intersection_times[iterator][solutions] = -1.0; } + } } - + // If enabled, the tagging system tracks all different histories sampled by the program. // Initialize the tagging tree // Allocate a list of host nodes with the same length as the number of volumes - - stop_creating_nodes = 0; stop_tagging_ray = 0; tagging_leaf_counter = 0; + + stop_creating_nodes = 0; + stop_tagging_ray = 0; + tagging_leaf_counter = 0; if (enable_tagging) { master_tagging_node_list.num_elements = number_of_volumes; - master_tagging_node_list.elements = malloc(master_tagging_node_list.num_elements * sizeof(struct tagging_tree_node_struct*)); - + master_tagging_node_list.elements = malloc (master_tagging_node_list.num_elements * sizeof (struct tagging_tree_node_struct*)); + // Initialize - for (volume_index=0;volume_index %g %g %g\n",x,y,z,vx,vy,vz); - int starting_volume_warning=0; + // printf("incoming event: %g %g %g -> %g %g %g\n",x,y,z,vx,vy,vz); + int starting_volume_warning = 0; // Record absorption double r_old[3]; double initial_weight; @@ -959,35 +1002,43 @@ TRACE int abs_weight_factor_set; double my_abs; struct abs_event absorption_event_data[1000]; - + // Absorption logger Coords abs_position; Coords transformed_abs_position; double t_abs_propagation; double abs_distance; double abs_max_length; - + #ifdef Union_trace_verbal_setting - printf("\n\n\n\n\n----------- NEW RAY -------------------------------------------------\n"); - printf("Union_master component name: %s \n \n",NAME_CURRENT_COMP); + printf ("\n\n\n\n\n----------- NEW RAY -------------------------------------------------\n"); + printf ("Union_master component name: %s \n \n", NAME_CURRENT_COMP); #endif - + // Initialize logic int done = 0; int current_volume; int error_msg = 0; int my_iterator; int geometry_output; - + double k[3]; double k_new[3]; double k_old[3]; double k_rotated[3]; - k[0]=0; k[1]=0; k[2]=0; - k_new[0]=0; k_new[1]=0; k_new[2]=0; - k_old[0]=0; k_old[1]=0; k_old[2]=0; - k_rotated[0]=0; k_rotated[1]=0; k_rotated[2]=0; + k[0] = 0; + k[1] = 0; + k[2] = 0; + k_new[0] = 0; + k_new[1] = 0; + k_new[2] = 0; + k_old[0] = 0; + k_old[1] = 0; + k_old[2] = 0; + k_rotated[0] = 0; + k_rotated[1] = 0; + k_rotated[2] = 0; double v_length; double my_sum; @@ -1005,124 +1056,138 @@ TRACE struct pointer_to_1d_int_list my_mask_status_list; my_mask_status_list.num_elements = mask_status_list.num_elements; - if (number_of_masks >0) my_mask_status_list.elements = malloc( number_of_masks * sizeof(int)); + if (number_of_masks > 0) + my_mask_status_list.elements = malloc (number_of_masks * sizeof (int)); my_mask_status_list.elements = mask_status_list.elements; - struct intersection_time_table_struct *my_intersection_time_table; - my_intersection_time_table = malloc(sizeof(struct intersection_time_table_struct)); + struct intersection_time_table_struct* my_intersection_time_table; + my_intersection_time_table = malloc (sizeof (struct intersection_time_table_struct)); my_intersection_time_table = intersection_time_table; - int *my_logger_conditional_extend_array = malloc((max_conditional_extend_index + 1)*sizeof(int)); + int* my_logger_conditional_extend_array = malloc ((max_conditional_extend_index + 1) * sizeof (int)); my_logger_conditional_extend_array = logger_conditional_extend_array; struct starting_lists_struct my_starting_lists; - my_starting_lists=starting_lists; + my_starting_lists = starting_lists; - int *pre_allocated1; - int *pre_allocated2; - int *pre_allocated3; + int* pre_allocated1; + int* pre_allocated2; + int* pre_allocated3; // Pre allocated memory for destination list search - pre_allocated1 = malloc(number_of_volumes * sizeof(int)); - pre_allocated2 = malloc(number_of_volumes * sizeof(int)); - pre_allocated3 = malloc(number_of_volumes * sizeof(int)); - + pre_allocated1 = malloc (number_of_volumes * sizeof (int)); + pre_allocated2 = malloc (number_of_volumes * sizeof (int)); + pre_allocated3 = malloc (number_of_volumes * sizeof (int)); + // Any reason to clear here? - clear_intersection_table(my_intersection_time_table); - + clear_intersection_table (my_intersection_time_table); + time_propagated_without_scattering = 0; - v_length = sqrt(vx*vx+vy*vy+vz*vz); - + v_length = sqrt (vx * vx + vy * vy + vz * vz); + // Initialize logger system / Statistics number_of_scattering_events = 0; - + #ifndef OPENACC - if (inherit_number_of_scattering_events==1) // Continue number of scattering from previous Union_master - number_of_scattering_events = global_master_list_master->elements[this_global_master_index-1].stored_number_of_scattering_events; + if (inherit_number_of_scattering_events == 1) // Continue number of scattering from previous Union_master + number_of_scattering_events = global_master_list_master->elements[this_global_master_index - 1].stored_number_of_scattering_events; #endif - + #ifndef OPENACC // Zero scattered_flag_VP data - for (my_volume_index = 1;my_volume_indexelements[0].component_index == INDEX_CURRENT_COMP) { // If this is the first Union master, clean up logger data for rays that did not make it through Union components - for (log_index=loggers_with_data_array.used_elements-1;log_index>-1;log_index--) { - loggers_with_data_array.logger_pointers[log_index]->function_pointers.clear_temp(&loggers_with_data_array.logger_pointers[log_index]->data_union); + for (log_index = loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { + loggers_with_data_array.logger_pointers[log_index]->function_pointers.clear_temp (&loggers_with_data_array.logger_pointers[log_index]->data_union); } loggers_with_data_array.used_elements = 0; - for (log_index=abs_loggers_with_data_array.used_elements-1;log_index>-1;log_index--) { - abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.clear_temp(&abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); + for (log_index = abs_loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { + abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.clear_temp ( + &abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); } abs_loggers_with_data_array.used_elements = 0; } #endif int tagging_conditional_extend = 0; - for (my_iterator=0;my_iteratorgeometry.within_function(ray_position,&Volumes[mask_volume_index_list.elements[my_iterator]]->geometry) == 1) { + // if(Volumes[mask_volume_index_list.elements[my_iterator]]->geometry.within_function(ray_position,&Volumes[mask_volume_index_list.elements[my_iterator]]->geometry) + // == 1) { // GPU - if (r_within_function(ray_position, &Volumes[mask_volume_index_list.elements[my_iterator]]->geometry) == 1) { + if (r_within_function (ray_position, &Volumes[mask_volume_index_list.elements[my_iterator]]->geometry) == 1) { my_mask_status_list.elements[my_iterator] = 1; } else { my_mask_status_list.elements[my_iterator] = 0; } } - + #ifdef Union_trace_verbal_setting - print_1d_int_list(my_mask_status_list,"Initial mask status list"); + print_1d_int_list (my_mask_status_list, "Initial mask status list"); #endif - + // Now the initial current_volume can be found, which requires the up to date mask_status_list - current_volume = within_which_volume_GPU(ray_position, starting_lists.reduced_start_list, starting_lists.starting_destinations_list, Volumes, &my_mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); - + current_volume = within_which_volume_GPU (ray_position, starting_lists.reduced_start_list, starting_lists.starting_destinations_list, Volumes, + &my_mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); + // Using the mask_status_list and the current volume, the current_mask_intersect_list_status can be made // it contains the effective mask status of all volumes on the current volumes mask intersect list, which needs to be calculated, // but only when the current volume or mask status changes, not under for example scattering inside the current volume - update_current_mask_intersect_status(¤t_mask_intersect_list_status, &my_mask_status_list, Volumes, ¤t_volume); - + update_current_mask_intersect_status (¤t_mask_intersect_list_status, &my_mask_status_list, Volumes, ¤t_volume); + #ifdef Union_trace_verbal_setting - printf("Starting current_volume = %d\n",current_volume); + printf ("Starting current_volume = %d\n", current_volume); #endif - + // Check if the ray appeared in an allowed starting volume, unless this check is disabled by the user for advanced cases if (allow_inside_start == 0 && my_starting_lists.allowed_starting_volume_logic_list.elements[current_volume] == 0) { - printf("ERROR, ray ''teleported'' into Union component %s, if intentional, set allow_inside_start=1\n", NAME_CURRENT_COMP); + printf ("ERROR, ray ''teleported'' into Union component %s, if intentional, set allow_inside_start=1\n", NAME_CURRENT_COMP); #ifndef OPENACC // NEED ERROR FLAG: Need to set an error flag that is read in finally to warn user of problem. - exit(1); + exit (1); #endif } // Warn the user that rays have appeared inside a volume instead of outside as expected if (starting_volume_warning == 0 && current_volume != 0) { - printf("WARNING: Ray started in volume ''%s'' rather than the surrounding vacuum in component %s. This warning is only shown once.\n",Volumes[current_volume]->name,NAME_CURRENT_COMP); - starting_volume_warning = 1; + printf ("WARNING: Ray started in volume ''%s'' rather than the surrounding vacuum in component %s. This warning is only shown once.\n", + Volumes[current_volume]->name, NAME_CURRENT_COMP); + starting_volume_warning = 1; } - + // Placing the new ray at the start of the tagging tree corresponding to current volume // A history limit can be imposed so that no new nodes are created after this limit (may be necessary to fit in memory) // Rays can still follow the nodes created before even when no additional nodes are created, but if a situation that @@ -1132,15 +1197,18 @@ TRACE if (enable_tagging) { current_tagging_node = master_tagging_node_list.elements[current_volume]; stop_tagging_ray = 0; // Allow this ray to be tracked - if (tagging_leaf_counter > history_limit) stop_creating_nodes = 1; + if (tagging_leaf_counter > history_limit) + stop_creating_nodes = 1; } #endif - + #ifdef Union_trace_verbal_setting - if (enable_tagging) printf("current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging) printf("current_tagging_node->number_of_rays = %d \n",current_tagging_node->number_of_rays); + if (enable_tagging) + printf ("current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging) + printf ("current_tagging_node->number_of_rays = %d \n", current_tagging_node->number_of_rays); #endif - + // Propagation loop including scattering // This while loop continues until the ray leaves the ensamble of user defined volumes either through volume 0 // or a dedicated exit volume. The loop is cancelled after a large number of iterations as a failsafe for errors. @@ -1149,199 +1217,233 @@ TRACE int limit = 100000; while (done == 0) { limit--; - + #ifdef Union_trace_verbal_setting - printf("----------- START OF WHILE LOOP --------------------------------------\n"); - print_intersection_table(my_intersection_time_table); - printf("current_volume = %d \n",current_volume); + printf ("----------- START OF WHILE LOOP --------------------------------------\n"); + print_intersection_table (my_intersection_time_table); + printf ("current_volume = %d \n", current_volume); #endif - + // Calculating intersections with the necessary volumes. The relevant set of volumes depend on the current volume and the mask status array. // First the volumes on the current volumes intersect list is checked, then its mask interset list. Before checking the volume itself, it is // checked if any children of the current volume is intersected, in which case the intersection calculation with the current volume can be // skipped. - + // Checking intersections for all volumes in the intersect list. - for (start=check=Volumes[current_volume]->geometry.intersect_check_list.elements;check-startgeometry.intersect_check_list.num_elements;check++) { - // This will leave check as a pointer to the intergers in the intersect_check_list and iccrement nicely + for (start = check = Volumes[current_volume]->geometry.intersect_check_list.elements; + check - start < Volumes[current_volume]->geometry.intersect_check_list.num_elements; check++) { + // This will leave check as a pointer to the intergers in the intersect_check_list and iccrement nicely + #ifdef Union_trace_verbal_setting + printf ("Intersect_list = %d being checked \n", *check); + #endif + + if (my_intersection_time_table->calculated[*check] == 0) { #ifdef Union_trace_verbal_setting - printf("Intersect_list = %d being checked \n",*check); + printf ("running intersection for intersect_list with *check = %d \n", *check); #endif - - if (my_intersection_time_table->calculated[*check] == 0) { - #ifdef Union_trace_verbal_setting - printf("running intersection for intersect_list with *check = %d \n",*check); - #endif - // Calculate intersections using intersect function imbedded in the relevant volume structure using parameters that are also imbedded in the structure. - - // GPU Flexible intersect_function call - geometry_output = intersect_function(my_intersection_time_table->intersection_times[*check], &number_of_solutions, r_start, v, &Volumes[*check]->geometry); - printf("geometry_output=%i, *check=%i, number_of_solutions=%i, r_start=[%g %g %g], v=[%g %g %g]\n",geometry_output, *check, number_of_solutions, r_start[0],r_start[1],r_start[2], v[0], v[1], v[2]); - my_intersection_time_table->calculated[*check] = 1; - } + // Calculate intersections using intersect function imbedded in the relevant volume structure using parameters that are also imbedded in the structure. + + // GPU Flexible intersect_function call + geometry_output + = intersect_function (my_intersection_time_table->intersection_times[*check], &number_of_solutions, r_start, v, &Volumes[*check]->geometry); + printf ("geometry_output=%i, *check=%i, number_of_solutions=%i, r_start=[%g %g %g], v=[%g %g %g]\n", geometry_output, *check, number_of_solutions, + r_start[0], r_start[1], r_start[2], v[0], v[1], v[2]); + my_intersection_time_table->calculated[*check] = 1; + } } - + // Mask update: add additional loop for checking intersections with masked volumes depending on mask statuses - for (mask_iterator=0;mask_iteratorgeometry.mask_intersect_list.num_elements;mask_iterator++) { + for (mask_iterator = 0; mask_iterator < Volumes[current_volume]->geometry.mask_intersect_list.num_elements; mask_iterator++) { if (current_mask_intersect_list_status.elements[mask_iterator] == 1) { // Only check if the mask is active - #ifdef Union_trace_verbal_setting - printf("Mask Intersect_list = %d being checked \n",Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); + #ifdef Union_trace_verbal_setting + printf ("Mask Intersect_list = %d being checked \n", Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); #endif if (my_intersection_time_table->calculated[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]] == 0) { #ifdef Union_trace_verbal_setting - printf("running intersection for mask_intersect_list element = %d \n",Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); + printf ("running intersection for mask_intersect_list element = %d \n", Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]); // printf("r = (%f,%f,%f) v = (%f,%f,%f) \n",r[0],r[1],r[2],v[0],v[1],v[2]); #endif // Calculate intersections using intersect function imbedded in the relevant volume structure using parameters - // that are also imbedded in the structure. + // that are also imbedded in the structure. // CPU Only - //geometry_output = Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry.intersect_function(my_intersection_time_table->intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]],number_of_solutions,r_start,v,&Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry); - + // geometry_output = + // Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry.intersect_function(my_intersection_time_table->intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]],number_of_solutions,r_start,v,&Volumes[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]->geometry); + // GPU allowed int selected_index; selected_index = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; - geometry_output = intersect_function(my_intersection_time_table->intersection_times[selected_index], &number_of_solutions, r_start, v, &Volumes[selected_index]->geometry); - + geometry_output = intersect_function (my_intersection_time_table->intersection_times[selected_index], &number_of_solutions, r_start, v, + &Volumes[selected_index]->geometry); + my_intersection_time_table->calculated[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]] = 1; - printf("succesfully calculated intersection times for volume *check = %d \n",*check); + printf ("succesfully calculated intersection times for volume *check = %d \n", *check); } } } - - // Checking if there are intersections with children of current volume, which means there is an intersection before current_volume, and thus can be skipped. But only if they have not been overwritten. In case current_volume is 0, there is no need to do this regardless. + + // Checking if there are intersections with children of current volume, which means there is an intersection before current_volume, and thus can be skipped. + // But only if they have not been overwritten. In case current_volume is 0, there is no need to do this regardless. if (current_volume != 0 && my_intersection_time_table->calculated[current_volume] == 0) { + #ifdef Union_trace_verbal_setting + printf ("Checking if children of current_volume = %d have intersections. \n", current_volume); + #endif + intersection_with_children = 0; + // for (start = check = Volumes[current_volume]->geometry.direct_children.elements;check - start < + // Volumes[current_volume]->geometry.children.num_elements;check++) { // REVIEW LINE. Caused bug with masks. + for (start = check = Volumes[current_volume]->geometry.children.elements; check - start < Volumes[current_volume]->geometry.children.num_elements; + check++) { #ifdef Union_trace_verbal_setting - printf("Checking if children of current_volume = %d have intersections. \n",current_volume); + printf ("Checking if child %d of current_volume = %d have intersections. \n", *check, current_volume); #endif - intersection_with_children = 0; - //for (start = check = Volumes[current_volume]->geometry.direct_children.elements;check - start < Volumes[current_volume]->geometry.children.num_elements;check++) { // REVIEW LINE. Caused bug with masks. - for (start = check = Volumes[current_volume]->geometry.children.elements;check - start < Volumes[current_volume]->geometry.children.num_elements;check++) { + // Only check the first of the two results in the intersection table, as they are ordered, and the second is of no interest + if (my_intersection_time_table->calculated[*check] == 1 + && my_intersection_time_table->intersection_times[*check][0] > time_propagated_without_scattering) { + // If this child is masked, its mask status need to be 1 in order to be taken into account + if (Volumes[*check]->geometry.is_masked_volume == 0) { #ifdef Union_trace_verbal_setting - printf("Checking if child %d of current_volume = %d have intersections. \n",*check,current_volume); + printf ("Found an child of current_volume with an intersection. Skips calculating for current_volume \n"); #endif - // Only check the first of the two results in the intersection table, as they are ordered, and the second is of no interest - if (my_intersection_time_table->calculated[*check] == 1 && my_intersection_time_table->intersection_times[*check][0] > time_propagated_without_scattering) { - // If this child is masked, its mask status need to be 1 in order to be taken into account - if (Volumes[*check]->geometry.is_masked_volume == 0) { - #ifdef Union_trace_verbal_setting - printf("Found an child of current_volume with an intersection. Skips calculating for current_volume \n"); - #endif + intersection_with_children = 1; + break; // No need to check more, if there is just one it is not necessary to calculate intersection with current_volume yet + } else { + #ifdef Union_trace_verbal_setting + printf ("Found an child of current_volume with an intersection, but it is masked. Check to see if it can skip calculating for current_volume \n"); + #endif + + if (Volumes[*check]->geometry.mask_mode == 2) { // ANY mask mode + tree_next_volume = 0; + for (mask_start = mask_check = Volumes[*check]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start < Volumes[*check]->geometry.masked_by_mask_index_list.num_elements; mask_check++) { + if (my_mask_status_list.elements[*mask_check] == 1) { intersection_with_children = 1; - break; // No need to check more, if there is just one it is not necessary to calculate intersection with current_volume yet - } else { - #ifdef Union_trace_verbal_setting - printf("Found an child of current_volume with an intersection, but it is masked. Check to see if it can skip calculating for current_volume \n"); - #endif - - if (Volumes[*check]->geometry.mask_mode == 2) { // ANY mask mode - tree_next_volume = 0; - for (mask_start=mask_check=Volumes[*check]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.masked_by_mask_index_list.num_elements;mask_check++) { - if (my_mask_status_list.elements[*mask_check] == 1) { - intersection_with_children = 1; - break; - } - } - } else { // ALL mask mode - intersection_with_children = 1; - for (mask_start=mask_check=Volumes[*check]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.masked_by_mask_index_list.num_elements;mask_check++) { - if (my_mask_status_list.elements[*mask_check] == 0) { - intersection_with_children = 0; - break; - } - } - } - #ifdef Union_trace_verbal_setting - printf("The mask status was 1, can actually skip intersection calculation for current volume \n"); - #endif - if (intersection_with_children == 1) break; + break; + } + } + } else { // ALL mask mode + intersection_with_children = 1; + for (mask_start = mask_check = Volumes[*check]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start < Volumes[*check]->geometry.masked_by_mask_index_list.num_elements; mask_check++) { + if (my_mask_status_list.elements[*mask_check] == 0) { + intersection_with_children = 0; + break; } + } } + #ifdef Union_trace_verbal_setting + printf ("The mask status was 1, can actually skip intersection calculation for current volume \n"); + #endif + if (intersection_with_children == 1) + break; + } } - #ifdef Union_trace_verbal_setting - printf("intersection_with_children = %d \n",intersection_with_children); - #endif - if (intersection_with_children == 0) { - // GPU Allowed - geometry_output = intersect_function(my_intersection_time_table->intersection_times[current_volume], &number_of_solutions, r_start, v, &Volumes[current_volume]->geometry); - my_intersection_time_table->calculated[current_volume] = 1; - } + } + #ifdef Union_trace_verbal_setting + printf ("intersection_with_children = %d \n", intersection_with_children); + #endif + if (intersection_with_children == 0) { + // GPU Allowed + geometry_output = intersect_function (my_intersection_time_table->intersection_times[current_volume], &number_of_solutions, r_start, v, + &Volumes[current_volume]->geometry); + my_intersection_time_table->calculated[current_volume] = 1; + } } // At this point, my_intersection_time_table is updated with intersection times of all possible intersections. #ifdef Union_trace_verbal_setting - print_intersection_table(my_intersection_time_table); + print_intersection_table (my_intersection_time_table); #endif - + // Next task is to find the next intersection time. The next intersection must be greater than the time_propagated_without_scattering (0 at start of loop) // Loops are eqvialent to the 3 intersection calculation loops already completed - + // First loop for checking intersect_check_list #ifdef Union_trace_verbal_setting - min_intersection_time=0; - printf("Incoming value of MIN_intersection_time=%g\n",min_intersection_time); + min_intersection_time = 0; + printf ("Incoming value of MIN_intersection_time=%g\n", min_intersection_time); #endif time_found = 0; - for (start=check=Volumes[current_volume]->geometry.intersect_check_list.elements;check-startgeometry.intersect_check_list.num_elements;check++) { - for (solution = 0;solutionn_elements[*check];solution++) { - if (time_found) { - if ((intersection_time = my_intersection_time_table->intersection_times[*check][solution]) > time_propagated_without_scattering && intersection_time < min_intersection_time) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = *check; - #ifdef Union_trace_verbal_setting - printf("found A at %i x %i\n",*check,solution); - #endif - } - } else { - if ((intersection_time = my_intersection_time_table->intersection_times[*check][solution]) > time_propagated_without_scattering) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = *check; - time_found = 1; - #ifdef Union_trace_verbal_setting - printf("found B at %i x %i\n",*check,solution); - #endif - } - } + for (start = check = Volumes[current_volume]->geometry.intersect_check_list.elements; + check - start < Volumes[current_volume]->geometry.intersect_check_list.num_elements; check++) { + for (solution = 0; solution < my_intersection_time_table->n_elements[*check]; solution++) { + if (time_found) { + if ((intersection_time = my_intersection_time_table->intersection_times[*check][solution]) > time_propagated_without_scattering + && intersection_time < min_intersection_time) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = *check; + #ifdef Union_trace_verbal_setting + printf ("found A at %i x %i\n", *check, solution); + #endif + } + } else { + if ((intersection_time = my_intersection_time_table->intersection_times[*check][solution]) > time_propagated_without_scattering) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = *check; + time_found = 1; + #ifdef Union_trace_verbal_setting + printf ("found B at %i x %i\n", *check, solution); + #endif + } } + } } #ifdef Union_trace_verbal_setting - printf("min_intersection_time=%g min_solution=%i\n",min_intersection_time,min_solution); + printf ("min_intersection_time=%g min_solution=%i\n", min_intersection_time, min_solution); #endif // Now check the masked_intersect_list, but only the ones that are currently active - for (mask_iterator=0;mask_iteratorgeometry.mask_intersect_list.num_elements;mask_iterator++) { + for (mask_iterator = 0; mask_iterator < Volumes[current_volume]->geometry.mask_intersect_list.num_elements; mask_iterator++) { if (current_mask_intersect_list_status.elements[mask_iterator] == 1) { - for (solution = 0;solutionn_elements[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]];solution++) { - if (time_found) { - if ((intersection_time = my_intersection_time_table->intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) > time_propagated_without_scattering && intersection_time < min_intersection_time) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; - } - } else { - if ((intersection_time = my_intersection_time_table->intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) > time_propagated_without_scattering) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; - time_found = 1; - } + for (solution = 0; solution < my_intersection_time_table->n_elements[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]]; + solution++) { + if (time_found) { + if ((intersection_time + = my_intersection_time_table->intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) + > time_propagated_without_scattering + && intersection_time < min_intersection_time) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; + } + } else { + if ((intersection_time + = my_intersection_time_table->intersection_times[Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]][solution]) + > time_propagated_without_scattering) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = Volumes[current_volume]->geometry.mask_intersect_list.elements[mask_iterator]; + time_found = 1; } + } } } } - + // And check the current_volume - for (solution = 0;solutionn_elements[current_volume];solution++) { - if (time_found) { - if ((intersection_time = my_intersection_time_table->intersection_times[current_volume][solution]) > time_propagated_without_scattering && intersection_time < min_intersection_time) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = current_volume; - } - } else { - if ((intersection_time = my_intersection_time_table->intersection_times[current_volume][solution]) > time_propagated_without_scattering) { - min_intersection_time = intersection_time;min_solution = solution;min_volume = current_volume; - time_found = 1; - } + for (solution = 0; solution < my_intersection_time_table->n_elements[current_volume]; solution++) { + if (time_found) { + if ((intersection_time = my_intersection_time_table->intersection_times[current_volume][solution]) > time_propagated_without_scattering + && intersection_time < min_intersection_time) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = current_volume; + } + } else { + if ((intersection_time = my_intersection_time_table->intersection_times[current_volume][solution]) > time_propagated_without_scattering) { + min_intersection_time = intersection_time; + min_solution = solution; + min_volume = current_volume; + time_found = 1; } + } } - + #ifdef Union_trace_verbal_setting - printf("min_intersection_time = %f \n",min_intersection_time); - printf("min_solution = %d \n",min_solution); - printf("min_volume = %d \n",min_volume); - printf("time_found = %d \n",time_found); + printf ("min_intersection_time = %f \n", min_intersection_time); + printf ("min_solution = %d \n", min_solution); + printf ("min_volume = %d \n", min_volume); + printf ("time_found = %d \n", time_found); #endif abs_weight_factor = 1.0; @@ -1350,821 +1452,932 @@ TRACE // If a time is found, propagation continues, and it will be checked if a scattering occurs before the next intersection. // If a time is not found, the ray must be leaving the ensamble of volumes and the loop will be concluded if (time_found) { - time_to_boundery = min_intersection_time - time_propagated_without_scattering; // calculate the time remaining before the next intersection - scattering_event = 0; // Assume a scattering event will not occur - - // Check if a scattering event should occur - if (current_volume != 0) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur - if (Volumes[current_volume]->p_physics->number_of_processes == 0) { // If there are no processes, the volume could be vacuum or an absorber - if (Volumes[current_volume]->p_physics->is_vacuum == 0) { - // This volume does not have physical processes but does have an absorption cross section, so the ray weight is reduced accordingly - - my_sum_plus_abs = Volumes[current_volume]->p_physics->my_a*(2200/v_length); - length_to_boundery = time_to_boundery * v_length; - - abs_weight_factor = exp(-Volumes[current_volume]->p_physics->my_a*2200*time_to_boundery); - abs_weight_factor_set = 1; - - #ifdef Union_trace_verbal_setting - printf("name of material: %s \n",Volumes[current_volume]->name); - printf("length to boundery = %f\n",length_to_boundery); - printf("absorption cross section = %f\n",Volumes[current_volume]->p_physics->my_a); - printf("chance to get through this length of absorber: %f \%\n", 100*exp(-Volumes[current_volume]->p_physics->my_a*length_to_boundery)); - #endif - } - } else { - // Since there is a non-zero number of processes in this material, all the scattering cross section for these are calculated - my_sum = 0; k[0] = V2K*vx; k[1] = V2K*vy; k[2] = V2K*vz; p_my_trace = my_trace; wavevector = coords_set(k[0],k[1],k[2]); - //for (process_start = process = Volumes[current_volume]->p_physics->p_scattering_array;process - process_start < Volumes[current_volume]->p_physics->number_of_processes;process++) { - int p_index; - for (p_index=0; p_index < Volumes[current_volume]->p_physics->number_of_processes; p_index++ ){ // GPU - - if (Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index != -1) { - // If the process is not isotropic, the wavevector is transformed into the local coordinate system of the process - wavevector_rotated = rot_apply(Volumes[current_volume]->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index],wavevector); - - coords_get(wavevector_rotated,&k_rotated[0],&k_rotated[1],&k_rotated[2]); + time_to_boundery = min_intersection_time - time_propagated_without_scattering; // calculate the time remaining before the next intersection + scattering_event = 0; // Assume a scattering event will not occur - } else { - k_rotated[0] = k[0]; k_rotated[1] = k[1]; k_rotated[2] = k[2]; - } - - // Find correct focus_data_array index for this volume/process - focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[p_index]; - - // Call the probability for scattering function assighed to this specific procress (the process pointer is updated in the for loop) - process = &Volumes[current_volume]->p_physics->p_scattering_array[p_index]; // GPU Allowed - - int physics_output; - physics_output = physics_my(process->eProcess, p_my_trace, k_rotated, process->data_transfer,&Volumes[current_volume]->geometry.focus_data_array.elements[focus_data_index], _particle); - - my_sum += *p_my_trace; - #ifdef Union_trace_verbal_setting - printf("my_trace = %f, my_sum = %f\n",*p_my_trace,my_sum); - #endif - p_my_trace++; // increment the pointer so that it point to the next element (max number of process in any material is allocated) - } - - #ifdef Union_trace_verbal_setting - printf("time_propagated_without_scattering = %f.\n",time_propagated_without_scattering); - printf("v_length = %f.\n",v_length); - #endif - + // Check if a scattering event should occur + if (current_volume != 0) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur + if (Volumes[current_volume]->p_physics->number_of_processes == 0) { // If there are no processes, the volume could be vacuum or an absorber + if (Volumes[current_volume]->p_physics->is_vacuum == 0) { + // This volume does not have physical processes but does have an absorption cross section, so the ray weight is reduced accordingly + + my_sum_plus_abs = Volumes[current_volume]->p_physics->my_a * (2200 / v_length); length_to_boundery = time_to_boundery * v_length; - + + abs_weight_factor = exp (-Volumes[current_volume]->p_physics->my_a * 2200 * time_to_boundery); + abs_weight_factor_set = 1; + #ifdef Union_trace_verbal_setting - printf("exp(- length_to_boundery*my_sum) = %f. length_to_boundery = %f. my_sum = %f.\n",exp(-length_to_boundery*my_sum),length_to_boundery,my_sum); + printf ("name of material: %s \n", Volumes[current_volume]->name); + printf ("length to boundery = %f\n", length_to_boundery); + printf ("absorption cross section = %f\n", Volumes[current_volume]->p_physics->my_a); + printf ("chance to get through this length of absorber: %f \%\n", 100 * exp (-Volumes[current_volume]->p_physics->my_a * length_to_boundery)); #endif - - // Selecting if a scattering takes place, and what scattering process. - // This section have too many if statements, and unessecary calculations - // Could make seperate functions for p_interact on/off and interact_fraction on/off, - // and set function pointers to these in initialize, thus avoiding many unessecary if statements and calculations of x/x. - - my_sum_plus_abs = my_sum + Volumes[current_volume]->p_physics->my_a*(2200/v_length); - - if (my_sum < 1E-18) { - // The scattering cross section is basicly zero, no scattering should occur. - scattering_event = 0; - abs_weight_factor = exp(-length_to_boundery*my_sum_plus_abs); // Correct for absorption and the almost zero scattering - abs_weight_factor_set = 1; - } else if (length_to_boundery < safty_distance2) { - // Too close to boundery to safly make another scattering, attenuate - scattering_event = 0; - abs_weight_factor = exp(-length_to_boundery*my_sum_plus_abs); // Attentuate the beam for the small distance - + } + } else { + // Since there is a non-zero number of processes in this material, all the scattering cross section for these are calculated + my_sum = 0; + k[0] = V2K * vx; + k[1] = V2K * vy; + k[2] = V2K * vz; + p_my_trace = my_trace; + wavevector = coords_set (k[0], k[1], k[2]); + // for (process_start = process = Volumes[current_volume]->p_physics->p_scattering_array;process - process_start < + // Volumes[current_volume]->p_physics->number_of_processes;process++) { + int p_index; + for (p_index = 0; p_index < Volumes[current_volume]->p_physics->number_of_processes; p_index++) { // GPU + + if (Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index != -1) { + // If the process is not isotropic, the wavevector is transformed into the local coordinate system of the process + wavevector_rotated + = rot_apply (Volumes[current_volume] + ->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[p_index].non_isotropic_rot_index], + wavevector); + + coords_get (wavevector_rotated, &k_rotated[0], &k_rotated[1], &k_rotated[2]); + } else { - // The scattering cross section is above zero and the distance to the boundery is sufficient for a scattering - if (Volumes[current_volume]->geometry.geometry_p_interact != 0) { - // a fraction of the beam (geometry_p_interact) is forced to scatter - real_transmission_probability = exp(-length_to_boundery*my_sum_plus_abs); - mc_transmission_probability = (1.0 - Volumes[current_volume]->geometry.geometry_p_interact); - if ((scattering_event = (rand01() > mc_transmission_probability))) { - // Scattering event happens, this is the correction for the weight - p *= (1.0-real_transmission_probability)/(1.0-mc_transmission_probability); // Absorption simulated in weight - - // Find length to next scattering knowing the ray will scatter. - length_to_scattering = safty_distance -log(1.0 - rand0max((1.0 - exp(-my_sum_plus_abs*(length_to_boundery-safty_distance2))))) / my_sum_plus_abs; - } else { - // Scattering event does not happen, this is the appropriate correction - p *= real_transmission_probability/mc_transmission_probability; // Absorption simulated in weight - - } - } else { - // probability to scatter is the natural value - if(my_sum*length_to_boundery < 1e-6) { // Scattering probability very small, linear method is used as exponential is unreliable - if (length_to_boundery > safty_distance2) { - if (rand01() < exp(-length_to_boundery*my_sum_plus_abs)) { - // Scattering happens, use linear description to select scattering position - length_to_scattering = safty_distance + rand0max(length_to_boundery - safty_distance2); - // Weight factor necessary to correct for using the linear scattering position distribution - abs_weight_factor = length_to_boundery*my_sum*exp(-length_to_scattering*my_sum_plus_abs); // Absorption simulated in weight - abs_weight_factor_set = 1; - - scattering_event = 1; - } else scattering_event = 0; - } else { - // The distance is too short to reliably make a scattering event (in comparison to accuraccy of intersect functions) - abs_weight_factor = exp(-length_to_boundery*my_sum_plus_abs); // Attentuate the beam for the small distance - scattering_event = 0; - } - } else { - // Strong scattering, use exponential description to select scattering position between safetydistance and infinity - length_to_scattering = safty_distance -log(1 - rand01() ) / my_sum_plus_abs; - // Scattering happens if the scattering position is before the boundery (and safty distance) - if (length_to_scattering < length_to_boundery - safty_distance) scattering_event = 1; - else scattering_event = 0; - } - } - - if (scattering_event == 1) { - // Adjust weight for absorption - abs_weight_factor *= my_sum/my_sum_plus_abs; - abs_weight_factor_set = 1; - // Safety feature, alert in case of nonsense my results / negative absorption - if (my_sum/my_sum_plus_abs > 1.0) printf("WARNING: Absorption weight factor above 1! Should not happen! \n"); - // Select process - if (Volumes[current_volume]->p_physics->number_of_processes == 1) { // trivial case - // Select the only available process, which will always have index 0 - selected_process = 0; - } else { - if (Volumes[current_volume]->p_physics->interact_control == 1) { - // Interact_fraction is used to influence the choice of process in this material - mc_prop = rand01();culmative_probability=0;total_process_interact=1.0; - - // If any of the processes have probability 0, they are excluded from the selection - for (iterator = 0;iterator < Volumes[current_volume]->p_physics->number_of_processes;iterator++) { - if (my_trace[iterator] < 1E-18) { - // When this happens, the total force probability is corrected and the probability for this particular instance is set to 0 - total_process_interact -= Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; - my_trace_fraction_control[iterator] = 0; - // In cases where my_trace is not zero, the forced fraction is still used. - } else my_trace_fraction_control[iterator] = Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; - } - // Randomly select a process using the weights stored in my_trace_fraction_control divided by total_process_interact - for (iterator = 0;iterator < Volumes[current_volume]->p_physics->number_of_processes;iterator++) { - culmative_probability += my_trace_fraction_control[iterator]/total_process_interact; - if (culmative_probability > mc_prop) { - selected_process = iterator; - p *= (my_trace[iterator]/my_sum)*(total_process_interact/my_trace_fraction_control[iterator]); - break; - } - } - - } else { - // Select a process based on their relative attenuations factors - mc_prop = rand01();culmative_probability=0; - for (iterator = 0;iterator < Volumes[current_volume]->p_physics->number_of_processes;iterator++) { - culmative_probability += my_trace[iterator]/my_sum; - if (culmative_probability > mc_prop) { - selected_process = iterator; - break; - } - } - } - } - } // end of select process - } - - } - - } // Done checking for scttering event and in case of scattering selecting a process - - // Record initial weight, absorption weight factor and initial position - - initial_weight = p; - r_old[0] = r[0]; r_old[1] = r[1]; r_old[2] = r[2]; time_old = t; - // Apply absorption - p *= abs_weight_factor; - - // Create event for absorption loggers - // Need to use start position and length travelled to sample that trajectory for absorption event. Could do several, here just one. - - // min length: 0, max length: length_to_scattering if scattering, else length to boundary - - // Avoid logging absorption when the ray is in vacuum. - #ifndef OPENACC - if (current_volume != 0 && abs_weight_factor_set == 1) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur - if (Volumes[current_volume]->p_physics->is_vacuum == 0) { // No absorption in vacuum - - if (scattering_event == 1) { - // When scattering events occur, place the absoprtion the same place (the total cross section is used to place it) - abs_distance = length_to_scattering; - } else { - // When the ray exits a volume, the absorption position should be exponentially distributed using the total cross section - my_abs = Volumes[current_volume]->p_physics->my_a*(2200/v_length); - abs_distance = -log(1.0 - rand0max(1.0 - exp(-my_sum_plus_abs*length_to_boundery)) ) / my_sum_plus_abs; + k_rotated[0] = k[0]; + k_rotated[1] = k[1]; + k_rotated[2] = k[2]; } - t_abs_propagation = abs_distance/v_length; + // Find correct focus_data_array index for this volume/process + focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[p_index]; - abs_position = coords_set(x + t_abs_propagation*vx, y + t_abs_propagation*vy, z + t_abs_propagation*vz); - - // This info needs to be loaded into the absorption loggers - - // Need to run through relevant absorption loggers here - #ifdef Union_trace_verbal_setting - printf("Running abs_logger system for specific volumes \n"); - #endif - - // Logging for detector components assosiated with this volume - for (log_index=0;log_indexabs_loggers.num_elements;log_index++) { - // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers - transformed_abs_position = coords_sub(abs_position, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->position); - transformed_abs_position = rot_apply(Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->rotation, transformed_abs_position); - - // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis - Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->function_pointers.active_record_function(&transformed_abs_position, k_new, initial_weight*(1.0-abs_weight_factor), t + t_abs_propagation, scattered_flag[current_volume], number_of_scattering_events, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index], &abs_loggers_with_data_array); - // If the logging component have a conditional attatched, the collected data will be written to a temporary place - // At the end of the rays life, it will be checked if the condition is met - // if it is met, the temporary data is transfered to permanent, and temp is cleared. - // if it is not met, the temporary data is cleared. - } - + // Call the probability for scattering function assighed to this specific procress (the process pointer is updated in the for loop) + process = &Volumes[current_volume]->p_physics->p_scattering_array[p_index]; // GPU Allowed + + int physics_output; + physics_output = physics_my (process->eProcess, p_my_trace, k_rotated, process->data_transfer, + &Volumes[current_volume]->geometry.focus_data_array.elements[focus_data_index], _particle); + + my_sum += *p_my_trace; #ifdef Union_trace_verbal_setting - printf("Running abs_logger system for all volumes \n"); + printf ("my_trace = %f, my_sum = %f\n", *p_my_trace, my_sum); #endif - for (log_index=0;log_indexnum_elements;log_index++) { - // As above, but on a global scale, meaning scattering in all volumes are logged - - // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components general. - // Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). Weird but not meaningless. - - // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers - transformed_abs_position = coords_sub(abs_position, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->position); - transformed_abs_position = rot_apply(global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->rotation, transformed_abs_position); - - // Above version includes scattered_flag_VP, but selected_process may be undefined at this point. - global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->function_pointers.active_record_function(&transformed_abs_position, k_new, initial_weight*(1.0-abs_weight_factor), t+t_abs_propagation, scattered_flag[current_volume], number_of_scattering_events, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger, &abs_loggers_with_data_array); - } + p_my_trace++; // increment the pointer so that it point to the next element (max number of process in any material is allocated) } - } - #endif - - if (scattering_event == 1) { - #ifdef Union_trace_verbal_setting - printf("SCATTERING EVENT \n"); - printf("current_volume = %d \n", current_volume); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n", r[0], r[1], r[2], v[0], v[1], v[2]); - #endif - - // Calculate the time to scattering - time_to_scattering = length_to_scattering/v_length; - - #ifdef Union_trace_verbal_setting - printf("time to scattering = %2.20f \n",time_to_scattering); - printf("length to boundery = %f, length to scattering = %f \n",length_to_boundery,length_to_scattering); - #endif - - // May be replace by version without gravity - //PROP_DT(time_to_scattering); - - // Reduce the double book keeping done here - x += time_to_scattering*vx; y += time_to_scattering*vy; z += time_to_scattering*vz; t += time_to_scattering; - r_start[0] = x; r_start[1] = y; r_start[2] = z; - r[0] = x; r[1] = y; r[2] = z; - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - - // Safe check that should be unecessary. Used to fine tune how close to the edge of a volume a scattering event is allowed to take place (1E-14 m away currently). - if (r_within_function(ray_position, &Volumes[current_volume]->geometry) == 0) { - printf("\nERROR, propagated out of current volume instead of to a point within!\n"); - printf("length_to_scattering_specified = %2.20f\n length propagated = %2.20f\n length_to_boundery = %2.20f \n current_position = (%lf,%lf,%lf) \n",length_to_scattering,sqrt(time_to_scattering*time_to_scattering*vx*vx+time_to_scattering*time_to_scattering*vy*vy+time_to_scattering*time_to_scattering*vz*vz),length_to_boundery,x,y,z); - - my_volume_index = within_which_volume_GPU(ray_position,my_starting_lists.reduced_start_list,my_starting_lists.starting_destinations_list,Volumes,&my_mask_status_list,number_of_volumes,pre_allocated1,pre_allocated2,pre_allocated3); - - printf("Debug info: Volumes[current_volume]->name = %s, but now inside volume number %d named %s.\n",Volumes[current_volume]->name,my_volume_index,Volumes[my_volume_index]->name); - printf("Ray absorbed \n"); - ABSORB; - } - - // Save information before scattering event needed in logging section - p_old = p; - k_old[0] = k[0];k_old[1] = k[1];k_old[2] = k[2]; - - // Find correct focus_data_array index for this volume/process - focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[selected_process]; - - // Rotation to local process coordinate system (for non isotropic processes) - if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { - ray_velocity_rotated = rot_apply(Volumes[current_volume]->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index],ray_velocity); - } else { - ray_velocity_rotated = ray_velocity; - } - #ifdef Union_trace_verbal_setting - printf("Kin: %g %g %g, selected_process: %i %i\n",k[0],k[1],k[2],selected_process,current_volume); - coords_print(Volumes[current_volume]->geometry.focus_data_array.elements[0].Aim); - #endif - // test_physics_scattering(double *k_final, double *k_initial, union data_transfer_union data_transfer) { - coords_get(coords_scalar_mult(ray_velocity_rotated,V2K), &k[0], &k[1], &k[2]); - - // I may replace a intial and final k with one instance that serves as both input and output - process = &Volumes[current_volume]->p_physics->p_scattering_array[selected_process]; // CPU Only - if (0 == physics_scattering(process->eProcess, k_new, k, &p, process->data_transfer, &Volumes[current_volume]->geometry.focus_data_array.elements[0], _particle)) { - /* - // PowderN and Single_crystal requires the option of absorbing the neutron, which is weird. If there is a scattering probability, there should be a new direction. - // It can arise from need to simplify sampling process and end up in cases where weight factor is 0, and the ray should be absorbed in these cases - printf("ERROR: Union_master: %s.Absorbed ray because scattering function returned 0 (error/absorb)\n",NAME_CURRENT_COMP); - component_error_msg++; - if (component_error_msg > 100) { - printf("To many errors encountered, exiting. \n"); - exit(1); + + #ifdef Union_trace_verbal_setting + printf ("time_propagated_without_scattering = %f.\n", time_propagated_without_scattering); + printf ("v_length = %f.\n", v_length); + #endif + + length_to_boundery = time_to_boundery * v_length; + + #ifdef Union_trace_verbal_setting + printf ("exp(- length_to_boundery*my_sum) = %f. length_to_boundery = %f. my_sum = %f.\n", exp (-length_to_boundery * my_sum), length_to_boundery, + my_sum); + #endif + + // Selecting if a scattering takes place, and what scattering process. + // This section have too many if statements, and unessecary calculations + // Could make seperate functions for p_interact on/off and interact_fraction on/off, + // and set function pointers to these in initialize, thus avoiding many unessecary if statements and calculations of x/x. + + my_sum_plus_abs = my_sum + Volumes[current_volume]->p_physics->my_a * (2200 / v_length); + + if (my_sum < 1E-18) { + // The scattering cross section is basicly zero, no scattering should occur. + scattering_event = 0; + abs_weight_factor = exp (-length_to_boundery * my_sum_plus_abs); // Correct for absorption and the almost zero scattering + abs_weight_factor_set = 1; + } else if (length_to_boundery < safty_distance2) { + // Too close to boundery to safly make another scattering, attenuate + scattering_event = 0; + abs_weight_factor = exp (-length_to_boundery * my_sum_plus_abs); // Attentuate the beam for the small distance + + } else { + // The scattering cross section is above zero and the distance to the boundery is sufficient for a scattering + if (Volumes[current_volume]->geometry.geometry_p_interact != 0) { + // a fraction of the beam (geometry_p_interact) is forced to scatter + real_transmission_probability = exp (-length_to_boundery * my_sum_plus_abs); + mc_transmission_probability = (1.0 - Volumes[current_volume]->geometry.geometry_p_interact); + if ((scattering_event = (rand01 () > mc_transmission_probability))) { + // Scattering event happens, this is the correction for the weight + p *= (1.0 - real_transmission_probability) / (1.0 - mc_transmission_probability); // Absorption simulated in weight + + // Find length to next scattering knowing the ray will scatter. + length_to_scattering + = safty_distance - log (1.0 - rand0max ((1.0 - exp (-my_sum_plus_abs * (length_to_boundery - safty_distance2))))) / my_sum_plus_abs; + } else { + // Scattering event does not happen, this is the appropriate correction + p *= real_transmission_probability / mc_transmission_probability; // Absorption simulated in weight } - */ - ABSORB; - } - #ifdef Union_trace_verbal_setting - printf("Kout: %g %g %g\n", k_new[0],k_new[1],k_new[2]); - #endif - // Update velocity using k - ray_velocity_rotated = coords_set(K2V*k_new[0],K2V*k_new[1],K2V*k_new[2]); - - // Transformation back to main coordinate system (maybe one should only do this when multiple scattering in that volume was over, especially if there is only one non isotropic frame) - if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { - ray_velocity_final = rot_apply(Volumes[current_volume]->geometry.transpose_process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index],ray_velocity_rotated); } else { - ray_velocity_final = ray_velocity_rotated; - } - #ifdef Union_trace_verbal_setting - printf("Final velocity vector "); coords_print(ray_velocity_final); - #endif - // Write velocity to global variable (temp, only really necessary at final) - coords_get(ray_velocity_final, &vx, &vy, &vz); - - // Write velocity in array format as it is still used by intersect functions (temp, they need to be updated to ray_position / ray_velocity) - v[0] = vx; v[1] = vy; v[2] = vz; - v_length = sqrt(vx*vx+vy*vy+vz*vz); - k_new[0] = V2K*vx; k_new[1] = V2K*vy; k_new[2] = V2K*vz; - if (verbal) if (v_length < 1) printf("velocity set to less than 1\n"); - - #ifdef Union_trace_verbal_setting - printf("Running logger system for specific volumes \n"); - #endif - // Logging for detector components assosiated with this volume - #ifndef OPENACC - for (log_index=0;log_indexloggers.num_elements;log_index++) { - if (Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process] != NULL) { - // Technically the scattering function could edit k, the wavevector before the scattering, even though there would be little point to doing that. - // Could save a secure copy and pass that instead to be certain that no scattering process accidently tampers with the logging. - - // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis - Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process]->function_pointers.active_record_function(&ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], number_of_scattering_events, Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process], &loggers_with_data_array); - // If the logging component have a conditional attatched, the collected data will be written to a temporary place - // At the end of the rays life, it will be checked if the condition is met - // if it is met, the temporary data is transfered to permanent, and temp is cleared. - // if it is not met, the temporary data is cleared. + // probability to scatter is the natural value + if (my_sum * length_to_boundery < 1e-6) { // Scattering probability very small, linear method is used as exponential is unreliable + if (length_to_boundery > safty_distance2) { + if (rand01 () < exp (-length_to_boundery * my_sum_plus_abs)) { + // Scattering happens, use linear description to select scattering position + length_to_scattering = safty_distance + rand0max (length_to_boundery - safty_distance2); + // Weight factor necessary to correct for using the linear scattering position distribution + abs_weight_factor = length_to_boundery * my_sum * exp (-length_to_scattering * my_sum_plus_abs); // Absorption simulated in weight + abs_weight_factor_set = 1; + + scattering_event = 1; + } else + scattering_event = 0; + } else { + // The distance is too short to reliably make a scattering event (in comparison to accuraccy of intersect functions) + abs_weight_factor = exp (-length_to_boundery * my_sum_plus_abs); // Attentuate the beam for the small distance + scattering_event = 0; + } + } else { + // Strong scattering, use exponential description to select scattering position between safetydistance and infinity + length_to_scattering = safty_distance - log (1 - rand01 ()) / my_sum_plus_abs; + // Scattering happens if the scattering position is before the boundery (and safty distance) + if (length_to_scattering < length_to_boundery - safty_distance) + scattering_event = 1; + else + scattering_event = 0; } } - #endif - + + if (scattering_event == 1) { + // Adjust weight for absorption + abs_weight_factor *= my_sum / my_sum_plus_abs; + abs_weight_factor_set = 1; + // Safety feature, alert in case of nonsense my results / negative absorption + if (my_sum / my_sum_plus_abs > 1.0) + printf ("WARNING: Absorption weight factor above 1! Should not happen! \n"); + // Select process + if (Volumes[current_volume]->p_physics->number_of_processes == 1) { // trivial case + // Select the only available process, which will always have index 0 + selected_process = 0; + } else { + if (Volumes[current_volume]->p_physics->interact_control == 1) { + // Interact_fraction is used to influence the choice of process in this material + mc_prop = rand01 (); + culmative_probability = 0; + total_process_interact = 1.0; + + // If any of the processes have probability 0, they are excluded from the selection + for (iterator = 0; iterator < Volumes[current_volume]->p_physics->number_of_processes; iterator++) { + if (my_trace[iterator] < 1E-18) { + // When this happens, the total force probability is corrected and the probability for this particular instance is set to 0 + total_process_interact -= Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; + my_trace_fraction_control[iterator] = 0; + // In cases where my_trace is not zero, the forced fraction is still used. + } else + my_trace_fraction_control[iterator] = Volumes[current_volume]->p_physics->p_scattering_array[iterator].process_p_interact; + } + // Randomly select a process using the weights stored in my_trace_fraction_control divided by total_process_interact + for (iterator = 0; iterator < Volumes[current_volume]->p_physics->number_of_processes; iterator++) { + culmative_probability += my_trace_fraction_control[iterator] / total_process_interact; + if (culmative_probability > mc_prop) { + selected_process = iterator; + p *= (my_trace[iterator] / my_sum) * (total_process_interact / my_trace_fraction_control[iterator]); + break; + } + } + + } else { + // Select a process based on their relative attenuations factors + mc_prop = rand01 (); + culmative_probability = 0; + for (iterator = 0; iterator < Volumes[current_volume]->p_physics->number_of_processes; iterator++) { + culmative_probability += my_trace[iterator] / my_sum; + if (culmative_probability > mc_prop) { + selected_process = iterator; + break; + } + } + } + } + } // end of select process + } + } + + } // Done checking for scttering event and in case of scattering selecting a process + + // Record initial weight, absorption weight factor and initial position + + initial_weight = p; + r_old[0] = r[0]; + r_old[1] = r[1]; + r_old[2] = r[2]; + time_old = t; + // Apply absorption + p *= abs_weight_factor; + + // Create event for absorption loggers + // Need to use start position and length travelled to sample that trajectory for absorption event. Could do several, here just one. + + // min length: 0, max length: length_to_scattering if scattering, else length to boundary + + // Avoid logging absorption when the ray is in vacuum. + #ifndef OPENACC + if (current_volume != 0 && abs_weight_factor_set == 1) { // Volume 0 is always vacuum, and if this is the current volume, an event will not occur + if (Volumes[current_volume]->p_physics->is_vacuum == 0) { // No absorption in vacuum + + if (scattering_event == 1) { + // When scattering events occur, place the absoprtion the same place (the total cross section is used to place it) + abs_distance = length_to_scattering; + } else { + // When the ray exits a volume, the absorption position should be exponentially distributed using the total cross section + my_abs = Volumes[current_volume]->p_physics->my_a * (2200 / v_length); + abs_distance = -log (1.0 - rand0max (1.0 - exp (-my_sum_plus_abs * length_to_boundery))) / my_sum_plus_abs; + } + + t_abs_propagation = abs_distance / v_length; + + abs_position = coords_set (x + t_abs_propagation * vx, y + t_abs_propagation * vy, z + t_abs_propagation * vz); + + // This info needs to be loaded into the absorption loggers + + // Need to run through relevant absorption loggers here + #ifdef Union_trace_verbal_setting + printf ("Running abs_logger system for specific volumes \n"); + #endif + + // Logging for detector components assosiated with this volume + for (log_index = 0; log_index < Volumes[current_volume]->abs_loggers.num_elements; log_index++) { + // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers + transformed_abs_position = coords_sub (abs_position, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->position); + transformed_abs_position = rot_apply (Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->rotation, transformed_abs_position); + + // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis + Volumes[current_volume]->abs_loggers.p_abs_logger[log_index]->function_pointers.active_record_function ( + &transformed_abs_position, k_new, initial_weight * (1.0 - abs_weight_factor), t + t_abs_propagation, scattered_flag[current_volume], + number_of_scattering_events, Volumes[current_volume]->abs_loggers.p_abs_logger[log_index], &abs_loggers_with_data_array); + // If the logging component have a conditional attatched, the collected data will be written to a temporary place + // At the end of the rays life, it will be checked if the condition is met + // if it is met, the temporary data is transfered to permanent, and temp is cleared. + // if it is not met, the temporary data is cleared. + } + + #ifdef Union_trace_verbal_setting + printf ("Running abs_logger system for all volumes \n"); + #endif + for (log_index = 0; log_index < global_all_volume_abs_logger_list_master->num_elements; log_index++) { + // As above, but on a global scale, meaning scattering in all volumes are logged + + // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components + // general. Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). + // Weird but not meaningless. + + // Make transformation according to the individual position of the abs_logger? This would require position / rotation for all abs_loggers + transformed_abs_position = coords_sub (abs_position, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->position); + transformed_abs_position = rot_apply (global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->rotation, transformed_abs_position); + + // Above version includes scattered_flag_VP, but selected_process may be undefined at this point. + global_all_volume_abs_logger_list_master->elements[log_index].abs_logger->function_pointers.active_record_function ( + &transformed_abs_position, k_new, initial_weight * (1.0 - abs_weight_factor), t + t_abs_propagation, scattered_flag[current_volume], + number_of_scattering_events, global_all_volume_abs_logger_list_master->elements[log_index].abs_logger, &abs_loggers_with_data_array); + } + } + } + #endif + + if (scattering_event == 1) { + #ifdef Union_trace_verbal_setting + printf ("SCATTERING EVENT \n"); + printf ("current_volume = %d \n", current_volume); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", r[0], r[1], r[2], v[0], v[1], v[2]); + #endif + + // Calculate the time to scattering + time_to_scattering = length_to_scattering / v_length; + + #ifdef Union_trace_verbal_setting + printf ("time to scattering = %2.20f \n", time_to_scattering); + printf ("length to boundery = %f, length to scattering = %f \n", length_to_boundery, length_to_scattering); + #endif + + // May be replace by version without gravity + // PROP_DT(time_to_scattering); + + // Reduce the double book keeping done here + x += time_to_scattering * vx; + y += time_to_scattering * vy; + z += time_to_scattering * vz; + t += time_to_scattering; + r_start[0] = x; + r_start[1] = y; + r_start[2] = z; + r[0] = x; + r[1] = y; + r[2] = z; + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + + // Safe check that should be unecessary. Used to fine tune how close to the edge of a volume a scattering event is allowed to take place (1E-14 m away + // currently). + if (r_within_function (ray_position, &Volumes[current_volume]->geometry) == 0) { + printf ("\nERROR, propagated out of current volume instead of to a point within!\n"); + printf ("length_to_scattering_specified = %2.20f\n length propagated = %2.20f\n length_to_boundery = %2.20f \n " + "current_position = (%lf,%lf,%lf) \n", + length_to_scattering, + sqrt (time_to_scattering * time_to_scattering * vx * vx + time_to_scattering * time_to_scattering * vy * vy + + time_to_scattering * time_to_scattering * vz * vz), + length_to_boundery, x, y, z); + + my_volume_index = within_which_volume_GPU (ray_position, my_starting_lists.reduced_start_list, my_starting_lists.starting_destinations_list, Volumes, + &my_mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); + + printf ("Debug info: Volumes[current_volume]->name = %s, but now inside volume number %d named %s.\n", Volumes[current_volume]->name, my_volume_index, + Volumes[my_volume_index]->name); + printf ("Ray absorbed \n"); + ABSORB; + } + + // Save information before scattering event needed in logging section + p_old = p; + k_old[0] = k[0]; + k_old[1] = k[1]; + k_old[2] = k[2]; + + // Find correct focus_data_array index for this volume/process + focus_data_index = Volumes[current_volume]->geometry.focus_array_indices.elements[selected_process]; + + // Rotation to local process coordinate system (for non isotropic processes) + if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { + ray_velocity_rotated = rot_apply ( + Volumes[current_volume] + ->geometry.process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index], + ray_velocity); + } else { + ray_velocity_rotated = ray_velocity; + } + #ifdef Union_trace_verbal_setting + printf ("Kin: %g %g %g, selected_process: %i %i\n", k[0], k[1], k[2], selected_process, current_volume); + coords_print (Volumes[current_volume]->geometry.focus_data_array.elements[0].Aim); + #endif + // test_physics_scattering(double *k_final, double *k_initial, union data_transfer_union data_transfer) { + coords_get (coords_scalar_mult (ray_velocity_rotated, V2K), &k[0], &k[1], &k[2]); + + // I may replace a intial and final k with one instance that serves as both input and output + process = &Volumes[current_volume]->p_physics->p_scattering_array[selected_process]; // CPU Only + if (0 + == physics_scattering (process->eProcess, k_new, k, &p, process->data_transfer, &Volumes[current_volume]->geometry.focus_data_array.elements[0], + _particle)) { + /* + // PowderN and Single_crystal requires the option of absorbing the neutron, which is weird. If there is a scattering probability, there should be a new + direction. + // It can arise from need to simplify sampling process and end up in cases where weight factor is 0, and the ray should be absorbed in these cases + printf("ERROR: Union_master: %s.Absorbed ray because scattering function returned 0 (error/absorb)\n",NAME_CURRENT_COMP); + component_error_msg++; + if (component_error_msg > 100) { + printf("To many errors encountered, exiting. \n"); + exit(1); + } + */ + ABSORB; + } + #ifdef Union_trace_verbal_setting + printf ("Kout: %g %g %g\n", k_new[0], k_new[1], k_new[2]); + #endif + // Update velocity using k + ray_velocity_rotated = coords_set (K2V * k_new[0], K2V * k_new[1], K2V * k_new[2]); + + // Transformation back to main coordinate system (maybe one should only do this when multiple scattering in that volume was over, especially if there is + // only one non isotropic frame) + if (Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index != -1) { + ray_velocity_final = rot_apply ( + Volumes[current_volume] + ->geometry.transpose_process_rot_matrix_array[Volumes[current_volume]->p_physics->p_scattering_array[selected_process].non_isotropic_rot_index], + ray_velocity_rotated); + } else { + ray_velocity_final = ray_velocity_rotated; + } + #ifdef Union_trace_verbal_setting + printf ("Final velocity vector "); + coords_print (ray_velocity_final); + #endif + // Write velocity to global variable (temp, only really necessary at final) + coords_get (ray_velocity_final, &vx, &vy, &vz); + + // Write velocity in array format as it is still used by intersect functions (temp, they need to be updated to ray_position / ray_velocity) + v[0] = vx; + v[1] = vy; + v[2] = vz; + v_length = sqrt (vx * vx + vy * vy + vz * vz); + k_new[0] = V2K * vx; + k_new[1] = V2K * vy; + k_new[2] = V2K * vz; + if (verbal) + if (v_length < 1) + printf ("velocity set to less than 1\n"); + + #ifdef Union_trace_verbal_setting + printf ("Running logger system for specific volumes \n"); + #endif + // Logging for detector components assosiated with this volume + #ifndef OPENACC + for (log_index = 0; log_index < Volumes[current_volume]->loggers.num_elements; log_index++) { + if (Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process] != NULL) { + // Technically the scattering function could edit k, the wavevector before the scattering, even though there would be little point to doing that. + // Could save a secure copy and pass that instead to be certain that no scattering process accidently tampers with the logging. + + // This function calls a logger function which in turn stores some data among the passed, and possibly performs some basic data analysis + Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process]->function_pointers.active_record_function ( + &ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], + number_of_scattering_events, Volumes[current_volume]->loggers.p_logger_volume[log_index].p_logger_process[selected_process], + &loggers_with_data_array); + // If the logging component have a conditional attatched, the collected data will be written to a temporary place + // At the end of the rays life, it will be checked if the condition is met + // if it is met, the temporary data is transfered to permanent, and temp is cleared. + // if it is not met, the temporary data is cleared. + } + } + #endif + + #ifdef Union_trace_verbal_setting + printf ("Running logger system for all volumes \n"); + #endif + #ifndef OPENACC + for (log_index = 0; log_index < global_all_volume_logger_list_master->num_elements; log_index++) { + // As above, but on a global scale, meaning scattering in all volumes are logged + + // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components + // general. Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). + // Weird but not meaningless. + global_all_volume_logger_list_master->elements[log_index].logger->function_pointers.active_record_function ( + &ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], + number_of_scattering_events, global_all_volume_logger_list_master->elements[log_index].logger, &loggers_with_data_array); + } + #endif + #ifdef Union_trace_verbal_setting + printf ("Outgoing event: %g %g %g // %g %g %g\n", x, y, z, vx, vy, vz); + #endif + SCATTER; + #ifndef OPENACC + ++number_of_scattering_events; + ++scattered_flag[current_volume]; + ++scattered_flag_VP[current_volume][selected_process]; + #endif + + // Clear intersection time lists as the direction of the ray has changed + clear_intersection_table (my_intersection_time_table); + time_propagated_without_scattering = 0.0; + #ifdef Union_trace_verbal_setting + printf ("SCATTERED SUCSSESFULLY \n"); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new process node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + #endif + + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node = goto_process_node (current_tagging_node, selected_process, Volumes[current_volume], &stop_tagging_ray, stop_creating_nodes); + #endif + #ifdef Union_trace_verbal_setting + + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new process node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + #endif + + } else { + #ifdef Union_trace_verbal_setting + printf ("Propagate out of volume %d\n", current_volume); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + #endif + // Propagate neutron to found minimum time + // PROP_DT(time_to_boundery); + x += time_to_boundery * vx; + y += time_to_boundery * vy; + z += time_to_boundery * vz; + t += time_to_boundery; + r[0] = x; + r[1] = y; + r[2] = z; + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + + time_propagated_without_scattering = min_intersection_time; + SCATTER; // For debugging purposes + #ifdef Union_trace_verbal_setting + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + #endif + // Remove this entry from the my_intersection_time_table + my_intersection_time_table->intersection_times[min_volume][min_solution] = -1; + + // Use destination list for corresponding intersection entry n,i) to find next volume + #ifdef Union_trace_verbal_setting + printf ("PROPAGATION FROM VOLUME %d \n", current_volume); + #endif + if (min_volume == current_volume) { + #ifdef Union_trace_verbal_setting + printf ("min_volume == current_volume \n"); + #endif + // List approach to finding the next volume. + // When the ray intersects the current volume, the next volume must be on the destination list of the current volume + // However, the reduced_destination_list can be investigated first, and depending on the results, the + // direct children of the volumes on the reduced destination list are investigated. + // In the worst case, all direct children are investigated, which is eqvivalent to the entire destination list. + // There is however a certain overhead in the logic needed to set up this tree, avoid duplicates of direct children, and so on. + // This method is only faster than just checking the destination list when there are direct children (nested structures), + // but in general the tree method scales better with complexity, and is only slightly slower in simple cases. + + if (Volumes[current_volume]->geometry.destinations_list.num_elements == 1) + tree_next_volume = Volumes[current_volume]->geometry.destinations_list.elements[0]; + else { + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + tree_next_volume = within_which_volume_GPU (ray_position, Volumes[current_volume]->geometry.reduced_destinations_list, + Volumes[current_volume]->geometry.destinations_list, Volumes, &my_mask_status_list, number_of_volumes, + pre_allocated1, pre_allocated2, pre_allocated3); + } + + #ifdef Union_trace_verbal_setting + #ifndef OPENACC + if (enable_tagging) + printf ("tree method moves from %d to %d\n", current_volume, tree_next_volume); + + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new tree volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new tree volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + #endif + + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + #endif + + #ifdef Union_trace_verbal_setting + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new tree volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("After new tree volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + #endif + + // Set next volume to the solution found in the tree method + current_volume = tree_next_volume; + update_current_mask_intersect_status (¤t_mask_intersect_list_status, &my_mask_status_list, Volumes, ¤t_volume); + #ifdef Union_trace_verbal_setting + print_1d_int_list (current_mask_intersect_list_status, "Updated current_mask_intersect_list_status"); + #endif + + } else { + #ifdef Union_trace_verbal_setting + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new intersection volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging && stop_tagging_ray == 0) + printf ("Before new intersection volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + #endif + + // Mask update: If the min_volume is not a mask, things are simple, current_volume = min_volume. + // however, if it is a mask, the mask status will switch. + // if the mask status becomes one, the masked volumes inside may be the next volume (unless they are children of the mask) + // if the mask status becomes zero (and the current volume is masked by min_volume), the destinations list of the mask is searched + // if the mask status becomes zero (and the current volume is NOT masked by min volume), the current volume doesn't change + + if (Volumes[min_volume]->geometry.is_mask_volume == 0) { #ifdef Union_trace_verbal_setting - printf("Running logger system for all volumes \n"); + printf ("Min volume is not a mask, next volume = min volume\n"); #endif #ifndef OPENACC - for (log_index=0;log_indexnum_elements;log_index++) { - // As above, but on a global scale, meaning scattering in all volumes are logged - - // Problems with VN, PV, as there is no assosiated volume or process. The functions however need to have the same input to make the logger components general. - // Could be interesting to have a monitor that just globally measurres the second scattering event in any volume (must be two in the same). Weird but not meaningless. - global_all_volume_logger_list_master->elements[log_index].logger->function_pointers.active_record_function(&ray_position, k_new, k_old, p, p_old, t, scattered_flag[current_volume], scattered_flag_VP[current_volume][selected_process], number_of_scattering_events, global_all_volume_logger_list_master->elements[log_index].logger, &loggers_with_data_array); + if (enable_tagging && stop_tagging_ray == 0) { + current_tagging_node = goto_volume_node (current_tagging_node, current_volume, min_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); } #endif + current_volume = min_volume; + } else { #ifdef Union_trace_verbal_setting - printf("Outgoing event: %g %g %g // %g %g %g\n",x,y,z,vx,vy,vz); - #endif - SCATTER; - #ifndef OPENACC - ++number_of_scattering_events; - ++scattered_flag[current_volume]; - ++scattered_flag_VP[current_volume][selected_process]; - #endif - - // Clear intersection time lists as the direction of the ray has changed - clear_intersection_table(my_intersection_time_table); - time_propagated_without_scattering = 0.0; - #ifdef Union_trace_verbal_setting - printf("SCATTERED SUCSSESFULLY \n"); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n",x,y,z,vx,vy,vz); - - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) printf("Before new process node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("Before new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); - #endif + printf ("Current volume is not a mask, complex decision tree\n"); #endif - - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) - current_tagging_node = goto_process_node(current_tagging_node, selected_process,Volumes[current_volume], &stop_tagging_ray,stop_creating_nodes); - #endif - #ifdef Union_trace_verbal_setting - - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) printf("After new process node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("After new process node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + if (my_mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] == 1) { + // We are leaving the mask, change the status + #ifdef Union_trace_verbal_setting + printf ("mask status changed from 1 to 0 as a mask is left\n"); #endif - #endif - - } else { - #ifdef Union_trace_verbal_setting - printf("Propagate out of volume %d\n", current_volume); - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); - #endif - // Propagate neutron to found minimum time - // PROP_DT(time_to_boundery); - x += time_to_boundery*vx; - y += time_to_boundery*vy; - z += time_to_boundery*vz; - t += time_to_boundery; - r[0] = x; r[1] = y; r[2] = z; - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - - time_propagated_without_scattering = min_intersection_time; - SCATTER; // For debugging purposes - #ifdef Union_trace_verbal_setting - printf("r = (%f,%f,%f) v = (%f,%f,%f) \n",x,y,z,vx,vy,vz); - #endif - // Remove this entry from the my_intersection_time_table - my_intersection_time_table->intersection_times[min_volume][min_solution] = -1; - - // Use destination list for corresponding intersection entry n,i) to find next volume - #ifdef Union_trace_verbal_setting - printf("PROPAGATION FROM VOLUME %d \n",current_volume); - #endif - if (min_volume == current_volume) { - #ifdef Union_trace_verbal_setting - printf("min_volume == current_volume \n"); - #endif - // List approach to finding the next volume. - // When the ray intersects the current volume, the next volume must be on the destination list of the current volume - // However, the reduced_destination_list can be investigated first, and depending on the results, the - // direct children of the volumes on the reduced destination list are investigated. - // In the worst case, all direct children are investigated, which is eqvivalent to the entire destination list. - // There is however a certain overhead in the logic needed to set up this tree, avoid duplicates of direct children, and so on. - // This method is only faster than just checking the destination list when there are direct children (nested structures), - // but in general the tree method scales better with complexity, and is only slightly slower in simple cases. - - if (Volumes[current_volume]->geometry.destinations_list.num_elements == 1) - tree_next_volume = Volumes[current_volume]->geometry.destinations_list.elements[0]; - else { - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - tree_next_volume = within_which_volume_GPU(ray_position,Volumes[current_volume]->geometry.reduced_destinations_list,Volumes[current_volume]->geometry.destinations_list,Volumes,&my_mask_status_list,number_of_volumes,pre_allocated1,pre_allocated2,pre_allocated3); - } - - #ifdef Union_trace_verbal_setting - #ifndef OPENACC - if (enable_tagging) printf("tree method moves from %d to %d\n",current_volume,tree_next_volume); - - if (enable_tagging && stop_tagging_ray == 0) printf("Before new tree volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("Before new tree volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); - #endif - #endif - - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) - current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes,&stop_tagging_ray,stop_creating_nodes); - #endif - + my_mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 0; + // If the current volume is masked by this mask, run within_which_volume using the masks destination list, otherwise keep the current volume + if (on_int_list (Volumes[current_volume]->geometry.masked_by_list, min_volume) == 1) { #ifdef Union_trace_verbal_setting - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) printf("After new tree volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("After new tree volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); - #endif + printf ("The current volume was masked by this mask, and my need updating\n"); #endif - - // Set next volume to the solution found in the tree method - current_volume = tree_next_volume; - update_current_mask_intersect_status(¤t_mask_intersect_list_status, &my_mask_status_list, Volumes, ¤t_volume); - #ifdef Union_trace_verbal_setting - print_1d_int_list(current_mask_intersect_list_status,"Updated current_mask_intersect_list_status"); - #endif - - } else { - #ifdef Union_trace_verbal_setting - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) printf("Before new intersection volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging && stop_tagging_ray == 0) printf("Before new intersection volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); - #endif - #endif - - // Mask update: If the min_volume is not a mask, things are simple, current_volume = min_volume. - // however, if it is a mask, the mask status will switch. - // if the mask status becomes one, the masked volumes inside may be the next volume (unless they are children of the mask) - // if the mask status becomes zero (and the current volume is masked by min_volume), the destinations list of the mask is searched - // if the mask status becomes zero (and the current volume is NOT masked by min volume), the current volume doesn't change - - if (Volumes[min_volume]->geometry.is_mask_volume == 0) { - #ifdef Union_trace_verbal_setting - printf("Min volume is not a mask, next volume = min volume\n"); - #endif - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) { - current_tagging_node = goto_volume_node(current_tagging_node, current_volume, min_volume, Volumes,&stop_tagging_ray,stop_creating_nodes); + // In case of ANY mode, need to see if another mask on the masked_by list of the current volume is active, and if so, nothing happens + need_to_run_within_which_volume = 1; + if (Volumes[current_volume]->geometry.mask_mode == 2) { + for (mask_start = mask_check = Volumes[current_volume]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start < Volumes[current_volume]->geometry.masked_by_mask_index_list.num_elements; mask_check++) { + if (my_mask_status_list.elements[*mask_check] == 1) { + // Nothing needs to be done, the effective mask status of the current volume is still 1 + need_to_run_within_which_volume = 0; + break; + } } - #endif - current_volume = min_volume; - } else { + } + if (need_to_run_within_which_volume == 1) { #ifdef Union_trace_verbal_setting - printf("Current volume is not a mask, complex decision tree\n"); + printf ("The current volume was masked by this mask, and does need updating\n"); #endif - if (my_mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] == 1) { - // We are leaving the mask, change the status + if (Volumes[min_volume]->geometry.destinations_list.num_elements == 1) { #ifdef Union_trace_verbal_setting - printf("mask status changed from 1 to 0 as a mask is left\n"); + printf ("Only one element in the destination tree of the mask\n"); #endif - my_mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 0; - // If the current volume is masked by this mask, run within_which_volume using the masks destination list, otherwise keep the current volume - if (on_int_list(Volumes[current_volume]->geometry.masked_by_list,min_volume) == 1) { + // If there is only one element on the destinations list (quite common) there is no reason to run within_which_volume + // Instead the mask status is calculated here + if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.is_masked_volume == 1) { #ifdef Union_trace_verbal_setting - printf("The current volume was masked by this mask, and my need updating\n"); + printf ("The one element is however masked, so the mask status need to be calculated\n"); #endif - // In case of ANY mode, need to see if another mask on the masked_by list of the current volume is active, and if so, nothing happens - need_to_run_within_which_volume = 1; - if (Volumes[current_volume]->geometry.mask_mode == 2) { - for (mask_start=mask_check=Volumes[current_volume]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.masked_by_mask_index_list.num_elements;mask_check++) { + // figure out the effective mask status of this volume + if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.mask_mode == 2) { // ANY mask mode + tree_next_volume = 0; + for (mask_start = mask_check + = Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start + < Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements; + mask_check++) { if (my_mask_status_list.elements[*mask_check] == 1) { - // Nothing needs to be done, the effective mask status of the current volume is still 1 - need_to_run_within_which_volume = 0; + tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; break; } } - } - if (need_to_run_within_which_volume == 1) { - #ifdef Union_trace_verbal_setting - printf("The current volume was masked by this mask, and does need updating\n"); - #endif - if (Volumes[min_volume]->geometry.destinations_list.num_elements == 1) { - #ifdef Union_trace_verbal_setting - printf("Only one element in the destination tree of the mask\n"); - #endif - // If there is only one element on the destinations list (quite common) there is no reason to run within_which_volume - // Instead the mask status is calculated here - if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.is_masked_volume == 1) { - #ifdef Union_trace_verbal_setting - printf("The one element is however masked, so the mask status need to be calculated\n"); - #endif - // figure out the effective mask status of this volume - if (Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.mask_mode == 2) { // ANY mask mode - tree_next_volume = 0; - for (mask_start=mask_check=Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements;mask_check++) { - if (my_mask_status_list.elements[*mask_check] == 1) { - tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; - break; - } - } - } else { // ALL mask mode - tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; - for (mask_start=mask_check=Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements;mask_check-mask_startgeometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements;mask_check++) { - if (my_mask_status_list.elements[*mask_check] == 0) { - tree_next_volume = 0; - break; - } - } - } - } else tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; - #ifdef Union_trace_verbal_setting - printf("The method found the next tree volume to be %d\n",tree_next_volume); - #endif - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); - #endif - current_volume = tree_next_volume; - } else { - #ifdef Union_trace_verbal_setting - printf("Many elements in destinations list, use within_which_volume\n"); - #endif - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - tree_next_volume = within_which_volume_GPU(ray_position,Volumes[min_volume]->geometry.reduced_destinations_list,Volumes[min_volume]->geometry.destinations_list,Volumes,&my_mask_status_list,number_of_volumes,pre_allocated1,pre_allocated2,pre_allocated3); - - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes,&stop_tagging_ray,stop_creating_nodes); - #endif - current_volume = tree_next_volume; - #ifdef Union_trace_verbal_setting - printf("Set new new volume to %d\n",tree_next_volume); - #endif + } else { // ALL mask mode + tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; + for (mask_start = mask_check + = Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.elements; + mask_check - mask_start + < Volumes[Volumes[min_volume]->geometry.destinations_list.elements[0]]->geometry.masked_by_mask_index_list.num_elements; + mask_check++) { + if (my_mask_status_list.elements[*mask_check] == 0) { + tree_next_volume = 0; + break; + } } - } else { - #ifdef Union_trace_verbal_setting - printf("Did not need updating, as another mask was covering the volume\n"); - #endif } - } - + } else + tree_next_volume = Volumes[min_volume]->geometry.destinations_list.elements[0]; + #ifdef Union_trace_verbal_setting + printf ("The method found the next tree volume to be %d\n", tree_next_volume); + #endif + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node + = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + #endif + current_volume = tree_next_volume; } else { - // Here beccause the mask status of the mask that is intersected was 0, and it is thus switched to 1 - my_mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 1; - // When entering a mask, the new highest priority volume may be one of the masked volumes, if not we keep the current volume - ray_position = coords_set(x,y,z); - ray_velocity = coords_set(vx,vy,vz); - // Bug found on the 2/9 2016, the destinations_list of a mask does not contain the volumes inside it. Could make an additional list for this. - // The temporary fix will be to use the mask list for both reduced destinations list and destinations list. - tree_next_volume = within_which_volume_GPU(ray_position,Volumes[min_volume]->geometry.mask_list,Volumes[min_volume]->geometry.mask_list,Volumes,&my_mask_status_list,number_of_volumes,pre_allocated1,pre_allocated2,pre_allocated3); - // if within_which_volume returns 0, no result was found (volume 0 can not be masked, so it could not be on the mask list) - if (tree_next_volume != 0) { - if (Volumes[tree_next_volume]->geometry.priority_value > Volumes[current_volume]->geometry.priority_value) { - // In case the current volume has a higher priority, nothing happens, otherwise change current volume - #ifndef OPENACC - if (enable_tagging && stop_tagging_ray == 0) current_tagging_node = goto_volume_node(current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); - #endif - current_volume = tree_next_volume; - } - } + #ifdef Union_trace_verbal_setting + printf ("Many elements in destinations list, use within_which_volume\n"); + #endif + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + tree_next_volume = within_which_volume_GPU (ray_position, Volumes[min_volume]->geometry.reduced_destinations_list, + Volumes[min_volume]->geometry.destinations_list, Volumes, &my_mask_status_list, number_of_volumes, + pre_allocated1, pre_allocated2, pre_allocated3); + + #ifndef OPENACC + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node + = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); + #endif + current_volume = tree_next_volume; + #ifdef Union_trace_verbal_setting + printf ("Set new new volume to %d\n", tree_next_volume); + #endif } + } else { + #ifdef Union_trace_verbal_setting + printf ("Did not need updating, as another mask was covering the volume\n"); + #endif } - - // Regardless of the outcome of the above code, either the mask status or current volume have changed, and thus a effective mask update is needed. - update_current_mask_intersect_status(¤t_mask_intersect_list_status, &my_mask_status_list, Volumes, ¤t_volume); - #ifdef Union_trace_verbal_setting - print_1d_int_list(my_mask_status_list,"Updated mask status list"); - print_1d_int_list(current_mask_intersect_list_status,"Updated current_mask_intersect_list_status"); + } + + } else { + // Here beccause the mask status of the mask that is intersected was 0, and it is thus switched to 1 + my_mask_status_list.elements[Volumes[min_volume]->geometry.mask_index] = 1; + // When entering a mask, the new highest priority volume may be one of the masked volumes, if not we keep the current volume + ray_position = coords_set (x, y, z); + ray_velocity = coords_set (vx, vy, vz); + // Bug found on the 2/9 2016, the destinations_list of a mask does not contain the volumes inside it. Could make an additional list for this. + // The temporary fix will be to use the mask list for both reduced destinations list and destinations list. + tree_next_volume = within_which_volume_GPU (ray_position, Volumes[min_volume]->geometry.mask_list, Volumes[min_volume]->geometry.mask_list, Volumes, + &my_mask_status_list, number_of_volumes, pre_allocated1, pre_allocated2, pre_allocated3); + // if within_which_volume returns 0, no result was found (volume 0 can not be masked, so it could not be on the mask list) + if (tree_next_volume != 0) { + if (Volumes[tree_next_volume]->geometry.priority_value > Volumes[current_volume]->geometry.priority_value) { + // In case the current volume has a higher priority, nothing happens, otherwise change current volume #ifndef OPENACC - if (enable_tagging) printf("After new intersection volume node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - if (enable_tagging) printf("After new intersection volume node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); + if (enable_tagging && stop_tagging_ray == 0) + current_tagging_node + = goto_volume_node (current_tagging_node, current_volume, tree_next_volume, Volumes, &stop_tagging_ray, stop_creating_nodes); #endif - #endif - - } - if (Volumes[current_volume]->geometry.is_exit_volume==1) { - done = 1; // Exit volumes allow the ray to escape the component - ray_sucseeded = 1; // Allows the ray to + current_volume = tree_next_volume; + } + } } - #ifdef Union_trace_verbal_setting - printf(" TO VOLUME %d \n",current_volume); - #endif + } + + // Regardless of the outcome of the above code, either the mask status or current volume have changed, and thus a effective mask update is needed. + update_current_mask_intersect_status (¤t_mask_intersect_list_status, &my_mask_status_list, Volumes, ¤t_volume); + #ifdef Union_trace_verbal_setting + print_1d_int_list (my_mask_status_list, "Updated mask status list"); + print_1d_int_list (current_mask_intersect_list_status, "Updated current_mask_intersect_list_status"); + #ifndef OPENACC + if (enable_tagging) + printf ("After new intersection volume node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + if (enable_tagging) + printf ("After new intersection volume node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); + #endif + #endif } - + if (Volumes[current_volume]->geometry.is_exit_volume == 1) { + done = 1; // Exit volumes allow the ray to escape the component + ray_sucseeded = 1; // Allows the ray to + } + #ifdef Union_trace_verbal_setting + printf (" TO VOLUME %d \n", current_volume); + #endif + } + } else { // Here because a shortest time is not found - if (current_volume == 0) { - done = 1; - ray_sucseeded = 1; - - } else { // Check for errors (debugging phase) - if (error_msg == 0) { - component_error_msg++; - ray_sucseeded = 0; - done = 1; // stop the loop - #ifndef OPENACC - printf("\n----------------------------------------------------------------------------------------------------\n"); - printf("Union_master %s: Somehow reached a situation with no intersection time found, but still inside volume %d instead of 0\n",NAME_CURRENT_COMP,current_volume); - for (my_volume_index = 1; my_volume_index < number_of_volumes; my_volume_index++) { - if (r_within_function(ray_position,&Volumes[my_volume_index]->geometry) == 1) - printf("The ray is in volume %d\n",my_volume_index); - } - - print_1d_int_list(my_mask_status_list,"mask status list"); - for (iterator=0;iterator 100) { - printf("To many errors encountered, exiting. \n"); - #ifndef OPENACC - // need ERROR FLAG to be read in finally which can warn the user of problems! - exit(1); - #endif - } + if (current_volume == 0) { + done = 1; + ray_sucseeded = 1; + + } else { // Check for errors (debugging phase) + if (error_msg == 0) { + component_error_msg++; + ray_sucseeded = 0; + done = 1; // stop the loop + #ifndef OPENACC + printf ("\n----------------------------------------------------------------------------------------------------\n"); + printf ("Union_master %s: Somehow reached a situation with no intersection time found, but still inside volume %d instead of 0\n", NAME_CURRENT_COMP, + current_volume); + for (my_volume_index = 1; my_volume_index < number_of_volumes; my_volume_index++) { + if (r_within_function (ray_position, &Volumes[my_volume_index]->geometry) == 1) + printf ("The ray is in volume %d\n", my_volume_index); + } + + print_1d_int_list (my_mask_status_list, "mask status list"); + for (iterator = 0; iterator < number_of_volumes; iterator++) + printf ("%d:%d - ", iterator, scattered_flag[iterator]); + printf ("\n"); + printf ("r = (%f,%f,%f) v = (%f,%f,%f) \n", x, y, z, vx, vy, vz); + + printf ("Trace error number (%d/100) \n", component_error_msg); + #endif } + error_msg++; + + if (component_error_msg > 100) { + printf ("To many errors encountered, exiting. \n"); + #ifndef OPENACC + // need ERROR FLAG to be read in finally which can warn the user of problems! + exit (1); + #endif + } + } + } + + if (limit == 0) { + done = 1; + ray_sucseeded = 0; + printf ("Reached limit on number of interactions, and discarded the neutron, was in volume %d\n", current_volume); + ABSORB; } - - if (limit == 0) {done = 1; ray_sucseeded = 0; printf("Reached limit on number of interactions, and discarded the neutron, was in volume %d\n",current_volume);ABSORB;} #ifdef Union_trace_verbal_setting - printf("----------- END OF WHILE LOOP --------------------------------------\n"); + printf ("----------- END OF WHILE LOOP --------------------------------------\n"); #endif - } // Could move all add_statistics and similar to this point, but need to filter for failed rays if (ray_sucseeded == 1) { - + // Ray sucseeded, need to check status of conditionals #ifdef Union_trace_verbal_setting - printf("----------- logger loop --------------------------------------\n"); + printf ("----------- logger loop --------------------------------------\n"); #endif // Loggers attatched to specific volumes need to be handled with care to avoid looping over all loggers for every ray #ifndef OPENACC if (enable_conditionals == 1) { - for (log_index=loggers_with_data_array.used_elements-1; log_index>-1; log_index--) { + for (log_index = loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { // Check all conditionals attatched to the current logger this_logger = loggers_with_data_array.logger_pointers[log_index]; conditional_status = 1; - for (iterator=0;iteratorconditional_list.num_elements;iterator++) { + for (iterator = 0; iterator < loggers_with_data_array.logger_pointers[log_index]->conditional_list.num_elements; iterator++) { // Call this particular conditional. If it fails, report the status and break #ifdef Union_trace_verbal_setting - printf("Checking conditional number %d for logger named %s \n",iterator,loggers_with_data_array.logger_pointers[log_index]->name); + printf ("Checking conditional number %d for logger named %s \n", iterator, loggers_with_data_array.logger_pointers[log_index]->name); #endif - if (0 == this_logger->conditional_list.conditional_functions[iterator]( - this_logger->conditional_list.p_data_unions[iterator], - &ray_position, &ray_velocity, &p, &t, ¤t_volume, - &number_of_scattering_events, scattered_flag,scattered_flag_VP)) { + if (0 + == this_logger->conditional_list.conditional_functions[iterator](this_logger->conditional_list.p_data_unions[iterator], &ray_position, + &ray_velocity, &p, &t, ¤t_volume, &number_of_scattering_events, + scattered_flag, scattered_flag_VP)) { conditional_status = 0; break; } } if (conditional_status == 1) { - // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the temp_to_perm function needs to be called - // The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger - + // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the + // temp_to_perm function needs to be called The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger + if (loggers_with_data_array.logger_pointers[log_index]->function_pointers.select_t_to_p == 1) { - loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm(&loggers_with_data_array.logger_pointers[log_index]->data_union); - } - else if (loggers_with_data_array.logger_pointers[log_index]->function_pointers.select_t_to_p == 2) { - loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm_final_p(&loggers_with_data_array.logger_pointers[log_index]->data_union,p); + loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm (&loggers_with_data_array.logger_pointers[log_index]->data_union); + } else if (loggers_with_data_array.logger_pointers[log_index]->function_pointers.select_t_to_p == 2) { + loggers_with_data_array.logger_pointers[log_index]->function_pointers.temp_to_perm_final_p ( + &loggers_with_data_array.logger_pointers[log_index]->data_union, p); } - - // The user can set a condtional_extend_index, so that the evaluation of this specific conditional can be taken easily from extend + + // The user can set a condtional_extend_index, so that the evaluation of this specific conditional can be taken easily from extend if (loggers_with_data_array.logger_pointers[log_index]->logger_extend_index != -1) { #ifdef Union_trace_verbal_setting - printf("Updating my_logger_conditional_extend_array[%d] to 1 (max length = %d)\n",loggers_with_data_array.logger_pointers[log_index]->logger_extend_index,max_conditional_extend_index); + printf ("Updating my_logger_conditional_extend_array[%d] to 1 (max length = %d)\n", + loggers_with_data_array.logger_pointers[log_index]->logger_extend_index, max_conditional_extend_index); #endif // The user can set a condtional_extend_index, so that the evaluation of this specific conditional can be taken easily from extend my_logger_conditional_extend_array[loggers_with_data_array.logger_pointers[log_index]->logger_extend_index] = 1; // Can be reached from EXTEND // Are all reset to 0 for each new ray #ifdef Union_trace_verbal_setting - printf("Updated extend index sucessfully\n"); + printf ("Updated extend index sucessfully\n"); #endif } - + // Need to remove the current element from logger_with_data as it has been cleared and written to disk // The remaining elements is passed on to the next Union_master as it may fulfill the conditional after that master - if (global_master_list_master->elements[global_master_list_master->num_elements-1].component_index != INDEX_CURRENT_COMP) { + if (global_master_list_master->elements[global_master_list_master->num_elements - 1].component_index != INDEX_CURRENT_COMP) { // Move current logger pointer in logger_with_data to end position - loggers_with_data_array.logger_pointers[log_index] = loggers_with_data_array.logger_pointers[loggers_with_data_array.used_elements-1]; + loggers_with_data_array.logger_pointers[log_index] = loggers_with_data_array.logger_pointers[loggers_with_data_array.used_elements - 1]; // Decrease logger_with_data.used_elements with 1 loggers_with_data_array.used_elements--; } } } - + // Perform the same loop with abs_loggers and their conditionals - for (log_index=abs_loggers_with_data_array.used_elements-1; log_index>-1; log_index--) { + for (log_index = abs_loggers_with_data_array.used_elements - 1; log_index > -1; log_index--) { // Check all conditionals attatched to the current logger this_abs_logger = abs_loggers_with_data_array.abs_logger_pointers[log_index]; conditional_status = 1; - for (iterator=0;iteratorconditional_list.num_elements;iterator++) { + for (iterator = 0; iterator < abs_loggers_with_data_array.abs_logger_pointers[log_index]->conditional_list.num_elements; iterator++) { // Call this particular conditional. If it fails, report the status and break #ifdef Union_trace_verbal_setting - printf("Checking conditional number %d for abs logger named %s \n",iterator, abs_loggers_with_data_array.abs_logger_pointers[log_index]->name); + printf ("Checking conditional number %d for abs logger named %s \n", iterator, abs_loggers_with_data_array.abs_logger_pointers[log_index]->name); #endif - if (0 == this_abs_logger->conditional_list.conditional_functions[iterator]( - this_abs_logger->conditional_list.p_data_unions[iterator], - &ray_position, &ray_velocity, &p, &t, ¤t_volume, - &number_of_scattering_events, scattered_flag, scattered_flag_VP)) { + if (0 + == this_abs_logger->conditional_list.conditional_functions[iterator](this_abs_logger->conditional_list.p_data_unions[iterator], &ray_position, + &ray_velocity, &p, &t, ¤t_volume, &number_of_scattering_events, + scattered_flag, scattered_flag_VP)) { conditional_status = 0; break; } } if (conditional_status == 1) { - // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the temp_to_perm function needs to be called - // The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger - abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.temp_to_perm(&abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); - + // If a logger does not have a conditional, it will write directly to perm, and not even add it to the loggers_with_data_array, thus we know the + // temp_to_perm function needs to be called The input for the temp_to_perm function is a pointer to the logger_data_union for the appropriate logger + abs_loggers_with_data_array.abs_logger_pointers[log_index]->function_pointers.temp_to_perm ( + &abs_loggers_with_data_array.abs_logger_pointers[log_index]->data_union); + // The user can set a condtional_extend_index, so that the evaluation of this specific conditional can be taken easily from extend if (abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index != -1) { #ifdef Union_trace_verbal_setting - printf("Updating logger_conditional_extend_array[%d] to 1 (max length = %d)\n",abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index,max_conditional_extend_index); + printf ("Updating logger_conditional_extend_array[%d] to 1 (max length = %d)\n", + abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index, max_conditional_extend_index); #endif - abs_logger_conditional_extend_array[abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index] = 1; // Can be reached from EXTEND - // Are all reset to 0 for each new ray - #ifdef Union_trace_verbal_setting - printf("Updated extend index sucessfully\n"); + abs_logger_conditional_extend_array[abs_loggers_with_data_array.abs_logger_pointers[log_index]->abs_logger_extend_index] + = 1; // Can be reached from EXTEND + // Are all reset to 0 for each new ray + #ifdef Union_trace_verbal_setting + printf ("Updated extend index sucessfully\n"); #endif } - + // Need to remove the current element from logger_with_data as it has been cleared and written to disk // The remaining elements is passed on to the next Union_master as it may fulfill the conditional after that master - if (global_master_list_master->elements[global_master_list_master->num_elements-1].component_index != INDEX_CURRENT_COMP) { + if (global_master_list_master->elements[global_master_list_master->num_elements - 1].component_index != INDEX_CURRENT_COMP) { // Move current logger pointer in logger_with_data to end position - abs_loggers_with_data_array.abs_logger_pointers[log_index] = abs_loggers_with_data_array.abs_logger_pointers[abs_loggers_with_data_array.used_elements-1]; + abs_loggers_with_data_array.abs_logger_pointers[log_index] + = abs_loggers_with_data_array.abs_logger_pointers[abs_loggers_with_data_array.used_elements - 1]; // Decrease logger_with_data.used_elements with 1 abs_loggers_with_data_array.used_elements--; } - } } } #endif - + #ifndef OPENACC if (enable_tagging && stop_tagging_ray == 0) { conditional_status = 1; - for (iterator=0; iteratornum_elements; iterator++) { + for (iterator = 0; iterator < tagging_conditional_list->num_elements; iterator++) { // Call this particular conditional. If it fails, report the status and break // Since a conditional can work for a logger and master_tagging at the same time, it may be evaluated twice #ifdef Union_trace_verbal_setting - printf("Checking tagging conditional number %d\n",iterator); + printf ("Checking tagging conditional number %d\n", iterator); #endif - if (0 == tagging_conditional_list->conditional_functions[iterator]( - tagging_conditional_list->p_data_unions[iterator], - &ray_position, &ray_velocity, &p, &t, ¤t_volume, - &number_of_scattering_events, scattered_flag,scattered_flag_VP)) { + if (0 + == tagging_conditional_list->conditional_functions[iterator](tagging_conditional_list->p_data_unions[iterator], &ray_position, &ray_velocity, &p, &t, + ¤t_volume, &number_of_scattering_events, scattered_flag, scattered_flag_VP)) { conditional_status = 0; break; } @@ -2172,43 +2385,44 @@ TRACE if (conditional_status == 1) { tagging_conditional_extend = 1; #ifdef Union_trace_verbal_setting - printf("Before adding statistics to node: current_tagging_nodbe->intensity = %f\n",current_tagging_node->intensity); - printf("Before adding statistics to node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); + printf ("Before adding statistics to node: current_tagging_nodbe->intensity = %f\n", current_tagging_node->intensity); + printf ("Before adding statistics to node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); #endif - - add_statistics_to_node(current_tagging_node,&ray_position, &ray_velocity, &p, &tagging_leaf_counter); - + + add_statistics_to_node (current_tagging_node, &ray_position, &ray_velocity, &p, &tagging_leaf_counter); + #ifdef Union_trace_verbal_setting - printf("After adding statistics to node: current_tagging_node->intensity = %f\n",current_tagging_node->intensity); - printf("After adding statistics to node: current_tagging_node->number_of_rays = %d\n",current_tagging_node->number_of_rays); + printf ("After adding statistics to node: current_tagging_node->intensity = %f\n", current_tagging_node->intensity); + printf ("After adding statistics to node: current_tagging_node->number_of_rays = %d\n", current_tagging_node->number_of_rays); #endif } } #endif - + // Move the rays a nano meter away from the surface it left, in case activation counter > 1, this will prevent the ray from starting on a volume boundery - x += vx*1E-9; y += vy*1E-9; z += vz*1E-9; t += 1E-9; - + x += vx * 1E-9; + y += vy * 1E-9; + z += vz * 1E-9; + t += 1E-9; + } else { ABSORB; // Absorb rays that didn't exit correctly for whatever reason // Could error log here } - + #pragma acc atomic number_of_solutions_static = number_of_solutions_static + number_of_solutions; - + // Stores nubmer of scattering events in global master list so that another master with inherit_number_of_scattering_events can continue #ifndef OPENACC global_master_list_master->elements[this_global_master_index].stored_number_of_scattering_events = number_of_scattering_events; #endif - + #ifdef debug_initialize_timetable #ifdef OPENACC - free(my_intersection_time_table); + free (my_intersection_time_table); #endif #endif - - %} @@ -2219,195 +2433,248 @@ SAVE FINALLY %{ -// write out histories from tagging system if enabled -if (enable_tagging) { - if (finally_verbal) printf("Writing tagging tree to disk \n"); - if (finally_verbal) printf("Number of leafs = %d \n",tagging_leaf_counter); + // write out histories from tagging system if enabled + if (enable_tagging) { + if (finally_verbal) + printf ("Writing tagging tree to disk \n"); + if (finally_verbal) + printf ("Number of leafs = %d \n", tagging_leaf_counter); // While writing the tagging tree to disk, all the leafs are deallocated - write_tagging_tree(&master_tagging_node_list, Volumes, tagging_leaf_counter, number_of_volumes); -} -if (master_tagging_node_list.num_elements > 0) free(master_tagging_node_list.elements); - - -if (finally_verbal) printf("Freeing variables which are always allocated \n"); -// free allocated arrays specific to this master union component -free(scattered_flag); -free(my_trace); -free(number_of_processes_array); -free(Geometries); - -#ifndef OPENACC -if (finally_verbal) printf("Freeing my_intersection_time_table \n"); -for (iterator = 1;iterator < intersection_time_table->num_volumes;iterator++){ - free(intersection_time_table->intersection_times[iterator]); -} - -free(intersection_time_table->n_elements); -free(intersection_time_table->calculated); -free(intersection_time_table->intersection_times); -free(intersection_time_table); -#endif - -if (free_tagging_conditioanl_list == 1) free(tagging_conditional_list); - -if (finally_verbal) printf("Freeing lists for individual volumes \n"); -for (volume_index=0;volume_indexgeometry.intersect_check_list.num_elements > 0) free(Volumes[volume_index]->geometry.intersect_check_list.elements); - if (Volumes[volume_index]->geometry.destinations_list.num_elements > 0) free(Volumes[volume_index]->geometry.destinations_list.elements); - if (Volumes[volume_index]->geometry.reduced_destinations_list.num_elements > 0) free(Volumes[volume_index]->geometry.reduced_destinations_list.elements); - if (Volumes[volume_index]->geometry.children.num_elements > 0) free(Volumes[volume_index]->geometry.children.elements); - if (Volumes[volume_index]->geometry.direct_children.num_elements > 0) free(Volumes[volume_index]->geometry.direct_children.elements); - if (Volumes[volume_index]->geometry.masked_by_list.num_elements > 0) free(Volumes[volume_index]->geometry.masked_by_list.elements); - if (Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements > 0) free(Volumes[volume_index]->geometry.masked_by_mask_index_list.elements); - if (Volumes[volume_index]->geometry.mask_list.num_elements > 0) free(Volumes[volume_index]->geometry.mask_list.elements); - if (Volumes[volume_index]->geometry.mask_intersect_list.num_elements > 0) free(Volumes[volume_index]->geometry.mask_intersect_list.elements); - if (Volumes[volume_index]->geometry.next_volume_list.num_elements > 0) free(Volumes[volume_index]->geometry.next_volume_list.elements); - - if (finally_verbal) printf(" Freeing physics\n"); - if (volume_index > 0) { // Volume 0 does not have physical properties allocated - free(scattered_flag_VP[volume_index]); - if (Volumes[volume_index]->geometry.process_rot_allocated == 1) { - free(Volumes[volume_index]->geometry.process_rot_matrix_array); - free(Volumes[volume_index]->geometry.transpose_process_rot_matrix_array); - Volumes[volume_index]->geometry.process_rot_allocated = 0; - } - if (on_int_list(Volume_copies_allocated,volume_index)) { - // This is a local copy of a volume, deallocate that local copy (all the allocated memory attachted to it was just deallocated, so this should not leave any leaks) - free(Volumes[volume_index]); - } else { - // Only free p_physics for vacuum volumes for the original at the end (there is a p_physics allocated for each vacuum volume) - if (Volumes[volume_index]->p_physics->is_vacuum == 1 ) free(Volumes[volume_index]->p_physics); - } - } - - if (finally_verbal) printf(" Freeing loggers\n"); - if (Volumes[volume_index]->loggers.num_elements >0) { - for (iterator=0;iteratorloggers.num_elements;iterator++) { - free(Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process); - } - free(Volumes[volume_index]->loggers.p_logger_volume); - } - - if (finally_verbal) printf(" Freeing abs_loggers\n"); - if (Volumes[volume_index]->abs_loggers.num_elements > 0) { - free(Volumes[volume_index]->abs_loggers.p_abs_logger); + write_tagging_tree (&master_tagging_node_list, Volumes, tagging_leaf_counter, number_of_volumes); } - if (finally_verbal) printf(" Freeing Volumes[index]\n"); - //free(Volumes[volume_index]); // Not able to free - //if (finally_verbal) printf(" Managed to free Volumes[index]\n"); -} + if (master_tagging_node_list.num_elements > 0) + free (master_tagging_node_list.elements); -free(scattered_flag_VP); + if (finally_verbal) + printf ("Freeing variables which are always allocated \n"); + // free allocated arrays specific to this master union component + free (scattered_flag); + free (my_trace); + free (number_of_processes_array); + free (Geometries); -if (finally_verbal) printf("Freeing starting lists \n"); -if (starting_lists.allowed_starting_volume_logic_list.num_elements > 0) free(starting_lists.allowed_starting_volume_logic_list.elements); -if (starting_lists.reduced_start_list.num_elements > 0) free(starting_lists.reduced_start_list.elements); -if (starting_lists.start_logic_list.num_elements > 0) free(starting_lists.start_logic_list.elements); + #ifndef OPENACC + if (finally_verbal) + printf ("Freeing my_intersection_time_table \n"); + for (iterator = 1; iterator < intersection_time_table->num_volumes; iterator++) { + free (intersection_time_table->intersection_times[iterator]); + } -if (finally_verbal) printf("Freeing mask lists \n"); -if (mask_status_list.num_elements>0) free(mask_status_list.elements); -if (current_mask_intersect_list_status.num_elements>0) free(current_mask_intersect_list_status.elements); -if (mask_volume_index_list.num_elements>0) free(mask_volume_index_list.elements); + free (intersection_time_table->n_elements); + free (intersection_time_table->calculated); + free (intersection_time_table->intersection_times); + free (intersection_time_table); + #endif -if (finally_verbal) printf("Freeing component index list \n"); -if (geometry_component_index_list.num_elements>0) free(geometry_component_index_list.elements); + if (free_tagging_conditioanl_list == 1) + free (tagging_conditional_list); + + if (finally_verbal) + printf ("Freeing lists for individual volumes \n"); + for (volume_index = 0; volume_index < number_of_volumes; volume_index++) { + + if (finally_verbal) + printf (" Freeing geometry\n"); + if (Volumes[volume_index]->geometry.intersect_check_list.num_elements > 0) + free (Volumes[volume_index]->geometry.intersect_check_list.elements); + if (Volumes[volume_index]->geometry.destinations_list.num_elements > 0) + free (Volumes[volume_index]->geometry.destinations_list.elements); + if (Volumes[volume_index]->geometry.reduced_destinations_list.num_elements > 0) + free (Volumes[volume_index]->geometry.reduced_destinations_list.elements); + if (Volumes[volume_index]->geometry.children.num_elements > 0) + free (Volumes[volume_index]->geometry.children.elements); + if (Volumes[volume_index]->geometry.direct_children.num_elements > 0) + free (Volumes[volume_index]->geometry.direct_children.elements); + if (Volumes[volume_index]->geometry.masked_by_list.num_elements > 0) + free (Volumes[volume_index]->geometry.masked_by_list.elements); + if (Volumes[volume_index]->geometry.masked_by_mask_index_list.num_elements > 0) + free (Volumes[volume_index]->geometry.masked_by_mask_index_list.elements); + if (Volumes[volume_index]->geometry.mask_list.num_elements > 0) + free (Volumes[volume_index]->geometry.mask_list.elements); + if (Volumes[volume_index]->geometry.mask_intersect_list.num_elements > 0) + free (Volumes[volume_index]->geometry.mask_intersect_list.elements); + if (Volumes[volume_index]->geometry.next_volume_list.num_elements > 0) + free (Volumes[volume_index]->geometry.next_volume_list.elements); + + if (finally_verbal) + printf (" Freeing physics\n"); + if (volume_index > 0) { // Volume 0 does not have physical properties allocated + free (scattered_flag_VP[volume_index]); + if (Volumes[volume_index]->geometry.process_rot_allocated == 1) { + free (Volumes[volume_index]->geometry.process_rot_matrix_array); + free (Volumes[volume_index]->geometry.transpose_process_rot_matrix_array); + Volumes[volume_index]->geometry.process_rot_allocated = 0; + } + if (on_int_list (Volume_copies_allocated, volume_index)) { + // This is a local copy of a volume, deallocate that local copy (all the allocated memory attachted to it was just deallocated, so this should not leave + // any leaks) + free (Volumes[volume_index]); + } else { + // Only free p_physics for vacuum volumes for the original at the end (there is a p_physics allocated for each vacuum volume) + if (Volumes[volume_index]->p_physics->is_vacuum == 1) + free (Volumes[volume_index]->p_physics); + } + } + if (finally_verbal) + printf (" Freeing loggers\n"); + if (Volumes[volume_index]->loggers.num_elements > 0) { + for (iterator = 0; iterator < Volumes[volume_index]->loggers.num_elements; iterator++) { + free (Volumes[volume_index]->loggers.p_logger_volume[iterator].p_logger_process); + } + free (Volumes[volume_index]->loggers.p_logger_volume); + } -if (finally_verbal) printf("Freeing Volumes \n"); -free(Volumes); + if (finally_verbal) + printf (" Freeing abs_loggers\n"); + if (Volumes[volume_index]->abs_loggers.num_elements > 0) { + free (Volumes[volume_index]->abs_loggers.p_abs_logger); + } + if (finally_verbal) + printf (" Freeing Volumes[index]\n"); + // free(Volumes[volume_index]); // Not able to free + // if (finally_verbal) printf(" Managed to free Volumes[index]\n"); + } -// Free global allocated arrays if this is the last master union component in the instrument file + free (scattered_flag_VP); + + if (finally_verbal) + printf ("Freeing starting lists \n"); + if (starting_lists.allowed_starting_volume_logic_list.num_elements > 0) + free (starting_lists.allowed_starting_volume_logic_list.elements); + if (starting_lists.reduced_start_list.num_elements > 0) + free (starting_lists.reduced_start_list.elements); + if (starting_lists.start_logic_list.num_elements > 0) + free (starting_lists.start_logic_list.elements); + + if (finally_verbal) + printf ("Freeing mask lists \n"); + if (mask_status_list.num_elements > 0) + free (mask_status_list.elements); + if (current_mask_intersect_list_status.num_elements > 0) + free (current_mask_intersect_list_status.elements); + if (mask_volume_index_list.num_elements > 0) + free (mask_volume_index_list.elements); + + if (finally_verbal) + printf ("Freeing component index list \n"); + if (geometry_component_index_list.num_elements > 0) + free (geometry_component_index_list.elements); + + if (finally_verbal) + printf ("Freeing Volumes \n"); + free (Volumes); + + // Free global allocated arrays if this is the last master union component in the instrument file + + if (global_master_list_master->elements[global_master_list_master->num_elements - 1].component_index == INDEX_CURRENT_COMP) { + if (finally_verbal) + printf ("Freeing global arrays because this is the last Union master component\n"); -if (global_master_list_master->elements[global_master_list_master->num_elements-1].component_index == INDEX_CURRENT_COMP) { - if (finally_verbal) printf("Freeing global arrays because this is the last Union master component\n"); - // Freeing lists allocated in Union_initialization - - if (finally_verbal) printf("Freeing global process list \n"); - if (global_process_list_master->num_elements > 0) free(global_process_list_master->elements); - if (finally_verbal) printf("Freeing global material list \n"); - if (global_material_list_master->num_elements > 0) free(global_material_list_master->elements); - - if (finally_verbal) printf("Freeing global geometry list \n"); - if (global_geometry_list_master->num_elements > 0) free(global_geometry_list_master->elements); - - if (finally_verbal) printf("Freeing global master list \n"); - if (global_master_list_master->num_elements > 0) free(global_master_list_master->elements); - - if (finally_verbal) printf("Freeing global logger lists \n"); - for (iterator=0;iteratornum_elements;iterator++) { + if (finally_verbal) + printf ("Freeing global process list \n"); + if (global_process_list_master->num_elements > 0) + free (global_process_list_master->elements); + + if (finally_verbal) + printf ("Freeing global material list \n"); + if (global_material_list_master->num_elements > 0) + free (global_material_list_master->elements); + + if (finally_verbal) + printf ("Freeing global geometry list \n"); + if (global_geometry_list_master->num_elements > 0) + free (global_geometry_list_master->elements); + + if (finally_verbal) + printf ("Freeing global master list \n"); + if (global_master_list_master->num_elements > 0) + free (global_master_list_master->elements); + + if (finally_verbal) + printf ("Freeing global logger lists \n"); + for (iterator = 0; iterator < global_all_volume_logger_list_master->num_elements; iterator++) { if (global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.num_elements > 0) { - free(global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); - free(global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); + free (global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); + free (global_all_volume_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); } } - if (global_all_volume_logger_list_master->num_elements > 0) free(global_all_volume_logger_list_master->elements); - - for (iterator=0;iteratornum_elements;iterator++) { + if (global_all_volume_logger_list_master->num_elements > 0) + free (global_all_volume_logger_list_master->elements); + + for (iterator = 0; iterator < global_specific_volumes_logger_list_master->num_elements; iterator++) { if (global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.num_elements > 0) { - free(global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); - free(global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); + free (global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.conditional_functions); + free (global_specific_volumes_logger_list_master->elements[iterator].logger->conditional_list.p_data_unions); } } - if (global_specific_volumes_logger_list_master->num_elements > 0) free(global_specific_volumes_logger_list_master->elements); - - if (finally_verbal) printf("Freeing global abs logger lists \n"); - for (iterator=0;iteratornum_elements;iterator++) { + if (global_specific_volumes_logger_list_master->num_elements > 0) + free (global_specific_volumes_logger_list_master->elements); + + if (finally_verbal) + printf ("Freeing global abs logger lists \n"); + for (iterator = 0; iterator < global_all_volume_abs_logger_list_master->num_elements; iterator++) { if (global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.num_elements > 0) { - free(global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); - free(global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); + free (global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); + free (global_all_volume_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); } } - if (global_all_volume_abs_logger_list_master->num_elements > 0) free(global_all_volume_abs_logger_list_master->elements); - - for (iterator=0;iteratornum_elements;iterator++) { + if (global_all_volume_abs_logger_list_master->num_elements > 0) + free (global_all_volume_abs_logger_list_master->elements); + + for (iterator = 0; iterator < global_specific_volumes_abs_logger_list_master->num_elements; iterator++) { if (global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.num_elements > 0) { - free(global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); - free(global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); + free (global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.conditional_functions); + free (global_specific_volumes_abs_logger_list_master->elements[iterator].abs_logger->conditional_list.p_data_unions); } } - if (global_specific_volumes_abs_logger_list_master->num_elements > 0) free(global_specific_volumes_abs_logger_list_master->elements); + if (global_specific_volumes_abs_logger_list_master->num_elements > 0) + free (global_specific_volumes_abs_logger_list_master->elements); - if (finally_verbal) printf("Freeing global tagging conditional lists \n"); - for (iterator=0;iteratornum_elements;iterator++) { + if (finally_verbal) + printf ("Freeing global tagging conditional lists \n"); + for (iterator = 0; iterator < global_tagging_conditional_list_master->num_elements; iterator++) { if (global_tagging_conditional_list_master->elements[iterator].conditional_list.num_elements > 0) { - free(global_tagging_conditional_list_master->elements[iterator].conditional_list.conditional_functions); - free(global_tagging_conditional_list_master->elements[iterator].conditional_list.p_data_unions); + free (global_tagging_conditional_list_master->elements[iterator].conditional_list.conditional_functions); + free (global_tagging_conditional_list_master->elements[iterator].conditional_list.p_data_unions); } } - if (global_tagging_conditional_list_master->num_elements>0) free(global_tagging_conditional_list_master->elements); -} - + if (global_tagging_conditional_list_master->num_elements > 0) + free (global_tagging_conditional_list_master->elements); + } %} MCDISPLAY %{ - // mcdisplay is handled in the component files for each geometry and called here. The line function is only available in this section, and not through functions, + // mcdisplay is handled in the component files for each geometry and called here. The line function is only available in this section, and not through + // functions, // so all the lines to be drawn for each volume are collected in a structure that is then drawn here. - magnify("xyz"); + magnify ("xyz"); struct lines_to_draw lines_to_draw_master; - for (volume_index=1; volume_indexgeometry.visualization_on == 1) { - lines_to_draw_master.number_of_lines = 0; - - Volumes[volume_index]->geometry.mcdisplay_function(&lines_to_draw_master,volume_index,Geometries,number_of_volumes); - - for (iterator = 0;iterator0) free(lines_to_draw_master.lines); - } - } + for (volume_index = 1; volume_index < number_of_volumes; volume_index++) { + if (Volumes[volume_index]->geometry.visualization_on == 1) { + lines_to_draw_master.number_of_lines = 0; + + Volumes[volume_index]->geometry.mcdisplay_function (&lines_to_draw_master, volume_index, Geometries, number_of_volumes); + for (iterator = 0; iterator < lines_to_draw_master.number_of_lines; iterator++) { + if (lines_to_draw_master.lines[iterator].number_of_dashes == 1) { + line (lines_to_draw_master.lines[iterator].point1.x, lines_to_draw_master.lines[iterator].point1.y, lines_to_draw_master.lines[iterator].point1.z, + lines_to_draw_master.lines[iterator].point2.x, lines_to_draw_master.lines[iterator].point2.y, lines_to_draw_master.lines[iterator].point2.z); + } else { + dashed_line (lines_to_draw_master.lines[iterator].point1.x, lines_to_draw_master.lines[iterator].point1.y, + lines_to_draw_master.lines[iterator].point1.z, lines_to_draw_master.lines[iterator].point2.x, + lines_to_draw_master.lines[iterator].point2.y, lines_to_draw_master.lines[iterator].point2.z, + lines_to_draw_master.lines[iterator].number_of_dashes); + } + } + if (lines_to_draw_master.number_of_lines > 0) + free (lines_to_draw_master.lines); + } + } %} END diff --git a/mcstas-comps/union/Union_mesh.comp b/mcstas-comps/union/Union_mesh.comp index 47eb8b280e..04b4502839 100644 --- a/mcstas-comps/union/Union_mesh.comp +++ b/mcstas-comps/union/Union_mesh.comp @@ -104,612 +104,580 @@ SETTING PARAMETERS(string filename = 0, //============================================================================= SHARE %{ -%include "read_table-lib" -%include "interoff-lib" + %include "read_table-lib" + %include "interoff-lib" -#ifndef Union -#error "The Union_init component must be included before this Union_mesh component" -#endif + #ifndef Union + #error "The Union_init component must be included before this Union_mesh component" + #endif -#ifndef ANY_GEOMETRY_DETECTOR_DECLARE - #define ANY_GEOMETRY_DETECTOR_DECLARE dummy - //struct pointer_to_global_geometry_list global_geometry_list = {0,NULL}; -#endif + #ifndef ANY_GEOMETRY_DETECTOR_DECLARE + #define ANY_GEOMETRY_DETECTOR_DECLARE dummy + // struct pointer_to_global_geometry_list global_geometry_list = {0,NULL}; + #endif -#ifndef MAX_VERT_DIST - #define MAX_VERT_DIST 1e-30 // Maximum distance between vertex points, before they are the same point. -#endif + #ifndef MAX_VERT_DIST + #define MAX_VERT_DIST 1e-30 // Maximum distance between vertex points, before they are the same point. + #endif -// define struct to import triangles from stl file. -#pragma pack(push, 1) // Disable padding -typedef struct { + // define struct to import triangles from stl file. + #pragma pack(push, 1) // Disable padding + typedef struct { float normal[3]; float vertex1[3]; float vertex2[3]; float vertex3[3]; uint16_t attribute_byte_count; -} Triangle; -#pragma pack(pop) -void read_stl(char* filename, - int* n_verts, - int* n_faces, - int* n_edges, - Coords** verts, - int*** faces, - char* comp_name){ - unsigned char buffer[1000]; - Triangle *triangles; - FILE *file = Open_File(filename, "r", NULL); - if (!file) { - perror("ERROR: Failed to open file"); - exit(1); - } - // Check if the file is binary or ASCII - int file_is_ascii = 0; - char word[6]; // "solid" + null terminator - if (fscanf(file, "%5s", word) == 1) { - file_is_ascii = strcmp(word, "solid") == 0; - } - fclose(file); - - if (file_is_ascii){ - - FILE *file = Open_File(filename, "r", NULL); + } Triangle; + #pragma pack(pop) + void + read_stl (char* filename, int* n_verts, int* n_faces, int* n_edges, Coords** verts, int*** faces, char* comp_name) { + unsigned char buffer[1000]; + Triangle* triangles; + FILE* file = Open_File (filename, "r", NULL); + if (!file) { + perror ("ERROR: Failed to open file"); + exit (1); + } + // Check if the file is binary or ASCII + int file_is_ascii = 0; + char word[6]; // "solid" + null terminator + if (fscanf (file, "%5s", word) == 1) { + file_is_ascii = strcmp (word, "solid") == 0; + } + fclose (file); + + if (file_is_ascii) { + + FILE* file = Open_File (filename, "r", NULL); char line[256]; int capacity = 100; // initial allocation int count = 0; // Allocate memory for triangles - triangles = (Triangle *)malloc(capacity * sizeof(Triangle)); - if (triangles == NULL){ - free(triangles); - printf("\nERROR: malloc failed for triangles"); - exit(1); + triangles = (Triangle*)malloc (capacity * sizeof (Triangle)); + if (triangles == NULL) { + free (triangles); + printf ("\nERROR: malloc failed for triangles"); + exit (1); } - + Triangle current; int vertex_index = 0; - while (fgets(line, sizeof(line), file)) { - - char *trimmed = line; - while (*trimmed == ' ' || *trimmed == '\t') { - trimmed++; - } - - // If line is empty after trimming, skip it - if (*trimmed == '\0') { - continue; - } - - if (strncmp(trimmed, "facet normal", 12) == 0) { - memset(¤t, 0, sizeof(Triangle)); - - sscanf(trimmed, "facet normal %f %f %f", - ¤t.normal[0], ¤t.normal[1], ¤t.normal[2]); - } else if (strncmp(trimmed, "vertex", 6) == 0) { - float x, y, z; - sscanf(trimmed, "vertex %f %f %f", &x, &y, &z); - if (vertex_index == 0) { - current.vertex1[0] = x; current.vertex1[1] = y; current.vertex1[2] = z; - } else if (vertex_index == 1) { - current.vertex2[0] = x; current.vertex2[1] = y; current.vertex2[2] = z; - } else if (vertex_index == 2) { - current.vertex3[0] = x; current.vertex3[1] = y; current.vertex3[2] = z; - } - vertex_index++; - if (vertex_index == 3) { - vertex_index = 0; - } - } else if (strncmp(trimmed, "endfacet", 8) == 0) { - current.attribute_byte_count = 0; // ASCII STL always 0 - if (count >= capacity) { - capacity *= 2; - void * tmp = realloc(triangles, capacity * sizeof(Triangle)); - if (tmp) { - free(triangles); - free(tmp); - perror("ERROR: Memory reallocation failed"); - fclose(file); - exit(1); - } - triangles = tmp; - } - triangles[count++] = current; - } + while (fgets (line, sizeof (line), file)) { + + char* trimmed = line; + while (*trimmed == ' ' || *trimmed == '\t') { + trimmed++; + } + + // If line is empty after trimming, skip it + if (*trimmed == '\0') { + continue; + } + + if (strncmp (trimmed, "facet normal", 12) == 0) { + memset (¤t, 0, sizeof (Triangle)); + + sscanf (trimmed, "facet normal %f %f %f", ¤t.normal[0], ¤t.normal[1], ¤t.normal[2]); + } else if (strncmp (trimmed, "vertex", 6) == 0) { + float x, y, z; + sscanf (trimmed, "vertex %f %f %f", &x, &y, &z); + if (vertex_index == 0) { + current.vertex1[0] = x; + current.vertex1[1] = y; + current.vertex1[2] = z; + } else if (vertex_index == 1) { + current.vertex2[0] = x; + current.vertex2[1] = y; + current.vertex2[2] = z; + } else if (vertex_index == 2) { + current.vertex3[0] = x; + current.vertex3[1] = y; + current.vertex3[2] = z; + } + vertex_index++; + if (vertex_index == 3) { + vertex_index = 0; + } + } else if (strncmp (trimmed, "endfacet", 8) == 0) { + current.attribute_byte_count = 0; // ASCII STL always 0 + if (count >= capacity) { + capacity *= 2; + void* tmp = realloc (triangles, capacity * sizeof (Triangle)); + if (tmp) { + free (triangles); + free (tmp); + perror ("ERROR: Memory reallocation failed"); + fclose (file); + exit (1); + } + triangles = tmp; + } + triangles[count++] = current; + } } *n_faces = count; - fclose(file); - - } else { - FILE *file = Open_File(filename, "rb", NULL); - // Read header - char header[80]; - fread(header, sizeof(char), 80, file); - - // Read number of triangles - fread(n_faces, sizeof(uint32_t), 1, file); - // Allocate memory for triangles - triangles = (Triangle *)malloc(*n_faces * sizeof(Triangle)); - - - - if (!triangles) { - perror("ERROR: Memory allocation failed"); - fclose(file); - exit(1); - } - - // Read triangles - for (int i = 0; i < *n_faces; i++) { - fread(&triangles[i], sizeof(Triangle), 1, file); - } - - fclose(file); - } - - *n_verts = 3* *n_faces; - *verts = (Coords *)malloc(sizeof(Coords)* *n_verts); - *faces = (int **)malloc(sizeof(int *)* *n_faces); - - // Now, we make a list of the triangles, and then give them each an index. - int j = 0; - for (int i = 0; i < *n_faces; i++) { - (*faces)[i] = (int *)malloc(sizeof(int)*3); - j = i*3; - (*verts)[j] = coords_set((double)triangles[i].vertex1[0], (double)triangles[i].vertex1[1], (double)triangles[i].vertex1[2]); - (*verts)[j+1] = coords_set((double)triangles[i].vertex2[0], (double)triangles[i].vertex2[1], (double)triangles[i].vertex2[2]); - (*verts)[j+2] = coords_set((double)triangles[i].vertex3[0], (double)triangles[i].vertex3[1], (double)triangles[i].vertex3[2]); + fclose (file); + + } else { + FILE* file = Open_File (filename, "rb", NULL); + // Read header + char header[80]; + fread (header, sizeof (char), 80, file); + + // Read number of triangles + fread (n_faces, sizeof (uint32_t), 1, file); + // Allocate memory for triangles + triangles = (Triangle*)malloc (*n_faces * sizeof (Triangle)); + + if (!triangles) { + perror ("ERROR: Memory allocation failed"); + fclose (file); + exit (1); + } + + // Read triangles + for (int i = 0; i < *n_faces; i++) { + fread (&triangles[i], sizeof (Triangle), 1, file); + } + + fclose (file); + } + + *n_verts = 3 * *n_faces; + *verts = (Coords*)malloc (sizeof (Coords) * *n_verts); + *faces = (int**)malloc (sizeof (int*) * *n_faces); + + // Now, we make a list of the triangles, and then give them each an index. + int j = 0; + for (int i = 0; i < *n_faces; i++) { + (*faces)[i] = (int*)malloc (sizeof (int) * 3); + j = i * 3; + (*verts)[j] = coords_set ((double)triangles[i].vertex1[0], (double)triangles[i].vertex1[1], (double)triangles[i].vertex1[2]); + (*verts)[j + 1] = coords_set ((double)triangles[i].vertex2[0], (double)triangles[i].vertex2[1], (double)triangles[i].vertex2[2]); + (*verts)[j + 2] = coords_set ((double)triangles[i].vertex3[0], (double)triangles[i].vertex3[1], (double)triangles[i].vertex3[2]); (*faces)[i][0] = j; - (*faces)[i][1] = j+1; - (*faces)[i][2] = j+2; - } - free(triangles); - // Loop over vertices, and make sure we only use unique vertices - Coords* unique_vertices = (Coords *)malloc( - sizeof(Coords)* *n_verts) ; - - int vertex_is_unique; - int x_are_equal, y_are_equal, z_are_equal; - int* map_old_to_unique = malloc(sizeof(int)* *n_verts); - int unique_counter = 0; - int vert_index_in_faces = 0; - for (int i = 0; i < *n_verts; i++) { + (*faces)[i][1] = j + 1; + (*faces)[i][2] = j + 2; + } + free (triangles); + // Loop over vertices, and make sure we only use unique vertices + Coords* unique_vertices = (Coords*)malloc (sizeof (Coords) * *n_verts); + + int vertex_is_unique; + int x_are_equal, y_are_equal, z_are_equal; + int* map_old_to_unique = malloc (sizeof (int) * *n_verts); + int unique_counter = 0; + int vert_index_in_faces = 0; + for (int i = 0; i < *n_verts; i++) { vertex_is_unique = 1; - // First we check if the vertex exist - for (j = 0; j < i; j++){ - x_are_equal = fabs((*verts)[i].x - (*verts)[j].x)=( *n_verts+2)){ - (*faces)[face_index] = (int *)malloc(sizeof(int)*3); - // The faces are always after the vertices in an off file. - sscanf(buffer,"%d %d %d %d", - &face_vertices, - &(*faces)[face_index][0], - &(*faces)[face_index][1], - &(*faces)[face_index][2]); - if (face_vertices>3){ - printf("\nERROR: Facets use more than 3 vertices." - "\n Please correct your .off file used for Component %s", - comp_name); - exit(1); - } - ++face_index; - } + if (n_lines >= (*n_verts + 2)) { + (*faces)[face_index] = (int*)malloc (sizeof (int) * 3); + // The faces are always after the vertices in an off file. + sscanf (buffer, "%d %d %d %d", &face_vertices, &(*faces)[face_index][0], &(*faces)[face_index][1], &(*faces)[face_index][2]); + if (face_vertices > 3) { + printf ("\nERROR: Facets use more than 3 vertices." + "\n Please correct your .off file used for Component %s", + comp_name); + exit (1); + } + ++face_index; + } ++n_lines; - - } - fclose(fp); -} - - - + } + fclose (fp); + } -int mesh_is_not_closed(int n_verts, int n_faces, int n_edges){ - if (n_verts - n_edges + n_faces ==2){ + int + mesh_is_not_closed (int n_verts, int n_faces, int n_edges) { + if (n_verts - n_edges + n_faces == 2) { return 0; - } - return 1; -} - -void generate_vertex_vertex_pair_list(int** faces, int** vert_pairs, - int n_faces){ - int vert1, vert2, vert3, vert_pair_0; - // Make list of vertex vertex pairs - for (int i=0; i < n_faces; i++){ + } + return 1; + } + + void + generate_vertex_vertex_pair_list (int** faces, int** vert_pairs, int n_faces) { + int vert1, vert2, vert3, vert_pair_0; + // Make list of vertex vertex pairs + for (int i = 0; i < n_faces; i++) { vert1 = faces[i][0]; vert2 = faces[i][1]; vert3 = faces[i][2]; - vert_pairs[i][0] = vert1; + vert_pairs[i][0] = vert1; vert_pairs[i][1] = vert2; vert_pairs[i + n_faces][0] = vert1; vert_pairs[i + n_faces][1] = vert3; - vert_pairs[i + 2*n_faces][0] = vert2; - vert_pairs[i + 2*n_faces][1] = vert3; - } -} - -void find_unique_vertex_vertex_pairs(int* unique_index, int** unique_verts, - int** vert_pairs, int* n_faces){ - int vert1,vert2; - int pair_is_unique; - - // Make a copy of only the unique pairs - for (int i=0; i < 3* (*n_faces); i++){ + vert_pairs[i + 2 * n_faces][0] = vert2; + vert_pairs[i + 2 * n_faces][1] = vert3; + } + } + + void + find_unique_vertex_vertex_pairs (int* unique_index, int** unique_verts, int** vert_pairs, int* n_faces) { + int vert1, vert2; + int pair_is_unique; + + // Make a copy of only the unique pairs + for (int i = 0; i < 3 * (*n_faces); i++) { // Check if the first vertex exist in the unique list vert1 = vert_pairs[i][0]; vert2 = vert_pairs[i][1]; pair_is_unique = 1; - for (int j = 0; j<(*unique_index); j++){ - if (unique_verts[j][0]==vert1){ - if (unique_verts[j][1]==vert2) { - pair_is_unique=0; - break; - } - } - else if (unique_verts[j][0]==vert2){ - if (unique_verts[j][1]==vert1) { - pair_is_unique=0; - break; - } - } + for (int j = 0; j < (*unique_index); j++) { + if (unique_verts[j][0] == vert1) { + if (unique_verts[j][1] == vert2) { + pair_is_unique = 0; + break; + } + } else if (unique_verts[j][0] == vert2) { + if (unique_verts[j][1] == vert1) { + pair_is_unique = 0; + break; + } + } } - if (pair_is_unique){ - unique_verts[*unique_index][0] = vert1; - unique_verts[*unique_index][1] = vert2; - *unique_index +=1; - + if (pair_is_unique) { + unique_verts[*unique_index][0] = vert1; + unique_verts[*unique_index][1] = vert2; + *unique_index += 1; } - } -} + } + } -int coord_comp(Coords A,Coords B) { - if (A.x==B.x && A.y==B.y && A.z==B.z){ - return 1; + int + coord_comp (Coords A, Coords B) { + if (A.x == B.x && A.y == B.y && A.z == B.z) { + return 1; } return 0; -}; -Coords get_coords_from_string(char* line){ - Coords vert_coords = coords_set(1,2,1); - return vert_coords; -} - -void mcdisplay_mesh_function(struct lines_to_draw *lines_to_draw_output,int index, struct geometry_struct **Geometries,int number_of_volumes) { - // Function to call in mcdisplay section of the sample component for this volume - - int n_facets = Geometries[index]->geometry_parameters.p_mesh_storage->n_facets; - double *v1_x = Geometries[index]->geometry_parameters.p_mesh_storage->v1_x; - double *v1_y = Geometries[index]->geometry_parameters.p_mesh_storage->v1_y; - double *v1_z = Geometries[index]->geometry_parameters.p_mesh_storage->v1_z; - double *v2_x = Geometries[index]->geometry_parameters.p_mesh_storage->v2_x; - double *v2_y = Geometries[index]->geometry_parameters.p_mesh_storage->v2_y; - double *v2_z = Geometries[index]->geometry_parameters.p_mesh_storage->v2_z; - double *v3_x = Geometries[index]->geometry_parameters.p_mesh_storage->v3_x; - double *v3_y = Geometries[index]->geometry_parameters.p_mesh_storage->v3_y; - double *v3_z = Geometries[index]->geometry_parameters.p_mesh_storage->v3_z; - - Coords center = Geometries[index]->center; - - struct lines_to_draw lines_to_draw_temp; - lines_to_draw_temp.number_of_lines = 0; - - Coords point1,point2,point3; - int iterate, i,j; - int print1 = 0; - int print2 = 0; - int print3 = 0; - - Coords *list_startpoints = (Coords*)calloc(n_facets*3,sizeof(Coords)); - Coords *list_endpoints = (Coords*)calloc(n_facets*3,sizeof(Coords)); - // Check for failed allocation - if (list_startpoints == NULL || list_endpoints == NULL){ - free(list_startpoints); - free(list_endpoints); + }; + Coords + get_coords_from_string (char* line) { + Coords vert_coords = coords_set (1, 2, 1); + return vert_coords; } - int counter=0; - // For every triangle it should add three lines - for (iterate=0 ; iteraterotation_matrix,coords_set(*(v1_x+iterate),*(v1_y+iterate),*(v1_z+iterate))),center); - point2 = coords_add(rot_apply(Geometries[index]->rotation_matrix,coords_set(*(v2_x+iterate),*(v2_y+iterate),*(v2_z+iterate))),center); - point3 = coords_add(rot_apply(Geometries[index]->rotation_matrix,coords_set(*(v3_x+iterate),*(v3_y+iterate),*(v3_z+iterate))),center); - - print1 = 1; - print2 = 1; - print3 = 1; - - // Make sure it does not print a line if it is already printed.... (might take a while?) - for (i = 0 ; i < counter ; i++){ - if (print1 == 1 && coord_comp(point1 , list_startpoints[i])){ - for (j = 0 ; j < counter ; j++){ - if (coord_comp(point2 , list_startpoints[i])){ - print1 = 0; - } - } + void + mcdisplay_mesh_function (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { + // Function to call in mcdisplay section of the sample component for this volume + + int n_facets = Geometries[index]->geometry_parameters.p_mesh_storage->n_facets; + double* v1_x = Geometries[index]->geometry_parameters.p_mesh_storage->v1_x; + double* v1_y = Geometries[index]->geometry_parameters.p_mesh_storage->v1_y; + double* v1_z = Geometries[index]->geometry_parameters.p_mesh_storage->v1_z; + double* v2_x = Geometries[index]->geometry_parameters.p_mesh_storage->v2_x; + double* v2_y = Geometries[index]->geometry_parameters.p_mesh_storage->v2_y; + double* v2_z = Geometries[index]->geometry_parameters.p_mesh_storage->v2_z; + double* v3_x = Geometries[index]->geometry_parameters.p_mesh_storage->v3_x; + double* v3_y = Geometries[index]->geometry_parameters.p_mesh_storage->v3_y; + double* v3_z = Geometries[index]->geometry_parameters.p_mesh_storage->v3_z; + + Coords center = Geometries[index]->center; + + struct lines_to_draw lines_to_draw_temp; + lines_to_draw_temp.number_of_lines = 0; + + Coords point1, point2, point3; + int iterate, i, j; + int print1 = 0; + int print2 = 0; + int print3 = 0; + + Coords* list_startpoints = (Coords*)calloc (n_facets * 3, sizeof (Coords)); + Coords* list_endpoints = (Coords*)calloc (n_facets * 3, sizeof (Coords)); + // Check for failed allocation + if (list_startpoints == NULL || list_endpoints == NULL) { + free (list_startpoints); + free (list_endpoints); + } + + int counter = 0; + // For every triangle it should add three lines + for (iterate = 0; iterate < n_facets; iterate++) { + point1 = coords_add (rot_apply (Geometries[index]->rotation_matrix, coords_set (*(v1_x + iterate), *(v1_y + iterate), *(v1_z + iterate))), center); + point2 = coords_add (rot_apply (Geometries[index]->rotation_matrix, coords_set (*(v2_x + iterate), *(v2_y + iterate), *(v2_z + iterate))), center); + point3 = coords_add (rot_apply (Geometries[index]->rotation_matrix, coords_set (*(v3_x + iterate), *(v3_y + iterate), *(v3_z + iterate))), center); + + print1 = 1; + print2 = 1; + print3 = 1; + + // Make sure it does not print a line if it is already printed.... (might take a while?) + for (i = 0; i < counter; i++) { + if (print1 == 1 && coord_comp (point1, list_startpoints[i])) { + for (j = 0; j < counter; j++) { + if (coord_comp (point2, list_startpoints[i])) { + print1 = 0; + } + } + } + if (print2 == 1 && coord_comp (point2, list_startpoints[i])) { + for (j = 0; j < counter; j++) { + if (coord_comp (point1, list_startpoints[i])) { + print1 = 0; + } + } + } + if (print2 == 1 && coord_comp (point2, list_startpoints[i])) { + for (j = 0; j < counter; j++) { + if (coord_comp (point3, list_startpoints[i])) { + print2 = 0; + } + } + } + if (print3 == 1 && coord_comp (point3, list_startpoints[i])) { + for (j = 0; j < counter; j++) { + if (coord_comp (point2, list_startpoints[i])) { + print2 = 0; + } + } + } + if (print1 == 1 && coord_comp (point1, list_startpoints[i])) { + for (j = 0; j < counter; j++) { + if (coord_comp (point1, list_startpoints[i])) { + print3 = 0; + } + } + } + if (print3 == 1 && coord_comp (point3, list_startpoints[i])) { + for (j = 0; j < counter; j++) { + if (coord_comp (point1, list_startpoints[i])) { + print3 = 0; + } + } + } } - if (print2 == 1 && coord_comp(point2 , list_startpoints[i])){ - for (j = 0 ; j < counter ; j++){ - if (coord_comp(point1 , list_startpoints[i])){ - print1 = 0; - } - } + + // Create lines + // Line 1 + if (print1 == 1) { + lines_to_draw_temp = draw_line_with_highest_priority (point1, point2, index, Geometries, number_of_volumes, 100); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); + list_startpoints[counter] = point1; + list_endpoints[counter] = point2; + counter++; } - if (print2 == 1 && coord_comp(point2 , list_startpoints[i]) ){ - for (j = 0 ; j < counter ; j++){ - if (coord_comp(point3 , list_startpoints[i])){ - print2 = 0; - } - } + // Line 2 + if (print2 == 1) { + lines_to_draw_temp = draw_line_with_highest_priority (point2, point3, index, Geometries, number_of_volumes, 100); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); + list_startpoints[counter] = point2; + list_endpoints[counter] = point3; + counter++; } - if (print3 == 1 && coord_comp(point3 , list_startpoints[i]) ){ - for (j = 0 ; j < counter ; j++){ - if (coord_comp(point2 , list_startpoints[i])){ - print2 = 0; - } - } + // Line 3 + if (print3 == 1) { + lines_to_draw_temp = draw_line_with_highest_priority (point3, point1, index, Geometries, number_of_volumes, 100); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); + list_startpoints[counter] = point3; + list_endpoints[counter] = point1; + counter++; } - if (print1 == 1 && coord_comp(point1 , list_startpoints[i]) ){ - for (j = 0 ; j < counter ; j++){ - if (coord_comp(point1 , list_startpoints[i])){ - print3 = 0; - } - } + } + free (list_startpoints); + free (list_endpoints); + }; + + struct pointer_to_1d_coords_list + allocate_shell_points (struct geometry_struct* geometry, int max_number_of_points) { + // Function that returns a number (less than max) of points on the geometry surface + // Run trhough all points in list of faces, and remove dublicates + // There are three points in a face and very often these will be dublicated a few times. This removes dublicates to boost performance down stream... + + struct pointer_to_1d_coords_list mesh_shell_array; + + int n_facets = geometry->geometry_parameters.p_mesh_storage->n_facets; + double* v1_x = geometry->geometry_parameters.p_mesh_storage->v1_x; + double* v1_y = geometry->geometry_parameters.p_mesh_storage->v1_y; + double* v1_z = geometry->geometry_parameters.p_mesh_storage->v1_z; + double* v2_x = geometry->geometry_parameters.p_mesh_storage->v2_x; + double* v2_y = geometry->geometry_parameters.p_mesh_storage->v2_y; + double* v2_z = geometry->geometry_parameters.p_mesh_storage->v2_z; + double* v3_x = geometry->geometry_parameters.p_mesh_storage->v3_x; + double* v3_y = geometry->geometry_parameters.p_mesh_storage->v3_y; + double* v3_z = geometry->geometry_parameters.p_mesh_storage->v3_z; + int number_of_points_in_array = 0; + mesh_shell_array.elements = malloc (3 * n_facets * sizeof (Coords)); + int is_dublicate = 0; + Coords this_vert; + int i, j; + for (i = 0; i < n_facets; i++) { + + // v1 + is_dublicate = 0; + this_vert = coords_set (*(v1_x + i), *(v1_y + i), *(v1_z + i)); + + // test if dublicate + for (j = 0; j < number_of_points_in_array; j++) { + if (this_vert.x == mesh_shell_array.elements[j].x && this_vert.y == mesh_shell_array.elements[j].y && this_vert.z == mesh_shell_array.elements[j].z) { + is_dublicate = 1; + j = number_of_points_in_array; + } } - if (print3 == 1 && coord_comp(point3 , list_startpoints[i])){ - for (j = 0 ; j < counter ; j++){ - if (coord_comp(point1 , list_startpoints[i])){ - print3 = 0; - } - } + if (is_dublicate == 0) { + mesh_shell_array.elements[number_of_points_in_array] = this_vert; + number_of_points_in_array += 1; } - - } + // v2 + is_dublicate = 0; + this_vert = coords_set (*(v2_x + i), *(v2_y + i), *(v2_z + i)); - // Create lines - // Line 1 - if (print1 == 1){ - lines_to_draw_temp = draw_line_with_highest_priority(point1,point2,index,Geometries,number_of_volumes,100); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - list_startpoints[counter] = point1; - list_endpoints[counter] = point2; - counter++; - } - // Line 2 - if (print2 == 1){ - lines_to_draw_temp = draw_line_with_highest_priority(point2,point3,index,Geometries,number_of_volumes,100); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - list_startpoints[counter] = point2; - list_endpoints[counter] = point3; - counter++; - } - // Line 3 - if (print3 == 1){ - lines_to_draw_temp = draw_line_with_highest_priority(point3,point1,index,Geometries,number_of_volumes,100); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - list_startpoints[counter] = point3; - list_endpoints[counter] = point1; - counter++; + for (j = 0; j < number_of_points_in_array; j++) { + if (this_vert.x == mesh_shell_array.elements[j].x && this_vert.y == mesh_shell_array.elements[j].y && this_vert.z == mesh_shell_array.elements[j].z) { + is_dublicate = 1; + j = number_of_points_in_array; + } + } + if (is_dublicate == 0) { + mesh_shell_array.elements[number_of_points_in_array] = this_vert; + number_of_points_in_array += 1; + } + + // v3 + is_dublicate = 0; + this_vert = coords_set (*(v3_x + i), *(v3_y + i), *(v3_z + i)); + + // test if dublicate + for (j = 0; j < number_of_points_in_array; j++) { + if (this_vert.x == mesh_shell_array.elements[j].x && this_vert.y == mesh_shell_array.elements[j].y && this_vert.z == mesh_shell_array.elements[j].z) { + is_dublicate = 1; + j = number_of_points_in_array; + } + } + if (is_dublicate == 0) { + mesh_shell_array.elements[number_of_points_in_array] = this_vert; + number_of_points_in_array += 1; + } } - } - free(list_startpoints); - free(list_endpoints); -}; - - -struct pointer_to_1d_coords_list allocate_shell_points(struct geometry_struct *geometry,int max_number_of_points) { - // Function that returns a number (less than max) of points on the geometry surface - // Run trhough all points in list of faces, and remove dublicates - // There are three points in a face and very often these will be dublicated a few times. This removes dublicates to boost performance down stream... - - - struct pointer_to_1d_coords_list mesh_shell_array; - - int n_facets = geometry->geometry_parameters.p_mesh_storage->n_facets; - double *v1_x = geometry->geometry_parameters.p_mesh_storage->v1_x; - double *v1_y = geometry->geometry_parameters.p_mesh_storage->v1_y; - double *v1_z = geometry->geometry_parameters.p_mesh_storage->v1_z; - double *v2_x = geometry->geometry_parameters.p_mesh_storage->v2_x; - double *v2_y = geometry->geometry_parameters.p_mesh_storage->v2_y; - double *v2_z = geometry->geometry_parameters.p_mesh_storage->v2_z; - double *v3_x = geometry->geometry_parameters.p_mesh_storage->v3_x; - double *v3_y = geometry->geometry_parameters.p_mesh_storage->v3_y; - double *v3_z = geometry->geometry_parameters.p_mesh_storage->v3_z; - int number_of_points_in_array = 0; - mesh_shell_array.elements = malloc(3*n_facets * sizeof(Coords)); - int is_dublicate = 0; - Coords this_vert; - int i,j; - for (i=0 ; i < n_facets ; i++){ - - // v1 - is_dublicate = 0; - this_vert = coords_set(*(v1_x+i),*(v1_y+i),*(v1_z+i)); - - // test if dublicate - for (j = 0; j < number_of_points_in_array ; j++ ){ - if (this_vert.x == mesh_shell_array.elements[j].x && this_vert.y == mesh_shell_array.elements[j].y && this_vert.z == mesh_shell_array.elements[j].z){ - is_dublicate = 1; - j = number_of_points_in_array; - } - } - if (is_dublicate == 0){ - mesh_shell_array.elements[number_of_points_in_array] = this_vert; - number_of_points_in_array += 1; - } - - - - // v2 - is_dublicate = 0; - this_vert = coords_set(*(v2_x+i),*(v2_y+i),*(v2_z+i)); - - for (j = 0; j < number_of_points_in_array ; j++){ - if (this_vert.x == mesh_shell_array.elements[j].x && this_vert.y == mesh_shell_array.elements[j].y && this_vert.z == mesh_shell_array.elements[j].z){ - is_dublicate = 1; - j = number_of_points_in_array; - } - } - if (is_dublicate == 0){ - mesh_shell_array.elements[number_of_points_in_array] = this_vert; - number_of_points_in_array += 1; - } - - - - // v3 - is_dublicate = 0; - this_vert = coords_set(*(v3_x+i),*(v3_y+i),*(v3_z+i)); - - // test if dublicate - for (j = 0; j < number_of_points_in_array ; j++ ){ - if (this_vert.x == mesh_shell_array.elements[j].x && this_vert.y == mesh_shell_array.elements[j].y && this_vert.z == mesh_shell_array.elements[j].z){ - is_dublicate = 1; - j = number_of_points_in_array; - } - } - if (is_dublicate == 0){ - mesh_shell_array.elements[number_of_points_in_array] = this_vert; - number_of_points_in_array += 1; - } - } - - j = number_of_points_in_array - 1; // Last legal index, currently j is out of bounds. - - mesh_shell_array.num_elements = number_of_points_in_array; - - - for (i=0; icenter); - mesh_shell_array.elements[i] = rot_apply(geometry->rotation_matrix, mesh_shell_array.elements[i]); - } - return mesh_shell_array; -} + j = number_of_points_in_array - 1; // Last legal index, currently j is out of bounds. + mesh_shell_array.num_elements = number_of_points_in_array; -void initialize_mesh_geometry_from_main_component(struct geometry_struct *mesh) { + for (i = 0; i < number_of_points_in_array; i++) { + // Transpose and rotate the points such that they are in the right coordinate system + mesh_shell_array.elements[i] = coords_add (mesh_shell_array.elements[i], geometry->center); + mesh_shell_array.elements[i] = rot_apply (geometry->rotation_matrix, mesh_shell_array.elements[i]); + } + return mesh_shell_array; + } + + void + initialize_mesh_geometry_from_main_component (struct geometry_struct* mesh) { // Function to be called in initialize of the main component // This is done as the rotation matrix needs to be relative to the main component instead of global // Everything done in initialize in this component file has the rotation matrix relative to global - + Coords simple_vector; Coords mesh_vector; - + // Start with vector that points along the mesh in the local frame - simple_vector = coords_set(0,1,0); + simple_vector = coords_set (0, 1, 0); // Rotate the direction vector of the mesh to the master component frame of reference - mesh_vector = rot_apply(mesh->rotation_matrix,simple_vector); - NORM(mesh_vector.x,mesh_vector.y,mesh_vector.z); + mesh_vector = rot_apply (mesh->rotation_matrix, simple_vector); + NORM (mesh_vector.x, mesh_vector.y, mesh_vector.z); mesh->geometry_parameters.p_mesh_storage->direction_vector.x = mesh_vector.x; mesh->geometry_parameters.p_mesh_storage->direction_vector.y = mesh_vector.y; mesh->geometry_parameters.p_mesh_storage->direction_vector.z = mesh_vector.z; - - mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center = rot_apply(mesh->rotation_matrix, mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center); - + + mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center + = rot_apply (mesh->rotation_matrix, mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center); + /* // Works for pure translation print_position(mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center, "BB before adjustment"); mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center = coords_add(mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center, mesh->center); print_position(mesh->geometry_parameters.p_mesh_storage->Bounding_Box_Center, "BB after adjustment"); */ -} - - -double square(double x){ - return x*x; -} + } + double + square (double x) { + return x * x; + } %} //============================================================================= @@ -717,29 +685,26 @@ double square(double x){ //============================================================================= DECLARE %{ -// Needed for transport to the main component -struct global_geometry_element_struct global_geometry_element; - -int loop_index; -int loop_2_index; -int material_index; -off_struct offdata; // off struct isnt currently in use - -// Volume struct contains name, geometry struct, physics struct -// loggers struct and absorption loggers struct. -struct Volume_struct mesh_vol; - -// Mesh storage contains the number of facets, and for each facet -// the three vertexes coordinates. Not in an optimal way. -// However, the Bounding box center and radius is also stored here. -struct mesh_storage mesh_data; - -// Structs for surface effects -struct surface_stack_struct surface_stack; -struct surface_stack_struct cut_surface_stack; - - - + // Needed for transport to the main component + struct global_geometry_element_struct global_geometry_element; + + int loop_index; + int loop_2_index; + int material_index; + off_struct offdata; // off struct isnt currently in use + + // Volume struct contains name, geometry struct, physics struct + // loggers struct and absorption loggers struct. + struct Volume_struct mesh_vol; + + // Mesh storage contains the number of facets, and for each facet + // the three vertexes coordinates. Not in an optimal way. + // However, the Bounding box center and radius is also stored here. + struct mesh_storage mesh_data; + + // Structs for surface effects + struct surface_stack_struct surface_stack; + struct surface_stack_struct cut_surface_stack; %} //============================================================================= // INITIALIZE SECTION @@ -747,413 +712,345 @@ struct surface_stack_struct cut_surface_stack; INITIALIZE %{ -geometry_struct_init(&(mesh_vol.geometry)); -mesh_vol.geometry.skip_hierarchy_optimization = skip_convex_check; -// Initializes the focusing system for this volume including input sanitation. -focus_initialize(&mesh_vol.geometry, - POS_A_COMP_INDEX(INDEX_CURRENT_COMP+target_index), - POS_A_CURRENT_COMP, - ROT_A_CURRENT_COMP, - target_index, - target_x, - target_y, - target_z, - focus_aw, - focus_ah, - focus_xw, - focus_xh, - focus_r, - NAME_CURRENT_COMP); - - - -if (_getcomp_index(init) < 0) { - fprintf(stderr,"Union_mesh:%s: Error identifying Union_init component," - "%s is not a known component name.\n",NAME_CURRENT_COMP, init); -exit(-1); -} -struct pointer_to_global_material_list *global_material_list = COMP_GETPAR3( - Union_init, - init, - global_material_list); - -// Use sanitation -#ifdef MATERIAL_DETECTOR -if (global_material_list->num_elements == 0) { - // Here if the user have defined a material, but only after this material - printf("\nERROR: Need to define a material using Union_make_material" + geometry_struct_init (&(mesh_vol.geometry)); + mesh_vol.geometry.skip_hierarchy_optimization = skip_convex_check; + // Initializes the focusing system for this volume including input sanitation. + focus_initialize (&mesh_vol.geometry, POS_A_COMP_INDEX (INDEX_CURRENT_COMP + target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, target_x, + target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); + + if (_getcomp_index (init) < 0) { + fprintf (stderr, + "Union_mesh:%s: Error identifying Union_init component," + "%s is not a known component name.\n", + NAME_CURRENT_COMP, init); + exit (-1); + } + struct pointer_to_global_material_list* global_material_list = COMP_GETPAR3 (Union_init, init, global_material_list); + + // Use sanitation + #ifdef MATERIAL_DETECTOR + if (global_material_list->num_elements == 0) { + // Here if the user have defined a material, but only after this material + printf ("\nERROR: Need to define a material using Union_make_material" + " before using a Union geometry component. \n"); + printf ("%s was defined before first use of Union_make_material.\n", NAME_CURRENT_COMP); + exit (1); + } + + #endif + #ifndef MATERIAL_DETECTOR + printf ("\nERROR: Need to define a material using Union_make_material" " before using a Union geometry component. \n"); - printf("%s was defined before first use of Union_make_material.\n",NAME_CURRENT_COMP); - exit(1); -} - -#endif -#ifndef MATERIAL_DETECTOR -printf("\nERROR: Need to define a material using Union_make_material" - " before using a Union geometry component. \n"); - exit(1); -#endif - - -mesh_vol.geometry.is_masked_volume = 0; -mesh_vol.geometry.is_exit_volume = 0; -mesh_vol.geometry.is_mask_volume = 0; - -struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, - init, - global_geometry_list); -//============================================================================== -// Find out what this component masks -//============================================================================== - - - -// Read the material input, or if it lacks, use automatic linking. -if (mask_string && - strlen(mask_string) && - strcmp(mask_string, "NULL") && - strcmp(mask_string, "0")) { - // A mask volume is used to limit the extend of other volumes, - // called the masked volumes. These are specified in the mask_string. - // In order for a ray to enter a masked volume, - // it needs to be both in the region covered by that volume AND the mask volume. + exit (1); + #endif + + mesh_vol.geometry.is_masked_volume = 0; + mesh_vol.geometry.is_exit_volume = 0; + mesh_vol.geometry.is_mask_volume = 0; + + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + //============================================================================== + // Find out what this component masks + //============================================================================== + + // Read the material input, or if it lacks, use automatic linking. + if (mask_string && strlen (mask_string) && strcmp (mask_string, "NULL") && strcmp (mask_string, "0")) { + // A mask volume is used to limit the extend of other volumes, + // called the masked volumes. These are specified in the mask_string. + // In order for a ray to enter a masked volume, + // it needs to be both in the region covered by that volume AND the mask volume. // When more than mesh_vol.geometry.mask_mode = 1; // Default mask mode is ALL - if (mask_setting && strlen(mask_setting) && strcmp(mask_setting, - "NULL") && strcmp(mask_setting, "0")) { - if (strcmp(mask_setting,"ALL") == 0 || strcmp(mask_setting,"All") == 0) { - mesh_vol.geometry.mask_mode = 1; - } - else if (strcmp(mask_setting,"ANY") == 0 || strcmp(mask_setting,"Any") == 0) { - mesh_vol.geometry.mask_mode = 2; - } - else { - printf("The mask_mode of component %s is set to %s," + if (mask_setting && strlen (mask_setting) && strcmp (mask_setting, "NULL") && strcmp (mask_setting, "0")) { + if (strcmp (mask_setting, "ALL") == 0 || strcmp (mask_setting, "All") == 0) { + mesh_vol.geometry.mask_mode = 1; + } else if (strcmp (mask_setting, "ANY") == 0 || strcmp (mask_setting, "Any") == 0) { + mesh_vol.geometry.mask_mode = 2; + } else { + printf ("The mask_mode of component %s is set to %s," " but must be either ALL or ANY.\n", - NAME_CURRENT_COMP,mask_setting); - exit(1); - } + NAME_CURRENT_COMP, mask_setting); + exit (1); + } } - + int found_geometries = 0; - for (loop_index=0;loop_indexnum_elements;loop_index++) { - // Add mask list - - if (1 == manual_linking_function(global_geometry_list->elements[loop_index].name,mask_string)) { - add_element_to_int_list(&mesh_vol.geometry.mask_list,global_geometry_list->elements[loop_index].component_index); - add_element_to_int_list(&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list,INDEX_CURRENT_COMP); - global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; - if (mesh_vol.geometry.mask_mode == 2) - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; - if (mesh_vol.geometry.mask_mode == 1) { - if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) - // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; - } - - found_geometries = 1; + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + // Add mask list + + if (1 == manual_linking_function (global_geometry_list->elements[loop_index].name, mask_string)) { + add_element_to_int_list (&mesh_vol.geometry.mask_list, global_geometry_list->elements[loop_index].component_index); + add_element_to_int_list (&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list, INDEX_CURRENT_COMP); + global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; + if (mesh_vol.geometry.mask_mode == 2) + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; + if (mesh_vol.geometry.mask_mode == 1) { + if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 + && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) + // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; } + + found_geometries = 1; + } } if (found_geometries == 0) { - printf("The mask_string in geometry: " - "%s did not find any of the specified volumes in the mask_string " - "%s \n",NAME_CURRENT_COMP,mask_string); - exit(1); + printf ("The mask_string in geometry: " + "%s did not find any of the specified volumes in the mask_string " + "%s \n", + NAME_CURRENT_COMP, mask_string); + exit (1); } - mesh_vol.p_physics = malloc(sizeof(struct physics_struct)); - mesh_vol.p_physics->is_vacuum = 0; // Makes this volume a vacuum - mesh_vol.p_physics->number_of_processes = (int) 0; // Should not be used. - mesh_vol.p_physics->my_a = 0; // Should not be used. - sprintf(mesh_vol.p_physics->name,"Mask"); + mesh_vol.p_physics = malloc (sizeof (struct physics_struct)); + mesh_vol.p_physics->is_vacuum = 0; // Makes this volume a vacuum + mesh_vol.p_physics->number_of_processes = (int)0; // Should not be used. + mesh_vol.p_physics->my_a = 0; // Should not be used. + sprintf (mesh_vol.p_physics->name, "Mask"); mesh_vol.geometry.is_mask_volume = 1; - - -// Read the material input, or if it lacks, use automatic linking. -} else if (material_string - && strlen(material_string) - && strcmp(material_string, "NULL") - && strcmp(material_string, "0")) { + + // Read the material input, or if it lacks, use automatic linking. + } else if (material_string && strlen (material_string) && strcmp (material_string, "NULL") && strcmp (material_string, "0")) { // A geometry string was given, use it to determine which material - if (0 == strcmp(material_string,"vacuum") - || 0 == strcmp(material_string,"Vacuum")) { - // One could have a global physics struct for vacuum instead of creating one for each - mesh_vol.p_physics = malloc(sizeof(struct physics_struct)); - mesh_vol.p_physics->is_vacuum = 1; // Makes this volume a vacuum - mesh_vol.p_physics->number_of_processes = (int) 0; - mesh_vol.p_physics->my_a = 0; // Should not be used. - sprintf(mesh_vol.p_physics->name,"Vacuum"); - } else if (0 == strcmp(material_string,"exit") - || 0 == strcmp(material_string,"Exit")) { - // One could have a global physics struct for exit instead of creating one for each - mesh_vol.p_physics = malloc(sizeof(struct physics_struct)); - mesh_vol.p_physics->is_vacuum = 1; // Makes this volume a vacuum - mesh_vol.p_physics->number_of_processes = (int) 0; - mesh_vol.p_physics->my_a = 0; // Should not be used. - mesh_vol.geometry.is_exit_volume = 1; - sprintf(mesh_vol.p_physics->name,"Exit"); + if (0 == strcmp (material_string, "vacuum") || 0 == strcmp (material_string, "Vacuum")) { + // One could have a global physics struct for vacuum instead of creating one for each + mesh_vol.p_physics = malloc (sizeof (struct physics_struct)); + mesh_vol.p_physics->is_vacuum = 1; // Makes this volume a vacuum + mesh_vol.p_physics->number_of_processes = (int)0; + mesh_vol.p_physics->my_a = 0; // Should not be used. + sprintf (mesh_vol.p_physics->name, "Vacuum"); + } else if (0 == strcmp (material_string, "exit") || 0 == strcmp (material_string, "Exit")) { + // One could have a global physics struct for exit instead of creating one for each + mesh_vol.p_physics = malloc (sizeof (struct physics_struct)); + mesh_vol.p_physics->is_vacuum = 1; // Makes this volume a vacuum + mesh_vol.p_physics->number_of_processes = (int)0; + mesh_vol.p_physics->my_a = 0; // Should not be used. + mesh_vol.geometry.is_exit_volume = 1; + sprintf (mesh_vol.p_physics->name, "Exit"); } else { - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (0 == strcmp(material_string,global_material_list->elements[loop_index].name)) { - mesh_vol.p_physics = global_material_list->elements[loop_index].physics; - break; - } - if (loop_index == global_material_list->num_elements-1) { - printf("\n"); - printf("ERROR: The material string \"%s\" in Union geometry \"%s\"" - " did not match a specified material. \n",material_string,NAME_CURRENT_COMP); - printf(" The materials available at this point" - " (need to be defined before the geometry): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_material_list->elements[loop_index].name); - printf("\n"); - printf(" It is also possible to use one of the defualt materials avaiable: \n"); - printf(" Vacuum (for a Volume without scattering or absorption)\n"); - printf(" Exit (for a Volume where the ray exits the component if it enters)\n"); - printf(" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); - exit(1); - } + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) { + if (0 == strcmp (material_string, global_material_list->elements[loop_index].name)) { + mesh_vol.p_physics = global_material_list->elements[loop_index].physics; + break; + } + if (loop_index == global_material_list->num_elements - 1) { + printf ("\n"); + printf ("ERROR: The material string \"%s\" in Union geometry \"%s\"" + " did not match a specified material. \n", + material_string, NAME_CURRENT_COMP); + printf (" The materials available at this point" + " (need to be defined before the geometry): \n"); + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) + printf (" %s\n", global_material_list->elements[loop_index].name); + printf ("\n"); + printf (" It is also possible to use one of the defualt materials avaiable: \n"); + printf (" Vacuum (for a Volume without scattering or absorption)\n"); + printf (" Exit (for a Volume where the ray exits the component if it enters)\n"); + printf (" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); + exit (1); } + } } -} else { + } else { // Automatic linking, simply using the last defined material. #ifndef MATERIAL_DETECTOR - printf("Need to define a material before the geometry to use automatic linking %s.\n",NAME_CURRENT_COMP); - exit(1); + printf ("Need to define a material before the geometry to use automatic linking %s.\n", NAME_CURRENT_COMP); + exit (1); #endif - mesh_vol.p_physics = global_material_list->elements[global_material_list->num_elements-1].physics; -} -//============================================================================== -// READ FIle -//============================================================================== -// Read input file and put into storage. -// We assume that the input file is using triangular faces, otherwise -// the check for closed mesh using the Euler-Poincare characteristic -// is wrong. -int n_verts = 0; -int n_faces = 0; -int n_edges = 0; -Coords* verts; -Coords tmp_vert = coords_set(0,0,0); -verts = &tmp_vert; // This tmp vert is just for linter play... -int** faces; -int unique_index = 0; - -const char *dot = strrchr(filename, '.'); -if (!dot || dot == filename) { - printf("ERROR: given file has no extension %s", NAME_CURRENT_COMP); - exit(1); -} -if(strcmp(dot, ".stl") == 0 || strcmp(dot, ".STL") == 0){ - printf("\n%s, Given file is in stl format. Union_mesh assumes three vertices per face.\n", - NAME_CURRENT_COMP); - read_stl(filename, - &n_verts, - &n_faces, - &n_edges, - &verts, - &faces, - NAME_CURRENT_COMP); -} else if (strcmp(dot, ".off") == 0 || strcmp(dot, ".OFF") == 0) { - printf("\n%s, Given file is in off format. Union_mesh assumes three vertices per face.\n", - NAME_CURRENT_COMP); - read_off_file_vertices_and_faces(filename, - &n_verts, - &n_faces, - &n_edges, - &verts, - &faces, - NAME_CURRENT_COMP); -} else { - printf("\nERROR IN %s: File %s is read as neither an stl or an off file.", - NAME_CURRENT_COMP, filename); - exit(1); -} -printf("\nCOMPONENT %s: Number of faces read: %d\t Number of vertices read: %d\n", - NAME_CURRENT_COMP, n_verts, n_faces); -// Loop over all vertices and multiply their positions with coordinate_scale -for (int i = 0; ielements[global_material_list->num_elements - 1].physics; + } + //============================================================================== + // READ FIle + //============================================================================== + // Read input file and put into storage. + // We assume that the input file is using triangular faces, otherwise + // the check for closed mesh using the Euler-Poincare characteristic + // is wrong. + int n_verts = 0; + int n_faces = 0; + int n_edges = 0; + Coords* verts; + Coords tmp_vert = coords_set (0, 0, 0); + verts = &tmp_vert; // This tmp vert is just for linter play... + int** faces; + int unique_index = 0; + + const char* dot = strrchr (filename, '.'); + if (!dot || dot == filename) { + printf ("ERROR: given file has no extension %s", NAME_CURRENT_COMP); + exit (1); + } + if (strcmp (dot, ".stl") == 0 || strcmp (dot, ".STL") == 0) { + printf ("\n%s, Given file is in stl format. Union_mesh assumes three vertices per face.\n", NAME_CURRENT_COMP); + read_stl (filename, &n_verts, &n_faces, &n_edges, &verts, &faces, NAME_CURRENT_COMP); + } else if (strcmp (dot, ".off") == 0 || strcmp (dot, ".OFF") == 0) { + printf ("\n%s, Given file is in off format. Union_mesh assumes three vertices per face.\n", NAME_CURRENT_COMP); + read_off_file_vertices_and_faces (filename, &n_verts, &n_faces, &n_edges, &verts, &faces, NAME_CURRENT_COMP); + } else { + printf ("\nERROR IN %s: File %s is read as neither an stl or an off file.", NAME_CURRENT_COMP, filename); + exit (1); + } + printf ("\nCOMPONENT %s: Number of faces read: %d\t Number of vertices read: %d\n", NAME_CURRENT_COMP, n_verts, n_faces); + // Loop over all vertices and multiply their positions with coordinate_scale + for (int i = 0; i < n_verts; i++) { + verts[i] = coords_scale (verts[i], coordinate_scale); + } + + // Make lists that will be used to calculate the number of edges + int** vert_pairs = (int**)malloc (sizeof (int*) * 3 * n_faces); + int** unique_verts = (int**)malloc (sizeof (int*) * 3 * n_faces); + // Check for failing mallocs + if (vert_pairs == NULL || unique_verts == NULL) { + free (vert_pairs); + free (unique_verts); + printf ("ERROR: malloc failed on vert pairs or unique verts"); + exit (1); + } + for (int i = 0; i < 3 * n_faces; i++) { + vert_pairs[i] = (int*)malloc (sizeof (int) * 2); + unique_verts[i] = (int*)malloc (sizeof (int) * 2); + if (vert_pairs[i] == NULL || unique_verts[i] == NULL) { // Should probably be a loop over all vert pairs - free(vert_pairs[i]); - free(unique_verts[i]); - printf("\nERROR: malloc failed on specific vert pairs or unique verts"); - exit(1); - } -} - -generate_vertex_vertex_pair_list(faces, vert_pairs, n_faces); - -find_unique_vertex_vertex_pairs(&unique_index, unique_verts, - vert_pairs, &n_faces); - -n_edges = unique_index; // The number of edges is the number of unique - // vertex vertex pairs. -if (mesh_is_not_closed(n_faces,n_verts,n_edges) && !skip_convex_check){ - printf("\nNumber of edges is the unique index, %d", unique_index); - printf("\nEuler Pointcare characteristic is %d", - n_faces + n_verts - unique_index); - - printf("\n\nERROR: Input mesh from %s, is not a closed shape according to Euler Pointcare." - "\nNumber of faces = %d, Number of vertices = %d, Number of Edges = %d" - "\nUnion_mesh_off requires the user input to be a convex hull.\n" - "If you are sure that it is, set skip_convex_check to 1\n\n", - NAME_CURRENT_COMP,n_faces, n_verts,n_edges); - exit(1); -} - -// Calculate bounding box -double max_dist = 0; -double dist = 0; -if (n_verts <= 0 ){ - printf("\nERROR: Number of vertices read is 0\n"); - exit(1); -} -Coords B_sphere_x = verts[0]; -Coords B_sphere_y = B_sphere_x; - -for (int i = 0; imax_dist){ + free (vert_pairs[i]); + free (unique_verts[i]); + printf ("\nERROR: malloc failed on specific vert pairs or unique verts"); + exit (1); + } + } + + generate_vertex_vertex_pair_list (faces, vert_pairs, n_faces); + + find_unique_vertex_vertex_pairs (&unique_index, unique_verts, vert_pairs, &n_faces); + + n_edges = unique_index; // The number of edges is the number of unique + // vertex vertex pairs. + if (mesh_is_not_closed (n_faces, n_verts, n_edges) && !skip_convex_check) { + printf ("\nNumber of edges is the unique index, %d", unique_index); + printf ("\nEuler Pointcare characteristic is %d", n_faces + n_verts - unique_index); + + printf ("\n\nERROR: Input mesh from %s, is not a closed shape according to Euler Pointcare." + "\nNumber of faces = %d, Number of vertices = %d, Number of Edges = %d" + "\nUnion_mesh_off requires the user input to be a convex hull.\n" + "If you are sure that it is, set skip_convex_check to 1\n\n", + NAME_CURRENT_COMP, n_faces, n_verts, n_edges); + exit (1); + } + + // Calculate bounding box + double max_dist = 0; + double dist = 0; + if (n_verts <= 0) { + printf ("\nERROR: Number of vertices read is 0\n"); + exit (1); + } + Coords B_sphere_x = verts[0]; + Coords B_sphere_y = B_sphere_x; + + for (int i = 0; i < n_verts; i++) { + dist = sqrt (B_sphere_x.x - verts[i].x + B_sphere_x.y - verts[i].y + B_sphere_x.z - verts[i].z); + if (dist > max_dist) { max_dist = dist; B_sphere_y = verts[i]; - } -} -Coords B_sphere_z = B_sphere_y; -max_dist = 0; -for (int i=0; imax_dist){ + } + } + Coords B_sphere_z = B_sphere_y; + max_dist = 0; + for (int i = 0; i < n_verts; i++) { + dist = sqrt (square (B_sphere_y.x - verts[i].x) + square (B_sphere_y.y - verts[i].y) + square (B_sphere_y.z - verts[i].z)); + + if (dist > max_dist) { max_dist = dist; B_sphere_z = verts[i]; - } -} -double radius = sqrt(square(B_sphere_y.x-B_sphere_z.x) - + square(B_sphere_y.y-B_sphere_z.y) - + square(B_sphere_y.z-B_sphere_z.z))/2; -Coords bbcenter = coords_set((B_sphere_y.x + B_sphere_z.x)/2, - (B_sphere_y.y + B_sphere_z.y)/2, - (B_sphere_y.z + B_sphere_z.z)/2); -mesh_data.Bounding_Box_Center = bbcenter; -double test_rad = 0; -for (int i=0; iradius){ + } + } + double radius = sqrt (square (B_sphere_y.x - B_sphere_z.x) + square (B_sphere_y.y - B_sphere_z.y) + square (B_sphere_y.z - B_sphere_z.z)) / 2; + Coords bbcenter = coords_set ((B_sphere_y.x + B_sphere_z.x) / 2, (B_sphere_y.y + B_sphere_z.y) / 2, (B_sphere_y.z + B_sphere_z.z) / 2); + mesh_data.Bounding_Box_Center = bbcenter; + double test_rad = 0; + for (int i = 0; i < n_verts; i++) { + test_rad = sqrt (square (bbcenter.x - verts[i].x) + square (bbcenter.y - verts[i].y) + square (bbcenter.z - verts[i].z)); + if (test_rad > radius) { radius = test_rad; - } -} -mesh_data.Bounding_Box_Radius = radius; - - - - -Coords vert1, vert2, vert3; -Coords edge1, edge2; -// Allocate space vertices in mesh data -// TODO: Change data format to be in a less verbose data structure, or a more effective one. -mesh_data.v1_x = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v1_y = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v1_z = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v2_x = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v2_y = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v2_z = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v3_x = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v3_y = (double *)malloc(n_faces*sizeof(double)); -mesh_data.v3_z = (double *)malloc(n_faces*sizeof(double)); -mesh_data.normal_x = (double *)malloc(n_faces*sizeof(double)); -mesh_data.normal_y = (double *)malloc(n_faces*sizeof(double)); -mesh_data.normal_z = (double *)malloc(n_faces*sizeof(double)); -for (int i=0; igeometry_parameters.p_sphere_storage->sph_radius; Coords center = Geometries[index]->center; - - Coords direction1 = coords_set(0,0,1.0); - Coords direction2 = coords_set(0,1.0,0); - Coords direction3 = coords_set(1.0,0,0); - + + Coords direction1 = coords_set (0, 0, 1.0); + Coords direction2 = coords_set (0, 1.0, 0); + Coords direction3 = coords_set (1.0, 0, 0); + struct lines_to_draw lines_to_draw_temp; lines_to_draw_temp.number_of_lines = 0; - - - lines_to_draw_temp = draw_circle_with_highest_priority(center,direction1,radius,index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - - lines_to_draw_temp = draw_circle_with_highest_priority(center,direction2,radius,index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - - lines_to_draw_temp = draw_circle_with_highest_priority(center,direction3,radius,index,Geometries,number_of_volumes,2); - merge_lines_to_draw(lines_to_draw_output,&lines_to_draw_temp); - -}; - -void initialize_sphere_geometry_from_main_component(struct geometry_struct *sphere) { + + lines_to_draw_temp = draw_circle_with_highest_priority (center, direction1, radius, index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); + + lines_to_draw_temp = draw_circle_with_highest_priority (center, direction2, radius, index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); + + lines_to_draw_temp = draw_circle_with_highest_priority (center, direction3, radius, index, Geometries, number_of_volumes, 2); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); + }; + + void + initialize_sphere_geometry_from_main_component (struct geometry_struct* sphere) { // Function to be called in initialize of the main component // This is done as the rotation matrix needs to be relative to the main component instead of global // Everything done in initialize in this component file has the rotation matrix relative to global - + // Nothing needs to be done for the sphere // If an empty function provides difficulties for some compilers, a dummy operation can be added int dummy; - -}; - -struct pointer_to_1d_coords_list sphere_shell_points(struct geometry_struct *geometry,int max_number_of_points) { - // Function that returns a number (less than max) of points on the geometry surface - // If used, remember to free the space allocated. - - int points_per_circle = floor(sqrt(max_number_of_points)); - int number_of_circles = points_per_circle; - - struct pointer_to_1d_coords_list sphere_shell_array; - sphere_shell_array.elements = malloc(points_per_circle*number_of_circles*sizeof(Coords)); - sphere_shell_array.num_elements = points_per_circle*number_of_circles; - - Coords center = geometry->center; - double radius = geometry->geometry_parameters.p_sphere_storage->sph_radius; - - Coords direction = coords_set(0,0,1.0); - - Rotation rot_matrix; - rot_set_rotation(rot_matrix,(double) PI/number_of_circles,0,0); - - //print_rotation(rot_matrix,"rot matrix"); - - // Do the first iteration before the loop to avoid one unecessary matrix operation - points_on_circle(sphere_shell_array.elements,center,direction,radius,points_per_circle); - - int iterate; - for (iterate=1;iteratecenter; + double radius = geometry->geometry_parameters.p_sphere_storage->sph_radius; + + Coords direction = coords_set (0, 0, 1.0); + + Rotation rot_matrix; + rot_set_rotation (rot_matrix, (double)PI / number_of_circles, 0, 0); + + // print_rotation(rot_matrix,"rot matrix"); + + // Do the first iteration before the loop to avoid one unecessary matrix operation + points_on_circle (sphere_shell_array.elements, center, direction, radius, points_per_circle); + + int iterate; + for (iterate = 1; iterate < number_of_circles; iterate++) { + direction = rot_apply (rot_matrix, direction); + points_on_circle (sphere_shell_array.elements + points_per_circle * iterate, center, direction, radius, points_per_circle); + } + // Other parts of the program change behavior when I use the above code, may be writing to unwanted parts of memory! + + /* + // Debug + for (iterate=0;iteratenum_elements == 0) { - // Here if the user have defined a material, but only after this material - printf("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); - printf(" %s was defined before first use of Union_make_material.\n",NAME_CURRENT_COMP); - exit(1); -} -#endif -#ifndef MATERIAL_DETECTOR - printf("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); - exit(1); -#endif - - -this_sphere_volume.geometry.is_masked_volume = 0; -this_sphere_volume.geometry.is_exit_volume = 0; -this_sphere_volume.geometry.is_mask_volume = 0; - -struct pointer_to_global_geometry_list *global_geometry_list = COMP_GETPAR3(Union_init, init, global_geometry_list); -// Read the material input, or if it lacks, use automatic linking. -if (mask_string && strlen(mask_string) && strcmp(mask_string, "NULL") && strcmp(mask_string, "0")) { + geometry_struct_init (&(this_sphere_volume.geometry)); + // Initializes the focusing system for this volume including input sanitation. + focus_initialize (&this_sphere_volume.geometry, POS_A_COMP_INDEX (INDEX_CURRENT_COMP + target_index), POS_A_CURRENT_COMP, ROT_A_CURRENT_COMP, target_index, + target_x, target_y, target_z, focus_aw, focus_ah, focus_xw, focus_xh, focus_r, NAME_CURRENT_COMP); + + // Input sanitation for this geometry + if (radius <= 0) { + printf ("\nERROR in Union_sphere named %s, the radius is <= 0. \n", NAME_CURRENT_COMP); + exit (1); + } + + if (_getcomp_index (init) < 0) { + fprintf (stderr, "Union_sphere:%s: Error identifying Union_init component, %s is not a known component name.\n", NAME_CURRENT_COMP, init); + exit (-1); + } + // Get global variable from init component + struct pointer_to_global_material_list* global_material_list = COMP_GETPAR3 (Union_init, init, global_material_list); + // Use sanitation + #ifdef MATERIAL_DETECTOR + if (global_material_list->num_elements == 0) { + // Here if the user have defined a material, but only after this material + printf ("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); + printf (" %s was defined before first use of Union_make_material.\n", NAME_CURRENT_COMP); + exit (1); + } + #endif + #ifndef MATERIAL_DETECTOR + printf ("\nERROR: Need to define a material using Union_make_material before using a Union geometry component. \n"); + exit (1); + #endif + + this_sphere_volume.geometry.is_masked_volume = 0; + this_sphere_volume.geometry.is_exit_volume = 0; + this_sphere_volume.geometry.is_mask_volume = 0; + + struct pointer_to_global_geometry_list* global_geometry_list = COMP_GETPAR3 (Union_init, init, global_geometry_list); + // Read the material input, or if it lacks, use automatic linking. + if (mask_string && strlen (mask_string) && strcmp (mask_string, "NULL") && strcmp (mask_string, "0")) { // A mask volume is used to limit the extend of other volumes, called the masked volumes. These are specified in the mask_string. // In order for a ray to enter a masked volume, it needs to be both in the region covered by that volume AND the mask volume. // When more than this_sphere_volume.geometry.mask_mode = 1; // Default is mask mode is ALL - if (mask_setting && strlen(mask_setting) && strcmp(mask_setting, "NULL") && strcmp(mask_setting, "0")) { - if (strcmp(mask_setting,"ALL") == 0 || strcmp(mask_setting,"All") == 0) this_sphere_volume.geometry.mask_mode = 1; - else if (strcmp(mask_setting,"ANY") == 0 || strcmp(mask_setting,"Any") == 0) this_sphere_volume.geometry.mask_mode = 2; - else { - printf("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n",NAME_CURRENT_COMP,mask_setting); - exit(1); - } + if (mask_setting && strlen (mask_setting) && strcmp (mask_setting, "NULL") && strcmp (mask_setting, "0")) { + if (strcmp (mask_setting, "ALL") == 0 || strcmp (mask_setting, "All") == 0) + this_sphere_volume.geometry.mask_mode = 1; + else if (strcmp (mask_setting, "ANY") == 0 || strcmp (mask_setting, "Any") == 0) + this_sphere_volume.geometry.mask_mode = 2; + else { + printf ("The mask_mode of component %s is set to %s, but must be either ALL or ANY.\n", NAME_CURRENT_COMP, mask_setting); + exit (1); + } } - + int found_geometries = 0; - for (loop_index=0;loop_indexnum_elements;loop_index++) { - // Add mask list - if (1 == manual_linking_function(global_geometry_list->elements[loop_index].name,mask_string)) { - add_element_to_int_list(&this_sphere_volume.geometry.mask_list,global_geometry_list->elements[loop_index].component_index); - add_element_to_int_list(&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list,INDEX_CURRENT_COMP); - global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; - if (this_sphere_volume.geometry.mask_mode == 2) - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; - if (this_sphere_volume.geometry.mask_mode == 1) { - if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) - // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. - global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; - } - - found_geometries = 1; + for (loop_index = 0; loop_index < global_geometry_list->num_elements; loop_index++) { + // Add mask list + if (1 == manual_linking_function (global_geometry_list->elements[loop_index].name, mask_string)) { + add_element_to_int_list (&this_sphere_volume.geometry.mask_list, global_geometry_list->elements[loop_index].component_index); + add_element_to_int_list (&global_geometry_list->elements[loop_index].Volume->geometry.masked_by_list, INDEX_CURRENT_COMP); + global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume = 1; + if (this_sphere_volume.geometry.mask_mode == 2) + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 2; + if (this_sphere_volume.geometry.mask_mode == 1) { + if (global_geometry_list->elements[loop_index].Volume->geometry.is_masked_volume == 1 + && global_geometry_list->elements[loop_index].Volume->geometry.mask_mode != 2) + // If more than one mask is added to one volume, the ANY mode overwrites the (default) ALL mode. + global_geometry_list->elements[loop_index].Volume->geometry.mask_mode = 1; } + + found_geometries = 1; + } } if (found_geometries == 0) { - printf("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n",NAME_CURRENT_COMP,mask_string); - exit(1); + printf ("The mask_string in geometry: %s did not find any of the specified volumes in the mask_string %s \n", NAME_CURRENT_COMP, mask_string); + exit (1); } - this_sphere_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_sphere_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum - this_sphere_volume.p_physics->number_of_processes = (int) 0; // Should not be used. - this_sphere_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_sphere_volume.p_physics->name,"Mask"); + this_sphere_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_sphere_volume.p_physics->is_vacuum = 0; // Makes this volume a vacuum + this_sphere_volume.p_physics->number_of_processes = (int)0; // Should not be used. + this_sphere_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_sphere_volume.p_physics->name, "Mask"); this_sphere_volume.geometry.is_mask_volume = 1; - - -// Read the material input, or if it lacks, use automatic linking. -} else if (material_string && strlen(material_string) && strcmp(material_string, "NULL") && strcmp(material_string, "0")) { + + // Read the material input, or if it lacks, use automatic linking. + } else if (material_string && strlen (material_string) && strcmp (material_string, "NULL") && strcmp (material_string, "0")) { // A geometry string was given, use it to determine which material - if (0 == strcmp(material_string,"vacuum") || 0 == strcmp(material_string,"Vacuum")) { - // One could have a global physics struct for vacuum instead of creating one for each - this_sphere_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_sphere_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_sphere_volume.p_physics->number_of_processes = (int) 0; - this_sphere_volume.p_physics->my_a = 0; // Should not be used. - sprintf(this_sphere_volume.p_physics->name,"Vacuum"); - } else if (0 == strcmp(material_string,"exit") || 0 == strcmp(material_string,"Exit")) { - // One could have a global physics struct for exit instead of creating one for each - this_sphere_volume.p_physics = malloc(sizeof(struct physics_struct)); - this_sphere_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum - this_sphere_volume.p_physics->number_of_processes = (int) 0; - this_sphere_volume.p_physics->my_a = 0; // Should not be used. - this_sphere_volume.geometry.is_exit_volume = 1; - sprintf(this_sphere_volume.p_physics->name,"Exit"); + if (0 == strcmp (material_string, "vacuum") || 0 == strcmp (material_string, "Vacuum")) { + // One could have a global physics struct for vacuum instead of creating one for each + this_sphere_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_sphere_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_sphere_volume.p_physics->number_of_processes = (int)0; + this_sphere_volume.p_physics->my_a = 0; // Should not be used. + sprintf (this_sphere_volume.p_physics->name, "Vacuum"); + } else if (0 == strcmp (material_string, "exit") || 0 == strcmp (material_string, "Exit")) { + // One could have a global physics struct for exit instead of creating one for each + this_sphere_volume.p_physics = malloc (sizeof (struct physics_struct)); + this_sphere_volume.p_physics->is_vacuum = 1; // Makes this volume a vacuum + this_sphere_volume.p_physics->number_of_processes = (int)0; + this_sphere_volume.p_physics->my_a = 0; // Should not be used. + this_sphere_volume.geometry.is_exit_volume = 1; + sprintf (this_sphere_volume.p_physics->name, "Exit"); } else { - for (loop_index=0;loop_indexnum_elements;loop_index++) { - if (0 == strcmp(material_string,global_material_list->elements[loop_index].name)) { - this_sphere_volume.p_physics = global_material_list->elements[loop_index].physics; - break; - } - if (loop_index == global_material_list->num_elements-1) { - printf("\n"); - printf("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n",material_string,NAME_CURRENT_COMP); - printf(" The materials available at this point (need to be defined before the geometry): \n"); - for (loop_index=0;loop_indexnum_elements;loop_index++) - printf(" %s\n",global_material_list->elements[loop_index].name); - printf("\n"); - printf(" It is also possible to use one of the defualt materials avaiable: \n"); - printf(" Vacuum (for a Volume without scattering or absorption)\n"); - printf(" Exit (for a Volume where the ray exits the component if it enters)\n"); - printf(" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); - exit(1); - } + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) { + if (0 == strcmp (material_string, global_material_list->elements[loop_index].name)) { + this_sphere_volume.p_physics = global_material_list->elements[loop_index].physics; + break; + } + if (loop_index == global_material_list->num_elements - 1) { + printf ("\n"); + printf ("ERROR: The material string \"%s\" in Union geometry \"%s\" did not match a specified material. \n", material_string, NAME_CURRENT_COMP); + printf (" The materials available at this point (need to be defined before the geometry): \n"); + for (loop_index = 0; loop_index < global_material_list->num_elements; loop_index++) + printf (" %s\n", global_material_list->elements[loop_index].name); + printf ("\n"); + printf (" It is also possible to use one of the defualt materials avaiable: \n"); + printf (" Vacuum (for a Volume without scattering or absorption)\n"); + printf (" Exit (for a Volume where the ray exits the component if it enters)\n"); + printf (" Mask (for a Volume that masks existing volumes specified in the mask_string\n"); + exit (1); } + } } -} else { + } else { // Automatic linking, simply using the last defined material. #ifndef MATERIAL_DETECTOR - printf("Need to define a material before the geometry to use automatic linking %s.\n",NAME_CURRENT_COMP); - exit(1); + printf ("Need to define a material before the geometry to use automatic linking %s.\n", NAME_CURRENT_COMP); + exit (1); #endif - this_sphere_volume.p_physics = global_material_list->elements[global_material_list->num_elements-1].physics; -} - -this_sphere_volume.geometry.number_of_faces = 1; -this_sphere_volume.geometry.surface_stack_for_each_face = malloc(this_sphere_volume.geometry.number_of_faces*sizeof(struct surface_stack_struct*)); - -// This could be inserted into the fill_surface_stack function -this_sphere_volume.geometry.surface_stack_for_each_face[0] = &surface_stack; -this_sphere_volume.geometry.internal_cut_surface_stack = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume - -struct pointer_to_global_surface_list *global_surface_list = COMP_GETPAR3(Union_init, init, global_surface_list); -fill_surface_stack(surface, global_surface_list, NAME_CURRENT_COMP, &surface_stack); -fill_surface_stack(cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); - -sprintf(this_sphere_volume.name,"%s",NAME_CURRENT_COMP); -sprintf(this_sphere_volume.geometry.shape,"sphere"); -this_sphere_volume.geometry.eShape = sphere; -this_sphere_volume.geometry.priority_value = priority; -// Currently the coordinates will be in absolute space. -this_sphere_volume.geometry.center = POS_A_CURRENT_COMP; - -this_sphere_volume.geometry.geometry_p_interact = p_interact; -this_sphere_storage.sph_radius = radius; -this_sphere_volume.geometry.visualization_on = visualize; -this_sphere_volume.geometry.geometry_parameters.p_sphere_storage = &this_sphere_storage; -this_sphere_volume.geometry.within_function = &r_within_sphere; -this_sphere_volume.geometry.intersect_function = &sample_sphere_intersect; -this_sphere_volume.geometry.mcdisplay_function = &mcdisplay_sphere_function; -this_sphere_volume.geometry.initialize_from_main_function = &initialize_sphere_geometry_from_main_component; -this_sphere_volume.geometry.shell_points = &sphere_shell_points; -this_sphere_volume.geometry.process_rot_allocated = 0; -this_sphere_volume.geometry.copy_geometry_parameters = &allocate_sphere_storage_copy; - -rot_copy(this_sphere_volume.geometry.rotation_matrix,ROT_A_CURRENT_COMP); -rot_transpose(ROT_A_CURRENT_COMP,this_sphere_volume.geometry.transpose_rotation_matrix); - -// Initialize loggers -this_sphere_volume.loggers.num_elements = 0; -this_sphere_volume.abs_loggers.num_elements = 0; - -// packing the information into the global_geometry_element, which is then included in the global_geometry_list. -sprintf(global_geometry_element.name,"%s",NAME_CURRENT_COMP); -global_geometry_element.activation_counter = number_of_activations; -global_geometry_element.component_index = INDEX_CURRENT_COMP; -global_geometry_element.Volume = &this_sphere_volume; -add_element_to_geometry_list(global_geometry_list, global_geometry_element); - -// TEST Union sphere has been initialized, test shell point function by writing to file. -/* -struct pointer_to_1d_coords_list shell_points; -shell_points = this_sphere_volume.geometry.shell_points(&this_sphere_volume.geometry,400); // using 500 rings with 500 points + this_sphere_volume.p_physics = global_material_list->elements[global_material_list->num_elements - 1].physics; + } + this_sphere_volume.geometry.number_of_faces = 1; + this_sphere_volume.geometry.surface_stack_for_each_face = malloc (this_sphere_volume.geometry.number_of_faces * sizeof (struct surface_stack_struct*)); + + // This could be inserted into the fill_surface_stack function + this_sphere_volume.geometry.surface_stack_for_each_face[0] = &surface_stack; + this_sphere_volume.geometry.internal_cut_surface_stack + = &cut_surface_stack; // This surface is used if the volume is cut by overlapping of higher priority volume + + struct pointer_to_global_surface_list* global_surface_list = COMP_GETPAR3 (Union_init, init, global_surface_list); + fill_surface_stack (surface, global_surface_list, NAME_CURRENT_COMP, &surface_stack); + fill_surface_stack (cut_surface, global_surface_list, NAME_CURRENT_COMP, &cut_surface_stack); + + sprintf (this_sphere_volume.name, "%s", NAME_CURRENT_COMP); + sprintf (this_sphere_volume.geometry.shape, "sphere"); + this_sphere_volume.geometry.eShape = sphere; + this_sphere_volume.geometry.priority_value = priority; + // Currently the coordinates will be in absolute space. + this_sphere_volume.geometry.center = POS_A_CURRENT_COMP; + + this_sphere_volume.geometry.geometry_p_interact = p_interact; + this_sphere_storage.sph_radius = radius; + this_sphere_volume.geometry.visualization_on = visualize; + this_sphere_volume.geometry.geometry_parameters.p_sphere_storage = &this_sphere_storage; + this_sphere_volume.geometry.within_function = &r_within_sphere; + this_sphere_volume.geometry.intersect_function = &sample_sphere_intersect; + this_sphere_volume.geometry.mcdisplay_function = &mcdisplay_sphere_function; + this_sphere_volume.geometry.initialize_from_main_function = &initialize_sphere_geometry_from_main_component; + this_sphere_volume.geometry.shell_points = &sphere_shell_points; + this_sphere_volume.geometry.process_rot_allocated = 0; + this_sphere_volume.geometry.copy_geometry_parameters = &allocate_sphere_storage_copy; + + rot_copy (this_sphere_volume.geometry.rotation_matrix, ROT_A_CURRENT_COMP); + rot_transpose (ROT_A_CURRENT_COMP, this_sphere_volume.geometry.transpose_rotation_matrix); + + // Initialize loggers + this_sphere_volume.loggers.num_elements = 0; + this_sphere_volume.abs_loggers.num_elements = 0; + + // packing the information into the global_geometry_element, which is then included in the global_geometry_list. + sprintf (global_geometry_element.name, "%s", NAME_CURRENT_COMP); + global_geometry_element.activation_counter = number_of_activations; + global_geometry_element.component_index = INDEX_CURRENT_COMP; + global_geometry_element.Volume = &this_sphere_volume; + add_element_to_geometry_list (global_geometry_list, global_geometry_element); + + // TEST Union sphere has been initialized, test shell point function by writing to file. + /* + struct pointer_to_1d_coords_list shell_points; + shell_points = this_sphere_volume.geometry.shell_points(&this_sphere_volume.geometry,400); // using 500 rings with 500 points -FILE *fp; -char filename[124] = ""; + FILE *fp; -strcat(filename,NAME_CURRENT_COMP); -strcat(filename,"_debug.dat"); + char filename[124] = ""; -fp = fopen(filename,"w"); + strcat(filename,NAME_CURRENT_COMP); + strcat(filename,"_debug.dat"); -for (loop_index=0;loop_index