angle_geomgrad Subroutine

public subroutine angle_geomgrad(bds, grad)

Uses

  • proc~~angle_geomgrad~~UsesGraph proc~angle_geomgrad angle_geomgrad module~mod_constants mod_constants proc~angle_geomgrad->module~mod_constants module~mod_jacobian_mat mod_jacobian_mat proc~angle_geomgrad->module~mod_jacobian_mat iso_c_binding iso_c_binding module~mod_constants->iso_c_binding module~mod_memory mod_memory module~mod_jacobian_mat->module~mod_memory module~mod_memory->module~mod_constants module~mod_memory->iso_c_binding module~mod_io mod_io module~mod_memory->module~mod_io module~mod_io->module~mod_constants

Trigonal center

Arguments

Type IntentOptional Attributes Name
type(ommp_bonded_type), intent(in) :: bds

Bonded potential data structure

real(kind=rp), intent(inout) :: grad(3,bds%top%mm_atoms)

Gradients of bond stretching terms of potential energy


Calls

proc~~angle_geomgrad~~CallsGraph proc~angle_geomgrad angle_geomgrad proc~simple_angle_jacobian simple_angle_jacobian proc~angle_geomgrad->proc~simple_angle_jacobian proc~inplane_angle_jacobian inplane_angle_jacobian proc~angle_geomgrad->proc~inplane_angle_jacobian proc~inplane_angle_jacobian->proc~simple_angle_jacobian proc~cross_product cross_product proc~inplane_angle_jacobian->proc~cross_product proc~versor_der versor_der proc~inplane_angle_jacobian->proc~versor_der proc~vec_skw vec_skw proc~inplane_angle_jacobian->proc~vec_skw

Called by

proc~~angle_geomgrad~~CalledByGraph proc~angle_geomgrad angle_geomgrad proc~link_atom_angle_geomgrad link_atom_angle_geomgrad proc~link_atom_angle_geomgrad->proc~angle_geomgrad proc~ommp_angle_geomgrad ommp_angle_geomgrad proc~ommp_angle_geomgrad->proc~angle_geomgrad proc~ommp_angle_geomgrad->proc~link_atom_angle_geomgrad proc~ommp_full_bnd_geomgrad ommp_full_bnd_geomgrad proc~ommp_full_bnd_geomgrad->proc~angle_geomgrad proc~ommp_full_bnd_geomgrad->proc~link_atom_angle_geomgrad proc~qm_helper_link_atom_geomgrad qm_helper_link_atom_geomgrad proc~qm_helper_link_atom_geomgrad->proc~link_atom_angle_geomgrad proc~c_ommp_full_bnd_geomgrad C_ommp_full_bnd_geomgrad proc~c_ommp_full_bnd_geomgrad->proc~ommp_full_bnd_geomgrad proc~c_ommp_angle_geomgrad C_ommp_angle_geomgrad proc~c_ommp_angle_geomgrad->proc~ommp_angle_geomgrad proc~ommp_full_geomgrad ommp_full_geomgrad proc~ommp_full_geomgrad->proc~ommp_full_bnd_geomgrad proc~ommp_qm_helper_link_atom_geomgrad ommp_qm_helper_link_atom_geomgrad proc~ommp_qm_helper_link_atom_geomgrad->proc~qm_helper_link_atom_geomgrad proc~c_ommp_full_geomgrad C_ommp_full_geomgrad proc~c_ommp_full_geomgrad->proc~ommp_full_geomgrad proc~c_ommp_qm_helper_link_atom_geomgrad C_ommp_qm_helper_link_atom_geomgrad proc~c_ommp_qm_helper_link_atom_geomgrad->proc~ommp_qm_helper_link_atom_geomgrad

Contents

Source Code


