#include "softwareParmela.h" #include "abstractElement.h" #include "parmelaParticle.h" #include "mathematicalConstants.h" #include "PhysicalConstants.h" #include "dataManager.h" #include "mixedTools.h" //#include "nomDeLogiciel.h" softwareParmela::softwareParmela() : abstractSoftware() { nameOfSoftware_ = nomDeLogiciel("parmela"); } softwareParmela::softwareParmela(string inputFileName, globalParameters* globals, dataManager* dt) : abstractSoftware(inputFileName, globals, dt) { nameOfSoftware_ = nomDeLogiciel("parmela"); } void softwareParmela::setRelativeParmelaElementIndices() { relativeParmelaElementIndices_.clear(); relativeParmelaElementIndices_.resize(numeroFin_ - numeroDeb_ + 1, -1); cout << " setRelativeParmelaElementIndices() taille a priori : " << relativeParmelaElementIndices_.size() << endl; abstractElement* elPtr = dataManager_->getElementPointerFromNumero(numeroDeb_); bool there_is_rfgun = ( elPtr->getNomdElement().getElementType() == RFgun ); unsigned offsetNumElem; // les elements de parmela sont indexes de 1 à max, s'il n'y a pas de rfgun if ( !there_is_rfgun ) { offsetNumElem = numeroDeb_ -1; // les elements de parmela sont indexes de 0 à max, s'il y a un rfgun } else { offsetNumElem = numeroDeb_; } // index du premier element de parmela int id= numeroDeb_ - offsetNumElem; unsigned k; unsigned curseur = 0; for ( k=numeroDeb_; k <= numeroFin_ ; k++ ) { abstractElement* elem = dataManager_->getElementPointerFromNumero(k); cout << " liste PARMELA no absolu " << k << " relatif provisoire " << relativeParmelaElementIndices_.at(curseur) << endl; if ( elem->is_accepted_by_software(nameOfSoftware_) == TBoolOk ) { relativeParmelaElementIndices_.at(curseur) = id; cout << " mis a " << id << endl; id++; } curseur++; } } bool softwareParmela::createInputFile(particleBeam* beamBefore,unsigned int numeroDeb,unsigned int numeroFin,string workingDir) { unsigned int k; if ( !initComputationLimits(numeroDeb,numeroFin) ) return false; setRelativeParmelaElementIndices(); 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(); premier++; } else { outfile << "INPUT 0 /NP=" << beamBefore->getNbParticles() << endl; } for ( k = premier; k <= numeroFin_; k++) { elPtr = dataManager_->getElementPointerFromNumero(k); if (elPtr) { outfile << elPtr->parmelaOutputFlow(); } } 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(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( string workingDir) { bool result = true; if ( !ComputationLimitsOk() ) return false; unsigned curseur; for(unsigned k = numeroDeb_; k <= numeroFin_; k++) { abstractElement* elem = dataManager_->getElementPointerFromNumero(k); if ( elem == NULL ) { dataManager_->consoleMessage(" softwareParmela::buildBeamAfterElements : null pointer on element " ); return false; } curseur = k - numeroDeb_; if ( relativeParmelaElementIndices_.at(curseur) < 0 ) { // si l'element doit etre ignore de parmela, on renvoie sur le diag precedent particleBeam* lastDiag = dataManager_->updateCurrentDiagnostic(false); // if(elem->getNomdElement().getElementType() == snapshot) { // // si cet element est un snapshot, on organise la sortie correspondante // string* param = elem->getParametersString(); // string cliche = workingDir + param[2].c_str(); // if( beamToParmela(cliche,lastDiag) ) { // // cout << "[" << k << "] : ecrit sur fichier " << cliche << " le contenu de beam["<updateCurrentDiagnostic(true); vector centroid; bareParticle refPart; vector particles; double freq= globParamPtr_->getFrequency(); unsigned numeroParmel; numeroParmel = (unsigned)relativeParmelaElementIndices_.at(curseur); cout << " lecture PARMELA el no absolu " << k << " numero relatif " << numeroParmel << " nom " << elem->getNomdElement().getElementName() << endl; // lecture sortie parmela if(!beamFromParmela(workingDir,numeroParmel,freq,centroid,refPart,particles)) { // si echec, fin dataManager_->consoleMessage(" softwareParmela::buildBeamAfterElements : failure in reading parmela result for element " + elem->getLabel() + " for unknown reason " ); return false; } else { // si succes, on complete le diagnostic newDiag->setWithParticles(centroid,refPart,particles); } } } 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 xp, yp; double betagammaz; // double betaz; double cdt; 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; cdt = FACTEUR * dephas / referencefrequency; // x += xp * deltaz; // y += yp * deltaz; pos.setComponents(faisceau.at(k).xx,faisceau.at(k).yy,cdt); 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; // TRIDVECTOR pos, begam; double zmin = GRAND; double zmax = -zmin; double cdtmin, cdtmax; beam->ZrangeCdt(cdtmin, cdtmax); cout << " softwareParmela::beamToParmela cdtmin = " << cdtmin << " cdtmax = " << cdtmax << endl; for (unsigned k = 0; k < beam->getNbParticles(); k++) { // partic.at(k).getPosition().getComponents(xx,yy,zz); // partic.at(k).getBetaGamma().getComponents(begamx,begamy,begamz); beam->coordonneesDeployees(k, -cdtmax).getComponents(xx,yy,zz); beam->betaGamma(k).getComponents(begamx,begamy,begamz); if ( zz > zmax) zmax = zz; if ( zz < zmin ) zmin = zz; outfile << xx << " " << begamx << " " << yy << " " << begamy << " " << zz << " " << begamz << " " << weight << endl; } outfile.close(); cout << " softwareParmela::beamToParmela zmn = " << zmin << " zmax = " << zmax << endl; return true; }