Differences From Artifact [6c724e5d33]:

To Artifact [5fcd824e34]:


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
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
function [bonds,components] = rbg2abg(name,rbonds,rstrokes,rcomponents,\
				      port_coord,port_name,\
				      infofile,errorfile)

# ###############################################################
# ## Version control history
# ###############################################################
# ## $Id$
# ## $Log$



# ## Revision 1.39  1999/08/19 05:22:16  peterg
# ## To RCS prior to inplementing vector junctions
# ##
# ## Revision 1.38  1999/03/12 00:58:06  peterg
# ## Now gets portlist from the _abg.m file NOT the _rbg.m file
# ## - this allows expansion of vector SS ports.
# ##
# ## Revision 1.37  1998/07/28 19:06:43  peterg
# ## Still some bugs (vector SS ports)??
# ##
# ## Revision 1.36  1998/07/28 10:30:50  peterg
# ## Implemented vector SS ports.
# ##
# ## Revision 1.35  1998/07/08 15:35:15  peterg
# ## Added errorfile argument
# ##
# ## Revision 1.34  1998/07/02 19:41:29  peterg
# ## Fixed empty port string bug - set to null string.
# ##
# ## Revision 1.33  1998/07/02 17:16:06  peterg
# ## Commented out redundent code -- obsolete due to new default mechanism
# ##
# ## Revision 1.32  1998/07/02 15:12:05  peterg
# ## Added hard error reporting
# ## Added error when two unlabled bonds point in.
# ##
# ## Revision 1.31  1998/07/02 14:30:50  peterg
# ## Corrected various bugs - including resettting n_ports to correct value
# ##
# ## Revision 1.30  1998/07/02 13:40:50  peterg
# ## Added extra ports names (due to defaults) to relevant lists:
# ## 	port_name
# ## 	port_bond
# ##
# ## Revision 1.29  1998/07/02 13:28:31  peterg
# ## Added defaults in new form BEFORE alias expansion
# ##
# ## Revision 1.28  1998/07/02 12:36:05  peterg
# ## Removed debugging lines
# ##
# ## Revision 1.27  1998/07/02 12:24:02  peterg
# ## Expand port aliases
# ##
# ## Revision 1.26  1998/04/16 14:07:51  peterg
# ## Sorted out [] problem with vector ports -- new octave function
# ## split_port
# ##
# ## Revision 1.25  1998/04/12 15:01:04  peterg
# ## Converted to uniform port notation - always use []
# ##
# ## Revision 1.24  1998/02/19 08:57:16  peterg
# ## Fixed mtt-info bug -- confused filename with number
# ##
# ## Revision 1.23  1997/12/04 14:24:22  peterg
# ## Removed error message about through-pointing arrows
# ##
# ## Revision 1.22  1997/09/18 19:49:37  peterg
# ## Added test for uniquness of bonds on a component -- if non-unique
# ## implies same component at both ends of a bond.
# ##
# ## Revision 1.21  1997/09/16  15:14:14  peterg
# ## Added warning if a component has no bonds.
# ##
# ## Revision 1.20  1997/08/18  19:39:48  peterg
# ## Now generates (exampaded) port_bond list correctely
# ##
# ## Revision 1.19  1997/08/14  11:59:47  peterg
# ## Vector ports added!!
# ##
# ## Revision 1.18  1997/08/14  11:01:42  peterg
# ## Reordered algorithms as follows:
# ## bond end coordinates
# ## associate port labels with bonds (port_bond)
# ## associate bonds with components
# ## unsorted list of bonds on each component (components)
# ## interpret strokes and setup the causality of the bonds (bonds)
# ## expand vector ports & add new bonds and connections
# ## sort bonds on each component according to the labels -- two ports
# ## default included here.
# ##
# ## Revision 1.17  1997/08/09 11:31:16  peterg
# ## Default two port list is [in;out] (or [out;in])
# ## Dont do global default if no ports labels.
# ##
# ## Revision 1.16  1997/08/07  16:12:36  peterg
# ## Fixed sorting bug: now puts the jth component from the unsorted list
# ## into the kth component of the sorted list .. not vice versa!
# ##
# ## Revision 1.15  1997/08/06  21:43:19  peterg
# ## Corrected error in creating component list: the kth component of the
# ## list is given by the jth component of the original list NOT vice
# ## versa.
# ##
# ## Revision 1.14  1997/08/04 14:18:55  peterg
# ## If no ports labels at all, just use the default component list.
# ##
# ## Revision 1.13  1997/08/04 12:50:39  peterg
# ## Many bug fixes to the named port version + tied up the logic and
# ## supporting comments.
# ##
# ## Revision 1.12  1997/08/02 19:37:53  peterg
# ## Now uses named ports.
# ##
# ## Revision 1.11  1997/04/29 09:12:37  peterg
# ## Added error message if port label near to >1 bond.
# ##
# ## Revision 1.10  1997/03/17  13:45:42  peterg
# ## Added more error info.
# ##
# ## Revision 1.9  1996/12/31  11:25:57  peterg
# ## Clearer error messages for incorrect ports.
# ##
# ## Revision 1.8  1996/12/04 21:52:39  peterg
# ## Now uses fopen.
# ##
# ## Revision 1.7  1996/11/01 18:01:57  peterg
# ## Rationalised port ordering.
# ## Fixed port bug.
# ##
# ## Revision 1.6  1996/08/25 08:27:14  peter
# ## Now checks ports correctely - I hope.
# ##
# ## Revision 1.5  1996/08/24 19:21:26  peter
# ## More specific error messages.
# ##
# ## Revision 1.4  1996/08/24 18:00:33  peter
# ## Fixed bug with finding ports.
# ##
# ## Revision 1.3  1996/08/09 08:26:35  peter
# ## Cosmetic tidy up.
# ##
# ## Revision 1.2  1996/08/04 18:37:57  peter
# ## Fixed  no causal strokes bug.
# ##
# ## Revision 1.1  1996/08/04 18:30:14  peter
# ## Initial revision
# ##
# ###############################################################


