!
! 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 <http://www.gnu.org/licenses/>.
! 
! 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 <http://www.gnu.org/licenses/>.
! 
! The University of Nottingham can be contacted at: ggiemr@nottingham.ac.uk
!
!
! File Contents:
! SUBROUTINE time_domain_analysis
!
! NAME
!     time_domain_analysis
!
! AUTHORS
!     Chris Smartt
!
! DESCRIPTION
!     This subroutine controls the analytic solution for the transient analysis of
!     multi-conductor transmission lines. The solution is obtained using the Inverse 
!     Fourier Transform (IFT) method.
!     The solution is obtained using the full dimension transmission line equations 
!     i.e. we are NOT using the weak form of transfer impedance coupling
!     Note also that frequency dependent quantities are evaluated separately at
!     each frequency of analysis, i.e. the frequency dependence of the solution is rigorous 
!     given only the frequency dependence of the dielectrics is modelled using impedance/ admittance 
!     matrices whose elements are rational frequency dependent filter functions.
!
!     INPUTS:
!       spice_bundle_model structure
!       spice_validation_test structure 
!    
!     OUTPUT
!        analytic time domain termination voltage for the specified validation test case written to file
!
!    Note that the analysis assumes that the excitation (and hence the response) are periodic
!    with period equal to the maximimum time of the simulation. If the response of the circuit 
!    is longer than this then aliasing will occur and the comparison between Spice model results
!    and analytic results will be in error so please ensure that all transients have reduced
!    to insignificant levels within the simulation time.
!     
! COMMENTS
!     STAGE_1: frequency independent parameter solution
!     STAGE_2: multi-conductor solution
!     STAGE_3: shielded cable solution
!     STAGE_4: frequency dependent model 
!     STAGE_5: transfer impedance model 
!
! HISTORY
!
!     started 7/12/2015 CJS: STAGE_1 developments
!     24/03/2016 CJS: STAGE_3 developments -shielded cables
!     22/04/2016 CJS: STAGE_4 developments -frequency dependent model
!     04/05/2016 CJS: Only write time domain output over the time period requested,not the full FFT time period.
!    Include general conductor impedance model 12/05/2016 CJS
!     Fix bug with conductor impedance contributions 12/05/2016 CJS
!     8/09/2016 CJS Correct the common mode/ differential mode loss terms for twisted pairs
!     13/10/2016 CJS Correct transfer impedance for multiple modes in external domain
!     7/3/2017         CJS: Add resistance and voltage source onto the reference coonductor 
!     8/5/2017         CJS: Include references to Theory_Manual
!
!
SUBROUTINE time_domain_analysis(spice_bundle_model,spice_validation_test)

USE type_specifications
USE general_module
USE constants
USE cable_module
USE cable_bundle_module
USE spice_cable_bundle_module
USE maths
USE frequency_spec

IMPLICIT NONE

! variables passed to subroutine

TYPE(spice_model_specification_type),intent(IN):: spice_bundle_model    ! Spice cable bundle model structure

TYPE(spice_validation_test_type),intent(IN)    :: spice_validation_test ! Spice validation circuit structure

! local variables

! variables for time domain analytic solution using IFT

integer            :: n_timesteps             ! number of timesteps requested
integer            :: n_FFT                   ! nummber of samples in the FFT
complex(dp),allocatable    :: Vs_time(:)      ! Source voltage as a function of time
complex(dp),allocatable    :: Vs_freq(:)      ! Source voltage as a function of frequency
complex(dp),allocatable    :: VTL_time(:)     ! Output voltage as a function of time
complex(dp),allocatable    :: VTL_freq(:)     ! Output voltage as a function of frequency
real(dp),allocatable       :: time(:)         ! time values
real(dp),allocatable       :: freq(:)         ! frequency values

! variables for the frequency domain MTL solution

real(dp)    :: f,w            ! frequency and angular frequency
integer     :: frequency_loop ! frequency loop variable

integer        :: dim         ! dimension of matrix system to solve

