Index: mttroot/mtt/bin/trans/m/abg2cbg.m ================================================================== --- mttroot/mtt/bin/trans/m/abg2cbg.m +++ mttroot/mtt/bin/trans/m/abg2cbg.m @@ -17,10 +17,13 @@ # ############################################################### # ## Version control history # ############################################################### # ## $Id$ # ## $Log$ +# ## Revision 1.35 1998/08/24 10:16:32 peterg +# ## Coverted to new structure - still needs status sorting. +# ## # ## Revision 1.34 1998/08/24 07:35:03 peterg # ## About to go to new abg format. # ## # ## Revision 1.33 1998/07/29 13:36:37 peterg # ## Don't set port status if there aren't any ports. @@ -162,12 +165,12 @@ # Create a file to contain shell commands which map subsystem types # onto components if at_top_level # Then at top level fprintf(typefile, "# Commands to map types onto subsystems\n"); - fprintf(typefile, "# File #s_type.sh\n", system_name); - fprintf(typefile, "# Generated by MTT on #s\n\n", date); + fprintf(typefile, "# File %s_type.sh\n", system_name); + fprintf(typefile, "# Generated by MTT at %s\n\n", ctime(time)); end; # Create the (full) system name if at_top_level full_name = system_name; @@ -177,11 +180,11 @@ end; # Add to file to contain shell commands which map subsystem types # onto components - fprintf(typefile, "$1#s$2#s$3\n", system_type, full_name); + fprintf(typefile, "$1%s$2%s$3\n", system_type, full_name); fun_name = [system_type, "_abg"]; disp("===================================="); disp(["BEGIN: ", full_name, " (", fun_name, ")"]); @@ -196,22 +199,30 @@ end; # Evaluate the system function to get the bonds and number of ports #eval(["[bonds,components,n_ports,N_ports]=", fun_name, ";"]); eval(["[ABG]=", fun_name, ";"]); - bonds = ABG.bonds; - n_ports=0; - if !struct_contains(ABG,"subsystems")# Are there any subsystems + + if !struct_contains(ABG,"subsystems")# Are there any subsystems? return; # Nothing to do else [n_subsystems,junk] = size(struct_elements(ABG.subsystems)); endif - + if struct_contains(ABG,"ports")# Are there any ports? + [n_ports,junk] = size(struct_elements(ABG.ports)); + port_bond_index=zeros(n_ports,1); + for port = ABG.ports # Find indices of the internal port bonds + port_bond_index(port.index) = port.connections; + endfor + port_bond_index=abs(port_bond_index); + else + n_ports = 0; + endif - [n_bonds,columns] = size(bonds);# Find number of bonds + [n_bonds,columns] = size(ABG.bonds);# Find number of bonds if (columns ~= 2)&(n_bonds>0) error("Incorrect bonds matrix: must have 2 columns"); end; @@ -219,260 +230,278 @@ # [n_components,m_components] = size(components); # if n_components==0 # there is nothing to be done # return # end; - port_bond_direction + # Coerce the port (SS:[]) component bonds to have the same direction as # of the bonds in the encapsulating system -- but not at top level - if (n_ports>0)&&(~at_top_level) - port_bond_index = abs(components(1:n_ports,1:m_components))# relevant - # bond - # numbers - port_bond_index = nozeros(reshape(\ - port_bond_index',n_ports*m_components,1))'# vectorise - - for i=1:n_ports - # Is the direction different? - if (sign(components(i,1))~=port_bond_direction(i)) - mtt_info(sprintf("Flip port #i",i),infofile); - # Flip direction at port - components(i,1) = - components(i,1); - # and at the other end - for j=n_ports+1:n_components - for k=1:m_components - if (abs(components(j,k))==port_bond_index(i)) - components(j,k) = - components(j,k); - end - end - end; - # Flip the bond causalities (these are arrow-orientated) - bonds(port_bond_index(i),:) = -bonds(port_bond_index(i),:); - end - end - end +# if (n_ports>0)&&(!at_top_level) + +# # port_bond_index = abs(components(1:n_ports,1:m_components))# relevant +# # bond +# # numbers +# # port_bond_index = nozeros(reshape(\ +# # port_bond_index',n_ports*m_components,1))'# vectorise + +# for port = ABG.ports +# #for i=1:n_ports +# # Is the direction different? +# if (sign(port.connections)!=port_bond_direction(i)) +# mtt_info(sprintf("Flip port #i",i),infofile); +# # Flip direction at port +# port.connections = - port.connections; +# # and at the other end +# for subsystem = ABG.subsystems +# for k=1:length(subsystem.connections) +# if (abs(subsystem.connection(k))==port_bond_index(i)) +# subsystem.connection(k) = -subsystem.connection(k); +# end +# end +# end; +# # Flip the bond causalities (these are arrow-orientated) +# ABG.bonds(port_bond_index(i),:) = -ABG.bonds(port_bond_index(i),:); +# end +# end +# end # Set initial status - status = -ones(n_subsystems,1); +# status = -ones(n_subsystems,1); # If not at top level, then copy the port bonds. if ~at_top_level # Find number of port bonds [n_port_bonds,columns] = size(port_bonds); # Check compatibility - if ok copy port bonds to the internal bonds list. - if n_port_bonds~=N_ports - mtt_error(sprintf("#s: #1.0f port bonds incompatible with #1.0f ports", ... - full_name, n_port_bonds, n_ports), errorfile); +# if n_port_bonds~=N_ports +# mtt_error(sprintf("#s: #1.0f port bonds incompatible with #1.0f ports", ... +# full_name, n_port_bonds, n_ports), errorfile); - else # Copy the port bonds & status +# else # Copy the port bonds & status for j = 1:n_port_bonds jj = port_bond_index(j); for k = 1:2 - if bonds(jj,k)==0 # only copy if not already set - bonds(jj,k) = port_bonds(j,k); + if ABG.bonds(jj,k)==0 # only copy if not already set + ABG.bonds(jj,k) = port_bonds(j,k); end; end; # status(1:N_ports) = port_status; - end +# end end else n_port_bonds=0; end; # bonds,port_bonds # Causality indicator total = 2*n_bonds; - done = sum(sum(abs(bonds)))/total*100; - -# Outer while loop sets preferred causality - ci_index=1; - - for [subsystem,name] = ABG.subsystems# Set new status field to -1 - eval(["ABG.subsystems.",name,".status=-1;"]); - endfor; - - while( ci_index>0) - old_done = inf; - - while done~=old_done # Inner loop propagates causality - old_done = done; - for [subsystem,name] = ABG.subsystems - if subsystem.status ~= 0 # only do this if causality not yet complete - - # Get the bonds on this component - comp = subsystem.connections; - bond_list = abs(comp); - direction = sign(comp)'*[1 1]; - n_bonds = length(bond_list); - - # Get the component details - #eval([ "[comp_type,name,cr,arg] = ", system_type, "_cmp(i);" ]); - - # Change name of 0 and 1 components -- matlab doesn't like numbers here - if strcmp(subsystem.type,"0") - subsystem.type = "zero"; - end; - if strcmp(subsystem.type,"1") - subsystem.type = "one"; - end; - - # Component causality procedure name - cause_name = [subsystem.type, "_cause"]; - - # Component equation procedure name - eqn_name = [subsystem.type, "_eqn"]; - - # Bonds on this component (arrow-orientated) -- these become the - # port bonds on the ith component of this subsystem. - - comp_bonds=[]; - for kk = 1:n_bonds - comp_bonds(kk,:) = bonds(bond_list(kk),:); - end; - - - # Invoke the appropriate causality procedure - if exist(eqn_name)~=2 # Try a compound component - # Port status depends on whether the corresponding bonds are - # fully causal at this stage. - one = ones(n_bonds,1); - port_status = (sum(abs(comp_bonds'))'==2*one) - one; - - # Direction of bonds on the ports (0 if next to port) - port_bond_direction = -sign(components(i,1:n_bonds))'; - - # If there is a predefined causality function; use it - if exist(cause_name)==2 - # Convert from arrow orientated to component orientated causality - comp_bonds = comp_bonds.*(port_bond_direction*[1 1]); - - # Evaluate the built-in causality procedure - eval([ "[comp_bonds] = ", cause_name, "(comp_bonds);" ]); - - # and convert from component orientated to arrow orientated causality - comp_bonds = comp_bonds.*(port_bond_direction*[1 1]); - end; - - [comp_bonds,s] = abg2cbg(name, subsystem.type, full_name, - comp_bonds, port_bond_direction, port_status, ... - typefile, infofile, errorfile); - - # Create a single status from the status vector s - if max(abs(s)) == 0 # Causal - status(i) = 0; - else - if max(s) == 1 # At least one component is overcausal - status(i) = 1; - else # no component is overcausal but some are undercausal - status(i) = -1; - end; - end; - - else # its a simple component -- or explicit causality defined - disp(["---", name, " (", cause_name, ") ---"]); - comp_bonds_in = comp_bonds - - # Convert from arrow orientated to component orientated causality - comp_bonds = comp_bonds.*direction; - - # Evaluate the built-in causality procedure - #eval([ "[comp_bonds,status(i)] = ", cause_name, "(comp_bonds);" ]); - eval([ "[comp_bonds,subsystem.status] = ", cause_name, "(comp_bonds);" ]); - # and convert from component orientated to arrow orientated causality - comp_bonds = comp_bonds.*direction; - - comp_bonds_out = comp_bonds - end; - - bonds,bond_list,comp_bonds - # Update the full bonds list - bonds(bond_list,:) = comp_bonds; - end; - end; - - done = sum(sum(abs(bonds)))/total*100; - #disp(sprintf("Causality is #3.0f#s complete.", done, pc), infofile)); - - end; - - # Set causality of a C or I which is not already set - [name,prefered] = getdynamic(ABG.subsystems) - if prefered==0 - ci_index=0; - else - disp("Set causality of a C or I which is not already set") - eval(["ci_bond_index = ABG.subsystems.",name,".connections;"]); # Get all bonds - ci_direction = sign(ci_bond_index); - ci_bond_index = abs(ci_bond_index); - bonds(ci_bond_index,1:2) = prefered*ci_direction'*[1 1]; - eval(["ABG.subsystems.",name,".status=0"]); #set status of the C or I - endif; - end; - - if n_ports>0 - status(1:n_ports) = zeros(n_ports,1); # Port status not relevant - endif; - -# Print final causality -# final_done = (sum(status==zeros(n_components,1))/n_components)*100; - -if at_top_level - mtt_info(sprintf("Final causality of #s is #3.0f#s complete.", ... - full_name, done, pc), infofile); - - if done<100 - mtt_error(sprintf("Unable to complete causality"),errorfile); - end; - - # List overcausal bonds - [over_causal_bonds,n] = getindex(status,1); - if n>0 - for i=over_causal_bonds' - eval([ "[comp_type,name] = ", system_type, "_cmp(i);" ]); - mtt_info(sprintf("Component #s (#s) is overcausal", name, subsystem.type), ... - infofile); - end; - end; - - # List undercausal bonds - [under_causal_bonds,n] = getindex(status,-1); - if n>0 - for i=under_causal_bonds' - eval([ "[comp_type,name] = ", system_type, "_cmp(i);" ]); - mtt_info(sprintf("Component #s (#s) is undercausal", name, subsystem.type), ... - infofile); - end; - end; -end; - -# $$$ file_name = [full_name, "_", system_type] -file_name = [full_name, "_cbg.m"]; -disp(["Writing ", file_name]); -cbgfilenum = fopen(file_name,"w"); - -components=[]; -for [subsystem,name] = ABG.subsystems - components=add_row(components,subsystem.connections); -endfor - -write_cbg(cbgfilenum,full_name,system_type,bonds,status,components); -fclose(cbgfilenum); - -# Return the port bonds - arrow orientated causality - and the direction -if ~at_top_level # Not at top level - port_bonds = bonds(port_bond_index,:) # Return port bonds -end; - -disp("===================================="); -disp(["END: ", full_name, " (", fun_name, ")"]); -disp("===================================="); + done = sum(sum(abs(ABG.bonds)))/total*100; + + +field=["ports";"subsystems"]; # Do for both ports and subsystems - +# # ports first + for i=1:2 + if struct_contains(ABG,field(i,:)); + eval(["ABG_field = ABG.",field(i,:), ";"]); + +# Outer while loop sets preferred causality + ci_index=1; + + for [subsystem,name] = ABG_field# Set new status field to -1 + eval(["ABG_field.",name,".status=-1;"]); + endfor; + + while( ci_index>0) + old_done = inf; + + while done!=old_done # Inner loop propagates causality + old_done = done; + for [subsystem,name] = ABG_field + if subsystem.status != 0 # only do this if causality not yet complete + + # Get the bonds on this component + comp = subsystem.connections; + bond_list = abs(comp); + direction = sign(comp)'*[1 1]; + n_bonds = length(bond_list); + + # Get the component details + #eval([ "[comp_type,name,cr,arg] = ", system_type, "_cmp(i);" ]); + + # Change name of 0 and 1 components -- matlab doesn't like numbers here + if strcmp(subsystem.type,"0") + subsystem.type = "zero"; + end; + if strcmp(subsystem.type,"1") + subsystem.type = "one"; + end; + + # Component causality procedure name + cause_name = [subsystem.type, "_cause"]; + + #Component equation procedure name + eqn_name = [subsystem.type, "_eqn"]; + + # Bonds on this component (arrow-orientated) -- these become the + # port bonds on the ith component of this subsystem. + + comp_bonds=[]; + for kk = 1:n_bonds + comp_bonds(kk,:) = ABG.bonds(bond_list(kk),:); + end; + + + # Invoke the appropriate causality procedure + if exist(eqn_name)!=2 # Try a compound component + # Port status depends on whether the corresponding bonds are + # fully causal at this stage. + one = ones(n_bonds,1); + port_status = (sum(abs(comp_bonds'))'==2*one) - one; + + # Direction of bonds on the ports (0 if next to port) + #port_bond_direction = -sign(components(i,1:n_bonds))'; + port_bond_direction = -sign(subsystem.connections)'; + # If there is a predefined causality function; use it + if exist(cause_name)==2 + # Convert from arrow orientated to component orientated causality + comp_bonds = comp_bonds.*(port_bond_direction*[1 1]); + + # Evaluate the built-in causality procedure + eval([ "[comp_bonds] = ", cause_name, "(comp_bonds);" ]); + + # and convert from component orientated to arrow orientated causality + comp_bonds = comp_bonds.*(port_bond_direction*[1 1]); + end; + + [comp_bonds,subsystem.status] = abg2cbg(name, subsystem.type, full_name, + comp_bonds, port_bond_direction, port_status, ... + typefile, infofile, errorfile); + # # Create a single status from the status vector s + # if max(abs(s)) == 0 # Causal + # status(i) = 0; + # else + # if max(s) == 1 # At least one component is overcausal + # status(i) = 1; + # else # no component is overcausal but some are undercausal + # status(i) = -1; + # end; + # end; + + else # its a simple component -- or explicit causality defined + disp(["---", name, " (", cause_name, ") ---"]); + comp_bonds_in = comp_bonds + + # Convert from arrow orientated to component orientated causality + comp_bonds = comp_bonds.*direction; + + # Evaluate the built-in causality procedure + #eval([ "[comp_bonds,status(i)] = ", cause_name, "(comp_bonds);" ]); + eval([ "[comp_bonds,subsystem.status] = ", cause_name, "(comp_bonds)" ]); + # and convert from component orientated to arrow orientated causality + comp_bonds = comp_bonds.*direction; + + comp_bonds_out = comp_bonds + end; + + ABG.bonds(bond_list,:) = comp_bonds;# Update the full bonds list + eval(["ABG.subsystems.",name,".status = subsystem.status'"]); + end; + end; + + done = sum(sum(abs(ABG.bonds)))/total*100 + #disp(sprintf("Causality is #3.0f#s complete.", done, pc), infofile)); + + endwhile # done!=old_done + + # Set causality of a C or I which is not already set + [name,prefered] = getdynamic(ABG.subsystems) + if prefered==0 + ci_index=0; + else + disp("Set causality of a C or I which is not already set") + eval(["ci_bond_index = ABG.subsystems.",name,".connections;"]); # Get bonds + ci_direction = sign(ci_bond_index); + ci_bond_index = abs(ci_bond_index) + ABG.bonds(ci_bond_index,1:2) = prefered*ci_direction'*[1 1] + eval(["ABG.subsystems.",name,".status=0"]); #set status of the C or I + endif + endwhile # ( ci_index>0) + endif # struct_contains(CBG,field(i,:)); + endfor +# if n_ports>0 +# status(1:n_ports) = zeros(n_ports,1); # Port status not relevant +# endif; + + # Print final causality + # final_done = (sum(status==zeros(n_components,1))/n_components)*100; + + if at_top_level + mtt_info(sprintf("Final causality of %s is %3.0f%s complete.", ... + full_name, done, pc), infofile); + + if done<100 + mtt_error(sprintf("Unable to complete causality"),errorfile); + end; + + + # List overcausal bonds + # [over_causal_bonds,n] = getindex(status,1); + # if n>0 + # for i=over_causal_bonds' + # eval([ "[comp_type,name] = ", system_type, "_cmp(i);" ]); + # mtt_info(sprintf("Component #s (#s) is overcausal", name, subsystem.type), ... + # infofile); + # end; + # end; + + # List undercausal bonds + # [under_causal_bonds,n] = getindex(status,-1); + # if n>0 + # for i=under_causal_bonds' + # eval([ "[comp_type,name] = ", system_type, "_cmp(i);" ]); + # mtt_info(sprintf("Component #s (#s) is undercausal", name, subsystem.type), ... + # infofile); + # end; + # end; + + # List over and undercausal bonds and set status + + endif + + + disp(["Writing ", full_name]); + write_cbg(full_name,system_type,ABG); + + # Return the port bonds - arrow orientated causality - and the direction + status=0; + if !at_top_level # Not at top level + port_bonds = ABG.bonds(port_bond_index,:); # Return port bonds + for [subsystem,name] = ABG.subsystems + if subsystem.status==-1 # Under causal + status=-1; + mtt_info(sprintf("Component %s (%s) is undercausal", name, subsystem.type), ... + infofile); + elseif subsystem.status==1; # Over causal + status=-1; + mtt_info(sprintf("Component %s (%s) is overcausal", name, subsystem.type), ... + infofile); + endif; + endfor; # [subsystem,name] = ABG.subsystems + endif; # at top level + + status, port_bonds + disp("===================================="); + disp(["END: ", full_name, " (", fun_name, ")"]); + disp("===================================="); + +endfunction;