Физическая программная археология

18e9fd291c71b864d1e356c8e5f19c5a.jpg
program NMR_rarefied
implicit none
real(8), dimension(:,:,:), allocatable :: dip, a1 ! dipolar interaction and additional
real(8), dimension(:,:), allocatable :: sx, sy, sz, sI, sp, sm, o, u, v, w, & ! spin matrices and additional
                                        x, y, z, r, & ! r = {x, y, z}, distances between magnetic ions (MI)
                                        J0, & ! exchange interactions
                                        ReH, ImH, b, q, q2, & ! Hamiltonian parts and additional
                                        d0, d1 ! for Kronecker product procedure
real(8), dimension(:), allocatable :: x1, y1, z1, & ! coordinates of MI
                                      RT2, RT3, RT4, RT1, sum_sqr, & ! for rotation method
                                      histp, hist ! partial and averaged histogram
logical, dimension(:), allocatable :: mask1
real(8), dimension(1:3) :: e1, e2, e3, d ! lattice basis
real(8), dimension(1) :: i11, k11
real(8) S, eps, & ! spin, precision
        alpha, beta, pd, & ! parameters of exchange (A*exp(-B*r)) and dipolar interaction (pd = (hbar*gamma)^2)
        res, & ! histogram resolution
        s1, s2, c1, c2, & ! rotation parameters
        m, e, c
integer N, N1, N2, N3, NN, Nres, & ! total number of MI and their concentration
        i, j, k, i1, j1, k1, t, m3, ms, l, r1, ires, & ! counters
        f, fn, & ! 2S+1, (2S+1)^N
        nh ! number of histogram bars
logical noconv
        
!----------------------------------------------------
! read and set the initial parameters
!----------------------------------------------------
open(1, file="init.txt", form="formatted", action="read")
read(1,*) eps, S, N, N1, N2, N3, nh, alpha, beta, pd, &
          e1, e2, e3, res, Nres
close(1)

f = 2*S + 1; fn = f**N
call RANDOM_SEED()

!----------------------------------------------------
! memory alloc
!----------------------------------------------------
allocate(sx(1:f,1:f)); allocate(sy(1:f,1:f)); allocate(sz(1:f,1:f))
allocate(sI(1:f,1:f)); allocate(sp(1:f,1:f)); allocate(sm(1:f,1:f))
allocate(o(1:f,1:f)); allocate(v(1:f,1:f)); allocate(w(1:f,1:f))
allocate(dip(1:6,1:N,1:N)); allocate(J0(1:N,1:N)); allocate(u(1:N,1:N))
allocate(x(1:N,1:N)); allocate(y(1:N,1:N)); allocate(z(1:N,1:N))
allocate(r(1:N,1:N))
allocate(x1(1:N)); allocate(y1(1:N)); allocate(z1(1:N))
allocate(ReH(1:fn,1:fn)); allocate(ImH(1:fn,1:fn))
allocate(b(1:fn,1:fn)); allocate(q(1:fn,1:fn)); allocate(q2(1:fn,1:fn))
allocate(mask1(1:fn))
allocate(a1(1:N,1:f,1:f))
allocate(RT1(1:fn)); allocate(RT2(1:fn))
allocate(RT3(1:fn)); allocate(RT4(1:fn))
allocate(sum_sqr(1:fn))
allocate(histp(1:nh)); allocate(hist(1:nh))

hist = 0.0d0

open(1, file="MI_coords.txt", form="formatted", action="write")
open(2,file="E.txt", form="formatted", action="write")

!----------------------------------------------------
! spin matrices initialization
!----------------------------------------------------
sx = 0.0d0; sy = 0.0d0; sz = 0.0d0; sp = 0.0d0; sm = 0.0d0; sI = 0.0d0
do i = 1, f, 1
  sI(i,i) = 1.0d0
  sz(i,i) = S - (i-1)
  if(i <= f-1) sp(i,i+1) = dsqrt(dabs(S*(S+1.0d0) - real(i*(i+1))))
enddo
sm = transpose(sp)
sx = 0.5d0*(sp + sm)
sy = 0.5d0*(sm - sp)