! domain based impedance and admittance matrices
complex(dp),allocatable     :: Z_domain(:,:)
complex(dp),allocatable     :: Y_domain(:,:)

! domain based conductor impedance terms
complex(dp),allocatable     ::Z_domain_conductor_impedance_correction(:,:)

! Vectors and matrices used in the frequency domain solution of the transmission line equations with termination conditions 
complex(dp),allocatable     :: Vs1(:)
complex(dp),allocatable     :: Z1(:,:)
complex(dp),allocatable     :: Vs2(:)
complex(dp),allocatable     :: Z2(:,:)

complex(dp)    :: Vout ! complex output voltage value

! domain transformation matrices
complex(dp),allocatable     :: MI(:,:)
complex(dp),allocatable     :: MII(:,:)
complex(dp),allocatable     :: MV(:,:)
complex(dp),allocatable     :: MVI(:,:)

! temporary working matrices
complex(dp),allocatable     :: TM1(:,:)

integer    :: conductor,inner_domain,outer_domain

integer    :: domain1,inner_domain1,outer_domain1
integer    :: conductor1,reference_conductor1
integer    :: domain_conductor1,domain_reference_conductor1
logical    :: is_shield1

integer    :: domain2,inner_domain2,outer_domain2
integer    :: conductor2,reference_conductor2
integer    :: domain_conductor2,domain_reference_conductor2
logical    :: is_shield2

! conductor based impedance (loss) and transfer impedance model data
complex(dp) :: Zint_c          ! conductor surface impedance
complex(dp) :: Zint_c_ref      ! reference conductor surface impedance
real(dp)    :: Rdc_c           ! d.c. resistance of conductor
real(dp)    :: Rdc_c_ref       ! d.c. resistance of reference conductor
complex(dp) :: Zint_t          ! conductor transfer impedance
complex(dp) :: Zint_t_ref      ! reference conductor transfer impedance
real(dp)    :: Rdc_t           ! d.c. resistance of conductor (from transfer impedance)
real(dp)    :: Rdc_t_ref       ! d.c. resistance of reference conductor (from transfer impedance)

! complex amplitude of incident field
complex(dp) :: Einc

logical,allocatable  :: is_shielded_flag(:)            ! flags conductors which are not exposed to the incident field
integer              :: shield_conductor               ! temporary variable, shield conductor number for shielded conductors
real(dp),allocatable :: local_conductor_x_offset(:)    ! x coordinate in bundle cross section of conductors
real(dp),allocatable :: local_conductor_y_offset(:)    ! y coordinate in bundle cross section of conductors

integer             :: n_conductors_outer_domain ! for shield conductors, the number of conductors in the domain outside the shield
integer             :: shield_conductor_number_in_outer_domain ! for shield conductors, the conductor number in the domain outside the shield

! loop variables
integer    :: i
integer    :: row,col

integer :: ierr

! START

! initialise FFT stuff

! set the number of frequencies to be equal to the next power of 2 above the number of timesteps requested
! Theory_Manual_Section 2.3.3

  n_timesteps=NINT(spice_validation_test%runtime/spice_validation_test%timestep)+1
  
  if(verbose) write(*,*)'Number of timesteps in transient analysis:',n_timesteps
  
  i=1
10  CONTINUE
    i=i*2
    if (i.ge.n_timesteps) then
      n_FFT=i
    else
      GOTO 10
    end if
    
  if(verbose) write(*,*)'Number of frequency in transient analysis:',n_FFT

! allocate the arrays used in the FFT
  ALLOCATE( time(n_FFT) ) 
  ALLOCATE( Vs_time(n_FFT) ) 
  ALLOCATE( VTL_time(n_FFT) ) 
  ALLOCATE( freq(n_FFT) ) 
  ALLOCATE( Vs_freq(n_FFT) ) 
  ALLOCATE( VTL_freq(n_FFT) )   

