cable_bundle_model_builder.F90
19.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
!
! 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 cable_bundle_model_builder
!
! NAME
! cable_bundle_model_builder
!
! AUTHORS
! Chris Smartt
!
! DESCRIPTION
! The cable_bundle_model_builder brings together a number of cable models, ground plane and
! overshield models with their position in the bundle cross section as required to build a model of a cable bundle.
! The output of the bundle_model_builder code is a file name.bundle which can be used to generate Spice cable bundle models
! for a particular modellling scenario using the program spice_cable_bundle_model_builder
!
! The input to the program is the name of a cablebundle specification file. A file name.bundle_spec must exist, containing
! all the data required to specify a cable bundle.
!
! The .cable files referred to in the .bundle_spec file are looked for in a directory specified in the .bundle_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 output of the cable_bundle_model_builder code is a file name.bundle which can be used as an input to the
! spice_cable_bundle_model_builder software
!
! The .bundle file is placed in a directory specified in the .bundle_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 bundle name specified in the command line i.e. 'cable_bundle_model_builder name'
! or it the name is absent from the command line, the user is prompted for the name.
!
! COMMENTS
! Update to V2
!
!
! HISTORY
!
! started 17/11/2015 CJS: STAGE_1 developments
! started 3/2/2016 CJS: STAGE_2 developments - multi-conductor bundles
! started 22/3/2016 CJS: STAGE_3 developments - multi-domain bundles (shielded cables)
! started 13/4/2016 CJS: Simplify the code and improve the notation. At this stage the format of the .bundle_spec file changed
! Shift the complex bundle building processes into BUNDLE_DOMAIN_CREATION/create_global_domain_structure.F90
! 20/4/2016 CJS: Allow the code to read x,y OR x, y, theta formats for cable position and orientation. Similar for ground plane
! 27/4/2016 CJS: Include a conductor based impedance (loss) model
! 29/6/2016 CJS: Check that the cables are all on one side of the ground plane if it is present
! December 2016 CJS Version 2: Rationalise cable types so that there is only a single version of each type of cable
! 24/2/2017 CJS Allow the input name to include a path i.e. the _spec file does not need to be local.
! 13/3/2018 CJS Add flag for direct/ iterative matrix solver in Laplace solution and inf/finite ground plane
! 19/6/2018 CJS Add flag for Neumann/ Asymptotic boundary condition in Laplace solver. Default is Neumann
!
PROGRAM cable_bundle_model_builder
USE type_specifications
USE general_module
USE constants
USE cable_module
USE cable_bundle_module
USE PUL_parameter_module
USE filter_module
USE maths
USE bundle_domain_creation
IMPLICIT NONE
! local variables
! command line argument value and length if it exists
character(len=filename_length) :: argument1
integer :: argument1_length
character(len=filename_length) :: bundle_name_with_path ! name of the bundle including the path
character(len=filename_length) :: bundle_path ! path to the bundle_spec file
character(len=filename_length) :: bundle_name ! name of the bundle
character(len=filename_length) :: filename ! filename of the .bundle_spec file
! structure for the bundle specification (see CABLE_BUNDLE_MODULES/cable_bundle_module.F90)
type(bundle_specification_type) ::bundle_spec
logical :: file_exists
character(len=line_length) :: line
integer :: ierr,ierr2 ! integers to return error codes from file reads
! loop variables
integer :: cable
integer :: domain
integer :: dim
logical :: must_use_laplace
! START
program_name="cable_bundle_model_builder"
run_status='Started'
CALL write_program_status()
CALL read_version()
CALL write_license()
! Open the input file describing the cable bundle parameters
! This file could be created by the associated GUI or otherwise generated
CALL get_command_argument(1 , argument1, argument1_length)
if (argument1_length.NE.0) then
bundle_name_with_path=trim(argument1)
else
write(*,*)'Enter the name of the cable bundle specification data (without .bundle_spec extension)'
read(*,'(A)')bundle_name_with_path
end if
CALL strip_path(bundle_name_with_path,bundle_path,bundle_name)
filename=trim(bundle_name_with_path)//bundle_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 cable_bundle structure
bundle_spec%version=SPICE_CABLE_MODEL_BUILDER_version
! open and read the .bundle_spec file
OPEN(unit=bundle_spec_file_unit,file=filename)
write(*,*)'Opened file:',trim(filename)
! set the bundle name to be the same as the name of the bundle specification data
bundle_spec%bundle_name=bundle_name
! read .bundle_spec file.
! read the MOD directory information for the cable and bundle models
read(bundle_spec_file_unit,*) ! comment line
read(bundle_spec_file_unit,'(A)')MOD_cable_lib_dir
CALL path_format(MOD_cable_lib_dir)
read(bundle_spec_file_unit,*) ! comment line
read(bundle_spec_file_unit,'(A)')MOD_bundle_lib_dir
CALL path_format(MOD_bundle_lib_dir)
! ensure that the paths exist
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
CALL check_and_make_path(MOD_bundle_lib_dir)
read(bundle_spec_file_unit,*,IOSTAT=ierr)bundle_spec%n_cables
if (ierr.NE.0) then
run_status='ERROR reading bundle_spec%n_cables '
CALL write_program_status()
STOP 1
end if
! Allocate the cable based data structures including an additional cable for the ground plane if required
ALLOCATE( bundle_spec%cable(1:bundle_spec%n_cables+1) )
ALLOCATE( bundle_spec%cable_x_offset(1:bundle_spec%n_cables+1) )
ALLOCATE( bundle_spec%cable_y_offset(1:bundle_spec%n_cables+1) )
ALLOCATE( bundle_spec%cable_angle(1:bundle_spec%n_cables+1) )
! read the name (which indicates the name.cable file specifying the cable)
! and position in the x-y bundle cross section of each cable
do cable=1,bundle_spec%n_cables
read(bundle_spec_file_unit,'(A)',IOSTAT=ierr)bundle_spec%cable(cable)%cable_name
if (ierr.NE.0) then
run_status='ERROR reading bundle_spec%cable(cable)%cable_name '
CALL write_program_status()
STOP 1
end if
read(bundle_spec_file_unit,'(A)',IOSTAT=ierr)line
read(line,*,IOSTAT=ierr)bundle_spec%cable_x_offset(cable), &
bundle_spec%cable_y_offset(cable), &
bundle_spec%cable_angle(cable)
if (ierr.NE.0) then
! Try reading the old format, set angle to zero and read x and y only
bundle_spec%cable_angle(cable)=0d0
read(line,*,IOSTAT=ierr2)bundle_spec%cable_x_offset(cable), &
bundle_spec%cable_y_offset(cable)
if (ierr2.NE.0) then
run_status='ERROR reading bundle_spec%cable_x_offset(cable),bundle_spec%cable_y_offset(cable)'
CALL write_program_status()
STOP 1
end if
end if
bundle_spec%cable_angle(cable)=bundle_spec%cable_angle(cable)*pi/180d0 ! convert angle to radians
end do ! read the informaton for the next cable
! read ground plane specification (if it exists, if it is absent then assume we have no ground plane)
read(bundle_spec_file_unit,'(A)',IOSTAT=ierr)line
if (ierr.NE.0) then
run_status='ERROR reading ground plane present/ absent information'
CALL write_program_status()
STOP 1
end if
CALL convert_to_lower_case(line,line_length)
bundle_spec%n_cables_without_ground_plane=bundle_spec%n_cables
if (line.eq.'ground_plane') then
bundle_spec%ground_plane_present=.TRUE.
! include an additional cable in the cable list for the ground plane (space for this is already allocated)
bundle_spec%n_cables=bundle_spec%n_cables+1
cable=bundle_spec%n_cables
! We now assume that the ground plane is along the x axis in the bundle cross section
! set x, y, theta, angle and offset to 0
bundle_spec%ground_plane_x=0d0
bundle_spec%ground_plane_y=0d0
bundle_spec%ground_plane_theta=0d0
bundle_spec%ground_plane_angle=pi/2d0
bundle_spec%ground_plane_nx=cos(bundle_spec%ground_plane_angle)
bundle_spec%ground_plane_ny=sin(bundle_spec%ground_plane_angle)
bundle_spec%ground_plane_offset=bundle_spec%ground_plane_nx*bundle_spec%ground_plane_x+ &
bundle_spec%ground_plane_ny*bundle_spec%ground_plane_y
! copy to cable structure
bundle_spec%cable_x_offset(cable)=bundle_spec%ground_plane_x
bundle_spec%cable_y_offset(cable)=bundle_spec%ground_plane_y
bundle_spec%cable_angle(cable)=bundle_spec%ground_plane_theta
! create conductor impedance model for the new cable
ALLOCATE(bundle_spec%cable(cable)%conductor_impedance(1:1))
bundle_spec%cable(cable)%conductor_impedance(1)%impedance_model_type=impedance_model_type_PEC
bundle_spec%cable(cable)%conductor_impedance(1)%Resistance_multiplication_factor=1d0
bundle_spec%cable(cable)%conductor_impedance(1)%radius=0d0
bundle_spec%cable(cable)%conductor_impedance(1)%conductivity=0d0
else if (line.eq.'no_ground_plane') then
bundle_spec%ground_plane_present=.FALSE. ! no ground plane present
! set x, y, theta, angle and offset to 0
bundle_spec%ground_plane_x=0d0
bundle_spec%ground_plane_y=0d0
bundle_spec%ground_plane_theta=0d0
bundle_spec%ground_plane_angle=0d0
bundle_spec%ground_plane_offset=0d0
else ! no ground plane information was given
bundle_spec%ground_plane_present=.FALSE. ! no ground plane present
! go back one line of the input file before continuing to read the .bundle_spec file
backspace(unit=bundle_spec_file_unit)
end if ! ground plane
! Set deafult propagation correction transfer function fit information
bundle_spec%Y_fit_model_order=0
CALL reset_frequency_specification(bundle_spec%Y_fit_freq_spec)
CALL set_up_frequency_specification(bundle_spec%Y_fit_freq_spec)
! Read the optional propagation correction transfer function fit information
read(bundle_spec_file_unit,*,IOSTAT=ierr)bundle_spec%Y_fit_model_order
if (ierr.NE.0) then
! Assume there is no filter fit information specified so move on to the next stage
backspace(bundle_spec_file_unit)
goto 100
end if
write(*,*)'Reading the filter fit frequency range'
CALL read_and_set_up_frequency_specification(bundle_spec%Y_fit_freq_spec,bundle_spec_file_unit)
100 continue
! the file can contain flags to control the running of the software and the output
rewind(bundle_spec_file_unit)
write(*,*)'Processing flags'
do
read(bundle_spec_file_unit,*,END=110,ERR=110)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_laplace').NE.0) use_Laplace=.TRUE.
if (INDEX(line,'no_laplace').NE.0) use_Laplace=.FALSE.
if (INDEX(line,'plot_potential').NE.0) plot_potential=.TRUE.
if (INDEX(line,'no_plot_potential').NE.0) plot_potential=.FALSE.
if (INDEX(line,'plot_mesh').NE.0) plot_mesh=.TRUE.
if (INDEX(line,'no_plot_mesh').NE.0) plot_mesh=.FALSE.
if (INDEX(line,'direct_solver').NE.0) direct_solver=.TRUE.
if (INDEX(line,'iterative_solver').NE.0) direct_solver=.FALSE.
if (INDEX(line,'inf_gnd').NE.0) inf_gnd=.TRUE.
if (INDEX(line,'finite_gnd').NE.0) inf_gnd=.FALSE.
if (INDEX(line,'abc').NE.0) use_ABC=.TRUE.
if (INDEX(line,'neumann').NE.0) use_ABC=.FALSE.
! redefine mesh generation parameters if required
if (INDEX(line,'laplace_boundary_constant').NE.0) then
read(bundle_spec_file_unit,*,END=9000,ERR=9000)Laplace_boundary_constant
end if
if (INDEX(line,'laplace_surface_mesh_constant').NE.0) then
read(bundle_spec_file_unit,*,END=9000,ERR=9000)Laplace_surface_mesh_constant
end if
if (INDEX(line,'twisted_pair_equivalent_radius').NE.0) then
read(bundle_spec_file_unit,*,END=9000,ERR=9000)Twisted_pair_equivalent_radius
end if
if (INDEX(line,'max_mesh_edge_length').NE.0) then
read(bundle_spec_file_unit,*,END=9000,ERR=9000)max_mesh_edge_length
end if
if (INDEX(line,'gp_edge_length').NE.0) then
read(bundle_spec_file_unit,*,END=9000,ERR=9000)gp_edge_length
end if
if (INDEX(line,'cg_tol').NE.0) then
read(bundle_spec_file_unit,*,END=9000,ERR=9000)cg_tol
end if
end do ! continue until all flags are read - indicated by an end of file.
110 CONTINUE
! close the bundle_spec file
CLOSE(unit=bundle_spec_file_unit)
write(*,*)'Closed file:',trim(filename)
write(*,*)'Total number of cables (including ground plane):',bundle_spec%n_cables
write(*,*)'Number of cables (not including ground plane) :',bundle_spec%n_cables_without_ground_plane
! read the .cable files required to build the bundle
! Also check which cable types need to use the Laplace solver in the external domain
must_use_laplace=.FALSE.
do cable=1,bundle_spec%n_cables_without_ground_plane
CALL read_cable( bundle_spec%cable(cable),cable_file_unit)
if ( (bundle_spec%cable(cable)%cable_type.EQ.cable_geometry_type_flex_cable) &
.OR.(bundle_spec%cable(cable)%cable_type.EQ.cable_geometry_type_ML_flex_cable) ) then
must_use_laplace=.TRUE.
end if
if ( (bundle_spec%cable(cable)%cable_type.EQ.cable_geometry_type_dconnector) &
.AND.(bundle_spec%n_cables.GT.1) ) then
must_use_laplace=.TRUE.
end if
end do ! read the next cable file in the bundle
! Check whether Laplace solver must be used
if (must_use_laplace.AND.(.NOT.use_Laplace)) then
run_status='ERROR: The laplace solver must be used for this cable bundle.'
CALL write_program_status()
STOP 1
end if
! set the ground plane cable data (if it is present)
if (bundle_spec%ground_plane_present) then
cable=bundle_spec%n_cables
bundle_spec%cable(cable)%version=SPICE_CABLE_MODEL_BUILDER_version
bundle_spec%cable(cable)%cable_name='ground plane'
bundle_spec%cable(cable)%cable_type_string='ground_plane'
bundle_spec%cable(cable)%cable_type=cable_geometry_type_ground_plane
CALL ground_plane_set_parameters(bundle_spec%cable(cable))
CALL ground_plane_set_internal_domain_information(bundle_spec%cable(cable))
! check that all the conductors are on one side of the ground plane
CALL check_cables_wrt_ground_plane(bundle_spec)
end if
! Write the bundle cross section (condcutors and dielectrics) to files suitable for gnuplot
CALL plot_bundle_cross_section(bundle_spec)
! check whether there is any intersection between cables
CALL check_cable_intersection(bundle_spec)
! now we have the complete bundle specification information we can go and build the bundle structure
CALL create_global_domain_structure(bundle_spec)
! Create the arrays of x and y coordinates of each conductor which are used in the incident field excitation
! moved from before create_global_domain_structure
CALL set_conductor_positions_for_Einc(bundle_spec)
if (verbose) then
! Write the .bundle structure to screen
write(*,*)'____________________________________________'
write(*,*)''
write(*,*)'Domain inductance matrices [L]'
write(*,*)''
do domain=1,bundle_spec%tot_n_domains
write(*,*)'Domain=',domain,' matrix dimension=',bundle_spec%L(domain)%dim
dim=bundle_spec%L(domain)%dim
CALL dwrite_matrix(bundle_spec%L(domain)%mat,dim,dim,dim,0)
end do
write(*,*)'____________________________________________'
write(*,*)''
write(*,*)'Domain capacitance matrices [C]'
write(*,*)''
do domain=1,bundle_spec%tot_n_domains
write(*,*)'Domain=',domain,' matrix dimension=',bundle_spec%C(domain)%dim
dim=bundle_spec%C(domain)%dim
CALL dwrite_matrix(bundle_spec%C(domain)%mat,dim,dim,dim,0)
end do
write(*,*)'____________________________________________'
write(*,*)''
write(*,*)'Global external to domain conductor current transformation matrix, [MI]'
write(*,*)''
dim=bundle_spec%global_MI%dim
CALL dwrite_matrix(bundle_spec%global_MI%mat,dim,dim,dim,0)
write(*,*)'____________________________________________'
write(*,*)''
write(*,*)'Global external to domain conductor voltage transformation matrix, [MV]'
write(*,*)''
dim=bundle_spec%global_MV%dim
CALL dwrite_matrix(bundle_spec%global_MV%mat,dim,dim,dim,0)
write(*,*)'____________________________________________'
write(*,*)''
write(*,*)'Global Inductance matrix, [L]'
write(*,*)''
dim=bundle_spec%global_L%dim
CALL dwrite_matrix(bundle_spec%global_L%mat,dim,dim,dim,0)
write(*,*)'____________________________________________'
write(*,*)''
write(*,*)'Global Capacitance matrix, [C]'
write(*,*)''
dim=bundle_spec%global_C%dim
CALL dwrite_matrix(bundle_spec%global_C%mat,dim,dim,dim,0)
end if ! verbose
CALL write_cable_bundle(bundle_spec,bundle_file_unit)
CALL deallocate_frequency_specification(bundle_spec%Y_fit_freq_spec)
CALL deallocate_cable_bundle(bundle_spec)
! finish up
run_status='Finished_Correctly'
CALL write_program_status()
STOP
9000 run_status='ERROR reading control parameter from the bundle_spec file'
CALL write_program_status()
STOP 1
END PROGRAM cable_bundle_model_builder