#include "softwareParmela.h" #include "abstractElement.h" #include "parmelaParticle.h" #include "mathematicalConstants.h" #include "PhysicalConstants.h" #include "dataManager.h" #include "mixedTools.h" softwareParmela::softwareParmela() : abstractSoftware() {;} softwareParmela::softwareParmela(string inputFileName, globalParameters* globals, dataManager* dt) : abstractSoftware(inputFileName, globals, dt) {;} bool softwareParmela::createInputFile(particleBeam* beamBefore,unsigned int numeroDeb,unsigned int numeroFin,string workingDir) { unsigned int k; if ( numeroDeb < 1 || numeroFin > dataManager_->getBeamLineSize() ) { dataManager_->consoleMessage(" softwareParmela::createInputFile : numero of element out of limits " ); cerr << " numero of element out of limits " << endl; return false; } string name = workingDir + inputFileName_; ofstream outfile; outfile.open(name.c_str(), ios::out); if (!outfile) { dataManager_->consoleMessage(" softwareParmela::createInputFile : error opening output stream " ); cerr << " softwareParmela::createInputFile : error opening output stream " << name << endl; return false; } abstractElement* elPtr; double initalKineticEnergy = 0.0; elPtr = dataManager_->getElementPointerFromNumero(numeroDeb); bool there_is_rfgun = ( elPtr->getNomdElement().getElementType() == RFgun ); if ( !there_is_rfgun ) { string nameOfInput = workingDir + "parin.input0"; if ( !beamToParmela(nameOfInput,beamBefore) ) return false; initalKineticEnergy = beamBefore->referenceKineticEnergyMeV(); // les elements de parmela sont indexes de 1 à max, s'il n'y a pas de rfgun offsetNumElem_ = numeroDeb -1; } else { elPtr->setPhaseStep( globParamPtr_->getIntegrationStep() ); initalKineticEnergy = elPtr->getInitialKineticEnergy(); // les elements de parmela sont indexes de 0 à max, s'il y a un rfgun offsetNumElem_ = numeroDeb; } outfile << "TITLE" << endl; outfile << " titre provisoire " << endl; outfile << "RUN /n0=1 /ip=999 /freq=" << globParamPtr_->getFrequency() << " /z0=0.0 /W0=" << initalKineticEnergy << " /itype=1" << endl; outfile << "OUTPUT 0" << endl; unsigned int premier = numeroDeb ; if ( there_is_rfgun ) { outfile << dataManager_->getElementPointerFromNumero(numeroDeb)->parmelaOutputFlow() << endl; premier++; } else { outfile << "INPUT 0 /NP=" << beamBefore->getNbParticles() << endl; } // commentaire : si l'element est un snapshot ne rien ecrire dans inputFileName_ (= parmin) un saut de ligne perturbe l'execution de parmela for ( k = premier; k <= numeroFin; k++) { elPtr = dataManager_->getElementPointerFromNumero(k); if (elPtr) { if(elPtr->getNomdElement().getElementType() == snapshot) continue; outfile << elPtr->parmelaOutputFlow() << endl; } } outfile << "ZOUT" << endl; outfile << "START /wt=0.0 /dwt=" << globParamPtr_->getIntegrationStep() << " /nsteps=" << globParamPtr_->getNbSteps() << " nsc=" << globParamPtr_->getScPeriod() << " /nout=10" << endl; outfile << "END" << endl; outfile.close(); dataManager_->consoleMessage("fichier input termine pour PARMELA"); return true; } bool softwareParmela::execute(unsigned int numeroDeb,unsigned int numeroFin,string workingDir) { bool ExecuteStatus = true; ostringstream sortie; sortie << " EXECUTION DE PARMELA DE l'ELEMENT " << numeroDeb << " A L'ELEMENT " << numeroFin << endl; string parmelaJob = workingDir + "parmela"; parmelaJob += string(" "); parmelaJob += workingDir; string resultOfRun; bool success = launchJob(parmelaJob,resultOfRun); sortie << resultOfRun << endl; if ( !success ) { sortie << " launching of parmela failed " << endl; ExecuteStatus = false; } else { sortie << " successful launching of parmela " << endl; cout << " execution parmela MARCHE " << endl; string::size_type nn = (resultOfRun).find("normal"); if ( nn == string::npos ) { sortie << " abnormal exit of parmela " << endl; ExecuteStatus = false; } } dataManager_->consoleMessage(sortie.str()); return ExecuteStatus; } bool softwareParmela::buildBeamAfterElements(unsigned int numeroDeb,unsigned int numeroFin, vector& beams, string workingDir) { bool result = true; //cout << "debug:: debut " << numeroDeb << ", fin " << numeroFin << endl; // index du premier element de parmela int id= numeroDeb-offsetNumElem_; for(unsigned k = numeroDeb; k <= numeroFin; k++) { abstractElement* elem = dataManager_->getElementPointerFromNumero(k); // si l'element est un snapshot, recuperer la sortie precedente if(elem->getNomdElement().getElementType() == snapshot) { int avantDernier = beams.size() - 1; string* param = elem->getParametersString(); string cliche = workingDir + param[2].c_str(); if( beamToParmela(cliche,&beams.at(avantDernier)) ) { cout << "[" << k << "] : ecrit sur fichier " << cliche << " le contenu de beam["< centroid; bareParticle refPart; vector particles; double freq= globParamPtr_->getFrequency(); cout << " lecture PARMELA el no absolu " << k << " nom " << elem->getNomdElement().getElementName() << endl; if(!beamFromParmela(workingDir,id,freq,centroid,refPart,particles)) { if(elem->is_accepted_by_software(nomDeLogiciel::parmela) == TBoolIgnore) { int avantDernier = beams.size() -2; beams.back() = beams.at(avantDernier); } else { dataManager_->consoleMessage("softwareParmela::buildBeamAfterElements : reading parmdesz failed"); result = false; break; } } else { beams.back().setWithParticles(centroid,refPart,particles); } // l'element de parmela suivant id++; } return result; } bool softwareParmela::beamFromParmela(string workingDir,unsigned numeroParmel, double referencefrequency, vector& centroid, bareParticle& refPart,vector& particles ) { string nomfilefais = workingDir + "parmdesz"; cout << " nom fichier desz : " << nomfilefais << endl; FILE *filefais = fopen(nomfilefais.c_str(), "r"); if ( filefais == (FILE*)0 ) { dataManager_->consoleMessage(" beamFromParmela() erreur a l'ouverture du fichier 'parmdesz'"); cerr << " beamFromParmela() erreur a l'ouverture du fichier" << nomfilefais << endl; return false; } else cout << " beamFromParmela() : ouverture du fichier " << nomfilefais << endl; parmelaParticle partic; std::vector faisceau; int testNombrePartRef =0; double phaseRef = 0.0; while( partic.readFromParmelaFile(filefais) > 0 ) { if ( partic.ne == (int)numeroParmel ) { if ( partic.np == 1 ) { // en principe on est sur la particule de reference if ( fabs(partic.xx) > EPSILON || fabs(partic.yy) > EPSILON || fabs(partic.xxp) > EPSILON || fabs(partic.yyp) > EPSILON) { printf(" ATTENTION part. reference douteuse \n"); partic.imprim(); } phaseRef = partic.phi; // le 'z' est 'absolu' (le long de la trajectoire) TRIDVECTOR posRef(partic.xx,partic.yy,partic.z); TRIDVECTOR betagammaRef(partic.xxp*partic.begamz, partic.yyp*partic.begamz, partic.begamz); refPart = bareParticle(posRef, betagammaRef); testNombrePartRef++; if ( testNombrePartRef != 1 ) { dataManager_->consoleMessage(" beamFromParmela : nombre de part. de ref different de 1 :"); cerr << " nombre de part. de ref different de 1 : " << testNombrePartRef << " !! " << endl; return false; } } faisceau.push_back(partic); } } //while if ( faisceau.size() == 0) { string stringNum = mixedTools::intToString( (int)numeroParmel ); dataManager_->consoleMessage("beamFromParmela echec lecture element numero relatif parmela : " + stringNum); cerr << " beamFromParmela echec lecture element numero relatif parmela " << numeroParmel << endl; return false; } // facteur c/ 360. pour calculer (c dphi) / (360.freq) // avec freq en Mhz et dphi en degres et résultat en cm: double FACTEUR = 83.3333; // ameliorer la precision // pour l'instant on choisit un centroid nul; centroid.clear(); centroid = vector(6,0.0); particles.clear(); particles.resize(faisceau.size(), bareParticle()); double x,xp,y,yp; double betagammaz; double betaz; double deltaz; double dephas; double g; TRIDVECTOR pos; TRIDVECTOR betagamma; // contrairement a ce qu'indique la notice PARMELA, dans parmdesz, les xp et yp // sont donnes en radians for (unsigned k = 0; k < faisceau.size(); k++) { x= faisceau.at(k).xx; xp=faisceau.at(k).xxp; y= faisceau.at(k).yy; yp=faisceau.at(k).yyp; // dephasage par rapport a la reference dephas = faisceau.at(k).phi - phaseRef; // degrés g = faisceau.at(k).wz/EREST_MeV; betagammaz = faisceau.at(k).begamz; betaz = betagammaz/(g+1.0); deltaz = FACTEUR * betaz * dephas / referencefrequency; x += xp * deltaz; y += yp * deltaz; pos.setComponents(x,y,deltaz); betagamma.setComponents(xp*betagammaz, yp*betagammaz, betagammaz); particles.at(k) = bareParticle(pos,betagamma); } return true; } // sauvegarde d'un 'particleBeam' sur un fichier parmela, en guise d'INPUT // pour l'instant de nom standard 'parin.input0' bool softwareParmela::beamToParmela(string nameOfFile,particleBeam* beam) { if ( !beam->particleRepresentationOk() ) { dataManager_->consoleMessage("softwareParmela::beamToParmela : beam not in particles form : not yet programmed"); cout << " softwareParmela::beamToParmela : beam not in particles form : not yet programmed " << endl; return false; } ofstream outfile; outfile.open(nameOfFile.c_str(),ios::out); if (!outfile) { dataManager_->consoleMessage(" softwareParmela::beamToParmela : error opening output stream "); cerr << " softwareParmela::beamToParmela : error opening output stream " << nameOfFile << endl; return false; } const vector& partic = beam->getParticleVector(); double weight = 1.0; double xx,yy,zz; double begamx, begamy, begamz; for (unsigned k = 0; k < partic.size(); k++) { partic.at(k).getPosition().getComponents(xx,yy,zz); partic.at(k).getBetaGamma().getComponents(begamx,begamy,begamz); outfile << xx << " " << begamx << " " << yy << " " << begamy << " " << zz << " " << begamz << " " << weight << endl; } outfile.close(); return true; }