! Generate the time domain voltage source function array
! The time domain waveform is the Exponential Pulse, the same as that used in Spice
! See Ngspice manual, section 4.1.3

  do i=1,n_FFT
  
    time(i)=(i-1)*spice_validation_test%timestep
        
    if (time(i).LT.spice_validation_test%width) then
      Vs_time(i)=(1d0-exp(-time(i)/spice_validation_test%risetime))
    else if (time(i).GE.spice_validation_test%width) then
      Vs_time(i)=(exp(-(time(i)-spice_validation_test%width)/spice_validation_test%risetime))
    end if
      
  end do

! FFT the time domain voltage source array to give the frequency domain excitation function
! Theory_Manual_Equation 2.48

  CALL FFT_TIME_TO_FREQ(n_FFT,time,Vs_time,freq,Vs_freq)
  
! allocate memory

  dim=spice_bundle_model%bundle%system_dimension
  ALLOCATE( Z_domain(dim,dim) )
  ALLOCATE( Y_domain(dim,dim) )
  
  ALLOCATE( Z_domain_conductor_impedance_correction(dim,dim) )
  
  ALLOCATE( Vs1(dim) )
  ALLOCATE( Z1(dim,dim) )
  ALLOCATE( Vs2(dim) )
  ALLOCATE( Z2(dim,dim) )
  
! domain transformation matrices
  ALLOCATE( MI(dim,dim) )
  ALLOCATE( MII(dim,dim) )
  ALLOCATE( MV(dim,dim) )
  ALLOCATE( MVI(dim,dim) )
  
! temporary working matrices
  ALLOCATE( TM1(dim,dim) )
   
   
  ALLOCATE( is_shielded_flag(1:dim+1) )
  ALLOCATE( local_conductor_x_offset(1:dim+1) )
  ALLOCATE( local_conductor_y_offset(1:dim+1) )
  
! loop over conductors to work out which are in shielded domains and which are in the external domain
! also get the position of the conductor in the bundle cross section for incident field excitation

  do i=1,dim+1
    if (spice_bundle_model%bundle%terminal_conductor_to_outer_domain(i).EQ.spice_bundle_model%bundle%tot_n_domains) then
      is_shielded_flag(i)=.FALSE.
      local_conductor_x_offset(i)=spice_bundle_model%bundle%conductor_x_offset(i)
      local_conductor_y_offset(i)=spice_bundle_model%bundle%conductor_y_offset(i)
    else
      is_shielded_flag(i)=.TRUE.
! work out the conductor number of the shield
      shield_conductor=spice_bundle_model%bundle%terminal_conductor_to_reference_terminal_conductor(i)
! shielded conductors pick up the coordinate of the shield for the purposes on incident field excitation
      local_conductor_x_offset(i)=spice_bundle_model%bundle%conductor_x_offset(shield_conductor)
      local_conductor_y_offset(i)=spice_bundle_model%bundle%conductor_y_offset(shield_conductor)
    end if
  end do
  
! build the termination specifications and convert to complex
  Vs1(1:dim)=cmplx( spice_validation_test%Vs_end1(1:dim)-spice_validation_test%Vs_end1(dim+1) )
  Vs2(1:dim)=cmplx( spice_validation_test%Vs_end2(1:dim)-spice_validation_test%Vs_end2(dim+1) )
  
  Z1(:,:) =cmplx( spice_validation_test%R_end1(dim+1)  )
  Z2(:,:) =cmplx( spice_validation_test%R_end2(dim+1)  )
  do i=1,dim
    Z1(i,i) =Z1(i,i)+cmplx( spice_validation_test%R_end1(i)  )
    Z2(i,i) =Z2(i,i)+cmplx( spice_validation_test%R_end2(i)  )
  end do

! Copy the domain transformation matrices and calculate the inverses
  MI(:,:)=spice_bundle_model%bundle%global_MI%mat(:,:)
  MV(:,:)=spice_bundle_model%bundle%global_MV%mat(:,:)
  
  ierr=0   ! set ierr=0 on input to matrix inverse to cause the program to stop if we have a singular matrix
  CALL cinvert_Gauss_Jordan(MI,dim,MII,dim,ierr)
  ierr=0   ! set ierr=0 on input to matrix inverse to cause the program to stop if we have a singular matrix
  CALL cinvert_Gauss_Jordan(MV,dim,MVI,dim,ierr)

