! ! 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 ! ! ! NAME ! SUBROUTINE create_global_domain_structure ! ! DESCRIPTION ! The processes implemented in this subroutine calculate the matrices which are required to ! characterise the multi-conductor cable propagation in both a local, domain based system for the Spice model development ! and in a global basis for analysis of the bundle as a whole for the validation test circuit. ! The matrices characterising the propagation are : ! the domain based 'high frequency' L and C matrices, ! the domain based frequency dependent Z and Y matrices, ! the global 'high frequency' L and C matrices, ! the global frequency dependent Z and Y matrices, ! the voltage and current domain decomposition matrices MI and MV ! ! For shielded domains the L, C, Z, and Y matrices are known from the cable data structures ! For any overshield domains and the external domain these matrices are calculated here via ! calls to the appopriate PUL calculation subroutines ! ! The processes implemented in this subroutine are summarised as follows: ! ! 1. Count the total number of conductors in the bundle and Allocate and reset the local data structures ! 2. Loop over the cables filling the referencing arrays with local information ! 3. For each cable, work out which domain it is in and hence its reference conductor number. ! 4. Count the number of conductors in the external domain to check whether it is viable i.e. at least 2 conductors ! 5. build the global_domain numbering, ignoring any unused domains ! 6. build the domain based L and C matrices plus the global MI and MV matrices and the global L and C matrices ! 7. Calculate the inductance and capacitance matrices for the external domains (domains within overshields and the external domain) ! 8. Copy the cable based conductor impedance (loss) models to the bundle structure ! 8b. Copy the cable based conductor labels to the bundle structure ! 9 save numbering information required for the transfer impedance calculation ! 10. deallocate local memory ! ! COMMENTS ! ! ! HISTORY ! started 2/12/2015 CJS ! 27/4/2016 CJS: Include a conductor based impedance (loss) model ! 24/5/2016 CJS: Fix errors in MI and MV matrices for multi-conductor overshield domains ! 7/7/2016 CJS: Allow the use of the Laplace solver for L,C,G matrix calculation in external and overshield domains. ! 9/9/2016 CJS: Fix problem with MV and MI matrix for the twisted pair model. Elements were being overwritten incorrectly. ! when adding the external conductor contribution to the domain decomposition matrices ! 4/10/2016 CJS: Save the local domain conductor numbering ! 17/5/2017 CJS: Work out which domains are Shielded Twisted Pair differential mode domains and flag these ! so that we can work out the is_shield flag properly in all circumstances. ! 18/10/2017 CJS: include 8b. Copy the cable based conductor labels to the bundle structure ! 16/11/2017 CJS Include network synthesis process to replace s-domain transfer functions ! 16/3/2018 CJS add y offset for ML_flex_cable ! 22/10/2019 CJS Fix bug with numbering here: overshields were numbered using terminal conductor number not global domain number ! 24/10/2019 CJS Allow mutliple layers of overshields (previously overshields could not be 'nested' ! (though they could cover shielded cables). ! SUBROUTINE create_global_domain_structure(bundle) USE type_specifications USE general_module USE constants USE cable_module USE cable_bundle_module USE PUL_parameter_module USE filter_module USE maths IMPLICIT NONE ! variables passed to subroutine type(bundle_specification_type),intent(INOUT) :: bundle ! local variables ! global cable, conductor and domain numbers and loop variables integer :: cable,cable_t integer :: tot_n_cables integer :: tot_n_cables_without_ground_plane integer :: tot_n_conductors,conductor,conductor_count,terminal_conductor integer :: tot_n_domains,tot_n_viable_domains,domain,domain_count integer :: tot_n_internal_domains ! local conductor and domain numbers and loop variables integer :: local_n_conductors,local_conductor,n_cable_conductors integer :: local_cable_conductor,local_domain_conductor integer :: local_n_domains,local_domain integer :: first_external_domain integer :: reference_conductor,global_reference_conductor integer :: first_external_conductor ! variables for looking at overshields and determining which domain cables are in integer :: tot_n_overshields,n_overshield_domains,overshield,reference_overshield real(dp)::radius_reference_overshield integer,allocatable :: overshield_shape(:) real(dp),allocatable :: overshield_x(:) real(dp),allocatable :: overshield_y(:) real(dp),allocatable :: overshield_r(:) real(dp),allocatable :: overshield_w(:) real(dp),allocatable :: overshield_w2(:) real(dp),allocatable :: overshield_h(:) integer,allocatable :: overshield_domain(:) integer,allocatable :: overshield_reference_terminal_conductor(:) integer,allocatable :: overshield_to_cable_number(:) integer,allocatable :: overshield_n_conductors(:) integer,allocatable :: overshield_terminal_conductor(:,:) real(dp) :: cable_x,cable_y,dist_cable_to_overshield_centre,cable_r logical :: is_overshield_domain ! referencing arrays integer,allocatable :: terminal_conductor_to_cable(:) integer,allocatable :: terminal_conductor_to_cable_local_domain(:) integer,allocatable :: terminal_conductor_to_global_domain(:) integer,allocatable :: terminal_conductor_to_global_domain_conductor(:) integer,allocatable :: terminal_conductor_to_reference_global_domain_conductor(:) integer,allocatable :: terminal_conductor_to_reference_terminal_conductor(:) integer,allocatable :: global_domain_conductor_to_terminal_conductor(:) logical,allocatable :: terminal_conductor_is_reference_conductor(:) logical,allocatable :: domain_is_TP_differential_mode(:) integer,allocatable :: cable_reference_domain(:) integer,allocatable :: cable_reference_conductor(:) integer,allocatable :: external_terminal_conductor(:) logical :: is_external_domain integer :: external_conductor_count integer,allocatable :: global_domain_reference_conductor(:) ! structure used by the Per-Unit-Length parameter calculation for overshield and external domains type(PUL_type) :: PUL ! loop variables for matrix operations integer :: dim integer :: row,col integer :: row_l,col_l integer :: row_g,col_g,row_g_ref character(LEN=3) :: conductor_string ! used to generate the conductor labels in the bundle real(dp),allocatable :: M1(:,:),M1I(:,:),M2(:,:) integer :: Mdim integer :: ierr real(dp) :: Mdiff ! START if(verbose) write(*,*)'CALLED: create_global_domain_structure' ! Copy some data to local variables for clarity of notation tot_n_cables=bundle%n_cables if (bundle%ground_plane_present) then tot_n_cables_without_ground_plane=tot_n_cables-1 else tot_n_cables_without_ground_plane=tot_n_cables end if if(verbose) write(*,*)' Total number of cables=',tot_n_cables if(verbose) write(*,*)' Total number of cables not including ground plane=',tot_n_cables_without_ground_plane ! 1a. Count the total number of conductors in the bundle tot_n_conductors=0 do cable=1,tot_n_cables tot_n_conductors = tot_n_conductors + bundle%cable(cable)%tot_n_conductors end do if(verbose) write(*,*)' Total number of conductors=',tot_n_conductors bundle%tot_n_conductors=tot_n_conductors bundle%system_dimension=tot_n_conductors-1 ! 1b Allocate and reset the local data structures ALLOCATE( terminal_conductor_to_cable(1:tot_n_conductors) ) ALLOCATE( terminal_conductor_to_cable_local_domain(1:tot_n_conductors) ) ALLOCATE( terminal_conductor_to_global_domain(1:tot_n_conductors) ) ALLOCATE( terminal_conductor_to_global_domain_conductor(1:tot_n_conductors) ) ALLOCATE( terminal_conductor_to_reference_global_domain_conductor(1:tot_n_conductors) ) ALLOCATE( terminal_conductor_to_reference_terminal_conductor(1:tot_n_conductors) ) ALLOCATE( terminal_conductor_is_reference_conductor(1:tot_n_conductors) ) ALLOCATE( global_domain_conductor_to_terminal_conductor(1:tot_n_conductors) ) terminal_conductor_to_cable(1:tot_n_conductors)=0 terminal_conductor_to_cable_local_domain(1:tot_n_conductors)=0 terminal_conductor_to_global_domain(1:tot_n_conductors)=0 terminal_conductor_to_global_domain_conductor(1:tot_n_conductors)=0 terminal_conductor_to_reference_global_domain_conductor(1:tot_n_conductors)=0 terminal_conductor_to_reference_terminal_conductor(1:tot_n_conductors)=0 terminal_conductor_is_reference_conductor(1:tot_n_conductors)=.FALSE. global_domain_conductor_to_terminal_conductor(1:tot_n_conductors)=0 ! numbering information required for the transfer impedance calculation ALLOCATE( bundle%terminal_conductor_is_shield_flag(1:bundle%tot_n_conductors) ) ALLOCATE( bundle%terminal_conductor_to_inner_domain(1:bundle%tot_n_conductors) ) ALLOCATE( bundle%terminal_conductor_to_outer_domain(1:bundle%tot_n_conductors) ) ALLOCATE( bundle%terminal_conductor_to_global_domain_conductor(1:bundle%tot_n_conductors) ) ALLOCATE( bundle%terminal_conductor_to_local_domain_conductor(1:bundle%tot_n_conductors) ) ALLOCATE( bundle%terminal_conductor_to_reference_terminal_conductor(1:bundle%tot_n_conductors) ) bundle%terminal_conductor_is_shield_flag(1:bundle%tot_n_conductors)=.FALSE. bundle%terminal_conductor_to_inner_domain(1:bundle%tot_n_conductors)=0 bundle%terminal_conductor_to_outer_domain(1:bundle%tot_n_conductors)=0 bundle%terminal_conductor_to_global_domain_conductor(1:bundle%tot_n_conductors)=0 bundle%terminal_conductor_to_local_domain_conductor(1:bundle%tot_n_conductors)=0 bundle%terminal_conductor_to_reference_terminal_conductor(1:bundle%tot_n_conductors)=0 ! 2. Loop over the cables filling the referencing arrays with local information ! Also count the total number of internal domains in the bundle conductor=0 tot_n_domains=0 do cable=1,tot_n_cables local_n_domains=bundle%cable(cable)%tot_n_domains tot_n_domains=tot_n_domains+bundle%cable(cable)%n_internal_domains do local_domain=1,local_n_domains local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain)-1 ! subtract 1 as the reference conductor is included do local_conductor=1,local_n_conductors conductor=conductor+1 terminal_conductor_to_cable(conductor)=cable terminal_conductor_to_cable_local_domain(conductor)=local_domain end do end do ! next conductor in this cable end do tot_n_internal_domains=tot_n_domains first_external_domain=tot_n_domains+1 if(verbose) then write(*,*)'Total number of internal domains=',tot_n_domains write(*,*)'First external domain=',first_external_domain end if ! check counting... if (conductor.NE.tot_n_conductors) then run_status='ERROR in create_global_domain_structure: last conductor.NE.tot_n_conductors' CALL write_program_status() STOP 1 end if ! 3. For each cable, work out which domain it is in and hence its reference conductor number. ! 3a. first count the overshields tot_n_overshields=0 do cable=1,tot_n_cables if (bundle%cable(cable)%cable_type.EQ.cable_geometry_type_overshield) then tot_n_overshields=tot_n_overshields+1 end if end do if(verbose) write(*,*)'Total number of over-shields=',tot_n_overshields ! 3b. Get the position of the overshields if (tot_n_overshields.GT.0) then ALLOCATE( overshield_shape(1:tot_n_overshields) ) ALLOCATE( overshield_x(1:tot_n_overshields) ) ALLOCATE( overshield_y(1:tot_n_overshields) ) ALLOCATE( overshield_r(1:tot_n_overshields) ) ALLOCATE( overshield_w(1:tot_n_overshields) ) ALLOCATE( overshield_w2(1:tot_n_overshields) ) ALLOCATE( overshield_h(1:tot_n_overshields) ) ALLOCATE( overshield_reference_terminal_conductor(1:tot_n_overshields) ) ALLOCATE( overshield_to_cable_number(1:tot_n_overshields) ) overshield=0 conductor_count=0 do cable=1,tot_n_cables if (bundle%cable(cable)%cable_type.EQ.cable_geometry_type_overshield) then overshield=overshield+1 overshield_to_cable_number(overshield)=cable overshield_shape(overshield)=circle overshield_x(overshield)=bundle%cable_x_offset(cable) overshield_y(overshield)=bundle%cable_y_offset(cable) overshield_r(overshield)=bundle%cable(cable)%parameters(1) ! overshield radius overshield_w(overshield)=0d0 overshield_w2(overshield)=0d0 overshield_h(overshield)=0d0 overshield_reference_terminal_conductor(overshield)=conductor_count+1 else ! This is not an overshield if ( (bundle%cable(cable)%cable_type.NE.cable_geometry_type_ground_plane) .AND. (overshield.NE.0) ) then ! check that oveshields are the last conductors defined in the bundle_spec file run_status='ERROR, Overshields should be the last cables defined in the bundle specification' CALL write_program_status() STOP 1 end if end if conductor_count=conductor_count+bundle%cable(cable)%tot_n_conductors end do ALLOCATE( overshield_domain(1:tot_n_overshields) ) overshield_domain(1:tot_n_overshields)=0 ALLOCATE( overshield_n_conductors(1:tot_n_overshields) ) overshield_n_conductors(1:tot_n_overshields)=0 ALLOCATE( overshield_terminal_conductor(1:tot_n_overshields,1:tot_n_conductors) ) ! over the top memory allocation here but simpler this way overshield_terminal_conductor(1:tot_n_overshields,1:tot_n_conductors)=0 end if ! n_overshields.GT.0 ! allocate array for domain reference conductors assuming worst case that all overshields and external domain are viable ALLOCATE( global_domain_reference_conductor(1:tot_n_domains+tot_n_overshields+1) ) global_domain_reference_conductor(1:tot_n_domains+tot_n_overshields+1)=0 ! 3c. Loop over cables and see whether it sits within an overshield or not ALLOCATE( cable_reference_domain(1:bundle%n_cables) ) cable_reference_domain(1:bundle%n_cables)=0 ALLOCATE( cable_reference_conductor(1:bundle%n_cables) ) cable_reference_conductor(1:bundle%n_cables)=0 n_overshield_domains=0 ! counter for overshield domains write(*,*)'**********************************************************************' do cable=1,tot_n_cables write(*,*) write(*,*)'Checking cable number',cable if (bundle%cable(cable)%cable_type.NE.cable_geometry_type_overshield) then ! IF THIS CABLE IS NOT AN OVERSHIELD THEN SEE WHETHER IT IS WITHIN AN OVERSHIELD write(*,*)'THIS CABLE IS NOT AN OVERSHIELD' cable_x=bundle%cable_x_offset(cable) cable_y=bundle%cable_y_offset(cable) ! find the smallest overshield enclosing this cable reference_overshield=0 radius_reference_overshield=1d30 do overshield=1,tot_n_overshields dist_cable_to_overshield_centre=sqrt( (cable_x-overshield_x(overshield))**2+ & (cable_y-overshield_y(overshield))**2 ) if ( dist_cable_to_overshield_centre.LT.overshield_r(overshield) ) then ! we conclude that this cable is within the overshield write(*,*)'This cable is inside overshield number',overshield if (radius_reference_overshield.GT.overshield_r(overshield)) then ! this overshield is smaller than the current reference overshield so this becomes the new reference overshield reference_overshield=overshield radius_reference_overshield=overshield_r(overshield) write(*,*)'This cable reference overshield has been updated to',reference_overshield end if ! is this the smallest overshield? end if ! is cable within this overshield? end do if (reference_overshield.NE.0) then ! this cable has been identified as being within an overshield if (overshield_domain(reference_overshield).EQ.0) then ! this overshield domain is unallocated so create a new domain tot_n_domains=tot_n_domains+1 n_overshield_domains=n_overshield_domains+1 if(verbose) write(*,*)'Creating overshield domain=',tot_n_domains overshield_domain(reference_overshield)=tot_n_domains global_domain_reference_conductor(tot_n_domains)=overshield_reference_terminal_conductor(reference_overshield) write(*,*)'This overshield domain is unallocated so create a new domain, domain=',tot_n_domains end if ! this overshield domain is unallocated cable_reference_domain(cable)=overshield_domain(reference_overshield) write(*,*)'Setting the cable reference domain to',overshield_domain(reference_overshield) end if ! this cable is within the overshield terminal_conductor=terminal_conductor+bundle%cable(cable)%tot_n_conductors ! update the terminal conductor count else ! THIS CABLE IS AN OVERSHIELD SO WE NEED TO CHECK WHETHER IT IS INSIDE ANY OTHER OVERSHIELDS write(*,*)'THIS CABLE IS AN OVERSHIELD' cable_x=bundle%cable_x_offset(cable) cable_y=bundle%cable_y_offset(cable) cable_r=bundle%cable(cable)%parameters(1) ! overshield radius ! find the smallest overshield enclosing this overshield if there is one reference_overshield=0 radius_reference_overshield=1d30 do overshield=1,tot_n_overshields cable_t=overshield_to_cable_number(overshield) if (cable_t.NE.cable) then ! don't check an overshield against itself dist_cable_to_overshield_centre=sqrt( (cable_x-overshield_x(overshield))**2+ & (cable_y-overshield_y(overshield))**2 ) if ( dist_cable_to_overshield_centre.LT.overshield_r(overshield) ) then ! we conclude that this cable is within the overshield write(*,*)'This overshield centre is inside overshield number',overshield !! Check that can be removed when we are happy with nexted overshields code ! run_status='ERROR, Nested overshields cannot be used in SACAMOS at the moment' ! CALL write_program_status() ! STOP 1 if (radius_reference_overshield.GT.overshield_r(overshield)) then ! this overshield is smaller than the current reference overshield so this becomes the new reference overshield if (overshield_r(overshield).GT.cable_r) then ! the cable is smaller than the overshield and hence is inside it ! Check that the lowest number overshield is the smaller. Overshields should be numbered inside to out if (cable_t.LT.cable) then run_status='ERROR, Nested overshields should be numbered in the order inside to out' CALL write_program_status() STOP 1 end if write(*,*)'This overshield is smaller than the reference overshield and is therefore inside it' reference_overshield=overshield radius_reference_overshield=overshield_r(overshield) write(*,*)'This cable reference overshield has been updated to',reference_overshield end if ! This overshield is smaller than the reference overshield and is therefore inside it end if ! is this the smallest overshield? end if ! is cable centre within this overshield? end if ! don't check an overshield against itself end do if (reference_overshield.NE.0) then ! this cable has been identified as being within an overshield if (overshield_domain(reference_overshield).EQ.0) then ! this overshield domain is unallocated so create a new domain tot_n_domains=tot_n_domains+1 n_overshield_domains=n_overshield_domains+1 if(verbose) write(*,*)'Creating overshield domain=',tot_n_domains overshield_domain(reference_overshield)=tot_n_domains global_domain_reference_conductor(tot_n_domains)=overshield_reference_terminal_conductor(reference_overshield) write(*,*)'This overshield domain is unallocated so create a new domain, domain=',tot_n_domains end if ! this overshield domain is unallocated cable_reference_domain(cable)=overshield_domain(reference_overshield) write(*,*)'Setting the cable reference domain to',overshield_domain(reference_overshield) end if ! this cable is within the overshield terminal_conductor=terminal_conductor+bundle%cable(cable)%tot_n_conductors ! update the terminal conductor count end if ! not an overshield end do ! next cable if (verbose) write(*,*) 'n_overshield_domains=',n_overshield_domains write(*,*)'**********************************************************************' ! 3c part 2. loop over the overshield domains and count the number of external conductors in each one do overshield=1,tot_n_overshields terminal_conductor=0 ! count the terminal conductor number conductor_count=0 ! count the number of condcutors referenced to this overshield do cable=1,tot_n_cables_without_ground_plane if (cable_reference_domain(cable).EQ.overshield_domain(overshield)) then ! this cable contributes its external conductors to the overshield first_external_conductor=terminal_conductor+bundle%cable(cable)%tot_n_conductors-bundle%cable(cable)%n_external_conductors+1 do conductor=1,bundle%cable(cable)%n_external_conductors conductor_count=conductor_count+1 overshield_terminal_conductor(overshield,conductor_count)=first_external_conductor+(conductor-1) end do end if terminal_conductor=terminal_conductor+bundle%cable(cable)%tot_n_conductors ! update the terminal conductor count end do ! next cable overshield_n_conductors(overshield)=conductor_count end do ! next overshield if (verbose) then write(*,*) write(*,*)'Overshield conductor information' do overshield=1,tot_n_overshields write(*,*)'Overshield:',overshield,' Number of condcutors=',overshield_n_conductors(overshield) write(*,*)' Overshield_conductor terminal_conductor ' do conductor=1,overshield_n_conductors(overshield) write(*,*)conductor,overshield_terminal_conductor(overshield,conductor) end do end do ! next overshield write(*,*) end if ! 3d. We now have unallocated reference domains, these are not in overshields so must be in the external domain ! 4. Count the number of conductors in the external domain to check whether it is viable i.e. at least 2 conductors bundle%tot_n_external_conductors=0 do cable=1,tot_n_cables if (cable_reference_domain(cable).EQ.0) then ! this cable reference domain must be the external domain bundle%tot_n_external_conductors=bundle%tot_n_external_conductors+bundle%cable(cable)%n_external_conductors end if ! reference domain not yet set end do ! next cable if(verbose) write(*,*)'Number of conductors in external domain=',bundle%tot_n_external_conductors ! 4b. Create an external domain and allocate unallocated reference domains now... ALLOCATE( external_terminal_conductor(1:bundle%tot_n_external_conductors) ) external_terminal_conductor(1:bundle%tot_n_external_conductors)=0 tot_n_viable_domains=tot_n_domains tot_n_domains=tot_n_domains+1 if (bundle%tot_n_external_conductors.GT.1) then tot_n_viable_domains=tot_n_viable_domains+1 end if if(verbose) write(*,*)'Creating external domain=',tot_n_domains terminal_conductor=0 external_conductor_count=0 do cable=1,tot_n_cables is_external_domain=.FALSE. if (cable_reference_domain(cable).EQ.0) then ! this cable reference domain must be the external domain cable_reference_domain(cable)=tot_n_domains is_external_domain=.TRUE. end if do local_conductor=1,bundle%cable(cable)%tot_n_conductors terminal_conductor=terminal_conductor+1 if ( (is_external_domain).AND.(bundle%cable(cable)%local_reference_conductor(local_conductor).EQ.0) ) then external_conductor_count=external_conductor_count+1 external_terminal_conductor(external_conductor_count)=terminal_conductor end if end do if (is_external_domain) then ! this cable reference domain must be the external domain global_domain_reference_conductor(tot_n_domains)=terminal_conductor end if end do ! next cable ! check the conductor count if (external_conductor_count.NE.bundle%tot_n_external_conductors) then run_status='ERROR in create_global_domain_structure: external_conductor_count.NE.bundle%tot_n_external_conductors' CALL write_program_status() STOP 1 end if if(verbose) then write(*,*)'External domain terminal conductors:' do conductor=1,bundle%tot_n_external_conductors write(*,*)'conductor=',external_terminal_conductor(conductor) end do ! next cable end if bundle%tot_n_domains=tot_n_viable_domains if(verbose) then write(*,*)'Total number of domains=',tot_n_domains write(*,*)'Total number of viable domains=',tot_n_viable_domains write(*,*)'Cable reference domain numbers:' do cable=1,tot_n_cables write(*,*)'cable=',cable,' reference domain=',cable_reference_domain(cable) end do ! next cable end if ALLOCATE( domain_is_TP_differential_mode(1:tot_n_domains) ) domain_is_TP_differential_mode(1:tot_n_domains)=.FALSE. ! 5. build the global_domain numbering, ignoring any unused domains conductor=0 ! this is the external conductor number domain_count=0 conductor_count=0 ! this is the conductor count for the domain based numbering ! 5a. Count conductors from internal domains initially do cable=1,tot_n_cables local_cable_conductor=0 local_n_domains=bundle%cable(cable)%tot_n_domains ! 17/5/2017 CJS Add a check here to flag twisted pair differential mode domains ! The check is hrd wired based on cable types if (bundle%cable(cable)%cable_type.EQ.cable_geometry_type_twisted_pair) then domain_is_TP_differential_mode(domain_count+1)=.TRUE. else if (bundle%cable(cable)%cable_type.EQ.cable_geometry_type_shielded_twisted_pair) then domain_is_TP_differential_mode(domain_count+1)=.TRUE. else if (bundle%cable(cable)%cable_type.EQ.cable_geometry_type_spacewire) then domain_is_TP_differential_mode(domain_count+1)=.TRUE. domain_is_TP_differential_mode(domain_count+3)=.TRUE. domain_is_TP_differential_mode(domain_count+5)=.TRUE. domain_is_TP_differential_mode(domain_count+7)=.TRUE. end if ! exclude the external domain do local_domain=1,local_n_domains if (local_domain.NE.local_n_domains) then ! This is an internal domain so add to the domain count domain_count=domain_count+1 domain=domain_count local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain)-1 ! subtract 1 as the reference conductor is included do local_conductor=1,local_n_conductors conductor=conductor+1 local_cable_conductor=local_cable_conductor+1 conductor_count=conductor_count+1 terminal_conductor_to_global_domain(conductor)=domain terminal_conductor_to_cable_local_domain(conductor)=local_conductor terminal_conductor_to_global_domain_conductor(conductor)=conductor_count bundle%cable(cable)%global_domain_conductor(local_cable_conductor)=conductor_count bundle%cable(cable)%terminal_conductor(local_cable_conductor)=conductor end do else ! This is an external domain so leave until later but count the global conductors. local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain)-1 ! subtract 1 as the reference conductor is included do local_conductor=1,local_n_conductors conductor=conductor+1 local_cable_conductor=local_cable_conductor+1 end do end if ! internal or external domain end do ! next conductor in this cable end do ! next cable ! 5b. Include the 'external' domain conductors now do domain=first_external_domain,tot_n_domains conductor=0 ! this is the external conductor number do cable=1,tot_n_cables local_cable_conductor=0 local_n_domains=bundle%cable(cable)%tot_n_domains do local_domain=1,local_n_domains if (local_domain.NE.local_n_domains) then ! This is an internal domain so this is already included, only count the conductors local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain)-1 ! subtract 1 as the reference conductor is included do local_conductor=1,local_n_conductors conductor=conductor+1 local_cable_conductor=local_cable_conductor+1 end do else ! This is an external domain so add the conductors if it is the currrent external domain local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain)-1 ! subtract 1 as the reference conductor is included do local_conductor=1,local_n_conductors conductor=conductor+1 local_cable_conductor=local_cable_conductor+1 if (cable_reference_domain(cable).EQ.domain) then conductor_count=conductor_count+1 terminal_conductor_to_global_domain(conductor)=domain terminal_conductor_to_cable_local_domain(conductor)=local_conductor terminal_conductor_to_global_domain_conductor(conductor)=conductor_count bundle%cable(cable)%global_domain_conductor(local_cable_conductor)=conductor_count bundle%cable(cable)%terminal_conductor(local_cable_conductor)=conductor end if ! this external domain is the current one to be included end do ! next local conductor end if ! internal or external domain end do ! next local domain end do ! next cable end do ! next external domain ! 5c. Set the global_domain_conductor_to_terminal_conductor from terminal_conductor_to_global_domain_conductor if (verbose) then write(*,*)'conductor,terminal_conductor_to_global_domain_conductor(conductor)' do conductor=1,tot_n_conductors write(*,*)conductor,terminal_conductor_to_global_domain_conductor(conductor) end do end if ! loop over terminal conductors do conductor=1,tot_n_conductors global_domain_conductor_to_terminal_conductor(terminal_conductor_to_global_domain_conductor(conductor))=conductor end do if (verbose) then write(*,*)'conductor,global_domain_conductor_to_terminal_conductor(conductor)' do conductor=1,tot_n_conductors write(*,*)conductor,global_domain_conductor_to_terminal_conductor(conductor) end do end if ! 22/10/2019 CJS Fix bug with numbering here: overshields were numbered using terminal conductor number ! not global domain conductor as it should be at this stage ! 5d. Renumber the reference conductors for overshield domains. At the moment these are terminal conductors ! not global domain conductors do overshield=1,tot_n_overshields domain=overshield_domain(overshield) reference_conductor=global_domain_reference_conductor(domain) global_reference_conductor=terminal_conductor_to_global_domain_conductor(reference_conductor) global_domain_reference_conductor(domain)=global_reference_conductor end do ! next overshield ! 5e. Set the global_domain_reference_conductor information, also flag all the reference conductors in internal domains conductor=0 ! this is the external conductor number write(*,*) write(*,*) write(*,*)' terminal cable local local_domain global cable local_ref ref terminal ref global ' write(*,*)' conductor domain conductor domain conductor conductor conductor domain conductor' do cable=1,tot_n_cables local_n_domains=bundle%cable(cable)%tot_n_domains local_cable_conductor=0 do local_domain=1,local_n_domains local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain)-1 ! subtract 1 as the reference conductor is included do local_domain_conductor=1,local_n_conductors conductor=conductor+1 local_cable_conductor=local_cable_conductor+1 reference_conductor=bundle%cable(cable)%local_reference_conductor(local_cable_conductor) if (reference_conductor.NE.0) then ! the reference conductor is defined locally terminal_conductor_to_reference_global_domain_conductor(conductor)= & bundle%cable(cable)%global_domain_conductor(reference_conductor) ! 27/4/2016 CJS domain=terminal_conductor_to_global_domain(conductor) ! 16/5/2016 this should be the global not the local number... global_domain_reference_conductor(domain)=reference_conductor global_domain_reference_conductor(domain)=bundle%cable(cable)%global_domain_conductor(reference_conductor) else ! the reference conductor is defined in terms of the reference domain of the cable domain=cable_reference_domain(cable) global_reference_conductor=global_domain_reference_conductor(domain) reference_conductor=global_domain_conductor_to_terminal_conductor(global_reference_conductor) terminal_conductor_to_reference_global_domain_conductor(conductor)= & terminal_conductor_to_global_domain_conductor(reference_conductor) reference_conductor=0 end if local_conductor=terminal_conductor_to_reference_global_domain_conductor(conductor) terminal_conductor_to_reference_terminal_conductor(conductor)= & global_domain_conductor_to_terminal_conductor(local_conductor) terminal_conductor_is_reference_conductor(terminal_conductor_to_reference_terminal_conductor(conductor))=.TRUE. write(*,8000)bundle%cable(cable)%terminal_conductor(local_cable_conductor),& cable,local_domain,local_domain_conductor, & terminal_conductor_to_global_domain(conductor), & local_cable_conductor,reference_conductor, & terminal_conductor_to_reference_terminal_conductor(conductor), & terminal_conductor_to_reference_global_domain_conductor(conductor) 8000 format(5I11,4I13) end do ! next local domain conductor end do ! next local domain end do ! next cable ! 6. Now that we have counted the number of domains we can allocate the ! domain based number of conductors and L and C matrices plus ! the global MI and MV matrices ! Note: this allocation includes non-viable domains ALLOCATE( bundle%n_conductors(1:tot_n_domains) ) bundle%n_conductors(1:tot_n_domains)=0 ALLOCATE( bundle%L(1:tot_n_domains) ) ALLOCATE( bundle%C(1:tot_n_domains) ) ALLOCATE( bundle%Z(1:tot_n_domains) ) ALLOCATE( bundle%Y(1:tot_n_domains) ) ! 6a. Count the number of conductors in each domain if (verbose) write(*,*)'terminal_conductor domain local_domain_conductor' do conductor=1,tot_n_conductors domain=terminal_conductor_to_global_domain(conductor) bundle%n_conductors(domain)=bundle%n_conductors(domain)+1 ! 4/10/2016 Save the local domain coonductor numbering bundle%terminal_conductor_to_local_domain_conductor(conductor)=bundle%n_conductors(domain) if (verbose) write(*,*)conductor,domain,bundle%terminal_conductor_to_local_domain_conductor(conductor) end do ! next conductor ! Note there may be unviable overshield domains which need to be excluded in the following loop... ! internal domains and overshield domains don't include the reference conductor so add this here do domain=1,tot_n_internal_domains+n_overshield_domains bundle%n_conductors(domain)=bundle%n_conductors(domain)+1 end do if (verbose) then write(*,*) write(*,*)'Number of conductors in each domain' write(*,*)' domain n_conductors' do domain=1,tot_n_domains write(*,*)domain,bundle%n_conductors(domain) end do end if ! allocate the global voltage and current domain transformation matrices ! strictly the dimension should be bundle%tot_n_conductors-1 ! this would require many checks later on to prevent array bounds problems with no ground plane specified ! so we allocate the extra space then ignore the last row and col when doing the domain decomposition dim=bundle%tot_n_conductors if(verbose) then write(*,*)'ALLOCATING global_MI and global_MV, dimension:',dim end if bundle%global_MI%dim=dim ALLOCATE( bundle%global_MI%mat(1:dim,1:dim) ) bundle%global_MI%mat(1:dim,1:dim)=0d0 bundle%global_MV%dim=dim ALLOCATE( bundle%global_MV%mat(1:dim,1:dim) ) bundle%global_MV%mat(1:dim,1:dim)=0d0 ! Allocate the conductor based impedance (loss) model and reset all the parameters ALLOCATE( bundle%conductor_impedance(1:dim) ) do conductor=1,bundle%tot_n_conductors bundle%conductor_impedance(conductor)%radius=0d0 bundle%conductor_impedance(conductor)%width=0d0 bundle%conductor_impedance(conductor)%height=0d0 bundle%conductor_impedance(conductor)%conductivity=0d0 bundle%conductor_impedance(conductor)%thickness=0d0 bundle%conductor_impedance(conductor)%Resistance_multiplication_factor=1d0 end do ! allocate the global inductance and capacitance matrices - these are used in the analytic solution ! which is used for validation dim=bundle%tot_n_conductors-1 if(verbose) then write(*,*)'ALLOCATING global_L and global_C, dimension:',dim end if bundle%global_L%dim=dim ALLOCATE( bundle%global_L%mat(1:dim,1:dim) ) bundle%global_L%mat(1:dim,1:dim)=0d0 bundle%global_C%dim=dim ALLOCATE( bundle%global_C%mat(1:dim,1:dim) ) bundle%global_C%mat(1:dim,1:dim)=0d0 if(verbose) then write(*,*)'ALLOCATING global_Z and global_Y, dimension:',dim end if bundle%global_Z%dim=dim ALLOCATE( bundle%global_Z%sfilter_mat(1:dim,1:dim) ) do row=1,dim do col=1,dim bundle%global_Z%sfilter_mat(row,col)=0d0 ! set all filters to zero filter for now end do end do bundle%global_Y%dim=dim ALLOCATE( bundle%global_Y%sfilter_mat(1:dim,1:dim) ) do row=1,dim do col=1,dim bundle%global_Y%sfilter_mat(row,col)=0d0 ! set all filters to zero filter for now end do end do ! Allocate the domain based terminal conductor list CJS 27/4/2016 ALLOCATE( bundle%terminal_conductor_list(1:bundle%tot_n_domains)) ! 6b. Copy the cable based internal domain L and C matrices to bundle structure ! and construct the global MI and MV matrices from the cable based structures terminal_conductor=0 ! this is the external conductor number domain_count=0 if (verbose) then write(*,*)'' write(*,*)'SET MI, MV matrices' write(*,*)'' end if do cable=1,tot_n_cables_without_ground_plane local_n_domains=bundle%cable(cable)%tot_n_domains local_cable_conductor=0 n_cable_conductors=bundle%cable(cable)%tot_n_conductors ! copy the cable based MI and MV matrices to the global structure. The cable based ! MI and MV matrices are on the basis of terminal_conductor numbering if (verbose) then write(*,*)'' write(*,*)'Copy MI, MV, cable=',cable,' of', tot_n_cables_without_ground_plane write(*,*)'Matrix dimension',n_cable_conductors+1 write(*,*)'intial terminal_conductor count=',terminal_conductor end if do row_l=1,n_cable_conductors+1 ! add 1 as the reference conductor must be included do col_l=1,n_cable_conductors+1 ! add 1 as the reference conductor must be included ! In the global MI, MV structure rows correspond to the global domain conductor number, cols correspond to the terminal conductor number if (row_l.NE.n_cable_conductors+1) then row_g=terminal_conductor_to_global_domain_conductor(terminal_conductor+row_l) else row_g=terminal_conductor_to_reference_global_domain_conductor(terminal_conductor+row_l-1) ! last conductor for this cable and the reference end if if (col_l.NE.n_cable_conductors+1) then col_g=terminal_conductor+col_l else col_g=terminal_conductor_to_reference_terminal_conductor(terminal_conductor+col_l-1) ! last conductor for this cable and the reference end if bundle%global_MI%mat(row_g,col_g)=bundle%cable(cable)%MI%mat(row_l,col_l) bundle%global_MV%mat(row_g,col_g)=bundle%cable(cable)%MV%mat(row_l,col_l) ! if (verbose) write(*,*)'Copy MV element',row_g,col_g,bundle%global_MV%mat(row_g,col_g) if (verbose) then write(*,'(A,A,I3,A,I3,A,I3,A,I3,F5.2,F5.2)')'Copy MI element',' row_g=',row_g,' col_g=',col_g, & ' row_l=',row_l,' col_l=',col_l,bundle%cable(cable)%MI%mat(row_l,col_l),bundle%cable(cable)%MV%mat(row_l,col_l) end if end do ! next col end do ! next row if (bundle%cable(cable)%cable_type.EQ.cable_geometry_type_overshield) then ! This is an overshield so invoke the special process for overshields ! Get the global domain number of the shield conductor row_g=terminal_conductor_to_global_domain_conductor(terminal_conductor+1) ! Get the global domain number of the shield reference conductor row_g_ref=terminal_conductor_to_reference_global_domain_conductor(terminal_conductor+1) ! Add all the non-zero elements of the MI matrix shield row to the shield reference row write(*,*)'Overshield cable',cable,' Copying row',row_g,' to row',row_g_ref do col_g=1,bundle%global_MI%dim ! In the global MI, MV structure rows correspond to the global domain conductor number, cols correspond to the terminal conductor number if (bundle%global_MI%mat(row_g,col_g).NE.0d0) then bundle%global_MI%mat(row_g_ref,col_g)=bundle%global_MI%mat(row_g,col_g) end if end do ! next col end if ! overshield do local_domain=1,local_n_domains ! exclude the external domain for now if (local_domain.NE.local_n_domains) then ! This is an internal domain so add to the domain count domain_count=domain_count+1 domain=domain_count ! 6c copy the domain based L and C matrices to the domain based L and C in the bundle structure # if (verbose) write(*,*)'Copy the domain based L and C matrices to the domain based L and C in the bundle structure' if (verbose) write(*,*)'domain=',domain dim=bundle%cable(cable)%L_domain(local_domain)%dim ALLOCATE( bundle%L(domain)%mat(dim,dim) ) bundle%L(domain)%dim=dim if (verbose) write(*,*)'Allocating bundle%L(domain) ,dim=',dim dim=bundle%cable(cable)%C_domain(local_domain)%dim ALLOCATE( bundle%C(domain)%mat(dim,dim) ) bundle%C(domain)%dim=dim if (verbose) write(*,*)'Allocating bundle%C(domain) ,dim=',dim dim=bundle%cable(cable)%Z_domain(local_domain)%dim ALLOCATE( bundle%Z(domain)%sfilter_mat(dim,dim) ) bundle%Z(domain)%dim=dim if (verbose) write(*,*)'Allocating bundle%Z(domain) ,dim=',dim dim=bundle%cable(cable)%Y_domain(local_domain)%dim ALLOCATE( bundle%Y(domain)%sfilter_mat(dim,dim) ) bundle%Y(domain)%dim=dim if (verbose) write(*,*)'Allocating bundle%Y(domain) ,dim=',dim local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain) do row_l=1,local_n_conductors-1 ! subtract 1 as the reference conductor is included do col_l=1,local_n_conductors-1 ! subtract 1 as the reference conductor is included bundle%L(domain)%mat(row_l,col_l)=bundle%cable(cable)%L_domain(local_domain)%mat(row_l,col_l) bundle%C(domain)%mat(row_l,col_l)=bundle%cable(cable)%C_domain(local_domain)%mat(row_l,col_l) bundle%Z(domain)%sfilter_mat(row_l,col_l)=bundle%cable(cable)%Z_domain(local_domain)%sfilter_mat(row_l,col_l) bundle%Y(domain)%sfilter_mat(row_l,col_l)=bundle%cable(cable)%Y_domain(local_domain)%sfilter_mat(row_l,col_l) ! copy the domain based L and C matrices to the global L and C in the bundle structure ! in the global L,C structure rows and columns correspond to the global_domain conductor number row_g=terminal_conductor_to_global_domain_conductor(terminal_conductor+row_l) col_g=terminal_conductor_to_global_domain_conductor(terminal_conductor+col_l) bundle%global_L%mat(row_g,col_g)=bundle%L(domain)%mat(row_l,col_l) bundle%global_C%mat(row_g,col_g)=bundle%C(domain)%mat(row_l,col_l) bundle%global_Z%sfilter_mat(row_g,col_g)=bundle%Z(domain)%sfilter_mat(row_l,col_l) bundle%global_Y%sfilter_mat(row_g,col_g)=bundle%Y(domain)%sfilter_mat(row_l,col_l) end do ! next column of matrix end do ! next row of matrix ! Added CJS 27/4/2016 bundle%terminal_conductor_list(domain)%n_elements=local_n_conductors ALLOCATE( bundle%terminal_conductor_list(domain)%element(1:local_n_conductors) ) do conductor=1,local_n_conductors-1 ! do reference conductor separately bundle%terminal_conductor_list(domain)%element(conductor)=terminal_conductor+conductor end do ! next conductor in this domain ! reference conductor reference_conductor=global_domain_reference_conductor(domain) ! note domain based numbering... write(*,*)'Domain=',domain write(*,*)'Global domain reference conductor=',reference_conductor bundle%terminal_conductor_list(domain)%element(local_n_conductors)= & global_domain_conductor_to_terminal_conductor(reference_conductor) terminal_conductor=terminal_conductor+local_n_conductors-1 ! subtract 1 as the count includes the reference conductor else ! This is an external domain so leave until later but count the global conductors. local_n_conductors=bundle%cable(cable)%local_domain_n_conductors(local_domain)-1 ! subtract 1 as the reference conductor is included do local_conductor=1,local_n_conductors terminal_conductor=terminal_conductor+1 end do end if ! internal or external domain end do ! next local domain end do ! next cable ! if (verbose) then write(*,*)'' write(*,*)'CHECK CONSISTENCY OF MI, MV matrices, (MV)T=(MI^-1)' write(*,*)'' Mdim=bundle%global_MI%dim ! This is the matrix dimensions however if there is no ground plane then the last conductor is ! the reference and hence the matrix dimension is reduced by one if (.NOT.bundle%ground_plane_present) then Mdim=Mdim-1 end if ALLOCATE( M1(1:Mdim,1:Mdim) ) ALLOCATE( M2(1:Mdim,1:Mdim) ) ALLOCATE( M1I(1:Mdim,1:Mdim) ) M1(1:Mdim,1:Mdim)=bundle%global_MI%mat(1:Mdim,1:Mdim) do row_l=1,Mdim do col_l=1,Mdim M2(row_l,col_l)=bundle%global_MV%mat(col_l,row_l) end do end do CALL dinvert_Gauss_Jordan(M1,Mdim,M1I,Mdim,ierr) Mdiff=0d0 do row_l=1,Mdim do col_l=1,Mdim Mdiff=Mdiff+abs( M1I(row_l,col_l)-M2(row_l,col_l) ) end do end do write(*,*)'MI=' CALL dwrite_matrix(M1,Mdim,Mdim,Mdim,0) write(*,*)'' write(*,*)'(MI)^-1^=' CALL dwrite_matrix(M1I,Mdim,Mdim,Mdim,0) write(*,*)'' write(*,*)'(MV)T=' CALL dwrite_matrix(M2,Mdim,Mdim,Mdim,0) write(*,*)'' write(*,*)'Matrix difference=',Mdiff write(*,*)'' DEALLOCATE( M1 ) DEALLOCATE( M2 ) DEALLOCATE( M1I ) if (Mdiff.GT.0.001) then write(*,*)'ERROR in create_global_domain_structure' write(*,*)'(MV)T .NE. (MI)^-1' STOP end if ! end if ! 7. Calculate the inductance and capacitance matrices for the external domains (domains within overshields and the external domain) if(verbose) write(*,*)'first external domain:',first_external_domain if(verbose) write(*,*)'total number of domains:',tot_n_domains overshield=0 ! counter for overshield domains do domain=first_external_domain,tot_n_viable_domains ! exclude the external domain if there is only one conductor ! allocate memory for the PUL parameter solver interface if(verbose) write(*,*)'Domain:',domain if(verbose) write(*,*)'Allocating PUL data structure for ',bundle%n_conductors(domain),' conductors' CALL allocate_and_reset_PUL_data(PUL,bundle%n_conductors(domain)) ! copy external conductor information to the PUL structure conductor=0 ! this provides a count of the external domain conductor numbering for PUL parameter calculation ! loop over cables do cable=1,bundle%n_cables if (cable_reference_domain(cable).EQ.domain) then ! The reference domain of this cable is the domain we are currently working on so add the external ! conductor information for this cable to the PUL structure do local_conductor=1,bundle%cable(cable)%n_external_conductors if (bundle%cable(cable)%cable_type.NE.cable_geometry_type_ground_plane) then conductor=conductor+1 ! add another conductor to the external domain if(verbose) write(*,*)'Adding conductor number',local_conductor,' from cable',cable,'. Domain conductor',conductor PUL%shape(conductor)=bundle%cable(cable)%external_model(local_conductor)%conductor_type PUL%x(conductor)=bundle%cable_x_offset(cable) PUL%y(conductor)=bundle%cable_y_offset(cable) PUL%rtheta(conductor)=bundle%cable_angle(cable) PUL%ox(conductor)=bundle%cable(cable)%external_model(local_conductor)%conductor_ox PUL%oy(conductor)=bundle%cable(cable)%external_model(local_conductor)%conductor_oy PUL%r(conductor)=bundle%cable(cable)%external_model(local_conductor)%conductor_radius PUL%rw(conductor)=bundle%cable(cable)%external_model(local_conductor)%conductor_width PUL%rw2(conductor)=bundle%cable(cable)%external_model(local_conductor)%conductor_width2 PUL%rh(conductor)=bundle%cable(cable)%external_model(local_conductor)%conductor_height PUL%rd(conductor)=bundle%cable(cable)%external_model(local_conductor)%dielectric_radius PUL%rdw(conductor)=bundle%cable(cable)%external_model(local_conductor)%dielectric_width PUL%rdh(conductor)=bundle%cable(cable)%external_model(local_conductor)%dielectric_height PUL%rdox(conductor)=bundle%cable(cable)%external_model(local_conductor)%dielectric_ox PUL%rdoy(conductor)=bundle%cable(cable)%external_model(local_conductor)%dielectric_oy PUL%epsr(conductor)=bundle%cable(cable)%external_model(local_conductor)%dielectric_epsr end if ! not a ground plane end do ! next cable external conductor end if ! cable contributes to this domain end do ! next cable ! Calculate the per-unit-length parameters (inductance and capacitance matrices) ! if this is an overshield domain then if (verbose) write(*,*)'domain=',domain,' last domain(check)=',first_external_domain+tot_n_overshields if(domain.LT.(first_external_domain+n_overshield_domains)) then overshield=overshield+1 if (verbose) write(*,*)'PUL parameter calculation for oversheild domain' ! no ground plane PUL%ground_plane_present=.FALSE. PUL%ground_plane_angle =0d0 PUL%ground_plane_offset =0d0 ! add overshield information if (verbose) write(*,*)'Add overshield information' is_overshield_domain=.TRUE. PUL%overshield_present=.TRUE. overshield=domain-first_external_domain+1 PUL%overshield_shape = overshield_shape(overshield) PUL%overshield_x = overshield_x(overshield) PUL%overshield_y = overshield_y(overshield) PUL%overshield_r = overshield_r(overshield) PUL%overshield_w = overshield_w(overshield) PUL%overshield_w2 = overshield_w2(overshield) PUL%overshield_h = overshield_h(overshield) PUL%epsr_background = 1d0 ! background permittivity =1.0 within an overshield i.e. cables are in air if (use_Laplace) then CALL PUL_LC_Laplace(PUL,bundle%bundle_name,bundle%Y_fit_model_order,bundle%Y_fit_freq_spec,domain) else if (verbose) write(*,*)'CALL PUL_LC_calc_overshield_wide_separation_approximation' CALL PUL_LC_calc_overshield_wide_separation_approximation(PUL) end if ! use_Laplace or not... else ! this is an external domain ! copy ground plane information PUL%ground_plane_present=bundle%ground_plane_present PUL%ground_plane_angle =bundle%ground_plane_angle PUL%ground_plane_offset =bundle%ground_plane_offset ! No overshield information is_overshield_domain=.FALSE. PUL%overshield_present=.FALSE. PUL%overshield_shape=0 PUL%overshield_r= 0d0 PUL%overshield_w= 0d0 PUL%overshield_w2= 0d0 PUL%overshield_h= 0d0 PUL%epsr_background = 1d0 ! background permittivity =1.0 i.e. cables are in air if (use_Laplace) then CALL PUL_LC_Laplace(PUL,bundle%bundle_name,bundle%Y_fit_model_order,bundle%Y_fit_freq_spec,domain) else CALL PUL_LC_calc_wide_separation_approximation(PUL) end if ! use_Laplace or not... end if ! last external domain (i.e. not an overshield domain) ! We now have the L and C matrices for this external domain ! Copy the domain based L and C matrices to the domain based L and C in the bundle structure if (verbose) write(*,*)'domain=',domain dim=PUL%L%dim if (verbose) write(*,*)'Allocating bundle%L(domain) ,dim=',dim ALLOCATE( bundle%L(domain)%mat(dim,dim) ) bundle%L(domain)%dim=dim dim=PUL%C%dim if (verbose) write(*,*)'Allocating bundle%C(domain) ,dim=',dim ALLOCATE( bundle%C(domain)%mat(dim,dim) ) bundle%C(domain)%dim=dim dim=PUL%Zfilter%dim if (verbose) write(*,*)'Allocating bundle%Z(domain) ,dim=',dim Bundle%Z(domain)%dim=dim ALLOCATE(Bundle%Z(domain)%sfilter_mat(dim,dim)) dim=PUL%Yfilter%dim if (verbose) write(*,*)'Allocating bundle%Y(domain) ,dim=',dim Bundle%Y(domain)%dim=dim ALLOCATE(Bundle%Y(domain)%sfilter_mat(dim,dim)) local_n_conductors=bundle%n_conductors(domain) if (is_overshield_domain) then if (verbose) write(*,*)'Copying L, C, Z, Y matrices in overshield domain, n_conductors=',local_n_conductors, & overshield_n_conductors(overshield)+1 do row_l=1,local_n_conductors-1 ! Note that the reference conductor is included in the conductor count here do col_l=1,local_n_conductors-1 ! Note that the reference conductor is included in the conductor count here ! In the global L,C structure rows and columns correspond to the global_domain conductor number row_g=terminal_conductor_to_global_domain_conductor(overshield_terminal_conductor(overshield,row_l)) col_g=terminal_conductor_to_global_domain_conductor(overshield_terminal_conductor(overshield,col_l)) bundle%L(domain)%mat(row_l,col_l)=PUL%L%mat(row_l,col_l) bundle%C(domain)%mat(row_l,col_l)=PUL%C%mat(row_l,col_l) bundle%Z(domain)%sfilter_mat(row_l,col_l)=PUL%Zfilter%sfilter_mat(row_l,col_l) bundle%Y(domain)%sfilter_mat(row_l,col_l)=PUL%Yfilter%sfilter_mat(row_l,col_l) ! copy the domain based L and C matrices to the global L and C in the bundle structure bundle%global_L%mat(row_g,col_g)=bundle%L(domain)%mat(row_l,col_l) bundle%global_C%mat(row_g,col_g)=bundle%C(domain)%mat(row_l,col_l) ! copy the domain based Z and Y filter matrices to the global Z and Y in the bundle structure bundle%global_Z%sfilter_mat(row_g,col_g)=bundle%Z(domain)%sfilter_mat(row_l,col_l) bundle%global_Y%sfilter_mat(row_g,col_g)=bundle%Y(domain)%sfilter_mat(row_l,col_l) end do ! next column of matrix end do ! next row of matrix ! Added CJS 27/4/2016 bundle%terminal_conductor_list(domain)%n_elements=local_n_conductors ALLOCATE( bundle%terminal_conductor_list(domain)%element(1:local_n_conductors) ) do conductor=1,local_n_conductors-1 ! do reference conductor separately bundle%terminal_conductor_list(domain)%element(conductor)=overshield_terminal_conductor(overshield,conductor) end do ! next conductor in this domain ! reference conductor reference_conductor=global_domain_reference_conductor(domain) ! note domain based numbering... bundle%terminal_conductor_list(domain)%element(local_n_conductors)= & global_domain_conductor_to_terminal_conductor(reference_conductor) else ! external domain write(*,*)'External domain, n_conductors=',local_n_conductors,' dim=',local_n_conductors-1 do row_l=1,local_n_conductors-1 ! subtract 1 as the reference conductor is included do col_l=1,local_n_conductors-1 ! subtract 1 as the reference conductor is included ! In the global L,C structure rows and columns correspond to the bundle_domain conductor number row_g=terminal_conductor_to_global_domain_conductor(external_terminal_conductor(row_l)) col_g=terminal_conductor_to_global_domain_conductor(external_terminal_conductor(col_l)) if (verbose) write(*,*)'Copy L,C from PUL structure' bundle%L(domain)%mat(row_l,col_l)=PUL%L%mat(row_l,col_l) bundle%C(domain)%mat(row_l,col_l)=PUL%C%mat(row_l,col_l) if (verbose) write(*,*)'Copy Z,Y from PUL structure' bundle%Z(domain)%sfilter_mat(row_l,col_l)=PUL%Zfilter%sfilter_mat(row_l,col_l) bundle%Y(domain)%sfilter_mat(row_l,col_l)=PUL%Yfilter%sfilter_mat(row_l,col_l) ! copy the domain based L and C matrices to the global L and C in the bundle structure if (verbose) write(*,*)'Copy L,C from bundle structure' bundle%global_L%mat(row_g,col_g)=bundle%L(domain)%mat(row_l,col_l) bundle%global_C%mat(row_g,col_g)=bundle%C(domain)%mat(row_l,col_l) if (verbose) write(*,*)'Copy Z,Y from bundle structure' ! copy the domain based Z and Y filter matrices to the global Z and Y in the bundle structure bundle%global_Z%sfilter_mat(row_g,col_g)=bundle%Z(domain)%sfilter_mat(row_l,col_l) bundle%global_Y%sfilter_mat(row_g,col_g)=bundle%Y(domain)%sfilter_mat(row_l,col_l) end do ! next column of matrix end do ! next row of matrix ! Added CJS 27/4/2016 bundle%terminal_conductor_list(domain)%n_elements=local_n_conductors ALLOCATE( bundle%terminal_conductor_list(domain)%element(1:local_n_conductors) ) do conductor=1,local_n_conductors-1 ! do reference conductor separately bundle%terminal_conductor_list(domain)%element(conductor)=external_terminal_conductor(conductor) end do ! next conductor in this domain ! reference conductor reference_conductor=global_domain_reference_conductor(domain) ! note domain based numbering... bundle%terminal_conductor_list(domain)%element(local_n_conductors)= & global_domain_conductor_to_terminal_conductor(reference_conductor) end if ! external domain CALL deallocate_PUL_data(PUL) end do ! next external domain ! 8. Copy the cable based conductor impedance (loss) models to the bundle structure conductor=0 ! count of terminal conductors do cable=1,tot_n_cables do local_conductor=1,bundle%cable(cable)%tot_n_conductors conductor=conductor+1 ! copy the conductor impedance model for this cable conductor to the bundle structure bundle%conductor_impedance(conductor)%impedance_model_type= & bundle%cable(cable)%conductor_impedance(local_conductor)%impedance_model_type bundle%conductor_impedance(conductor)%radius= & bundle%cable(cable)%conductor_impedance(local_conductor)%radius bundle%conductor_impedance(conductor)%width= & bundle%cable(cable)%conductor_impedance(local_conductor)%width bundle%conductor_impedance(conductor)%height= & bundle%cable(cable)%conductor_impedance(local_conductor)%height bundle%conductor_impedance(conductor)%conductivity= & bundle%cable(cable)%conductor_impedance(local_conductor)%conductivity bundle%conductor_impedance(conductor)%thickness= & bundle%cable(cable)%conductor_impedance(local_conductor)%thickness bundle%conductor_impedance(conductor)%Resistance_multiplication_factor= & bundle%cable(cable)%conductor_impedance(local_conductor)%Resistance_multiplication_factor if((bundle%conductor_impedance(conductor)%impedance_model_type.EQ.impedance_model_type_filter).OR. & (bundle%conductor_impedance(conductor)%impedance_model_type.EQ.impedance_model_type_cylindrical_shield)) then bundle%conductor_impedance(conductor)%ZT_filter= & bundle%cable(cable)%conductor_impedance(local_conductor)%ZT_filter end if end do ! next conductor on this cable end do ! next cable ! 8b. Copy the cable based conductor labels to the bundle structure ALLOCATE( bundle%conductor_label(1:bundle%tot_n_conductors) ) conductor=0 ! count of terminal conductors do cable=1,tot_n_cables do local_conductor=1,bundle%cable(cable)%tot_n_conductors conductor=conductor+1 ! copy the conductor impedance model for this cable conductor to the bundle structure write(conductor_string,'(I3)')conductor bundle%conductor_label(conductor)='Conductor number '//conductor_string//'. '// & trim(bundle%cable(cable)%conductor_label(local_conductor)) end do ! next conductor on this cable end do ! next cable ! 9 save numbering information required for the transfer impedance calculation ! first loop over shielded domains. The reference conductor for each domain is a shield (by definition) ! apart from the shielded twisted pair differential mode exception ! so record this hence set out the inner domain number for shields write(*,*)'****************************************************************' do domain=1,bundle%tot_n_domains-1 ! note we exclude the exterior domain here reference_conductor=global_domain_reference_conductor(domain) terminal_conductor=global_domain_conductor_to_terminal_conductor(reference_conductor) write(*,*)'domain=',domain,' reference_conductor=',reference_conductor,' terminal_conductor=',terminal_conductor if (.NOT.domain_is_TP_differential_mode(domain)) then bundle%terminal_conductor_is_shield_flag(terminal_conductor)=.TRUE. bundle%terminal_conductor_to_inner_domain(terminal_conductor)=domain end if end do ! next conductor write(*,*)'****************************************************************' ! work out the outer domain for each conductor and the associated reference conductor do conductor=1,bundle%tot_n_conductors bundle%terminal_conductor_to_outer_domain(conductor)=terminal_conductor_to_global_domain(conductor) bundle%terminal_conductor_to_global_domain_conductor(conductor)=terminal_conductor_to_global_domain_conductor(conductor) bundle%terminal_conductor_to_reference_terminal_conductor(conductor)= & terminal_conductor_to_reference_terminal_conductor(conductor) end do ! next conductor ! 10. finish up if (allocated( overshield_shape )) DEALLOCATE( overshield_shape) if (allocated( overshield_x )) DEALLOCATE( overshield_x) if (allocated( overshield_y )) DEALLOCATE( overshield_y) if (allocated( overshield_r )) DEALLOCATE( overshield_r) if (allocated( overshield_w )) DEALLOCATE( overshield_w) if (allocated( overshield_w2 )) DEALLOCATE( overshield_w2) if (allocated( overshield_h )) DEALLOCATE( overshield_h) if (allocated( overshield_domain )) DEALLOCATE( overshield_domain) if (allocated( overshield_reference_terminal_conductor)) DEALLOCATE( overshield_reference_terminal_conductor ) if (allocated( overshield_to_cable_number)) DEALLOCATE( overshield_to_cable_number ) if (allocated( global_domain_reference_conductor )) DEALLOCATE( global_domain_reference_conductor ) DEALLOCATE( cable_reference_conductor ) DEALLOCATE( cable_reference_domain ) ! Deallocate the referencing arrays DEALLOCATE( terminal_conductor_to_cable ) DEALLOCATE( terminal_conductor_to_cable_local_domain ) DEALLOCATE( terminal_conductor_to_global_domain ) DEALLOCATE( terminal_conductor_to_global_domain_conductor ) DEALLOCATE( terminal_conductor_to_reference_global_domain_conductor ) DEALLOCATE( terminal_conductor_to_reference_terminal_conductor ) DEALLOCATE( terminal_conductor_is_reference_conductor ) DEALLOCATE( global_domain_conductor_to_terminal_conductor ) DEALLOCATE( external_terminal_conductor ) if (allocated( domain_is_TP_differential_mode )) DEALLOCATE( domain_is_TP_differential_mode ) END SUBROUTINE create_global_domain_structure