##Default to no components
components = [0];

## Xfig scaling factor
scale = 1200.0/2.54546;

## Rotation matrix
rot = [0 -1; 1 0];

## Find number of strokes
[n_strokes,columns] = size(rstrokes);
if (columns ~= 4)&(n_strokes>0)
  error('Incorrect rstrokes matrix: must have 4 columns');
endif


## Find number of bonds
[n_bonds,columns] = size(rbonds);
if (columns ~= 6)&(n_bonds>0)
  error('Incorrect rbonds matrix: must have 6 columns');
endif


## Find number of components
[n_components,columns] = size(rcomponents);

## Find the number of ports refered to within the component
[n_ports,columns] = size(port_coord)

## If port_name is empty, make it a empty string
if (length(port_name)==0)
  port_name="";
endif


## Determine coordinates of the arrow end of the bond and the other end
other_end_1 = rbonds(:,1:2);
arrow_end   = rbonds(:,3:4);
other_end_2 = rbonds(:,5:6);

distance_1   = length2d(other_end_1 - arrow_end);
distance_2   = length2d(other_end_2 - arrow_end);
which_end    = (distance_1>distance_2)*[1 1];
one          = ones(size(which_end));
other_end    = which_end.*other_end_1 + (one-which_end).*other_end_2;
arrow_vector = ( which_end.*other_end_2 + (one-which_end).*other_end_1 ) - ...
    arrow_end;
 
## Locate the bond end nearest to each port
## col 1 of port_near_bond contains a signed bond number (+ for arrow end)
## col 2  of port_near_bond contains the corresponding port index
port_bond = [];
for i = 1:n_ports
   near_bond = adjbond(port_coord(i,1:2),arrow_end,other_end);
   [rows,cols]=size(near_bond);
   if rows>1
     error(sprintf ...
	 ("A port is near to more than one bond at coordinates %g,%g\n", ...
	 port_coord(i,1)/scale,  port_coord(i,2)/scale));
   endif
   

  ##The (signed) bond corresponding to the ith port label
  port_bond(i) = near_bond(1)*sign(1.5-near_bond(2));
endfor

port_bond
##We now have the (signed) bond (port_bond(i)) correponding to the
## ith port label within the component 

## Locate the components at the ends of each bond
## col 1 of comp_near_bond contain the component nearest to the arrow end
## col 2 of comp_near_bond contain the component nearest to the other end
for i = 1:n_bonds
  comp_near_bond(i,:) = adjcomp(arrow_end(i,:),other_end(i,:),rcomponents);
endfor

comp_near_bond
## We now have a list (comp_near_bond) of the component(s) at each end
## of each bond

