build_particle_source_plan Subroutine

public subroutine build_particle_source_plan(cfg, plan, mpi_rank, mpi_size, mpi, kinetic_inflow_active, kinetic_reservoir_potential_v, kinetic_access_potential_v, kinetic_inflow_face, number_flux_override_active, number_flux_override_m2_s)

設定とMPI配置だけに依存する粒子 source の導出値を構築する。 乱数、残差、mesh/snapshot依存の障壁は扱わず、run中に不変な値だけを保持する。

Arguments

Type IntentOptional Attributes Name
type(app_config), intent(in) :: cfg
type(particle_source_plan_type), intent(out) :: plan
integer(kind=i32), intent(in), optional :: mpi_rank
integer(kind=i32), intent(in), optional :: mpi_size
type(mpi_context), intent(in), optional :: mpi
logical, intent(in), optional :: kinetic_inflow_active(:)
real(kind=dp), intent(in), optional :: kinetic_reservoir_potential_v(:)
real(kind=dp), intent(in), optional :: kinetic_access_potential_v(:)
integer(kind=i32), intent(in), optional :: kinetic_inflow_face(:)
logical, intent(in), optional :: number_flux_override_active(:)
real(kind=dp), intent(in), optional :: number_flux_override_m2_s(:)

Calls

proc~~build_particle_source_plan~~CallsGraph proc~build_particle_source_plan build_particle_source_plan proc~has_boundary_inflow has_boundary_inflow proc~build_particle_source_plan->proc~has_boundary_inflow proc~lower_ascii lower_ascii proc~build_particle_source_plan->proc~lower_ascii proc~resolve_parallel_rank_size~2 resolve_parallel_rank_size proc~build_particle_source_plan->proc~resolve_parallel_rank_size~2 proc~species_number_density_m3 species_number_density_m3 proc~build_particle_source_plan->proc~species_number_density_m3 proc~species_temperature_k species_temperature_k proc~build_particle_source_plan->proc~species_temperature_k proc~mpi_get_rank_size mpi_get_rank_size proc~resolve_parallel_rank_size~2->proc~mpi_get_rank_size