Source Code

    subroutine angle_geomgrad(bds, grad)
        use mod_jacobian_mat, only: simple_angle_jacobian, &
                                    inplane_angle_jacobian
        use mod_constants, only: eps_rp

        implicit none

        type(ommp_bonded_type), intent(in) :: bds
        !! Bonded potential data structure
        real(rp), intent(inout) :: grad(3,bds%top%mm_atoms)
        !! Gradients of bond stretching terms of potential energy
        
        real(rp) :: a(3), b(3), c(3), Ja(3), Jb(3), Jc(3), Jx(3), g, thet, &
                    d_theta, aux(3)
        integer(ip) :: i
        logical :: sk_a, sk_b, sk_c, sk_x

        if(.not. bds%use_angle) return
        
        !$omp parallel do default(shared) schedule(dynamic) &
        !$omp private(i,sk_a,sk_b,sk_c,sk_x,a,b,c,aux,thet,d_theta,g,Ja,Jb,Jc,Jx)
        do i=1, bds%nangle
            if(abs(bds%kangle(i)) < eps_rp) cycle
            if(bds%anglety(i) == OMMP_ANG_SIMPLE .or. &
               bds%anglety(i) == OMMP_ANG_H0 .or. &
               bds%anglety(i) == OMMP_ANG_H1 .or. &
               bds%anglety(i) == OMMP_ANG_H2) then
                if(bds%top%use_frozen) then
                    sk_a = bds%top%frozen(bds%angleat(1,i))
                    sk_b = bds%top%frozen(bds%angleat(2,i))
                    sk_c = bds%top%frozen(bds%angleat(3,i))
                    if(sk_a .and. sk_b .and. sk_c) cycle
                else
                    sk_a = .false.
                    sk_b = .false.
                    sk_c = .false.
                end if

                a = bds%top%cmm(:, bds%angleat(1,i)) 
                b = bds%top%cmm(:, bds%angleat(2,i))
                c = bds%top%cmm(:, bds%angleat(3,i))
                call simple_angle_jacobian(a, b, c, thet, Ja, Jb, Jc)
                d_theta = thet - bds%eqangle(i) 
           
                g = bds%kangle(i) * d_theta * (2.0 &
                                               + 3.0 * bds%angle_cubic * d_theta &
                                               + 4.0 * bds%angle_quartic * d_theta**2 &
                                               + 5.0 * bds%angle_pentic * d_theta**3 &
                                               + 6.0 * bds%angle_sextic * d_theta**4)

                if(.not. sk_a) then
                    !$omp atomic update
                    grad(1,bds%angleat(1,i)) = grad(1,bds%angleat(1,i)) + g * Ja(1)
                    !$omp atomic update
                    grad(2,bds%angleat(1,i)) = grad(2,bds%angleat(1,i)) + g * Ja(2)
                    !$omp atomic update
                    grad(3,bds%angleat(1,i)) = grad(3,bds%angleat(1,i)) + g * Ja(3)
                end if

                if(.not. sk_b) then
                    !$omp atomic update
                    grad(1,bds%angleat(2,i)) = grad(1,bds%angleat(2,i)) + g * Jb(1)
                    !$omp atomic update
                    grad(2,bds%angleat(2,i)) = grad(2,bds%angleat(2,i)) + g * Jb(2)
                    !$omp atomic update
                    grad(3,bds%angleat(2,i)) = grad(3,bds%angleat(2,i)) + g * Jb(3)
                end if

                if(.not. sk_c) then
                    !$omp atomic update
                    grad(1,bds%angleat(3,i)) = grad(1,bds%angleat(3,i)) + g * Jc(1)
                    !$omp atomic update
                    grad(2,bds%angleat(3,i)) = grad(2,bds%angleat(3,i)) + g * Jc(2)
                    !$omp atomic update
                    grad(3,bds%angleat(3,i)) = grad(3,bds%angleat(3,i)) + g * Jc(3)
                end if
            else if(bds%anglety(i) == OMMP_ANG_INPLANE .or. &
                    bds%anglety(i) == OMMP_ANG_INPLANE_H0 .or. &
                    bds%anglety(i) == OMMP_ANG_INPLANE_H1) then
                
                if(bds%top%use_frozen) then
                    sk_a = bds%top%frozen(bds%angleat(1,i))
                    sk_b = bds%top%frozen(bds%angleat(2,i))
                    sk_c = bds%top%frozen(bds%angleat(3,i))
                    sk_x = bds%top%frozen(bds%angauxat(i))
                    if(sk_a .and. sk_b .and. sk_c .and. sk_x) cycle
                else
                    sk_a = .false.
                    sk_b = .false.
                    sk_c = .false.
                    sk_x = .false.
                end if
                
                a = bds%top%cmm(:, bds%angleat(1,i))
                b = bds%top%cmm(:, bds%angleat(2,i)) !! Trigonal center
                c = bds%top%cmm(:, bds%angleat(3,i))

                aux = bds%top%cmm(:, bds%angauxat(i))
                
                call inplane_angle_jacobian(a, b, c, aux, thet, Ja, Jb, Jc, Jx)
                d_theta = thet - bds%eqangle(i) 
                g = bds%kangle(i) * d_theta * (2.0 &
                                               + 3.0 * bds%angle_cubic * d_theta &
                                               + 4.0 * bds%angle_quartic * d_theta**2 &
                                               + 5.0 * bds%angle_pentic * d_theta**3 &
                                               + 6.0 * bds%angle_sextic * d_theta**4)
                if(.not. sk_a) then
                    !$omp atomic update
                    grad(1,bds%angleat(1,i)) = grad(1,bds%angleat(1,i)) + g * Ja(1)
                    !$omp atomic update
                    grad(2,bds%angleat(1,i)) = grad(2,bds%angleat(1,i)) + g * Ja(2)
                    !$omp atomic update
                    grad(3,bds%angleat(1,i)) = grad(3,bds%angleat(1,i)) + g * Ja(3)
                end if

                if(.not. sk_b) then
                    !$omp atomic update
                    grad(1,bds%angleat(2,i)) = grad(1,bds%angleat(2,i)) + g * Jb(1)
                    !$omp atomic update
                    grad(2,bds%angleat(2,i)) = grad(2,bds%angleat(2,i)) + g * Jb(2)
                    !$omp atomic update
                    grad(3,bds%angleat(2,i)) = grad(3,bds%angleat(2,i)) + g * Jb(3)
                end if

                if(.not. sk_c) then
                    !$omp atomic update
                    grad(1,bds%angleat(3,i)) = grad(1,bds%angleat(3,i)) + g * Jc(1)
                    !$omp atomic update
                    grad(2,bds%angleat(3,i)) = grad(2,bds%angleat(3,i)) + g * Jc(2)
                    !$omp atomic update
                    grad(3,bds%angleat(3,i)) = grad(3,bds%angleat(3,i)) + g * Jc(3)
                end if

                if(.not. sk_x) then
                    !$omp atomic update
                    grad(1,bds%angauxat(i)) = grad(1,bds%angauxat(i)) + g * Jx(1)
                    !$omp atomic update
                    grad(2,bds%angauxat(i)) = grad(2,bds%angauxat(i)) + g * Jx(2)
                    !$omp atomic update
                    grad(3,bds%angauxat(i)) = grad(3,bds%angauxat(i)) + g * Jx(3)
                end if
            end if
        end do
    end subroutine angle_geomgrad