!
! 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:
! PROGRAM spice_cable_bundle_model_builder
!
! NAME
!     spice_cable_bundle_model_builder
!
! AUTHORS
!     Chris Smartt
!
! DESCRIPTION
!     The spice_cable_bundle_model_builder takes a previously specified cable bundle model and
!     generates a spice circuit model for a specific analysis scenario e.g
!     crosstalk analysis, plane wave illumination analysis etc. for a specified cable bundle length
!     The code also allows the generation of a validation test case and an analytic solution 
!     for this test case so that the accuracy and validity of the model can be assessed. 
!
!     The input to the program is the name of a spice cable bundle specification file. 
!     A file 'name.spice_model_spec' must exist, containing all the data required to specify 
!     a spice cable bundle model and validation test circuit.
!
!     The .cable and .bundle files referred to in the .spice_mode_spec file are looked for in directories specified 
!     in the .spice_model_spec file. These may be the local directory (./) other specified paths. In this way the software can interact with a 
!     library of cable models (MOD).
!
!     The output of the spice_cable_model_builder code are the following files:
!
!     name_LTspice.lib              Subcircuit file suitable for use in LTspice
!     name_NGspice.lib              Subcircuit file suitable for use in Ngspice        
!     name_Pspice.lib               Subcircuit file suitable for use in Pspice           
!         
!     name_LTspice.cir              Circuit file for the validation test cirucit suitable for use in LTspice
!     name_NGspice.cir              Circuit file for the validation test cirucit suitable for use in Ngspice
!     name_Pspice.cir               Circuit file for the validation test cirucit suitable for use in Pspice
!
!     name.sym                      Schematic symbol file for use in gschem
!     name.asy                      Schematic symbol file for use in LTspice
!
!     analytic_solution.dat         Analytic solution for the validation test cirucit
!     spice_solution.dat            Spice solution for the validation test cirucit
!
!     The .lib files are placed in a directory specified in the .spice_model_spec file. This may be the local directory (./) 
!     or another specified path. In this way the software can interact with a library of cable models (MOD).
!!
!     The program may be run with the cable name specified in the command line i.e. 'spice_cable_bundle_model_builder name'
!     or it the name is absent from the command line, the user is prompted for the name.
!     
! COMMENTS
!     Updated to V2
!
! HISTORY
!
!     started 17/11/2015 CJS: STAGE_1 developments
!     started 1/02/2016  CJS: STAGE_2 developments
!     started 24/03/2016 CJS: STAGE_3 developments
!     started 10/05/2016 CJS: STAGE_5 developments
!     started 13/06/2016 CJS: STAGE_6 developments
!     Include ground plane into incident field excitation 28/6/2016 CJS
!     Use frequency_spec structure for all frequency ranges 15/12/2016 CJS
!     December 2016 CJS Version 2
!     24/2/2017 CJS Allow the input name to include a path i.e. the _spec file does not need to be local.
!     28/2/2017 CJS Make the validation test circuit model optional
!     16/11/2017 CJS Include network synthesis process to replace s-domain transfer functions
!
!
PROGRAM spice_cable_bundle_model_builder

USE type_specifications
USE general_module
USE constants
USE cable_module
USE cable_bundle_module
USE spice_cable_bundle_module
USE MTL_analytic_solution
USE create_spice_model
USE frequency_spec

IMPLICIT NONE

! local variables

! command line argument value and length
character(len=filename_length)    :: argument1
integer                           :: argument1_length

character(len=filename_length)    :: spice_model_name_with_path  ! name of the spice model including the path
character(len=filename_length)    :: spice_model_path            ! path to the spice model_spec file
character(len=filename_length)    :: spice_model_name            ! name of the spice model
character(len=filename_length)    :: filename                    ! filename for the .spice_model_spec file
    
logical        :: file_exists

! Structure to hold the spice cable bundle model specification (see SPICE_CABLE_BUNDLE_MODULES/spice_cable_bundle_module.F90)
TYPE(spice_model_specification_type)    :: spice_bundle_model

