Index: mttroot/mtt/bin/trans/m/abg2cbg.m ================================================================== --- mttroot/mtt/bin/trans/m/abg2cbg.m +++ mttroot/mtt/bin/trans/m/abg2cbg.m @@ -2,450 +2,477 @@ port_bonds, port_bond_direction, port_status, typefile, infofile, errorfile) -% abg2cbg - acausal to causal bg conversion -% -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% %%%%% Model Transformation Tools %%%%% -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% Matlab function abg2cbg.m -% Acausal bond graph to causal bond graph: mfile format -% [bonds,status] = abg2cbg(system_name, system_type, full_name, port_bonds, infofile) - -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% %% Version control history -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% %% $Id$ -% %% $Log$ -% %% Revision 1.33 1998/07/29 13:36:37 peterg -% %% Don't set port status if there aren't any ports. -% %% -% %% Revision 1.32 1998/07/28 19:06:11 peterg -% %% *** empty log message *** -% %% -% %% Revision 1.31 1998/07/28 13:15:10 peterg -% %% Vector SS ports included. -% %% -% %% Revision 1.30 1998/07/27 20:29:49 peterg -% %% Had another go at causality .... -% %% 1. Impose external causality onto all port bonds -% %% 2. Set C_cause.m so that it DOESN'T set causality -% %% -- I_cause is already ok ! -% %% -% %% Revision 1.29 1998/07/10 09:01:42 peterg -% %% Added error + info file in new form -% %% -% %% Revision 1.28 1998/07/08 09:23:42 peterg -% %% Undid the previous change -- needs more thought. -% %% -% %% Revision 1.27 1998/07/03 19:03:31 peterg -% %% Always override the causality of port bonds! -% %% -% %% Revision 1.26 1998/06/27 13:24:04 peterg -% %% Causality now set correctly for: -% %% multi-port C and I -% %% C and I with arrows pointing in -% %% -% %% Revision 1.25 1998/06/25 18:53:30 peterg -% %% Actually, the previous comment was optimistic. -% %% The port causalities on a compound are now forced to be the same as -% %% that specified by a a _cuase.m file (if it exists) -% %% -% %% Revision 1.24 1998/06/25 17:45:03 peterg -% %% No change -- but checked that explicit causality works! -% %% -% %% Revision 1.23 1998/04/04 10:46:37 peterg -% %% Coerces port bonds to have smae direction as the imposing bonds -% %% _cbg now generates the (coerced) components as welll as the (coerced) -% %% causality. -% %% -% %% Revision 1.22 1997/08/19 10:21:09 peterg -% %% Only copy port cuaslity info if not already set within the -% %% subsystem. I thought I'd done this already .... -% %% -% %% Revision 1.21 1997/08/18 16:25:25 peterg -% %% Minor bug fixes -% %% -% %% Revision 1.20 1997/08/18 12:45:24 peterg -% %% Replaced: comp_bonds = bonds(bond_list,:) -% %% by: for kk = 1:n_comp -% %% comp_bonds(kk,:) = bonds(comp(kk),:); -% %% end; -% %% -% %% to avoid an octave bug in 1.92. -% %% -% %% Revision 1.19 1997/08/18 11:23:59 peterg -% %% Main component loop now misses out the ports (SS:[]) -- the causality -% %% is merely passed through these components. -% %% -% %% Revision 1.18 1997/08/08 08:11:04 peterg -% %% Suppress compoment trace. -% %% -% %% Revision 1.17 1997/08/07 16:10:13 peterg -% %% Move the if status .. to the beginning of the main loop. -% %% -% %% Revision 1.16 1997/08/04 13:11:19 peterg -% %% Only change to component-orientated causality for simple components -% %% NOT for compound components. -% %% -% %% Revision 1.15 1997/01/05 12:25:59 peterg -% %% More informative message about port bonds incompatible with ports -% %% -% %% Revision 1.14 1996/12/31 16:20:42 peterg -% %% Just write causality information at top level -- it gets a bit -% %% voluminous if written at deeper levels. -% %% -% %% Revision 1.13 1996/12/31 11:49:09 peterg -% %% Don't copy port bond causality if already set -- allows subsystem -% %% causality to be preset directely on named SS. -% %% -% %% Revision 1.12 1996/12/31 11:42:36 peterg -% %% *** empty log message *** -% %% -% %% Revision 1.11 1996/12/07 17:10:48 peterg -% %% Allows port SS at top level - ie takes it to be an ardianry SS at top -% %% level. -% %% -% %% Revision 1.10 1996/12/04 21:48:55 peterg -% %% Compares full-name with empty string (instead of testing for zero -% %% length. -% %% -% %% Revision 1.9 1996/08/30 12:55:40 peter -% %% More heirachical stuff added. -% %% -% %% Revision 1.8 1996/08/26 10:04:25 peterg -% %% Fixed error due to a line wrap. -% %% -% %%Revision 1.7 1996/08/16 12:58:58 peter -% %% Now does preferred causality of I and C. -% %% Revision 1.6 1996/08/09 08:27:29 peter -% %% Added a few deguging lines -% %% -% %% Revision 1.5 1996/08/08 18:06:18 peter -% %% Unified file naming scheme -% %% -% %% Revision 1.4 1996/08/08 08:30:06 peter -% %% The cbg filename contains the system name - this makes things easier -% %% when setting up the m to fig translation and m to ese translation -% %% -% %% Revision 1.3 1996/08/05 18:53:21 peter -% %% Fixed bug passing causality from subsystems. -% %% -% %% Revision 1.2 1996/08/05 15:41:41 peter -% %% Now recursively does causality on subsystems. -% %% -% %% Revision 1.1 1996/08/04 17:55:55 peter -% %% Initial revision -% %% -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -pc = '%'; -if nargin<1 - system_name = 'no_name'; -end; - -if nargin<4 - port_bonds = []; -end; - -if nargin<5 - infofile = 'stdout'; -end; - -% Are we at the top level of the heirarchy? -at_top_level = strcmp(full_name, ''); - -% 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); -end; - -% Create the (full) system name -if at_top_level - full_name = system_name; - system_type = system_name; -else - full_name = [full_name, '_', system_name]; -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); - -fun_name = [system_type, '_abg']; - -disp('===================================='); -disp(['BEGIN: ', full_name, ' (', fun_name, ')']); -disp('===================================='); - -% If no such function - then there is nothing to be done. -if exist(fun_name)~=2 - mtt_error(['m-file ', fun_name, ' does not exist'], errorfile); - bonds = []; - status = []; - return -end; - -% Evaluate the system function to get the bonds and number of ports -eval(['[bonds,components,n_ports,N_ports]=', fun_name, ';']); - -% Find number of bonds -[n_bonds,columns] = size(bonds); -if (columns ~= 2)&(n_bonds>0) - error('Incorrect bonds matrix: must have 2 columns'); -end; - - -% Find number of components -[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 - - - -% Set initial status -status = -ones(n_components,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); - - 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); - end; - end; -# status(1:N_ports) = port_status; - 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; - -while( ci_index>0) - ci_index - old_done = inf; - % Inner loop propagates causality - while done~=old_done - % disp(sprintf('Causality is %3.0f%s complete.', done, pc)); - old_done = done; -done,ci_index - for i = n_ports+1:n_components % Miss out the ports - if status(i) ~= 0 % only do this if causality not yet complete - - % Get the bonds on this component - comp = nozeros(components(i,:)); - 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(comp_type,'0') - comp_type = 'zero'; - end; - if strcmp(comp_type,'1') - comp_type = 'one'; - end; - - % Component causality procedure name - cause_name = [comp_type, '_cause']; - - % Component equation procedure name - eqn_name = [comp_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, comp_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);' ]); - - % 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 - [ci_index,prefered] = getdynamic(status,system_type) - if ci_index>0 - disp('Set causality of a C or I which is not already set') - ci_bond_index = nozeros(components(ci_index,:)); # 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]; - end; - -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, final_done, pc), infofile); - - if final_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, comp_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, comp_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'); -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('===================================='); +# abg2cbg - acausal to causal bg conversion +# +# ###################################### +# ##### Model Transformation Tools ##### +# ###################################### +# +# Matlab function abg2cbg.m +# Acausal bond graph to causal bond graph: mfile format +# [bonds,status] = abg2cbg(system_name, system_type, full_name, port_bonds, infofile) + +# ############################################################### +# ## Version control history +# ############################################################### +# ## $Id$ +# ## $Log$ +# ## 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. +# ## +# ## Revision 1.32 1998/07/28 19:06:11 peterg +# ## *** empty log message *** +# ## +# ## Revision 1.31 1998/07/28 13:15:10 peterg +# ## Vector SS ports included. +# ## +# ## Revision 1.30 1998/07/27 20:29:49 peterg +# ## Had another go at causality .... +# ## 1. Impose external causality onto all port bonds +# ## 2. Set C_cause.m so that it DOESN'T set causality +# ## -- I_cause is already ok ! +# ## +# ## Revision 1.29 1998/07/10 09:01:42 peterg +# ## Added error + info file in new form +# ## +# ## Revision 1.28 1998/07/08 09:23:42 peterg +# ## Undid the previous change -- needs more thought. +# ## +# ## Revision 1.27 1998/07/03 19:03:31 peterg +# ## Always override the causality of port bonds! +# ## +# ## Revision 1.26 1998/06/27 13:24:04 peterg +# ## Causality now set correctly for: +# ## multi-port C and I +# ## C and I with arrows pointing in +# ## +# ## Revision 1.25 1998/06/25 18:53:30 peterg +# ## Actually, the previous comment was optimistic. +# ## The port causalities on a compound are now forced to be the same as +# ## that specified by a a _cuase.m file (if it exists) +# ## +# ## Revision 1.24 1998/06/25 17:45:03 peterg +# ## No change -- but checked that explicit causality works! +# ## +# ## Revision 1.23 1998/04/04 10:46:37 peterg +# ## Coerces port bonds to have smae direction as the imposing bonds +# ## _cbg now generates the (coerced) components as welll as the (coerced) +# ## causality. +# ## +# ## Revision 1.22 1997/08/19 10:21:09 peterg +# ## Only copy port cuaslity info if not already set within the +# ## subsystem. I thought I'd done this already .... +# ## +# ## Revision 1.21 1997/08/18 16:25:25 peterg +# ## Minor bug fixes +# ## +# ## Revision 1.20 1997/08/18 12:45:24 peterg +# ## Replaced: comp_bonds = bonds(bond_list,:) +# ## by: for kk = 1:n_comp +# ## comp_bonds(kk,:) = bonds(comp(kk),:); +# ## end; +# ## +# ## to avoid an octave bug in 1.92. +# ## +# ## Revision 1.19 1997/08/18 11:23:59 peterg +# ## Main component loop now misses out the ports (SS:[]) -- the causality +# ## is merely passed through these components. +# ## +# ## Revision 1.18 1997/08/08 08:11:04 peterg +# ## Suppress compoment trace. +# ## +# ## Revision 1.17 1997/08/07 16:10:13 peterg +# ## Move the if status .. to the beginning of the main loop. +# ## +# ## Revision 1.16 1997/08/04 13:11:19 peterg +# ## Only change to component-orientated causality for simple components +# ## NOT for compound components. +# ## +# ## Revision 1.15 1997/01/05 12:25:59 peterg +# ## More informative message about port bonds incompatible with ports +# ## +# ## Revision 1.14 1996/12/31 16:20:42 peterg +# ## Just write causality information at top level -- it gets a bit +# ## voluminous if written at deeper levels. +# ## +# ## Revision 1.13 1996/12/31 11:49:09 peterg +# ## Don't copy port bond causality if already set -- allows subsystem +# ## causality to be preset directely on named SS. +# ## +# ## Revision 1.12 1996/12/31 11:42:36 peterg +# ## *** empty log message *** +# ## +# ## Revision 1.11 1996/12/07 17:10:48 peterg +# ## Allows port SS at top level - ie takes it to be an ardianry SS at top +# ## level. +# ## +# ## Revision 1.10 1996/12/04 21:48:55 peterg +# ## Compares full-name with empty string (instead of testing for zero +# ## length. +# ## +# ## Revision 1.9 1996/08/30 12:55:40 peter +# ## More heirachical stuff added. +# ## +# ## Revision 1.8 1996/08/26 10:04:25 peterg +# ## Fixed error due to a line wrap. +# ## +# ##Revision 1.7 1996/08/16 12:58:58 peter +# ## Now does preferred causality of I and C. +# ## Revision 1.6 1996/08/09 08:27:29 peter +# ## Added a few deguging lines +# ## +# ## Revision 1.5 1996/08/08 18:06:18 peter +# ## Unified file naming scheme +# ## +# ## Revision 1.4 1996/08/08 08:30:06 peter +# ## The cbg filename contains the system name - this makes things easier +# ## when setting up the m to fig translation and m to ese translation +# ## +# ## Revision 1.3 1996/08/05 18:53:21 peter +# ## Fixed bug passing causality from subsystems. +# ## +# ## Revision 1.2 1996/08/05 15:41:41 peter +# ## Now recursively does causality on subsystems. +# ## +# ## Revision 1.1 1996/08/04 17:55:55 peter +# ## Initial revision +# ## +# ############################################################### + + pc = '%'; + if nargin<1 + system_name = 'no_name'; + end; + + if nargin<4 + port_bonds = []; + end; + + if nargin<5 + infofile = 'stdout'; + end; + +# Are we at the top level of the heirarchy? + at_top_level = strcmp(full_name, ''); + +# 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); + end; + +# Create the (full) system name + if at_top_level + full_name = system_name; + system_type = system_name; + else + full_name = [full_name, "_", system_name]; + 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); + + fun_name = [system_type, "_abg"]; + + disp("===================================="); + disp(["BEGIN: ", full_name, " (", fun_name, ")"]); + disp("===================================="); + +# If no such function - then there is nothing to be done. + if exist(fun_name)~=2 + mtt_error(["m-file ", fun_name, " does not exist"], errorfile); + bonds = []; + status = []; + return + 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 + return; # Nothing to do + else + [n_subsystems,junk] = size(struct_elements(ABG.subsystems)); + endif + + + + + [n_bonds,columns] = size(bonds);# Find number of bonds + if (columns ~= 2)&(n_bonds>0) + error("Incorrect bonds matrix: must have 2 columns"); + end; + + +## Find number of components +# [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 + + + +# Set initial status + 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); + + 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); + end; + end; +# status(1:N_ports) = port_status; + 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("===================================="); + + + + +