! This file is part of SACAMOS, State of the Art CAble MOdels in 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-2017 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 create_spice_validation_test_circuit ! ! NAME ! create_spice_validation_test_circuit ! ! AUTHORS ! Chris Smartt ! ! DESCRIPTION ! This subroutine creates the Spice circuit model for the cable bundle ! with the resistive terminations and voltage sources and the ! simulation parameters i.e. a ready to run circuit file. ! ! The process is as follows: ! STAGE 1: Open the circuit file, allocate memory and set up the node numbering ! STAGE 2: set up the circuit element names ! STAGE 3: write circuit elements to file ! STAGE 3a: write circuit excitation voltage sources to file ! STAGE 3b: write termination impedance networks ! STAGE 3c: write incident field excitation source if required ! STAGE 3d: write link to transmission line sub-circuit model ! STAGE 3e: write circuit outputs to file taking into accout the different spice syntaxes for output specifications ! STAGE 4: close file and deallocate memory ! ! COMMENTS ! STAGE_1 Ngspice only ! STAGE_4 Ngspice, Pspice and LTspice ! ! HISTORY ! ! started 9/12/2015 CJS: STAGE_1 developments ! 22/4/2016 CJS: STAGE_4 developments: we can't use a common reference node at both ends now due to the d.c. resistances added into the ! transmission line sub-circuit so it has been changed ! 15/6/2016 CJS: Incident field excitation requires a voltage to be supplied to two additional terminals on the multi-conductor sub-circuit ! interface to supply the incident field source function ! 24/8/2016 CJS: Change the writing format for the transmission line model subcircuit to remove long lines (this is a problem for Pspice) ! ! SUBROUTINE create_spice_validation_test_circuit(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 IMPLICIT NONE ! variables passed to the subroutine TYPE(spice_model_specification_type),intent(IN) :: spice_bundle_model ! spice bundle model information TYPE(spice_validation_test_type),intent(IN) :: spice_validation_test ! spice validation test circuit information ! local variables character(len=filename_length) :: filename character(len=filename_length) :: spice_subcircuit_filename integer :: n_conductors ! node numbering and component name stuff integer :: node ! variables for external circuit, end 1 integer :: end1_reference_node integer,allocatable :: Vs_end1_nodes(:) ! conductor based end 1 voltage list integer,allocatable :: R_end1_nodes(:) ! conductor based end 1 resistance list character(len=spice_name_length),allocatable :: Vs_end1_name(:) ! conductor based end 1 voltage source name list character(len=spice_name_length),allocatable :: R_end1_name(:) ! conductor based end 1 resistance name list ! variables for external circuit, end 2 integer :: end2_reference_node integer,allocatable :: Vs_end2_nodes(:) ! conductor based end 2 voltage list integer,allocatable :: R_end2_nodes(:) ! conductor based end 2 resistance list character(len=spice_name_length),allocatable :: Vs_end2_name(:) ! conductor based end 2 voltage source name list character(len=spice_name_length),allocatable :: R_end2_name(:) ! conductor based end 2 resistance name list ! variables for incident field excitation source if requuired integer :: Einc_node1 integer :: Einc_node2 character(len=spice_name_length) :: Einc_name integer :: output_node,output_reference_node character(len=spice_name_length) :: output_node_name character(len=spice_name_length) :: output_node_name2 character(len=spice_name_length) :: name1 character(len=spice_name_length) :: name2 integer,allocatable :: node_list(:) ! Resistance value to write real(dp) :: Rvalue ! loop variables integer :: row,col integer :: i ! START ! STAGE1: Open the circuit file, allocate memory and set up the node numbering ! open the file for the spice validation model - this goes in the current working directory... filename=trim(spice_bundle_model%spice_model_name)//test_circuit_file_extn OPEN(unit=test_circuit_file_unit,file=filename) write(*,*)'Opened file:',trim(filename) ! Allocate memory n_conductors=spice_bundle_model%bundle%tot_n_conductors ALLOCATE( Vs_end1_nodes(n_conductors) ) ALLOCATE( R_end1_nodes(n_conductors) ) ALLOCATE( Vs_end1_name(n_conductors) ) ALLOCATE( R_end1_name(n_conductors) ) ALLOCATE( Vs_end2_nodes(n_conductors) ) ALLOCATE( R_end2_nodes(n_conductors) ) ALLOCATE( Vs_end2_name(n_conductors) ) ALLOCATE( R_end2_name(n_conductors) ) ! set up the termination circuit nodes first, source end then load end. node=0 end1_reference_node=node ! this is the reference node for end 1 of the circuit (and the global reference node) node=node+1 end2_reference_node=node ! this is the reference node for end 2 of the circuit do row=1,n_conductors node=node+1 Vs_end1_nodes(row)=node end do do row=1,n_conductors ! We cannot now use the same reference at both ends node=node+1 Vs_end2_nodes(row)=node end do do row=1,n_conductors node=node+1 R_end1_nodes(row)=node end do do row=1,n_conductors node=node+1 R_end2_nodes(row)=node end do if (spice_bundle_model%include_incident_field) then node=node+1 Einc_node1=node Einc_node2=end1_reference_node ! i.e. the global reference node for the external circuit end if ! include_incident_field ! STAGE 2: set up the circuit element names do row=1,n_conductors name1='VS_' CALL add_integer_to_string(name1,row,Vs_end1_name(row)) end do do row=1,n_conductors name1='RS_' CALL add_integer_to_string(name1,row,R_end1_name(row)) end do do row=1,n_conductors name1='VL_' CALL add_integer_to_string(name1,row,Vs_end2_name(row)) end do do row=1,n_conductors name1='RL_' CALL add_integer_to_string(name1,row,R_end2_name(row)) end do if (spice_bundle_model%include_incident_field) then Einc_name='V_Einc' end if ! include_incident_field ! STAGE 3: write circuit elements to file if (spice_version.EQ.ngspice) then write(test_circuit_file_unit,'(A)')'Ngspice multi-conductor transmission line validation model' else if (spice_version.EQ.LTspice) then write(test_circuit_file_unit,'(A)')'LTspice multi-conductor transmission line validation model' else if (spice_version.EQ.Pspice) then write(test_circuit_file_unit,'(A)')'Pspice multi-conductor transmission line validation model' end if ! spice version write(test_circuit_file_unit,'(A,A)')'* Created by Spice cable model builder ',trim(SPICE_CABLE_MODEL_BUILDER_version) write(test_circuit_file_unit,'(A)')'*' write(test_circuit_file_unit,'(A)')'* Voltage sources at end 1' ! STAGE 3a: write circuit excitation to file taking into accout the different spice syntaxes for output specifications if (spice_validation_test%analysis_type.EQ.analysis_type_AC) then do row=1,n_conductors ! could specify magnitude AND phase here but use specified amplitude and set phase to 0 at the moment write(test_circuit_file_unit,'(A20,2I6,A4,2ES16.6)')Vs_end1_name(row),Vs_end1_nodes(row),end1_reference_node, & ' AC ',spice_validation_test%Vs_end1(row),0.0 end do else if (spice_validation_test%analysis_type.EQ.analysis_type_TRANS) then do row=1,n_conductors write(test_circuit_file_unit,'(A20,2I6,A,5ES16.6,A)')Vs_end1_name(row),Vs_end1_nodes(row),end1_reference_node, & ' EXP( 0.0 ',spice_validation_test%Vs_end1(row),0.0,spice_validation_test%risetime, & spice_validation_test%width,spice_validation_test%risetime,' )' end do end if write(test_circuit_file_unit,'(A)')'* Voltage sources at end 2' if (spice_validation_test%analysis_type.EQ.analysis_type_AC) then do row=1,n_conductors ! could specify magnitude AND phase here but use specified amplitude and set phase to 0 at the moment write(test_circuit_file_unit,'(A20,2I6,A4,2ES16.6)')Vs_end2_name(row),Vs_end2_nodes(row),end2_reference_node, & ' AC ',spice_validation_test%Vs_end2(row),0.0 end do else if (spice_validation_test%analysis_type.EQ.analysis_type_TRANS) then do row=1,n_conductors write(test_circuit_file_unit,'(A20,2I6,A,5ES16.6,A)')Vs_end2_name(row),Vs_end2_nodes(row),end2_reference_node, & ' EXP( 0.0 ',spice_validation_test%Vs_end2(row),0.0,spice_validation_test%risetime, & spice_validation_test%width,spice_validation_test%risetime,' )' end do end if ! STAGE 3b: write termination impedance networks write(test_circuit_file_unit,'(A)')'* Impedance network at end 1' ! note that the source impedance could be complex in the subroutine call - assumes a resistive diagonal matrix here... do row=1,n_conductors Rvalue=max(Rsmall,spice_validation_test%R_end1(row)) write(test_circuit_file_unit,'(A20,2I6,ES16.6)')R_end1_name(row),R_end1_nodes(row),Vs_end1_nodes(row),Rvalue end do write(test_circuit_file_unit,'(A)')'* Impedance network at end 2' ! note that the load impedance could be complex in the subroutine call - assumes a resistive diagonal matrix here... do row=1,n_conductors Rvalue=max(Rsmall,spice_validation_test%R_end2(row)) write(test_circuit_file_unit,'(A20,2I6,ES16.6)')R_end2_name(row),R_end2_nodes(row),Vs_end2_nodes(row),Rvalue end do ! STAGE 3c: write incident field excitation source if required if (spice_bundle_model%include_incident_field) then write(test_circuit_file_unit,'(A)')'* Incident field excitation source' if (spice_validation_test%analysis_type.EQ.analysis_type_AC) then ! could specify magnitude AND phase here but use specified amplitude and set phase to 0 at the moment write(test_circuit_file_unit,'(A20,2I6,A4,2ES16.6)')Einc_name,Einc_node1,Einc_node2, & ' AC ',spice_bundle_model%Eamplitude,0.0 else if (spice_validation_test%analysis_type.EQ.analysis_type_TRANS) then write(test_circuit_file_unit,'(A20,2I6,A,5ES16.6,A)')Einc_name,Einc_node1,Einc_node2, & ' EXP( 0.0 ',spice_bundle_model%Eamplitude,0.0,spice_validation_test%risetime, & spice_validation_test%width,spice_validation_test%risetime,' )' end if ! include a resistance in series with the incident field voltage source to avoid a 'dangling' node write(test_circuit_file_unit,'(A7,2I6,A4)')'R_Einc ',Einc_node1,Einc_node2,' 1E6' end if ! include_incident_field ! Link to transmission line sub-circuit write(test_circuit_file_unit,'(A)')'* Link to transmission line sub-circuit' ! note: include voltage reference nodes now ALLOCATE( node_list(n_conductors) ) write(test_circuit_file_unit,'(A)')'xtransmission_line' node_list(1:n_conductors)=R_end1_nodes(1:n_conductors) CALL write_long_node_list(n_conductors,node_list,max_spice_line_length,test_circuit_file_unit) node_list(1:n_conductors)=R_end2_nodes(1:n_conductors) CALL write_long_node_list(n_conductors,node_list,max_spice_line_length,test_circuit_file_unit) if (spice_bundle_model%include_incident_field) then write(test_circuit_file_unit,'(A,2I6)')'+',Einc_node1,Einc_node2 end if write(test_circuit_file_unit,'(A,A)')'+',trim(spice_bundle_model%spice_model_name) spice_subcircuit_filename=trim(MOD_spice_bundle_lib_dir)//trim(spice_bundle_model%spice_model_name)//spice_model_file_extn ! include the transmission line subcircuit file here. write(test_circuit_file_unit,'(A)')'*' write(test_circuit_file_unit,'(A,A)')'.INCLUDE ',trim(spice_subcircuit_filename) write(test_circuit_file_unit,'(A)')'*' ! STAGE 3e: write circuit outputs to file taking into accout the different spice syntaxes for output specifications ! work out the output voltage node number if (spice_validation_test%output_end.eq.1) then output_node =R_end1_nodes(spice_validation_test%output_conductor) output_reference_node =R_end1_nodes(spice_validation_test%output_conductor_ref) else output_node =R_end2_nodes(spice_validation_test%output_conductor) output_reference_node =R_end2_nodes(spice_validation_test%output_conductor_ref) end if if (spice_validation_test%analysis_type.EQ.analysis_type_AC) then ! log frequency output if (spice_validation_test%analysis_freq_spec%freq_range_type.EQ.'log') then write(test_circuit_file_unit,'(A,I10,2ES16.6)')'.AC DEC ', & NINT(spice_validation_test%analysis_freq_spec%n_frequencies/ & log10(spice_validation_test%analysis_freq_spec%fmax/spice_validation_test%analysis_freq_spec%fmin)), & spice_validation_test%analysis_freq_spec%fmin,spice_validation_test%analysis_freq_spec%fmax else ! linear frequency output write(test_circuit_file_unit,'(A,I10,2ES16.6)')'.AC LIN ', & spice_validation_test%analysis_freq_spec%n_frequencies, & spice_validation_test%analysis_freq_spec%fmin, & spice_validation_test%analysis_freq_spec%fmax end if ! frequency range type write(test_circuit_file_unit,'(A)')'*' if (spice_version.EQ.Pspice) then name1='V(' CALL add_integer_to_string(name1,output_node,name2) if (spice_validation_test%output_end.eq.2) then name1=trim(name2)//',' CALL add_integer_to_string(name1,output_reference_node,name2) end if output_node_name=trim(name2)//')' name1='VP(' CALL add_integer_to_string(name1,output_node,name2) if (spice_validation_test%output_end.eq.2) then name1=trim(name2)//',' CALL add_integer_to_string(name1,output_reference_node,name2) end if output_node_name2=trim(name2)//')' write(test_circuit_file_unit,'(A,A,A,A)')'.PRINT ac ',trim(output_node_name),' ',trim(output_node_name2) else ! ngspice or LTspice if (spice_validation_test%output_type.EQ.'li') then if (plot_real) then name1='V(' else name1='VM(' end if else if (spice_validation_test%output_type.EQ.'dB') then name1='VDB(' end if CALL add_integer_to_string(name1,output_node,name2) name1=trim(name2)//',' CALL add_integer_to_string(name1,output_reference_node,name2) output_node_name=trim(name2)//')' write(test_circuit_file_unit,'(A,A)')'.PRINT ac ',trim(output_node_name) end if if ( (spice_version.EQ.LTspice) .OR.(spice_version.EQ.Pspice) ) then write(test_circuit_file_unit,'(A)')'.PROBE' end if else ! Transient simulation if (spice_validation_test%output_type.EQ.'li') then name1='V(' else if (spice_validation_test%output_type.EQ.'dB') then name1='VDB(' end if CALL add_integer_to_string(name1,output_node,name2) name1=trim(name2)//',' CALL add_integer_to_string(name1,output_reference_node,name2) output_node_name=trim(name2)//')' if (spice_version.NE.LTspice) then write(test_circuit_file_unit,'(A,2ES16.6)')'.TRAN ', & spice_validation_test%timestep,spice_validation_test%runtime else ! Add a timestep limit for LTpsice write(test_circuit_file_unit,'(A,2ES16.6,A,ES16.6)')'.TRAN ', & spice_validation_test%timestep,spice_validation_test%runtime,' 0.0 ',spice_validation_test%timestep/10d0 end if write(test_circuit_file_unit,'(A)')'*' write(test_circuit_file_unit,'(A,A)')'.PRINT tran ',output_node_name if (spice_version.EQ.Pspice) then write(test_circuit_file_unit,'(A)')'*' write(test_circuit_file_unit,'(A)')'.PROBE' end if end if write(test_circuit_file_unit,'(A)')'*' write(test_circuit_file_unit,'(A)')'*' write(test_circuit_file_unit,'(A)')'.END' 8100 format(10I4) ! STAGE 4: Close file and Deallocate memory CLOSE(unit=test_circuit_file_unit) write(*,*)'Closed file:',trim(filename) DEALLOCATE( Vs_end1_nodes) DEALLOCATE( R_end1_nodes ) DEALLOCATE( Vs_end1_name ) DEALLOCATE( R_end1_name ) DEALLOCATE( Vs_end2_nodes ) DEALLOCATE( R_end2_nodes ) DEALLOCATE( Vs_end2_name ) DEALLOCATE( R_end2_name ) RETURN END SUBROUTINE create_spice_validation_test_circuit