! Structure to hold the validation circuit specification 
TYPE(spice_validation_test_type)    :: spice_validation_test

! incident field k vector dotted with the ground plane normal - used to check that the incident field vector is not from below the ground plane
real(dp)   :: k_dot_norm     

real(dp)   :: min_delay   ! used to redefine the minimum transmission line delay allowed in the transmission line sub-circuit

character(len=line_length)    :: line   ! used to read a line from the spice_model_spec file.

character  :: ch  ! used to read a character from the spice_model_spec file.

integer  :: ierr  ! integer to return error codes from file reads

! local termporary variables
integer  :: phrase_found

integer    :: tot_n_conductors
integer    :: system_dimension
integer    :: i

! START

  program_name="spice_cable_bundle_model_builder"
  run_status='Started'
  CALL write_program_status()
  
  CALL read_version()
    
  CALL write_license()

! Open the input file describing the spice cable bundle simulation (.spice_model_spec file)
! This file could be created by the associated GUI or otherwise generated

! get the first command line argument. If set then this is the cable name, if it is not set then
! it must be read

  CALL get_command_argument(1 , argument1, argument1_length)

  if (argument1_length.NE.0) then
  
    spice_model_name_with_path=trim(argument1)
  
  else

    write(*,*)'Enter the name of the spice cable bundle model specification data (without .spice_model_spec extension)'

    read(*,'(A)')spice_model_name_with_path

  end if
    
  CALL strip_path(spice_model_name_with_path,spice_model_path,spice_model_name)
  
  filename=trim(spice_model_name_with_path)//spice_model_spec_file_extn

  inquire(file=trim(filename),exist=file_exists)
  if (.NOT.file_exists) then
    run_status='ERROR: Cannot find the file:'//trim(filename)
    CALL write_program_status()
    STOP 1
  end if 

! set the version tag in the spice_bundle_model structure
  spice_bundle_model%version=SPICE_CABLE_MODEL_BUILDER_version
  
  spice_bundle_model%spice_model_name=spice_model_name
  
! open and read the .spice_model_spec file
  
  OPEN(unit=spice_model_spec_file_unit,file=filename)

  if (verbose) write(*,*)'Opened file:',trim(filename)

! read the bundle model name

! read the MOD directory information for the cable models, bundle models and spice bundle models
  read(spice_model_spec_file_unit,*)  ! comment line
  read(spice_model_spec_file_unit,'(A)')MOD_cable_lib_dir
  CALL path_format(MOD_cable_lib_dir)
  
  read(spice_model_spec_file_unit,*)  ! comment line
  read(spice_model_spec_file_unit,'(A)')MOD_bundle_lib_dir
  CALL path_format(MOD_bundle_lib_dir)
  
  read(spice_model_spec_file_unit,*)  ! comment line
  read(spice_model_spec_file_unit,'(A)')MOD_spice_bundle_lib_dir
  CALL path_format(MOD_spice_bundle_lib_dir)
  
  read(spice_model_spec_file_unit,*)  ! comment line
  read(spice_model_spec_file_unit,'(A)')spice_symbol_dir
  CALL path_format(spice_symbol_dir)

! ensure that the specified paths exist - make the MOD_bundle_lib_dir path if required

  if (.NOT.path_exists(MOD_cable_lib_dir)) then
    run_status='ERROR MOD_cable_lib_dir does not exist '//trim(MOD_cable_lib_dir)
    CALL write_program_status()
    STOP 1
  end if
  
  if (.NOT.path_exists(MOD_bundle_lib_dir)) then
    run_status='ERROR: MOD_bundle_lib_dir does not exist '//trim(MOD_bundle_lib_dir)
    CALL write_program_status()
    STOP 1
  end if
  
  CALL check_and_make_path(MOD_spice_bundle_lib_dir)
  
  if (.NOT.path_exists(spice_symbol_dir)) then
    run_status='ERROR: spice_symbol_dir does not exist '//trim(spice_symbol_dir)
    CALL write_program_status()
    STOP 1
  end if

  read(spice_model_spec_file_unit,*)          ! comment line
  read(spice_model_spec_file_unit,'(A)')spice_bundle_model%bundle%bundle_name

