vdw_potential Subroutine

public subroutine vdw_potential(vdw, V)

Uses

  • proc~~vdw_potential~~UsesGraph proc~vdw_potential vdw_potential module~mod_memory mod_memory proc~vdw_potential->module~mod_memory module~mod_profiling mod_profiling proc~vdw_potential->module~mod_profiling module~mod_neighbor_list mod_neighbor_list proc~vdw_potential->module~mod_neighbor_list module~mod_io mod_io proc~vdw_potential->module~mod_io module~mod_constants mod_constants proc~vdw_potential->module~mod_constants module~mod_memory->module~mod_io module~mod_memory->module~mod_constants iso_c_binding iso_c_binding module~mod_memory->iso_c_binding module~mod_profiling->module~mod_memory module~mod_profiling->module~mod_io module~mod_profiling->module~mod_constants module~mod_neighbor_list->module~mod_memory module~mod_neighbor_list->module~mod_io module~mod_adjacency_mat mod_adjacency_mat module~mod_neighbor_list->module~mod_adjacency_mat module~mod_io->module~mod_constants module~mod_constants->iso_c_binding module~mod_adjacency_mat->module~mod_memory

Compute the dispersion repulsion energy for the whole system using a double loop algorithm

All neighbors done!

Arguments

Type IntentOptional Attributes Name
type(ommp_nonbonded_type), intent(in), target :: vdw

Nonbonded data structure

real(kind=rp), intent(inout) :: V

Potential, result will be added


Calls

proc~~vdw_potential~~CallsGraph proc~vdw_potential vdw_potential proc~time_push time_push proc~vdw_potential->proc~time_push proc~fatal_error fatal_error proc~vdw_potential->proc~fatal_error proc~get_rij0 get_Rij0 proc~vdw_potential->proc~get_rij0 interface~mallocate mallocate proc~vdw_potential->interface~mallocate proc~get_ith_nl get_ith_nl proc~vdw_potential->proc~get_ith_nl proc~get_eij get_eij proc~vdw_potential->proc~get_eij interface~mfree mfree proc~vdw_potential->interface~mfree proc~time_pull time_pull proc~vdw_potential->proc~time_pull proc~time_push->proc~fatal_error proc~mem_stat mem_stat proc~time_push->proc~mem_stat proc~ommp_message ommp_message proc~fatal_error->proc~ommp_message proc~close_output close_output proc~fatal_error->proc~close_output proc~l_alloc2 l_alloc2 interface~mallocate->proc~l_alloc2 proc~r_alloc1 r_alloc1 interface~mallocate->proc~r_alloc1 proc~i_alloc2 i_alloc2 interface~mallocate->proc~i_alloc2 proc~r_alloc3 r_alloc3 interface~mallocate->proc~r_alloc3 proc~i_alloc3 i_alloc3 interface~mallocate->proc~i_alloc3 proc~i_alloc1 i_alloc1 interface~mallocate->proc~i_alloc1 proc~r_alloc2 r_alloc2 interface~mallocate->proc~r_alloc2 proc~l_alloc1 l_alloc1 interface~mallocate->proc~l_alloc1 proc~r_free1 r_free1 interface~mfree->proc~r_free1 proc~i_free3 i_free3 interface~mfree->proc~i_free3 proc~i_free1 i_free1 interface~mfree->proc~i_free1 proc~r_free3 r_free3 interface~mfree->proc~r_free3 proc~l_free2 l_free2 interface~mfree->proc~l_free2 proc~l_free1 l_free1 interface~mfree->proc~l_free1 proc~i_free2 i_free2 interface~mfree->proc~i_free2 proc~r_free2 r_free2 interface~mfree->proc~r_free2 proc~time_pull->proc~fatal_error proc~time_pull->proc~ommp_message proc~time_pull->proc~mem_stat proc~chk_free chk_free proc~r_free1->proc~chk_free proc~chk_alloc chk_alloc proc~l_alloc2->proc~chk_alloc proc~memory_init memory_init proc~l_alloc2->proc~memory_init proc~i_free3->proc~chk_free proc~r_alloc1->proc~chk_alloc proc~r_alloc1->proc~memory_init proc~i_alloc2->proc~chk_alloc proc~i_alloc2->proc~memory_init proc~r_alloc3->proc~chk_alloc proc~r_alloc3->proc~memory_init proc~i_alloc3->proc~chk_alloc proc~i_alloc3->proc~memory_init proc~i_free1->proc~chk_free proc~r_free3->proc~chk_free proc~l_free2->proc~chk_free proc~l_free1->proc~chk_free proc~mem_stat->proc~memory_init proc~close_output->proc~ommp_message proc~i_alloc1->proc~chk_alloc proc~i_alloc1->proc~memory_init proc~r_alloc2->proc~chk_alloc proc~r_alloc2->proc~memory_init proc~l_alloc1->proc~chk_alloc proc~l_alloc1->proc~memory_init proc~i_free2->proc~chk_free proc~r_free2->proc~chk_free proc~chk_free->proc~fatal_error proc~chk_alloc->proc~fatal_error