! loop over frequency to calculate the frequency domain transmission line transfer function

  write(6,8100,advance='no')'Frequency ',0,' of ',n_FFT/2+1
  flush(6)
  
  do frequency_loop=1,n_FFT/2+1
  
    write(6,'(A)',advance='no')char(13)
    write(6,8100,advance='no')'Frequency ',frequency_loop,' of ',n_FFT/2+1
    flush(6)
    
8100 format(A10,I10,A4,I10)    

    f=freq(frequency_loop)

! shift frequency from d.c. as solution fails for lossless systems at f=0 Hz
    if (f.eq.0d0) then
      f=1d0
    end if 

    w=2d0*pi*f

! Use the global domain based L and C matrices and the domain voltage and current 
! domain transformation matrices to calculate the impedance [Z] and admittance [Y] matrices
    do row=1,dim
      do col=1,dim
      
! Evaluate the cable impedance filter function
        Z_domain(row,col)=evaluate_Sfilter_frequency_response(spice_bundle_model%bundle%global_Z%sfilter_mat(row,col),f)

! Evaluate the cable admittance filter function        
        Y_domain(row,col)=evaluate_Sfilter_frequency_response(spice_bundle_model%bundle%global_Y%sfilter_mat(row,col),f)

      end do  ! next col
       
    end do ! next row

! calculate the contribution to the matrices from the conductor based impedance models. 
! See Theory_Manual_Section 2.2.3 

!Initailly set to zero

    Z_domain_conductor_impedance_correction(1:dim,1:dim)=(0d0,0d0)

!   new domain based model

    do conductor1=1,dim
   
      domain1=spice_bundle_model%bundle%terminal_conductor_to_outer_domain(conductor1)
      reference_conductor1=spice_bundle_model%bundle%terminal_conductor_to_reference_terminal_conductor(conductor1)
      domain_conductor1=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(conductor1)
      domain_reference_conductor1=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(reference_conductor1)
      is_shield1=spice_bundle_model%bundle%terminal_conductor_is_shield_flag(conductor1)
      
! evaluate the surface impedance for this conductor conductor 
      CALL evaluate_conductor_impedance_model(spice_bundle_model%bundle%conductor_impedance(conductor1),    &
                                              f,Zint_c,Rdc_c,Zint_t,Rdc_t)
                                              
! Apply multiplication factor to the conductor impedance to correct for common mode/ differential modes in twisted pairs
! See note at the end of Theory_Manual_Section 3.5.4

      Zint_c=Zint_c*spice_bundle_model%bundle%conductor_impedance(conductor1)%Resistance_multiplication_factor
                                              
! evaluate the surface impedance for the reference conductor 
      CALL evaluate_conductor_impedance_model(spice_bundle_model%bundle%conductor_impedance(reference_conductor1),  &
                                              f,Zint_c_ref,Rdc_c_ref,Zint_t_ref,Rdc_t_ref)

! Apply multiplication factor to the conductor impedance to correct for common mode/ differential modes in twisted pairs
      Zint_c_ref=Zint_c_ref*spice_bundle_model%bundle%conductor_impedance(reference_conductor1)%Resistance_multiplication_factor
              
! The surface impedance of the conductor and the reference conductor contribute to the diagonal element
      Z_domain_conductor_impedance_correction(domain_conductor1,domain_conductor1)=Zint_c+Zint_c_ref
      
      if (verbose) then
        write(*,*)'conductor:',conductor1,' reference conductor',reference_conductor1
        write(*,*)'conductor loss model type',spice_bundle_model%bundle%conductor_impedance(conductor1)%impedance_model_type
        write(*,*)'refconductor loss model type',  &
                  spice_bundle_model%bundle%conductor_impedance(reference_conductor1)%impedance_model_type
        write(*,*)'radius',  &
                  spice_bundle_model%bundle%conductor_impedance(reference_conductor1)%radius
        write(*,*)'conductivity',  &
                  spice_bundle_model%bundle%conductor_impedance(reference_conductor1)%conductivity
        write(*,*)'Resistance_multiplication_factor',  &
                  spice_bundle_model%bundle%conductor_impedance(reference_conductor1)%Resistance_multiplication_factor
        write(*,*)'thickness',  &
                  spice_bundle_model%bundle%conductor_impedance(reference_conductor1)%thickness

        write(*,*)'domain conductor:',domain_conductor1,' domain reference conductor',domain_reference_conductor1
        write(*,*)'Contribution to Zc(',domain_conductor1,domain_conductor1,')'
        write(*,*)'Zc conductor:',Zint_c
        write(*,*)'Zc reference:',Zint_c_ref
      end if ! verbose
      