!----------------------------------------------------
ires = 1
REALIZATION: do while(ires <= Nres)
!----------------------------------------------------
! generation of MI distribution in lattice
!----------------------------------------------------
  x = 0.0d0; y = 0.0d0; z = 0.0d0; r = 0.0d0
  COORDS: do
  ! MI coordinates
    do i = 1, N, 1
      call RANDOM_NUMBER(d)
      d(1) = floor(d(1)*N1); d(2) = floor(d(2)*N2); d(3) = floor(d(3)*N3)
      x1(i) = d(1)*e1(1) + d(2)*e2(1) + d(3)*e3(1)
      y1(i) = d(1)*e1(2) + d(2)*e2(2) + d(3)*e3(2)
      z1(i) = d(1)*e1(3) + d(2)*e2(3) + d(3)*e3(3)
    enddo
  
  ! MI distances
    do i = 1, N, 1
      do j = 1, N, 1
        if(i /= j)then
          x(i,j) = x1(i) - x1(j)
          y(i,j) = y1(i) - y1(j)
          z(i,j) = z1(i) - z1(j)
          ! full interaction
          r(i,j) = dsqrt( x(i,j)**2 + y(i,j)**2 + z(i,j)**2 )
        endif
      enddo
      r(i,i) = 1.0d0
    enddo

    if(minval(r) > 0.5d0)exit
  enddo COORDS

  ! write MI coordinated
  write(1,'(A,I8)') "Realization ", ires
  do i = 1, N, 1
    write(1,'(I6, 3E20.6E3)') i, x1(i), y1(i), z1(i)
  enddo
  write(1,*)
  
!----------------------------------------------------
! pair interaction evaluation
!----------------------------------------------------
  ! isotropic part
  J0 = alpha*dexp(-beta*r)
  dip(1,:,:) = J0 + pd * (1.0d0 - 3.0d0*x**2 / r**2) / r**3
  dip(2,:,:) = J0 + pd * (1.0d0 - 3.0d0*y**2 / r**2) / r**3
  dip(3,:,:) = J0 + pd * (1.0d0 - 3.0d0*z**2 / r**2) / r**3
  ! anisotropic part
  dip(4,:,:) = -3.0d0*pd*x*y / r**5
  dip(5,:,:) = -3.0d0*pd*x*z / r**5
  dip(6,:,:) = -3.0d0*pd*y*z / r**5

!----------------------------------------------------
! real part of the Hamiltonian matrix
!----------------------------------------------------
  o = sz; call p78()
  ReH = b
  u = dip(1,:,:); v = sx; w = sx; call p56()
  u = dip(2,:,:); v = sy; w = -sy; call p56()
  u = dip(3,:,:); v = sz; w = sz; call p56()
  u = dip(5,:,:); v = sx; w = sz; call p56()
  q = ReH; ReH = 0.0d0

!----------------------------------------------------
! imaginary part of the Hamiltonian matrix
!----------------------------------------------------
  u = dip(4,:,:); v = sx; w = sy; call p56()
  u = dip(6,:,:); v = sy; w = sz; call p56()
  ImH = ReH; ReH = q

