autoDiffArray.f90 Source File

This File Depends On

sourcefile~~autodiffarray.f90~~EfferentGraph sourcefile~autodiffarray.f90 autoDiffArray.f90 sourcefile~autodiffoperator.f90 autoDiffOperator.f90 sourcefile~autodiffoperator.f90->sourcefile~autodiffarray.f90 sourcefile~kinds.f90 kinds.f90 sourcefile~kinds.f90->sourcefile~autodiffarray.f90 sourcefile~kinds.f90->sourcefile~autodiffoperator.f90 sourcefile~autodifftype.f90 autoDiffType.f90 sourcefile~kinds.f90->sourcefile~autodifftype.f90 sourcefile~autodifftype.f90->sourcefile~autodiffarray.f90 sourcefile~autodifftype.f90->sourcefile~autodiffoperator.f90
Help

Files Dependent On This One

sourcefile~~autodiffarray.f90~~AfferentGraph sourcefile~autodiffarray.f90 autoDiffArray.f90 sourcefile~autodiff.f90 autoDiff.f90 sourcefile~autodiffarray.f90->sourcefile~autodiff.f90 sourcefile~testautodiff.f90 testAutoDiff.f90 sourcefile~autodiff.f90->sourcefile~testautodiff.f90
Help

Source Code


Source Code

module autoDiffArray_mod
	use kinds_mod
	use autoDiffType_mod
	use autoDiffOperator_mod
	implicit none
	private
	
	! Maximum Location
	interface maxloc
		module procedure maxloc_a1
	end interface
	
	! Summation
	interface sum
		module procedure sum_a1
		module procedure sum_a2
		module procedure sum_a3
	end interface
	public::sum
	
	! L2 Norm
	interface norm2
		module procedure norm2_a1
		module procedure norm2_a2
		module procedure norm2_a3
	end interface
	public::norm2
	
	! Matrix Multiply
	interface matmul
		module procedure matmul_a21
		module procedure matmul_a22
	end interface
	public::matmul
	
	! TDMA
	interface TDMA
		module procedure TDMA_sA
		module procedure TDMA_mA
	end interface
	public::TDMA
	
	! solveLU
	interface solveLU
		module procedure solveLU_s
		module procedure solveLU_m
	end interface
	public::solveLU
	