! read the bundle model

  CALL read_cable_bundle(spice_bundle_model%bundle,bundle_file_unit)

  tot_n_conductors=spice_bundle_model%bundle%tot_n_conductors
  system_dimension=spice_bundle_model%bundle%system_dimension
  
! read the cable bundle length

  read(spice_model_spec_file_unit,*)          ! comment line
  read(spice_model_spec_file_unit,*)spice_bundle_model%length

! read the Incident field excitation specification

  read(spice_model_spec_file_unit,*)          ! comment line
  read(spice_model_spec_file_unit,*)spice_bundle_model%Eamplitude
  read(spice_model_spec_file_unit,*)spice_bundle_model%ktheta,spice_bundle_model%kphi
  read(spice_model_spec_file_unit,*)spice_bundle_model%etheta,spice_bundle_model%ephi
  
! There is the possibility that the problem could be a single domain which is shielded so check for this
! We need to implement a check as to whether the last viable domain is an external domain
! There is the possibility that the last domain is shielded so no differential mode can be excited by the incident field
 
  if ( (spice_bundle_model%Eamplitude.NE.0d0).AND.    &
       (spice_bundle_model%bundle%tot_n_external_conductors.LT.2) ) then
       
    run_status='ERROR: There must be at least two conductors in the external domain for an incident field excitation'
    CALL write_program_status()
    STOP 1

  end if

! convert angles from degrees to radians
  spice_bundle_model%Ktheta=spice_bundle_model%Ktheta*pi/180d0
  spice_bundle_model%Kphi=spice_bundle_model%Kphi*pi/180d0
  
! only include incident field excitation terms if the amplitude is not zero
  if (spice_bundle_model%Eamplitude.NE.0d0) then
  
    spice_bundle_model%include_incident_field=.TRUE.

! work out the cartesian field components of the incident field
    CALL calc_incident_field_components(spice_bundle_model%Ktheta,spice_bundle_model%Kphi, &
                                        spice_bundle_model%Etheta,spice_bundle_model%Ephi, &
                                        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)
   
    if (spice_bundle_model%bundle%ground_plane_present) then
    
! Check that the incident field k vector is illuminating the cables and is not 
! incident from 'below' the ground plane

      k_dot_norm=spice_bundle_model%kx*spice_bundle_model%bundle%ground_plane_nx+   &
                 spice_bundle_model%ky*spice_bundle_model%bundle%ground_plane_ny
               
! k_dot_norm should be of the opposite sign to spice_bundle_model%bundle%ground_plane_cable_side

      if(verbose) then
        write(*,*)'ground_plane_normal:',spice_bundle_model%bundle%ground_plane_nx, &
                                         spice_bundle_model%bundle%ground_plane_ny,0d0
        write(*,*)'k.norm:',k_dot_norm
      end if ! verbose

      if (k_dot_norm*spice_bundle_model%bundle%ground_plane_cable_side.GT.small) then
    
        run_status='ERROR: The incident field excitation is from below the ground plane '
        CALL write_program_status()
        STOP 1
    
      end if
      
! check that the ground plane is aligned along the x axis. This is a restriction which could
! ultimately be removed...
 
      if ( (abs(spice_bundle_model%bundle%ground_plane_angle-pi/2d0).GT.small).OR.     &
           (abs(spice_bundle_model%bundle%ground_plane_x).GT.small)         .OR.     &
           (abs(spice_bundle_model%bundle%ground_plane_y).GT.small) )       then
           
        write(*,*) abs(spice_bundle_model%bundle%ground_plane_angle-pi/2d0)
        write(*,*) abs(spice_bundle_model%bundle%ground_plane_x)
        write(*,*) abs(spice_bundle_model%bundle%ground_plane_y)
           
        run_status='ERROR: The ground plane must be aligned along the x axis with an incident field excitation'
        CALL write_program_status()
        STOP 1
    
      end if ! ground plane not on the x axis

    end if ! ground plane present

  else
  
    spice_bundle_model%include_incident_field=.FALSE. 
    
  end if
  
