bool xaeBlockScene::update(float fDT) { g_BGMPlayer.update(fDT); #ifdef __DEBUG if(xae::Instance().keyup(HGEK_ESCAPE)) { g_bDebugStop ^= true; } if(g_bDebugStop) return false; /** 彩旦:直接赢了 */ if(xae::Instance().keystate(HGEK_CTRL) && xae::Instance().keystate(HGEK_E)) { xaeAVGScene* scene = (xaeAVGScene*)(xaeSceneMgr::Instance().get_scene("AVG")); /** 若死过了而且是PreBoss关 */ if(scene->getRevived() && m_szLevelName == g_Setting.Block.m_szPreBoss) { xaeSceneMgr::Instance().del_scene("AVG"); xaeSceneObject* sceneo = xaeSceneMgr::Instance().create_scene("Welcome", "Welcome"); xaeSceneMgr::Instance().add_scene("Welcome", sceneo); xaeSceneMgr::Instance().set_current_scene("Welcome"); return false; } /** 否则跳到AVG画面 */ scene->parseNextPause(); xaeSceneMgr::Instance().set_current_scene("AVG"); /** Pre Boss干翻了 */ if(m_szLevelName == g_Setting.Block.m_szPreBoss) { scene->setPreBossed(); } return false; } #endif /** 暂停 */ if(xae::Instance().keyup(HGEK_ENTER)) { if(m_emStatus == XBPS_PLAYING) { m_emStatus = XBPS_PAUSE; return false; } else if(m_emStatus == XBPS_PAUSE) { m_emStatus = XBPS_PLAYING; } } if(m_emStatus == XBPS_PAUSE) return false; /** GUI */ float mousex, mousey; m_pHGE->Input_GetMousePos(&mousex, &mousey); m_pGUI->update(fDT, mousex, mousey); /** 挡板左右转 */ float dx = fDT * g_Setting.Block.m_fFlapSpeed; if(xae::Instance().keystate(HGEK_RIGHT)) { if(m_fFlapX + dx + g_Setting.Block.m_nFlapLength * m_dwFlapNum <= 600.0f) { m_fFlapX += dx; if(m_emStatus == XBPS_READY) { m_fBallX += dx; } } else { m_fFlapX = 600.0f - g_Setting.Block.m_nFlapLength * m_dwFlapNum; if(m_emStatus == XBPS_READY) { m_fBallX = 600.0f - (g_Setting.Block.m_nFlapLength * m_dwFlapNum) / 2.0f; } } } if(xae::Instance().keystate(HGEK_LEFT)) { if(m_fFlapX - dx >= 0) { m_fFlapX -= dx; if(m_emStatus == XBPS_READY) { m_fBallX -= dx; } } else { m_fFlapX = 0.0f; if(m_emStatus == XBPS_READY) { m_fBallX = (g_Setting.Block.m_nFlapLength * m_dwFlapNum) / 2.0f; } } } /** 道具更新 */ m_Treasure.update(fDT, m_fFlapX, m_fFlapY); /** 挡板长度 */ float fFlapCenterX = m_fFlapX + (m_dwFlapNum * g_Setting.Block.m_nFlapLength) / 2.0f; m_dwFlapNum = m_Treasure.getFlapNum(); m_fFlapX = fFlapCenterX - (m_dwFlapNum * g_Setting.Block.m_nFlapLength) / 2; if(m_fFlapX < 0) m_fFlapX = 0; else if(m_fFlapX + m_dwFlapNum * g_Setting.Block.m_nFlapLength > 600.0f) m_fFlapX = 600.0f - m_dwFlapNum * g_Setting.Block.m_nFlapLength; /** 空格或者回车 */ if(xae::Instance().keyup(HGEK_SPACE) || xae::Instance().keyup(HGEK_ENTER)) { /** 变成开始状态 */ if(m_emStatus == XBPS_READY) { m_emStatus =XBPS_PLAYING; } else /** 赢了按回车回到AVG画面 */ if(m_emStatus == XBPS_WIN) { xaeAVGScene* scene = (xaeAVGScene*)(xaeSceneMgr::Instance().get_scene("AVG")); /** 若死过了而且是PreBoss关 */ if(scene->getRevived() && m_szLevelName == g_Setting.Block.m_szPreBoss) { xaeSceneMgr::Instance().del_scene("AVG"); xaeSceneObject* sceneo = xaeSceneMgr::Instance().create_scene("Welcome", "Welcome"); xaeSceneMgr::Instance().add_scene("Welcome", sceneo); xaeSceneMgr::Instance().set_current_scene("Welcome"); return false; } /** 否则跳到AVG画面 */ scene->parseNextPause(); xaeSceneMgr::Instance().set_current_scene("AVG"); /** Pre Boss干翻了 */ if(m_szLevelName == g_Setting.Block.m_szPreBoss) { scene->setPreBossed(); } return false; } } /** 游戏在玩的状态 */ if(m_emStatus == XBPS_PLAYING) { /** 球飞啦! */ float fbdx = m_fBallSpeedX * fDT, fbdy = m_fBallSpeedY * fDT; fbdx *= m_Treasure.getSpeedScale(); fbdy *= m_Treasure.getSpeedScale(); /** 横向飞 */ if(m_fBallX + fbdx - g_Setting.Block.m_nBallLength / 2 >= 0.0f && m_fBallX + fbdx + g_Setting.Block.m_nBallLength / 2 <= 600.0f) { m_fBallX += fbdx; } else if(m_fBallX + fbdx - g_Setting.Block.m_nBallLength / 2 < 0.0f) m_fBallX = g_Setting.Block.m_nBallLength / 2, m_fBallSpeedX = -m_fBallSpeedX; else m_fBallX = 600 - g_Setting.Block.m_nBallLength / 2, m_fBallSpeedX = -m_fBallSpeedX; /** 纵向飞 */ if(m_fBallY + fbdy - g_Setting.Block.m_nBallLength / 2 >= 0.0f) { m_fBallY += fbdy; } else if(m_fBallY + fbdy - g_Setting.Block.m_nBallLength / 2 < 0.0f) m_fBallY = g_Setting.Block.m_nBallLength / 2, m_fBallSpeedY = - m_fBallSpeedY; //else m_fBallY = 590.0f, m_fBallSpeedY = - m_fBallSpeedY; /** 碰到挡板:往上弹 */ if(m_fBallY >= g_Setting.Block.m_fFlapY - g_Setting.Block.m_nBallLength / 2 && m_fBallY <= g_Setting.Block.m_fFlapY + 15.0f - g_Setting.Block.m_nBallLength / 2) { /** x轴在挡板范围内 */ if(m_fBallX >= m_fFlapX && m_fBallX <= m_fFlapX + m_dwFlapNum * g_Setting.Block.m_nFlapLength) { /** 根据小球在挡板的位置确定x速度 */ m_fBallSpeedX = (m_fBallX - (m_fFlapX + m_dwFlapNum * g_Setting.Block.m_nFlapLength / 2)) / (m_dwFlapNum * (g_Setting.Block.m_nFlapLength) / 2); m_fBallSpeedX *= g_Setting.Block.m_fMaxHorizontalRate; m_fBallSpeedX *= g_Setting.Block.m_fBallSpeed; /** 确定y轴速度:保证x和y的合速度为g_Setting.Block.m_fBallSpeed */ m_fBallSpeedY = -sqrt(g_Setting.Block.m_fBallSpeed * g_Setting.Block.m_fBallSpeed - m_fBallSpeedX * m_fBallSpeedX); } } /** 飞丢了 */ if(m_fBallY >= 600.0f) { /** 如果已经干翻了Pre Boss,则直接到welcome */ xaeAVGScene* scenea = (xaeAVGScene*)xaeSceneMgr::Instance().get_scene("AVG"); if(scenea->getPreBossed()) { xaeSceneObject* sceneo = xaeSceneMgr::Instance().create_scene("Welcome", "Welcome"); xaeSceneMgr::Instance().add_scene("Welcome", sceneo); xaeSceneMgr::Instance().del_scene("AVG"); xaeSceneMgr::Instance().set_current_scene("Welcome"); return false; } xaeSceneObject* scene = xaeSceneMgr::Instance().create_scene("Revive", "Revive"); if(NULL != scene) { xaeSceneMgr::Instance().add_scene("Revive", scene); } xaeSceneMgr::Instance().set_current_scene("Revive"); ((xaeReviveScene*)scene)->setLevel(m_szLevelName); /** 设置AVG为死过了 */ ((xaeAVGScene*)xaeSceneMgr::Instance().get_scene("AVG"))->setRevived(); return false; } /** 得到小球区域四个角的坐标 */ coor zs(m_fBallX, m_fBallY), zx(m_fBallX, m_fBallY), ys(m_fBallX, m_fBallY), yx(m_fBallX, m_fBallY); zs.x -= (g_Setting.Block.m_nBallLength / 2), zs.y -= (g_Setting.Block.m_nBallLength / 2); ys.x += (g_Setting.Block.m_nBallLength / 2), ys.y -= (g_Setting.Block.m_nBallLength / 2); zx.x -= (g_Setting.Block.m_nBallLength / 2), zx.y += (g_Setting.Block.m_nBallLength / 2); yx.x -= (g_Setting.Block.m_nBallLength / 2), yx.y -= (g_Setting.Block.m_nBallLength / 2); /** 求四个角所在的各方块的下标 */ int zsi = ((int)zs.y) / g_Setting.Block.m_nBlockHeight, zsj = ((int)zs.x) / g_Setting.Block.m_nBlockWidth; int ysi = ((int)ys.y) / g_Setting.Block.m_nBlockHeight, ysj = ((int)ys.x) / g_Setting.Block.m_nBlockWidth; int zxi = ((int)zx.y) / g_Setting.Block.m_nBlockHeight, zxj = ((int)zx.x) / g_Setting.Block.m_nBlockWidth; int yxi = ((int)yx.y) / g_Setting.Block.m_nBlockHeight, yxj = ((int)yx.x) / g_Setting.Block.m_nBlockWidth; /** 碰撞检测 */ coor zspz = collisionCheck(m_hTexClothHot, zsj * g_Setting.Block.m_nBlockWidth, zsi * g_Setting.Block.m_nBlockHeight, g_Setting.Block.m_nBlockWidth, g_Setting.Block.m_nBlockHeight); coor zxpz = collisionCheck(m_hTexClothHot, zxj * g_Setting.Block.m_nBlockWidth, zxi * g_Setting.Block.m_nBlockHeight, g_Setting.Block.m_nBlockWidth, g_Setting.Block.m_nBlockHeight); coor yspz = collisionCheck(m_hTexClothHot, ysj * g_Setting.Block.m_nBlockWidth, ysi * g_Setting.Block.m_nBlockHeight, g_Setting.Block.m_nBlockWidth, g_Setting.Block.m_nBlockHeight); coor yxpz = collisionCheck(m_hTexClothHot, yxj * g_Setting.Block.m_nBlockWidth, yxi * g_Setting.Block.m_nBlockHeight, g_Setting.Block.m_nBlockWidth, g_Setting.Block.m_nBlockHeight); /** 处理碰撞 */ if(zspz.x >= 0.0f && zspz.y >= 0.0f) { /** 这个方块消失 */ m_bClothes[zsi][zsj] = false; /** 方块数减少 */ m_dwBlockLeft--; m_Treasure.generateTreasure(zsj * g_Setting.Block.m_nBlockWidth + g_Setting.Block.m_nBlockWidth / 2, zsi * g_Setting.Block.m_nBlockHeight + g_Setting.Block.m_nBlockHeight / 2); /** 下同 */ } if(zxpz.x >= 0.0f && zxpz.y >= 0.0f && (zsi != zxi || zsj != zxj)) { m_bClothes[zxi][zxj] = false; m_dwBlockLeft--; m_Treasure.generateTreasure(zxj * g_Setting.Block.m_nBlockWidth + g_Setting.Block.m_nBlockWidth / 2, zxi * g_Setting.Block.m_nBlockHeight + g_Setting.Block.m_nBlockHeight / 2); } if(yspz.x >= 0.0f && yspz.y >= 0.0f && (zxi != ysi || zxj != ysj) && (zsi != ysi || zsj != ysj)) { m_bClothes[ysi][ysj] = false; m_dwBlockLeft--; m_Treasure.generateTreasure(ysj * g_Setting.Block.m_nBlockWidth + g_Setting.Block.m_nBlockWidth / 2, ysi * g_Setting.Block.m_nBlockHeight + g_Setting.Block.m_nBlockHeight / 2); } if(yxpz.x >= 0.0f && yxpz.y >= 0.0f && (zxi != yxi || zxj != yxj) && (ysi != yxi || ysj != yxj) && (zsi != yxi || zsj != yxj)) { m_bClothes[yxi][yxj] = false; m_dwBlockLeft--; m_Treasure.generateTreasure(yxj * g_Setting.Block.m_nBlockWidth + g_Setting.Block.m_nBlockWidth / 2, yxi * g_Setting.Block.m_nBlockHeight + g_Setting.Block.m_nBlockHeight / 2); } /** 重新设置速度 */ if(!m_Treasure.getHits()) { if(zspz.x >= 0.0f && zspz.y >= 0.0f) setRebound(zspz); else if(yspz.x >= 0.0f && yspz.y >= 0.0f) setRebound(yspz); else if(zxpz.x >= 0.0f && zxpz.y >= 0.0f) setRebound(zxpz); else if(yxpz.x >= 0.0f && yxpz.y >= 0.0f) setRebound(yxpz); } /** 所有方块打完了就赢了 */ if(m_dwBlockLeft == 0) m_emStatus = XBPS_WIN; } return false; }
main(int argc, char* argv[]){ time_t time1 = time(0), time2; //-------MPI initialzation------------- int numprocs, myid, namelen; char processor_name[MPI_MAX_PROCESSOR_NAME]; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Get_processor_name(processor_name, &namelen); fprintf(stderr, "Process %d running on %s\n", myid, processor_name); string numbers = "0123456789"; // !!!!! np <= 10 string myid_str(numbers, myid, 1); MPI_Status status; // define a new MPI data type for particles MPI_Datatype particletype; MPI_Type_contiguous(18, MPI_DOUBLE, &particletype); // !!! 14->18 changed MPI_Type_commit(&particletype); //-------- end MPI init---------------- // wait for gdb waitforgdb(myid); // read input file (e.g. patric.cfg): if(argv[1] == 0){ printf("No input file name !\n"); MPI_Abort(MPI_COMM_WORLD, 0); } input_from_file(argv[1], myid); double eps_x = rms_emittance_x0; // handy abbreviation double eps_y = rms_emittance_y0; // same // Synchronous particle: SynParticle SP; SP.Z = Z; SP.A = A; SP.gamma0 = 1.0 + (e_kin*1e6*qe)/(mp*clight*clight) ; SP.beta0 = sqrt((SP.gamma0*SP.gamma0-1.0)/(SP.gamma0*SP.gamma0)) ; SP.eta0 = 1.0/pow(gamma_t, 2)-1.0/pow(SP.gamma0, 2); //-------Init Lattice------- BeamLine lattice; double tunex, tuney; SectorMap CF(CF_advance_h/NCF, CF_advance_v/NCF, CF_R, CF_length/NCF, SP.gamma0); BeamLine CF_cell; if(madx_input_file == 1){ // read madx sectormap and twiss files cout << "madx sectormap" << endl; string data_dir_in = input; lattice.init(data_dir_in+"/mad/", circum, tunex, tuney); } else{ // init constant focusing (CF) sectormap and cell: cout << "constsnt focusing" << endl; for(int j=0; j<NCF; j++) CF_cell.add_map(CF); lattice.init(CF_cell); } // Other variables: double dx = 2.0*piperadius/(NX-1.0); // needed for Poisson solver and grids double dy = 2.0*piperadius/(NY-1.0); // needed for Poisson solver and grids double dz = circum/NZ; double ds = 0.4; // value needed here only for setting dxs, dys. double dxs = 4.0*(dx/ds)/(NX-1.0); // only for plotting xs, not for tracking double dys = 4.0*(dx/ds)/(NX-1.0); // only for plotting ys, not for tracking double charge = current*circum/(NPIC*SP.beta0*clight*qe); // macro-particle charge Q/e double zm = 0.5*circum*bunchfactor; // (initial) bunch length if(init_pic_z == 1 || init_pic_z == 3 || init_pic_z == 4 || init_pic_z == 6) zm = 1.5*0.5*circum*bunchfactor; // for parabolic bunch double zm1 = -zm*1.0; // left bunch boundary double zm2 = zm*1.0; // right bunch boundary if(init_pic_z==7) zm=0.25; double rmsToFull; // ratio of rms to full emittance for Bump; SP // open output file patric.dat: string data_dir = ausgabe; data_dir = data_dir + "/"; string outfile = data_dir + "patric.dat"; FILE *out = fopen(outfile.c_str(), "w"); // init random number generator: long d = -11*(myid+1); // was -1021 transverse distribution: each slice needs a different initialization ! long dl = -103; // was -103 longitudinal plane: same random set needed long dran = -101; // for BTF noise excitation: same random sets needed // set some global lattice parameters double cell_length = lattice.get_L(); int Nelements = lattice.get_size(); if(myid == 0){ cout << "Nelements:" << Nelements << endl; cout << "Cell length:" << cell_length << endl; } // define pointers to first/last element in beam line: const list<SectorMap>::iterator first_elem = lattice.get_first_element(); const list<SectorMap>::iterator last_elem = --lattice.get_end_element(); TwissP twiss0, twiss_TK; lattice.first_element(); twiss0 = last_elem->get_twiss(); twiss_TK = first_elem->get_twiss(); double Ds0 = 0.0; // Dispersion derivative if(madx_input_file == 0){ // machine tunes from lattice lattice.phase_advance(tunex, tuney); tunex = circum/cell_length*tunex/(2.0*PI); tuney = circum/cell_length*tuney/(2.0*PI); bumpI=0; if(myid == 0){ cout << "advancex: " << tunex*180.0/PI << endl; cout << "tunex0: " << tunex << endl; cout << "tuney0: " << tuney << endl; } } // Chromatic correction kick: Chrom Chrom0; // Octupole: Octupole Oct0(koct); // Amplitude detuning; works only for constant focusing; SA //if(madx_input_file == 0) //AmplitudeDetuning Amp0(tunex, tuney, dqx_detune/(1.0e-6*eps_x), dqy_detune/(1.0e-6*eps_y), circum/(2.0*PI), CF); //--------end lattice---------- // set matched RF voltage: int linrf = 0; if (cavity == 3) linrf = 1; double Ym = circum/(2.0*PI)*(1.0-cos(2.0*PI*zm/circum)); if (linrf == 1) Ym = circum/(2.0*PI)*0.5*pow(2.0*PI*zm/circum, 2); double velm = abs(SP.eta0)*SP.beta0*clight*sqrt(5.0)*momentum_spread*2.0*PI/(circum); double fsyn = 1.0/(2.0*PI)*velm*sqrt(circum/(2.0*PI))/sqrt(2.0*Ym); double V0rf = pow(2.0*PI*fsyn, 2)*pow(circum, 2)/(2.0*PI)*mp*SP.A*SP.gamma0/(qe*SP.Z*abs(SP.eta0)); // Init particle distribution: Pic Pics(&SP, charge, NPIC/numprocs, data_dir + "pics_" + myid_str + ".dat"); Pics.z1 = zm1+myid*(zm2-zm1)/numprocs; // left boundary in z for this slice Pics.z2 = Pics.z1+(zm2-zm1)/numprocs; // right boundary double slice_length = Pics.z2-Pics.z1; // slice length Pic NewPics(&SP, charge, NPIC/numprocs); NewPics.z1 = Pics.z1; NewPics.z2 = Pics.z2; // Init 1D longitudinal grids Grid1D rho_z_tmp(NZ, dz, -0.5*circum); Grid1D rho_z(NZ, dz, -0.5*circum, data_dir + "rho_z.dat"); Grid1D dipole_current_x_tmp(NZ, dz, -0.5*circum); Grid1D dipole_current_x(NZ, dz, -0.5*circum, data_dir + "dipole_x.dat"); Grid1D dipole_current_xs_tmp(NZ, dz, -0.5*circum); Grid1D dipole_current_xs(NZ, dz, -0.5*circum); Grid1D dipole_kick_x(NZ, dz, -0.5*circum, data_dir + "dipole_kick_x.dat"); Grid1D dipole_current_y_tmp(NZ, dz, -0.5*circum); Grid1D dipole_current_y(NZ, dz, -0.5*circum, data_dir + "dipole_y.dat"); // Init 2D transverse grids: Grid2D rho_xy(NX, NY, dx, dy, data_dir + "rho_xy.dat"); Grid2D rho_xy_tmp(NX, NY, dx, dy); Grid2D xxs(NX, NX, dx, dxs, data_dir + "xxs.dat"); Grid2D xxs_tmp(NX, NX, dx, dxs); Grid2D yys(NY, NY, dy, dys, data_dir + "yys.dat"); Grid2D yys_tmp(NY, NY, dy, dys); Grid2D xsys(NX, NY, dxs, dys, data_dir + "xsys.dat"); Grid2D xsys_tmp(NX, NY, dxs, dys); Grid2D zx(NZ, NX, dz, dx, data_dir + "zx.dat"); Grid2D zx_tmp(NZ, NX, dz, dx); Grid2D Ex(NX, NY, dx, dy, data_dir + "Ex.dat"); Grid2D Ey(NX, NY, dx, dy, data_dir + "Ey.dat"); // Init 3D sliced grids (for 3D space charge calculation) if( fmod((float)NZ_bunch, (float)numprocs) != 0.0 ){ cout << "NZ_bunch kein Vielfaches von numprocs" << endl; MPI_Abort(MPI_COMM_WORLD, 0); } Grid3D rho_xyz(NZ_bunch/numprocs, Pics.z1, Pics.z2, rho_xy); Grid3D Ey3(NZ_bunch/numprocs, Pics.z1, Pics.z2, rho_xy); Grid3D Ex3(NZ_bunch/numprocs, Pics.z1, Pics.z2, rho_xy); // Init 2D Greens function for poisson solver Greenfb gf1(rho_xy, image_x, image_y); // open boundary condition // for the beam radius cacluation; factor for rms equivalent switch(init_pic_xy){ case 0: // Waterbag rmsToFull = 6; break; case 1: // KV rmsToFull = 4; break; case 2: // Semi-Gauss rmsToFull = 4; // approximate break; case 3: // Gauss rmsToFull = 4; // approximate break; default: printf("Invalid option for transverse particle distribution. Aborting.\n"); MPI_Abort(MPI_COMM_WORLD, 0); } // injection bump initialize Bump lob(tunex); double a; // beam radius horizontal switch(bumpI){ case 0: cout << "no mti" << endl; max_inj = 1; amp0=0; break; case 1: // The bump height is defined by user given offcenter parameter. The injection angle is equal to the septum tilt angle (as done in SIS18). cout << "mti version SP" << endl; a = sqrt(twiss_TK.betx*eps_x*rmsToFull)*0.001+twiss_TK.Dx*momentum_spread; // half width of injected beam [m] with WB distribution, change to Main, SA offcenter_x=x_septum + d_septum + a; amp0=offcenter_x; amp=amp0; ampp0=inj_angle; delAmp=(amp0-2*a)/double(max_inj); //0.0041*3;// lob.BumpSp(&lattice,max_inj, myid, amp0, ampp0, delAmp); // local orbit bump for beam injection; SP break; case 2: amp=amp0; cout << "mti flexibility version" << endl; lob.BumpModi(&lattice,amp); break; case 3: amp=amp0; cout << "mti flexibility version exponential decrease" << "tau" << tau << endl; lob.BumpModi(&lattice,amp); break; case 4: amp=amp0; cout << "mti flexibility version sin decrease" << "tau" << tau << endl; lob.BumpModi(&lattice,amp); break; default: printf("Invalid option for bump injection. Aborting.\n"); MPI_Abort(MPI_COMM_WORLD, 0); } //if(myid == 0) //cout << "Expected single beamlett tune shifts: dQ_x=" //<< rp*SP.Z*current*circum / (rmsToFull*PI*clight*qe*SP.A*pow(SP.beta0*SP.gamma0, 3)*(eps_x+sqrt(eps_x*eps_y*tunex/tuney)))*1e6 //<< ", dQ_y=" //<< rp*SP.Z*current*circum / (rmsToFull*PI*clight*qe*SP.A*pow(SP.beta0*SP.gamma0, 3)*(eps_y+sqrt(eps_x*eps_y*tuney/tunex)))*1e6 //<< endl; // print IDL parameter file idl.dat: if(myid == 0){ //cout << "Vrf [kV]: " << V0rf*1.0e-3 << " fsyn [kHz]: " << fsyn*1.0e-3 << endl; print_IDL(data_dir, numprocs, cell_length, Nelements, tunex, tuney, lattice, cells, max_inj); } //----------------counters and other variables-------------------------- int Nexchange = 1; // exchange of particles between slices after every sector map. int Nprint = print_cell*Nelements; // output of particles every cell*print_cell //int Nibs = 1; // correct for IBS every Nibs steps double Ntot; // total number of particles: for screen output int counter = 0; // counts sector maps double s = 0.0; // path length double Nslice; // total number of slices double emitx; // emittance: for screen output double dtheta = 0.0; // btf dipole kick double pickup_h, pickup_v; // horizontal/vertical pickup signals double rms_advancex = 0.0, rms_advancey = 0.0; // rms phase advance: for output int inj_counter = 0; // number of injected beamletts; SP long N_inj = 0; // number of injected particles //---------parameters for exchange of particles between slices------- int destl; //!< ID of left neighbour slice (-1: no neighbour). int destr; //!< ID of right neighbour //---finite bunch: no exchange between ends--- if(bc_end == 0){ if(myid == 0){ destl =-1; destr = myid+1; }else if(myid == numprocs-1){ destl = myid-1; destr =-1; }else{ destl = myid-1; destr = myid+1; } } //---periodic (in z) boundary condition--- if(bc_end == 1){ if(myid == 0){ destl = numprocs-1; destr = myid+1; }else if(myid == numprocs-1){ destl = myid-1; destr = 0; } else{ destl = myid-1; destr = myid+1; } } //--------------------- end-parameters for particle exchange --------------- long *septLoss = new long; long *sl_slice = new long; double *momenta = new double[19]; double *momenta_tot = new double[19]; double tmp=0; long size_old; offcenter_y=0.0; inj_phase_y=0.0e-3; //-------------------------------------------------------------------------- //----------------------- start loop (do...while) -------------------------- //-------------------------------------------------------------------------- double z0; do{ // injection; SP if(!(counter%Nelements)) { // at beginning each turn... if(inj_counter < max_inj) { size_old=Pics.get_size(); // set longitudinal distribution: switch(init_pic_z){ case 0: // coasting + Elliptic Pics.parabolic_dc(bunchfactor, circum, momentum_spread, NPIC, &dl); break; case 1: // bunch + Elliptic (1.5 correction factor for bunching) Pics.parabolic(zm, 0, momentum_spread, NPIC, &dl); break; case 2: // coasting + Gauss Pics.coast_gauss(bunchfactor, circum, momentum_spread, NPIC, &dl); break; case 3: // bunch + Gauss Pics.bunch_gauss(zm, circum, momentum_spread, NPIC, &dl); break; case 4: // const. bunch dist. Pics.bunch_const(zm, circum, momentum_spread, NPIC, &dl,linrf); break; case 5: // air bag dist. Pics.barrier_air_bag(zm, momentum_spread, NPIC, &dl); break; case 6: // bunch air bag dist. Pics.bunch_air_bag(zm, circum, momentum_spread, NPIC, &dl); break; case 7: // 168 mirco bunches, injection z0=-circum/2.; int l; for (l=0; l<168; l++){ Pics.parabolic(zm, z0, momentum_spread, NPIC/168, &dl); z0+=1.286; } break; default: printf("Invalid option for longitudinal particle distribution. Aborting.\n"); MPI_Abort(MPI_COMM_WORLD, 0); } // set transverse distribution: switch(init_pic_xy){ case 0: // Waterbag rmsToFull = 6; Pics.waterbag_xy(1.e-6*eps_x, 1.0e-6*eps_y, twiss_TK.alpx, twiss_TK.alpy, pow(mismatch_x, 2)*twiss_TK.betx, pow(mismatch_y, 2)*twiss_TK.bety, twiss_TK.Dx, Ds0, offcenter_x, inj_angle, offcenter_y, inj_phase_y, size_old, &d); break; case 1: // KV rmsToFull = 4; Pics.KV_xy(1.e-6*eps_x, 1.0e-6*eps_y, twiss_TK.alpx, twiss_TK.alpy, pow(mismatch_x, 2)*twiss_TK.betx, pow(mismatch_y, 2)*twiss_TK.bety, twiss_TK.Dx, Ds0, offcenter_x, inj_angle, offcenter_y, inj_phase_y, size_old, &d); break; case 2: // Semi-Gauss rmsToFull = 4; // approximate Pics.SG(1.e-6*eps_x, 1.0e-6*eps_y, twiss_TK.alpx, twiss_TK.alpy, pow(mismatch_x, 2)*twiss_TK.betx, pow(mismatch_y, 2)*twiss_TK.bety, twiss_TK.Dx, Ds0, offcenter_x, inj_angle, offcenter_y, inj_phase_y, size_old, &d); break; case 3: // Gauss rmsToFull = 4; // approximate Pics.Gauss_xy(1.e-6*eps_x, 1.0e-6*eps_y, twiss_TK.alpx, twiss_TK.alpy, pow(mismatch_x, 2)*twiss_TK.betx, pow(mismatch_y, 2)*twiss_TK.bety, twiss_TK.Dx, Ds0, offcenter_x, inj_angle, offcenter_y, inj_phase_y, size_old, &d); break; default: printf("Invalid option for transverse particle distribution. Aborting.\n"); MPI_Abort(MPI_COMM_WORLD, 0); } if (bumpI!=0) { *sl_slice = NewPics.localLoss_x(x_septum, 100.); // loss on septum loss+=*sl_slice; MPI_Reduce(sl_slice, septLoss, 1, MPI_LONG, MPI_SUM, 0, MPI_COMM_WORLD); if(myid == 0) cout<<"The incoming beamlett number "<<inj_counter+1<< " lost "<<loss<< " macro particles on the septum.\n"; } N_inj += NPIC; inj_counter +=1; } // bump reduction if (amp > 0.001 ) { if(bumpI==1) { amp-=delAmp; ampp0-=delAmp*ampp0/amp0; lob.decrement(); } if (bumpI==2) { amp-=delAmp; lob.decrementModi(amp); } if (bumpI==3) { amp=amp0*exp(-tau*counter/Nelements); lob.decrementModi(amp); } if (bumpI==4) { amp=amp0*(1+sin(-tau*counter/Nelements)); lob.decrementModi(amp); } } } //------------ Start Output---------------------------------------- // store rms momenta every time step in patric.dat: if(counter%1 == 0){ Nslice = Pics.get_size(); // number of particles in this slice momenta[0] = Nslice*Pics.rms_emittance_x(); momenta[1] = Nslice*Pics.rms_emittance_y(); momenta[2] = Nslice*Pics.x_max(); momenta[3] = Nslice*Pics.y_max(); momenta[4] = Nslice*Pics.x_rms(); momenta[5] = Nslice*Pics.y_rms(); momenta[6] = Nslice*Pics.rms_momentum_spread(); momenta[7] = Nslice*Pics.xzn(2.0, zm); momenta[8] = Nslice*Pics.xzn(1.0, zm); momenta[9] = Nslice; momenta[10] = Nslice*rms_advancex; // rms phase advance in x momenta[11] = Nslice*rms_advancey; momenta[12] = Nslice*Pics.offset_x(); momenta[13] = Nslice*Pics.offset_y(); momenta[14] = Nslice*dtheta; // btf noise signal momenta[15] = Nslice*pickup_h; momenta[16] = Nslice*pickup_v; momenta[17] = Nslice*loss; momenta[18] = Nslice*N_inj; // mpi_reduce for summation of all 17 moments over all slices MPI_Reduce(momenta, momenta_tot, 19, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); Ntot = momenta_tot[9]; // total number of particles over all slices emitx = momenta_tot[0]/Ntot; // total rms emittance // stop when loss tolerance level is exceeded (1-Ntot/(max_inj*NPIC))*100. if(myid == 0 && Ntot/N_inj <= lossTol){ // test on numer of injected particles; SP cout<<"Loss tolerance exceeded within "<<counter/Nelements+1<<" turns ("<< Ntot<<" of "<<N_inj<<" macro particles left). Exiting.\n"; cout.flush(); MPI_Abort(MPI_COMM_WORLD, 0); } // cout<<counter<<' '<<lattice.get_element()->get_name()<<' '<<lattice.get_element()->get_K(1)<<endl; //tmp // write momenta if(myid == 0){ fprintf(out, "%g", s); for(int i=0; i<19; i++) if(i != 9){ fprintf(out, "%15g", momenta_tot[i]/Ntot);} else{ fprintf(out, "%15g", momenta_tot[i]);} fprintf(out, "\n"); fflush(out); } } //------output every Nprint*sectormap--------- if(counter%Nprint == 0){ if(myid == 0){ // to screen //printf("saving at s=%g (m) eps_t=%g dp/p=%g zm2=%g Ntotal=%g\n", s, 1.0e6*emitx, Pics.rms_momentum_spread(), zm2, Ntot); cout.flush(); // electric fields Ex.print(); Ey.print(); } // paricle coordinates to pic.dat: Pics.print(pic_subset); // collect densities for output only: Pics.gatherZ(charge*qe/dz, rho_z_tmp); Pics.gatherX(SP.beta0*clight*charge*qe/dz, dipole_current_x_tmp); Pics.gatherY(SP.beta0*clight*charge*qe/dz, dipole_current_y_tmp); Pics.gatherXY(charge*qe/circum, rho_xy_tmp); Pics.gatherXXs(charge*qe/circum, xxs_tmp); Pics.gatherYYs(charge*qe/circum, yys_tmp); Pics.gatherXsYs(charge*qe/circum, xsys_tmp); Pics.gatherZX(charge*qe/circum, zx_tmp); // summation over all slices: MPI_Allreduce(rho_z_tmp.get_grid(), rho_z.get_grid(), NZ, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(dipole_current_x_tmp.get_grid(), dipole_current_x.get_grid(), NZ, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(dipole_current_y_tmp.get_grid(), dipole_current_y.get_grid(), NZ, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(rho_xy_tmp.get_grid(), rho_xy.get_grid(), NX*NY, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(xxs_tmp.get_grid(), xxs.get_grid(), NX*NX, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(yys_tmp.get_grid(), yys.get_grid(), NY*NY, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(xsys_tmp.get_grid(), xsys.get_grid(), NX*NY, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(zx_tmp.get_grid(), zx.get_grid(), NZ*NX, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); // output to density files: if(myid == 0){ dipole_current_x.print(); dipole_kick_x.print(); dipole_current_y.print(); rho_z.print(); rho_xy.print(); xxs.print(); yys.print(); xsys.print(); zx.print(); } } //-----------------end output-------------------------------------------- // at beginning of a cell: calculate advance per (last) cell, // store old coordinates if(lattice.get_element() == first_elem){ rms_advancex = Pics.rms_phaseadvance_h(); // Pics.rms_wavelength_h(); rms_advancey = Pics.rms_phaseadvance_v(); // Pics.rms_wavelength_v(); if(footprint == 0) Pics.store_old_coordinates(); } if(lattice.get_element()->get_name() == "\"SEPTUM\""){ // losses at septum; SP loss += Pics.localLoss_x(-piperadius, coll_halfgap); } if(lattice.get_element()->get_name() == "\"ACCEPTANCE\""){ // losses at limiting acceptance; SA double tmp = lattice.get_element()->get_betx(); Pics.localLoss_x(-sqrt(180e-6*tmp), sqrt(180e-6*tmp)); } // Transport particles through sectormap, update slice position s: ds = lattice.get_element()->get_L(); s += ds; Pics.transport(lattice.get_element()->get_map(), piperadius); //-----exchange particles between slices------------------------ if(counter != 0 && counter%Nexchange == 0 && numprocs > 1){ int Npl; //!< Number of particles to be exchanged with left neighbour int Npr; //!< particles exchanged with right neighbour //! vector of particles to be exchanged vector<Particle> pl, pr; // send particle to neighbor slices: if(destl >= 0){ pl = Pics.get_particles_left(circum); Npl = pl.size(); MPI_Send(&Npl, 1, MPI_INT, destl, 1, MPI_COMM_WORLD); MPI_Send(&pl[0], Npl, particletype, destl, 1, MPI_COMM_WORLD); } if(destr >= 0){ pr = Pics.get_particles_right(circum); Npr = pr.size(); MPI_Send(&Npr, 1, MPI_INT, destr, 0, MPI_COMM_WORLD); MPI_Send(&pr[0], Npr, particletype, destr, 0, MPI_COMM_WORLD); } // receive from neighbour slices: Npl = 0; Npr = 0; vector<Particle> pl_in, pr_in; if( destl >= 0 ){ MPI_Recv(&Npl, 1, MPI_INT, destl, 0, MPI_COMM_WORLD, &status); pl_in = vector<Particle>(Npl); MPI_Recv(&pl_in[0], Npl, particletype, destl, 0, MPI_COMM_WORLD, &status); } if(destr >= 0){ MPI_Recv(&Npr, 1, MPI_INT, destr, 1, MPI_COMM_WORLD, &status); pr_in = vector<Particle>(Npr); MPI_Recv(&pr_in[0], Npr, particletype, destr, 1, MPI_COMM_WORLD, &status); } Pics.add_particles(pl_in); Pics.add_particles(pr_in); } //-----end exchange of particles------------- // periodic bc without exchange if(numprocs == 1) Pics.periodic_bc(circum); // update wave lengths //if( footprint == 1){ //Pics.update_wavelength_h(ds, 0.0); //Pics.update_wavelength_v(ds);} // nonlinear thin lens kick: if(octupole_kick == 1) Pics.kick(Oct0, lattice.get_element()->get_twiss(), ds); //if(ampdetun_kick == 1) // works only for constant focusing //Pics.kick(Amp0, lattice.get_element()->get_twiss()ds); // correct for chromaticity if(chroma == 1) Pics.kick(Chrom0,lattice.get_element()->get_twiss(), ds); // cavity kick every cell: if(cavity == 1 && counter%Nelements == 0.0) Pics.cavity_kick(V0rf*cell_length/circum, 1, circum/(2.0*PI)); if(cavity == 2 && counter%Nelements == 0.0) Pics.barrier_kick(zm1, zm2); if(cavity == 3 && counter%Nelements == 0.0) Pics.cavity_kick_linear(V0rf*cell_length/circum, 1, circum/(2.0*PI)); // Pickup signals Pics.gatherX(SP.beta0*clight*charge*qe/dz, dipole_current_x_tmp); Pics.gatherY(SP.beta0*clight*charge*qe/dz, dipole_current_y_tmp); MPI_Allreduce(dipole_current_x_tmp.get_grid(), dipole_current_x.get_grid(), NZ, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(dipole_current_y_tmp.get_grid(), dipole_current_y.get_grid(), NZ, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); pickup_h = Pics.pickup_signal(dipole_current_x, circum, s/(SP.beta0*clight))/current; pickup_v = Pics.pickup_signal(dipole_current_y, circum, s/(SP.beta0*clight))/current; //---------------impedance kicks----------------------- komplex dqc_t(dqcr, dqci); // for sliced == 0 if(imp_kick == 1){ if(sliced == 0) Pics.kick(ds/circum*InducedKick(Pics.offset_x(), ds, dqc_t, SP.beta0, tunex, circum), 0.0); else{ dipole_kick_x.reset(); if(Rs > 0.0 || leit > 0.0){ Pics.gatherXs(SP.beta0*clight*charge*qe/dz, dipole_current_xs_tmp); MPI_Allreduce(dipole_current_xs_tmp.get_grid(), dipole_current_xs.get_grid(), NZ, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); InducedWakeKick(dipole_kick_x, dipole_current_x, dipole_current_xs, tunex, 2.0*PI*SP.beta0*clight/circum, nres, Rs, Qs, piperadius, leit, SP.beta0, SP.gamma0*mp*SP.A*pow(clight, 2), SP.Z*qe); } if(Zimage != 0.0) InducedKick(dipole_kick_x, dipole_current_x, Zimage, SP.beta0, SP.gamma0*mp*SP.A*pow(clight, 2), SP.Z*qe); Pics.impedance_kick(dipole_kick_x, circum, ds); } } //---------------end impedance kicks----------------------- //------------self-consistent space charge kicks after every sectormap---- if(space_charge == 1){ // PIC -> charge density for Poisson solver: if (sliced == 0){ Pics.gatherXY(charge*qe/circum, rho_xy_tmp); MPI_Allreduce(rho_xy_tmp.get_grid(), rho_xy.get_grid(), NX*NY, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); }else{ Pics.gatherXYZ(charge*qe/rho_xyz.get_dz(), rho_xyz); // send and receive density ghost grids to neighbor slices: // what is exchanged here ??? if(destl >= 0) MPI_Send(rho_xyz.get_ghostl(), NX*NY, MPI_DOUBLE, destl, 2, MPI_COMM_WORLD); if(destr >= 0){ MPI_Recv(rho_xy_tmp.get_grid(), NX*NY, MPI_DOUBLE, destr, 2, MPI_COMM_WORLD, &status); rho_xyz[NZ_bunch/numprocs-1] += rho_xy_tmp; } if(destr >= 0) MPI_Send(rho_xyz.get_ghostr(), NX*NY, MPI_DOUBLE, destr, 3, MPI_COMM_WORLD); if(destl >= 0){ MPI_Recv(rho_xy_tmp.get_grid(), NX*NY, MPI_DOUBLE, destl, 3, MPI_COMM_WORLD, &status); rho_xyz[0]+= rho_xy_tmp; } } // Poisson solver if(sliced == 0) poisson_xy(Ex, Ey, rho_xy, gf1); else{ poisson_xyz(Ex3, Ey3, rho_xyz, gf1); // send and receive efield ghost grids to neighbor slices: if(destl >= 0){ MPI_Send(Ex3.get_ghostl(), NX*NY, MPI_DOUBLE, destl, 2, MPI_COMM_WORLD); MPI_Send(Ey3.get_ghostl(), NX*NY, MPI_DOUBLE, destl, 4, MPI_COMM_WORLD); } if(destr >= 0){ MPI_Recv(Ex3[NZ_bunch/numprocs-1].get_grid(), NX*NY, MPI_DOUBLE, destr, 2, MPI_COMM_WORLD, &status); MPI_Recv(Ey3[NZ_bunch/numprocs-1].get_grid(), NX*NY, MPI_DOUBLE, destr, 4, MPI_COMM_WORLD, &status); } if(destr >= 0){ MPI_Send(Ex3.get_ghostr(), NX*NY, MPI_DOUBLE, destr, 3, MPI_COMM_WORLD); MPI_Send(Ey3.get_ghostr(), NX*NY, MPI_DOUBLE, destr, 5, MPI_COMM_WORLD); } if(destl >= 0){ MPI_Recv(Ex3[0].get_grid(), NX*NY, MPI_DOUBLE, destl, 3, MPI_COMM_WORLD, &status); MPI_Recv(Ey3[0].get_grid(), NX*NY, MPI_DOUBLE, destl, 5, MPI_COMM_WORLD, &status); } } } // Shift xs and ys: if(space_charge == 1 && ds > 0.0){ if(sliced == 0) Pics.kick(Ex, Ey, ds); else Pics.kick(Ex3, Ey3, ds); } //---------------end self-consistent space charge kicks--------------- // linear sc kicks: if(space_charge == 2 && ds > 0.0) Pics.linear_SC_kick(dQxm, dQym, tunex, tuney, rho_z, current/(SP.beta0*clight), dipole_current_x, dipole_current_y, circum, ds); // nonlinear sc kicks: if(space_charge == 3 && ds > 0.0) Pics.nonlinear_SC_kick(sqrt(1.0e-6*twiss0.betx*eps_x), sqrt(1.0e-6*twiss0.bety*eps_y), dQxm, dQym, tunex, tuney, rho_z, current/(SP.beta0*clight), circum, ds); // dipole noise modulation kick: double dnoiseamp = 1.0e-6; double nus = fsyn/(SP.beta0*clight/circum); if(btf == 1) dtheta = Pics.dipole_mod_kick(s/(SP.beta0*clight), ds, circum, dnoiseamp, (tunex+nus)*SP.beta0*clight/circum, btf_harmonic); // correct for ibs: /*if(counter != 0 && counter%Nibs == 0){ double rate_ibs = 1.0e4; double Dz = rate_ibs*pow(Pics.rms_momentum_spread(), 2); double Dxy = rate_ibs*0.5*(Pics.rms_emittance_x()+Pics.rms_emittance_y()); double betx = lattice.get_element()->get_betx(); double bety = lattice.get_element()->get_bety(); Pics.langevin(rate_ibs, rate_ibs*0.0, Dxy, Dz*0.0, Nibs*ds, betx, bety, &d); }*/ // For bunch compression: Update slice boundaries z1 and z2 from // new bunch boundaries zm1, zm2: /*if(counter != 0 && counter%Nexchange == 0){ if(myid == 0) zm1 = Pics.z_min(); MPI_Bcast(&zm1, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); if(myid == numprocs-1) zm2 = Pics.z_max(); MPI_Bcast(&zm2, 1, MPI_DOUBLE, numprocs-1, MPI_COMM_WORLD); Pics.z1 = zm1+myid*(zm2-zm1)/numprocs; Pics.z2 = Pics.z1+(zm2-zm1)/numprocs; slice_length = Pics.z2-Pics.z1; rho_xyz.get_zleft() = zm1; rho_xyz.get_zright() = zm2; Ex3.get_zleft() = zm1; Ex3.get_zright() = zm2; Ey3.get_zleft() = zm1; Ey3.get_zright() = zm2; }*/ // advance in beam line, go to next element: lattice.next_element(); ++counter; }while(counter != cells*Nelements); //loop check, cells (turns) given by user SA //------------------end of loop------------------------------- // close files, free heap: delete septLoss, sl_slice; delete[] momenta, momenta_tot; // [] needed here!; SP fclose(out); // MPI end: MPI_Finalize(); time2 = time(0); double sec = difftime(time2, time1); double h = floor(sec/3600); double min = floor(sec/60-60.*h); sec -= 3600.*h+60.*min; if(myid == 0) {cout << "Total losses: " << (1-Ntot/(max_inj*NPIC))*100. << " \%\n" << "Stored particles: " << current*circum*Ntot/(qe*Z*SP.beta0*clight*NPIC) << endl << "Computation time: " << h << ":" << min << ":" << sec << endl; } }