Source Code

  subroutine build_particle_source_plan( &
    cfg, plan, mpi_rank, mpi_size, mpi, kinetic_inflow_active, kinetic_reservoir_potential_v, &
    kinetic_access_potential_v, kinetic_inflow_face, number_flux_override_active, number_flux_override_m2_s &
    )
    type(app_config), intent(in) :: cfg
    type(particle_source_plan_type), intent(out) :: plan
    integer(i32), intent(in), optional :: mpi_rank, mpi_size
    type(mpi_context), intent(in), optional :: mpi
    logical, intent(in), optional :: kinetic_inflow_active(:)
    real(dp), intent(in), optional :: kinetic_reservoir_potential_v(:), kinetic_access_potential_v(:)
    integer(i32), intent(in), optional :: kinetic_inflow_face(:)
    logical, intent(in), optional :: number_flux_override_active(:)
    real(dp), intent(in), optional :: number_flux_override_m2_s(:)

    integer(i32) :: s, local_rank, n_ranks
    logical :: has_enabled_reservoir

    call resolve_parallel_rank_size(local_rank, n_ranks, mpi_rank, mpi_size, mpi, 'build_particle_source_plan')
    plan%nspecies = cfg%n_particle_species
    plan%mpi_rank = local_rank
    plan%mpi_size = n_ranks
    plan%mpi_argument_present = present(mpi)
    has_enabled_reservoir = .false.
    do s = 1, cfg%n_particle_species
      if (.not. cfg%particle_species(s)%enabled) cycle
      has_enabled_reservoir = has_enabled_reservoir .or. &
                              trim(lower_ascii(cfg%particle_species(s)%source_mode)) == 'reservoir_face' .or. &
                              trim(lower_ascii(cfg%particle_species(s)%source_mode)) == 'plane_source' .or. &
                              has_boundary_inflow(cfg%particle_species(s))
    end do
    plan%use_collective_reservoir_count = present(mpi) .and. has_enabled_reservoir

    allocate (plan%effective_density_m3(cfg%n_particle_species))
    allocate (plan%effective_particle_flux_m2_s(cfg%n_particle_species))
    allocate (plan%number_flux_override_active(cfg%n_particle_species))
    allocate (plan%effective_temperature_k(cfg%n_particle_species))
    allocate (plan%effective_drift_velocity(3, cfg%n_particle_species))
    allocate (plan%effective_weight(cfg%n_particle_species))
    allocate (plan%photo_emit_current_density(cfg%n_particle_species))
    allocate (plan%photo_normal_drift_speed(cfg%n_particle_species))
    allocate (plan%kinetic_inflow_active(cfg%n_particle_species))
    allocate (plan%kinetic_reservoir_potential_v(cfg%n_particle_species))
    allocate (plan%kinetic_access_potential_v(cfg%n_particle_species))
    allocate (plan%kinetic_inflow_face(cfg%n_particle_species))
    plan%effective_density_m3 = 0.0_dp
    plan%effective_particle_flux_m2_s = 0.0_dp
    plan%number_flux_override_active = .false.
    plan%effective_temperature_k = 0.0_dp
    plan%effective_drift_velocity = 0.0_dp
    plan%effective_weight = 0.0_dp
    plan%photo_emit_current_density = 0.0_dp
    plan%photo_normal_drift_speed = 0.0_dp
    plan%kinetic_inflow_active = .false.
    plan%kinetic_reservoir_potential_v = 0.0_dp
    plan%kinetic_access_potential_v = 0.0_dp
    plan%kinetic_inflow_face = 0_i32

    if (present(kinetic_inflow_active) .or. present(kinetic_reservoir_potential_v) .or. &
        present(kinetic_access_potential_v) .or. present(kinetic_inflow_face)) then
      if (.not. present(kinetic_inflow_active) .or. .not. present(kinetic_reservoir_potential_v) .or. &
          .not. present(kinetic_access_potential_v) .or. .not. present(kinetic_inflow_face)) then
        error stop 'particle source kinetic map requires active, reservoir, access, and face arrays together.'
      end if
      if (size(kinetic_inflow_active) /= cfg%n_particle_species .or. &
          size(kinetic_reservoir_potential_v) /= cfg%n_particle_species .or. &
          size(kinetic_access_potential_v) /= cfg%n_particle_species .or. &
          size(kinetic_inflow_face) /= cfg%n_particle_species) then
        error stop 'particle source kinetic map species count mismatch.'
      end if
      if (.not. all(ieee_is_finite(kinetic_reservoir_potential_v)) .or. &
          .not. all(ieee_is_finite(kinetic_access_potential_v))) then
        error stop 'particle source kinetic map potentials must be finite.'
      end if
      plan%kinetic_inflow_active = kinetic_inflow_active
      plan%kinetic_reservoir_potential_v = kinetic_reservoir_potential_v
      plan%kinetic_access_potential_v = kinetic_access_potential_v
      plan%kinetic_inflow_face = kinetic_inflow_face
      if (any(plan%kinetic_inflow_active .and. &
              (plan%kinetic_inflow_face < 1_i32 .or. plan%kinetic_inflow_face > 6_i32))) then
        error stop 'active particle source kinetic map face must be in [1, 6].'
      end if
    end if

    if (present(number_flux_override_active) .or. present(number_flux_override_m2_s)) then
      if (.not. present(number_flux_override_active) .or. .not. present(number_flux_override_m2_s)) then
        error stop 'particle source number-flux override requires active and flux arrays together.'
      end if
      if (size(number_flux_override_active) /= cfg%n_particle_species .or. &
          size(number_flux_override_m2_s) /= cfg%n_particle_species) then
        error stop 'particle source number-flux override species count mismatch.'
      end if
      if (any(number_flux_override_active .and. &
              (.not. ieee_is_finite(number_flux_override_m2_s) .or. number_flux_override_m2_s < 0.0_dp))) then
        error stop 'active particle source number-flux overrides must be finite and nonnegative.'
      end if
      plan%number_flux_override_active = number_flux_override_active
    end if

    do s = 1, cfg%n_particle_species
      if (.not. cfg%particle_species(s)%enabled) cycle
      select case (trim(lower_ascii(cfg%particle_species(s)%source_mode)))
      case ('volume_seed')
        plan%effective_weight(s) = cfg%particle_species(s)%w_particle
        plan%effective_temperature_k(s) = species_temperature_k(cfg%particle_species(s))
        plan%effective_drift_velocity(:, s) = cfg%particle_species(s)%drift_velocity
        if (has_boundary_inflow(cfg%particle_species(s))) then
          if (trim(lower_ascii(cfg%particle_species(s)%velocity_distribution)) == 'grid') then
            plan%effective_particle_flux_m2_s(s) = cfg%particle_species(s)%particle_flux_m2_s
          else
            plan%effective_density_m3(s) = species_number_density_m3(cfg%particle_species(s))
          end if
        end if
      case ('reservoir_face', 'plane_source')
        if (trim(lower_ascii(cfg%particle_species(s)%velocity_distribution)) == 'grid') then
          plan%effective_particle_flux_m2_s(s) = cfg%particle_species(s)%particle_flux_m2_s
        else
          plan%effective_density_m3(s) = species_number_density_m3(cfg%particle_species(s))
        end if
        plan%effective_weight(s) = cfg%particle_species(s)%w_particle
        plan%effective_temperature_k(s) = species_temperature_k(cfg%particle_species(s))
        plan%effective_drift_velocity(:, s) = cfg%particle_species(s)%drift_velocity
      case ('photo_raycast')
        plan%photo_emit_current_density(s) = cfg%particle_species(s)%emit_current_density_a_m2
        plan%photo_normal_drift_speed(s) = cfg%particle_species(s)%normal_drift_speed
      end select
      if (plan%number_flux_override_active(s)) then
        plan%effective_particle_flux_m2_s(s) = number_flux_override_m2_s(s)
      end if
    end do

    plan%ready = .true.
  end subroutine build_particle_source_plan