double rate(double energy) { double R=rate_vs_electron_energy->call(energy); if( R!=R ) //R is nan, energy is too high { throw gen_exception("energy too high for bremsstrahlung table:", energy); } return R; }
static void gen_mtvscr(DisasContext *ctx) { TCGv_ptr p; if (unlikely(!ctx->altivec_enabled)) { gen_exception(ctx, POWERPC_EXCP_VPU); return; } p = gen_avr_ptr(rB(ctx->opcode)); gen_helper_mtvscr(cpu_env, p); tcg_temp_free_ptr(p); }
static void gen_mfvscr(DisasContext *ctx) { TCGv_i32 t; if (unlikely(!ctx->altivec_enabled)) { gen_exception(ctx, POWERPC_EXCP_VPU); return; } tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0); t = tcg_temp_new_i32(); tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr)); tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t); tcg_temp_free_i32(t); }
static void gen_vsbox(DisasContext *ctx) { TCGv_ptr ra, rd; if (unlikely(!ctx->altivec_enabled)) { gen_exception(ctx, POWERPC_EXCP_VPU); return; } ra = gen_avr_ptr(rA(ctx->opcode)); rd = gen_avr_ptr(rD(ctx->opcode)); gen_helper_vsbox(rd, ra); tcg_temp_free_ptr(ra); tcg_temp_free_ptr(rd); }
static void gen_vmrgow(DisasContext *ctx) { int VT, VA, VB; if (unlikely(!ctx->altivec_enabled)) { gen_exception(ctx, POWERPC_EXCP_VPU); return; } VT = rD(ctx->opcode); VA = rA(ctx->opcode); VB = rB(ctx->opcode); tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VB], cpu_avrh[VA], 32, 32); tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VB], cpu_avrl[VA], 32, 32); }
static void gen_lvsr(DisasContext *ctx) { TCGv_ptr rd; TCGv EA; if (unlikely(!ctx->altivec_enabled)) { gen_exception(ctx, POWERPC_EXCP_VPU); return; } EA = tcg_temp_new(); gen_addr_reg_index(ctx, EA); rd = gen_avr_ptr(rD(ctx->opcode)); gen_helper_lvsr(rd, EA); tcg_temp_free(EA); tcg_temp_free_ptr(rd); }
gsl::vector force(gsl::vector &position, gsl::vector &momentum, double time, int charge) { //values double momentum_squared=momentum.sum_of_squares(); double momentum_magnitude=sqrt(momentum_squared); double G=gamma(momentum_squared); double inverse_gamma=1.0/G; //electric field gsl::vector force=charge*E_field->get(position, time); //magnetic field gsl::vector B=charge*B_field->get(position, time); force[0]+=inverse_gamma*(momentum[1]*B[2]-momentum[2]*B[1]); force[1]+=inverse_gamma*(momentum[2]*B[0]-momentum[0]*B[2]); force[2]+=inverse_gamma*(momentum[0]*B[1]-momentum[1]*B[0]); //ionization friction double friction=-1; if(charge==-1) { if(remove_moller==0 or remove_moller==1) //if not removing moller losses, or constant min_energy { friction=electron_table.electron_lookup(momentum_squared); } else if(remove_moller==2) //variable min energy { friction=electron_table.electron_lookup_variable_RML(momentum_squared, min_energy); } } else { throw gen_exception("positrons not implemented"); ////positrons not implemented //friction=ionization.positron_lookup(momentum_squared); } //friction*=0.2; if(friction>0) //don't want weird stuff { force[0]-=friction*momentum[0]/momentum_magnitude; force[1]-=friction*momentum[1]/momentum_magnitude; force[2]-=friction*momentum[2]/momentum_magnitude; } return force; }
static void gen_vsldoi(DisasContext *ctx) { TCGv_ptr ra, rb, rd; TCGv_i32 sh; if (unlikely(!ctx->altivec_enabled)) { gen_exception(ctx, POWERPC_EXCP_VPU); return; } ra = gen_avr_ptr(rA(ctx->opcode)); rb = gen_avr_ptr(rB(ctx->opcode)); rd = gen_avr_ptr(rD(ctx->opcode)); sh = tcg_const_i32(VSH(ctx->opcode)); gen_helper_vsldoi (rd, ra, rb, sh); tcg_temp_free_ptr(ra); tcg_temp_free_ptr(rb); tcg_temp_free_ptr(rd); tcg_temp_free_i32(sh); }
static void gen_vmrgew(DisasContext *ctx) { TCGv_i64 tmp; int VT, VA, VB; if (unlikely(!ctx->altivec_enabled)) { gen_exception(ctx, POWERPC_EXCP_VPU); return; } VT = rD(ctx->opcode); VA = rA(ctx->opcode); VB = rB(ctx->opcode); tmp = tcg_temp_new_i64(); tcg_gen_shri_i64(tmp, cpu_avrh[VB], 32); tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VA], tmp, 0, 32); tcg_gen_shri_i64(tmp, cpu_avrl[VB], 32); tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VA], tmp, 0, 32); tcg_temp_free_i64(tmp); }
void charged_particle_RungeKuttaDP(electron_T *particle) // run Dormand-Prince Runge-Kutta with continuous extension, does not rely on the FSAL property { if(particle->pos_K_interpolant.size()==0) //need to initialize particle { particle->pos_K_interpolant.reserve(8); particle->mom_K_interpolant.reserve(8); for(int i=0; i<8; i++) { particle->pos_K_interpolant.push_back(gsl::vector({0,0,0})); particle->mom_K_interpolant.push_back(gsl::vector({0,0,0})); } } bool acceptable=false; //print("run:", particle.next_timestep);//(sqrt(particle.momentum.sum_of_squares()+1)-1)*510); int N=0; while(not acceptable) { N++; particle->timestep=particle->next_timestep; if(particle->timestep>maximum_timestep) { particle->timestep=maximum_timestep; } if(particle->timestep != particle->timestep) { throw gen_exception("timestep is Nan"); } gsl::vector pos_step=particle->position; gsl::vector mom_step=particle->momentum; double time=particle->current_time; gsl::vector K_1_pos=mom_step*(1.0/gamma(mom_step)); gsl::vector K_1_mom=force(pos_step, mom_step, time, particle->charge); //note that this is a bit redundant. We could calculate this once at the beginning. It doesn't change if stepsize changes K_1_pos*=particle->timestep; K_1_mom*=particle->timestep; pos_step=K_1_pos*(1.0/5.0); mom_step=K_1_mom*(1.0/5.0); pos_step+=particle->position; mom_step+=particle->momentum; time=particle->current_time + particle->timestep*(1.0/5.0); gsl::vector K_2_pos=mom_step*(1.0/gamma(mom_step)); gsl::vector K_2_mom=force(pos_step, mom_step, time, particle->charge); K_2_pos*=particle->timestep; K_2_mom*=particle->timestep; pos_step=K_1_pos*(3.0/40.0); mom_step=K_1_mom*(3.0/40.0); pos_step.mult_add( K_2_pos, (9.0/40.0) ); mom_step.mult_add( K_2_mom, (9.0/40.0) ); pos_step+=particle->position; mom_step+=particle->momentum; time=particle->current_time + particle->timestep*3.0/10.0; gsl::vector K_3_pos=mom_step*(1.0/gamma(mom_step)); gsl::vector K_3_mom=force(pos_step, mom_step, time, particle->charge); K_3_pos*=particle->timestep; K_3_mom*=particle->timestep; pos_step=K_1_pos*(44.0/45.0); mom_step=K_1_mom*(44.0/45.0); pos_step.mult_add( K_2_pos, -(56.0/15.0) ); mom_step.mult_add( K_2_mom, -(56.0/15.0) ); pos_step.mult_add( K_3_pos, (32.0/9.0) ); mom_step.mult_add( K_3_mom, (32.0/9.0) ); pos_step+=particle->position; mom_step+=particle->momentum; time=particle->current_time + particle->timestep*(4.0/5.0); gsl::vector K_4_pos=mom_step*(1.0/gamma(mom_step)); gsl::vector K_4_mom=force(pos_step, mom_step, time, particle->charge); K_4_pos*=particle->timestep; K_4_mom*=particle->timestep; pos_step=K_1_pos*(19372.0/6561.0); mom_step=K_1_mom*(19372.0/6561.0); pos_step.mult_add( K_2_pos, -(25360.0/2187.0) ); mom_step.mult_add( K_2_mom, -(25360.0/2187.0) ); pos_step.mult_add( K_3_pos, (64448.0/6561.0) ); mom_step.mult_add( K_3_mom, (64448.0/6561.0) ); pos_step.mult_add( K_4_pos, -(212.0/729.0) ); mom_step.mult_add( K_4_mom, -(212.0/729.0) ); pos_step+=particle->position; mom_step+=particle->momentum; time=particle->current_time + particle->timestep*8.0/9.0; gsl::vector K_5_pos=mom_step*(1.0/gamma(mom_step)); gsl::vector K_5_mom=force(pos_step, mom_step, time, particle->charge); K_5_pos*=particle->timestep; K_5_mom*=particle->timestep; pos_step=K_1_pos*(9017.0/3168.0); mom_step=K_1_mom*(9017.0/3168.0); pos_step.mult_add( K_2_pos, -(355.0/33.0) ); mom_step.mult_add( K_2_mom, -(355.0/33.0) ); pos_step.mult_add( K_3_pos, (46732.0/5247.0) ); mom_step.mult_add( K_3_mom, (46732.0/5247.0) ); pos_step.mult_add( K_4_pos, (49.0/176.0) ); mom_step.mult_add( K_4_mom, (49.0/176.0) ); pos_step.mult_add( K_5_pos, -(5103.0/18656.0) ); mom_step.mult_add( K_5_mom, -(5103.0/18656.0) ); pos_step+=particle->position; mom_step+=particle->momentum; time=particle->current_time + particle->timestep; gsl::vector K_6_pos=mom_step*(1.0/gamma(mom_step)); gsl::vector K_6_mom=force(pos_step, mom_step, time, particle->charge); K_6_pos*=particle->timestep; K_6_mom*=particle->timestep; pos_step=K_1_pos*(35.0/384.0); mom_step=K_1_mom*(35.0/384.0); //K2 is zero pos_step.mult_add( K_3_pos, (500.0/1113.0) ); mom_step.mult_add( K_3_mom, (500.0/1113.0) ); pos_step.mult_add( K_4_pos, (125.0/192.0) ); mom_step.mult_add( K_4_mom, (125.0/192.0) ); pos_step.mult_add( K_5_pos, -(2187.0/6784.0) ); mom_step.mult_add( K_5_mom, -(2187.0/6784.0) ); pos_step.mult_add( K_6_pos, (11.0/84.0) ); mom_step.mult_add( K_6_mom, (11.0/84.0) ); pos_step+=particle->position; mom_step+=particle->momentum; time=particle->current_time + particle->timestep; gsl::vector K_7_pos=mom_step*(1.0/gamma(mom_step)); gsl::vector K_7_mom=force(pos_step, mom_step, time, particle->charge); K_7_pos*=particle->timestep; K_7_mom*=particle->timestep; gsl::vector pos_O4=K_1_pos*(5179.0/57600.0); gsl::vector mom_O4=K_1_mom*(5179.0/57600.0); //pos_O4.mult_add( K_2_pos, 0.0 ); //mom_O4.mult_add( K_2_mom, 0.0 ); pos_O4.mult_add( K_3_pos, (7571.0/16695.0) ); mom_O4.mult_add( K_3_mom, (7571.0/16695.0) ); pos_O4.mult_add( K_4_pos, (393.0/640.0) ); mom_O4.mult_add( K_4_mom, (393.0/640.0) ); pos_O4.mult_add( K_5_pos, -(92097.0/339200.0) ); mom_O4.mult_add( K_5_mom, -(92097.0/339200.0) ); pos_O4.mult_add( K_6_pos, (187.0/2100.0) ); mom_O4.mult_add( K_6_mom, (187.0/2100.0) ); pos_O4.mult_add( K_7_pos, (1.0/40.0) ); mom_O4.mult_add( K_7_mom, (1.0/40.0) ); //pos_O4+=particle.position; //don't need to do this //mom_O4+=particle.momentum; gsl::vector pos_O5=K_1_pos*(35.0/384.0); gsl::vector mom_O5=K_1_mom*(35.0/384.0); //pos_O5.mult_add( K_2_pos, 0.0 ); //mom_O5.mult_add( K_2_mom, 0.0 ); pos_O5.mult_add( K_3_pos, (500.0/1113.0) ); mom_O5.mult_add( K_3_mom, (500.0/1113.0) ); pos_O5.mult_add( K_4_pos, (125.0/192.0) ); mom_O5.mult_add( K_4_mom, (125.0/192.0) ); pos_O5.mult_add( K_5_pos, -(2187.0/6784.0) ); mom_O5.mult_add( K_5_mom, -(2187.0/6784.0) ); pos_O5.mult_add( K_6_pos, (11.0/84.0) ); mom_O5.mult_add( K_6_mom, (11.0/84.0) ); //pos_O5.mult_add( K_7_pos, 0.0 ); //mom_O5.mult_add( K_7_mom, 0.0 ); pos_O4-=pos_O5;//for calculating the error mom_O4-=mom_O5; double pos_error_sq=pos_O4.sum_of_squares(); double mom_error_sq=mom_O4.sum_of_squares(); double max_pos_error_sq=rel_tol*rel_tol*pos_O5.sum_of_squares(); double max_mom_error_sq=rel_tol*rel_tol*mom_O5.sum_of_squares(); double err_f=std::min(max_pos_error_sq/pos_error_sq, max_mom_error_sq/mom_error_sq );//note the inverses pos_O5+=particle->position; mom_O5+=particle->momentum; //double pos_error_sq=pos_O4.sum_of_squares(); //double mom_error_sq=mom_O4.sum_of_squares(); //pos_error_sq=pos_tol*pos_tol/pos_error_sq; //mom_error_sq=mom_tol*mom_tol/mom_error_sq; if(err_f>1)//error is good, exit { //set timestep particle->interpolant_timestep=particle->timestep; particle->next_timestep=particle->timestep*kappa*std::pow( std::sqrt(err_f), 0.25); particle->pos_K_interpolant[0]=particle->position; particle->mom_K_interpolant[0]=particle->momentum; particle->pos_K_interpolant[1]=K_1_pos; particle->mom_K_interpolant[1]=K_1_mom; particle->pos_K_interpolant[2]=K_2_pos; particle->mom_K_interpolant[2]=K_2_mom; particle->pos_K_interpolant[3]=K_3_pos; particle->mom_K_interpolant[3]=K_3_mom; particle->pos_K_interpolant[4]=K_4_pos; particle->mom_K_interpolant[4]=K_4_mom; particle->pos_K_interpolant[5]=K_5_pos; particle->mom_K_interpolant[5]=K_5_mom; particle->pos_K_interpolant[6]=K_6_pos; particle->mom_K_interpolant[6]=K_6_mom; particle->pos_K_interpolant[7]=K_7_pos; particle->mom_K_interpolant[7]=K_7_mom; particle->current_time+=particle->timestep; particle->position=pos_O5; particle->momentum=mom_O5; acceptable=true; } else {//repeat with new timestep if(N>100) { throw gen_exception("error in Dormand-Prince RK: ", N); } //print(pos_O4.sum_of_squares(), mom_O4.sum_of_squares(), max_pos_error_sq, max_mom_error_sq); particle->next_timestep=particle->timestep*kappa*std::pow( std::sqrt(err_f), 0.20); acceptable=false; } } }