contains

	!====================!
	!= Maximum Location =!
	!====================!

	function maxloc_a1(u,idx) result(o)
		type(ad_t),dimension(:),intent(in)::u
		integer,intent(in)::idx
		integer::o
		
		integer::N,i
		
		N = size(u)
		o = maxloc([( u(i)%val() , i=1,N )],1)
	end function maxloc_a1

	!=============!
	!= Summation =!
	!=============!

	pure function sum_a1(u) result(o)
		type(ad_t),dimension(:),intent(in)::u
		type(ad_t)::o
		
		integer,dimension(1)::N
		integer::i
		
		N = shape(u)
		
		o = ad_t( 0.0_wp , size(u(1)%grad()) )
		
		do i=1,N(1)
			o = o+u(i)
		end do
	end function sum_a1

	pure function sum_a2(u) result(o)
		type(ad_t),dimension(:,:),intent(in)::u
		type(ad_t)::o
		
		integer,dimension(2)::N
		integer::i,j
		
		N = shape(u)
		
		o = ad_t( 0.0_wp , size(u(1,1)%grad()) )
		
		do j=1,N(2)
			do i=1,N(1)
				o = o+u(i,j)
			end do
		end do
	end function sum_a2

	pure function sum_a3(u) result(o)
		type(ad_t),dimension(:,:,:),intent(in)::u
		type(ad_t)::o
		
		integer,dimension(3)::N
		integer::i,j,k
		
		N = shape(u)
		
		o = ad_t( 0.0_wp , size(u(1,1,1)%grad()) )
		
		do k=1,N(3)
			do j=1,N(2)
				do i=1,N(1)
					o = o+u(i,j,k)
				end do
			end do
		end do
	end function sum_a3

	!===========!
	!= L2 Norm =!
	!===========!

	function norm2_a1(u) result(o)
		type(ad_t),dimension(:),intent(in)::u
		type(ad_t)::o
		
		o = sqrt(sum( u**2 ))
	end function norm2_a1

	function norm2_a2(u) result(o)
		type(ad_t),dimension(:,:),intent(in)::u
		type(ad_t)::o
		
		o = sqrt(sum( u**2 ))
	end function norm2_a2

	function norm2_a3(u) result(o)
		type(ad_t),dimension(:,:,:),intent(in)::u
		type(ad_t)::o
		
		o = sqrt(sum( u**2 ))
	end function norm2_a3

	!===================!
	!= Matrix Multiply =!
	!===================!

	pure function matmul_a21(u,v) result(o)
		type(ad_t),dimension(:,:),intent(in)::u
		type(ad_t),dimension(:),intent(in)::v
		type(ad_t),dimension(:),allocatable::o
		
		integer,dimension(2)::N
		integer::i
		
		N = shape(u)
		allocate( o(N(1)) )
		
		do i=1,N(1)
			o(i) = sum( u(i,:)*v(:) )
		end do
	end function matmul_a21

	pure function matmul_a22(u,v) result(o)
		type(ad_t),dimension(:,:),intent(in)::u
		type(ad_t),dimension(:,:),intent(in)::v
		type(ad_t),dimension(:,:),allocatable::o
		
		integer,dimension(2)::N,M
		integer::i,j
		
		N = shape(u)
		M = shape(v)
		allocate( o(N(1),M(2)) )
		
		do j=1,M(2)
			do i=1,N(1)
				o(i,j) = sum( u(i,:)*v(:,j) )
			end do
		end do
	end function matmul_a22

	!========!
	!= TDMA =!
	!========!

	function TDMA_sA(A,b) result(x)
		!! Solve a tridiagonal linear algebra problem \( [A]\{x\}=\{b\} \)
		!! @todo
		!! Put behind interface and allow for multiple RHS in another routine
		type(ad_t),dimension(:,:),intent(in)::A
			!! Coefficient matrix with the diagonals in columns \( [A] \)
		type(ad_t),dimension(:),intent(in)::b
			!! Right-hand-side of the system \( \{b\} \)
		type(ad_t),dimension(:),allocatable::x
			!! Problem solution \( \{x\} \)
		
		type(ad_t),dimension(:,:),allocatable::W
		type(ad_t)::r
		integer::N,k
		
		N = size(A,1)
		
		allocate( W(N,-1:+1) )
		
		W(:,-1) = A(:,1)
		W(:, 0) = A(:,2)
		W(:,+1) = A(:,3)
		x       = b
		
		do k=2,N
			r = W(k,-1)/W(k-1,0)
			W(k,-1:0) = W(k,-1:0)-r*W(k-1,0:1)
			x(k) = x(k)-r*x(k-1)
		end do
		
		do k=N-1,1,-1
			r = W(k,1)/W(k+1,0)
			W(k,0:1) = W(k,0:1)-r*W(k+1,-1:0)
			x(k) = x(k)-r*x(k+1)
		end do
		
		do k=1,N
			r = 1.0_wp/W(k,0)
			W(k,:) = r*W(k,:)
			x(k) = r*x(k)
		end do
	end function TDMA_sA

	function TDMA_mA(A,b) result(x)
		!! Solve a tridiagonal linear algebra problem \( [A]\{x\}=\{b\} \)
		!! @todo
		!! Put behind interface and allow for multiple RHS in another routine
		type(ad_t),dimension(:,:),intent(in)::A
			!! Coefficient matrix with the diagonals in columns \( [A] \)
		type(ad_t),dimension(:,:),intent(in)::b
			!! Right-hand-side of the system \( \{b\} \)
		type(ad_t),dimension(:,:),allocatable::x
			!! Problem solution \( \{x\} \)
		
		type(ad_t),dimension(:,:),allocatable::W
		type(ad_t)::r
		integer::N,k
		
		N = size(A,1)
		
		allocate( W(N,-1:+1) )
		
		W(:,-1) = A(:,1)
		W(:, 0) = A(:,2)
		W(:,+1) = A(:,3)
		x       = b
		
		do k=2,N
			r = W(k,-1)/W(k-1,0)
			W(k,-1:0) = W(k,-1:0)-r*W(k-1,0:1)
			x(k,:) = x(k,:)-r*x(k-1,:)
		end do
		
		do k=N-1,1,-1
			r = W(k,1)/W(k+1,0)
			W(k,0:1) = W(k,0:1)-r*W(k+1,-1:0)
			x(k,:) = x(k,:)-r*x(k+1,:)
		end do
		
		do k=1,N
			r = 1.0_wp/W(k,0)
			W(k,:) = r*W(k,:)
			x(k,:) = r*x(k,:)
		end do
	end function TDMA_mA

	!====================!
	!= solveLU Routines =!
	!====================!

	subroutine decomposeLU(A,LU,p)
		!! Shamelessly adapted from Rosetta Code
		!!
		!! L -> j<i , L(i,i) = 1
		!! U -> j>=i
		type(ad_t),dimension(:,:),intent(in)::A
		type(ad_t),dimension(:,:),allocatable,intent(inout):: LU
		integer,dimension(:),allocatable,intent(inout)::p
		integer::N,j,i,m
		
		LU = A
		
		N = size(A,1)
		p = [( i , i=1,N )]
		do i=1,N-1
			m = maxloc( abs( LU(p(i:),i) ) , 1 ) + (i-1)
			
			if(m/=i) p([i,m]) = p([m,i])
			
			LU(p(i+1:),i) = LU(p(i+1:),i) / LU(p(i),i)
			
			forall(j=i+1:N) LU(p(i+1:),j) = LU(p(i+1:),j) - LU(p(i+1:),i) * LU(p(i),j)
		end do
		
		LU = LU(p,:)
	end subroutine decomposeLU

	function applyLU(LU,p,b) result(x)
		type(ad_t),dimension(:,:),intent(in)::LU
		integer,dimension(:),intent(in)::p
		type(ad_t),dimension(:),intent(in)::b
		type(ad_t),dimension(:),allocatable::x
		
		type(ad_t),dimension(:),allocatable::pb
		type(ad_t),dimension(:),allocatable::r
		integer::N,i
		
		N  = size(b)
		allocate(r(N),x(N),pb(N))
		r  = ad_t(0.0_wp,size(b(1)%grad()))
		x  = ad_t(0.0_wp,size(b(1)%grad()))
		pb = b(p)
		
		! L.r=pb
		r(1) = pb(1)
		do i=2,N,+1
			r(i) = pb(i)-sum(LU(i,1:i-1)*r(1:i-1))
		end do
		
		! U.x=r
		x(N) = r(N)/LU(N,N)
		do i=N-1,1,-1
			x(i) = ( r(i)-sum(LU(i,i+1:N)*x(i+1:N)) )/LU(i,i)
		end do
	end function applyLU

	function solveLU_s(A,b) result(x)
		type(ad_t),dimension(:,:),intent(in)::A
		type(ad_t),dimension(:),intent(in)::b
		type(ad_t),dimension(:),allocatable::x
		
		type(ad_t),dimension(:,:),allocatable::LU
		integer,dimension(:),allocatable::p
		
		call decomposeLU(A,LU,p)
		
		x = applyLU(LU,p,b)
	end function solveLU_s

	function solveLU_m(A,b) result(x)
		type(ad_t),dimension(:,:),intent(in)::A
		type(ad_t),dimension(:,:),intent(in)::b
		type(ad_t),dimension(:,:),allocatable::x
		
		type(ad_t),dimension(:,:),allocatable::LU
		integer,dimension(:),allocatable::p
		integer::k
		
		call decomposeLU(A,LU,p)
		
		allocate( x(size(b,1),size(b,2)) )
		
		do k=1,size(b,2)
			x(:,k) = applyLU(LU,p,b(:,k))
		end do
	end function solveLU_m

end module autoDiffArray_mod