assign_strbnd Subroutine

public subroutine assign_strbnd(bds, prm_buf)

Uses

  • proc~~assign_strbnd~~UsesGraph proc~assign_strbnd assign_strbnd module~mod_bonded mod_bonded proc~assign_strbnd->module~mod_bonded module~mod_constants mod_constants proc~assign_strbnd->module~mod_constants module~mod_memory mod_memory proc~assign_strbnd->module~mod_memory module~mod_bonded->module~mod_memory module~mod_topology mod_topology module~mod_bonded->module~mod_topology module~mod_io mod_io module~mod_bonded->module~mod_io iso_c_binding iso_c_binding module~mod_constants->iso_c_binding module~mod_memory->module~mod_constants module~mod_memory->iso_c_binding module~mod_memory->module~mod_io module~mod_topology->module~mod_memory module~mod_adjacency_mat mod_adjacency_mat module~mod_topology->module~mod_adjacency_mat module~mod_io->module~mod_constants module~mod_adjacency_mat->module~mod_memory

No parameters are defined, nothing to do.

Arguments

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

Bonded potential data structure

character(len=OMMP_STR_CHAR_MAX), intent(in) :: prm_buf(:)

Char buffer containing the prm file loaded in RAM


Calls

proc~~assign_strbnd~~CallsGraph proc~assign_strbnd assign_strbnd proc~read_atom_cards read_atom_cards proc~assign_strbnd->proc~read_atom_cards interface~mallocate mallocate proc~assign_strbnd->interface~mallocate proc~tokenize tokenize proc~assign_strbnd->proc~tokenize proc~isint isint proc~assign_strbnd->proc~isint proc~fatal_error fatal_error proc~assign_strbnd->proc~fatal_error proc~isreal isreal proc~assign_strbnd->proc~isreal proc~strbnd_init strbnd_init proc~assign_strbnd->proc~strbnd_init interface~mfree mfree proc~assign_strbnd->interface~mfree proc~read_atom_cards->interface~mallocate proc~read_atom_cards->proc~tokenize proc~read_atom_cards->proc~isint proc~read_atom_cards->proc~fatal_error proc~read_atom_cards->interface~mfree proc~count_substr_occurence count_substr_occurence proc~read_atom_cards->proc~count_substr_occurence proc~i_alloc1 i_alloc1 interface~mallocate->proc~i_alloc1 proc~i_alloc3 i_alloc3 interface~mallocate->proc~i_alloc3 proc~l_alloc2 l_alloc2 interface~mallocate->proc~l_alloc2 proc~r_alloc3 r_alloc3 interface~mallocate->proc~r_alloc3 proc~i_alloc2 i_alloc2 interface~mallocate->proc~i_alloc2 proc~r_alloc1 r_alloc1 interface~mallocate->proc~r_alloc1 proc~r_alloc2 r_alloc2 interface~mallocate->proc~r_alloc2 proc~l_alloc1 l_alloc1 interface~mallocate->proc~l_alloc1 proc~ommp_message ommp_message proc~fatal_error->proc~ommp_message proc~close_output close_output proc~fatal_error->proc~close_output proc~strbnd_init->interface~mallocate proc~l_free1 l_free1 interface~mfree->proc~l_free1 proc~i_free2 i_free2 interface~mfree->proc~i_free2 proc~r_free3 r_free3 interface~mfree->proc~r_free3 proc~r_free2 r_free2 interface~mfree->proc~r_free2 proc~i_free1 i_free1 interface~mfree->proc~i_free1 proc~r_free1 r_free1 interface~mfree->proc~r_free1 proc~l_free2 l_free2 interface~mfree->proc~l_free2 proc~i_free3 i_free3 interface~mfree->proc~i_free3 proc~chk_free chk_free proc~l_free1->proc~chk_free proc~i_free2->proc~chk_free proc~r_free3->proc~chk_free proc~chk_alloc chk_alloc proc~i_alloc1->proc~chk_alloc proc~memory_init memory_init proc~i_alloc1->proc~memory_init proc~i_alloc3->proc~chk_alloc proc~i_alloc3->proc~memory_init proc~l_alloc2->proc~chk_alloc proc~l_alloc2->proc~memory_init proc~r_free2->proc~chk_free proc~close_output->proc~ommp_message proc~i_free1->proc~chk_free proc~r_free1->proc~chk_free proc~r_alloc3->proc~chk_alloc proc~r_alloc3->proc~memory_init proc~i_alloc2->proc~chk_alloc proc~i_alloc2->proc~memory_init proc~r_alloc1->proc~chk_alloc proc~r_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~l_free2->proc~chk_free proc~i_free3->proc~chk_free proc~chk_free->proc~fatal_error proc~chk_alloc->proc~fatal_error

Called by

