1 本の光線を counter-based 乱数で発射し、当たれば光電子を 1 つ返す。
面内の発射位置は ray_counter の draw 1, 2、放出速度は velocity_counter で決まるので、どの rank・thread が
同じ slot を生成しても同じ粒子になる。
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_type), | intent(in) | :: | mesh | |||
| class(photo_raycast_config), | intent(in) | :: | sim | |||
| character(len=*), | intent(in) | :: | inject_face | |||
| real(kind=dp), | intent(in) | :: | pos_low(3) | |||
| real(kind=dp), | intent(in) | :: | pos_high(3) | |||
| real(kind=dp), | intent(in) | :: | ray_direction(3) | |||
| real(kind=dp), | intent(in) | :: | m_particle | |||
| real(kind=dp), | intent(in) | :: | temperature_k | |||
| real(kind=dp), | intent(in) | :: | normal_drift_speed | |||
| real(kind=dp), | intent(in) | :: | w_hit | |||
| integer(kind=i32), | intent(in) | :: | rng_seed | |||
| integer(kind=i64), | intent(in) | :: | ray_counter(:) | |||
| integer(kind=i64), | intent(in) | :: | velocity_counter(:) | |||
| real(kind=dp), | intent(out) | :: | x(3) | |||
| real(kind=dp), | intent(out) | :: | v(3) | |||
| real(kind=dp), | intent(out) | :: | w | |||
| integer(kind=i32), | intent(out) | :: | emit_elem | |||
| logical, | intent(out) | :: | emitted | |||
| integer(kind=i32), | intent(out) | :: | collision_status | |||
| integer(kind=i32), | intent(out) | :: | bounce_count | |||
| real(kind=dp), | intent(in), | optional | :: | vmin_normal |
subroutine sample_photo_ray_slot( & mesh, sim, inject_face, pos_low, pos_high, ray_direction, m_particle, temperature_k, normal_drift_speed, w_hit, & rng_seed, ray_counter, velocity_counter, x, v, w, emit_elem, emitted, collision_status, bounce_count, vmin_normal & ) type(mesh_type), intent(in) :: mesh class(photo_raycast_config), intent(in) :: sim character(len=*), intent(in) :: inject_face real(dp), intent(in) :: pos_low(3), pos_high(3), ray_direction(3) real(dp), intent(in) :: m_particle, temperature_k, normal_drift_speed, w_hit integer(i32), intent(in) :: rng_seed integer(i64), intent(in) :: ray_counter(:), velocity_counter(:) real(dp), intent(out) :: x(3), v(3), w integer(i32), intent(out) :: emit_elem, collision_status, bounce_count logical, intent(out) :: emitted real(dp), intent(in), optional :: vmin_normal integer :: axis_n, axis_t1, axis_t2 real(dp) :: boundary_value, inward_normal(3), launch_dir(3), ray_pos(3), hit_pos(3), hit_normal(3) real(dp) :: tangent1(3), tangent2(3), sigma, ray_uniform(2) logical :: use_periodic2_mode x = 0.0_dp v = 0.0_dp w = 0.0_dp emit_elem = -1_i32 call resolve_face_geometry(sim%box_min, sim%box_max, inject_face, axis_n, boundary_value, inward_normal) call resolve_face_axes(inject_face, axis_t1, axis_t2) launch_dir = ray_direction/sqrt(sum(ray_direction*ray_direction)) use_periodic2_mode = trim(lower_ascii(sim%field_bc_mode)) == 'periodic2' ray_pos = 0.0_dp ray_pos(axis_n) = boundary_value call counter_uniforms(rng_seed, ray_counter, 1_i64, ray_uniform) ray_pos(axis_t1) = pos_low(axis_t1) + (pos_high(axis_t1) - pos_low(axis_t1))*ray_uniform(1) ray_pos(axis_t2) = pos_low(axis_t2) + (pos_high(axis_t2) - pos_low(axis_t2))*ray_uniform(2) call cast_photo_ray( & mesh, sim, ray_pos, launch_dir, use_periodic2_mode, hit_pos, hit_normal, emit_elem, emitted, collision_status, & bounce_count & ) if (collision_status /= collision_query_ok .or. .not. emitted) return sigma = sqrt(k_boltzmann*temperature_k/m_particle) call build_tangent_basis(hit_normal, tangent1, tangent2) if (present(vmin_normal)) then call sample_photo_emission_velocity( & sigma, normal_drift_speed, hit_normal, tangent1, tangent2, v, vmin_normal=vmin_normal, rng_seed=rng_seed, & rng_counter=velocity_counter & ) else call sample_photo_emission_velocity( & sigma, normal_drift_speed, hit_normal, tangent1, tangent2, v, rng_seed=rng_seed, rng_counter=velocity_counter & ) end if x = hit_pos w = w_hit end subroutine sample_photo_ray_slot