! conductor always gets the contribution from its own surface impedance
    
      do conductor2=conductor1+1,dim
   
        domain2=spice_bundle_model%bundle%terminal_conductor_to_outer_domain(conductor2)
        reference_conductor2=spice_bundle_model%bundle%terminal_conductor_to_reference_terminal_conductor(conductor2)
        domain_conductor2=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(conductor2)
        domain_reference_conductor2=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(reference_conductor2)
        is_shield2=spice_bundle_model%bundle%terminal_conductor_is_shield_flag(conductor2)

! if the two conductors belong to the same domain then add the reference conductor impedance
        if (domain1.EQ.domain2) then
          Z_domain_conductor_impedance_correction(domain_conductor1,domain_conductor2)=Zint_c_ref
          Z_domain_conductor_impedance_correction(domain_conductor2,domain_conductor1)=Zint_c_ref
          
          if (verbose) then
            write(*,*)'Contribution to Zc(',domain_conductor1,domain_conductor2,')'
            write(*,*)'Contribution to Zc(',domain_conductor2,domain_conductor1,')'
            write(*,*)'Zc conductor:',Zint_c_ref
          end if ! verbose
          
       end if
      
      end do ! next conductor2
      
    end do ! next conductor1
    
    if (verbose) write(*,*)'Add transfer impedance contributions'
! add transfer impedance contributions

! loop over conductors looking for shields. Note include all conductors including the reference here
    do conductor=1,dim+1
   
      is_shield1=spice_bundle_model%bundle%terminal_conductor_is_shield_flag(conductor)
      
      if (is_shield1) then
! add transfer impedance contributions to inner and outer domain conductors
 
        inner_domain=spice_bundle_model%bundle%terminal_conductor_to_inner_domain(conductor)
        outer_domain=spice_bundle_model%bundle%terminal_conductor_to_outer_domain(conductor)
        
        CALL evaluate_conductor_impedance_model(spice_bundle_model%bundle%conductor_impedance(conductor),  &
                                                f,Zint_c,Rdc_c,Zint_t,Rdc_t)
                                                
! Check whether the shield is the reference conductor in the outer domain - the contributions
! are different if this is the case.

        n_conductors_outer_domain=spice_bundle_model%bundle%n_conductors(outer_domain)
        shield_conductor_number_in_outer_domain=spice_bundle_model%bundle%terminal_conductor_to_local_domain_conductor(conductor)
         
! number of conductors in a domain is spice_bundle_model%bundle%n_conductors(domain)
        if (shield_conductor_number_in_outer_domain.NE.n_conductors_outer_domain) then
               
! loop over all conductors
          do row=1,dim
         
! get the domain of row conductor
            domain1=spice_bundle_model%bundle%terminal_conductor_to_outer_domain(row)

            if (domain1.EQ.inner_domain) then
! The row conductor is in the inner shield domain and so gets a transfer impedance contribution from the shield conductor
                 