proc~~assign_strbnd~~CalledByGraph proc~assign_strbnd assign_strbnd proc~mmpol_init_from_xyz mmpol_init_from_xyz proc~mmpol_init_from_xyz->proc~assign_strbnd proc~ommp_system_from_qm_helper ommp_system_from_qm_helper proc~ommp_system_from_qm_helper->proc~assign_strbnd proc~ommp_init_xyz ommp_init_xyz proc~ommp_init_xyz->proc~mmpol_init_from_xyz proc~c_ommp_system_from_qm_helper C_ommp_system_from_qm_helper proc~c_ommp_system_from_qm_helper->proc~ommp_system_from_qm_helper proc~c_ommp_init_xyz C_ommp_init_xyz proc~c_ommp_init_xyz->proc~ommp_init_xyz

Contents

Source Code


Source Code

    subroutine assign_strbnd(bds, prm_buf)
        use mod_memory, only: mallocate, mfree
        use mod_bonded, only: strbnd_init 
        use mod_constants, only: kcalmol2au, angstrom2au
        
        implicit none
       
        type(ommp_bonded_type), intent(inout) :: bds
        !! Bonded potential data structure
        character(len=OMMP_STR_CHAR_MAX), intent(in) :: prm_buf(:)
        !! Char buffer containing the prm file loaded in RAM

        integer(ip) :: il, i, j, tokb, toke, isb, nstrbnd, &
                       cla, clb, clc, a, b, c, jc, jb, maxsb, &
                       l1a, l1b, l2a, l2b
        character(len=OMMP_STR_CHAR_MAX) :: line, errstring
        integer(ip), allocatable :: classa(:), classb(:), classc(:), sbtmp(:), &
                                    sbattmp(:, :), at2bnd(:), at2ang(:)
        real(rp), allocatable :: k1(:), k2(:)
        logical :: done, thet_done, l1_done, l2_done
        type(ommp_topology_type), pointer :: top

        top => bds%top

        if(.not. top%atclass_initialized .or. .not. top%atz_initialized) then
            call read_atom_cards(top, prm_buf)
        end if
        
        ! Read all the lines of file just to count how large vector should be 
        ! allocated
        nstrbnd = 0
        do il=1, size(prm_buf) 
            line = prm_buf(il)
            if(line(:7) == 'strbnd ') nstrbnd = nstrbnd + 1
        end do

        maxsb = (top%conn(2)%ri(top%mm_atoms+1)-1) / 2
        call mallocate('assign_strbnd [classa]', nstrbnd, classa)
        call mallocate('assign_strbnd [classb]', nstrbnd, classb)
        call mallocate('assign_strbnd [classc]', nstrbnd, classc)
        call mallocate('assign_strbnd [eqang]', nstrbnd, k1)
        call mallocate('assign_strbnd [kang]', nstrbnd, k2)
        call mallocate('assign_strbnd [sbtmp]', maxsb, sbtmp)
        call mallocate('assign_strbnd [sbattmp]', 3_ip, maxsb, sbattmp)
        call mallocate('assign_strbnd [at2bnd]', top%mm_atoms, at2bnd)
        call mallocate('assign_strbnd [at2ang]', top%mm_atoms, at2ang)

        ! Restart the reading from the beginning to actually save the parameters
        isb = 1
        i=1
        do il=1, size(prm_buf) 
            line = prm_buf(il)
           
            if(line(:7) == 'strbnd ') then
                tokb = 8
                toke = tokenize(line, tokb)
                if(.not. isint(line(tokb:toke))) then
                    write(errstring, *) "Wrong STRBND card"
                    call fatal_error(errstring)
                end if
                read(line(tokb:toke), *) classa(isb)

                tokb = toke + 1
                toke = tokenize(line, tokb)
                if(.not. isint(line(tokb:toke))) then
                    write(errstring, *) "Wrong STRBND card"
                    call fatal_error(errstring)
                end if
                read(line(tokb:toke), *) classb(isb)
                
                tokb = toke + 1
                toke = tokenize(line, tokb)
                if(.not. isint(line(tokb:toke))) then
                    write(errstring, *) "Wrong STRBND card"
                    call fatal_error(errstring)
                end if
                read(line(tokb:toke), *) classc(isb)

                tokb = toke + 1
                toke = tokenize(line, tokb)
                if(.not. isreal(line(tokb:toke))) then
                    write(errstring, *) "Wrong STRBND card"
                    call fatal_error(errstring)
                end if
                read(line(tokb:toke), *) k1(isb)

                tokb = toke + 1
                toke = tokenize(line, tokb)
                if(.not. isreal(line(tokb:toke))) then
                    write(errstring, *) "Wrong STRBND card"
                    call fatal_error(errstring)
                end if
                read(line(tokb:toke), *) k2(isb)

                isb = isb + 1
            end if
            i = i+1
        end do
        
        isb = 1
        do a=1, top%mm_atoms
            cla = top%atclass(a)
            do jb=top%conn(2)%ri(a), top%conn(2)%ri(a+1)-1
                b = top%conn(2)%ci(jb)
                if(a > b) cycle
                clb = top%atclass(b)
                
                do jc=top%conn(1)%ri(a), top%conn(1)%ri(a+1)-1
                    c = top%conn(1)%ci(jc)
                    if(all(top%conn(1)%ci(top%conn(1)%ri(b):&
                                          top%conn(1)%ri(b+1)-1) /= c)) cycle
                    ! There is an angle in the form A-C-B
                    clc = top%atclass(c)
                    done = .false.

                    do j=1, nstrbnd
                        if((cla == classa(j) &
                            .and. clb == classc(j) &
                            .and. clc == classb(j)) .or. &
                           (clb == classa(j) &
                            .and. cla == classc(j) &
                            .and. clc == classb(j))) then
                            sbattmp(1,isb) = a
                            sbattmp(2,isb) = c
                            sbattmp(3,isb) = b
                            if(cla == classa(j)) then
                                ! Assign the correct k to each bond stretching!
                                sbtmp(isb) = j
                            else
                                sbtmp(isb) = -j
                            end if
                            isb = isb + 1
                            exit
                        end if
                    end do
                end do
            end do
        end do

        call strbnd_init(bds, isb-1)
        if(isb-1 < 1) then
            !! No parameters are defined, nothing to do.
            return
        end if

        at2bnd(1) = 1
        do i=1, top%mm_atoms-1
            at2bnd(i+1) = at2bnd(i)
            do j=top%conn(1)%ri(i), top%conn(1)%ri(i+1)-1
                if(i < top%conn(1)%ci(j)) then
                    at2bnd(i+1) = at2bnd(i+1) + 1
                end if
            end do
        end do
            
        at2ang = 0
        do j=1, size(bds%angleat, 2)
          if(at2ang(bds%angleat(1,j)) == 0) at2ang(bds%angleat(1,j)) = j
        end do

        !$omp parallel do default(shared) schedule(dynamic) &
        !$omp private(i,j,l1a,l1b,l2a,l2b,l1_done,l2_done,thet_done)
        do i=1, isb-1
            ! First assign the parameters
            bds%strbndat(:,i) = sbattmp(:,i)
            j = abs(sbtmp(i))
            if(sbtmp(i) > 0) then
                bds%strbndk1(i) = k1(j) * kcalmol2au / angstrom2au
                bds%strbndk2(i) = k2(j) * kcalmol2au / angstrom2au
            else
                bds%strbndk1(i) = k2(j) * kcalmol2au / angstrom2au
                bds%strbndk2(i) = k1(j) * kcalmol2au / angstrom2au
            end if
            
            l1a = min(bds%strbndat(1,i), bds%strbndat(2,i))
            l1b = max(bds%strbndat(1,i), bds%strbndat(2,i))
            l2a = min(bds%strbndat(3,i), bds%strbndat(2,i))
            l2b = max(bds%strbndat(3,i), bds%strbndat(2,i))
           
            ! Now search for the corresponding bond and angle parameters to
            ! set the equilibrium distances and angle
            l1_done = .false.
            l2_done = .false.
            thet_done = .false.

            do j=at2bnd(l1a), size(bds%bondat, 2)
                if(l1a == bds%bondat(1,j) .and. l1b == bds%bondat(2,j)) then
                    l1_done = .true.
                    bds%strbndl10(i) = bds%l0bond(j)
                    exit
                end if
            end do

            do j=at2bnd(l2a), size(bds%bondat, 2)
                if(l2a == bds%bondat(1,j) .and. l2b == bds%bondat(2,j)) then
                    l2_done = .true.
                    bds%strbndl20(i) = bds%l0bond(j)
                    exit
                end if
            end do
            
            do j=at2ang(bds%strbndat(1,i)), size(bds%angleat, 2)
                if(all(bds%strbndat(:,i) == bds%angleat(:,j))) then
                    thet_done = .true.
                    bds%strbndthet0(i) = bds%eqangle(j)
                    exit
                end if
            end do
            
            if(.not.(l1_done .and. l2_done .and. thet_done)) then
                call fatal_error("Ill-defined stretch-bending cross term")
            end if
        end do

        call mfree('assign_strbnd [classa]', classa)
        call mfree('assign_strbnd [classb]', classb)
        call mfree('assign_strbnd [classc]', classc)
        call mfree('assign_strbnd [eqang]', k1)
        call mfree('assign_strbnd [kang]', k2)
        call mfree('assign_strbnd [sbtmp]', sbtmp)
        call mfree('assign_strbnd [sbattmp]', sbattmp)
        call mfree('assign_strbnd [at2bnd]', at2bnd)
        call mfree('assign_strbnd [at2ang]', at2ang)
    
    end subroutine assign_strbnd