Blame view

SRC/cable_model_builder.F90 19.3 KB
886c558b   Steve Greedy   SACAMOS Public Re...
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
!
! 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 <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_model_builder
!
! NAME
!     cable_model_builder
!
! AUTHORS
!     Chris Smartt
!
! DESCRIPTION
!     cable_model_builder collects all the information required to characterise
!     an individual cable from a .cable_spec file. The code performs any calculations necessary to 
!     derive the per-unit-length parameters of any shielded (internal) domains as required. 
!
!     The software supports the following cable types:
!
!     Frequency Dependent Cylindrical conductor with dielectric
!     Frequency Dependent Coaxial cable with transfer impedance and shield surface impedance loss
!     Frequency Dependent Twinax cable with transfer impedance and shield surface impedance loss
!     Frequency Dependent Twisted pair
!     Frequency Dependent Shielded twisted pair with transfer impedance and shield surface impedance loss
!     Frequency Dependent Spacewire with transfer impedance and shield surface impedance loss
!     Frequency Dependent Overshield with transfer impedance and shield surface impedance loss
!     Frequency Dependent flex cable
!     D connector
!
!     The input to the program is the name of a cable specification file. A file name.cable_spec must exist, containing
!     all the data required to specify a cable.
!
!     The output of the cable_model_builder code is a file name.cable which can be used as an input to the 
!     cable_bundle_model_builder software
!
!     The .cable file is placed in a directory specified in the .cable_spec file. This may be the local directory (./) 
!     or another specified path. In this way the software can interact with a library of cable models (MOD).
!
!     The program may be run with the cable name specified in the command line i.e. 'cable_model_builder name'
!     or it the name is absent from the command line, the user is prompted for the name.
!
!
! COMMENTS
!     Updated to V2
!
! HISTORY
!
!     started 25/11/2015 CJS Started STAGE_1 developments 
!     started 21/03/2016 CJS Started STAGE_3 developments 
!     7/4/2016  CJS add twinax, twisted_pair and shielded_twisted_pair cable types
!     27/4/2016 CJS add the conductor impedance (loss) model
!     12/5/2016 CJS Generalise the conductor impedance model to include transfer impedance
!     21/7/2016 CJS add models for FD_twisted_pair ZT_FD_shielded_twisted_pair ZT_FD_spacewire ZT_FD_twinax
!     5/9/2016  CJS Include the shielded cable models with surface impedance loss:
!                   FD_coax2, ZT_FD_coax2, FD_twisted_pair2, ZT_FD_shielded_twisted_pair2, ZT_FD_spacewire2 ZT_FD_twinax2
!     23/9/2016 CJS Include rectangular conductor type
!     16/11/2016 CJS Include Dconnector type
!     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.
189467e4   Steve Greedy   First Public Release
85
86
!     23/10/2017 CJS Check the pole stability of the dielectric and transfer impedance filters.
!     16/11/2017 CJS Include network synthesis process to replace s-domain transfer functions
44c11f06   Chris Smartt   Include software ...
87
!     13/3/2018 CJS Add flag for direct/ iterative matrix solver in Laplace solution
886c558b   Steve Greedy   SACAMOS Public Re...
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
!
!
PROGRAM cable_model_builder

USE type_specifications
USE general_module
USE constants
USE cable_module
USE filter_module

IMPLICIT NONE

! local variables

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

character(len=filename_length)    :: cable_name_with_path  ! name of the cable including the path
character(len=filename_length)    :: cable_path            ! path to the cable_spec file
character(len=filename_length)    :: cable_name            ! name of the cable
character(len=filename_length)    :: filename              ! filename of the .cable_spec file
    
logical        :: file_exists

! Structure to hold the cable specification (see CABLE_MODULES/cable_module.F90)
type(cable_specification_type)    :: cable_spec

! string for reading flags
character(len=line_length)    :: line

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

! temporary variables for reading number of conductors, parameters, frequency dependent parameters, transfer impedance functions.
integer        :: nc_in,np_in,nFDp_in,nFDZT_in
189467e4   Steve Greedy   First Public Release
123
logical        :: check_passed                   ! flag for stability testing of S domain transfer function filters
886c558b   Steve Greedy   SACAMOS Public Re...
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