! read the Transfer impedance model specification

  read(spice_model_spec_file_unit,'(A)')line  ! this could indicate the start of transfer impedance stuff
  
! look for the phrase 'transfer impedance' in the line. If it occurrs then read transfer impedance information

  CALL convert_to_lower_case(line,line_length)
  
  phrase_found=INDEX(line,'transfer impedance')
  
  if (phrase_found.NE.0) then  ! there are transfer impedance models required so read this data
  
    read(spice_model_spec_file_unit,*)spice_bundle_model%n_transfer_impedances
    
    ALLOCATE( spice_bundle_model%Zt_conductor(1:spice_bundle_model%n_transfer_impedances) )
    ALLOCATE( spice_bundle_model%Zt_direction(1:spice_bundle_model%n_transfer_impedances) )
    
    do i=1,spice_bundle_model%n_transfer_impedances

      read(spice_model_spec_file_unit,*)spice_bundle_model%Zt_conductor(i),spice_bundle_model%Zt_direction(i)
      
! check that the conductor number is in the appropriate range
      if ((spice_bundle_model%Zt_conductor(i).LT.1).OR.(spice_bundle_model%Zt_conductor(i).GT.tot_n_conductors)) then
        write(run_status,*)'ERROR: The transfer impedance conductor number should be in the range 1 to ',tot_n_conductors
        CALL write_program_status()
        STOP 1
      end if
      
      if ((spice_bundle_model%Zt_direction(i).NE.1).AND.(spice_bundle_model%Zt_direction(i).NE.-1)) then
        write(run_status,*)'ERROR: The transfer impedance coupling direction should be either 1 or -1'
        CALL write_program_status()
        STOP 1
      end if
      
    end do

  else

! there are no transfer impedance models required so set the number to zero and reset the file pointer
! to the beginning of the line
    spice_bundle_model%n_transfer_impedances=0
    backspace(spice_model_spec_file_unit)

  end if
    
  if (verbose) write(*,*)'Number of transfer impedance models=',spice_bundle_model%n_transfer_impedances
  
! read the next line to see if the 'no_validation_test' is set

  read(spice_model_spec_file_unit,'(A)')line  
  
! look for the phrase 'no_validation_test' in the line. If it occurrs then turn of the validation test circuit stuff

  CALL convert_to_lower_case(line,line_length)
  
  phrase_found=INDEX(line,'no_validation_test')
  
  if (phrase_found.NE.0) then
    
    run_validation_test=.FALSE.
    
  else
  
    backspace(spice_model_spec_file_unit)

! Validation test problem information
  
    if (verbose) then
      write(*,*)'tot_n_conductors',tot_n_conductors
      write(*,*)'system_dimension',system_dimension
    end if
  
! Allocate data for termination models

    ALLOCATE( spice_validation_test%Vs_end1(1:system_dimension+1) )  
    ALLOCATE( spice_validation_test%R_end1(1:system_dimension+1) )  
  
    ALLOCATE( spice_validation_test%Vs_end2(1:system_dimension+1) )  
    ALLOCATE( spice_validation_test%R_end2(1:system_dimension+1) )  
  
! read the end 1 termination model, voltage sources then resistances

    read(spice_model_spec_file_unit,*)          ! comment line

    do i=1,system_dimension+1
      read(spice_model_spec_file_unit,*,ERR=9030)spice_validation_test%Vs_end1(i)
    end do

    do i=1,system_dimension+1
      read(spice_model_spec_file_unit,*,ERR=9040)spice_validation_test%R_end1(i)
    end do

