設定とMPI配置だけに依存する粒子 source の導出値を構築する。 乱数、残差、mesh/snapshot依存の障壁は扱わず、run中に不変な値だけを保持する。
| Type | Intent | Optional | 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(:) |
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