! loop variable
integer        :: i

! START

! Open the input file describing the cable parameters
! This file could be created by the associated GUI or otherwise generated

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

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

  CALL get_command_argument(1 , argument1, argument1_length)

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

    write(*,*)'Enter the name of the cable specification data (without .cable_spec extension)'

    read(*,'(A)')cable_name_with_path 

  end if
  
  CALL strip_path(cable_name_with_path,cable_path,cable_name)

  filename=trim(cable_name_with_path)//cable_spec_file_extn

  inquire(file=trim(filename),exist=file_exists)
  if (.NOT.file_exists) then
    run_status='ERROR in cable_model_builder, Cannot find the file:'//trim(filename)
    CALL write_program_status()
    STOP 1
  end if 
  
! open and read the file
  
  OPEN(unit=cable_spec_file_unit,file=filename)

  write(*,*)'Opened file:',trim(filename)
  
! set the cable name to be the same as the name of the cable specification data
  cable_spec%cable_name=cable_name

! set the version tag in the cable structure
  cable_spec%version=SPICE_CABLE_MODEL_BUILDER_version

! read the directory for the cable models
  read(cable_spec_file_unit,*)  ! comment line
  read(cable_spec_file_unit,'(A)')MOD_cable_lib_dir
  CALL path_format(MOD_cable_lib_dir)
  
! ensure that the paths exist
  CALL check_and_make_path(MOD_cable_lib_dir)

! read the cable type
  read(cable_spec_file_unit,'(A)')cable_spec%cable_type_string
  
  CALL convert_to_lower_case(cable_spec%cable_type_string,line_length)
  
  if (cable_spec%cable_type_string.eq.'cylindrical') then

    CALL cylindrical_set_parameters(cable_spec)
    
  else if (cable_spec%cable_type_string.eq.'twisted_pair') then

    CALL twisted_pair_set_parameters(cable_spec)
    
  else if (cable_spec%cable_type_string.eq.'coax') then

    CALL coax_set_parameters(cable_spec)
        
  else if (cable_spec%cable_type_string.eq.'twinax') then

    CALL twinax_set_parameters(cable_spec)
    
  else if (cable_spec%cable_type_string.eq.'shielded_twisted_pair') then

    CALL shielded_twisted_pair_set_parameters(cable_spec)

  else if (cable_spec%cable_type_string.eq.'spacewire') then

    CALL spacewire_set_parameters(cable_spec)

44c11f06   Chris Smartt   Include software ...
218
  else if (cable_spec%cable_type_string.eq.'original_flex_cable') then
886c558b   Steve Greedy   SACAMOS Public Re...
219
220
221

    CALL flex_cable_set_parameters(cable_spec)

44c11f06   Chris Smartt   Include software ...
222
223
224
225
  else if (cable_spec%cable_type_string.eq.'flex_cable') then

    CALL ML_flex_cable_set_parameters(cable_spec)

886c558b   Steve Greedy   SACAMOS Public Re...
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
  else if (cable_spec%cable_type_string.eq.'dconnector') then

    CALL Dconnector_set_parameters(cable_spec)

  else if (cable_spec%cable_type_string.eq.'overshield') then

    CALL overshield_set_parameters(cable_spec)

  else
   
    run_status='ERROR in cable_model_builder, Unknown cable type:'//trim(cable_spec%cable_type_string)
    CALL write_program_status()
    STOP 1
      
  end if

! read the number of conductors from the .cable_spec file 

  read(cable_spec_file_unit,*,IOSTAT=ierr)nc_in
  if (ierr.NE.0) then 
    run_status='ERROR reading number of conductors'
    CALL write_program_status()
    STOP 1
  end if
  
  if (cable_spec%tot_n_conductors.NE.0) then ! This cable type has a specific number of conductors so
