#include #include #include #include #include #include #include #define numLayers 2 #define maxRings 76 /* maxRings is defined by the lens and crystal sizes. maxRing >= lensDiam / (crystalDiam * tan(30)) */ #define N_CryPos 17557 /*((1+maxRings)*maxRings*3+1) number of facet positions in hexagnal field surrounding the lens circle */ #define numFACETS 35114 /* (numLayers*N_CryPos) */ double PI; double TWOPI; double GTORAD; double MTORAD; /* structure characterizing a zone with particular reflections types */ typedef struct { float fR_outer; /* Inner radius of zone (as fraction of the lens width) */ float fR_inner; /* Outer radius of zone (as fraction of the lens width) */ float R_outer; /* Inner radius of zone */ /* DERIVED value */ float R_inner; /* Outer radius of zone */ /* DERIVED value */ int Z_lay[2][3]; int Millay[2][3]; float ftlay[2][3]; /* Thickness factor relative to 'optimal' thickness */ float fracA[2][3]; /* start fraction of potential redefined facets */ float fracB[2][3]; /* end fraction of potential redefined facets */ int Opt_lay[2][3]; /* Option value corresponding to Z and Miller-index */ /* DERIVED value */ int secZ_lay[2][3]; int secMillay[2][3]; float secftlay[2][3]; /* Thickness factor relative to 'optimal' thickness */ float secfracA[2][3]; /* start fraction of potential redefined facets */ float secfracB[2][3]; /* end fraction of potential redefined facets */ int secOpt_lay[2][3]; /* Option value corresponding to Z and Miller-index */ /* DERIVED value */ } zones; /* structure characterizing a reflection */ typedef struct { int Z; /* atomic number */ int CM; /* Miller index indicator */ char Miller_txt[4]; /* Miller index text */ float dist_geo; /* plane separation for this specific reflection (AA) */ float fwhmt; /* mosaic spread (arcmin) */ float minthick; /* minimum thickness acceptable to use (0.1) */ float atoms_eff; /* effective atoms factor */ } reflect; /* structure characterizing a chemical element */ typedef struct { int Z; /* atomic number */ char ELEM_name[10]; /* Element name */ char ELEM_symb[3]; /* Element symbol */ char Struc_txt[4]; /* Crystal structure text */ int Cstruc; /* Crystal structure indicator (0-4) */ /* 0: "fcc", 1: "bcc", 2: "dia", 3: "cph", 4: "cub" */ float A; /* mean atomic mass */ float DebyeT; /* Debye temperature (K) */ float atom_dens; /* atomic density (1/cm3) */ float dens; /* density (g/cm3) */ float dist; /* unit cell atomic distance (cm) */ float melt; /* melting point */ float ThermalFact; /* thermal factor */ float formfact_atom[4]; /* atomic form factor (n_order [1-3])*/ float FormFact[5][4]; /* Unit cell form factor for reflection type [0-4] and n_order [1-3] */ float atoms_eff[5][5]; float mass; } material; typedef struct { /* structure facet */ int ring_num; /* ring number (0 to 53 for 4 cm facets in 360 cm lens) */ int u; /* u coordinate (parallel to x) */ int v; /* v coordinate (60 deg axis) */ float x; /* x coordinate (cm) */ float y; /* y coordinate (cm) */ float r; /* r coordinate (cm) */ int nabo[2][3]; /* facet neigbors in the two neighbor crystal layers */ float thetaB; /* Bragg angle (= r/Focal length) (radians) */ float tilt; /* alignment mirror tilt up angle relative to lens plane (radians) */ float yaw; /* alignment mirror yaw angle relative to radius vector (radians) */ float displacement; /* alignment mirror tangential displacement (mm) (signed) */ int nOption; /* Reflection type index. Used as pointer to Z and Miller index values */ /* (set to -1 if facet is outside useable lens area) */ int Z; /* Used together with nOption, to indicate facet occupation */ /* (set to 0 if facet is not occupied */ float mosaic[20]; /* Mosaic width (arcmin) (May be defined as dependent on facet) */ float E[20]; /* Energy (keV) calculated for up to 20 different reflections (nOption values */ float dE[20]; /* FWHM_E (keV) calculated for up to 20 different reflections (nOption values */ float thick; /* chosen crystal thickness for selected option (cm) */ int zone; /* zone value */ float fzone; /* zone relative position, varies from 0.0 at outer radius to 1.0 at inner radius */ float azim; /* facet azimuth angle (0.0 to 360.0 degrees) */ int azimIndex; /* azimuth index. Three possible values0-2 */ float fring; /* ring relative position, varies from 0.0 at inner edge to 1.0 at outer edge */ float PEAKrefl; float PEAK_E; float FTlay; } facet; /* *******************************************************************************************' */ int reflect0(reflect* REFL, double E, int n_order, material* MATER, float Cgeo[5][5], double mufactor, double t_factor, double minthick, FILE *out); int DoubleLayer(reflect* REFL1, reflect* REFL2, double E, material* MATER, material* MATER2, float Cgeo[5][5], double mufactor, double t_factor, double minthick, FILE *out); float CromerWaber(int ZZ, float SL); int hexring( int ring_no, int layer_no, int facet_no, float panel_new[], /* structure specifying the lens and facet geometry */ facet FACET[]); int facet_geo(facet FACET[], float panel_new[], int layer_no, int facet_no); int mirror_interference (facet FACET[], float panel_new[], int side_UD); int facet_order (facet FACET[], int L_order[], int distrib[], int LEN, float ring_width, int side_UD); int detector_ovlap(float dis, float Rdet, float Rfac, float *overlap_frac); float NormalDistr(float disrad); int facet_connect3(facet FACET[], int LEN[], int Order[numLayers][N_CryPos], float facetR, int Lens_layers); int init_facet_REFL(reflect REFL[], material MATER[], facet FACET[], int LEN[], int Order[numLayers][N_CryPos], int numOptions); int reflect2(reflect *REFL, facet *FACET, int nOption); int initREFL(int ZZ, material *MATER, float Cgeo[5][5], float atoms_eff[5][5], int atoms_cell[], reflect REFL[], zones ZONES[], int n_zones, int nOptions, float fwhmt, float minthick, int OptZ[]); int OverlapFract(); int detector_ovlap(float dis, float Rdet, float Rfac, float *overlap_frac); float NormalDistr(float dis); float facet_Acontrib(float E, int iOpt, int iOrder, float panel_new[], facet *FACET, material *MATER, reflect *REFL, float *refl_E, int F_index); float facet_Bcontrib( float E, int iOpt, int iOrder, float panel_new[], facet FACET[], material *MATER, reflect *REFL, int LEN[], int L_order[numLayers][N_CryPos], float *refl_E, int index, float NABSTAT[3][30], FILE* gnufil, int Lens_layers); int reflect3A(float E, reflect REFL[], facet FACET[], material MATER[], int iOrder, float *ref_E); int reflect3B(float E, reflect REFL[], facet FACET[], material MATER[], int iOrder, float refl_E3[]); int reflectT2(reflect *REFL, material *MATER, facet *FACET, float t_factor); int came_here(int i); float get_thick(int N_z, int side_UD, float r, float E, zones ZONES[], facet FACET[], int LEN, int L_order[]); int randselect(float r, float rout, float rin, float fout, float fin); int randsel2(float val); int get_ZONES4(zones ZONES[], FILE* zone_file); int split6(int option2_num, int Xrest[]); /* The first part of the program defines a list of crystal positions on the mirror panel, 'LIST'. LIST is a structure, and initially only the members 'x', 'y' and 'area' need to be filled. When the coordinates of the lens axis, 'x_focus', 'y_focus', are given the radial distance between each crystal facet from the axis can be calculated and stored in 'LIST.dist'. LIST is now sorted according to 'dist', LIST members are not physically moved around, but an array, 'L_order' is defined holding the desired sequence order of the LIST elements, with the largest dist-values coming first. (We want to fill the outer lens positions (low energies first) because then the higher order diffraction contributions can be known when we fill the inner positions (higher energes)). The sorting process takes several minutes to complete, therefore the L_order-array is written to a file. If the program is used several times with the same panel geometry, the L_order file is read from disk rather than recalculated every time. A second step is to calculate the diffraction efficiencies for the potential crystal candidates and Miller indices: Cu(111), Cu(200), Ag(111), Ag(200), Au(111) and Au(200). The efficiencies for all reflection types are calculated for a particular set of energies, corresponding to steps of 15 arcseconds in the Bragg angles for Ag(200), starting at 200 keV and going down in Bragg angle until a Bragg angle of one arcminute - this Bragg angle corresponds to about 8700 keV for Ag(200). The use of a fixed and pre-defined energy scale for all possible element and Miller index choices is very practical in the later calculations. All the diffraction data are kept in a structure 'DIFR'. The diffraction data must include the constraints we want to impose on the quality of the crystals (mosaic spread) and, very importantly, also the minimum thickness of the crystals we believe we can manufacture. For the low energies this minimum thickness will make the use of copper prefereble to silver or gold. The third step is to specify a desired response for the Laue lens, achieving a certain number of cm2 collection area as function of energy. Now we are ready to start filling the lens with crystals. The program is not fully automatic, because it does not have the foresight to recognize the difficulties it is going to meet at higher energies when it fills the positions at large radii, corresponding to low energies. Therefore some manual guidance on which reflection types to prefer within a given energy range may be given. ********************************************************************** * 'LIST' structure characterizing one crystal facet on the lens panel * struct cryst { float x; * X coordinate on lens * float y; * Y coordinate on lens * float thick; * thickness (cm) * float area; * cross sectional area (cm2) * float dist; * crystal distance to axis * float dfi; * dfi associated with this crystal * float sort; * sorting parameter * int used; int elem; * reflection indicator * float Eval; * energy corresp. to selected element at this position * }; * 'DIFR' structure characterizing a reflection * * structure characterizing diffraction for Cu, Ag and Au at a specific energy * * for each energy the diffraction data are given for 9 crystal-MillerIndex pairs: 0: Cu(111), 1: Cu(200), 2: Cu(220), 3: Ag(111), 4: Ag(200), 5: Ag(220), 4: Au(111), 7: Au(200), 8: Au(220) struct diffrac { float Eval; * Energy * float focal_length; * telescope focal length * float thetaB1[9]; * 1st order Bragg angle (radians) * float radius1[9]; * 1st order radius corresponding to focal length and Bragg angle * float useref1[9]; * 1st order peak reflectivity corresponding to used thickness (=t_factor*maxthick) * float thetaB2[9]; * 2nd order Bragg angle (radians) * float radius2[9]; * 2nd order radius corresponding to focal length and Bragg angle * float useref2[9]; * 2nd order peak reflectivity corresponding to used thickness (=t_factor*maxthick) * float thetaB3[9]; * 3rd order Bragg angle (radians) * float radius3[9]; * 3rd order radius corresponding to focal length and Bragg angle * float useref3[9]; * 3rd order peak reflectivity corresponding to used thickness (=t_factor*maxthick) * float maxref[9]; * peak reflectivity corresponding to max_reflectivity_thickness (1st order) * float maxthick[9]; * max_reflectivity_thickness (cm) * float sigmaE[9]; * standard deviation (in energy) of reflectivity peak (keV) * float fwhmt[9]; * mosaic spread (arcmin) * float mufactor[9]; * reflectivity factor (for stacked crystals) * float t_factor[9]; * thickness factor - relative to max reflectivity * float thick[9]; * minimum acceptable thickness (cm) * float R[9]; * specific reflectivity (1/cm) * float mu[9]; * specific absorbtion (1/cm) * }; */