File mttroot/mtt/bin/trans/m/ibg2abg.m artifact 04eb14e49f part of check-in b08d59c51d


## -*-octave-*-

function [bonds,components,n_vector_bonds] = \
      ibg2abg(name,bonds,infofile,errorfile)

  ## write useful quantity of data to log
  struct_levels_to_print = 4;

  ################################
  ## create component structure ##
  ################################
  
  ## loop over each bond in ibg.m file
  for [bond, bond_name] = bonds
    i = str2num(split(bond_name, "bond")(2,:));

    ## populate "head" and "tail" structures
    ## then copy the contents to an overall structure

    ## track (signed) vector bond number within each component
    head.index = +i;
    tail.index = -i;

    ## extract type of component at each end
    head_type = deblank(split(bond.head.component, ":")(1,:));
    tail_type = deblank(split(bond.tail.component, ":")(1,:));

    ## extract name of component at each end
    head_name = deblank(split(bond.head.component, ":")(2,:));
    tail_name = deblank(split(bond.tail.component, ":")(2,:));

    ## extract port label data
    head.label = bond.head.ports;
    tail.label = bond.tail.ports;

    ## determine whether internal port or subsystem
    ## and fix names of ports
    if (strcmp(head_type, "SS") & (index(head_name, "[") == 1))
      head_comp_or_port = "port";
      head_name = mtt_strip_name(head_name);
    else
      head_comp_or_port = "comp";
    endif
    if (strcmp(tail_type, "SS") & (index(tail_name, "[") == 1))
      tail_comp_or_port = "port";
      tail_name = mtt_strip_name(tail_name);
    else
      tail_comp_or_port = "comp";
    endif

    eval(sprintf("comp_s.%s.%s.type = '%s';",
		 head_comp_or_port, head_name, head_type));
    eval(sprintf("comp_s.%s.%s.type = '%s';",
		 tail_comp_or_port, tail_name, tail_type));

    eval(sprintf("comp_s.%s.%s.bond%i = head;", 
		 head_comp_or_port, head_name, i));
    eval(sprintf("comp_s.%s.%s.bond%i = tail;", 
		 tail_comp_or_port, tail_name, i));
  endfor    

  disp("--finished extracting data from ibg.m --")
  comp_s
    
  ## comp_s
  ##   comp
  ##     %s (name)
  ##       type
  ##       bond%i
  ##         label
  ##   port
  ##     %s (name)
  ##       type
  ##       bond%i
  ##         label

  ####################################################
  ## count number of vector bonds on each component ##
  ####################################################

  if (struct_contains(comp_s, "comp"))
    for [comp, comp_name] = comp_s.comp
      n = size(struct_elements(comp))(1) - 1;
      eval(sprintf("comp_s.comp.%s.n_bonds = %i;",
		   comp_name, n));
    endfor
  endif
  
  if (struct_contains(comp_s, "port"))
    for [port, port_name] = comp_s.port
      n = size(struct_elements(port))(1) - 1;
      eval(sprintf("comp_s.port.%s.n_bonds = %i;",
		   port_name, n));
    endfor
  endif

  disp("-- finished counting number of bonds on components --")
  comp_s

  ## comp_s
  ##   comp
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##   port
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label

  ########################################################
  ## ensure labels exist on all ports of each component ##
  ########################################################

  if (struct_contains(comp_s, "comp"))
    for [comp, comp_name] = comp_s.comp
      if (strcmp(comp.type, "0") | strcmp(comp.type, "1"))
	
	## component is a junction
	n_named_ports = 0;
	
	## get labelled ports
	for [bond, bond_name] = comp
	  if (index(bond_name, "bond") == 1)
	    if (! exist("bond.label"))
	      bond.label = "[]";
	    endif
	    if (! strcmp(bond.label, "[]"))
	      n_named_ports += 1;
	      port_label = bond.label;
	    endif
	  endif
	  eval(sprintf("comp.%s = bond;", bond_name));
	endfor
	
	## attach labels to unlabelled ports
	if (n_named_ports == 0)
	  for [bond, bond_name] = comp
	    if (index(bond_name, "bond") == 1)
	      bond.label = "in";
	    endif
	    eval(sprintf("comp.%s = bond;", bond_name));
	  endfor
	elseif (n_named_ports == 1)
	  mtt_info(sprintf("Defaulting all ports on junction %s to %s", \
			   comp_name, port_label), infofile);
	  for [bond, bond_name] = comp
	    if (index(bond_name, "bond") == 1)
	      bond.label = port_label;
	    endif
	    eval(sprintf("comp.%s = bond;", bond_name));
	  endfor
	elseif (n_named_ports != bond.n_bonds)
	  mtt_error(sprintf("Junction must have 0,1 or %i port labels", \
			    n_bonds), errorfile);
	endif
	
      else
	## component is not a junction
	for [bond, bond_name] = comp
	  if (index(bond_name, "bond") == 1)
	    if (strcmp(bond.label, "[]"))
	      if (bond.index > 0)
		bond.label = "in";
	      else
		bond.label = "out";
	      endif
	    else
	      bond.label = mtt_strip_name(bond.label);
	    endif
	  endif
	  eval(sprintf("comp.%s = bond;", bond_name));
	endfor
      endif
      
      eval(sprintf("comp_s.comp.%s = comp;", comp_name));
    endfor
  endif

  ####################
  ## expand aliases ##
  ####################

  if (struct_contains(comp_s, "comp"))
    for [comp, comp_name] = comp_s.comp
      if ((! strcmp(comp.type, "0")) & (! strcmp(comp.type, "1")))
	alias = eval(sprintf("%s_alias", comp.type));
	if (is_struct(alias))
	  for [bond, bond_name] = comp
	    if (struct_contains(alias, "bond.label"))
	      old_name = bond.label;
	      new_name = eval(sprintf("alias.%s", old_name));
	      bond.label = new_name;
	      mtt_info(sprintf("Aliasing [%s] on %s (%s) to [%s]",
			       old_name, comp_name, comp.type, new_name),
		       infofile);
	    endif
	    eval(sprintf("comp.%s = bond;", bond_name));
	  endfor
	endif
	eval(sprintf("comp_s.%s = comp;", comp_name));
      endif
    endfor
  endif

  disp("-- finished expanding aliases --")
  comp_s

  ## comp_s
  ##   comp
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##   port
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label

  ##########################################
  ## create sub-bonds according to labels ##
  ##########################################

  if (struct_contains(comp_s, "comp"))
    for [comp, comp_name] = comp_s.comp
      for [bond, bond_name] = comp
	if (index(bond_name, "bond") == 1)
	  [sub_bonds, n_sub_bonds] = split_port(bond.label);
	  for i = 1:n_sub_bonds
	    eval(sprintf("bond.subbond%i.label = '%s';",
			 i, deblank(sub_bonds(i,:))))
	  endfor
	endif
	eval(sprintf("comp.%s = bond;", bond_name));
      endfor
      eval(sprintf("comp_s.comp.%s = comp;", comp_name));
    endfor
  endif

  if (struct_contains(comp_s, "port"))
    for [port, port_name] = comp_s.port
      for [bond, bond_name] = port
	if (index(bond_name, "bond") == 1)
	  [sub_bonds, n_sub_bonds] = split_port(bond.label);
	  for i = 1:n_sub_bonds
	    eval(sprintf("bond.subbond%i.label = '%s';",
			 i, deblank(sub_bonds(i,:))));
	  endfor
	endif
	eval(sprintf("port.%s = bond;", bond_name));
      endfor
      eval(sprintf("comp_s.port.%s = port;", port_name));
    endfor
  endif

  disp("-- finished creating sub-bonds --")
  comp_s

  ## comp_s
  ##   comp
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##         subbond%i
  ##   port
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##         subbond%i

  #########################################
  ## assign a unique number to each bond ##
  #########################################

  unique_bond_number = 0;
  
  for [bond, bond_name] = bonds
    i = str2num(split(bond_name, "bond")(2,:));

    ## extract type of component at each end
    head.type = deblank(split(bond.head.component, ":")(1,:));
    tail.type = deblank(split(bond.tail.component, ":")(1,:));

    ## extract name of component at each end
    head_name = deblank(split(bond.head.component, ":")(2,:));
    tail_name = deblank(split(bond.tail.component, ":")(2,:));
 
    ## determine whether internal port or subsystem
    ## and fix names of ports
    if (strcmp(head.type, "SS") & (index(head_name, "[") == 1))
      head_comp_or_port = "port";
      head_name = mtt_strip_name(head_name);
    else
      head_comp_or_port = "comp";
    endif
    if (strcmp(tail.type, "SS") & (index(tail_name, "[") == 1))
      tail_comp_or_port = "port";
      tail_name = mtt_strip_name(tail_name);
    else
      tail_comp_or_port = "comp";
    endif

    ## create strings to reference each component
    head_str = sprintf("comp_s.%s.%s.bond%i",
		       head_comp_or_port, head_name, i)
    tail_str = sprintf("comp_s.%s.%s.bond%i",
		       tail_comp_or_port, tail_name, i)

    head_bond = eval(head_str);
    tail_bond = eval(tail_str);
    
    ## check compatible sizes
    head.n_subs = size(struct_elements(head_bond))(1) - 2;
    tail.n_subs = size(struct_elements(tail_bond))(1) - 2;
    if (head.n_subs != tail.n_subs)
      mtt_error(sprintf("Vector ports %s and %s are not compatible",
			head_bond.label, tail_bond.label), errorfile);
    elseif (head.n_subs > 1)
      mtt_info(sprintf("Vector port %s matches %s",
		       head_bond.label, tail_bond.label), infofile);
    endif

    ## write type at other end
    eval(sprintf("%s.other_end_type = '%s';",
		 head_str, tail.type));
    eval(sprintf("%s.other_end_type = '%s';",
		 tail_str, head.type));

    ## assign bond number
    for i = 1:head.n_subs
      ++unique_bond_number;
      eval(sprintf("%s.subbond%i.index = +%i;",
		   head_str, i, unique_bond_number));
      eval(sprintf("%s.subbond%i.index = -%i;",
		   tail_str, i, unique_bond_number));

      ## write causality for bond
      if (strcmp(bond.causality.effort, "head"))
	eval(sprintf("causality(%i,1) = +1;", unique_bond_number));
      elseif (strcmp(bond.causality.effort, "tail"))
	eval(sprintf("causality(%i,1) = -1;", unique_bond_number));
      else
	eval(sprintf("causality(%i,1) = 0;", unique_bond_number));
      endif

      if (strcmp(bond.causality.flow, "head"))
	eval(sprintf("causality(%i,2) = -1;", unique_bond_number));
      elseif (strcmp(bond.causality.flow, "tail"))
	eval(sprintf("causality(%i,2) = +1;", unique_bond_number));
      else
	eval(sprintf("causality(%i,2) = 0;", unique_bond_number));
      endif
      
    endfor
  endfor

  disp("-- finished assigning unique numbers to bonds --")
  comp_s
  
  ## comp_s
  ##   comp
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##         subbond%i
  ##           index
  ##   port
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##         subbond%i
  ##           index

  ## causality matrix is called "bonds"
  bonds = causality
  disp("-- finished writing bonds matrix --")  

  #################################
  ## map component data to cmp.m ##
  #################################

  ## count number of components
  if (struct_contains(comp_s, "comp"))
    n_comps = size(struct_elements(comp_s.comp), 1)
  else
    n_comps = 0;
  endif

  ## count number of internal ports
  if (struct_contains(comp_s, "port"))
    n_ports = size(struct_elements(comp_s.port), 1)
  else
    n_ports = 0;
  endif

  ## read data from _cmp.m
  for cmp = 1:(n_comps + n_ports)
    [this_type, this_name] = eval(sprintf("%s_cmp(%i)", name, cmp));
    ## determine if internal port (and fix name) or subsystem
    if (strcmp(this_type, "SS") & (index(this_name, "[") == 1))
      comp_or_port = "port";
      this_name = mtt_strip_name(this_name)
    else
      comp_or_port = "comp";
    endif
    eval(sprintf("comp_s.%s.%s.index = cmp;", comp_or_port, this_name));
  endfor

  disp("-- finished getting component indices from cmp.m --")
  comp_s

  ## comp_s
  ##   comp
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##         subbond%i
  ##           index
  ##       index
  ##   port
  ##     %s (name)
  ##       type
  ##       n_bonds
  ##       bond%i
  ##         label
  ##         subbond%i
  ##           index
  ##       index

  ##########################
  ## write n_vector_bonds ##
  ##########################

  if (struct_contains(comp_s, "comp"))
    for [comp, comp_name] = comp_s.comp
      n_vector_bonds(comp.index) = comp.n_bonds;
    endfor
  endif

  disp("-- finished writing n_vector_bonds --")
  n_vector_bonds

  ###########################################
  ## Write connections matrix (components) ##
  ###########################################
  
  if (struct_contains(comp_s, "comp"))
    n_comps = size(struct_elements(comp_s.comp))(1);
  else
    n_comps = 0;
  endif

  components = zeros(n_comps, max(n_vector_bonds));

  if (struct_contains(comp_s, "comp"))
    for [comp, comp_name] = comp_s.comp
      counter = 0;
      for [bond, bond_name] = comp
	if (index(bond_name, "bond") == 1)
	  if (strcmp(bond.other_end_type, "SS"))
	    for [sub_bond, sub_bond_name] = bond
	      if (index(sub_bond_name, "subbond") == 1)
		components(comp.index, ++counter) = sub_bond.index
	      endif
	    endfor
	  endif
	endif
      endfor
      for [bond, bond_name] = comp
	if (index(bond_name, "bond") == 1)
	  if (!strcmp(bond.other_end_type, "SS"))
	    for [sub_bond, sub_bond_name] = bond
	      if (index(sub_bond_name, "subbond") == 1)
		components(comp.index, ++counter) = sub_bond.index
	      endif
	    endfor
	  endif
	endif
      endfor
    endfor
  endif

  if (struct_contains(comp_s, "port"))
    for [port, port_name] = comp_s.port
      counter = 0;
      for [bond, bond_name] = port
	if (index(bond_name, "bond") == 1)
	  for [sub_bond, sub_bond_name] = bond
	    if (index(sub_bond_name, "subbond") == 1)
	      components(port.index, ++counter) = sub_bond.index;
	    endif
	  endfor
	endif
      endfor
    endfor
  endif

  disp("-- finished writing components matrix --")
  components

endfunction


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