Called by

proc~~vdw_potential~~CalledByGraph proc~vdw_potential vdw_potential proc~ommp_get_vdw_energy ommp_get_vdw_energy proc~ommp_get_vdw_energy->proc~vdw_potential proc~ommp_get_full_energy ommp_get_full_energy proc~ommp_get_full_energy->proc~ommp_get_vdw_energy program~test_si_potential test_SI_potential program~test_si_potential->proc~ommp_get_vdw_energy proc~c_ommp_get_vdw_energy C_ommp_get_vdw_energy proc~c_ommp_get_vdw_energy->proc~ommp_get_vdw_energy proc~c_ommp_get_full_energy C_ommp_get_full_energy proc~c_ommp_get_full_energy->proc~ommp_get_full_energy

Contents

Source Code


Source Code

    subroutine vdw_potential(vdw, V)
        !! Compute the dispersion repulsion energy for the whole system
        !! using a double loop algorithm

        use mod_io, only : fatal_error
        use mod_profiling, only: time_push, time_pull
        use mod_constants, only: eps_rp
        use mod_memory, only: mallocate, mfree
        use mod_neighbor_list, only: get_ith_nl
        implicit none

        type(ommp_nonbonded_type), intent(in), target :: vdw
        !! Nonbonded data structure
        real(rp), intent(inout) :: V
        !! Potential, result will be added

        integer(ip) :: i, j, jc, l, ipair, ineigh, nthreads, ithread, nn
        real(rp) :: eij, rij0, rij, ci(3), cj(3), s, vtmp
        type(ommp_topology_type), pointer :: top
        procedure(vdw_term), pointer :: vdw_func

        integer(ip), allocatable :: nl_neigh(:,:)
        real(rp), allocatable :: nl_r(:,:)

        integer :: omp_get_num_threads, omp_get_thread_num
        
        call time_push()
        !$omp parallel
        nthreads = omp_get_num_threads()
        !$omp end parallel

        top => vdw%top
        select case(vdw%vdwtype)
            case(OMMP_VDWTYPE_LJ)
                vdw_func => vdw_lennard_jones
            case(OMMP_VDWTYPE_BUF714)
                vdw_func => vdw_buffered_7_14
            case default
                vdw_func => vdw_buffered_7_14
                call fatal_error("Unexpected error in vdw_potential")
        end select

        if(vdw%use_nl) then
            call mallocate('vdw_potential [rneigh]', top%mm_atoms, nthreads, nl_r)
            call mallocate('vdw_potential [nl_neigh]', top%mm_atoms, nthreads, nl_neigh)
        end if

        !$omp parallel do default(shared) reduction(+:v)  schedule(dynamic) &
        !$omp private(i,j,jc,ineigh,ithread,nn,s,ci,cj,ipair,l,Eij,Rij0,Rij,vtmp)
        do i=1, top%mm_atoms
            ithread = omp_get_thread_num() + 1
            if(abs(vdw%vdw_f(i) - 1.0_rp) < eps_rp) then
                ci = top%cmm(:,i)
            else
                ! Scale factors are used only for monovalent atoms, in that
                ! case the vdw center is displaced along the axis connecting
                ! the atom to its neighbour
                if(top%conn(1)%ri(i+1) - top%conn(1)%ri(i) /= 1) then
                    call fatal_error("Scale factors are only expected for &
                                     &monovalent atoms")
                end if
                ineigh = top%conn(1)%ci(top%conn(1)%ri(i))

                ci = top%cmm(:,ineigh) + (top%cmm(:,i) - top%cmm(:,ineigh)) &
                     * vdw%vdw_f(i)
            endif
            
            ! If neighbor list are enabled get the one for the current
            if(vdw%use_nl) call get_ith_nl(vdw%nl, i, top%cmm, &
                                           nl_neigh(:,ithread), &
                                           nl_r(:,ithread), nn)

            do jc=1, top%mm_atoms
                ! If the two atoms aren't neighbors, just skip the loop
                if(vdw%use_nl) then
                    if(jc > nn) exit !! All neighbors done!
                    j = nl_neigh(jc,ithread)
                    if(j <= i) cycle
                else
                    ! Skip all iteration with j <= i
                    if(jc > i) then
                        j = jc
                    else
                        cycle
                    end if
                end if
                ! Compute the screening factor for this pair
                s = 1.0_rp
                do ineigh=1,4
                    ! Look if j is at distance ineigh from i
                    if(any(top%conn(ineigh)%ci(top%conn(ineigh)%ri(i): &
                                               top%conn(ineigh)%ri(i+1)-1) == j)) then
                       
                        s = vdw%vdw_screening(ineigh)
                        ! Exit the loop
                        exit 
                    end if
                end do
                
                if(s > eps_rp) then
                    ipair = -1
                    do l=1, vdw%npair
                        if((vdw%vdw_pair_mask_a(i,l) .and. vdw%vdw_pair_mask_b(j,l)) .or. &
                           (vdw%vdw_pair_mask_a(j,l) .and. vdw%vdw_pair_mask_b(i,l))) then
                            ipair = l
                            exit
                        end if
                    end do

                    if(ipair > 0) then
                        Rij0 = vdw%vdw_pair_r(ipair)
                        eij = vdw%vdw_pair_e(ipair)
                    else
                        Rij0 = get_Rij0(vdw, i, j)
                        eij = get_eij(vdw, i, j)
                    end if
                
                    if(abs(vdw%vdw_f(j) - 1.0_rp) < eps_rp) then
                        cj = top%cmm(:,j)
                    else
                        ! Scale factors are used only for monovalent atoms, in that
                        ! case the vdw center is displaced along the axis connecting
                        ! the atom to its neighbour
                        if(top%conn(1)%ri(j+1) - top%conn(1)%ri(j) /= 1) then
                            call fatal_error("Scale factors are only expected &
                                             & for monovalent atoms")
                        end if
                        ineigh = top%conn(1)%ci(top%conn(1)%ri(j))

                        cj = top%cmm(:,ineigh) + &
                             (top%cmm(:,j) - top%cmm(:,ineigh)) * vdw%vdw_f(j)
                    endif
                    Rij = norm2(ci-cj)
                    if(Rij < eps_rp) then
                        call fatal_error("Requesting non-bonded potential for two atoms &
                                         &placed in the same point, this could be &
                                         &an internal bug or a problem in your input &
                                         &file, please check.")
                    end if
                    
                    vtmp = 0.0_rp
                    call vdw_func(Rij, Rij0, Eij, vtmp)
                    v = v + vtmp*s
                end if
            end do
        end do
        
        if(vdw%use_nl) then
            call mfree('vdw_potential [rneigh]', nl_r)
            call mfree('vdw_potential [nl_neigh]', nl_neigh)
        end if
        call time_pull('VdW potential calculation')
    end subroutine vdw_potential