source: PSPA/Interface_Web/trunk/pspaWT/sources/controler/src/softwareParmela.cc @ 481

Last change on this file since 481 was 481, checked in by garnier, 10 years ago

Suppression de methodes deprecated et de quelques warning de compilation

File size: 18.1 KB
Line 
1#include "softwareParmela.h"
2#include "abstractElement.h"
3#include "parmelaParticle.h"
4#include "mathematicalConstants.h"
5#include "PhysicalConstants.h"
6#include "dataManager.h"
7#include "mixedTools.h"
8
9softwareParmela::softwareParmela() : abstractSoftware()
10{
11  nameOfSoftware_ = nomDeLogiciel("parmela");
12}
13
14softwareParmela::softwareParmela(string inputFileName,sectionToExecute* sect, dataManager* data) : abstractSoftware(inputFileName, sect, data)
15{
16  nameOfSoftware_ = nomDeLogiciel("parmela");
17  registerElement(nomdElements::RFgun,TBoolOk);
18  registerElement(nomdElements::drift,TBoolOk);
19  registerElement(nomdElements::cell,TBoolOk);
20  registerElement(nomdElements::bend,TBoolOk);
21  registerElement(nomdElements::soleno,TBoolOk);
22  registerElement(nomdElements::fit,TBoolIgnore);
23  registerElement(nomdElements::snapshot,TBoolIgnore);
24}
25
26
27
28bool softwareParmela::createInputFile(particleBeam* beamBefore, string workingDir)
29{
30  unsigned int k;
31
32//  setRelativeParmelaElementIndices();
33  string name = workingDir + inputFileName_;
34  ofstream outfile;
35  outfile.open(name.c_str(), ios::out);
36  if (!outfile) {
37    dataManager_->consoleMessage(" softwareParmela::createInputFile : error opening output stream " );
38    cerr << " softwareParmela::createInputFile : error opening output stream " << name << endl;
39    return false;
40  }
41 
42  abstractElement* elPtr = getSectionToExecute()->getElements().front();
43  double initalKineticEnergy = 0.0;
44  bool there_is_rfgun = (elPtr->getNomdElement().getElementType() == nomdElements::RFgun );
45 
46  if ( !there_is_rfgun ) {
47    string nameOfInput = workingDir + "parin.input0";
48    if ( !beamToParmela(nameOfInput,beamBefore) ) return false;
49    initalKineticEnergy = beamBefore->referenceKineticEnergyMeV();
50    // les elements de parmela sont indexes de 1 à max, s'il n'y a pas de rfgun
51    //    offsetNumElem_ = numeroDeb_ -1;
52  } else {
53    elPtr->setPhaseStep( dataManager_->getGlobalParameters()->getIntegrationStep() );
54    initalKineticEnergy = elPtr->getInitialKineticEnergy();
55    // les elements de parmela sont indexes de 0 à max, s'il y a un rfgun
56  }
57 
58  outfile << "TITLE" << endl;
59  outfile << " titre provisoire " << endl;
60  outfile << "RUN /n0=1 /ip=999 /freq=" << dataManager_->getGlobalParameters()->getFrequency() << "  /z0=0.0 /W0=" << initalKineticEnergy << "  /itype=1" << endl;
61  outfile << "OUTPUT 0" << endl;
62  if ( there_is_rfgun ) {
63    outfile << elementsData(elPtr->parametersToSoftware());
64  } else {
65    outfile << "INPUT 0 /NP=" << beamBefore->getNbParticles() << endl;
66  }
67 
68 // retrouver le sector !!
69  for ( k =1; k < getSectionToExecute()->getElements().size(); k++)
70    {
71      outfile << elementsData(getSectionToExecute()->getElements()[k]->parametersToSoftware());
72    }
73   
74  outfile << "ZOUT" << endl;
75  outfile << "START /wt=0.0 /dwt=" << dataManager_->getGlobalParameters()->getIntegrationStep() << "  /nsteps=" << dataManager_->getGlobalParameters()->getNbSteps() << "  nsc=" << dataManager_->getGlobalParameters()->getScPeriod() << "  /nout=10" << endl;
76  outfile << "END" << endl;
77  outfile.close();
78  dataManager_->consoleMessage("fichier input termine pour PARMELA");
79  return true;
80}
81
82bool softwareParmela::execute(string workingDir)
83{
84  bool ExecuteStatus = true;
85 
86  ostringstream sortie;
87  sortie << " EXECUTION DE PARMELA " <<  endl;
88   
89  string parmelaJob = workingDir + "parmela";
90  parmelaJob += string("   ");
91  parmelaJob += workingDir;
92 
93  string resultOfRun;
94  bool success = launchJob(parmelaJob,resultOfRun);
95
96
97  //  sortie << resultOfRun << endl;
98  if ( !success ) {
99    sortie << " launching of parmela failed " << endl;
100    ExecuteStatus = false;
101  } else {
102    sortie << " successful launching of parmela " << endl;
103    cout << " execution parmela MARCHE " << endl;
104    string::size_type nn = (resultOfRun).find("normal");
105    if ( nn == string::npos )
106      {
107        sortie << " abnormal exit of parmela " << endl;
108        ExecuteStatus = false;
109      } 
110  }
111 
112  dataManager_->consoleMessage(sortie.str());
113  return ExecuteStatus;
114}
115
116bool softwareParmela::buildBeamAfterElements( string workingDir)
117{
118  bool result = true;
119
120  unsigned curseur;
121  for ( unsigned int k=0; k < getSectionToExecute()->getElements().size() ; k++ ) {
122    abstractElement* elem = getSectionToExecute()->getElements()[k];
123      if ( elem == NULL ) {
124        dataManager_->consoleMessage(" softwareParmela::buildBeamAfterElements : null pointer on element " );
125        return  false;       
126      }
127
128    curseur = k;
129
130    if (!(doAcceptElement(getSectionToExecute()->getElements()[curseur]->getNomdElement().getElementType()) == TBoolOk)) {
131//      if ( relativeParmelaElementIndices_.at(curseur) < 0 ) {
132
133        // si l'element doit etre ignore de parmela, on renvoie sur le diag precedent
134        particleBeam* lastDiag = dataManager_->updateCurrentDiagnostic(false);
135
136        // if(elem->getNomdElement().getElementType() == snapshot) {
137        //   // si cet element est un snapshot, on organise la sortie correspondante
138        //   string* param = elem->getParametersString();
139        //   string cliche = workingDir + param[2].c_str();
140        //   if( beamToParmela(cliche,lastDiag) ) {
141        //       //         cout  <<  "["  <<  k  <<  "] : ecrit sur fichier " << cliche << " le contenu de beam["<<avantDernier<<"]"<<endl;
142        //     cout  <<  "["  <<  k  <<  "] : ecrit sur fichier " << cliche << " le contenu de beam[ ]"<<endl;
143        //   }
144        // }
145        // si le numero est reconnu de parmela
146      } else {
147         
148        // on initialise une nouvelle sortie diagnostic
149          particleBeam* newDiag = dataManager_->updateCurrentDiagnostic(true);
150          vector<double> centroid;
151          bareParticle refPart;
152          vector<bareParticle> particles;
153          double freq= dataManager_->getGlobalParameters()->getFrequency();
154          unsigned numeroParmel;
155//        numeroParmel = (unsigned)relativeParmelaElementIndices_.at(curseur);
156    numeroParmel = curseur;
157          cout << " lecture PARMELA el no absolu " << k << " numero relatif " << numeroParmel << " nom " << elem->getNomdElement().getExpandedName() << endl;
158        // lecture sortie parmela
159        if(!beamFromParmela(workingDir,numeroParmel,freq,centroid,refPart,particles))
160          {
161            // si echec, fin
162            dataManager_->consoleMessage(" softwareParmela::buildBeamAfterElements : failure in reading parmela result for element " + elem->getLabel() + " for unknown reason " );
163            return  false;
164          } else {
165          // si succes, on complete le diagnostic
166          newDiag->setWithParticles(centroid,refPart,particles);
167        }
168      }
169    }
170  return result;
171}
172bool softwareParmela::beamFromParmela(string workingDir,unsigned numeroParmel, double referencefrequency, vector<double>& centroid, bareParticle& refPart,vector<bareParticle>& particles )
173{   
174  string nomfilefais = workingDir + "parmdesz";
175  cout << " nom fichier desz : " << nomfilefais << endl;
176  FILE *filefais = fopen(nomfilefais.c_str(), "r");
177 
178  if ( filefais == (FILE*)0 ) {
179    dataManager_->consoleMessage(" beamFromParmela() erreur a l'ouverture du fichier 'parmdesz'");
180    cerr << " beamFromParmela() erreur a l'ouverture du fichier" << nomfilefais  << endl;
181    return false;
182  } else
183    cout << " beamFromParmela() : ouverture du fichier " << nomfilefais << endl;
184 
185  parmelaParticle partic;
186  std::vector<parmelaParticle> faisceau;
187  int testNombrePartRef =0;
188  double phaseRef = 0.0;
189 
190  while( partic.readFromParmelaFile(filefais) > 0 )
191    {
192     
193      if ( partic.ne == (int)numeroParmel ) {
194        if ( partic.np == 1 ) {
195          // en principe on est sur la particule de reference
196          if ( fabs(partic.xx) > EPSILON || fabs(partic.yy) > EPSILON || fabs(partic.xxp) > EPSILON  || fabs(partic.yyp) > EPSILON) {
197            printf(" ATTENTION part. reference douteuse  \n");
198            partic.imprim();
199          }
200          phaseRef = partic.phi;
201         
202          // le 'z' est 'absolu' (le long de la trajectoire)
203          TRIDVECTOR  posRef(partic.xx,partic.yy,partic.z);
204          TRIDVECTOR betagammaRef(partic.xxp*partic.begamz, partic.yyp*partic.begamz, partic.begamz);
205          refPart = bareParticle(posRef, betagammaRef);
206          testNombrePartRef++;
207          if ( testNombrePartRef != 1 ) {
208            dataManager_->consoleMessage(" beamFromParmela : nombre de part. de ref different de 1 :");
209            cerr << " nombre de part. de ref different de 1 : " << testNombrePartRef << " !! " << endl;
210            return false;
211          }
212        }
213        faisceau.push_back(partic);
214      }
215    } //while
216 
217  if ( faisceau.size() == 0)
218    {
219      string stringNum = mixedTools::intToString( (int)numeroParmel );
220      dataManager_->consoleMessage("beamFromParmela echec lecture  element numero relatif  parmela : " + stringNum);
221      cerr << " beamFromParmela echec lecture  element numero relatif  parmela " << numeroParmel << endl;
222      return false;
223    }
224 
225  // facteur  c/ 360. pour calculer (c dphi) / (360.freq)
226  // avec freq en Mhz et dphi en degres et résultat en cm:
227  double FACTEUR =  83.3333;  // ameliorer la precision
228 
229  // pour l'instant on choisit un centroid nul;
230  centroid.clear();
231  centroid = vector<double>(6,0.0);
232 
233  particles.clear();
234  particles.resize(faisceau.size(), bareParticle());
235  //  double x,xp,y,yp;
236  double xp, yp;
237  double betagammaz;
238  //  double betaz;
239  double cdt;
240  double dephas;
241  double g;
242  TRIDVECTOR  pos;
243  TRIDVECTOR betagamma;
244  // contrairement a ce qu'indique la notice PARMELA, dans parmdesz, les xp et yp
245  // sont donnes en radians
246  for (unsigned k = 0; k < faisceau.size(); k++) {
247    //    x= faisceau.at(k).xx;
248    xp=faisceau.at(k).xxp;
249    //    y= faisceau.at(k).yy;
250    yp=faisceau.at(k).yyp;
251    // dephasage par rapport a la reference
252    dephas = faisceau.at(k).phi - phaseRef; // degrés
253    g = faisceau.at(k).wz/EREST_MeV;
254    betagammaz = faisceau.at(k).begamz;
255    //    betaz = betagammaz/(g+1.0);
256    //    deltaz = FACTEUR * betaz * dephas / referencefrequency;
257    cdt = FACTEUR * dephas / referencefrequency;
258    //    x += xp * deltaz;
259    //    y += yp * deltaz;
260    pos.setComponents(faisceau.at(k).xx,faisceau.at(k).yy,cdt);
261    betagamma.setComponents(xp*betagammaz, yp*betagammaz, betagammaz);
262    particles.at(k) = bareParticle(pos,betagamma);
263  }
264 
265  return true;
266}
267
268// sauvegarde d'un 'particleBeam' sur un fichier parmela, en guise d'INPUT
269// pour l'instant de nom standard 'parin.input0'
270bool softwareParmela::beamToParmela(string nameOfFile,particleBeam* beam)
271{
272    if ( !beam->particleRepresentationOk() ) {
273        dataManager_->consoleMessage("softwareParmela::beamToParmela : beam not in particles form : not yet programmed");
274        cout << " softwareParmela::beamToParmela : beam not in particles form : not yet programmed " << endl;
275        return false;
276    }
277   
278    ofstream outfile;
279    outfile.open(nameOfFile.c_str(),ios::out);
280    if (!outfile) {
281        dataManager_->consoleMessage(" softwareParmela::beamToParmela : error opening output stream ");
282        cerr << " softwareParmela::beamToParmela : error opening output stream " << nameOfFile << endl;
283        return false;
284    }
285   
286    //    const vector<bareParticle>& partic = beam->getParticleVector();
287    double weight = 1.0;
288    double xx,yy,zz;
289    double begamx, begamy, begamz;
290    //    TRIDVECTOR pos, begam;
291    double zmin = GRAND;
292    double zmax = -zmin; 
293    double cdtmin, cdtmax;
294    beam->ZrangeCdt(cdtmin, cdtmax);
295    cout << " softwareParmela::beamToParmela cdtmin = " << cdtmin << " cdtmax = " << cdtmax << endl;
296 
297    for (unsigned k = 0; k < beam->getNbParticles(); k++) {
298        // partic.at(k).getPosition().getComponents(xx,yy,zz);
299        // partic.at(k).getBetaGamma().getComponents(begamx,begamy,begamz);
300      beam->coordonneesDeployees(k, -cdtmax).getComponents(xx,yy,zz);
301      beam->betaGamma(k).getComponents(begamx,begamy,begamz);
302      if ( zz > zmax) zmax = zz;
303      if ( zz < zmin ) zmin = zz;
304        outfile << xx << " " << begamx << " " <<  yy << " " << begamy << " " << zz << " " << begamz  << " " << weight << endl;
305    }
306    outfile.close();
307    cout << " softwareParmela::beamToParmela zmn = " << zmin << " zmax = " << zmax << endl;
308    return true;
309}
310
311
312string softwareParmela::elementsData(const vector< pair<string, vector<string> > >& donnees) const {
313  unsigned k;
314  cout << " PASSAGE softwareParmela::elementsData " << endl;
315  if ( donnees.at(0).first != "labelsGenericSpecific" ) {
316    cout << " softwareParmela::elementsData ERROR : element badly defined " << endl;
317    return string();
318  }
319  string genericName = donnees.at(0).second.at(0);
320  if ( genericName == "rfgun" ) return rfgunData(donnees);
321  if ( genericName == "cell" ) return cellData(donnees);
322  if ( genericName == "drift" ) return driftData(donnees);
323  if ( genericName == "solnd" ) return solenoData(donnees);
324  if ( genericName == "bend" ) return bendData(donnees);
325  return string();
326}
327
328string softwareParmela::rfgunData(const vector< pair<string, vector<string> > >& donnees) const {
329
330  cout << " PASSAGE softwareParmela::rfgunData " << endl;
331  string nmacrop = "0";
332  string sigma_t = "0.0";
333  string sigma_r = "0.0";
334  string E_cin = "0.0";
335  string sigma_E = "0.0";
336  string phaseStep = "0.0";
337  string totalCharge = "0.0";
338
339  unsigned k;
340  for ( k=1; k < donnees.size(); k++) {
341    if ( donnees.at(k).first == "nbMacroparticles" ) { 
342      nmacrop = donnees.at(k).second.at(0);
343    } else if ( donnees.at(k).first == "sigmasTR" ) {
344      sigma_t = donnees.at(k).second.at(0);
345      sigma_r = donnees.at(k).second.at(1);
346    } else if ( donnees.at(k).first == "kineticE" ) {
347      E_cin = donnees.at(k).second.at(0);
348      sigma_E = donnees.at(k).second.at(1);
349    } else if ( donnees.at(k).first == "phaseStep" ) {
350      phaseStep = donnees.at(k).second.at(0);
351    } else if ( donnees.at(k).first == "totalCharge" ) {
352      totalCharge = donnees.at(k).second.at(0);
353    }
354  }
355  ostringstream sortie;
356  // on prend les troncatures tmax et rmax à 3 sigmas
357  sortie << "INPUT 10 /np=" << nmacrop << "  /sigt=" << sigma_t << endl;
358  sortie << "  /tmax=" << 3.3*atof(sigma_t.c_str()) << " /sigr=" << sigma_r << endl;
359  sortie << " /rmax=" << 3.0*atof(sigma_r.c_str()) << " /W0=" << E_cin << " /dw0=" << sigma_E << endl;
360  sortie << " /dwt=" << phaseStep << " /ran=2" << endl;
361
362  // on doit entrer le nb vrai de part. (avec signe moins)
363  sortie << "SCHEFF /beami=" << -fabs( atof(totalCharge.c_str()) )/ELECTRONANOCOULOMB << " /nprog=2 /point=-1.7"  << endl;
364 
365  return sortie.str();
366}
367
368string softwareParmela::cellData(const vector< pair<string, vector<string> > >& donnees) const {
369  cout << " PASSAGE softwareParmela::cellData " << endl;
370
371  string lenght = "0.0";
372  string aperture = "0.0";
373  string initialPhase = "0.0";
374  string acceleratingField = "0.0";
375  string phaseStepMax = "0.0";
376  string acceleratingShapeFile = "";
377  string focusingMagFile = "";
378  string offsetMag = "0.0";
379  string scaleFactor = "0.0";
380
381  unsigned k;
382  for ( k=1; k < donnees.size(); k++) {
383    if ( donnees.at(k).first == "lenghtAperture" ) { 
384      lenght = donnees.at(k).second.at(0);
385      aperture = donnees.at(k).second.at(1);
386    } else if ( donnees.at(k).first == "phaseInitialStepmax" ) {
387      initialPhase = donnees.at(k).second.at(0);
388      phaseStepMax = donnees.at(k).second.at(1);
389    } else if ( donnees.at(k).first == "fieldValueFile" ) {
390      acceleratingField = donnees.at(k).second.at(0);
391      acceleratingShapeFile = donnees.at(k).second.at(1);
392    } else if ( donnees.at(k).first == "MagFocusingFileOffsetScale") {
393      focusingMagFile = donnees.at(k).second.at(0);
394      offsetMag = donnees.at(k).second.at(1);
395      scaleFactor = donnees.at(k).second.at(2);
396    }
397  }
398  ostringstream sortie;
399    sortie << "CELL /l=" << lenght << "  /aper=" << aperture << endl;
400    sortie << "  /iout=1  /phi0=" << initialPhase << " /E0=" << acceleratingField << endl;
401    sortie << " /nc=1 /dwtmax=" << phaseStepMax << " /sym=-1" << endl;
402    sortie << "CFIELD 1" << endl;
403    sortie << acceleratingShapeFile << endl;
404    if ( focusingMagFile != "") {
405      sortie << "POISSON /zoff=" << offsetMag << " /rmult=" << scaleFactor << endl;
406      sortie << focusingMagFile << endl;
407    }
408  return sortie.str();
409
410}
411
412string softwareParmela::driftData(const vector< pair<string, vector<string> > >& donnees) const {
413  cout << " PASSAGE softwareParmela::driftData " << endl;
414
415  string lenght = "0.0";
416  string aperture = "0.0";
417
418  unsigned k;
419  for ( k=1; k < donnees.size(); k++) {
420    if ( donnees.at(k).first == "lenghtAperture" ) { 
421      lenght = donnees.at(k).second.at(0);
422      aperture = donnees.at(k).second.at(1);
423    }
424  }
425  ostringstream sortie;
426  sortie << "DRIFT /l=" << lenght << "  /aper=" << aperture << "  /iout=1" << endl;
427  return sortie.str();
428}
429
430string softwareParmela::solenoData(const vector< pair<string, vector<string> > >& donnees) const {
431  cout << " PASSAGE softwareParmela::solenoData " << endl;
432  string lenght = "0.0";
433  string aperture = "0.0";
434  string B0 = "0.0";
435
436  unsigned k;
437  for ( k=1; k < donnees.size(); k++) {
438    if ( donnees.at(k).first == "lenghtAperture" ) { 
439      lenght = donnees.at(k).second.at(0);
440      aperture = donnees.at(k).second.at(1);
441    } else if ( donnees.at(k).first == "field" ) {
442      B0 = donnees.at(k).second.at(0);
443    }
444  }
445    ostringstream sortie;
446    // on passe l'induction magnetique en Gauss
447    sortie << "SOLENOID /l=" << lenght << "  /aper=" << aperture << "  /iout=1 /h=" << 1000.*atof(B0.c_str())  << endl;
448    return sortie.str();
449
450}
451
452string softwareParmela::bendData(const vector< pair<string, vector<string> > >& donnees) const {
453  cout << " PASSAGE softwareParmela::bendData " << endl;
454
455  string lenght = "0.0";
456  string aperture = "0.0";
457  string angleDeg = "0.0";
458  string momentum = "0.0";
459  string beta1 = "0.0";
460  string beta2 = "0.0";
461  unsigned k;
462  for ( k=1; k < donnees.size(); k++) {
463    if ( donnees.at(k).first == "lenghtAperture" ) { 
464      lenght = donnees.at(k).second.at(0);
465      aperture = donnees.at(k).second.at(1);
466    } else if ( donnees.at(k).first == "angleDegre" ) {
467      angleDeg = donnees.at(k).second.at(0);
468    } else if ( donnees.at(k).first == "momentum" ) {
469      momentum = donnees.at(k).second.at(0);
470     } else if ( donnees.at(k).first == "rotatedFaces" ) {
471      beta1 = donnees.at(k).second.at(0);
472      beta2 = donnees.at(k).second.at(1);
473    }   
474  }
475
476  double ecin = atof(momentum.c_str())/EREST_MeV;
477    ecin = ecin*ecin + 1.;
478    ecin = EREST_MeV*(sqrt(ecin) - 1.0);
479
480    ostringstream sortie;
481    // il faut entrer l'energie cinetique
482    sortie << "BEND /l=" << lenght << "  / aper=" << aperture << "  / iout=1 / wr=" << ecin << " /alpha=" << angleDeg << " / beta1=" << beta1;
483    sortie << " / beta2=" << beta2  << endl;
484
485    return sortie.str();
486
487}
Note: See TracBrowser for help on using the repository browser.