common.f90 Source File


This file depends on

sourcefile~~common.f90~~EfferentGraph sourcefile~common.f90 common.f90 sourcefile~dynamics.f90 dynamics.f90 sourcefile~common.f90->sourcefile~dynamics.f90 sourcefile~kinds.f90 kinds.f90 sourcefile~common.f90->sourcefile~kinds.f90 sourcefile~network.f90 network.f90 sourcefile~common.f90->sourcefile~network.f90 sourcefile~network_io.f90 network_io.f90 sourcefile~common.f90->sourcefile~network_io.f90 sourcefile~dynamics_base.f90 dynamics_base.f90 sourcefile~dynamics.f90->sourcefile~dynamics_base.f90 sourcefile~dynamics_chooser.f90 dynamics_chooser.f90 sourcefile~dynamics.f90->sourcefile~dynamics_chooser.f90 sourcefile~network.f90->sourcefile~kinds.f90 sourcefile~network_io.f90->sourcefile~kinds.f90 sourcefile~network_io.f90->sourcefile~network.f90 sourcefile~dynamics_base.f90->sourcefile~kinds.f90 sourcefile~dynamics_base.f90->sourcefile~network.f90 sourcefile~dynamics_chooser.f90->sourcefile~kinds.f90 sourcefile~dynamics_chooser.f90->sourcefile~dynamics_base.f90 sourcefile~dynamics_hb_oga.f90 dynamics_HB_OGA.f90 sourcefile~dynamics_chooser.f90->sourcefile~dynamics_hb_oga.f90 sourcefile~dynamics_nb_oga.f90 dynamics_NB_OGA.f90 sourcefile~dynamics_chooser.f90->sourcefile~dynamics_nb_oga.f90 sourcefile~dynamics_hb_oga.f90->sourcefile~kinds.f90 sourcefile~dynamics_hb_oga.f90->sourcefile~network.f90 sourcefile~dynamics_hb_oga.f90->sourcefile~dynamics_base.f90 sourcefile~dynamics_nb_oga.f90->sourcefile~kinds.f90 sourcefile~dynamics_nb_oga.f90->sourcefile~network.f90 sourcefile~dynamics_nb_oga.f90->sourcefile~dynamics_base.f90

Source Code

module hyperSIS_program_common_mod
    use hyperSIS_kinds_mod, only: dp, i4
    use hyperSIS_network_mod, only: network_t
    use hyperSIS_network_io_mod, only: network_import
    use hyperSIS_dynamics_mod, only: dyn_parameters_t, net_state_base_t

    use rndgen_mod
    implicit none
    private

    interface
        subroutine proc_net_state_gen(net, state, gen)
            import :: net_state_base_t, rndgen, network_t
            class(network_t), intent(in) :: net
            class(net_state_base_t), intent(inout) :: state
            class(rndgen), intent(inout) :: gen
        end subroutine proc_net_state_gen
        subroutine proc_export_states(net, state, nodes_filename, edges_filename)
            import :: net_state_base_t, rndgen, network_t
            class(network_t), intent(in) :: net
            class(net_state_base_t), intent(inout) :: state
            character(len=*), intent(in) :: nodes_filename, edges_filename
        end subroutine proc_export_states
    end interface

    public :: proc_net_state_gen, proc_export_states
    public :: check_qs_method
    public :: read_network
    public :: set_dyn_params
    public :: set_initial_number_of_infected_nodes
    public :: get_path_prefix
    public :: check_export_nodes_and_edges_state