! check that the number of conductors is consistent with this cable type

    if (nc_in.NE.cable_spec%tot_n_conductors) then
      run_status='ERROR, Wrong number of conductors'
      CALL write_program_status()
      STOP 1
    end if
    
  else
! the number of conductors is set in the cable specification so set the 
! paramter values accordingly

    cable_spec%tot_n_conductors=nc_in
    
! if the number of external conductors is not set then we assume that all condcutors are external (e.g. flex cable)
    if (cable_spec%n_external_conductors.NE.0) then
      cable_spec%n_external_conductors=nc_in
    end if
    
  end if
  
! read the number of parameters from the .cable_spec file 

  read(cable_spec_file_unit,*,IOSTAT=ierr)np_in
  if (ierr.NE.0) then 
    run_status='ERROR reading number of parameters'
    CALL write_program_status()
    STOP 1
  end if
  
44c11f06   Chris Smartt   Include software ...
282
283
  if (cable_spec%n_parameters.NE.0) then
  
886c558b   Steve Greedy   SACAMOS Public Re...
284
! Check that the number of parameters is consistent with this cable type
44c11f06   Chris Smartt   Include software ...
285
286
287
288
289
290
291
292
293
294
295
    if (np_in.NE.cable_spec%n_parameters) then
      run_status='ERROR, Wrong number of parameters'
      CALL write_program_status()
      STOP 1
    end if
  
  else

! for a ML_flex cable the number of parameters depends on the cable specification  
    cable_spec%n_parameters=np_in
    
886c558b   Steve Greedy   SACAMOS Public Re...
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
  end if

! allocate and read parameters

  ALLOCATE( cable_spec%parameters(1:cable_spec%n_parameters) )
  
  do i=1,cable_spec%n_parameters

    read(cable_spec_file_unit,*,IOSTAT=ierr)cable_spec%parameters(i)
    if (ierr.NE.0) then 
      run_status='ERROR reading cable_spec%parameters'
      CALL write_program_status()
      STOP 1
    end if
  
  end do

! read the number of dielectric filters from the .cable_spec file or assume 0 if the information is not there

  read(cable_spec_file_unit,*,IOSTAT=ierr)nFDp_in
  if (ierr.NE.0) then 
! Assume that there are no frequency dependent dielectric models
    backspace(cable_spec_file_unit)
    nFDp_in=0
  end if
  
! Check that the number of dielectric filters is consistent with this cable type
  if (nFDp_in.NE.cable_spec%n_dielectric_filters) then
    run_status='ERROR, Wrong number of dielectric models for this cable type'
    CALL write_program_status()
    STOP 1
  end if
  
  if (cable_spec%n_dielectric_filters.GT.0) then
    ALLOCATE( cable_spec%dielectric_filter(1:cable_spec%n_dielectric_filters) )
    do i=1,cable_spec%n_dielectric_filters
      read(cable_spec_file_unit,*,IOSTAT=ierr)    ! comment line
      CALL read_Sfilter(cable_spec%dielectric_filter(i),cable_spec_file_unit)
189467e4   Steve Greedy   First Public Release
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
      
! test pole stability
      CALL test_filter_pole_stability(cable_spec%dielectric_filter(i),check_passed)
  
      if (.NOT.check_passed) then
        write(*,*)'ERROR in cable_model_builder'
        write(*,*)'The dielectric filter function has unstable poles'
        write(*,*)'Dielectric filter function number:',i
        CALL write_Sfilter(cable_spec%dielectric_filter(i),0)
        write(run_status,'(A,I2)')'ERROR, Unstable poles in dielectric filter function: ',i
        CALL write_program_status()
        STOP 1
      else
        if (verbose) write(*,*)'The dielectric filter function has stable poles: function number ',i    
      end if
          
886c558b   Steve Greedy   SACAMOS Public Re...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
    end do
  end if
   
! read the number of transfer impedance filters from the .cable_spec file or assume 0 if the information is not there

  read(cable_spec_file_unit,*,IOSTAT=ierr)nFDZT_in
  if (ierr.NE.0) then 
! Assume that there are no transfer impedance filters
    backspace(cable_spec_file_unit)
    nFDZT_in=0
  end if
  
