File mttroot/mtt/bin/trans/m/mtt_component_eqn.m artifact a190371a3c part of check-in 140dec84c3


function [known] = mtt_component_eqn (fullname, port, causality, ...
				      known, Cbg)

  ## function [known] = mtt_component_eqn (fullname, port, causality, known)
  ##
  ## Recursively finds the equations giving the signal of specified
  ## causality on the specified port of component named "name" within
  ## subsystem Name 

  ## fullname:  name of component and subsystem
  ## port: port number of component
  ## causality: effort or flow
  ## know_list: list of components already known

  ## Data structures.
  ## A signal is a row vector containing three numbers:
  ##   Index -- a unique (within a subsystem) signed integer
  ##            abs(index) is the unique bond number, sign is the direction.
  ##   Causality -- 1 for effort, -1 for flow
  ##   Port -- the port of the component to which it is connected.
  ## 

  [Name,name] = mtt_subname(fullname); # Split fullname

  SD = "__";			# Subsystem delimiter
  CD = "\n%%";			# Comment delimiter
  arg_default = "1";		# Default aliased arg
  cr_default = "lin";		# Default aliased arg

  DEBUG = 0;

  if DEBUG
    disp("=======================================");
    fullname, name, Name, port,causality,known
  endif
  
  eqn="## No equation -- something wrong"; # Default

  if length(known)<2		# Invalid
    known = "  ";
  endif

  if length(Name)>0
    cbg = mtt_cbg(Name);		# Structure for this subsystem
    if isfield (cbg, "ports")
      ## Combine ports with the other subsystems
      for [component_structure, component] = cbg.ports
	eval(sprintf("cbg.subsystems.%s=cbg.ports.%s;",component,component));
      endfor
    endif
  endif


  if length(name)>0 		# Alias
    ##Alias arguments
    eval(sprintf("ARG=cbg.subsystems.%s.arg;", name)); # Arguments
    ARG = mtt_alias (Name,ARG,arg_default); # Alias them
    eval(sprintf("cbg.subsystems.%s.arg=ARG;", name)); # and copy
    ## Alias CRs
    eval(sprintf("CR=cbg.subsystems.%s.cr;", name)); # CRs
    CR = mtt_alias (Name,CR,cr_default); # Alias them
    eval(sprintf("cbg.subsystems.%s.cr=CR;", name)); # and copy
  else			  # Call to a subsystem (represented by name="")
    if !isfield(cbg,"portlist")
      N_ports = 0;
    else
      [N_ports,M_ports] = size(cbg.portlist);
    endif
    
    if port>N_ports
      error(sprintf("port (%i) > N_ports (%i)", port, N_ports));
    else			# Get name and find equation
      name = deblank(cbg.portlist(port,:));
      if DEBUG
	disp("----> lower-level system")
      endif
      known = mtt_component_eqn (mtt_fullname(Name,name), 1, ...
				 causality, known, cbg);
      return
    endif
  endif
  

  ## Other causality representations
  if strcmp(causality,"effort")
    i_cause = 1;
    othercausality = "flow";
    index_cause = 1;
    cause = "e";
  elseif strcmp(causality,"flow")
    i_cause = -1;
    othercausality = "effort";
    index_cause = 2;
    cause = "f";
  else
    error(sprintf("mtt_component_eqn: causality %s invalid", causality));
  endif
  
  ## A useful composite name
  name_port_cause = sprintf("%s_%i_%s",name, port, cause);
  full_name_port_cause = mtt_fullname(Name,name_port_cause);

  ## If value is known, don't do anything.
  if findstr(sprintf(" %s ", full_name_port_cause), known)>0
    eqn = sprintf("%s The %s signal on port %i of %s is known already", ...
		  CD, causality, port, name);
    return
  else			# Add to list
    known = sprintf("%s %s", known, full_name_port_cause);
  endif
  
  
  
  ## Component type
  comp_type = eval(sprintf("cbg.subsystems.%s.type;", name));
  if DEBUG
    comp_type
  endif
  
  ## Component cr
  cr = eval(sprintf("cbg.subsystems.%s.cr;", name));

  ## Component arg
  arg = eval(sprintf("cbg.subsystems.%s.arg;", name));

  ## To which bond(s) is the component connected?
  connections = eval(sprintf("cbg.subsystems.%s.connections;", name));
  bond_list = abs(connections);	# Unsigned list 
  out_bond_number = bond_list(port);	# The bond at the output of this component
  direction = sign(connections); # Bond directions
  directions = direction'*[1 1]; 

  ## List of system bonds
  bonds = cbg.bonds;

  ## List of component bond causality (component-orientated causality)
  comp_bonds = bonds(bond_list,:).*directions; # Component bonds

  ## What components are at the other ends of the in bonds?
  ## Effort
  [in_e_bonds,in_e_components,in_e_ports,N_e] = mtt_component_inputs ...
      (name,comp_type,causality,"effort",comp_bonds,connections,cbg);
  ## Flow
  [in_f_bonds,in_f_components,in_f_ports,N_f] = mtt_component_inputs ...
      (name,comp_type,causality,"flow",comp_bonds,connections,cbg);


  ##Composite values
  N_ef = N_e + N_f;
  in_ef_bonds = [in_e_bonds; in_f_bonds];
  in_ef_components = [in_e_components; in_f_components];
  in_ef_ports = [in_e_ports; in_f_ports];
  in_causality = [ones(N_e,1); -ones(N_f,1)];

  ## Lists of signals relevant to this component
  outsig = [out_bond_number i_cause port];
  insigs = [in_ef_bonds in_causality in_ef_ports];
  innames = in_ef_components;

  if DEBUG
    outsig
    insigs
    innames
  endif
  
  ## Is the signal the output of a port?
  is_port_output = 0;			# Default
  if isfield (cbg, "ports")
    if isfield (cbg.ports,name)
      is_port_output = (outsig(2)!=insigs(1,2));
    endif
  endif
  
  if is_port_output
    ## Which port (number) is it?
    [N_ports,M_ports] = size(cbg.portlist);
    for i=1:N_ports
      if strcmp(deblank(cbg.portlist(i,:)), name)
	port_index = i;
	break;
      endif
    endfor

    ## File containing data structure
    NAME = mtt_subname(Name);
    CBG = mtt_cbg(NAME);
    
    ## And to which component (at higher level) is it connected?
    [new_Name,new_name] = mtt_subname(Name);
    port_bond = eval(sprintf("CBG.subsystems.%s.connections(%i);", new_name, port_index));
    [in_name, in_port, in_bond] = mtt_other_end (new_name,port_bond,CBG);

    ## Find its equation
    if DEBUG
      disp("----> higher level system")
    endif
    

    known = mtt_component_eqn (mtt_fullname(new_Name,in_name), ...
			       in_port, causality, known, cbg);

    LHS = Source_seqn ("external",Name);
    RHS = varname(NAME, abs(in_bond), i_cause);
    eqn = sprintf("%s%s%s := %s;", LHS, SD, name, RHS);

    if !DEBUG
      comment = sprintf("%s PORT", CD);
      disp(sprintf("%s\n%s",comment, eqn));
    endif

  endif
  

  ## Handle special components
  if strcmp(comp_type,"0")||strcmp(comp_type,"1") # Junctions
    [eqn,insigs,innames] = junction_seqn (comp_type,Name, outsig, ...
					  insigs, innames);
  else				# Everything else
    if exist(sprintf("%s_cause", comp_type)) # Simple component
      ## Do the equations
      [eqn,insigs,innames] = eval(sprintf("%s_seqn (Name, name, cr, ...
						    arg, outsig, ...
						    insigs, ...
						    innames, is_port_output);", ...
					  comp_type));
      ## Resolve CR
      eqn = mtt_resolve_cr(eqn);

    else			# Compound component
      new_NAME = Name;
      new_Name = mtt_fullname(Name,name);
      new_name = "";
      
      ## Get relevant data structure
      Cbg = mtt_cbg(new_Name);
      port_name = Cbg.portlist(port,:);

      LHS = varname(Name, outsig(1,1), outsig(1,2));
      RHS = Sensor_seqn ("external",new_Name);
      eqn = sprintf("%s := %s%s%s;", LHS, RHS, SD, port_name);

      if DEBUG
	disp("----> same-level subsystem")
      endif

      [known] = mtt_component_eqn ...
   	  (mtt_fullname(new_Name,new_name), port, causality, known, cbg);
      
    endif
  endif

  comment = ...
      sprintf("%s Equation for %s signal on port %i of %s (%s), subsystem %s.", ...
     	      CD, causality, port, name, comp_type, Name);

  if DEBUG
    disp(sprintf("%s\n%s",comment, eqn));
  endif
  
  is_external = mtt_is_external(comp_type,outsig, insigs, is_port_output);

  if !is_external
    ## Find the corresponding input equations
    [N_other,M_other] = size(insigs);
    for i = 1:N_other
      if insigs(i,2)==1
	other_causality = "effort";
      else
	other_causality = "flow";
      endif

      other_port = insigs(i,3);
      other_name = deblank(innames(i,:));
      if DEBUG
	disp("----> same-level component")
      endif
      

      [known] = mtt_component_eqn ...
    	  (mtt_fullname(Name,other_name), other_port, other_causality, ...
	   known, cbg);
    endfor
  endif

  ## Write this signal
  ##comment_2 = sprintf("Connected to:%s", in_component_list);
  if !DEBUG
    disp(sprintf("%s\n%s",comment, eqn));
  endif

endfunction

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