test_forceconstant_symmetry.f90 Source File

Files Dependent On This One

sourcefile~~test_forceconstant_symmetry.f90~~AfferentGraph sourcefile~test_forceconstant_symmetry.f90 test_forceconstant_symmetry.f90 sourcefile~main.f90 main.f90 sourcefile~test_forceconstant_symmetry.f90->sourcefile~main.f90
Help


Source Code

#include "precompilerdefinitions"
module test_forceconstant_symmetry
use konstanter, only: flyt,lo_sqtol,lo_status
use helpers, only: tochar,lo_sqnorm
use type_crystalstructure, only: lo_crystalstructure
use type_forceconstant_firstorder, only: lo_forceconstant_firstorder
use type_forceconstant_secondorder, only: lo_forceconstant_secondorder
use type_forceconstant_thirdorder, only: lo_forceconstant_thirdorder
use type_forceconstant_fourthorder, only: lo_forceconstant_fourthorder
use type_forcemap, only: lo_forcemap

implicit none
private
public :: test_forceconstant_constraints

contains

subroutine test_forceconstant_constraints(map,fc1,fc2,fc3,fc4,uc)
    !> all the forceconstant metadata
    type(lo_forcemap), intent(in) :: map
    !> firstorder forceconstant
    type(lo_forceconstant_firstorder), intent(in) :: fc1
    !> secondorder forceconstant
    type(lo_forceconstant_secondorder), intent(in) :: fc2
    !> thirdorder forceconstant
    type(lo_forceconstant_thirdorder), intent(in) :: fc3
    !> fourthorder forceconstant
    type(lo_forceconstant_fourthorder), intent(in) :: fc4
    !> crystal structure
    type(lo_crystalstructure), intent(in) :: uc

    ! Start testing a lot of sum rules on the forceconstants, start with the trivial
    ! rotational constraints on the first order forceconstant
    if ( map%firstorder ) then
    rot1: block
        real(flyt), dimension(3,3) :: m0,m1
        real(flyt), dimension(3) :: r
        integer :: a1,i,j

        ! Check the constraints
        m0=0.0_flyt
        m1=0.0_flyt
        do a1=1,uc%na
            r=uc%rcart(:,a1) 
            do i=1,3
            do j=1,3
                m0(i,j)=m0(i,j)+fc1%atom(a1)%m(i)*r(j)
                m1(i,j)=m1(i,j)+fc1%atom(a1)%m(j)*r(i)
            enddo
            enddo
        enddo
        write(*,*) '     firstorder rotational constraint:',abs(sum(m0-m1))
    end block rot1
    endif

    ! Then we have the first+second order
    if ( map%firstorder .and. map%secondorder ) then
    rot2: block
        real(flyt), dimension(3,3,3) :: m0,m1
        real(flyt), dimension(3) :: r
        integer :: a1,i,al,be,gm

        do a1=1,uc%na
            m0=0.0_flyt
            m1=0.0_flyt
            do i=1,fc2%atom(a1)%n
                r=fc2%atom(a1)%pair(i)%r
                do al=1,3
                do be=1,3
                do gm=1,3
                    m0(al,be,gm)=m0(al,be,gm)+fc2%atom(a1)%pair(i)%m(al,be)*r(gm)+fc1%atom(a1)%m(be)*kron(al,gm)
                    m1(al,be,gm)=m1(al,be,gm)+fc2%atom(a1)%pair(i)%m(al,gm)*r(be)+fc1%atom(a1)%m(gm)*kron(al,be)
                enddo
                enddo
                enddo
            enddo
            write(*,*) '   second+first rotational constraint:',sum(m0-m1),'(atom ',tochar(a1),')'
        enddo
    end block rot2
    endif

    ! Pure secondorder rotational
    if ( (map%firstorder .eqv. .false.) .and. map%secondorder ) then
    rot3: block
        real(flyt), dimension(3,3,3) :: m0,m1
        real(flyt), dimension(3) :: r
        integer :: a1,i,al,be,gm

        do a1=1,uc%na
            m0=0.0_flyt
            m1=0.0_flyt
            do i=1,fc2%atom(a1)%n
                r=fc2%atom(a1)%pair(i)%r
                do al=1,3
                do be=1,3
                do gm=1,3
                    m0(al,be,gm)=m0(al,be,gm)+fc2%atom(a1)%pair(i)%m(al,be)*r(gm)
                    m1(al,be,gm)=m1(al,be,gm)+fc2%atom(a1)%pair(i)%m(al,gm)*r(be)
                enddo
                enddo
                enddo
            enddo
            write(*,*) '    secondorder rotational constraint:',abs(sum(m0-m1))
        enddo
    end block rot3
    endif

    if ( map%secondorder .and. map%thirdorder ) then
    rot4: block
        real(flyt), dimension(3,3,3,3) :: m0,m1
        real(flyt), dimension(3) :: r
        real(flyt) :: f0
        integer :: a1,i,j,k,al,be,gm,lm,ii,ti
        integer, dimension(:), allocatable :: di

        do a1=1,uc%na
            lo_allocate( di(fc3%atom(a1)%n))
            di=0
            f0=0.0_flyt
            do i=1,fc2%atom(a1)%n
                r=fc2%atom(a1)%pair(i)%r
                ! get a list if triplets with the same j-vector, to sum over
                ii=0                
                do j=1,fc3%atom(a1)%n
                    if ( lo_sqnorm(r-fc3%atom(a1)%triplet(j)%rv3 ) .lt. lo_sqtol ) then
                        ii=ii+1
                        di(ii)=j
                    endif
                enddo
                ! Now loop and sum over these triplets
                m0=0.0_flyt
                m1=0.0_flyt
                do k=1,ii
                    ti=di(k)
                    do al=1,3
                    do be=1,3
                    do gm=1,3
                    do lm=1,3
                        m0(al,be,gm,lm)=m0(al,be,gm,lm)+&
                            fc2%atom(a1)%pair(i)%m(gm,be)*kron(al,lm)+&
                            fc2%atom(a1)%pair(i)%m(gm,be)*kron(al,lm)+&
                            fc3%atom(a1)%triplet(ti)%m(al,be,gm)*r(lm)
                        m1(al,be,gm,lm)=m1(al,be,gm,lm)+&
                            fc2%atom(a1)%pair(i)%m(lm,be)*kron(al,gm)+&
                            fc2%atom(a1)%pair(i)%m(lm,be)*kron(al,gm)+&
                            fc3%atom(a1)%triplet(ti)%m(al,be,lm)*r(gm)
                    enddo
                    enddo
                    enddo
                    enddo
                enddo
                f0=f0+abs(sum(m0-m1))
            enddo
            lo_deallocate(di)
            write(*,*) '     thirdorder rotational constraint:',a1,f0
        enddo
    end block rot4
    endif

    contains
    function kron(i,j) result(k)
        integer :: i,j,k
        if ( i .eq. j ) then
            k=1
        else
            k=0
        endif
    end function
end subroutine

end module