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

Last change on this file since 418 was 418, checked in by lemeur, 11 years ago

definition des compatibilites des elements dans les software

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