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

Last change on this file since 485 was 485, checked in by lemeur, 10 years ago

liste des logiciels compatibles dans les tooltip des elements

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