! read the end 2 termination model, voltage sources then resistances

    read(spice_model_spec_file_unit,*)          ! comment line

    do i=1,system_dimension+1
      read(spice_model_spec_file_unit,*,ERR=9050)spice_validation_test%Vs_end2(i)
    end do

    do i=1,system_dimension+1
      read(spice_model_spec_file_unit,*,ERR=9060)spice_validation_test%R_end2(i)
    end do

! read the type of analysis

    read(spice_model_spec_file_unit,*)          ! comment line
    read(spice_model_spec_file_unit,'(A)')ch
    if ( (ch.EQ.'A').OR.(ch.EQ.'a') ) then

      spice_validation_test%analysis_type=analysis_type_AC
    
      CALL read_and_set_up_frequency_specification(spice_validation_test%analysis_freq_spec,spice_model_spec_file_unit)
 
    else if ( (ch.EQ.'T').OR.(ch.EQ.'t') ) then

      spice_validation_test%analysis_type=analysis_type_TRANS
    
      read(spice_model_spec_file_unit,*)spice_validation_test%timestep,spice_validation_test%runtime
      read(spice_model_spec_file_unit,*)spice_validation_test%risetime,spice_validation_test%width

    else

      write(*,*)'Read character',ch
      run_status='ERROR: the analysis type should be ac or transient'
      CALL write_program_status()
      STOP 1
      
    end if

! read the output conductor number and end number

    read(spice_model_spec_file_unit,*)          ! comment line
    
! see if we have one or two conductors specified as well as the reference

! read the next line into a string then read from there.
    read(spice_model_spec_file_unit,'(A)')line  
    
    read(line,*,ERR=1000,END=1000)spice_validation_test%output_conductor,     &
                         spice_validation_test%output_conductor_ref, &
                         spice_validation_test%output_end
    GOTO 1010
    
1000 CONTINUE
    
    read(line,*,ERR=9020,END=9020)spice_validation_test%output_conductor,     &
                         spice_validation_test%output_end
                         
    spice_validation_test%output_conductor_ref=tot_n_conductors
    
1010 CONTINUE
  
! check that the conductor numbers are in the appropriate range
    if ( (spice_validation_test%output_conductor.LT.1).OR.       &
         (spice_validation_test%output_conductor.GT.tot_n_conductors) ) then
      write(run_status,*)'ERROR: The output conductor number should be in the range 1 to ',tot_n_conductors
      CALL write_program_status()
      STOP 1
    end if
    
    if ( (spice_validation_test%output_conductor_ref.LT.1) .OR.  &
         (spice_validation_test%output_conductor_ref.GT.tot_n_conductors) ) then
      write(run_status,*)'ERROR: The output conductor reference number should be in the range 1 to ',tot_n_conductors
      CALL write_program_status()
      STOP 1
    end if
  
    if ((spice_validation_test%output_end.NE.1).AND.(spice_validation_test%output_end.NE.2)) then
      write(run_status,*)'ERROR: The transfer impedance coupling direction should be either 1 or 2'
      CALL write_program_status()
      STOP 1
    end if

! read the output type (lin or dB)

    if (spice_validation_test%analysis_type.EQ.analysis_type_AC) then
  
      read(spice_model_spec_file_unit,'(A2)')spice_validation_test%output_type
    
      if ( (spice_validation_test%output_type.NE.'li').and.(spice_validation_test%output_type.NE.'dB') ) then
 
        run_status='ERROR the output type for ac analysis should be lin or dB'
        CALL write_program_status()
        STOP 1
    
      end if
    
    else
  
      spice_validation_test%output_type='li'
    
    end if
  
  end if ! run_validation_test
  
! Set deafult propagation correction transfer function fit information
  spice_bundle_model%Fit_model_order=0  
  CALL reset_frequency_specification(spice_bundle_model%prop_corr_fit_freq_spec)
  CALL set_up_frequency_specification(spice_bundle_model%prop_corr_fit_freq_spec)
  