contains

    subroutine export_nodes_and_edges_state(net, state, nodes_filename, edges_filename)
        class(network_t), intent(in) :: net
        class(net_state_base_t), intent(inout) :: state
        character(len=*), intent(in) :: nodes_filename, edges_filename

        call state%export_nodes_states(net, trim(adjustl(nodes_filename)))
        call state%export_edges_states(net, trim(adjustl(edges_filename)))

    end subroutine

    subroutine do_not_export_nodes_and_edges_state(net, state, nodes_filename, edges_filename)
        class(network_t), intent(in) :: net
        class(net_state_base_t), intent(inout) :: state
        character(len=*), intent(in) :: nodes_filename, edges_filename

    end subroutine

    subroutine check_export_nodes_and_edges_state(export_states, input_export_states)
        procedure(proc_export_states), pointer :: export_states
        logical, intent(in) :: input_export_states

        if (input_export_states) then
            export_states => export_nodes_and_edges_state
        else
            export_states => do_not_export_nodes_and_edges_state
        end if
    end subroutine check_export_nodes_and_edges_state

    !> QS reactivation (randomly chosen node)
    subroutine reactivate_random_node(net, state, gen)
        class(network_t), intent(in) :: net
        class(net_state_base_t), intent(inout) :: state
        class(rndgen), intent(inout) :: gen

        integer(kind=i4) :: node_id

        if (state%get_num_infected() == 0) then
            node_id = gen%int(1, net%num_nodes)
            call state%add_infected(net, node_id)
        end if
    end subroutine reactivate_random_node

    !> Do nothing after
    subroutine do_nothing(net, state, gen)
        class(network_t), intent(in) :: net
        class(net_state_base_t), intent(inout) :: state
        class(rndgen), intent(inout) :: gen
    end subroutine do_nothing

    !> Check which method to use after dynamics step
    subroutine check_qs_method(after_dynamics_step, input_use_qs)
        procedure(proc_net_state_gen), pointer :: after_dynamics_step
        logical, intent(in) :: input_use_qs

        if (input_use_qs) then
            after_dynamics_step => reactivate_random_node
        else
            after_dynamics_step => do_nothing
        end if
    end subroutine

    subroutine set_dyn_params(net, dyn_params, par_b, par_theta)
        class(network_t), intent(in) :: net
        type(dyn_parameters_t), intent(inout) :: dyn_params
        real(kind=dp), intent(in) :: par_b, par_theta

        integer(kind=i4) :: edge_order

        ! Set parameters
        call dyn_params%init(net)

        ! Fill the beta and theta parameters
        do edge_order = 1, net%max_order
            dyn_params%beta(edge_order) = 1.0_dp + par_b * (edge_order -1)
            dyn_params%theta(edge_order) = ceiling(1.0_dp + (edge_order-1) * par_theta)
        end do

    end subroutine set_dyn_params

    subroutine read_network(net, edges_filename)
        type(network_t), intent(inout) :: net
        character(len=*), intent(in) :: edges_filename

        call network_import(net, trim(adjustl(edges_filename)))

    end subroutine read_network

    subroutine set_initial_number_of_infected_nodes(net, inf_fraction, initial_number)
        class(network_t), intent(in) :: net
        real(kind=dp), intent(inout) :: inf_fraction
        integer(kind=i4), intent(inout) :: initial_number

        ! Check initial number of infected nodes
        if (initial_number > 0) then
            inf_fraction = real(initial_number,dp) / real(net%num_nodes,dp)
            if (inf_fraction < 0.0_dp .or. inf_fraction > 1.0_dp) error stop 'Initial number of infected nodes must be between 0 and network size'
        end if

    end subroutine set_initial_number_of_infected_nodes

    !> Build the prefix and remove old files
    function get_path_prefix(tmp_prefix, remove_files) result(prefix)
        character(len=*), intent(in) :: tmp_prefix
        logical, intent(in) :: remove_files
        character(len=:), allocatable :: prefix

        prefix = trim(adjustl(tmp_prefix))

        if (.not. prefix(len(prefix):len(prefix)) == '/') then
            ! Append a trailing underscore if it is not a directory
            prefix = prefix//'_'
        end if

        ! Remove old files with the same prefix
        call system('mkdir -pv '//prefix//'basedir/')
        if (remove_files) call system('rm -vf '//prefix//'*time*.dat')
    end function get_path_prefix

end module hyperSIS_program_common_mod