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

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

refection generale des secteurs et applications de softwares (suite)

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