module classes_particle_insertion_method use, intrinsic :: iso_fortran_env, only: DP => REAL64 use types_environment_wrapper, only: Environment_Wrapper use classes_num_particles, only: Abstract_Num_Particles use procedures_composition_factory, only: composition_destroy => destroy use types_component_wrapper, only: Component_Wrapper use types_particle_wrapper, only: Concrete_Particle use types_short_interactions_wrapper, only: Short_Interactions_Wrapper use procedures_visit_condition, only: visit_different use types_dipolar_interactions_dynamic_wrapper, only: Dipolar_Interactions_Dynamic_Wrapper use procedures_dipoles_field_interaction, only: dipoles_field_visit_add => visit_add use classes_random_coordinates, only: Abstract_Random_Coordinates use procedures_random_coordinates_factory, only: random_coordinates_destroy => destroy use types_observables_energies, only: Concrete_Single_Energies use types_exploring_observables_wrapper, only: Exploring_Observables_Wrapper implicit none private type, abstract, public :: Abstract_Particle_Insertion_Method private type(Environment_Wrapper), pointer :: environment => null() class(Abstract_Num_Particles), allocatable :: nums_particles(:) type(Component_Wrapper), pointer :: components(:, :) => null() type(Short_Interactions_Wrapper), pointer :: short_interactions => null() type(Dipolar_Interactions_Dynamic_Wrapper), pointer :: dipolar_interactions_dynamic(:) => & null() class(Abstract_Random_Coordinates), allocatable :: random_positions(:), random_orientation contains procedure :: construct => Abstract_construct procedure :: destroy => Abstract_destroy procedure :: try => Abstract_try procedure, private :: visit_walls => Abstract_visit_walls procedure, private :: visit_short => Abstract_visit_short procedure, private :: visit_field => Abstract_visit_field procedure, private :: visit_dipolar => Abstract_visit_dipolar end type Abstract_Particle_Insertion_Method type, extends(Abstract_Particle_Insertion_Method), public :: Concrete_Particle_Insertion_Method end type Concrete_Particle_Insertion_Method type, extends(Abstract_Particle_Insertion_Method), public :: Null_Particle_Insertion_Method contains procedure :: construct => Null_construct procedure :: destroy => Null_destroy procedure :: try => Null_try end type Null_Particle_Insertion_Method contains !implementation Abstract_Particle_Insertion_Method subroutine Abstract_construct(this, environment, nums_particles, components, & short_interactions, dipolar_interactions_dynamic, random_positions, random_orientation) class(Abstract_Particle_Insertion_Method), intent(out) :: this type(Environment_Wrapper), target, intent(in) :: environment class(Abstract_Num_Particles), intent(in) :: nums_particles(:) type(Component_Wrapper), target, intent(in) :: components(:, :) type(Short_Interactions_Wrapper), target, intent(in) :: short_interactions type(Dipolar_Interactions_Dynamic_Wrapper), target, intent(in) :: & dipolar_interactions_dynamic(:) class(Abstract_Random_Coordinates), intent(in) :: random_positions(:), random_orientation this%environment => environment allocate(this%nums_particles, source=nums_particles) this%components => components this%short_interactions => short_interactions this%dipolar_interactions_dynamic => dipolar_interactions_dynamic allocate(this%random_positions, source=random_positions) allocate(this%random_orientation, source=random_orientation) end subroutine Abstract_construct subroutine Abstract_destroy(this) class(Abstract_Particle_Insertion_Method), intent(inout) :: this call random_coordinates_destroy(this%random_orientation) call random_coordinates_destroy(this%random_positions) call composition_destroy(this%nums_particles) this%dipolar_interactions_dynamic => null() this%short_interactions => null() this%components => null() this%environment => null() end subroutine Abstract_destroy subroutine Abstract_try(this, observables) class(Abstract_Particle_Insertion_Method), intent(in) :: this type(Exploring_Observables_Wrapper), intent(inout) :: observables real(DP) :: inv_pow_activity_sum, delta_energy type(Concrete_Single_Energies) :: deltas type(Concrete_Particle) :: test integer :: i_box, i_component, i_particle logical :: overlap observables%inv_pow_activities = 0._DP test%i = 0 do i_box = 1, size(this%environment%periodic_boxes) allocate(deltas%short_energies(size(observables%energies(i_box)%short_energies))) allocate(deltas%dipolar_energies(size(observables%energies(i_box)%dipolar_energies))) do i_component = 1, size(this%nums_particles) inv_pow_activity_sum = 0._DP do i_particle = 1, this%nums_particles(i_component)%get() observables%insertion_counters(i_component, i_box)%num_hits = observables%& insertion_counters(i_component, i_box)%num_hits + 1 test%position = this%random_positions(i_box)%get(i_component) test%orientation = this%random_orientation%get(i_component) test%dipole_moment = this%components(i_component, i_box)%dipole_moments%& get_norm() * test%orientation call this%visit_walls(overlap, deltas%walls_energy, i_box, i_component, test) if (overlap) cycle call this%visit_short(overlap, deltas%short_energies, i_box, i_component, test) if (overlap) cycle call this%visit_field(deltas%field_energy, i_box, test) call this%visit_dipolar(deltas%dipolar_energies, deltas%dipolar_shared_energy, & i_box, i_component, test) delta_energy = deltas%field_energy + deltas%walls_energy + & sum(deltas%short_energies + deltas%dipolar_energies) + deltas%& dipolar_shared_energy inv_pow_activity_sum = inv_pow_activity_sum + & exp(-delta_energy / this%environment%temperature%get()) observables%insertion_counters(i_component, i_box)%num_successes = observables%& insertion_counters(i_component, i_box)%num_successes + 1 end do observables%inv_pow_activities(i_component, i_box) = inv_pow_activity_sum / & real(this%nums_particles(i_component)%get()) end do deallocate(deltas%dipolar_energies) deallocate(deltas%short_energies) end do end subroutine Abstract_try subroutine Abstract_visit_walls(this, overlap, delta, i_box, i_component, test) class(Abstract_Particle_Insertion_Method), intent(in) :: this logical, intent(out) :: overlap real(DP), intent(out) :: delta integer, intent(in) :: i_box, i_component type(Concrete_Particle), intent(in) :: test call this%environment%visitable_walls(i_box)%visit(overlap, delta, test%position, this%& short_interactions%wall_pairs(i_component)%potential) end subroutine Abstract_visit_walls subroutine Abstract_visit_short(this, overlap, deltas, i_box, i_component, test) class(Abstract_Particle_Insertion_Method), intent(in) :: this logical, intent(out) :: overlap real(DP), intent(out) :: deltas(:) integer, intent(in) :: i_box, i_component type(Concrete_Particle), intent(in) :: test integer :: j_component, i_exclude do j_component = 1, size(this%short_interactions%cells(i_box)%visitable_cells, 1) i_exclude = merge(test%i, 0, j_component == i_component) call this%short_interactions%cells(i_box)%visitable_cells(j_component, i_component)%& visit_energy(overlap, deltas(j_component), test, visit_different, i_exclude) if (overlap) return end do end subroutine Abstract_visit_short subroutine Abstract_visit_field(this, delta, i_box, test) class(Abstract_Particle_Insertion_Method), intent(in) :: this real(DP), intent(out) :: delta integer, intent(in) :: i_box type(Concrete_Particle), intent(in) :: test delta = dipoles_field_visit_add(this%environment%external_fields(i_box), test) end subroutine Abstract_visit_field subroutine Abstract_visit_dipolar(this, deltas, delta_shared_energy, i_box, i_component, test) class(Abstract_Particle_Insertion_Method), intent(in) :: this real(DP), intent(out) :: deltas(:) real(DP), intent(out) :: delta_shared_energy integer, intent(in) :: i_box, i_component type(Concrete_Particle), intent(in) :: test integer :: j_component, i_exclude do j_component = 1, size(this%dipolar_interactions_dynamic(i_box)%real_components, 1) i_exclude = merge(test%i, 0, j_component == i_component) call this%dipolar_interactions_dynamic(i_box)%& real_components(j_component, i_component)%component%& visit(deltas(j_component), test, visit_different, i_exclude) end do deltas(i_component) = deltas(i_component) - this%dipolar_interactions_dynamic(i_box)%& self_components(i_component)%component%meet(test%dipole_moment) delta_shared_energy = & this%dipolar_interactions_dynamic(i_box)%reci_visitor%visit_add(i_component, test) + & this%dipolar_interactions_dynamic(i_box)%surf_mixture%& visit_add(i_component, test%dipole_moment) - & this%dipolar_interactions_dynamic(i_box)%dlc_visitor%visit_add(i_component, test) end subroutine Abstract_visit_dipolar !end implementation Abstract_Particle_Insertion_Method !implementation Null_Particle_Insertion_Method subroutine Null_construct(this, environment, nums_particles, components, short_interactions, & dipolar_interactions_dynamic, random_positions, random_orientation) class(Null_Particle_Insertion_Method), intent(out) :: this type(Environment_Wrapper), target, intent(in) :: environment class(Abstract_Num_Particles), intent(in) :: nums_particles(:) type(Component_Wrapper), target, intent(in) :: components(:, :) type(Short_Interactions_Wrapper), target, intent(in) :: short_interactions type(Dipolar_Interactions_Dynamic_Wrapper), target, intent(in) :: & dipolar_interactions_dynamic(:) class(Abstract_Random_Coordinates), intent(in) :: random_positions(:), random_orientation end subroutine Null_construct subroutine Null_destroy(this) class(Null_Particle_Insertion_Method), intent(inout) :: this end subroutine Null_destroy subroutine Null_try(this, observables) class(Null_Particle_Insertion_Method), intent(in) :: this type(Exploring_Observables_Wrapper), intent(inout) :: observables end subroutine Null_try !end implementation Null_Particle_Insertion_Method end module classes_particle_insertion_method