!----------------------------------------------------
! Diagonalization of the Hamiltonian matrix
!----------------------------------------------------
  t = 0; q = 0.0d0; q2 = 0.0d0
  do i = 1, fn, 1
    q(i,i) = 1.0d0
  enddo

  ! sum of squares by strings
  sum_sqr = 0.0d0
  do i = 1, fn, 1
    do j = 1, fn, 1
      if(i /= j) sum_sqr(i) = sum_sqr(i) + (ReH(i,j)**2 + ImH(i,j)**2)
    enddo
  enddo
  noconv = .false.
  
  ! rotation iterations
  ROTATION: do
    i11 = maxloc(sum_sqr); i1 = i11(1)
    mask1 = .true.; mask1(i1) = .false.
    k11 = maxloc(ReH(i1,:)**2 + ImH(i1,:)**2, mask=mask1); k1 = k11(1)
    m = maxval(ReH(i1,:)**2 + ImH(i1,:)**2, mask=mask1)
  
    if(m < eps)exit 
    if(t == 100000)then
      noconv = .true.
      exit
    endif

    mask1(k1) = .false.
    sum_sqr = sum_sqr - sum(ReH(:,i1)**2 + ImH(:,i1)**2, mask=mask1)
    
    i = i1; k = k1
  
    ! rotation parameters
    e = dabs(ReH(i,i) - ReH(k,k)) / dsqrt( (ReH(i,i) - ReH(k,k))**2 + 4.0d0*(ReH(i,k)**2 + ImH(i,k)**2) )
    s1 = dsqrt( 0.5d0*(1.0d0 - e) ); c1 = dsqrt( 0.5d0*(1.0d0 + e) )
    if(ReH(i,i) /= ReH(k,k)) s1 = sign(s1, ReH(i,i) - ReH(k,k))
    if(ReH(i,k) /= 0.0d0) s1 = sign(s1, ReH(i,k))
  
    s2 = ImH(i,k) / dsqrt(ReH(i,k)**2 + ImH(i,k)**2)
    if(ReH(i,k) /= 0.0d0) s2 = sign(s2, ReH(i,k))
  
    c2 = s1 * dabs(ReH(i,k)) / dsqrt(ReH(i,k)**2 + ImH(i,k)**2)
    s1 = s1*s2
  
    ! make the rotations
    RT1 = c1*q(:,i) + c2*q(:,k) + s1*q2(:,k)
    RT2 = -c2*q(:,i) + c1*q(:,k) + s1*q2(:,i)
    RT3 = -s1*q(:,k) + c1*q2(:,i) + c2*q2(:,k)
    RT4 = -s1*q(:,i) - c2*q2(:,i) + c1*q2(:,k)
    
    q(:,i) = RT1; q(:,k) = RT2; q2(:,i) = RT3; q2(:,k) = RT4

    RT1 = c1*ReH(:,i) + c2*ReH(:,k) + s1*ImH(:,k)
    RT2 = -c2*ReH(:,i) + c1*ReH(:,k) + s1*ImH(:,i)
    RT3 = -s1*ReH(:,k) + c1*ImH(:,i) + c2*ImH(:,k)
    RT4 = -s1*ReH(:,i) - c2*ImH(:,i) + c1*ImH(:,k)

    ReH(:,i) = RT1; ReH(:,k) = RT2; ImH(:,i) = RT3; ImH(:,k) = RT4

    RT1 = c1*ReH(i,:) + c2*ReH(k,:) - s1*ImH(k,:)
    RT2 = -c2*ReH(i,:) + c1*ReH(k,:) - s1*ImH(i,:)
    RT3 = c1*ImH(i,:) + c2*ImH(k,:) + s1*ReH(k,:)
    RT4 = -c2*ImH(i,:) + c1*ImH(k,:) + s1*ReH(i,:)

    ReH(i,:) = RT1; ReH(k,:) = RT2; ImH(i,:) = RT3; ImH(k,:) = RT4
    
    t = t+1
  
    mask1 = .true.; mask1(i1) = .false.; mask1(k1) = .false.
    sum_sqr = sum_sqr + sum(ReH(:,i1)**2 + ImH(:,i1)**2, mask = mask1) &
              + sum(ReH(:,k1)**2 + ImH(:,k1)**2, mask = mask1)
   
    mask1 = .true.; mask1(i1) = .false.
    sum_sqr(i1) = sum(ReH(i1,:)**2 + ImH(i1,:)**2, mask = mask1)
  
    mask1 = .true.; mask1(k1) = .false.
    sum_sqr(k1) = sum(ReH(k1,:)**2 + ImH(k1,:)**2, mask = mask1)
  enddo ROTATION

!----------------------------------------------------
  if(noconv)then
    print *, "Realization does not converge"
  else
    print *,ires, ", Rotation finished at ", t, " iterations"
!----------------------------------------------------
! eigenvalues
!----------------------------------------------------
    do i = 1, fn, 1
      RT1(i) = ReH(i,i)
    enddo

    ! write energy
    write(2,'(A,I8)') "Realization ", ires
    do i = 1, fn, 1
      write(2,'(I6,E20.6E3)') i, RT1(i)
    enddo
    write(2,*)