## Now do a list of the bonds on each component - unsorted at this stage.
## Also expand aliases using the alias list for each component
components = [];
for i = 1:n_components
  ##Get component type
  eval(['[comp_type, comp_name] = ', name, '_cmp(i)']);


  ## There are n_comp_bonds bonds on this component with corresponding index
  [index,n_comp_bonds] = getindex(comp_near_bond,i);

  if index(1,1)==0
    mtt_error(sprintf("Component %s (%s) has no bonds", comp_name,
    comp_type),errorfile);
  endif
  
  
  ## Create the signed list of bonds on this component
  one = ones(n_comp_bonds,1);
  bond_list = index(:,1); %  bond at component
  
  ## Check that all bonds are unique -- error if not
  if unique(bond_list)==0
    mtt_error(sprintf("Component %s (%s) is at both ends of a bond", comp_name,
    comp_type),errorfile);
  endif
  
    

  ## which end of bond at component?
  bond_end = index(:,2); 
  direction = -sign(bond_end-1.5*one);
  signed_bond_list = bond_list.*direction;
  components = add_bond(components,signed_bond_list',i);
  
  # Unalias all the ports on this component - if not a junction
  unlabelled_ports = 0;  
  in_bonds = 0;
  out_bonds = 0;
  if ((comp_type!="0")&&(comp_type!="1")) # Don't do junctions
    for j=1:n_comp_bonds
      signed_bond = signed_bond_list(j);
      port_name_index = getindex(port_bond,signed_bond);
      port_direction = sign(signed_bond);
      
      if port_name_index==0	# There is no port on this bond - so try
				# to default
	unlabelled_ports++;
	if(unlabelled_ports==1)
	  if port_direction>0
	    in_bonds++;
	    port_name_i = "in";
	  else
	    out_bonds++;
	    port_name_i = "out";
	  endif
	  
	elseif (unlabelled_ports==2)
	  if port_direction>0
	    if (++in_bonds>1)
	      mtt_error(["More than one unlabelled INport on component " \
			comp_name " (" comp_type ")"],errorfile);
	    else
	      port_name_i = "in";
	    end
	  else
	    if (++out_bonds>1)
	      mtt_error(["More than one unlabelled OUTport on component " \
			comp_name " (" comp_type ")"],errorfile);
	    else
	      port_name_i = "out";
	    end
	  endif
	  
	else
	  mtt_error(["More than two unlabelled ports on component " \
		    comp_name " (" comp_type ")"],errorfile);
        endif
	
	mtt_info(["Defaulting port name [" port_name_i "]\t on component " \
		  comp_name " (" comp_type ")" ],infofile);
	port_name = [port_name; ["[" port_name_i "]"]];	# add to list
	[port_name_index,junk] = size(port_name); # the corresponding
				# index
	port_bond(port_name_index,:) = signed_bond; # add to port bond
      else  
      	port_name_i = deblank(port_name(port_name_index,:));
	port_name_i = port_name_i(2:length(port_name_i)-1) # strip []
      endif
      
      
      ## Replace by alias -- if any
    	eval( ["alias = ", comp_type, '_alias';]); # Get aliases
    	if is_struct(alias)		# are there any aliases
          if struct_contains(alias,port_name_i) # Is this an alias?
	    eval(["new_port_name_i = alias.",port_name_i]);
	    mtt_info(["Aliasing name [" port_name_i "]\t on component " \
		      comp_name " (" comp_type ")\t to [" new_port_name_i "]"],infofile);
	    port_name = replace_name(port_name, \
				     ["[",new_port_name_i,"]"], \
				     port_name_index);
	  endif
	  
      	endif
	
      endfor
      
    endif
    
  endfor
  
## At this point, every port should be labeled (port_name) and \
## associated with a bond (port_bond).
disp("--- Completed portnames and the corresponding bonds ---")
port_name, port_bond


## Deduce causality from the strokes (if any) and create the list of bonds
causality = zeros(n_bonds,2);
if n_strokes>0
  ## Find out location of centre and ends of stroke.
  stroke_end_1 = [rstrokes(:,1) rstrokes(:,2)];
  stroke_end_2 = [rstrokes(:,3) rstrokes(:,4)];
  
  stroke_centre = (stroke_end_1 + stroke_end_2)/2;
  stroke_vector = (stroke_end_1 - stroke_end_2);
  stroke_length = length2d(stroke_vector);

## Deduce bond causality from the strokes 
  for i = 1:n_strokes
    stroke = [stroke_centre(i,:) 
    stroke_end_1(i,:)
    stroke_end_2(i,:)];


    ## Find the nearest bond end.
    [index,distance] = adjbond(stroke(1,:),arrow_end,other_end);
    if (distance>2*stroke_length(i))
      info = sprintf('Stroke at (%4.3f,%4.3f) is %4.3f away from the nearest bond\n', ...
	stroke(1,1)/scale, stroke(1,2)/scale, distance/scale);
    endif
    
  
    ## Bond end coordinates
    j = index(1,1);
    which_end = index(1,2)==1;
    bond_end = arrow_end(j,:)*which_end + other_end(j,:)*(1-which_end);
  
    ## Now decide which bit of the stroke is nearest
    stroke_index = adjbond(bond_end,stroke,zeros(size(stroke)));
  
    if stroke_index(1)==1 ## uni-causal stroke
      causality(j,1:2) = (2*which_end-1)*[1 1];
    else ## bicausal stroke
      ## Find out whether stroke is on flow side of bond
      stroke_direction = stroke(1,:) - stroke(stroke_index(1),:);
      flow_side = stroke_direction*arrow_vector(j,:)'>0;
      causality(j,1+flow_side) = 2*which_end-1;
    endif
    
  endfor
  
endif


bonds = causality;

## Now expand vector ports
[n_bonds,junk] = size(bonds);
n_ports = length(port_bond);
n_exp_ports=n_ports;
exp_port_name="";
exp_port_bond = [];
##exp_comps = [];
for i=1:n_ports
  port_name_i = port_name(i,:)
  [subport,n_subports] = split_port(port_name_i, ','); ## Find the components of the vector port

  if n_subports==1 ## an ordinary port
    exp_port_name = [exp_port_name; subport(1,:)]; ## Write out the only port
    exp_port_bond = [exp_port_bond; port_bond(i)]; ## and the port_bond
  else ## its a vector port
    ## Check that there is a corresponding vector port at the other end of the
    ## bond
    signed_bond_index = port_bond(i);
    [other_bond_index,n_other] = getindex(port_bond,-signed_bond_index);
    if n_other == 1
      other_port_name = port_name(other_bond_index,:);
      [other_subport,n_other_subports] = split_port(other_port_name, ',');
      if n_other_subports~=n_subports
	mtt_error(['Vector ports ', port_name_i, ' and ', other_port_name, 'are not compatible'],errorfile);
      end
    else 
      mtt_error(['Vector port ', port_name_i, ' has no matching port'], errorfile);
    endif
    
    
    if other_bond_index>i ##then its not been done yet
      mtt_info(["Vector port: ", port_name_i],infofile);
      mtt_info(["matching: ", other_port_name],infofile);
      ## Remove sign info.
      bond_index = abs(signed_bond_index);
      sig = sign(signed_bond_index);
      
      ## Put the first element of each port list in the expanded list
      exp_port_name = [exp_port_name; subport(1,:)];
      exp_port_name = [exp_port_name; other_subport(1,:)];
      
      ## Add to the expanded port_bond list
      exp_port_bond = [exp_port_bond; signed_bond_index; ...
	-signed_bond_index];
      
      ## Add the other names to the expanded list and augment the bonds,
      ## components and port_bond lists.
      for j=2:n_subports
	## Add a new name (for each end) to give a non-vector list
	exp_port_name = [exp_port_name; subport(j,:)];
	exp_port_name = [exp_port_name; other_subport(j,:)];
	      
	## Add one more bond to the list
	bonds = [bonds; bonds(bond_index,:)];
	n_bonds = n_bonds + 1;
      
	## Add bond to the expanded port_bond list (ports at both ends)
	exp_port_bond = [exp_port_bond; sig*n_bonds; -sig*n_bonds];


	## Add the new bond to the component at both ends (taking note 
	## of the direction).
	arrow_index = comp_near_bond(bond_index,1);
	components = add_bond(components, n_bonds, arrow_index);
	other_index = comp_near_bond(bond_index,2);
	components = add_bond(components, -n_bonds, other_index);
      endfor
      
    endif
    
  endif
  
endfor



##Replace old list by new
port_name = exp_port_name
port_bond = exp_port_bond

## Resize the lists
[n_ports,junk] = size(port_name);

port_name, components
## Produce a list of bonds on each component (within this component) 
##  - sorted if explicit port numbers
for i = 1:n_components    
  disp('-----------------');
  ##Get component type
  eval(['[comp_type, comp_name] = ', name, '_cmp(i)']);

  ##Convert junction names

  if comp_type=='0'
    comp_type = 'zero';
  end

  if comp_type=='1'
    comp_type = 'one';
  end

  ## Find the (unsorted) bond list on this component
  signed_bond_list = nozeros(components(i,:));
  n_comp_bonds = length(signed_bond_list);
  direction = sign(signed_bond_list);
  
  ##Find the port list for this component
  if exist([comp_type, '_cause'])==0
#    eval(['[junk1,junk2,junk3,junk4,junk5,port_list]=', comp_type, '_rbg;']);
    eval(["ABG = ",comp_type, "_abg;"]);
    port_list = ABG.portlist;
  else
    port_list=comp_ports(comp_type,n_comp_bonds)
  endif
  

  [n_comp_ports,m_comp_ports] = size(port_list);
  subport_list="";
  for p=1:n_comp_ports		# Expand any vector ports
    [subport,n_sub] = split_port(port_list(p,:), ','); # Find the components
						  # of the vector port
    if n_sub>1
      mtt_info(sprintf("Expanding vector port %s of component type %s",\
		       port_list(p,:), comp_type, infofile));	
    endif
    
    subport_list = [subport_list; subport];
  endfor
  
  port_list = subport_list;	# Set the expanded port list.
  

  ## Check that number of bonds on the component is the same as the number of
  ## ports
  [n_comp_ports,m_comp_ports] = size(port_list);
  if (n_comp_ports~=n_comp_bonds) & ...
	~(strcmp(comp_type,'zero')|strcmp(comp_type,'one'))
    message=sprintf('Component %s (%s) has %1.0f impinging bonds but has %1.0f ports', ...
	comp_name,comp_type,n_comp_bonds,n_comp_ports);
    mtt_error(message, errorfile);
  endif
  
  
  unsorted_port_list="";
  if n_ports>0 ## then there are some named ports
    ## so find those associated with the bonds on this component.
    k=0; 
    for j = 1:n_comp_bonds
      b = signed_bond_list(j); 
      ## Find the port label on component end of bond (if any)
      [port_index,m] = getindex(port_bond,b);
      if m==1
	k=k+1;
	unsorted_port_list(k,:) = port_name(port_index,:);
      endif
      
    endfor
    
  else 
    k=0;
  endif
  
    
#  %Either all ports or no ports should be labelled - write error
#  %message if this is not so
#  if (k~=0)&(k~=n_comp_bonds)
#    mtt_info(['Component ', comp_name, ' (', comp_type, ') has wrong number of labels'], infofile); 
#    mtt_info(sprintf("\tit has %1.0f labels but should have 0 or \
#    %1.0f",k,n_comp_bonds), infofile);
#    portnames=""; 
#    for kk=1:k 
#      portnames=sprintf("%s %s",portnames, unsorted_port_list(kk,:));
#    
#    mtt_error(portnames,errorfile);
#  end;
  
  %Compute the number of labeled ports
  [n_unsorted_ports,m_unsorted_ports] = size(unsorted_port_list);
  if m_unsorted_ports==0
    n_unsorted_ports = 0;
  endif
  
#  n_unsorted_ports,n_comp_bonds
#  % One port defaults:
#  if (n_comp_bonds==1)&(n_unsorted_ports==0)
#    %if (direction(1)<0) & ~strcmp(comp_type,'SS') % Wrong way for default
#    % mtt_error(['One-port ', comp_name, ' (', comp_type, ') has the sign pointing the wrong way '], errorfile);
#    %end;
#    unsorted_port_list = port_list;
#  end;
  
#  %Two port defaults
#  if (n_comp_bonds==2)&(n_unsorted_ports==0)
#    if direction(1)==direction(2) % Wrong way for default
#      % mtt_error(['Two-port ', comp_name, ' (', comp_type, ') does not have through-pointing arrows'], errorfile);
#    end;
#    if direction(1)==1 %in
#      % mtt_info([comp_name, ' in'],infofile);
#      unsorted_port_list = ['[in]';'[out]'];
#    else %reverse the order
#      % mtt_info([comp_name, ' out'],infofile);
#      unsorted_port_list = ['[out]';'[in]'];
#    end;
#  end;
  
#  % Recompute the number of unsorted ports
#  [n_unsorted_ports,m_unsorted_ports] = size(unsorted_port_list);
#  if m_unsorted_ports==0
#    n_unsorted_ports = 0;
#  end;
  
  ## Junctions (order of ports unimportant)
  if strcmp(comp_type,'zero')|strcmp(comp_type,'one')
    for j = 1:n_comp_bonds
      components(i,j) = signed_bond_list(j);
    endfor
    
  else ##Order of ports is important
    unsorted_port_list, port_list
    if n_unsorted_ports==0
      mtt_error(['Component ', comp_name, ' (', comp_type, ') has no labeled ports'], errorfile); 
    endif
    
    ##Write out the signed bond list in the correct order
unsorted_port_list
[n_list,m_list] = size(unsorted_port_list);
if n_list!=n_comp_bonds
  error(sprintf("Component %s (%s) has %i bonds but %i port lables",\
		comp_name, comp_type, n_comp_bonds, n_list))
endif

for j = 1:n_comp_bonds
  j
      name_k = unsorted_port_list(j,:)
      k = name_in_list(name_k, port_list);
      ## Check that it only appears once in port list
      if length(k)>1
	mtt_error(['Component ', comp_name, ' (', comp_type, ') has ports with the same name:  ', name_k], errorfile); 
      endif
      
      
      ##Check that it only appears one in the label list
      kk = name_in_list(name_k,unsorted_port_list);
      if length(kk)>1
	mtt_error(['Component ', comp_name, ' (', comp_type, ') has multiple port labels:  ', name_k], errorfile); 
      endif
      
      
      if k==0
	mtt_error(['Component ', comp_name, ' (', comp_type, ') has an unrecognised port: ', name_k], errorfile); 
      else
	components(i,k) = signed_bond_list(j);     
      endif
      
    endfor
    
  endif
  
endfor
endfunction










|
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|

|
|

|
|

|
|
|
|
|


|
|
|
|
|


|
|

|
|

|
|
|
|


|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|

|
|
|
|
|
|

|
|
|

|
|
|
|
|
|

<
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|



















|
|
|
|


|
|
|
|
|
|
|
|
|
|

|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|

|
|

|
|
|
|
|
|
|

|
>
|
|
|

|
|
|

|
|
|
|
|
|
|
<
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
|
<
|







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
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560














561
562
563
564
565





























566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608

609

610

611
612
613
614
615
616
617
618
function [bonds,components] = rbg2abg(name,rbonds,rstrokes,rcomponents,\
				      port_coord,port_name,\
				      infofile,errorfile)

  ## ###############################################################
  ## ## Version control history
  ## ###############################################################
  ## ## $Id$
  ## ## $Log$
  ## ## Revision 1.40  1999/08/19 05:39:55  peterg
  ## ## Put into octave format
  ## ##
  ## ## Revision 1.39  1999/08/19 05:22:16  peterg
  ## ## To RCS prior to inplementing vector junctions
  ## ##
  ## ## Revision 1.38  1999/03/12 00:58:06  peterg
  ## ## Now gets portlist from the _abg.m file NOT the _rbg.m file
  ## ## - this allows expansion of vector SS ports.
  ## ##
  ## ## Revision 1.37  1998/07/28 19:06:43  peterg
  ## ## Still some bugs (vector SS ports)??
  ## ##
  ## ## Revision 1.36  1998/07/28 10:30:50  peterg
  ## ## Implemented vector SS ports.
  ## ##
  ## ## Revision 1.35  1998/07/08 15:35:15  peterg
  ## ## Added errorfile argument
  ## ##
  ## ## Revision 1.34  1998/07/02 19:41:29  peterg
  ## ## Fixed empty port string bug - set to null string.
  ## ##
  ## ## Revision 1.33  1998/07/02 17:16:06  peterg
  ## ## Commented out redundent code -- obsolete due to new default mechanism
  ## ##
  ## ## Revision 1.32  1998/07/02 15:12:05  peterg
  ## ## Added hard error reporting
  ## ## Added error when two unlabled bonds point in.
  ## ##
  ## ## Revision 1.31  1998/07/02 14:30:50  peterg
  ## ## Corrected various bugs - including resettting n_ports to correct value
  ## ##
  ## ## Revision 1.30  1998/07/02 13:40:50  peterg
  ## ## Added extra ports names (due to defaults) to relevant lists:
  ## ## 	port_name
  ## ## 	port_bond
  ## ##
  ## ## Revision 1.29  1998/07/02 13:28:31  peterg
  ## ## Added defaults in new form BEFORE alias expansion
  ## ##
  ## ## Revision 1.28  1998/07/02 12:36:05  peterg
  ## ## Removed debugging lines
  ## ##
  ## ## Revision 1.27  1998/07/02 12:24:02  peterg
  ## ## Expand port aliases
  ## ##
  ## ## Revision 1.26  1998/04/16 14:07:51  peterg
  ## ## Sorted out [] problem with vector ports -- new octave function
  ## ## split_port
  ## ##
  ## ## Revision 1.25  1998/04/12 15:01:04  peterg
  ## ## Converted to uniform port notation - always use []
  ## ##
  ## ## Revision 1.24  1998/02/19 08:57:16  peterg
  ## ## Fixed mtt-info bug -- confused filename with number
  ## ##
  ## ## Revision 1.23  1997/12/04 14:24:22  peterg
  ## ## Removed error message about through-pointing arrows
  ## ##
  ## ## Revision 1.22  1997/09/18 19:49:37  peterg
  ## ## Added test for uniquness of bonds on a component -- if non-unique
  ## ## implies same component at both ends of a bond.
  ## ##
  ## ## Revision 1.21  1997/09/16  15:14:14  peterg
  ## ## Added warning if a component has no bonds.
  ## ##
  ## ## Revision 1.20  1997/08/18  19:39:48  peterg
  ## ## Now generates (exampaded) port_bond list correctely
  ## ##
  ## ## Revision 1.19  1997/08/14  11:59:47  peterg
  ## ## Vector ports added!!
  ## ##
  ## ## Revision 1.18  1997/08/14  11:01:42  peterg
  ## ## Reordered algorithms as follows:
  ## ## bond end coordinates
  ## ## associate port labels with bonds (port_bond)
  ## ## associate bonds with components
  ## ## unsorted list of bonds on each component (components)
  ## ## interpret strokes and setup the causality of the bonds (bonds)
  ## ## expand vector ports & add new bonds and connections
  ## ## sort bonds on each component according to the labels -- two ports
  ## ## default included here.
  ## ##
  ## ## Revision 1.17  1997/08/09 11:31:16  peterg
  ## ## Default two port list is [in;out] (or [out;in])
  ## ## Dont do global default if no ports labels.
  ## ##
  ## ## Revision 1.16  1997/08/07  16:12:36  peterg
  ## ## Fixed sorting bug: now puts the jth component from the unsorted list
  ## ## into the kth component of the sorted list .. not vice versa!
  ## ##
  ## ## Revision 1.15  1997/08/06  21:43:19  peterg
  ## ## Corrected error in creating component list: the kth component of the
  ## ## list is given by the jth component of the original list NOT vice
  ## ## versa.
  ## ##
  ## ## Revision 1.14  1997/08/04 14:18:55  peterg
  ## ## If no ports labels at all, just use the default component list.
  ## ##
  ## ## Revision 1.13  1997/08/04 12:50:39  peterg
  ## ## Many bug fixes to the named port version + tied up the logic and
  ## ## supporting comments.
  ## ##
  ## ## Revision 1.12  1997/08/02 19:37:53  peterg
  ## ## Now uses named ports.
  ## ##
  ## ## Revision 1.11  1997/04/29 09:12:37  peterg
  ## ## Added error message if port label near to >1 bond.
  ## ##
  ## ## Revision 1.10  1997/03/17  13:45:42  peterg
  ## ## Added more error info.
  ## ##
  ## ## Revision 1.9  1996/12/31  11:25:57  peterg
  ## ## Clearer error messages for incorrect ports.
  ## ##
  ## ## Revision 1.8  1996/12/04 21:52:39  peterg
  ## ## Now uses fopen.
  ## ##
  ## ## Revision 1.7  1996/11/01 18:01:57  peterg
  ## ## Rationalised port ordering.
  ## ## Fixed port bug.
  ## ##
  ## ## Revision 1.6  1996/08/25 08:27:14  peter
  ## ## Now checks ports correctely - I hope.
  ## ##
  ## ## Revision 1.5  1996/08/24 19:21:26  peter
  ## ## More specific error messages.
  ## ##
  ## ## Revision 1.4  1996/08/24 18:00:33  peter
  ## ## Fixed bug with finding ports.
  ## ##
  ## ## Revision 1.3  1996/08/09 08:26:35  peter
  ## ## Cosmetic tidy up.
  ## ##
  ## ## Revision 1.2  1996/08/04 18:37:57  peter
  ## ## Fixed  no causal strokes bug.
  ## ##
  ## ## Revision 1.1  1996/08/04 18:30:14  peter
  ## ## Initial revision
  ## ##
  ## ###############################################################


  ##Default to no components
  components = [0];

  ## Xfig scaling factor
  scale = 1200.0/2.54546;

  ## Rotation matrix
  rot = [0 -1; 1 0];

  ## Find number of strokes
  [n_strokes,columns] = size(rstrokes);
  if (columns ~= 4)&(n_strokes>0)
    error('Incorrect rstrokes matrix: must have 4 columns');
  endif


  ## Find number of bonds
  [n_bonds,columns] = size(rbonds);
  if (columns ~= 6)&(n_bonds>0)
    error('Incorrect rbonds matrix: must have 6 columns');
  endif


  ## Find number of components
  [n_components,columns] = size(rcomponents);

  ## Find the number of ports refered to within the component
  [n_ports,columns] = size(port_coord)

  ## If port_name is empty, make it a empty string
  if (length(port_name)==0)
    port_name="";
  endif


  ## Determine coordinates of the arrow end of the bond and the other end
  other_end_1 = rbonds(:,1:2);
  arrow_end   = rbonds(:,3:4);
  other_end_2 = rbonds(:,5:6);

  distance_1   = length2d(other_end_1 - arrow_end);
  distance_2   = length2d(other_end_2 - arrow_end);
  which_end    = (distance_1>distance_2)*[1 1];
  one          = ones(size(which_end));
  other_end    = which_end.*other_end_1 + (one-which_end).*other_end_2;
  arrow_vector = ( which_end.*other_end_2 + (one-which_end).*other_end_1 ) - ...
      arrow_end;
  
  ## Locate the bond end nearest to each port
  ## col 1 of port_near_bond contains a signed bond number (+ for arrow end)
  ## col 2  of port_near_bond contains the corresponding port index
  port_bond = [];
  for i = 1:n_ports
    near_bond = adjbond(port_coord(i,1:2),arrow_end,other_end);
    [rows,cols]=size(near_bond);
    if rows>1
      error(sprintf ...
	    ("A port is near to more than one bond at coordinates %g,%g\n", ...
	     port_coord(i,1)/scale,  port_coord(i,2)/scale));
    endif
    

    ##The (signed) bond corresponding to the ith port label
    port_bond(i) = near_bond(1)*sign(1.5-near_bond(2));
  endfor

  port_bond
  ##We now have the (signed) bond (port_bond(i)) correponding to the
  ## ith port label within the component 

  ## Locate the components at the ends of each bond
  ## col 1 of comp_near_bond contain the component nearest to the arrow end
  ## col 2 of comp_near_bond contain the component nearest to the other end
  for i = 1:n_bonds
    comp_near_bond(i,:) = adjcomp(arrow_end(i,:),other_end(i,:),rcomponents);
  endfor

  comp_near_bond
  ## We now have a list (comp_near_bond) of the component(s) at each end
  ## of each bond

  ## Now do a list of the bonds on each component - unsorted at this stage.
  ## Also expand aliases using the alias list for each component
  components = [];
  for i = 1:n_components
    ##Get component type
    eval(['[comp_type, comp_name] = ', name, '_cmp(i)']);


    ## There are n_comp_bonds bonds on this component with corresponding index
    [index,n_comp_bonds] = getindex(comp_near_bond,i);

    if index(1,1)==0
      mtt_error(sprintf("Component %s (%s) has no bonds", comp_name,
			comp_type),errorfile);
    endif
    
    
    ## Create the signed list of bonds on this component
    one = ones(n_comp_bonds,1);
    bond_list = index(:,1); %  bond at component
    
    ## Check that all bonds are unique -- error if not
    if unique(bond_list)==0
      mtt_error(sprintf("Component %s (%s) is at both ends of a bond", comp_name,
			comp_type),errorfile);
    endif
    
    

    ## which end of bond at component?
    bond_end = index(:,2); 
    direction = -sign(bond_end-1.5*one);
    signed_bond_list = bond_list.*direction;
    components = add_bond(components,signed_bond_list',i);
    
				# Unalias all the ports on this component - if not a junction
    unlabelled_ports = 0;  
    in_bonds = 0;
    out_bonds = 0;
    if ((comp_type!="0")&&(comp_type!="1")) # Don't do junctions
      for j=1:n_comp_bonds
	signed_bond = signed_bond_list(j);
	port_name_index = getindex(port_bond,signed_bond);
	port_direction = sign(signed_bond);
	
	if port_name_index==0	# There is no port on this bond - so try
				# to default
	  unlabelled_ports++;
	  if(unlabelled_ports==1)
	    if port_direction>0
	      in_bonds++;
	      port_name_i = "in";
	    else
	      out_bonds++;
	      port_name_i = "out";
	    endif
	    
	  elseif (unlabelled_ports==2)
	    if port_direction>0
	      if (++in_bonds>1)
		mtt_error(["More than one unlabelled INport on component " \
			   comp_name " (" comp_type ")"],errorfile);
	      else
		port_name_i = "in";
	      end
	    else
	      if (++out_bonds>1)
		mtt_error(["More than one unlabelled OUTport on component " \
			   comp_name " (" comp_type ")"],errorfile);
	      else
		port_name_i = "out";
	      end
	    endif
	    
	  else
	    mtt_error(["More than two unlabelled ports on component " \
		       comp_name " (" comp_type ")"],errorfile);
          endif
	  
	  mtt_info(["Defaulting port name [" port_name_i "]\t on component " \
		    comp_name " (" comp_type ")" ],infofile);
	  port_name = [port_name; ["[" port_name_i "]"]];	# add to list
	  [port_name_index,junk] = size(port_name); # the corresponding
				# index
	  port_bond(port_name_index,:) = signed_bond; # add to port bond
	else  
      	  port_name_i = deblank(port_name(port_name_index,:));
	  port_name_i = port_name_i(2:length(port_name_i)-1) # strip []
	endif
	
	
	## Replace by alias -- if any
    	eval( ["alias = ", comp_type, '_alias';]); # Get aliases
    	if is_struct(alias)		# are there any aliases
          if struct_contains(alias,port_name_i) # Is this an alias?
	    eval(["new_port_name_i = alias.",port_name_i]);
	    mtt_info(["Aliasing name [" port_name_i "]\t on component " \
		      comp_name " (" comp_type ")\t to [" new_port_name_i "]"],infofile);
	    port_name = replace_name(port_name, \
				     ["[",new_port_name_i,"]"], \
				     port_name_index);
	  endif
	  
      	endif
	
      endfor
      
    endif
    
  endfor
  
  ## At this point, every port should be labeled (port_name) and \
  ## associated with a bond (port_bond).
  disp("--- Completed portnames and the corresponding bonds ---")
  port_name, port_bond


  ## Deduce causality from the strokes (if any) and create the list of bonds
  causality = zeros(n_bonds,2);
  if n_strokes>0
    ## Find out location of centre and ends of stroke.
    stroke_end_1 = [rstrokes(:,1) rstrokes(:,2)];
    stroke_end_2 = [rstrokes(:,3) rstrokes(:,4)];
    
    stroke_centre = (stroke_end_1 + stroke_end_2)/2;
    stroke_vector = (stroke_end_1 - stroke_end_2);
    stroke_length = length2d(stroke_vector);

    ## Deduce bond causality from the strokes 
    for i = 1:n_strokes
      stroke = [stroke_centre(i,:) 
		stroke_end_1(i,:)
		stroke_end_2(i,:)];


      ## Find the nearest bond end.
      [index,distance] = adjbond(stroke(1,:),arrow_end,other_end);
      if (distance>2*stroke_length(i))
	info = sprintf('Stroke at (%4.3f,%4.3f) is %4.3f away from the nearest bond\n', ...
		       stroke(1,1)/scale, stroke(1,2)/scale, distance/scale);
      endif
      
      
      ## Bond end coordinates
      j = index(1,1);
      which_end = index(1,2)==1;
      bond_end = arrow_end(j,:)*which_end + other_end(j,:)*(1-which_end);
      
      ## Now decide which bit of the stroke is nearest
      stroke_index = adjbond(bond_end,stroke,zeros(size(stroke)));
      
      if stroke_index(1)==1 ## uni-causal stroke
	causality(j,1:2) = (2*which_end-1)*[1 1];
      else ## bicausal stroke
	## Find out whether stroke is on flow side of bond
	stroke_direction = stroke(1,:) - stroke(stroke_index(1),:);
	flow_side = stroke_direction*arrow_vector(j,:)'>0;
	causality(j,1+flow_side) = 2*which_end-1;
      endif
      
    endfor
    
  endif


  bonds = causality;

  ## Now expand vector ports
  [n_bonds,junk] = size(bonds);
  n_ports = length(port_bond);
  n_exp_ports=n_ports;
  exp_port_name="";
  exp_port_bond = [];
  ##exp_comps = [];
  for i=1:n_ports
    port_name_i = port_name(i,:)
    [subport,n_subports] = split_port(port_name_i, ','); ## Find the components of the vector port

    if n_subports==1 ## an ordinary port
      exp_port_name = [exp_port_name; subport(1,:)]; ## Write out the only port
      exp_port_bond = [exp_port_bond; port_bond(i)]; ## and the port_bond
    else ## its a vector port
      ## Check that there is a corresponding vector port at the other end of the
      ## bond
      signed_bond_index = port_bond(i);
      [other_bond_index,n_other] = getindex(port_bond,-signed_bond_index);
      if n_other == 1
	other_port_name = port_name(other_bond_index,:);
	[other_subport,n_other_subports] = split_port(other_port_name, ',');
	if n_other_subports~=n_subports
	  mtt_error(['Vector ports ', port_name_i, ' and ', other_port_name, 'are not compatible'],errorfile);
	end
      else 
	mtt_error(['Vector port ', port_name_i, ' has no matching port'], errorfile);
      endif
      
      
      if other_bond_index>i ##then its not been done yet
	mtt_info(["Vector port: ", port_name_i],infofile);
	mtt_info(["matching: ", other_port_name],infofile);
	## Remove sign info.
	bond_index = abs(signed_bond_index);
	sig = sign(signed_bond_index);
	
	## Put the first element of each port list in the expanded list
	exp_port_name = [exp_port_name; subport(1,:)];
	exp_port_name = [exp_port_name; other_subport(1,:)];
	
	## Add to the expanded port_bond list
	exp_port_bond = [exp_port_bond; signed_bond_index; ...
			 -signed_bond_index];
	
	## Add the other names to the expanded list and augment the bonds,
	## components and port_bond lists.
	for j=2:n_subports
	  ## Add a new name (for each end) to give a non-vector list
	  exp_port_name = [exp_port_name; subport(j,:)];
	  exp_port_name = [exp_port_name; other_subport(j,:)];
	  
	  ## Add one more bond to the list
	  bonds = [bonds; bonds(bond_index,:)];
	  n_bonds = n_bonds + 1;
	  
	  ## Add bond to the expanded port_bond list (ports at both ends)
	  exp_port_bond = [exp_port_bond; sig*n_bonds; -sig*n_bonds];


	  ## Add the new bond to the component at both ends (taking note 
	  ## of the direction).
	  arrow_index = comp_near_bond(bond_index,1);
	  components = add_bond(components, n_bonds, arrow_index);
	  other_index = comp_near_bond(bond_index,2);
	  components = add_bond(components, -n_bonds, other_index);
	endfor
	
      endif
      
    endif
    
  endfor



  ##Replace old list by new
  port_name = exp_port_name
  port_bond = exp_port_bond

  ## Resize the lists
  [n_ports,junk] = size(port_name);

  port_name, components
  ## Produce a list of bonds on each component (within this component) 
  ##  - sorted if explicit port numbers
  for i = 1:n_components    
    disp('-----------------');
    ##Get component type
    eval(['[comp_type, comp_name] = ', name, '_cmp(i)']);

    ##Convert junction names & get order of vector ports
    
    if comp_type(1)=='0'
      comp_type = 'zero';
    end

    if comp_type(1)=='1'
      comp_type = 'one';
    end

    ## Find the (unsorted) bond list on this component
    signed_bond_list = nozeros(components(i,:));
    n_comp_bonds = length(signed_bond_list);
    direction = sign(signed_bond_list);
    
    ##Find the port list for this component
    if exist([comp_type, '_cause'])==0

      eval(["ABG = ",comp_type, "_abg;"]);
      port_list = ABG.portlist;
    else
      port_list=comp_ports(comp_type,n_comp_bonds)
    endif
    

    [n_comp_ports,m_comp_ports] = size(port_list);
    subport_list="";
    for p=1:n_comp_ports		# Expand any vector ports
      [subport,n_sub] = split_port(port_list(p,:), ','); # Find the components
				# of the vector port
      if n_sub>1
	mtt_info(sprintf("Expanding vector port %s of component type %s",\
			 port_list(p,:), comp_type, infofile));	
      endif
      
      subport_list = [subport_list; subport];
    endfor
    
    port_list = subport_list;	# Set the expanded port list.
    

    ## Check that number of bonds on the component is the same as the number of
    ## ports
    [n_comp_ports,m_comp_ports] = size(port_list);
    if (n_comp_ports~=n_comp_bonds) & ...
	  ~(strcmp(comp_type,'zero')|strcmp(comp_type,'one'))
      message=sprintf('Component %s (%s) has %1.0f impinging bonds but has %1.0f ports', ...
		      comp_name,comp_type,n_comp_bonds,n_comp_ports);
      mtt_error(message, errorfile);
    endif
    
    
    unsorted_port_list="";
    if n_ports>0 ## then there are some named ports
      ## so find those associated with the bonds on this component.
      k=0; 
      for j = 1:n_comp_bonds
	b = signed_bond_list(j); 
	## Find the port label on component end of bond (if any)
	[port_index,m] = getindex(port_bond,b);
	if m==1
	  k=k+1;
	  unsorted_port_list(k,:) = port_name(port_index,:);
	endif
	
      endfor
      
    else 
      k=0;
    endif
    














    %Compute the number of labeled ports
    [n_unsorted_ports,m_unsorted_ports] = size(unsorted_port_list);
    if m_unsorted_ports==0
      n_unsorted_ports = 0;
    endif





























    
    ## Junctions (order of ports unimportant)
    if strcmp(comp_type,'zero')|strcmp(comp_type,'one')
      for j = 1:n_comp_bonds
	components(i,j) = signed_bond_list(j);
      endfor
      
    else ##Order of ports is important
      unsorted_port_list, port_list
      if n_unsorted_ports==0
	mtt_error(['Component ', comp_name, ' (', comp_type, ') has no labeled ports'], errorfile); 
      endif
      
      ##Write out the signed bond list in the correct order
      unsorted_port_list
      [n_list,m_list] = size(unsorted_port_list);
      if n_list!=n_comp_bonds
	error(sprintf("Component %s (%s) has %i bonds but %i port lables",\
		      comp_name, comp_type, n_comp_bonds, n_list))
      endif

      for j = 1:n_comp_bonds
	j
	name_k = unsorted_port_list(j,:)
	k = name_in_list(name_k, port_list);
	## Check that it only appears once in port list
	if length(k)>1
	  mtt_error(['Component ', comp_name, ' (', comp_type, ') has ports with the same name:  ', name_k], errorfile); 
	endif
	
	
	##Check that it only appears one in the label list
	kk = name_in_list(name_k,unsorted_port_list);
	if length(kk)>1
	  mtt_error(['Component ', comp_name, ' (', comp_type, ') has multiple port labels:  ', name_k], errorfile); 
	endif
	
	
	if k==0
	  mtt_error(['Component ', comp_name, ' (', comp_type, ') has an unrecognised port: ', name_k], errorfile); 
	else
	  components(i,k) = signed_bond_list(j);     
	endif

      endfor

    endif

  endfor
endfunction







MTT: Model Transformation Tools
GitHub | SourceHut | Sourceforge | Fossil RSS ]