! Read the optional propagation correction transfer function fit information
  read(spice_model_spec_file_unit,*,IOSTAT=ierr)spice_bundle_model%Fit_model_order
  if (ierr.NE.0) then
! Assume there is no filter fit information specified so move on to the next stage
    backspace(spice_model_spec_file_unit)
    goto 100
  end if
  
  write(*,*)'Reading the filter fit frequency range'
  
  CALL read_and_set_up_frequency_specification(spice_bundle_model%prop_corr_fit_freq_spec,spice_model_spec_file_unit)

100 continue
  
! The file can contain flags to control the running of the software and the output

  rewind(spice_model_spec_file_unit)

  do
    read(spice_model_spec_file_unit,*,END=200,ERR=200)line
    CALL convert_to_lower_case(line,line_length)

! Set flags according to the information at the end of the .spice_model_spec file
   
    if (INDEX(line,'verbose').NE.0) verbose=.TRUE.
    if (INDEX(line,'use_s_xfer').NE.0) use_s_xfer=.TRUE.
    if (INDEX(line,'no_s_xfer').NE.0) use_s_xfer=.FALSE.
    if (INDEX(line,'use_xie').NE.0) use_Xie=.TRUE.
    if (INDEX(line,'no_xie').NE.0) use_Xie=.FALSE.
    if (INDEX(line,'use_ltra').NE.0) use_LTRA=.TRUE.
    if (INDEX(line,'no_ltra').NE.0) use_LTRA=.FALSE.
    if (INDEX(line,'use_high_freq_zt_model').NE.0) high_freq_Zt_model=.TRUE.
    if (INDEX(line,'no_high_freq_zt_model').NE.0) high_freq_Zt_model=.FALSE.
    if (INDEX(line,'plot_real').NE.0) plot_real=.TRUE.
    if (INDEX(line,'plot_mag').NE.0) plot_real=.FALSE.
    
    if (INDEX(line,'use_analytic_i').NE.0) run_validation_test_Vbased=.FALSE.
    if (INDEX(line,'use_analytic_v').NE.0) run_validation_test_Vbased=.TRUE.
    
    if (INDEX(line,'min_delay').NE.0) then

! Redefine minimum delay allowed for transmission lines in the sub-circuit models.
! Transmission lines with delays less than this value are dealt with in a different manner.

      read(spice_model_spec_file_unit,*,END=200,ERR=200)min_delay  

! set all transmission line minimum delays to this value

      ZT_min_delay   = min_delay
      Einc_min_delay = min_delay
      Tz_min_delay   = min_delay

    end if
    
    if (INDEX(line,'rsmall').NE.0) then
    
! Redefine minimum resistance value in the sub-circuit model. Resistances less than this value are replaced by this value.

      read(spice_model_spec_file_unit,*,END=200,ERR=200)Rsmall

    end if
    
  end do  ! continue until all flags are read - indicated by an end of file.

200 CONTINUE

  CLOSE(unit=spice_model_spec_file_unit)
  
  if (verbose) then
    write(*,*)'Closed file:',trim(filename)
  end if
  
! Finished reading the .spice_model_spec file

! Create the spice subcircuit circuit model of the multi-conductor transmission line
  
  do spice_version=1,3    ! Loop over all three spice versions supported

! set the file extensions for each of the spice versions  
    if (spice_version.EQ.ngspice) then
    
      spice_model_file_extn =ngspice_spice_model_file_extn
      symbol_file_extn=symbol_file_extn_NGspice
      
    else if (spice_version.EQ.LTspice) then
    
      spice_model_file_extn =LTspice_spice_model_file_extn
      symbol_file_extn=symbol_file_extn_LTspice
    
    else if (spice_version.EQ.Pspice) then
    
      spice_model_file_extn =Pspice_spice_model_file_extn