!----------------------------------------------------
! evaluate probabilities and histogram amplitudes
!----------------------------------------------------
    histp = 0.0d0
    o = sx

    call p78()

    ReH = matmul(b, q); ImH = matmul(b, q2)
    d1 = transpose(q); b = transpose(q2)

    q = matmul(d1, ReH) + matmul(b, ImH)
    q2 = matmul(d1, ImH) - matmul(b, ReH)

    do i = 1, fn, 1
      do j = 1, fn, 1
        c = q(i,j)**2 + q2(i,j)**2
        k = floor(1.0d0 + dabs(RT1(i) - RT1(j)) / res)
        if(k <= nh) histp(k) = histp(k) + c
      enddo
    enddo

    hist = hist + histp
    ires = ires + 1  
  endif
enddo REALIZATION
!----------------------------------------------------

open(3,file="hist.txt", form="formatted", action="write")
do i = 1, nh, 1
  write(3,'(2E20.6E3)') i*res, hist(i) / Nres
enddo
close(1); close(2); close(3)

print *,"Histogram is written at hist.txt"

!----------------------------------------------------
! memory clear
!----------------------------------------------------
deallocate(sx); deallocate(sy); deallocate(sz); deallocate(sI)
deallocate(o); deallocate(v); deallocate(w)
deallocate(ReH); deallocate(ImH); deallocate(b); deallocate(q); deallocate(q2)
deallocate(mask1); deallocate(a1)
deallocate(RT1); deallocate(RT2); deallocate(RT3); deallocate(RT4); deallocate(sum_sqr)
deallocate(histp); deallocate(hist)
deallocate(dip); deallocate(J0); deallocate(sp); deallocate(sm)
deallocate(x1); deallocate(y1); deallocate(z1)
deallocate(x); deallocate(y); deallocate(z); deallocate(r); deallocate(d1)

contains
!----------------------------------------------------
! Kronecker product of one spin and N-1 identity
!----------------------------------------------------
subroutine p78()
  b = 0.0d0

  do k = 1, N, 1
    a1(k,:,:) = sI
  enddo
  
  do k = 1, N, 1
    a1(k,:,:) = o
    call p34()
    a1(k,:,:) = sI
    b = b + d1
  enddo
end subroutine p78

!----------------------------------------------------
! Kronecker product of two spin and N-2 identity
!----------------------------------------------------
subroutine p56()
  do k = 1, N, 1
    do t = 1, N, 1
      if(k /= t)then
        a1(k,:,:) = v; a1(t,:,:) = w
      endif
      
      call p34()
            
      a1(k,:,:) = sI; a1(t,:,:) = sI
      ReH = ReH + u(k,t)*d1
    enddo
  enddo
end subroutine p56

!----------------------------------------------------
! Kronecker product of N matrices
!----------------------------------------------------
subroutine p34()
  if(allocated(d0)) deallocate(d0)
  if(allocated(d1)) deallocate(d1)
  
  allocate(d0(1:f,1:f)); d0 = 0.0d0
  allocate(d1(1:f**2,1:f**2)); d1 = 0.0d0
  
  d0 = a1(1,:,:)
  
  do m3 = 2, N, 1
    NN = f**(m3-1)
    do i = 1, NN, 1
      do j = 1, NN, 1
        do ms = 1, f, 1
          do l = 1, f, 1
            r1 = (i-1)*f + ms; i1 = (j-1)*f + l
            d1(r1,i1) = d0(i,j)*a1(m3,ms,l)
          enddo
        enddo
      enddo
    enddo
    
    if(m3 < N)then
      deallocate(d0); allocate(d0(1:f**m3,1:f**m3)); d0 = 0.0d0
      d0 = d1
      deallocate(d1); allocate(d1(1:f**(m3+1),1:f**(m3+1))); d1 = 0.0d0
    endif
    
  enddo
  deallocate(d0)
end subroutine p34

end program NMR_rarefied

Простите, без подсветки, хабраредактор всё-таки современен

© Habrahabr.ru