Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AdSCFT.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file AdSCFT.cc
1 /*************************************************************************************
2 * Copyright (c) The JETSCAPE Collaboration, 2018
3 *
4 * Modular, task-based framework for simulating all aspects of heavy-ion collisions
5 *
6 * For the list of contributors see AUTHORS.
7 *
8 * Report issues at https://github.com/JETSCAPE/JETSCAPE/issues
9 *
10 * or via email to bugs.jetscape@gmail.com
11 *
12 * Distributed under the GNU General Public License 3.0 (GPLv3 or later).
13 * See COPYING for details.
14 *
15 *************************************************************************************/
16 
17 #include "AdSCFT.h"
18 #include "JetScapeLogger.h"
19 #include "JetScapeXML.h"
20 #include <string>
21 
22 #include "tinyxml2.h"
23 #include <iostream>
24 #include <fstream>
25 
26 #include "FluidDynamics.h"
27 #include "AdSCFTMutex.h"
28 #define MAGENTA "\033[35m"
29 
30 // Register the module with the base class
32 
34  SetId("AdSCFT");
35  kappa = -99;
36  T0 = -99;
37  Q0 = -99;
38 
39  VERBOSE(8);
40 
41  // create and set Martini Mutex
42  auto adscft_mutex = make_shared<AdSCFTMutex>();
43  SetMutex(adscft_mutex);
44 }
45 
47 
48 void AdSCFT::Init() {
49  JSINFO << "Initialize AdSCFT ...";
50 
51  std::string s = GetXMLElementText({"Eloss", "AdSCFT", "name"});
52  JSDEBUG << s << " to be initialized ...";
53 
54  //Kappa
55  kappa = GetXMLElementDouble({"Eloss", "AdSCFT", "kappa"});
56  JSINFO << "AdSCFT kappa = " << kappa;
57 
58  //T0 [GeV]
59  T0 = GetXMLElementDouble({"Eloss", "AdSCFT", "T0"});
60  JSINFO << "AdSCFT T0 = " << T0;
61 
62  //Q0 [GeV]
63  Q0 = GetXMLElementDouble({"Eloss", "AdSCFT", "Q0"});
64  JSINFO << "AdSCFT Q0 = " << Q0;
65 
66  //Vac or Med
67  in_vac = GetXMLElementDouble({"Eloss", "AdSCFT", "in_vac"});
68  ;
69 }
70 
71 void AdSCFT::WriteTask(weak_ptr<JetScapeWriter> w) {
72  VERBOSE(8);
73  auto f = w.lock();
74  if (!f)
75  return;
76  f->WriteComment("ElossModule Parton List: " + GetId());
77  f->WriteComment("Energy loss to be implemented accordingly ...");
78 }
79 
80 void AdSCFT::DoEnergyLoss(double deltaT, double time, double Q2,
81  vector<Parton> &pIn, vector<Parton> &pOut) {
82 
83  VERBOSESHOWER(8) << MAGENTA << "SentInPartons Signal received : " << deltaT
84  << " " << Q2 << " " << &pIn;
85 
86  for (int i = 0; i < pIn.size(); i++) {
87  //Skip photons
88  if (pIn[i].pid() == photonid) {
89  pOut.push_back(pIn[i]);
90  return;
91  }
92 
93  JSDEBUG << " in AdS/CFT";
94  JSDEBUG << " Parton Q2= " << pIn[i].t();
95  JSDEBUG << " Parton Id= " << pIn[i].pid()
96  << " and mass= " << pIn[i].restmass();
97 
98  //Parton 4-momentum
99  double p[4];
100  p[0] = pIn[i].px();
101  p[1] = pIn[i].py();
102  p[2] = pIn[i].pz();
103  p[3] = pIn[i].e();
104  double pmod = std::sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
105 
106  //Parton velocity
107  vector<double> w;
108  for (unsigned int j = 0; j < 4; j++)
109  w.push_back(p[j] / p[3]);
110  double w2 = std::pow(w[0], 2.) + std::pow(w[1], 2.) + std::pow(w[2], 2.);
111  for (unsigned int j = 0; j < 3; j++)
112  w[j] /= std::sqrt(w2);
113 
114  //Parton 4-position
115  double initR0 = pIn[i].x_in().t(); //Time when the parton was last modified
116  double x[4];
117  //x[0] = pIn[i].x_in().x() + (time - initR0) * w[0] / std::sqrt(w2);
118  //x[1] = pIn[i].x_in().y() + (time - initR0) * w[1] / std::sqrt(w2);
119  //x[2] = pIn[i].x_in().z() + (time - initR0) * w[2] / std::sqrt(w2);
120  x[0] = pIn[i].x_in().x() + (time - initR0) * w[0];
121  x[1] = pIn[i].x_in().y() + (time - initR0) * w[1];
122  x[2] = pIn[i].x_in().z() + (time - initR0) * w[2];
123  x[3] = pIn[i].x_in().t() + (time - initR0) * w[3];
124 
125  //Extract fluid properties
126  std::unique_ptr<FluidCellInfo> check_fluid_info_ptr;
127  double tau = std::sqrt(x[3] * x[3] - x[2] * x[2]);
128  double temp, vx, vy, vz;
129  //Only get a temp!=0 if in_vac=0
130  //if (x[3]>=tStart && !in_vac) //Can use time if there is preequilibrium eloss
131  if (tau >= tStart &&
132  !in_vac) //Should use tau, not t, in absence of preequilibrium eloss
133  {
134  GetHydroCellSignal(x[3], x[0], x[1], x[2], check_fluid_info_ptr);
135  if (!GetJetSignalConnected()) {
136  JSWARN << "Couldn't find a hydro module attached!";
137  throw std::runtime_error(
138  "Please attach a hydro module or set in_vac to 1 in the XML file");
139  }
140 
141  VERBOSE(8) << MAGENTA << "Temperature from Brick (Signal) = "
142  << check_fluid_info_ptr->temperature;
143 
144  temp = check_fluid_info_ptr->temperature;
145  vx = check_fluid_info_ptr->vx;
146  vy = check_fluid_info_ptr->vy;
147  vz = check_fluid_info_ptr->vz;
148  } else
149  temp = 0., vx = 0., vy = 0., vz = 0.;
150  JSDEBUG << " system time= " << time << " parton time= " << x[3]
151  << " tau= " << tau << " temp= " << temp << " vz= " << w[2];
152  JSDEBUG << " energy= " << pIn[i].e();
153 
154  //Do eloss in AdS/CFT if:
155  // *Virtuality below Qcut ( QS[GeV^2] , NOT taken from XML yet )
156  // *Fluid temperature above Tcut ( T0 from XML )
157  // *Parton is not completely quenched ( Ecut = 0.00001 )
158  double QS = Q0 * Q0;
159  if (pIn[i].t() <= QS + rounding_error && temp >= T0 && pmod > 0.00001 &&
160  pIn[i].pstat() >= 0) {
161  //cout << " ADS Q= " << pIn[i].t() << " Q0= " << Q0 << " temp= " << temp << " T0= " << T0 << endl;
162  //cout << " ADS tau= " << tau << " x= " << x[0] << " y= " << x[1] << " z= " << x[2] << " t= " << x[3] << endl;
164  pIn[i]); // Generate error if another module already has responsibility.
165 
166  VERBOSE(8) << " ************ \n \n";
167  VERBOSE(8) << " DOING ADSCFT \n \n";
168  VERBOSE(8) << " ************ \n \n";
169 
170  //Fluid quantities
171  vector<double> v;
172  v.push_back(vx), v.push_back(vy), v.push_back(vz), v.push_back(1.);
173  double v2 = std::pow(v[0], 2.) + std::pow(v[1], 2.) + std::pow(v[2], 2.);
174  double lore = 1. / sqrt(1. - v2); //Gamma Factor
175 
176  //Color Factor (wrt quark)
177  double CF;
178  if (pIn[i].pid() == 21)
179  CF = std::pow(9. / 4., 1. / 3.); //Gluon
180  else
181  CF = 1.; //Quark
182 
183  //Energy (three-momentum) of parton as it entered this module for the first time
184  double ei = pmod;
185  double l_dist = 0., f_dist = 0.;
186  if (pIn[i].has_user_info<AdSCFTUserInfo>()) {
187  ei = pIn[i].user_info<AdSCFTUserInfo>().part_ei();
188  l_dist = pIn[i].user_info<AdSCFTUserInfo>().l_dist();
189  f_dist = pIn[i].user_info<AdSCFTUserInfo>().f_dist();
190  } else {
191  pIn[i].set_user_info(new AdSCFTUserInfo(ei, f_dist, l_dist));
192  }
193 
194  //JSDEBUG << " ei= " << ei;
195  //JSDEBUG << " px= " << p[0] << " py= " << p[1] << " pz= " << p[2] << " en= " << p[3];
196  //JSDEBUG << " x= " << x[0] << " y= " << x[1] << " z= " << x[2] << " t= " << x[3];
197 
198  double restmass = pIn[i].restmass();
199  if (abs(pIn[i].pid()) <= 3)
200  restmass = 0.;
201  double virttwo = p[3] * p[3] - p[0] * p[0] - p[1] * p[1] - p[2] * p[2] -
202  restmass * restmass;
203  double virt = std::sqrt(virttwo);
204  //JSDEBUG << " virt= " << virt;
205 
206  //Needed for boosts (v.w)
207  double vscalw = v[0] * w[0] + v[1] * w[1] + v[2] * w[2];
208 
209  //Distance travelled in LAB frame
210  l_dist += deltaT;
211 
212  //Distance travelled in FRF - accumulating steps from previous, different fluid cells
213  double insqrt = w2 + lore * lore * (v2 - 2. * vscalw + vscalw * vscalw);
214  if (insqrt <= 0.)
215  insqrt = 0.;
216  f_dist += deltaT * std::sqrt(insqrt);
217 
218  //JSDEBUG << " l_dist= " << l_dist << " f_dist= " << f_dist;
219  //Initial energy of the parton in the FRF
220  double Efs = ei * lore * (1. - vscalw);
221 
222  double newEn = pmod;
223  if (temp >= 0.)
224  newEn = pmod - AdSCFT::Drag(f_dist, deltaT, Efs, temp, CF);
225  if (newEn < 0.)
226  newEn = pmod / 10000000.;
227  double lambda = newEn / pmod;
228  //JSDEBUG << " lambda= " << lambda;
229  //JSDEBUG << " Elost= " << pmod-newEn;
230 
231  //Update 4-momentum (don't modify mass)
232  for (unsigned a = 0; a < 3; a++)
233  p[a] *= lambda;
234  virt *= lambda;
235  p[3] = std::sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2] + virt * virt +
236  restmass * restmass);
237  virttwo = p[3] * p[3] - p[0] * p[0] - p[1] * p[1] - p[2] * p[2] -
238  restmass * restmass;
239  virt = std::sqrt(virttwo);
240 
241  //DON'T Update 4-position here, already done at beginning
242  //for (unsigned a=0; a<4; a++) x[a]+=w[a]*deltaT;
243 
244  double fx[4];
245  fx[0] = x[3], fx[1] = x[0], fx[2] = x[1], fx[3] = x[2];
246  //Feed into parton list
247  int pLabel = pIn[i].plabel();
248  int Id = pIn[i].pid();
249  int pStat = pIn[i].pstat();
250  //cout << " pStat= " << pStat << endl;
251  FourVector pVec(p[0], p[1], p[2], p[3]);
252  FourVector xVec;
253  pOut.push_back(Parton(pLabel, Id, pStat, pVec, xVec));
254  pOut[pOut.size() - 1].set_x(fx);
255  pOut.back().set_user_info(new AdSCFTUserInfo(ei, f_dist, l_dist));
256 
257  //Copy variables needed in case parton returns to MATTER in future steps
258  double velocity_jet[4];
259  velocity_jet[0] = 1.0;
260  velocity_jet[1] = pIn[i].jet_v().x();
261  velocity_jet[2] = pIn[i].jet_v().y();
262  velocity_jet[3] = pIn[i].jet_v().z();
263  pOut[pOut.size() - 1].set_jet_v(velocity_jet);
264  pOut[pOut.size() - 1].set_mean_form_time();
265  double ft = pOut[pOut.size() - 1].mean_form_time();
266  pOut[pOut.size() - 1].set_form_time(ft);
267 
268  //Add missing momentum
269  FourVector pVecM(pIn[i].px() - p[0], pIn[i].py() - p[1],
270  pIn[i].pz() - p[2], pIn[i].e() - p[3]);
271  pOut.push_back(Parton(0, 21, -13, pVecM, xVec));
272  pOut[pOut.size() - 1].set_x(fx);
273 
274  } //End if do-eloss
275 
276  } //End pIn loop
277 }
278 
279 double AdSCFT::Drag(double f_dist, double deltaT, double Efs, double temp,
280  double CF) {
281  if (kappa != 0.) {
282  double tstop = 0.2 * std::pow(Efs, 1. / 3.) /
283  (2. * std::pow(temp, 4. / 3.) * kappa) /
284  CF; //Stopping distance in fm
285  double beta =
286  tstop / f_dist; //Ratio of stopping distance to distance travelled
287  if (beta > 1.) //If did not get to stopping distance
288  {
289  double intpiece = Efs * deltaT * 4. / (3.141592) *
290  (1. / (beta * tstop * std::sqrt(beta * beta - 1.)));
291  return intpiece;
292  } else //If reached stopping distance, subtract all energy
293  {
294  return 100000.;
295  }
296  } else
297  return 0.;
298 }
299 
300 void AdSCFT::Clear() {}