// --------------------------------------------------------------------------------------------------------------------- //! Project global current charge // --------------------------------------------------------------------------------------------------------------------- void Projector1D1Order::operator() (Field* rho, Particles &particles, int ipart) { Field1D* rho1D = static_cast<Field1D*>(rho); //Declaration of local variables int i; double xjn,xjmxi; double rho_j = particles.charge(ipart)*particles.weight(ipart); // charge density of the macro-particle //Locate particle on the grid xjn = particles.position(0, ipart) * dx_inv_; // normalized distance to the first node i = floor(xjn); // index of the central node xjmxi = xjn - (double)i; // normalized distance to the nearest grid point //cout << "Pos = " << particles.position(0, ipart) << " - i global = " << i << " - i local = " << i-index_domain_begin <<endl; i -= index_domain_begin; // 1nd order projection for the total density //#pragma omp atomic (*rho1D)( i ) += (1.0 - xjmxi) * rho_j ; //#pragma omp atomic (*rho1D)( i+1) += xjmxi * rho_j; } // END Project global current charge
/*********************************************************************** Interpolate the field fx defined on the primal grid with size nstp_x and space step stp_x_inv at the position xj and return the value fxj ***********************************************************************/ void Interpolator1D3Order::fields( ElectroMagn *EMfields, Particles &particles, int ipart, int nparts, double *ELoc, double *BLoc ) { //!\todo Julien, can you check that this is indeed the centered B-field which is passed to the pusher? Field1D *Ex1D = static_cast<Field1D *>( EMfields->Ex_ ); Field1D *Ey1D = static_cast<Field1D *>( EMfields->Ey_ ); Field1D *Ez1D = static_cast<Field1D *>( EMfields->Ez_ ); Field1D *Bx1D_m = static_cast<Field1D *>( EMfields->Bx_m ); Field1D *By1D_m = static_cast<Field1D *>( EMfields->By_m ); Field1D *Bz1D_m = static_cast<Field1D *>( EMfields->Bz_m ); // Calculate the normalized positions double xjn = particles.position( 0, ipart )*dx_inv_; // Calculate coeffs coeffs( xjn ); // Interpolate the fields from the Dual grid : Ex, By, Bz *( ELoc+0*nparts ) = compute( coeffd_, Ex1D, id_ ); *( BLoc+1*nparts ) = compute( coeffd_, By1D_m, id_ ); *( BLoc+2*nparts ) = compute( coeffd_, Bz1D_m, id_ ); // Interpolate the fields from the Primal grid : Ey, Ez, Bx *( ELoc+1*nparts ) = compute( coeffp_, Ey1D, ip_ ); *( ELoc+2*nparts ) = compute( coeffp_, Ez1D, ip_ ); *( BLoc+0*nparts ) = compute( coeffp_, Bx1D_m, ip_ ); }//END Interpolator1D3Order
// Interpolator on another field than the basic ones void Interpolator1D3Order::oneField( Field *field, Particles &particles, int *istart, int *iend, double *FieldLoc ) { Field1D *F = static_cast<Field1D *>( field ); double *coeff = field->isDual( 0 ) ? coeffd_ : coeffp_; int *i = field->isDual( 0 ) ? &id_ : &ip_; for( int ipart=*istart ; ipart<*iend; ipart++ ) { double xjn = particles.position( 0, ipart )*dx_inv_; coeffs( xjn ); FieldLoc[ipart] = compute( coeff, F, *i ); } }
void PusherBoris::operator() (Particles &particles, SmileiMPI* smpi, int istart, int iend, int ithread) { std::vector<LocalFields> *Epart = &(smpi->dynamics_Epart[ithread]); std::vector<LocalFields> *Bpart = &(smpi->dynamics_Bpart[ithread]); std::vector<double> *gf = &(smpi->dynamics_gf[ithread]); double charge_over_mass_ ; double umx, umy, umz, upx, upy, upz; double alpha, inv_det_T, Tx, Ty, Tz, Tx2, Ty2, Tz2; double TxTy, TyTz, TzTx; double pxsm, pysm, pzsm; for (int ipart=istart ; ipart<iend; ipart++ ) { charge_over_mass_ = static_cast<double>(particles.charge(ipart))*one_over_mass_; //(*this)(particles, ipart, (*Epart)[ipart], (*Bpart)[ipart] , (*gf)[ipart]); umx = particles.momentum(0, ipart) + charge_over_mass_*(*Epart)[ipart].x*dts2; umy = particles.momentum(1, ipart) + charge_over_mass_*(*Epart)[ipart].y*dts2; umz = particles.momentum(2, ipart) + charge_over_mass_*(*Epart)[ipart].z*dts2; (*gf)[ipart] = sqrt( 1.0 + umx*umx + umy*umy + umz*umz ); // Rotation in the magnetic field alpha = charge_over_mass_*dts2/(*gf)[ipart]; Tx = alpha * (*Bpart)[ipart].x; Ty = alpha * (*Bpart)[ipart].y; Tz = alpha * (*Bpart)[ipart].z; Tx2 = Tx*Tx; Ty2 = Ty*Ty; Tz2 = Tz*Tz; TxTy = Tx*Ty; TyTz = Ty*Tz; TzTx = Tz*Tx; inv_det_T = 1.0/(1.0+Tx2+Ty2+Tz2); upx = ( (1.0+Tx2-Ty2-Tz2)* umx + 2.0*(TxTy+Tz)* umy + 2.0*(TzTx-Ty)* umz )*inv_det_T; upy = ( 2.0*(TxTy-Tz)* umx + (1.0-Tx2+Ty2-Tz2)* umy + 2.0*(TyTz+Tx)* umz )*inv_det_T; upz = ( 2.0*(TzTx+Ty)* umx + 2.0*(TyTz-Tx)* umy + (1.0-Tx2-Ty2+Tz2)* umz )*inv_det_T; // Half-acceleration in the electric field pxsm = upx + charge_over_mass_*(*Epart)[ipart].x*dts2; pysm = upy + charge_over_mass_*(*Epart)[ipart].y*dts2; pzsm = upz + charge_over_mass_*(*Epart)[ipart].z*dts2; (*gf)[ipart] = sqrt( 1.0 + pxsm*pxsm + pysm*pysm + pzsm*pzsm ); particles.momentum(0, ipart) = pxsm; particles.momentum(1, ipart) = pysm; particles.momentum(2, ipart) = pzsm; // Move the particle for ( int i = 0 ; i<nDim_ ; i++ ) particles.position(i, ipart) += dt*particles.momentum(i, ipart)/(*gf)[ipart]; } }
void Interpolator1D3Order::fieldsAndCurrents( ElectroMagn *EMfields, Particles &particles, SmileiMPI *smpi, int *istart, int *iend, int ithread, LocalFields *JLoc, double *RhoLoc ) { int ipart = *istart; double *ELoc = &( smpi->dynamics_Epart[ithread][ipart] ); double *BLoc = &( smpi->dynamics_Bpart[ithread][ipart] ); //!\todo Julien, can you check that this is indeed the centered B-field which is passed to the pusher? Field1D *Ex1D = static_cast<Field1D *>( EMfields->Ex_ ); Field1D *Ey1D = static_cast<Field1D *>( EMfields->Ey_ ); Field1D *Ez1D = static_cast<Field1D *>( EMfields->Ez_ ); Field1D *Bx1D_m = static_cast<Field1D *>( EMfields->Bx_m ); Field1D *By1D_m = static_cast<Field1D *>( EMfields->By_m ); Field1D *Bz1D_m = static_cast<Field1D *>( EMfields->Bz_m ); Field1D *Jx1D = static_cast<Field1D *>( EMfields->Jx_ ); Field1D *Jy1D = static_cast<Field1D *>( EMfields->Jy_ ); Field1D *Jz1D = static_cast<Field1D *>( EMfields->Jz_ ); Field1D *Rho1D = static_cast<Field1D *>( EMfields->rho_ ); // Calculate the normalized positions double xjn = particles.position( 0, ipart )*dx_inv_; // Calculate coeffs coeffs( xjn ); int nparts( particles.size() ); // Interpolate the fields from the Dual grid : Ex, By, Bz *( ELoc+0*nparts ) = compute( coeffd_, Ex1D, id_ ); *( BLoc+1*nparts ) = compute( coeffd_, By1D_m, id_ ); *( BLoc+2*nparts ) = compute( coeffd_, Bz1D_m, id_ ); // Interpolate the fields from the Primal grid : Ey, Ez, Bx *( ELoc+1*nparts ) = compute( coeffp_, Ey1D, ip_ ); *( ELoc+2*nparts ) = compute( coeffp_, Ez1D, ip_ ); *( BLoc+0*nparts ) = compute( coeffp_, Bx1D_m, ip_ ); // Primal Grid : Jy, Jz, Rho JLoc->y = compute( coeffp_, Jy1D, ip_ ); JLoc->z = compute( coeffp_, Jz1D, ip_ ); ( *RhoLoc ) = compute( coeffp_, Rho1D, ip_ ); // Dual Grid : Jx JLoc->x = compute( coeffd_, Jx1D, id_ ); }
void PusherPonderomotivePositionBorisV::operator()( Particles &particles, SmileiMPI *smpi, int istart, int iend, int ithread, int ipart_ref ) { /////////// not vectorized std::vector<double> *Phi_mpart = &( smpi->dynamics_PHI_mpart[ithread] ); std::vector<double> *GradPhi_mpart = &( smpi->dynamics_GradPHI_mpart[ithread] ); double charge_sq_over_mass_dts4, charge_over_mass_sq; double gamma0, gamma0_sq, gamma_ponderomotive; double pxsm, pysm, pzsm; //int* cell_keys; double *momentum[3]; for( int i = 0 ; i<3 ; i++ ) { momentum[i] = &( particles.momentum( i, 0 ) ); } double *position[3]; for( int i = 0 ; i<nDim_ ; i++ ) { position[i] = &( particles.position( i, 0 ) ); } #ifdef __DEBUG double *position_old[3]; for( int i = 0 ; i<nDim_ ; i++ ) { position_old[i] = &( particles.position_old( i, 0 ) ); } #endif short *charge = &( particles.charge( 0 ) ); int nparts = GradPhi_mpart->size()/3; double *Phi_m = &( ( *Phi_mpart )[0*nparts] ); double *GradPhi_mx = &( ( *GradPhi_mpart )[0*nparts] ); double *GradPhi_my = &( ( *GradPhi_mpart )[1*nparts] ); double *GradPhi_mz = &( ( *GradPhi_mpart )[2*nparts] ); //particles.cell_keys.resize(nparts); //cell_keys = &( particles.cell_keys[0]); #pragma omp simd for( int ipart=istart ; ipart<iend; ipart++ ) { // begin loop on particles // ! ponderomotive force is proportional to charge squared and the field is divided by 4 instead of 2 charge_sq_over_mass_dts4 = ( double )( charge[ipart] )*( double )( charge[ipart] )*one_over_mass_*dts4; // (charge over mass)^2 charge_over_mass_sq = ( double )( charge[ipart] )*one_over_mass_*( charge[ipart] )*one_over_mass_; // compute initial ponderomotive gamma gamma0_sq = 1. + momentum[0][ipart]*momentum[0][ipart] + momentum[1][ipart]*momentum[1][ipart] + momentum[2][ipart]*momentum[2][ipart] + ( *( Phi_m+ipart-ipart_ref ) )*charge_over_mass_sq; gamma0 = sqrt( gamma0_sq ) ; // ponderomotive force for ponderomotive gamma advance (Grad Phi is interpolated in time, hence the division by 2) pxsm = charge_sq_over_mass_dts4 * ( *( GradPhi_mx+ipart-ipart_ref ) ) / gamma0_sq ; pysm = charge_sq_over_mass_dts4 * ( *( GradPhi_my+ipart-ipart_ref ) ) / gamma0_sq ; pzsm = charge_sq_over_mass_dts4 * ( *( GradPhi_mz+ipart-ipart_ref ) ) / gamma0_sq ; // update of gamma ponderomotive gamma_ponderomotive = gamma0 + ( pxsm*momentum[0][ipart]+pysm*momentum[1][ipart]+pzsm*momentum[2][ipart] ) ; // Move the particle #ifdef __DEBUG for( int i = 0 ; i<nDim_ ; i++ ) { position_old[i][ipart] = position[i][ipart]; } #endif for( int i = 0 ; i<nDim_ ; i++ ) { position[i][ipart] += dt*momentum[i][ipart]/gamma_ponderomotive; } } // end loop on particles //#pragma omp simd //for (int ipart=0 ; ipart<nparts; ipart++ ) { // // for ( int i = 0 ; i<nDim_ ; i++ ){ // cell_keys[ipart] *= nspace[i]; // cell_keys[ipart] += round( (position[i][ipart]-min_loc_vec[i]) * dx_inv_[i] ); // } // //} // end loop on particles }
// --------------------------------------------------------------------------------------------------------------------- //! Project current densities : main projector // --------------------------------------------------------------------------------------------------------------------- void Projector2D4Order::currents( double *Jx, double *Jy, double *Jz, Particles &particles, unsigned int ipart, double invgf, int *iold, double *deltaold ) { int nparts = particles.size(); // ------------------------------------- // Variable declaration & initialization // ------------------------------------- int iloc; // (x,y,z) components of the current density for the macro-particle double charge_weight = inv_cell_volume * ( double )( particles.charge( ipart ) )*particles.weight( ipart ); double crx_p = charge_weight*dx_ov_dt; double cry_p = charge_weight*dy_ov_dt; double crz_p = charge_weight*one_third*particles.momentum( 2, ipart )*invgf; // variable declaration double xpn, ypn; double delta, delta2, delta3, delta4; // arrays used for the Esirkepov projection method double Sx0[7], Sx1[7], Sy0[7], Sy1[7], DSx[7], DSy[7], tmpJx[7]; for( unsigned int i=0; i<7; i++ ) { Sx1[i] = 0.; Sy1[i] = 0.; tmpJx[i] = 0.; } Sx0[0] = 0.; Sx0[6] = 0.; Sy0[0] = 0.; Sy0[6] = 0.; // -------------------------------------------------------- // Locate particles & Calculate Esirkepov coef. S, DS and W // -------------------------------------------------------- // locate the particle on the primal grid at former time-step & calculate coeff. S0 delta = deltaold[0*nparts]; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sx0[1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sx0[2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx0[3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sx0[4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx0[5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; delta = deltaold[1*nparts]; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sy0[1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sy0[2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy0[3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sy0[4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy0[5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; // locate the particle on the primal grid at current time-step & calculate coeff. S1 xpn = particles.position( 0, ipart ) * dx_inv_; int ip = round( xpn ); int ipo = iold[0*nparts]; int ip_m_ipo = ip-ipo-i_domain_begin; delta = xpn - ( double )ip; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sx1[ip_m_ipo+1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sx1[ip_m_ipo+2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx1[ip_m_ipo+3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sx1[ip_m_ipo+4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx1[ip_m_ipo+5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; ypn = particles.position( 1, ipart ) * dy_inv_; int jp = round( ypn ); int jpo = iold[1*nparts]; int jp_m_jpo = jp-jpo-j_domain_begin; delta = ypn - ( double )jp; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sy1[jp_m_jpo+1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sy1[jp_m_jpo+2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy1[jp_m_jpo+3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sy1[jp_m_jpo+4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy1[jp_m_jpo+5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; for( unsigned int i=0; i < 7; i++ ) { DSx[i] = Sx1[i] - Sx0[i]; DSy[i] = Sy1[i] - Sy0[i]; } // calculate Esirkepov coeff. Wx, Wy, Wz when used double tmp, tmp2, tmp3, tmpY; //Do not compute useless weights. // ------------------------------------------------ // Local current created by the particle // calculate using the charge conservation equation // ------------------------------------------------ // --------------------------- // Calculate the total current // --------------------------- ipo -= 3; //This minus 3 come from the order 4 scheme, based on a 7 points stencil from -3 to +3. jpo -= 3; // i =0 { iloc = ipo*nprimy+jpo; tmp2 = 0.5*Sx1[0]; tmp3 = Sx1[0]; Jz[iloc] += crz_p * ( Sy1[0]*tmp3 ); tmp = 0; tmpY = Sx0[0] + 0.5*DSx[0]; for( unsigned int j=1 ; j<7 ; j++ ) { tmp -= cry_p * DSy[j-1] * tmpY; Jy[iloc+j+ipo] += tmp; //Because size of Jy in Y is nprimy+1. Jz[iloc+j] += crz_p * ( Sy0[j]*tmp2 + Sy1[j]*tmp3 ); } }//i for( unsigned int i=1 ; i<7 ; i++ ) { iloc = ( i+ipo )*nprimy+jpo; tmpJx[0] -= crx_p * DSx[i-1] * ( 0.5*DSy[0] ); Jx[iloc] += tmpJx[0]; tmp2 = 0.5*Sx1[i] + Sx0[i]; tmp3 = 0.5*Sx0[i] + Sx1[i]; Jz[iloc] += crz_p * ( Sy1[0]*tmp3 ); tmp = 0; tmpY = Sx0[i] + 0.5*DSx[i]; for( unsigned int j=1 ; j<7 ; j++ ) { tmpJx[j] -= crx_p * DSx[i-1] * ( Sy0[j] + 0.5*DSy[j] ); Jx[iloc+j] += tmpJx[j]; tmp -= cry_p * DSy[j-1] * tmpY; Jy[iloc+j+i+ipo] += tmp; //Because size of Jy in Y is nprimy+1. Jz[iloc+j] += crz_p * ( Sy0[j]*tmp2 + Sy1[j]*tmp3 ); } }//i }
// --------------------------------------------------------------------------------------------------------------------- //! Project charge : frozen & diagFields timstep // --------------------------------------------------------------------------------------------------------------------- void Projector2D4Order::basic( double *rhoj, Particles &particles, unsigned int ipart, unsigned int type ) { //Warning : this function is used for frozen species or initialization only and doesn't use the standard scheme. //rho type = 0 //Jx type = 1 //Jy type = 2 //Jz type = 3 int iloc; int ny( nprimy ); // (x,y,z) components of the current density for the macro-particle double charge_weight = inv_cell_volume * ( double )( particles.charge( ipart ) )*particles.weight( ipart ); if( type > 0 ) { charge_weight *= 1./sqrt( 1.0 + particles.momentum( 0, ipart )*particles.momentum( 0, ipart ) + particles.momentum( 1, ipart )*particles.momentum( 1, ipart ) + particles.momentum( 2, ipart )*particles.momentum( 2, ipart ) ); if( type == 1 ) { charge_weight *= particles.momentum( 0, ipart ); } else if( type == 2 ) { charge_weight *= particles.momentum( 1, ipart ); ny ++; } else { charge_weight *= particles.momentum( 2, ipart ); } } // variable declaration double xpn, ypn; double delta, delta2, delta3, delta4; // arrays used for the Esirkepov projection method double Sx1[7], Sy1[7]; for( unsigned int i=0; i<7; i++ ) { Sx1[i] = 0.; Sy1[i] = 0.; } // -------------------------------------------------------- // Locate particles & Calculate Esirkepov coef. S, DS and W // -------------------------------------------------------- // locate the particle on the primal grid at current time-step & calculate coeff. S1 xpn = particles.position( 0, ipart ) * dx_inv_; int ip = round( xpn + 0.5 * ( type==1 ) ); // index of the central node delta = xpn - ( double )ip; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sx1[1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sx1[2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx1[3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sx1[4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx1[5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; ypn = particles.position( 1, ipart ) * dy_inv_; int jp = round( ypn + 0.5*( type==2 ) ); delta = ypn - ( double )jp; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sy1[1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sy1[2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy1[3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sy1[4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy1[5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; // --------------------------- // Calculate the total current // --------------------------- ip -= i_domain_begin + 3; jp -= j_domain_begin + 3; for( unsigned int i=0 ; i<7 ; i++ ) { iloc = ( i+ip )*ny+jp; for( unsigned int j=0 ; j<7 ; j++ ) { rhoj[iloc+j] += charge_weight * Sx1[i]*Sy1[j]; } }//i }
// --------------------------------------------------------------------------------------------------------------------- //! Project current densities : main projector // --------------------------------------------------------------------------------------------------------------------- void Projector1D4Order::currents( double *Jx, double *Jy, double *Jz, Particles &particles, unsigned int ipart, double invgf, int *iold, double *delta ) { // Declare local variables int ipo, ip; int ip_m_ipo; double charge_weight = inv_cell_volume * ( double )( particles.charge( ipart ) )*particles.weight( ipart ); double xjn, xj_m_xipo, xj_m_xipo2, xj_m_xipo3, xj_m_xipo4, xj_m_xip, xj_m_xip2, xj_m_xip3, xj_m_xip4; double crx_p = charge_weight*dx_ov_dt; // current density for particle moving in the x-direction double cry_p = charge_weight*particles.momentum( 1, ipart )*invgf; // current density in the y-direction of the macroparticle double crz_p = charge_weight*particles.momentum( 2, ipart )*invgf; // current density allow the y-direction of the macroparticle double S0[7], S1[7], Wl[7], Wt[7], Jx_p[7]; // arrays used for the Esirkepov projection method // Initialize variables for( unsigned int i=0; i<7; i++ ) { S0[i]=0.; S1[i]=0.; Wl[i]=0.; Wt[i]=0.; Jx_p[i]=0.; }//i // Locate particle old position on the primal grid xj_m_xipo = *delta; // normalized distance to the nearest grid point xj_m_xipo2 = xj_m_xipo * xj_m_xipo; // square of the normalized distance to the nearest grid point xj_m_xipo3 = xj_m_xipo2 * xj_m_xipo; // cube of the normalized distance to the nearest grid point xj_m_xipo4 = xj_m_xipo3 * xj_m_xipo; // 4th power of the normalized distance to the nearest grid point // Locate particle new position on the primal grid xjn = particles.position( 0, ipart ) * dx_inv_; ip = round( xjn ); // index of the central node xj_m_xip = xjn - ( double )ip; // normalized distance to the nearest grid point xj_m_xip2 = xj_m_xip * xj_m_xip; // square of the normalized distance to the nearest grid point xj_m_xip3 = xj_m_xip2 * xj_m_xip; // cube of the normalized distance to the nearest grid point xj_m_xip4 = xj_m_xip3 * xj_m_xip; // 4th power of the normalized distance to the nearest grid point // coefficients 4th order interpolation on 5 nodes S0[1] = dble_1_ov_384 - dble_1_ov_48 * xj_m_xipo + dble_1_ov_16 * xj_m_xipo2 - dble_1_ov_12 * xj_m_xipo3 + dble_1_ov_24 * xj_m_xipo4; S0[2] = dble_19_ov_96 - dble_11_ov_24 * xj_m_xipo + dble_1_ov_4 * xj_m_xipo2 + dble_1_ov_6 * xj_m_xipo3 - dble_1_ov_6 * xj_m_xipo4; S0[3] = dble_115_ov_192 - dble_5_ov_8 * xj_m_xipo2 + dble_1_ov_4 * xj_m_xipo4; S0[4] = dble_19_ov_96 + dble_11_ov_24 * xj_m_xipo + dble_1_ov_4 * xj_m_xipo2 - dble_1_ov_6 * xj_m_xipo3 - dble_1_ov_6 * xj_m_xipo4; S0[5] = dble_1_ov_384 + dble_1_ov_48 * xj_m_xipo + dble_1_ov_16 * xj_m_xipo2 + dble_1_ov_12 * xj_m_xipo3 + dble_1_ov_24 * xj_m_xipo4; // coefficients 2nd order interpolation on 5 nodes ipo = *iold; // index of the central node ip_m_ipo = ip-ipo-index_domain_begin; S1[ip_m_ipo+1] = dble_1_ov_384 - dble_1_ov_48 * xj_m_xip + dble_1_ov_16 * xj_m_xip2 - dble_1_ov_12 * xj_m_xip3 + dble_1_ov_24 * xj_m_xip4; S1[ip_m_ipo+2] = dble_19_ov_96 - dble_11_ov_24 * xj_m_xip + dble_1_ov_4 * xj_m_xip2 + dble_1_ov_6 * xj_m_xip3 - dble_1_ov_6 * xj_m_xip4; S1[ip_m_ipo+3] = dble_115_ov_192 - dble_5_ov_8 * xj_m_xip2 + dble_1_ov_4 * xj_m_xip4; S1[ip_m_ipo+4] = dble_19_ov_96 + dble_11_ov_24 * xj_m_xip + dble_1_ov_4 * xj_m_xip2 - dble_1_ov_6 * xj_m_xip3 - dble_1_ov_6 * xj_m_xip4; S1[ip_m_ipo+5] = dble_1_ov_384 + dble_1_ov_48 * xj_m_xip + dble_1_ov_16 * xj_m_xip2 + dble_1_ov_12 * xj_m_xip3 + dble_1_ov_24 * xj_m_xip4; // coefficients used in the Esirkepov method for( unsigned int i=0; i<7; i++ ) { Wl[i] = S0[i] - S1[i]; // for longitudinal current (x) Wt[i] = 0.5 * ( S0[i] + S1[i] ); // for transverse currents (y,z) }//i // local current created by the particle // calculate using the charge conservation equation for( unsigned int i=1; i<7; i++ ) { Jx_p[i] = Jx_p[i-1] + crx_p * Wl[i-1]; } ipo -= 3 ; // 4th order projection for the total currents & charge density // At the 4th order, oversize = 3. for( unsigned int i=0; i<7; i++ ) { Jx[i + ipo] += Jx_p[i]; Jy[i + ipo] += cry_p * Wt[i]; Jz[i + ipo] += crz_p * Wt[i]; }//i }
// --------------------------------------------------------------------------------------------------------------------- //! Project charge : frozen & diagFields timstep // --------------------------------------------------------------------------------------------------------------------- void Projector1D4Order::basic( double *rhoj, Particles &particles, unsigned int ipart, unsigned int type ) { //Warning : this function is used for frozen species or initialization only and doesn't use the standard scheme. //rho type = 0 //Jx type = 1 //Jy type = 2 //Jz type = 3 // Declare local variables //int ipo, ip, iloc; int ip; //int ip_m_ipo; double charge_weight = inv_cell_volume * ( double )( particles.charge( ipart ) )*particles.weight( ipart ); double xjn, xj_m_xip, xj_m_xip2, xj_m_xip3, xj_m_xip4; double S1[7]; // arrays used for the Esirkepov projection method // Initialize variables for( unsigned int i=0; i<7; i++ ) { S1[i]=0.; }//i if( type > 0 ) { charge_weight *= 1./sqrt( 1.0 + particles.momentum( 0, ipart )*particles.momentum( 0, ipart ) + particles.momentum( 1, ipart )*particles.momentum( 1, ipart ) + particles.momentum( 2, ipart )*particles.momentum( 2, ipart ) ); if( type == 1 ) { charge_weight *= particles.momentum( 0, ipart ); } else if( type == 2 ) { charge_weight *= particles.momentum( 1, ipart ); } else { charge_weight *= particles.momentum( 2, ipart ); } } // Locate particle new position on the primal grid xjn = particles.position( 0, ipart ) * dx_inv_; ip = round( xjn + 0.5 * ( type==1 ) ); // index of the central node xj_m_xip = xjn - ( double )ip; // normalized distance to the nearest grid point xj_m_xip2 = xj_m_xip * xj_m_xip; // square of the normalized distance to the nearest grid point xj_m_xip3 = xj_m_xip2 * xj_m_xip; // cube of the normalized distance to the nearest grid point xj_m_xip4 = xj_m_xip3 * xj_m_xip; // 4th power of the normalized distance to the nearest grid point // coefficients 2nd order interpolation on 5 nodes //ip_m_ipo = ip-ipo; S1[1] = dble_1_ov_384 - dble_1_ov_48 * xj_m_xip + dble_1_ov_16 * xj_m_xip2 - dble_1_ov_12 * xj_m_xip3 + dble_1_ov_24 * xj_m_xip4; S1[2] = dble_19_ov_96 - dble_11_ov_24 * xj_m_xip + dble_1_ov_4 * xj_m_xip2 + dble_1_ov_6 * xj_m_xip3 - dble_1_ov_6 * xj_m_xip4; S1[3] = dble_115_ov_192 - dble_5_ov_8 * xj_m_xip2 + dble_1_ov_4 * xj_m_xip4; S1[4] = dble_19_ov_96 + dble_11_ov_24 * xj_m_xip + dble_1_ov_4 * xj_m_xip2 - dble_1_ov_6 * xj_m_xip3 - dble_1_ov_6 * xj_m_xip4; S1[5] = dble_1_ov_384 + dble_1_ov_48 * xj_m_xip + dble_1_ov_16 * xj_m_xip2 + dble_1_ov_12 * xj_m_xip3 + dble_1_ov_24 * xj_m_xip4; ip -= index_domain_begin + 3 ; // 4th order projection for the charge density // At the 4th order, oversize = 3. for( unsigned int i=0; i<7; i++ ) { //iloc = i + ipo - 3; rhoj[i + ip ] += charge_weight * S1[i]; }//i }
void PusherBorisV::operator()( Particles &particles, SmileiMPI *smpi, int istart, int iend, int ithread, int ipart_ref ) { std::vector<double> *Epart = &( smpi->dynamics_Epart[ithread] ); std::vector<double> *Bpart = &( smpi->dynamics_Bpart[ithread] ); double *invgf = &( smpi->dynamics_invgf[ithread][0] ); double charge_over_mass_dts2; double inv_det_T, Tx, Ty, Tz; double local_invgf; //int IX; //int* cell_keys; double *momentum[3]; for( int i = 0 ; i<3 ; i++ ) { momentum[i] = &( particles.momentum( i, 0 ) ); } double *position[3]; for( int i = 0 ; i<nDim_ ; i++ ) { position[i] = &( particles.position( i, 0 ) ); } #ifdef __DEBUG double *position_old[3]; for( int i = 0 ; i<nDim_ ; i++ ) { position_old[i] = &( particles.position_old( i, 0 ) ); } #endif short *charge = &( particles.charge( 0 ) ); int nparts = Epart->size()/3; double *Ex = &( ( *Epart )[0*nparts] ); double *Ey = &( ( *Epart )[1*nparts] ); double *Ez = &( ( *Epart )[2*nparts] ); double *Bx = &( ( *Bpart )[0*nparts] ); double *By = &( ( *Bpart )[1*nparts] ); double *Bz = &( ( *Bpart )[2*nparts] ); //particles.cell_keys.resize(nparts); //cell_keys = &( particles.cell_keys[0]); double dcharge[nparts]; #pragma omp simd for( int ipart=istart ; ipart<iend; ipart++ ) { dcharge[ipart] = ( double )( charge[ipart] ); } #pragma omp simd for( int ipart=istart ; ipart<iend; ipart++ ) { double psm[3], um[3]; charge_over_mass_dts2 = dcharge[ipart]*one_over_mass_*dts2; // init Half-acceleration in the electric field psm[0] = charge_over_mass_dts2*( *( Ex+ipart-ipart_ref ) ); psm[1] = charge_over_mass_dts2*( *( Ey+ipart-ipart_ref ) ); psm[2] = charge_over_mass_dts2*( *( Ez+ipart-ipart_ref ) ); //(*this)(particles, ipart, (*Epart)[ipart], (*Bpart)[ipart] , (*invgf)[ipart]); um[0] = momentum[0][ipart] + psm[0]; um[1] = momentum[1][ipart] + psm[1]; um[2] = momentum[2][ipart] + psm[2]; // Rotation in the magnetic field local_invgf = charge_over_mass_dts2 / sqrt( 1.0 + um[0]*um[0] + um[1]*um[1] + um[2]*um[2] ); Tx = local_invgf * ( *( Bx+ipart-ipart_ref ) ); Ty = local_invgf * ( *( By+ipart-ipart_ref ) ); Tz = local_invgf * ( *( Bz+ipart-ipart_ref ) ); inv_det_T = 1.0/( 1.0+Tx*Tx+Ty*Ty+Tz*Tz ); psm[0] += ( ( 1.0+Tx*Tx-Ty*Ty-Tz*Tz )* um[0] + 2.0*( Tx*Ty+Tz )* um[1] + 2.0*( Tz*Tx-Ty )* um[2] )*inv_det_T; psm[1] += ( 2.0*( Tx*Ty-Tz )* um[0] + ( 1.0-Tx*Tx+Ty*Ty-Tz*Tz )* um[1] + 2.0*( Ty*Tz+Tx )* um[2] )*inv_det_T; psm[2] += ( 2.0*( Tz*Tx+Ty )* um[0] + 2.0*( Ty*Tz-Tx )* um[1] + ( 1.0-Tx*Tx-Ty*Ty+Tz*Tz )* um[2] )*inv_det_T; // finalize Half-acceleration in the electric field local_invgf = 1. / sqrt( 1.0 + psm[0]*psm[0] + psm[1]*psm[1] + psm[2]*psm[2] ); invgf[ipart-ipart_ref] = local_invgf; momentum[0][ipart] = psm[0]; momentum[1][ipart] = psm[1]; momentum[2][ipart] = psm[2]; // Move the particle #ifdef __DEBUG for( int i = 0 ; i<nDim_ ; i++ ) { position_old[i][ipart] = position[i][ipart]; } #endif local_invgf *= dt; for( int i = 0 ; i<nDim_ ; i++ ) { position[i][ipart] += psm[i]*local_invgf; } } // This is temporarily moved to SpeciesV.cpp //#pragma omp simd //for (int ipart=istart ; ipart<iend; ipart++ ) { // // for ( int i = 0 ; i<nDim_ ; i++ ){ // cell_keys[ipart] *= nspace[i]; // cell_keys[ipart] += round( (position[i][ipart]-min_loc_vec[i]) * dx_inv_[i] ); // } // //} }
// --------------------------------------------------------------------------------------------------------------------- // 2nd Order Interpolation of the fields at a the particle position (3 nodes are used) // --------------------------------------------------------------------------------------------------------------------- void Interpolator2D1Order::operator() (ElectroMagn* EMfields, Particles &particles, int ipart, LocalFields* ELoc, LocalFields* BLoc) { // Static cast of the electromagnetic fields Field2D* Ex2D = static_cast<Field2D*>(EMfields->Ex_); Field2D* Ey2D = static_cast<Field2D*>(EMfields->Ey_); Field2D* Ez2D = static_cast<Field2D*>(EMfields->Ez_); Field2D* Bx2D = static_cast<Field2D*>(EMfields->Bx_m); Field2D* By2D = static_cast<Field2D*>(EMfields->By_m); Field2D* Bz2D = static_cast<Field2D*>(EMfields->Bz_m); // Normalized particle position double xpn = particles.position(0, ipart)*dx_inv_; double ypn = particles.position(1, ipart)*dy_inv_; // Indexes of the central nodes ip_ = floor(xpn); jp_ = floor(ypn); // Declaration and calculation of the coefficient for interpolation double delta; delta = xpn - (double)ip_; coeffxp_[0] = 1.0 - delta; coeffxp_[1] = delta; delta = ypn - (double)jp_; coeffyp_[0] = 1.0 - delta; coeffyp_[1] = delta; //!\todo CHECK if this is correct for both primal & dual grids !!! // First index for summation ip_ = ip_ - i_domain_begin; jp_ = jp_ - j_domain_begin; // ------------------------- // Interpolation of Ex^(d,p) // ------------------------- (*ELoc).x = compute( coeffxp_, coeffyp_, Ex2D, ip_, jp_); // ------------------------- // Interpolation of Ey^(p,d) // ------------------------- (*ELoc).y = compute( coeffxp_, coeffyp_, Ey2D, ip_, jp_); // ------------------------- // Interpolation of Ez^(p,p) // ------------------------- (*ELoc).z = compute( coeffxp_, coeffyp_, Ez2D, ip_, jp_); // ------------------------- // Interpolation of Bx^(p,d) // ------------------------- (*BLoc).x = compute( coeffxp_, coeffyp_, Bx2D, ip_, jp_); // ------------------------- // Interpolation of By^(d,p) // ------------------------- (*BLoc).y = compute( coeffxp_, coeffyp_, By2D, ip_, jp_); // ------------------------- // Interpolation of Bz^(d,d) // ------------------------- (*BLoc).z = compute( coeffxp_, coeffyp_, Bz2D, ip_, jp_); } // END Interpolator2D1Order
// --------------------------------------------------------------------------------------------------------------------- // 2nd Order Interpolation of the fields at a the particle position (3 nodes are used) // --------------------------------------------------------------------------------------------------------------------- void Interpolator2D2Order::operator() (ElectroMagn* EMfields, Particles &particles, int ipart, LocalFields* ELoc, LocalFields* BLoc) { // Static cast of the electromagnetic fields Field2D* Ex2D = static_cast<Field2D*>(EMfields->Ex_); Field2D* Ey2D = static_cast<Field2D*>(EMfields->Ey_); Field2D* Ez2D = static_cast<Field2D*>(EMfields->Ez_); Field2D* Bx2D = static_cast<Field2D*>(EMfields->Bx_m); Field2D* By2D = static_cast<Field2D*>(EMfields->By_m); Field2D* Bz2D = static_cast<Field2D*>(EMfields->Bz_m); // Normalized particle position double xpn = particles.position(0, ipart)*dx_inv_; double ypn = particles.position(1, ipart)*dy_inv_; // Indexes of the central nodes ip_ = round(xpn); id_ = round(xpn+0.5); jp_ = round(ypn); jd_ = round(ypn+0.5); // Declaration and calculation of the coefficient for interpolation double delta2; deltax = xpn - (double)id_ + 0.5; delta2 = deltax*deltax; coeffxd_[0] = 0.5 * (delta2-deltax+0.25); coeffxd_[1] = 0.75 - delta2; coeffxd_[2] = 0.5 * (delta2+deltax+0.25); deltax = xpn - (double)ip_; delta2 = deltax*deltax; coeffxp_[0] = 0.5 * (delta2-deltax+0.25); coeffxp_[1] = 0.75 - delta2; coeffxp_[2] = 0.5 * (delta2+deltax+0.25); deltay = ypn - (double)jd_ + 0.5; delta2 = deltay*deltay; coeffyd_[0] = 0.5 * (delta2-deltay+0.25); coeffyd_[1] = 0.75 - delta2; coeffyd_[2] = 0.5 * (delta2+deltay+0.25); deltay = ypn - (double)jp_; delta2 = deltay*deltay; coeffyp_[0] = 0.5 * (delta2-deltay+0.25); coeffyp_[1] = 0.75 - delta2; coeffyp_[2] = 0.5 * (delta2+deltay+0.25); //!\todo CHECK if this is correct for both primal & dual grids !!! // First index for summation ip_ = ip_ - i_domain_begin; id_ = id_ - i_domain_begin; jp_ = jp_ - j_domain_begin; jd_ = jd_ - j_domain_begin; // ------------------------- // Interpolation of Ex^(d,p) // ------------------------- (*ELoc).x = compute( &coeffxd_[1], &coeffyp_[1], Ex2D, id_, jp_); // ------------------------- // Interpolation of Ey^(p,d) // ------------------------- (*ELoc).y = compute( &coeffxp_[1], &coeffyd_[1], Ey2D, ip_, jd_); // ------------------------- // Interpolation of Ez^(p,p) // ------------------------- (*ELoc).z = compute( &coeffxp_[1], &coeffyp_[1], Ez2D, ip_, jp_); // ------------------------- // Interpolation of Bx^(p,d) // ------------------------- (*BLoc).x = compute( &coeffxp_[1], &coeffyd_[1], Bx2D, ip_, jd_); // ------------------------- // Interpolation of By^(d,p) // ------------------------- (*BLoc).y = compute( &coeffxd_[1], &coeffyp_[1], By2D, id_, jp_); // ------------------------- // Interpolation of Bz^(d,d) // ------------------------- (*BLoc).z = compute( &coeffxd_[1], &coeffyd_[1], Bz2D, id_, jd_); } // END Interpolator2D2Order
// --------------------------------------------------------------------------------------------------------------------- //! Project local currents (sort) // --------------------------------------------------------------------------------------------------------------------- void Projector3D4Order::currents( double *Jx, double *Jy, double *Jz, Particles &particles, unsigned int ipart, double invgf, int *iold, double *deltaold ) { int nparts = particles.size(); // ------------------------------------- // Variable declaration & initialization // ------------------------------------- // (x,y,z) components of the current density for the macro-particle double charge_weight = inv_cell_volume * ( double )( particles.charge( ipart ) )*particles.weight( ipart ); double crx_p = charge_weight*dx_ov_dt; double cry_p = charge_weight*dy_ov_dt; double crz_p = charge_weight*dz_ov_dt; // variable declaration double xpn, ypn, zpn; double delta, delta2, delta3, delta4; // arrays used for the Esirkepov projection method double Sx0[7], Sx1[7], Sy0[7], Sy1[7], Sz0[7], Sz1[7], DSx[7], DSy[7], DSz[7]; double tmpJx[7][7], tmpJy[7][7], tmpJz[7][7]; for( unsigned int i=0; i<7; i++ ) { Sx1[i] = 0.; Sy1[i] = 0.; Sz1[i] = 0.; } for( unsigned int j=0; j<7; j++ ) for( unsigned int k=0; k<7; k++ ) { tmpJx[j][k] = 0.; } for( unsigned int i=0; i<7; i++ ) for( unsigned int k=0; k<7; k++ ) { tmpJy[i][k] = 0.; } for( unsigned int i=0; i<7; i++ ) for( unsigned int j=0; j<7; j++ ) { tmpJz[i][j] = 0.; } // -------------------------------------------------------- // Locate particles & Calculate Esirkepov coef. S, DS and W // -------------------------------------------------------- // locate the particle on the primal grid at former time-step & calculate coeff. S0 delta = deltaold[0*nparts]; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sx0[0] = 0.; Sx0[1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sx0[2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx0[3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sx0[4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx0[5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sx0[6] = 0.; delta = deltaold[1*nparts]; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sy0[0] = 0.; Sy0[1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sy0[2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy0[3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sy0[4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy0[5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sy0[6] = 0.; delta = deltaold[2*nparts]; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sz0[0] = 0.; Sz0[1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sz0[2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sz0[3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sz0[4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sz0[5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sz0[6] = 0.; // locate the particle on the primal grid at current time-step & calculate coeff. S1 xpn = particles.position( 0, ipart ) * dx_inv_; int ip = round( xpn ); int ipo = iold[0*nparts]; int ip_m_ipo = ip-ipo-i_domain_begin; delta = xpn - ( double )ip; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sx1[ip_m_ipo+1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sx1[ip_m_ipo+2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx1[ip_m_ipo+3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sx1[ip_m_ipo+4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sx1[ip_m_ipo+5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; ypn = particles.position( 1, ipart ) * dy_inv_; int jp = round( ypn ); int jpo = iold[1*nparts]; int jp_m_jpo = jp-jpo-j_domain_begin; delta = ypn - ( double )jp; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sy1[jp_m_jpo+1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sy1[jp_m_jpo+2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy1[jp_m_jpo+3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sy1[jp_m_jpo+4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sy1[jp_m_jpo+5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; zpn = particles.position( 2, ipart ) * dz_inv_; int kp = round( zpn ); int kpo = iold[2*nparts]; int kp_m_kpo = kp-kpo-k_domain_begin; delta = zpn - ( double )kp; delta2 = delta*delta; delta3 = delta2*delta; delta4 = delta3*delta; Sz1[kp_m_kpo+1] = dble_1_ov_384 - dble_1_ov_48 * delta + dble_1_ov_16 * delta2 - dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; Sz1[kp_m_kpo+2] = dble_19_ov_96 - dble_11_ov_24 * delta + dble_1_ov_4 * delta2 + dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sz1[kp_m_kpo+3] = dble_115_ov_192 - dble_5_ov_8 * delta2 + dble_1_ov_4 * delta4; Sz1[kp_m_kpo+4] = dble_19_ov_96 + dble_11_ov_24 * delta + dble_1_ov_4 * delta2 - dble_1_ov_6 * delta3 - dble_1_ov_6 * delta4; Sz1[kp_m_kpo+5] = dble_1_ov_384 + dble_1_ov_48 * delta + dble_1_ov_16 * delta2 + dble_1_ov_12 * delta3 + dble_1_ov_24 * delta4; // computes Esirkepov coefficients for( unsigned int i=0; i < 7; i++ ) { DSx[i] = Sx1[i] - Sx0[i]; DSy[i] = Sy1[i] - Sy0[i]; DSz[i] = Sz1[i] - Sz0[i]; } // --------------------------- // Calculate the total current // --------------------------- ipo -= 3; //This minus 3 come from the order 4 scheme, based on a 7 points stencil from -3 to +3. // i/j/kpo stored with - i/j/k_domain_begin in Interpolator jpo -= 3; kpo -= 3; int iloc, jloc, kloc, linindex; // Jx^(d,p,p) for( unsigned int i=1 ; i<7 ; i++ ) { iloc = i+ipo; for( unsigned int j=0 ; j<7 ; j++ ) { jloc = j+jpo; for( unsigned int k=0 ; k<7 ; k++ ) { tmpJx[j][k] -= crx_p * DSx[i-1] * ( Sy0[j]*Sz0[k] + 0.5*DSy[j]*Sz0[k] + 0.5*DSz[k]*Sy0[j] + one_third*DSy[j]*DSz[k] ); kloc = k+kpo; linindex = iloc*nprimz*nprimy+jloc*nprimz+kloc; Jx [linindex] += tmpJx[j][k]; // iloc = (i+ipo)*nprimy; } } }//i // Jy^(p,d,p) for( unsigned int i=0 ; i<7 ; i++ ) { iloc = i+ipo; for( unsigned int j=1 ; j<7 ; j++ ) { jloc = j+jpo; for( unsigned int k=0 ; k<7 ; k++ ) { tmpJy[i][k] -= cry_p * DSy[j-1] * ( Sz0[k]*Sx0[i] + 0.5*DSz[k]*Sx0[i] + 0.5*DSx[i]*Sz0[k] + one_third*DSz[k]*DSx[i] ); kloc = k+kpo; linindex = iloc*nprimz*( nprimy+1 )+jloc*nprimz+kloc; Jy [linindex] += tmpJy[i][k]; // } } }//i // Jz^(p,p,d) for( unsigned int i=0 ; i<7 ; i++ ) { iloc = i+ipo; for( unsigned int j=0 ; j<7 ; j++ ) { jloc = j+jpo; for( unsigned int k=1 ; k<7 ; k++ ) { tmpJz[i][j] -= crz_p * DSz[k-1] * ( Sx0[i]*Sy0[j] + 0.5*DSx[i]*Sy0[j] + 0.5*DSy[j]*Sx0[i] + one_third*DSx[i]*DSy[j] ); kloc = k+kpo; linindex = iloc*( nprimz+1 )*nprimy+jloc*( nprimz+1 )+kloc; Jz [linindex] += tmpJz[i][j]; // } } }//i } // END Project local current densities (Jx, Jy, Jz, sort)