#include #include #include #include #include #include #include "simcrys.h" //crystal routine of the proton beam #include "crystalproton.h" #include "crystalprotonfuns.h" extern "C" { struct { double Cry_length, Rcurv, C_xmax, C_ymax, Alayer, C_orient; }Par_Cry1_; }; using namespace std; //Fortran crystal routine for the proton beam // By Jianfeng Zhang @ LAL, 05/2014 // extern "C" { // // void cryst_(int,double,double,double,double,double,double); // void cryst_(int IS, double x, double xp, double y,double yp,double PC,double Length); // } SimCrys::SimCrys(Crystal crys, Partcrys part) : crys(crys), part(part) //,moy(moy) //POUR faire varier la moyenne de la gaussienne aussi !!!!! { } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////// FUNCTION BASES THAT MAKE SOME BASIC CALCULATION //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SimCrys::bases(SimCrys& sim) { if ( (crys.miscut < 0 ) && ( part.x > 0) && (part.x < -crys.Cry_length * tan(crys.miscut))) { crys.L_chan = -part.x * tan(crys.miscut); } crys.tchan = crys.L_chan / crys.Rcurv; part.xp_rel = part.xp - crys.miscut; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////FUNCTIN CROSS TO KNOW IF THE PARTICULE CROSS THE CRYSTAL //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool SimCrys::cross(SimCrys& sim) { bool crossing(true); if ((part.y < crys.ymin) || (part.y > crys.ymax) || (part.x > crys.xmax)) { //cout << "OUT of the Crystal !!" << part.x << " , "<>>>>>>>>>>>>>"<= crys.s_length) { part.s = crys.s_length; } //cout<<"s : " << part.s <= 0) && ((part.y + part.yp * part.s) <= crys.ymax))) || (((part.yp < 0) && ((part.y + part.yp * part.s) >= crys.ymin)))) { length_ys = part.yp * length_xs; } else { part.s = (crys.ymax - part.y) / part.yp; length_ys = sqrt((crys.ymax - part.y) * (crys.ymax - part.y) + part.s * part.s); part.x = x0 + part.xp * part.s; length_xs = sqrt((part.x - x0) * (part.x - x0) + part.s * part.s); } am_length = sqrt(length_xs * length_xs + length_ys * length_ys); //cout << "AM_Length :" << am_length << endl; // TESTER FONCTION part.s = part.s / 2; part.x = x0 + part.xp * part.s; part.y = y0 + part.yp * part.s; //cout<<" am_length "< (crys.xmax - crys.Alayer)) && (part.x < crys.xmax)) { out = false; move_am(crys.IS, crys.NAM, crys.s_length, crys.DES[crys.IS], crys.DLYI[crys.IS], crys.DLRI[crys.IS], part.xp, part.yp, part.PC); //We call the move_am function part.namor = part.namor + 1; /////////////COUNT///////////// part.effet = 2; //cout<<"Fix HERE"<Rcritical=>no channeling is possible crys.ratio = crys.Rcurv / crys.Rcrit; crys.xpcrit = crys.xpcrit0 * (crys.Rcurv - crys.Rcrit) / crys.Rcurv; c_v1 = 1.7; c_v2 = -1.5; if (crys.ratio <= 1) { part.Ang_rms = c_v1 * 0.42 * crys.xpcrit0 * sin(1.4 * crys.ratio); //rms scattering part.Ang_avr = c_v2 * crys.xpcrit0 * 0.05 * crys.ratio; //average angle reflection part.Vcapt = 0.0; } else if (crys.ratio <= 3) { part.Ang_rms = c_v1 * 0.42 * crys.xpcrit0 * sin(1.571 * 0.3 * crys.ratio + 0.85); //rms scattering part.Ang_avr = c_v2 * crys.xpcrit0 * (0.1972 * crys.ratio - 0.1472); //average angle reflection part.Vcapt = 0.0007 * (crys.ratio - 0.7) / pow(part.PC, 0.2); //K=0.00070 is taken based on simulations using CATCH.f (V.Biryukov) } else { part.Ang_rms = c_v1 * crys.xpcrit0 * (1 / crys.ratio); part.Ang_avr = c_v2 * crys.xpcrit0 * (1 - 1.6667 / crys.ratio); part.Vcapt = 0.0007 * (crys.ratio - 0.7) / pow(part.PC, 0.2); } //cout < 0) && (Lrefl < crys.Cry_length)) { // IE : If the VR point is inside the crystal!!!! //cout<<"VRCapt : "< part.Vcapt) || (crys.ZN == 0)) { //cout<< "Volume Reflexion! "< 0) { move_am(crys.IS, crys.NAM, crys.s_length - Srefl, crys.DES[crys.IS], crys.DLYI[crys.IS], crys.DLRI[crys.IS], part.xp , part.yp, part.PC); //We call the move_am function } part.x = part.x + 0.5 * part.xp * (crys.s_length - Srefl); part.y = part.y + 0.5 * part.yp * (crys.s_length - Srefl); } else { //cout<< "Volume Capture! "; part.nvcapt = part.nvcapt + 1; /////////////COUNT///////////// part.effet = 6; part.x = part.x + part.xp * Srefl; part.y = part.y + part.yp * Srefl; /* TLdech2= 0.00011*pow(part.PC,0.25)*pow((1.-1./crys.ratio),2) //dechanneling length [m] part.Dechan = log(1.-random()) Ldech = -TLdech2*part.Dechan next 2 lines new from sasha - different dechanneling probability */ TLdech2 = 0.01 * part.PC * pow((1. - 1. / crys.ratio), 2); // typical dechanneling length [m] Ldech = 0.005 * TLdech2 * pow((sqrt(0.01 - log(random())) - 0.1), 2); // (dechanneling length) [m] tdech = Ldech / crys.Rcurv; Sdech = Ldech * cos(part.xp + 0.5 * tdech); if (Ldech < (crys.Cry_length - Lrefl)) { // for dechanneling part //cout<< "Dechanneling! "; part.ndechann = part.ndechann + 1; /////////////COUNT///////////// part.effet = 4; Dxp = Ldech / crys.Rcurv; part.x = part.x + Ldech * (sin(0.5 * Dxp + part.xp)); //trajectory at channeling exit part.y = part.y + Sdech * part.yp; part.xp = part.xp + Dxp + (random_gauss() - 0.5) * crys.xpcrit * 0.5; Red_S = crys.s_length - Srefl - Sdech; // move in amorphous substance---------------------------- part.x = part.x + 0.5 * part.xp * Red_S; part.y = part.y + 0.5 * part.yp * Red_S; if (crys.ZN > 0) { //cout<<"Amorphous! "< 0) { move_am(crys.IS, crys.NAM, crys.s_length, crys.DES[crys.IS], crys.DLYI[crys.IS], crys.DLRI[crys.IS], part.xp , part.yp, part.PC); //We call the move_am function } part.x = part.x + 0.5 * crys.s_length * part.xp; part.y = part.y + 0.5 * crys.s_length * part.yp; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //THE FUNCTION THAT DO ALL THE SCHEMA USING THE PREVIOUS FUNCTION !!!!!!!!!!111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //called the FORTRAN cyrstal-particle routine from SixTrack /* void SimCrys::general(SimCrys& sim, const int& pas, char name, double emitx0, double emity0, double enom, string outputpath, double Mirror, double C_rotation, double C_aperture, double C_offset, double C_tilt, double Crystal_tilt) { long int max_npart = 1500000; char name_coll[50] = name; int NP = ; double ENOM = enom*1e-3; // [GeV] double EMITX0 = emitx0; double EMITY0 = emity0; double AX = , AY = , BX = , BY = ; double X_IN[max_npart] ; double XP_IN[max_npart]; double Y_IN[max_npart]; double YP_IN[max_npart]; double P_IN[max_npart]; double S_IN[max_npart] = ; int flagsec[max_npart] = ; bool dowrite_impact = true; int name[max_npart] = ; char C_MATERIAL[6]; double C_LENGTH = crys.s_length; double C_ROTATION = C_rotation; double C_APERTURE = C_aperture; double C_OFFSET = C_offset; double C_TILT[2] = {C_tilt, 0} ; int LHIT[max_npart] = ; //position of the particle been hit int PART_ABS[max_npart] = ; double IMPACT[max_npart] = ; double INDIV[max_npart] = ; double LINT[max_npart] = ; */ /* ----------------- !++ Copy particle data to 1-dim array and go back to meters */ /* for(j = 1, napx) rcx(j) = (xv(1,j)-torbx(ie))/1d3 rcxp(j) = (yv(1,j)-torbxp(ie))/1d3 rcy(j) = (xv(2,j)-torby(ie))/1d3 rcyp(j) = (yv(2,j)-torbyp(ie))/1d3 rcp(j) = ejv(j)/1d3 rcs(j) = 0d0 part_hit_before(j) = part_hit(j) rcx0(j) = rcx(j) rcxp0(j) = rcxp(j) rcy0(j) = rcy(j) rcyp0(j) = rcyp(j) rcp0(j) = rcp(j) ejf0v(j) = ejfv(j) ! !++ For zero length element track back half collimator length ! if (stracki.eq.0.) then rcx(j) = rcx(j) - 0.5d0*c_length*rcxp(j) rcy(j)= rcy(j) - 0.5d0*c_length*rcyp(j) else Write(*,*) & "ERROR: Non-zero length collimator!" STOP endif flukaname(j) = ipart(j)+100*samplenumber ! end do ! !++ Do the collimation tracking ! enom_gev = myenom*1d-3 ! !++ Allow if (crys.IS == 0) { C_MATERIAL = "CRY-Si"; } else if (crys.IS == 1) { C_MATERIAL = "CRY-W"; } else if (crys.IS == 2) { C_MATERIAL = "CRY-C"; } else if (crys.IS == 3) { C_MATERIAL = "CRY-Ge"; }else{ cerr << "Material of the Crystal not fund !!!" << endl; } int count = 0; string rest; ifstream entree; string name2; name2 = outputpath + "/ascii_before.csv"; entree.open(name2.c_str()); if (entree) { while (!entree.eof()) { count = count + 1; getline(entree, rest, ','); X_IN[count] = atof(rest.c_str()); //cout<<" X " << part.x< 0 ) { p0 = part.PC; c_tilt0[0] = c_tilt[0]; c_tilt0[1] = c_tilt[1]; tiltangle = c_tilt0[0]; } //new.......................... // call scatin(p0) ?????????????? // scatin_(p0); /* EVENT LOOP, initial distribution is here a flat distribution with * xmin=x-, xmax=x+, etc. from the input file */ //initialize particle variables part.n_part = 0; part.nabsorbed = 0; part.namor = 0; part.nchann = 0; part.ndechann = 0; part.nout =0; part.nvcapt = 0; part.nvrefl = 0; part.nhit = 0; nhit = 0; double fracab = 0; // int n_chan = 0; // valentina :initialize to zero the counters for crystal effects // int n_VR = 0; // int n_amorphous = 0; double impact = 0; double indiv = 0; double lint = 0; // c- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //c WRITE(*,*) ITURN,ICOLL /* do j = 1, nev //c impact(j) = -1.0; lint(j) = -1.0; indiv(j) = -1.0; idx_proc = name(j)-100*samplenumber; if (ITURN == 1){ // !daniele bool_proc_old(idx_proc)=-1;} // !daniele // elseif (bool_proc(idx_proc) != -1){ else{ bool_proc_old(idx_proc)=bool_proc(idx_proc); // !daniele } // !daniele PROC= "out"; // !the default process is 'out' !daniele bool_proc(idx_proc)=-1; // !daniele */ int nabs = 0; //ofstream sortie("results.csv"); //sortie << "xp1" <<","<< "xp0"<<","<< "x"<<","<< "y"<>><<"< 0) { ////////////////////////// IF NUMERO 2////////////////// xp = xp - tiltangle; } //////////////////////////FIN IF NUMERO 2////////////////// else if (tiltangle < 0) { ////////////////////////// IF NUMERO 3////////////////// x = x + sin(tiltangle) * c_length; xp = xp - tiltangle; } //////////////////////////FIN IF NUMERO 3////////////////// if (Cry_tilt < 0) { ////////////////////////// IF NUMERO 4////////////////// s_shift = s; shift = crys.Rcurv * (1 - cos(Cry_tilt)); if (Cry_tilt < (-crys.cry_bend) ) { ////////////////////////// IF NUMERO 5////////////////// shift = ( crys.Rcurv * ( cos ( - Cry_tilt) - cos( crys.cry_bend - Cry_tilt) ) ); } //////////////////////////FIN IF NUMERO 5////////////////// x_shift = x - shift; } //////////////////////////fin IF NUMERO 4////////////////// else { //////////////////////////IF NUMERO 6////////////////// //cout<< "CRY-TILT POSSITIVE ++ or nul"<= 0) { ////////////////////////// IF NUMERO 7////////////////// s_impact = s_in0; //!(for the first impact) if(0){ cout<<"hit the cry entrance face"<= xp_tangent) { ////////////////////////// IF NUMERO 13////////////////// //if it hits the crystal, calculate in which point and apply the //transformation and drift to that point a_eq = (1 + xp * xp); b_eq = 2 * xp * (x - crys.Rcurv); c_eq = -2 * x * crys.Rcurv + x * x; Delta = b_eq * b_eq - 4 * (a_eq * c_eq); s_int = (-b_eq - sqrt(Delta)) / (2 * a_eq); //cout<< " s int "<= xp_tangent) }////////////////////// 12 // Finish particle not hit the crystal else (x < 0) //************************************************************************************************************************** //trasform back from the crystal to the collimator reference system // 1st: un-rotate the coordinates x_rot = x; s_rot = s; xp_rot = xp; //cout<< "debug - S Cry RF 2" , s_rot < 0) { x = x + tiltangle * c_length; xp = xp + tiltangle; } else if (tiltangle < 0) { x = x + tiltangle * c_length; xp = xp + tiltangle; x = x - sin(tiltangle) * c_length; } // Transform back to particle coordinates with opening and offset z00 = z; x00 = x + mirror * c_offset; x = x + c_aperture / 2 + mirror * c_offset; //+ Now mirror at the horizontal axis for negative X offset x = mirror * x; xp = mirror * xp; // Last do rotation into collimator frame part.x = x * cos((-1) * c_rotation) + z * sin((-1) * c_rotation); part.y = z * cos((-1) * c_rotation) - x * sin((-1) * c_rotation); part.xp = xp * cos((-1) * c_rotation) + zp * sin((-1) * c_rotation); part.yp = zp * cos((-1) * c_rotation) - xp * sin((-1) * c_rotation); //********************************************************************************** //For output.... by Zhang @ CERN, 24/04/2014 //p_in = (1 + dpop) * p0; //From Dianiele //p_in = p; //s_in = s_in + s; part.PC = p; part.s = part.s + s; if (part.effet == 1) { ////////////////////////// IF NUMERO 21////////////////// part.x = 99.99e-3; part.y = 99.99e-3; cout<< "Mean that the particules is lost"< dE/dx (stoping energy) PC = PC - DEI * DZ; //energy lost beacause of ionization process[GeV] // Coulomb Scattering //DYA ---> rms of coloumb scattering DYA = (14 / PC) * sqrt(DZ / DLR); //rms scattering (mrad) xp = xp + DYA * random_gauss_cut(); yp = yp + DYA * random_gauss_cut(); //Elastic scattering //cout<<"Plusieurs possibilitees : "<= 1); return resu; } double SimCrys::random_gauss_dist() //POUR faire varier la moyenne de la gaussienne il faut mettre en argu la sim& !!!!! { const double PI (4.0 * atan(1.0)); double U(random()); double V(random()); //moy=random(); return 1e-4 * (sqrt(-2 * log(U)) * cos(2 * PI * V)); //+(0.0002*moy); //POUR faire varier la moyenne de la gaussienne aussi !!!!! } /////////////////////////////////*******************************************************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //POUR 409 : double SimCrys::random_gauss_dist_409() //POUR faire varier la moyenne de la gaussienne il faut mettre en argu la sim& !!!!! { const double PI (4.0 * atan(1.0)); double U(random()); double V(random()); //moy=random(); return (8.939203e-06) * (sqrt(-2 * log(U)) * cos(2 * PI * V)) + (-7.183296e-08); //POUR faire varier la moyenne de la gaussienne aussi !!!!! } ///////////////////////////////////************************************************************++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void SimCrys::affiche() { cout << "Crystal Curved Length [m] :" << crys.Cry_length << endl; cout << "Crystal Curvature Radius [m] :" << crys.Rcurv << endl; cout << "Crystal Bending Angle [urad] :" << crys.cry_bend << " , " << crys.Cry_length / crys.Rcurv << endl; cout << "Critical Radius :" << crys.Rcrit << endl; cout << "Ratio :" << crys.ratio << endl; cout << "Critical Angle for straight Crystal :" << crys.xpcrit0 << endl; cout << "Critical Angle for curved Crystal :" << crys.xpcrit << endl; cout << "Angle average reflexion : " << part.Ang_avr << endl; cout << "Full Channeling : " << crys.Cry_length / crys.Rcurv << endl; cout << endl; cout << endl; cout << "N.AMORPH :" << part.namor << endl; cout << "N.DECHANNELING:" << part.ndechann << endl; cout << "N.CHANNELING :" << part.nchann << endl; cout << "N.OUT :" << part.nout << endl; cout << "N.VREFLECTION :" << part.nvrefl << endl; cout << "N.VCAPTURE:" << part.nvcapt << endl; cout << "N.ABSORBED: "<< part.nabsorbed << endl; //cout << "Si la somme ne donne pas le nbre de part., c est normale !! En effet, il est possible que plusieurs evenement se produisent!!!"; } void SimCrys::file_out(const int& pas, string outputpath) { ofstream out; string file; file = outputpath + "/crystal_output.out"; out.open(file.c_str(), ios::out | ios::app); if (out.fail()) { cerr << "Warning: problem writing in the file " << file << "!" << endl; } else { out << endl; out << "Crystal Curved Length [m] :" << crys.Cry_length << endl; out << "Crystal Curvature Radius [m] :" << crys.Rcurv << endl; out << "Crystal Bending Angle [urad] :" << crys.cry_bend << " , " << 1e6*crys.Cry_length / crys.Rcurv << endl; out << "Critical Radius :" << crys.Rcrit << endl; out << "Ratio :" << crys.ratio << endl; out << "Critical Angle for straight Crystal :" << crys.xpcrit0 << endl; out << "Critical Angle for curved Crystal :" << crys.xpcrit << endl; out << "Angle average reflexion : " << part.Ang_avr << endl; out << "Full Channeling : " << crys.Cry_length / crys.Rcurv << endl; out << endl; out << endl; out << "N.AMORPH :" << part.namor << endl; out << "N.DECHANNELING:" << part.ndechann << endl; out << "N.CHANNELING :" << part.nchann << endl; out << "N.OUT :" << part.nout << endl; out << "N.VREFLECTION :" << part.nvrefl << endl; out << "N.VCAPTURE :" << part.nvcapt << endl ; out << "N.ABSORBED: "<< part.nabsorbed << endl; out << "N. of particles that hit the crystal collimator: " << part.nhit << endl; cout << endl; cout << endl; out.close(); } }