! ! This file is part of SACAMOS, State of the Art CAble MOdels for Spice. ! It was developed by the University of Nottingham and the Netherlands Aerospace ! Centre (NLR) for ESA under contract number 4000112765/14/NL/HK. ! ! Copyright (C) 2016-2018 University of Nottingham ! ! SACAMOS is free software: you can redistribute it and/or modify it under the ! terms of the GNU General Public License as published by the Free Software ! Foundation, either version 3 of the License, or (at your option) any later ! version. ! ! SACAMOS is distributed in the hope that it will be useful, but ! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! for more details. ! ! A copy of the GNU General Public License version 3 can be found in the ! file GNU_GPL_v3 in the root or at . ! ! SACAMOS uses the EISPACK library (in /SRC/EISPACK). EISPACK is subject to ! the GNU Lesser General Public License. A copy of the GNU Lesser General Public ! License version can be found in the file GNU_LGPL in the root of EISPACK ! (/SRC/EISPACK ) or at . ! ! The University of Nottingham can be contacted at: ggiemr@nottingham.ac.uk ! ! ! File Contents: ! SUBROUTINE modal_decomposition_LC ! SUBROUTINE orthogonal_transformation ! SUBROUTINE normalise_matrix_columns ! ! NAME ! modal_decomposition_LC ! ! AUTHORS ! Chris Smartt ! ! DESCRIPTION ! This subroutine calculates the modal decomposition give the inductance and capacitance matrices L and C ! for an inhomogeneous, lossless configuration. ! The theory is in the Theory Manual_Section 3.3 however there is more detailed discussion in ! C. R. Paul,'Analasys of Multiconductor transmission lines,' ! ! Inputs: 1. L, the inductance matrix ! 2. C, the capacitance matrix ! ! Outputs 1. TI, TII, TV, TVI, the modal decomposition matrices ! 2. The mode velocities ! 3. The mode impedances ! ! COMMENTS ! ! ! HISTORY ! ! started 20/6/2015 CJS: Looking forward towards inhomogeneous transmission lines ! 8/5/2017 CJS: Include references to Theory_Manual ! SUBROUTINE modal_decomposition_LC(dim,L,C,TI,TII,TV,TVI,mode_velocity,mode_impedance) USE type_specifications USE general_module USE constants USE eispack USE maths IMPLICIT NONE ! variables passed to the subroutine integer,intent(IN) :: dim ! matrix dimension real(dp),intent(IN) :: L(dim,dim) ! inductance matrix real(dp),intent(IN) :: C(dim,dim) ! capacitance matrix real(dp),intent(OUT) :: TI(dim,dim) ! modal decomposition matrix [TI] real(dp),intent(OUT) :: TII(dim,dim) ! modal decomposition matrix inverse of [TI] real(dp),intent(OUT) :: TV(dim,dim) ! modal decomposition matrix [TV] real(dp),intent(OUT) :: TVI(dim,dim) ! modal decomposition matrix inverse of [TV] real(dp),intent(OUT) :: mode_velocity(dim) ! mode velocity list real(dp),intent(OUT) :: mode_impedance(dim) ! mode impedance list ! local variables ! orthonormal diagonalisation of C real(dp) :: UT(dim,dim) real(dp) :: thetasqr(dim,dim) real(dp) :: U(dim,dim) real(dp) :: theta(dim,dim) ! [M] and the orthonormal diagonalisation of [M]=[theta][UT][L][U][theta] real(dp) :: M(dim,dim) real(dp) :: ST(dim,dim) real(dp) :: gammasqr(dim,dim) real(dp) :: S(dim,dim) ! un-normalised mode transformation matrix, T real(dp) :: T(dim,dim) ! normalised mode transformation matrix, Tnorm and the normalisation matrix, alpha real(dp) :: Tnorm(dim,dim) real(dp) :: alpha(dim,dim) ! mode inductance and capacitance real(dp) ::lmode real(dp) ::cmode ! other matrices real(dp) :: TM1(dim,dim) real(dp) :: TM2(dim,dim) ! other variables integer :: row,col integer :: ierr ! START ! Calculate the product ofthe transmission line impedance (Z) and admittance (Y) matrices if(verbose) then write(*,*)'CALLED modal_decomposition_LC' write(*,*)'L' CALL dwrite_matrix(L,dim,dim,dim,0) write(*,*)'C' CALL dwrite_matrix(C,dim,dim,dim,0) TM1=matmul(L,C) write(*,*)'LC' CALL dwrite_matrix(TM1,dim,dim,dim,0) end if ! Stage 1: calculate the orthogonal transformation to diagonalise the symmetric real matrix C, [UT][C][U]=[thetasqr] ! Theory_Manual_Equation 3.37 CALL orthogonal_transformation(C,UT,thetasqr,U,dim) ! calculate the square root of the diagonal matrix thetasqr theta(:,:)=0d0 do row=1,dim theta(row,row)=dsqrt(thetasqr(row,row)) end do ! form the product [M]=[theta][UT][L][U][theta] ! Theory_Manual_Equation 3.39 TM1=matmul(U,theta) TM2=matmul(L,TM1) TM1=matmul(UT,TM2) M=matmul(theta,TM1) ! STAGE 2: ! Theory_Manual_Equation 3.40 CALL orthogonal_transformation(M,ST,gammasqr,S,dim) ! form the matrix [T]=[U][theta][S] then normalise the matrix columns ! Theory_Manual_Equation 3.42 TM1=matmul(theta,S) T=matmul(U,TM1) CALL normalise_matrix_columns(T,Tnorm,alpha,dim) ! set the modal decomposition matrices TI,TV,TII,TVI ! Theory_Manual_Equation 3.43,3,44,3.45 TI=Tnorm TM1=transpose(Tnorm) ierr=0 ! set ierr=0 on input to matrix inverse to cause the program to stop if we have a singular matrix CALL dinvert_Gauss_Jordan(TM1,dim,TV,dim,ierr) TVI=transpose(TI) TII=transpose(TV) ! calculate the mode inductance and capacitance and hence the mode velocities and impedances ! Theory_Manual_Equation 3.46,3,47 do row=1,dim lmode=(alpha(row,row)**2)*gammasqr(row,row) cmode=1d0/(alpha(row,row)**2) mode_velocity(row)=1d0/sqrt(lmode*cmode) mode_impedance(row)=sqrt(lmode/cmode) end do if (verbose) then ! do some checks write(*,*)' mode alpha gammasqr' do row=1,dim write(*,*)row,alpha(row,row),gammasqr(row,row) end do write(*,*)' mode lmode cmode mode_velocity mode_impedance' do row=1,dim write(*,*)row,(alpha(row,row)**2)*gammasqr(row,row),(alpha(row,row)**(-2)),mode_velocity(row),mode_impedance(row) end do write(*,*)'[TI]' do row=1,dim write(*,*)(TI(row,col),col=1,dim) end do end if RETURN END SUBROUTINE modal_decomposition_LC ! ! __________________________________________________________ ! ! SUBROUTINE orthogonal_transformation(M_in,UT,thetasqr,U,dim) ! ! DESCRIPTION ! calculate an orthogonal transformation which diagonalises the symmetric matrix M_in ! [UT][M_in][U]=[thetasqr] where [thetasqr] is a diagonal matrix. ! ! The subroutine uses the eispack routine rg to calculate the eigenvalues and eigenvectors ! of a real symmetric matrix. ! ! ! COMMENTS ! The eigenvalues (and eigenvectors) are ordered in ascending order ! ! HISTORY ! ! 20/06/2016 CJS. ! USE type_specifications USE general_module USE eispack USE maths IMPLICIT NONE ! vasriables passed to subroutine integer,intent(IN) :: dim ! matrix dimension real(dp),intent(IN) :: M_in(dim,dim) ! input symmetric matrix ! output matrices real(dp),intent(OUT) :: UT(dim,dim) real(dp),intent(OUT) :: thetasqr(dim,dim) real(dp),intent(OUT) :: U(dim,dim) ! EISPACK variables real(dp) :: M(dim,dim) real(dp) :: w(dim) ! vector of eigenvalues integer(i4):: matz integer(i4):: ierr ! local matrices for checks real(dp) :: UTU(dim,dim) real(dp) :: Uthetasqr(dim,dim) real(dp) :: UthetasqrUT(dim,dim) ! loop variables integer :: row,col ! START ! copy the M_in matrix M(:,:)=M_in(:,:) ! call the eispack routine rs matz=1 ! calculate both eigenvalues and eigenvectors CALL rs ( dim, M, w, matz, U, ierr ) if (ierr.NE.0) then run_status='ERROR in eispack routine rs called from orthogonal_transformation' CALL write_program_status() STOP 1 end if thetasqr(:,:)=0d0 do row=1,dim thetasqr(row,row)=w(row) end do UT=TRANSPOSE(U) ! Some checks if (verbose) then write(*,*)'Eigenvalues' do row=1,dim write(*,*)row,w(row) end do write(*,*)'Eigenvectors:' do col=1,dim write(*,*)'Eigenvector ',col do row=1,dim write(*,*)row,UT(row,col) end do end do ! check that the diagonalisation is orthogonal UTU=matmul(UT,U) write(*,*)'Check [UT][U]=[I]' CALL dwrite_matrix(UTU,dim,dim,dim,0) write(*,*)'[M]' CALL dwrite_matrix(M_in,dim,dim,dim,0) write(*,*)'Check [U][thetasqr][UT]=[M]' Uthetasqr=matmul(U,thetasqr) UthetasqrUT=matmul(Uthetasqr,UT) CALL dwrite_matrix(UthetasqrUT,dim,dim,dim,0) end if ! verbose END SUBROUTINE orthogonal_transformation ! ! __________________________________________________________ ! ! SUBROUTINE normalise_matrix_columns(T,Tnorm,alpha,dim) ! ! DESCRIPTION ! normalise the columns of matrix T to have length 1. ! Return the normalised matrix and the diagonal normalisation matrix, alpha ! such that [Tnorm]=[T][alpha] ! ! ! COMMENTS ! ! ! HISTORY ! ! 20/06/2016 CJS. ! USE type_specifications USE maths IMPLICIT NONE ! vasriables passed to subroutine integer,intent(IN) :: dim ! matrix dimension real(dp),intent(IN) :: T(dim,dim) ! input matrix ! output matrices such that [Tnorm]=[T][alpha] real(dp),intent(OUT) :: Tnorm(dim,dim) real(dp),intent(OUT) :: alpha(dim,dim) ! loop variables integer :: row,col real(dp) :: length ! START alpha(:,:)=0d0 do col=1,dim length=0d0 do row=1,dim length=length+T(row,col)*T(row,col) end do length=sqrt(length) alpha(col,col)=1d0/length do row=1,dim Tnorm(row,col)=T(row,col)/length end do end do END SUBROUTINE normalise_matrix_columns