! Check that the number of transfer impedance filters is consistent with this cable type
  if (nFDZT_in.NE.cable_spec%n_transfer_impedance_models) then
    run_status='ERROR, Wrong number of transfer impedance models for this cable type'
    CALL write_program_status()
    STOP 1
  end if
  
  if (cable_spec%n_transfer_impedance_models.GT.0) then
    ALLOCATE( cable_spec%transfer_impedance(1:cable_spec%n_transfer_impedance_models) )
    do i=1,cable_spec%n_transfer_impedance_models
      read(cable_spec_file_unit,*,IOSTAT=ierr)    ! comment line
      CALL read_Sfilter(cable_spec%transfer_impedance(i),cable_spec_file_unit)
189467e4   Steve Greedy   First Public Release
374
375
376
377
378
379
380
381
382
383
384
385
386
387
      
! test pole stability
      CALL test_filter_pole_stability(cable_spec%transfer_impedance(i),check_passed)
  
      if (.NOT.check_passed) then
        write(*,*)'ERROR in cable_rmpedance filter function has unstable poles'
        write(*,*)'Transfer impedance filter function number:',i
        CALL write_Sfilter(cable_spec%transfer_impedance(i),0)
        write(run_status,'(A,I2)')'ERROR, Unstable poles in transfer impedance filter function: ',i
        CALL write_program_status()
        STOP 1
      else
        if (verbose) write(*,*)'The transfer impedance filter function has stable poles: function number ',i    
      end if
886c558b   Steve Greedy   SACAMOS Public Re...
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
    end do
  end if
   
! Set deafult propagation correction transfer function fit information
  cable_spec%Y_fit_model_order=0  
  CALL reset_frequency_specification(cable_spec%Y_fit_freq_spec)
  CALL set_up_frequency_specification(cable_spec%Y_fit_freq_spec)
  
