function model = mttCreateCausalBondgraph(model)
model.representation = 'cbg' ;
model = incorporate_interface_definitions(model) ;
model = establish_abg_dependencies(model) ;
model = create_object_hierarchy(model) ;
model = assign_sympar_values(model) ;
model = complete_causal_assignment(model) ;
model = complete_domain_assignment(model) ;
model = overwrite_implicit_domains(model) ;
function model = incorporate_interface_definitions(model)
mttNotify('...incorporating "cr" definitions') ;
mttWriteNewLine ;
mttNotify([' ...processing ',model.source]) ;
mttWriteNewLine ;
objects = mttGetFieldNames(model,'obj') ;
for i = 1:length(objects)
object_name = objects{i} ;
object = getfield(model,'obj',object_name) ;
if ~mttIsFoundationClass(object.class)
mttAssert(xor(isempty(object.abg),isempty(object.cr)),...
['"',object_name,'" must exclusively have a "cr" or an "abg" representation']) ;
end
if isempty(object.cr)
object = mttDeleteField(object,'cr_item') ;
model = setfield(model,'obj',object_name,object) ;
else
model = mttEmbedInterfaceDefinition(model,object_name) ;
end
end
for i = 1:mttGetFieldLength(model,'abg')
component_type = mttDetachText(model.abg(i).source,'/') ;
mttNotify([' ...processing "#',num2str(i),':',component_type,'" ',model.abg(i).source]) ;
mttWriteNewLine ;
objects = mttGetFieldNames(model.abg(i),'obj') ;
for j = 1:length(objects)
object_name = objects{j} ;
object = getfield(model,'abg',{i},'obj',object_name) ;
if ~mttIsFoundationClass(object.class)
mttAssert(xor(isempty(object.abg),isempty(object.cr)),...
['abg[',num2str(i),']: "',object_name,'" must exclusively have a "cr" or an "abg" representation']) ;
end
if isempty(object.cr)
object = mttDeleteField(object,'cr_item') ;
model = setfield(model,'abg',{i},'obj',object_name,object) ;
else
model.abg(i) = mttEmbedInterfaceDefinition(model.abg(i),object_name,model) ;
end
end
model.abg(i).invokes = [] ;
model.abg(i).invoked_by = [] ;
end
model = mttDeleteField(model,'cr') ;
function model = establish_abg_dependencies(model)
mttNotify('...establishing "abg" dependencies') ;
mttWriteNewLine ;
for i = 1:mttGetFieldLength(model,'abg')
objects = mttGetFieldNames(model.abg(i),'obj') ;
for j = 1:length(objects)
object_name = objects{j} ;
object = getfield(model.abg(i).obj,object_name) ;
if isempty(object.cr) %... still within object hierarchy
if ~mttIsFoundationClass(object.class)
existing_dependencies = model.abg(i).invokes ;
if isempty(existing_dependencies)
new_dependency = 1 ;
else
new_dependency = isempty(find(existing_dependencies==object.abg)) ;
end
if new_dependency
model.abg(i).invokes = [existing_dependencies,object.abg] ;
end
existing_dependencies = model.abg(object.abg).invoked_by ;
if isempty(existing_dependencies)
new_dependency = 1 ;
else
new_dependency = isempty(find(existing_dependencies==i)) ;
end
if new_dependency
model.abg(object.abg).invoked_by = [existing_dependencies,i] ;
end
end
end
end
end
model.invokes = [] ;
objects = mttGetFieldNames(model,'obj') ;
for j = 1:length(objects)
object_name = objects{j} ;
object = getfield(model.obj,object_name) ;
if ~isempty(object.abg)
if ~mttIsFoundationClass(object.class)
existing_dependencies = model.invokes ;
if isempty(existing_dependencies)
new_dependency = 1 ;
else
new_dependency = isempty(find(existing_dependencies==object.abg)) ;
end
if new_dependency
model.invokes = [existing_dependencies,object.abg] ;
end
end
end
end
function model = create_object_hierarchy(model) ;
mttNotify('...creating object hierarchy') ;
mttWriteNewLine ;
top_level_model = mttDetachText(model.source,'/') ;
if isfield(model,'abg')
is_embedded = zeros(1,length(model.abg)) ;
embedding = 1 ;
else
embedding = 0 ;
end
component = 0 ;
embedding = isfield(model,'abg') ;
while embedding
component = 1 + mod(component,length(model.abg)) ;
if ~is_embedded(component)
if isempty(model.abg(component).invokes)
number_of_systems = length(model.abg(component).invoked_by) ;
for n = 1:number_of_systems
system = model.abg(component).invoked_by(n) ;
component_type = mttDetachText(model.abg(component).source,'/') ;
system_type = mttDetachText(model.abg(system).source,'/') ;
mttNotify([' ...embedding "#',num2str(component),':',component_type,...
'" definition within "#',num2str(system),':',system_type,'" objects']) ;
mttWriteNewLine ;
model = mttEmbedAcausalBondgraph(model,component,system) ;
end
model.abg(component).invoked_by = [] ;
if ~isempty(find(model.invokes==component))
component_type = mttDetachText(model.abg(component).source,'/') ;
mttNotify([' ...embedding "#',num2str(component),':',component_type,...
'" definition within "',top_level_model,'"']) ;
mttWriteNewLine ;
model = mttEmbedAcausalBondgraph(model,component) ;
end
is_embedded(component) = 1 ;
end
end
embedding = any(~is_embedded) ;
end
model = mttDeleteField(model,'abg') ;
model = mttDeleteField(model,'invokes') ;
function model = assign_sympar_values(model)
mttNotify('...assigning "sympar" values') ;
mttWriteNewLine ;
model_name = mttDetachText(model.source,'/') ;
current_branch = model_name ;
sympars = model.sympar ;
defaults = model.sympar_default ;
objects = mttGetFieldNames(model,'obj') ;
for i = 1:length(objects)
object_name = objects{i} ;
object = getfield(model,'obj',object_name) ;
if ~mttIsPassiveClass(object.class)
for j = 1:length(object.parameter)
object_parameter = object.parameter{j} ;
if ischar(object_parameter)
index = strmatch(object_parameter,sympars,'exact') ;
new_parameter = 0 ;
if isempty(index)
new_parameter = 1 ;
else
default_value = defaults{index} ;
if isempty(default_value)
new_parameter = 1 ;
else
object.parameter{j} = default_value ;
end
end
if new_parameter
object.parameter{j} = [current_branch,'___',object_parameter] ;
end
end
end
branch = [model_name,'__',object_name] ;
object = assign_object_sympar_values(object,branch) ;
model = setfield(model,'obj',object_name,object) ;
end
end
function model = assign_object_sympar_values(model,branch)
current_branch = branch ;
sympars = model.sympar ;
parameters = model.parameter ;
if ~isempty(model.abg)
objects = mttGetFieldNames(model,'obj') ;
for i = 1:length(objects)
object_name = objects{i} ;
object = getfield(model,'obj',object_name) ;
if ~mttIsPassiveClass(object.class)
for j = 1:length(object.parameter)
object_parameter = object.parameter{j} ;
if ischar(object_parameter)
index = strmatch(object_parameter,sympars,'exact') ;
if isempty(index)
object.parameter{j} = [current_branch,'___',object_parameter] ;
else
object.parameter{j} = parameters{index} ;
end
end
end
branch = [current_branch,'__',object_name] ;
object = assign_object_sympar_values(object,branch) ;
model = setfield(model,'obj',object_name,object) ;
end
end
elseif ~isempty(model.cr)
model.cr.parameter = model.parameter ;
end
function model = complete_causal_assignment(model)
mttWriteNewLine ;
mttNotify('...summarising model content') ;
mttWriteNewLine ;
model = mttCountObjects(model) ;
mttNotifyNumberOfObjects(model) ;
mttWriteNewLine ;
model = mttDeleteField(model,'count') ;
model = mttMeasureCausalCompletion(model) ;
mttNotifyNumberOfBonds(model) ;
mttWriteNewLine ;
mttWriteNewLine ;
mttNotify('...analysing predefined causality') ;
mttWriteNewLine ;
mttNotifyCausalCompletion(model) ;
mttWriteNewLine ;
if model.causal_completion.is_causal
mttNotify('...applying CR constraints') ;
mttWriteNewLine ;
model = incorporate_cr_rules(model,'assert') ;
else
mttNotify('...completing causality') ;
mttWriteNewLine ;
iterations = 0 ;
propagating = 1 ;
while propagating
iterations = iterations + 1 ;
previous_causal_completion = model.causal_completion ;
model = mttApplyInterfaceCausality(model,'assert') ;
model = mttPropagateCausality(model) ;
model = mttApplyInterfaceCausality(model,'prefer') ;
model = mttPropagateCausality(model) ;
model = mttMeasureCausalCompletion(model) ;
is_stable = mttCompareCausalCompletion(model.causal_completion,previous_causal_completion) ;
propagating = (~is_stable) ;
if propagating
mttNotify(['...iteration ',num2str(iterations)]) ;
mttWriteNewLine ;
mttNotifyCausalCompletion(model) ;
end
propagating = propagating & (~model.causal_completion.is_causal) ;
end
end
if ~model.causal_completion.is_causal
mttWriteNewLine ;
mttNotify('...causality not complete') ;
mttWriteNewLine ;
mttWriteNewLine ;
mttIdentifyUndercausalBonds(model) ;
end
model = mttDeleteField(model,'causal_completion') ;
function model = complete_domain_assignment(model)
mttWriteNewLine ;
mttNotify('...allocating domain definitions') ;
mttWriteNewLine ;
model = mttMeasureDomainCompletion(model) ;
iterations = 0 ;
propagating = 1 ;
while propagating
iterations = iterations + 1 ;
previous_domain_completion = model.domain_completion ;
model = mttApplyInterfaceDomains(model) ;
model = mttPropagateDomains(model) ;
model = mttMeasureDomainCompletion(model) ;
is_stable = mttCompareDomainCompletion(model.domain_completion,previous_domain_completion) ;
propagating = (~is_stable) ;
if propagating
mttNotify(['...iteration ',num2str(iterations)]) ;
mttWriteNewLine ;
mttNotifyDomainCompletion(model) ;
end
propagating = propagating & (~model.domain_completion.is_done) ;
end
model = mttDeleteField(model,'domain_completion') ;
function model = overwrite_implicit_domains(model)
mttWriteNewLine ;
mttNotify('...overwriting implicit domain definitions') ;
mttWriteNewLine ;
model = mttOverwriteImplicitDomains(model) ;
function model = mttOverwriteImplicitDomains(root,model,env)
is_root_model = nargin==1 ;
if is_root_model
model = root ;
env = root.env ;
end
objects = mttGetFieldNames(model,'obj') ;
for i = 1:length(objects)
object_name = objects{i} ;
object = getfield(model,'obj',object_name) ;
if ~isempty(object.abg)
object = mttOverwriteImplicitDomains(model,object,env) ;
end
if ~isempty(object.cr)
interface_ports = mttGetFieldNames(object.cr.interface,'port') ;
for j = 1:length(interface_ports)
port_name = interface_ports{j} ;
port = getfield(object.cr.interface,'port',port_name) ;
if isempty(port.domain)
if isempty(port.in)
bond_number = port.out ;
else
bond_number = port.in ;
end
actual_domain = model.bond(bond_number).domain ;
actual_domain_item = model.bond(bond_number).domain_item ;
port.domain = actual_domain ;
port.domain_item = actual_domain_item ;
object.cr.interface = setfield(object.cr.interface,'port',port_name,port) ;
number_of_operators = mttGetFieldLength(object.cr,'operator') ;
for op_counter = 1:number_of_operators
operator = object.cr.operator(op_counter) ;
matching_links = strmatch(port_name,{operator.link.name},'exact') ;
number_of_equations = mttGetFieldLength(operator,'equation') ;
for eq_counter = 1:number_of_equations
equation = operator.equation(eq_counter) ;
% if isempty(equation.domain)
number_of_chunks = mttGetFieldLength(equation,'chunk') ;
for chunk_counter = 1:number_of_chunks
chunk = equation.chunk{chunk_counter} ;
if iscell(chunk)
if strcmp(chunk{1},'link')
link = chunk{2} ;
if any(link==matching_links)
covar = chunk{3} ;
chunk{3} = ['generic___',covar] ;
end
end
equation.chunk{chunk_counter} = chunk ;
end
end
operator.equation(eq_counter) = equation ;
% end
end
object.cr.operator(op_counter) = operator ;
end
end
end
end
model = setfield(model,'obj',object_name,object) ;
end