! the shield couples these two domains so add the transfer impedance term - also include term to make the matrix symmetric
              domain_conductor1=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(row)
                 
              domain_conductor2=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(conductor)
              Z_domain_conductor_impedance_correction(domain_conductor1,domain_conductor2)=        &
              Z_domain_conductor_impedance_correction(domain_conductor1,domain_conductor2) -Zint_t
              Z_domain_conductor_impedance_correction(domain_conductor2,domain_conductor1)=        &
              Z_domain_conductor_impedance_correction(domain_conductor2,domain_conductor1) -Zint_t
                 
              if (verbose) then
                write(*,*)'Shield conductor',conductor,' inner domain',inner_domain,' outer domain',outer_domain
                write(*,*)'row',row,' col',col,' row domain',domain1,' col domain',domain2
                write(*,*)'Contribution to Zt(',domain_conductor1,domain_conductor2,')'
                write(*,*)'Contribution to Zt(',domain_conductor2,domain_conductor1,')'
                write(*,*)'Zt conductor:',-Zint_t
              end if ! verbose
                                                 
            end if  ! transfer impedance term required
            
          end do ! next row conductor
          
        else ! shield IS reference conductor in outer domain
               
! loop over all conductors
          do row=1,dim
         
! get the domain of row conductor
            domain1=spice_bundle_model%bundle%terminal_conductor_to_outer_domain(row)

            if (domain1.EQ.inner_domain) then
! The row conductor is in the inner shield domain and so gets a transfer impedance contribution from the shield conductor
                 
! the shield couples these two domains so add the transfer impedance term - also include term to make the matrix symmetric
              domain_conductor1=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(row)
                 
! As the shield conductor is the reference we need to find all the conductors contributing to the shield current
! note that the contribution is then -ve of the normal transfer impedance contribution as the currents are in the
! opposite direction

              do col=1,dim
              
                domain2=spice_bundle_model%bundle%terminal_conductor_to_outer_domain(col)
! Check the domain of the col conductor. If it is an outer domain conductor of the shield then it contributes

                if (domain2.EQ.outer_domain) then

                  domain_conductor2=spice_bundle_model%bundle%terminal_conductor_to_global_domain_conductor(col)
                  
                  Z_domain_conductor_impedance_correction(domain_conductor1,domain_conductor2)=        &
                  Z_domain_conductor_impedance_correction(domain_conductor1,domain_conductor2) +Zint_t
                  Z_domain_conductor_impedance_correction(domain_conductor2,domain_conductor1)=        &
                  Z_domain_conductor_impedance_correction(domain_conductor2,domain_conductor1) +Zint_t
                 
                  if (verbose) then
                    write(*,*)'Shield conductor',conductor,' inner domain',inner_domain,' outer domain',outer_domain
                    write(*,*)'row',row,' col',col,' row domain',domain1,' col domain',domain2
                    write(*,*)'Contribution to Zt(',domain_conductor1,domain_conductor2,')'
                    write(*,*)'Contribution to Zt(',domain_conductor2,domain_conductor1,')'
                    write(*,*)'Zt conductor:',-Zint_t
                  end if ! verbose
                  
                end if  ! transfer impedance term required for this col conductor
                 
              end do ! next condutor to check
                                                
            end if  ! transfer impedance term required for this row conductor
            
          end do ! next row conductor
         
        end if ! shield is/ is not reference conductor in outer domain
      
      end if ! conductor is a shield

    end do ! next conductor
    
! Add the conductor impedance contributions to the domain based impedance matrix
    Z_domain(:,:)=Z_domain(:,:)+Z_domain_conductor_impedance_correction(:,:)
    
    Einc=cmplx(spice_bundle_model%Eamplitude)
    
