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
    
    
}
Example #2
0
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] );
    //    }
    //
    //}
    
}