|
| 1 | +/******************************************************************************* |
| 2 | +* |
| 3 | +* McXtrace, x-ray ray-tracing package |
| 4 | +* Copyright(C) 2007 Risoe National Laboratory. |
| 5 | +* |
| 6 | +* %I |
| 7 | +* Written by: Mads Bertelsen and Erik B Knudsen |
| 8 | +* Date: 20.08.15 |
| 9 | +* Version: $Revision: 0.1 $ |
| 10 | +* Origin: ESS DMSC & DTU Physics |
| 11 | +* |
| 12 | +* A sample component to separate geometry and phsysics |
| 13 | +* |
| 14 | +* %D |
| 15 | +* |
| 16 | +* This Union_process is based on the Incoherent.comp component originally written |
| 17 | +* by Kim Lefmann and Kristian Nielsen |
| 18 | +* |
| 19 | +* Part of the Union components, a set of components that work together and thus |
| 20 | +* sperates geometry and physics within McXtrace. |
| 21 | +* The use of this component requires other components to be used. |
| 22 | +* |
| 23 | +* 1) One specifies a number of processes using process components like this one |
| 24 | +* 2) These are gathered into material definitions using Union_make_material |
| 25 | +* 3) Geometries are placed using Union_box / Union_cylinder, assigned a material |
| 26 | +* 4) A Union_master component placed after all of the above |
| 27 | +* |
| 28 | +* Only in step 4 will any simulation happen, and per default all geometries |
| 29 | +* defined before the master, but after the previous will be simulated here. |
| 30 | +* |
| 31 | +* There is a dedicated manual available for the Union_components |
| 32 | +* |
| 33 | +* Algorithm: |
| 34 | +* Described elsewhere |
| 35 | +* |
| 36 | +* %P |
| 37 | +* INPUT PARAMETERS: |
| 38 | +* density: [g/cm^3] Nominal density of material. |
| 39 | +* element: [str] The element (symbol) of the material. Overrides Z. |
| 40 | +* Z: [1] Atomic number. |
| 41 | +* OUTPUT PARAMETERS: |
| 42 | +* |
| 43 | +* %L |
| 44 | +* The test/example instrument <a href="../examples/Test_Phonon.instr">Test_Phonon.instr</a>. |
| 45 | +* |
| 46 | +* %E |
| 47 | +******************************************************************************/ |
| 48 | + |
| 49 | +DEFINE COMPONENT Compton_xrl_process |
| 50 | +DEFINITION PARAMETERS () |
| 51 | +SETTING PARAMETERS (density=0,atomno=14, string element="", string init="init") |
| 52 | +OUTPUT PARAMETERS (This_process,Compton_xrl_storage) |
| 53 | +DEPENDENCY "-lxrl" |
| 54 | +/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ |
| 55 | + |
| 56 | +SHARE |
| 57 | +%{ |
| 58 | +#ifndef Union |
| 59 | +#define Union $Revision: 0.8 $ |
| 60 | + |
| 61 | +%include "Union_functions.c" |
| 62 | +%include "Union_initialization.c" |
| 63 | + |
| 64 | +#endif |
| 65 | + |
| 66 | +/* If on windows this should likely be set like this |
| 67 | + * since xraylib.h is not (as a standard) installed |
| 68 | + * into an xraylib subdir*/ |
| 69 | +#ifdef _WIN32 |
| 70 | +#include <xraylib.h> |
| 71 | +#else |
| 72 | +#include <xraylib/xraylib.h> |
| 73 | +#endif |
| 74 | + |
| 75 | +struct Compton_xrl_physics_storage_struct{ |
| 76 | + char name[13]; |
| 77 | + int Z; |
| 78 | + double rho; |
| 79 | + double sigma; |
| 80 | +}; |
| 81 | + |
| 82 | +int Compton_xrl_physics_my(double *my, double *k_i, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle){ |
| 83 | + /*get the partial cross section using xraylib*/ |
| 84 | + double k_length = sqrt(k_i[0]*k_i[0]+k_i[1]*k_i[1]+k_i[2]*k_i[2]); |
| 85 | + double E=K2E*k_length; |
| 86 | + |
| 87 | + /*how to handle the fact that we may be dealing with polarized radiation - goes in data_transfer union?*/ |
| 88 | + /*we have to somehow transfer input data to this function - is this also in data_transfer union? yes. It contains pointers to all the possible physics_storage structs.*/ |
| 89 | + struct Compton_xrl_physics_storage_struct *p = data_transfer.pointer_to_a_Compton_xrl_physics_storage_struct; |
| 90 | + |
| 91 | + /*call xraylib to get cross_section in cm^2/g - scale by density to get mu in cm^-1 - scale by 10^2 to get mu in m^-1*/ |
| 92 | + p->sigma=CS_Compt(p->Z,E,NULL); |
| 93 | + *my=p->rho*p->sigma*100; |
| 94 | + return 1; |
| 95 | +} |
| 96 | + |
| 97 | +int Compton_xrl_physics_scattering(double *k_f, double *k_i, double *weight, union data_transfer_union data_transfer, struct focus_data_struct *focus_data, _class_particle *_particle) { |
| 98 | + double k_length = sqrt(k_i[0]*k_i[0]+k_i[1]*k_i[1]+k_i[2]*k_i[2]); |
| 99 | + double E=K2E*k_length; |
| 100 | + double E0; |
| 101 | + |
| 102 | + struct Compton_xrl_physics_storage_struct *p = data_transfer.pointer_to_a_Compton_xrl_physics_storage_struct; |
| 103 | + |
| 104 | + /*pick a direction randomly*/ |
| 105 | + Coords k_out; |
| 106 | + // Here is the focusing system in action, get a vector |
| 107 | + double solid_angle; |
| 108 | + focus_data->focusing_function(&k_out,&solid_angle,focus_data); |
| 109 | + NORM(k_out.x,k_out.y,k_out.z); |
| 110 | + *weight *= solid_angle*0.25/PI; |
| 111 | + |
| 112 | + double theta,dsigma; |
| 113 | + theta = acos(scalar_prod(k_out.x,k_out.y, k_out.z,k_i[0], k_i[1],k_i[2])/k_length); |
| 114 | + |
| 115 | + /*make the call to xraylib to get the partial cross section for the particular scattering triangle defined by k_i, k_f. |
| 116 | + We rely on a previous call to CS_Compt by _mu-function*/ |
| 117 | + dsigma = DCS_Compt(p->Z,E,theta,NULL); |
| 118 | + *weight *= dsigma/p->sigma; |
| 119 | + E0=E; |
| 120 | + E=ComptonEnergy(E0,theta,NULL); |
| 121 | + k_length=E*E2K; |
| 122 | + k_f[0]=k_out.x*k_length; |
| 123 | + k_f[1]=k_out.y*k_length; |
| 124 | + k_f[2]=k_out.z*k_length; |
| 125 | + /*get */ |
| 126 | + return 1; |
| 127 | +} |
| 128 | + |
| 129 | +#ifndef PROCESS_DETECTOR |
| 130 | + #define PROCESS_DETECTOR dummy |
| 131 | +#endif |
| 132 | + |
| 133 | +#ifndef PROCESS_COMPTON_XRL_DETECTOR |
| 134 | + #define PROCESS_COMPTON_XRL_DETECTOR dummy |
| 135 | +#endif |
| 136 | +%} |
| 137 | + |
| 138 | +DECLARE |
| 139 | +%{ |
| 140 | +// Needed for transport to the main component |
| 141 | +struct global_process_element_struct global_process_element; |
| 142 | +struct scattering_process_struct This_process; |
| 143 | + |
| 144 | +// Declare for this component, to do calculations on the input / store in the transported data |
| 145 | +struct Compton_xrl_physics_storage_struct Compton_xrl_storage; |
| 146 | + |
| 147 | +%} |
| 148 | + |
| 149 | +INITIALIZE |
| 150 | +%{ |
| 151 | + // Initialize done in the component |
| 152 | + xrl_error *xe; |
| 153 | + if(atomno==0 && strlen(element)!=0){ |
| 154 | + Compton_xrl_storage.Z=SymbolToAtomicNumber(element,&xe); |
| 155 | + snprintf(Compton_xrl_storage.name,3,element); |
| 156 | + } else if (atomno>0 || atomno<116){ |
| 157 | + Compton_xrl_storage.Z=atomno; |
| 158 | + snprintf(Compton_xrl_storage.name,3,AtomicNumberToSymbol(atomno,&xe)); |
| 159 | + }else{ |
| 160 | + fprintf(stderr,"ERROR: (%s): Must set either an element by symbol or by atomic number Got (%s,%d).\n",NAME_CURRENT_COMP,element,atomno); |
| 161 | + exit(-1); |
| 162 | + } |
| 163 | + Compton_xrl_storage.rho=density; |
| 164 | + |
| 165 | + // The type of the process must be saved in the global enum process |
| 166 | + This_process.eProcess = Compton_xrl; |
| 167 | + |
| 168 | + // Need to specify if this process is isotropic |
| 169 | + This_process.non_isotropic_rot_index = -1; // Yes (powder) |
| 170 | + //This_process.non_isotropic_rot_index = 1; // No (single crystal) |
| 171 | + |
| 172 | + // Packing the data into a structure that is transported to the main component |
| 173 | + sprintf(This_process.name,NAME_CURRENT_COMP); |
| 174 | + This_process.process_p_interact = -1; |
| 175 | + This_process.data_transfer.pointer_to_a_Compton_xrl_physics_storage_struct = &Compton_xrl_storage; |
| 176 | + //This_process.data_transfer.pointer_to_a_Incoherent_physics_storage_struct->my_scattering = effective_my_scattering; |
| 177 | + This_process.probability_for_scattering_function = &Compton_xrl_physics_my; |
| 178 | + This_process.scattering_function = &Compton_xrl_physics_scattering; |
| 179 | + |
| 180 | + // This will be the same for all process's, and can thus be moved to an include. |
| 181 | + sprintf(global_process_element.name,NAME_CURRENT_COMP); |
| 182 | + global_process_element.component_index = INDEX_CURRENT_COMP; |
| 183 | + global_process_element.p_scattering_process = &This_process; |
| 184 | + |
| 185 | + if (_getcomp_index(init) < 0) { |
| 186 | + fprintf(stderr,"Compton_xrl_process:%s: Error identifying Union_init component, %s is not a known component name.\n", |
| 187 | + NAME_CURRENT_COMP, init); |
| 188 | + exit(-1); |
| 189 | + } |
| 190 | + |
| 191 | + struct pointer_to_global_process_list *global_process_list = COMP_GETPAR3(Union_init, init, global_process_list); |
| 192 | + add_element_to_process_list(global_process_list, global_process_element); |
| 193 | + %} |
| 194 | + |
| 195 | +TRACE |
| 196 | +%{ |
| 197 | +%} |
| 198 | + |
| 199 | +FINALLY |
| 200 | +%{ |
| 201 | +// Since the process and it's storage is a static allocation, there is nothing to deallocate |
| 202 | + |
| 203 | +%} |
| 204 | + |
| 205 | +END |
0 commit comments