! Solve the frequency domain multi-conductor transmission line equations with the specified termination circuit and 
! return the required conductor voltage in Vout.   
! For the purposes of the frequency domain solution, the excitations are assumed to be constant in frequency
! The frequency response of the excitation is included afterwards         
    if (.NOT.run_validation_test_Vbased) then
                                          
      CALL frequency_domain_MTL_solution(dim,Z_domain,Y_domain,MV,MVI,MI,MII, &
                                       Einc,spice_bundle_model%Ex,spice_bundle_model%Ey,spice_bundle_model%Ez,    &
                                       spice_bundle_model%Hx,spice_bundle_model%Hy,spice_bundle_model%Hz,         &
                                       spice_bundle_model%kx,spice_bundle_model%ky,spice_bundle_model%kz,         &
                                       local_conductor_x_offset,                                                  &
                                       local_conductor_y_offset,                                                  &
                                       spice_bundle_model%bundle%ground_plane_present,                            &
                                       spice_bundle_model%bundle%ground_plane_x,                                  &
                                       spice_bundle_model%bundle%ground_plane_y,                                  &
                                       spice_bundle_model%bundle%ground_plane_theta,                              &
                                       spice_bundle_model%length,Vs1,Z1,Vs2,Z2,                                   &
                                       is_shielded_flag,                                                          &
                                       f,spice_validation_test%output_end,spice_validation_test%output_conductor, &
                                       spice_validation_test%output_conductor_ref,Vout)
    else
                                        
      CALL frequency_domain_MTL_solution_V(dim,Z_domain,Y_domain,MV,MVI,MI,MII, &
                                       Einc,spice_bundle_model%Ex,spice_bundle_model%Ey,spice_bundle_model%Ez,    &
                                       spice_bundle_model%Hx,spice_bundle_model%Hy,spice_bundle_model%Hz,         &
                                       spice_bundle_model%kx,spice_bundle_model%ky,spice_bundle_model%kz,         &
                                       local_conductor_x_offset,                                                  &
                                       local_conductor_y_offset,                                                  &
                                       spice_bundle_model%bundle%ground_plane_present,                            &
                                       spice_bundle_model%bundle%ground_plane_x,                                  &
                                       spice_bundle_model%bundle%ground_plane_y,                                  &
                                       spice_bundle_model%bundle%ground_plane_theta,                              &
                                       spice_bundle_model%length,Vs1,Z1,Vs2,Z2,                                   &
                                       is_shielded_flag,                                                          &
                                       f,spice_validation_test%output_end,spice_validation_test%output_conductor, &
                                       spice_validation_test%output_conductor_ref,Vout)
    end if
    
! multiply the Frequency domain source and transmission line transfer function 
! Save transfer function multiplied by frequency domain source voltage function i.e. include the time response of
! the excitation here. Theory_Manual_Section 2.3.3

    VTL_freq(frequency_loop)=Vout*Vs_freq(frequency_loop)
    
    if ( (frequency_loop.NE.1).AND.(frequency_loop.NE.N_FFT/2+1) ) then
      VTL_freq(N_FFT-frequency_loop+2)=conjg(VTL_freq(frequency_loop))
    end if
    
  end do ! next frequency in frequency loop

! Inverse FFT to give the time domain transmission line response
! Theory_Manual_Equation 2.50

  CALL FFT_FREQ_TO_TIME(n_FFT,time,VTL_time,freq,VTL_freq)

! write the time domain response to file

! Open output file 
  open(unit=analytic_soln_file_unit,file=trim(analytic_soln_filename))
  
! write the file header line
  write(analytic_soln_file_unit,'(A)')time_header

  do i=1,n_timesteps                                              ! changed from n_FFT 04/5/2016 CJS
    write(analytic_soln_file_unit,*)time(i),real(VTL_time(i))
  end do
  
! Close output file 
  Close(unit=analytic_soln_file_unit) 

! deallocate memory
  DEALLOCATE( Z_domain )
  DEALLOCATE( Y_domain )
  
  DEALLOCATE( Z_domain_conductor_impedance_correction )
  
  DEALLOCATE( Vs_time ) 
  DEALLOCATE( Vs_freq ) 
  DEALLOCATE( VTL_time ) 
  DEALLOCATE( VTL_freq ) 
  DEALLOCATE( time ) 
  DEALLOCATE( freq ) 
  
! domain transformation matrices
  DEALLOCATE( MI )
  DEALLOCATE( MII )
  DEALLOCATE( MV )
  DEALLOCATE( MVI )
    
  DEALLOCATE( is_shielded_flag )
  DEALLOCATE( local_conductor_x_offset )
  DEALLOCATE( local_conductor_y_offset )

! temporary working matrices
  DEALLOCATE( TM1 )
  
  write(6,*)

  RETURN

END SUBROUTINE time_domain_analysis