! note: no symbol is produced here for Pspice
    
    end if ! spice version

    if (verbose) write(*,*)'CALLING: create_spice_subcircuit_model'
  
    CALL create_spice_subcircuit_model(spice_bundle_model)
        
! Create the spice schematic symbol for the multi-conductor transmission line
! Note that there is no process here for Pspice symbols
! The process for Pspice is to load the .lib file in the Pspice model editor 
! and create the symbol there.

    if (verbose) write(*,*)'CALLING: create_spice_subcircuit_symbol'
    
    if (spice_version.EQ.ngspice) then
    
      CALL create_spice_subcircuit_symbol_NGspice(spice_bundle_model)
      
    else if (spice_version.EQ.LTspice) then
    
      CALL create_spice_subcircuit_symbol_LTspice(spice_bundle_model)      
            
    end if ! spice version
  
  end do ! next spice version
  
  if (run_validation_test) then
  
! Create the analytic and circuit models for solution of validation test case: i.e. a model of the 
! terminations and link to the now existing spice subcircuit model of the multi-conductor 
! transmission line and then add the analysis type information 

! Analytic solution of validation test case

    if (spice_validation_test%analysis_type.EQ.analysis_type_AC) then
  
      if (verbose) write(*,*)'CALLING: frequency_domain_analysis'
      CALL frequency_domain_analysis(spice_bundle_model,spice_validation_test)
      if (verbose) write(*,*)'FINISHED: frequency_domain_analysis'
    
    else
  
      if (verbose) write(*,*)'CALLING: time_domain_analysis'
      CALL time_domain_analysis(spice_bundle_model,spice_validation_test)
      if (verbose) write(*,*)'FINISHED: time_domain_analysis'
    
    end if

! Create the spice subcircuit circuit model of the multi-conductor transmission line
  
    do spice_version=1,3    ! Loop over all three spice versions supported

! set the file extensions for each of the spice versions  
      if (spice_version.EQ.ngspice) then
    
        spice_model_file_extn =ngspice_spice_model_file_extn
        test_circuit_file_extn=ngspice_test_circuit_file_extn
      
      else if (spice_version.EQ.LTspice) then
    
        spice_model_file_extn =LTspice_spice_model_file_extn
        test_circuit_file_extn=LTspice_test_circuit_file_extn
    
      else if (spice_version.EQ.Pspice) then
    
        spice_model_file_extn =Pspice_spice_model_file_extn
        test_circuit_file_extn=Pspice_test_circuit_file_extn
    
      end if ! spice version
  
      if (verbose) write(*,*)'CALLING: create_spice_validation_test_circuit'
      CALL create_spice_validation_test_circuit(spice_bundle_model,spice_validation_test)
 
    end do ! next spice version
    
  end if   ! run_validation_test

! Deallocate memory
  CALL deallocate_spice_cable_bundle(spice_bundle_model)
  CALL deallocate_spice_validation_test(spice_validation_test)
  
  CALL deallocate_frequency_specification(spice_bundle_model%prop_corr_fit_freq_spec)
  CALL deallocate_frequency_specification(spice_validation_test%analysis_freq_spec)

! finish up

  run_status='Finished_Correctly'
  CALL write_program_status()
  
STOP

9020 CONTINUE
  write(run_status,*)'Error reading cable output condcutor(s) and end number'
  CALL write_program_status()
  STOP 1

9030 CONTINUE
  write(run_status,*)'Error reading voltage sources at end 1, conductor number ',i
  CALL write_program_status()
  STOP 1

9040 CONTINUE
  write(run_status,*)'Error reading termination resistances at end 1, conductor number ',i
  CALL write_program_status()
  STOP 1

9050 CONTINUE
  write(run_status,*)'Error reading voltage sources at end 2, conductor number ',i
  CALL write_program_status()
  STOP 1

9060 CONTINUE
  write(run_status,*)'Error reading termination resistances at end 2, conductor number ',i
  CALL write_program_status()
  STOP 1

END PROGRAM spice_cable_bundle_model_builder


