function [port_bonds, status] = abg2cbg(system_name, ...
    system_type, full_name, ...
    port_bonds,infofile)
% [bonds,status] = abg2cbg(system_name,infofile)
% 
%     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
%     %%%%% Model Transformation Tools %%%%%
%     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
% Matlab function  abg2cbg.m
% Acausal bond graph to causal bond graph: mfile format

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %% Version control history
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %% $Id$
% %% $Log$
% %% 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;

% Create the (full) system name
if length(full_name)==0
  full_name = system_name;
  system_type = system_name;
else
  full_name = [full_name, '_', system_name];
end;

fun_name = [system_type, '_abg']

% If no such function - then there is nothing to be done.
if exist(fun_name)~=2
  mtt_info(['m-file ', fun_name, ' does not exist'], infofile);
  bonds = [];
  status = [];
  return
end;

% Evaluate the system function to get the bonds
eval(['[bonds,components,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,columns] = size(components);
if n_components==0 % there is nothing to be done
  return
end;

% 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_info(sprintf('%1.0f port bonds incompatible with %1.0f ports', ...
      n_port_bonds, n_ports), infofile);
else % Copy the port bonds
  for i = 1:n_ports
    bonds(i,:) = port_bonds(i,:);
  end;
end;

% Set initial status
status = -ones(n_components,1);
total = 2*n_bonds;
done = sum(sum(abs(bonds)))/total*100;
% $$$ mtt_info(sprintf('Initial causality is %3.0f%s complete.', done, pc), infofile);

% Set the causality of the ports
old_done = inf;

while done~=old_done
  disp(sprintf('Causality is %3.0f%s complete.', done, pc));
  old_done = done;
  
  for i = 1:n_components
    comp = nozeros(components(i,:));
    bond_list = abs(comp);
    direction = sign(comp)'*[1 1];
    % Convert from arrow orientated to component orientated causality
    comp_bonds = bonds(bond_list,:).*direction;
    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 cuasality procedure name
    cause_name = [comp_type, '_cause'];
    
    % Invoke  the appropriate causality procedure
    if exist(cause_name)~=2 % Try a compound component
      disp('------------PUSH-----------------');
      [comp_bonds,s] = abg2cbg(name, comp_type, full_name, comp_bonds, ...
	  infofile);
      status(i)=max(abs(s));
      disp('------------POP-----------------');
    else % its a simple component
      eval([ '[comp_bonds,status(i)] = ', cause_name, '(comp_bonds);' ]);
    end;
    
    % Update the full bonds list
    % and convert from component orientated to arrow orientated causality
    bonds(bond_list,:) = comp_bonds.*direction; 
  end;


  done = sum(sum(abs(bonds)))/total*100;
  %  mtt_info(sprintf('Causality is %3.0f%s complete.', done, pc), infofile);
  
end;


final_done =  (sum(status==zeros(n_components,1))/n_components)*100;;

mtt_info(sprintf('Final causality is %3.0f%s complete.', final_done, pc),
infofile);

% 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;

file_name = [full_name, '_', system_type]
write_cbg(file_name,bonds,status);

% Return the port bonds
for i = 1:n_ports
  port_bonds(i,:) = bonds(i,:);
end;

disp('----------------------');