! Read the optional propagation correction transfer function fit information
  read(cable_spec_file_unit,*,IOSTAT=ierr)cable_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(cable_spec_file_unit)
    goto 100
  end if
  
  write(*,*)'Reading the filter fit frequency range'
  
  CALL read_and_set_up_frequency_specification(cable_spec%Y_fit_freq_spec,cable_spec_file_unit)

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

  do
    read(cable_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.
44c11f06   Chris Smartt   Include software ...
427
428
429
    
    if (INDEX(line,'direct_solver').NE.0) direct_solver=.TRUE.
    if (INDEX(line,'iterative_solver').NE.0) direct_solver=.FALSE.
886c558b   Steve Greedy   SACAMOS Public Re...
430
431
432

! redefine mesh generation parameters if required
    if (INDEX(line,'laplace_boundary_constant').NE.0) then
68b0ecb2   Chris Smartt   Complete mesh gen...
433
      read(cable_spec_file_unit,*,END=9000,ERR=9000)Laplace_boundary_constant
886c558b   Steve Greedy   SACAMOS Public Re...
434
435
436
    end if
    
    if (INDEX(line,'laplace_surface_mesh_constant').NE.0) then
68b0ecb2   Chris Smartt   Complete mesh gen...
437
      read(cable_spec_file_unit,*,END=9000,ERR=9000)Laplace_surface_mesh_constant
886c558b   Steve Greedy   SACAMOS Public Re...
438
439
440
    end if
    
    if (INDEX(line,'twisted_pair_equivalent_radius').NE.0) then
68b0ecb2   Chris Smartt   Complete mesh gen...
441
      read(cable_spec_file_unit,*,END=9000,ERR=9000)Twisted_pair_equivalent_radius
886c558b   Steve Greedy   SACAMOS Public Re...
442
    end if
44c11f06   Chris Smartt   Include software ...
443
444
    
    if (INDEX(line,'max_mesh_edge_length').NE.0) then
68b0ecb2   Chris Smartt   Complete mesh gen...
445
446
447
448
449
      read(cable_spec_file_unit,*,END=9000,ERR=9000)max_mesh_edge_length
    end if
    
    if (INDEX(line,'cg_tol').NE.0) then
      read(cable_spec_file_unit,*,END=9000,ERR=9000)cg_tol
44c11f06   Chris Smartt   Include software ...
450
    end if
886c558b   Steve Greedy   SACAMOS Public Re...
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

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

110 CONTINUE
  
! close the file with the cable data
  CLOSE(unit=cable_spec_file_unit)
  
  if (cable_spec%n_internal_domains.GT.0) then
! construct the information for the internal domains

! allocate internal domain information
    ALLOCATE(cable_spec%n_internal_conductors_in_domain(1:cable_spec%n_internal_domains))
    ALLOCATE(cable_spec%L_domain(1:cable_spec%n_internal_domains))
    ALLOCATE(cable_spec%C_domain(1:cable_spec%n_internal_domains))
    ALLOCATE(cable_spec%Z_domain(1:cable_spec%n_internal_domains))
    ALLOCATE(cable_spec%Y_domain(1:cable_spec%n_internal_domains))

  end if ! There are internal domains requiring parameter specification

! allocate the conductor based impedance model and reset all parameters assuming PEC for now
  ALLOCATE( cable_spec%conductor_impedance(1:cable_spec%tot_n_conductors) )
  do i=1,cable_spec%tot_n_conductors
    cable_spec%conductor_impedance(i)%impedance_model_type=impedance_model_type_PEC
    cable_spec%conductor_impedance(i)%radius=0d0
    cable_spec%conductor_impedance(i)%conductivity=0d0
    cable_spec%conductor_impedance(i)%Resistance_multiplication_factor=1d0
  end do
      
! Set the cable structure information according to each cable type
  
  if (cable_spec%cable_type.EQ.cable_geometry_type_cylindrical) then

    CALL cylindrical_set_internal_domain_information(cable_spec)
  
  else if (cable_spec%cable_type.EQ.cable_geometry_type_twisted_pair) then

    CALL twisted_pair_set_internal_domain_information(cable_spec)

  else if (cable_spec%cable_type.EQ.cable_geometry_type_coax) then

    CALL coax_set_internal_domain_information(cable_spec)

  else if (cable_spec%cable_type.EQ.cable_geometry_type_twinax) then

    CALL twinax_set_internal_domain_information(cable_spec)

  else if (cable_spec%cable_type.EQ.cable_geometry_type_shielded_twisted_pair) then

    CALL shielded_twisted_pair_set_internal_domain_information(cable_spec)
    
  else if (cable_spec%cable_type.EQ.cable_geometry_type_spacewire) then

    CALL spacewire_set_internal_domain_information(cable_spec)

  else if (cable_spec%cable_type.EQ.cable_geometry_type_flex_cable) then

    CALL flex_cable_set_internal_domain_information(cable_spec)

44c11f06   Chris Smartt   Include software ...
510
511
512
513
  else if (cable_spec%cable_type.EQ.cable_geometry_type_ML_flex_cable) then

    CALL ML_flex_cable_set_internal_domain_information(cable_spec)

886c558b   Steve Greedy   SACAMOS Public Re...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  else if (cable_spec%cable_type.EQ.cable_geometry_type_dconnector) then

    CALL dconnector_set_internal_domain_information(cable_spec)
  
  else if (cable_spec%cable_type.EQ.cable_geometry_type_overshield) then

    CALL overshield_set_internal_domain_information(cable_spec)
  
  end if

! Write the cable information to a .cable file

  CAll write_cable(cable_spec,cable_file_unit)

! deallocate memory used
  
  CALL deallocate_frequency_specification(cable_spec%Y_fit_freq_spec)

  CAll deallocate_cable(cable_spec)

! finish up

  run_status='Finished_Correctly'
  CALL write_program_status()
  
68b0ecb2   Chris Smartt   Complete mesh gen...
539
540
541
542
543
544
  STOP
 
9000    run_status='ERROR reading control parameter from the cable_spec file'
        CALL write_program_status()
        STOP 1
  
886c558b   Steve Greedy   SACAMOS Public Re...
545
END PROGRAM cable_model_builder