mttCreateElementaryEquations.m 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. function model = mttCreateElementaryEquations(model,sorter_on)
  2. model.representation = 'ese' ;
  3. [model,ese,namelist] = specify_equations(model) ;
  4. if sorter_on
  5. [sse,counter] = sort_equations(ese,model,namelist) ;
  6. else
  7. sse = ese ;
  8. counter = 0 ;
  9. end
  10. model.equation = sse ;
  11. model.sorted_equations = counter ;
  12. model.namelist = namelist ;
  13. function [model,ese,namelist] = specify_equations(model,branch,root_namelist)
  14. is_root_model = (nargin==1) ;
  15. if is_root_model
  16. mttNotify('...specifying equations') ;
  17. mttWriteNewLine ;
  18. branch = mttDetachText(model.source,'/') ;
  19. name_counter = 1 ;
  20. namelist(name_counter).var = '0' ;
  21. namelist(name_counter).domain = [] ;
  22. namelist(name_counter).domain_item = [] ;
  23. else
  24. namelist = root_namelist ;
  25. name_counter = length(namelist) ;
  26. end
  27. mttNotify([' ...processing ',branch]) ;
  28. mttWriteNewLine ;
  29. objects = mttGetFieldNames(model,'obj') ;
  30. line = 0 ;
  31. for n = 1:length(objects)
  32. object_name = objects{n} ;
  33. object = getfield(model,'obj',object_name) ;
  34. here = [branch,':',object_name] ;
  35. switch object.class
  36. case {'SS','Se','Sf','De','Df'},
  37. for j = 1:mttGetFieldLength(object,'interface')
  38. flow_equation = [] ;
  39. effort_equation = [] ;
  40. terminal = [branch,'__',object_name] ;
  41. inbond = object.interface(j).in ;
  42. outbond = object.interface(j).out ;
  43. if ~isempty(inbond)
  44. bond = model.bond(inbond) ;
  45. [specified_domain,specified_domain_item] = mttGetBondDomain(model,inbond) ;
  46. new_name = 0 ;
  47. line = line + 1 ;
  48. if bond.flow
  49. if strcmp(object.class,'De')
  50. ese(line) = specify_ese(branch,[2*inbond],branch,{1},[]) ;
  51. else
  52. ese(line) = specify_ese(branch,[2*inbond],branch,{name_counter+1},[]) ;
  53. new_name = 1 ;
  54. end
  55. else
  56. ese(line) = specify_ese(branch,{name_counter+1},branch,[2*inbond],[]) ;
  57. new_name = 1 ;
  58. end
  59. if new_name
  60. name_counter = name_counter + 1 ;
  61. namelist(name_counter).var = [terminal,'.flow'] ;
  62. namelist(name_counter).domain = specified_domain ;
  63. namelist(name_counter).domain_item = specified_domain_item ;
  64. end
  65. new_name = 0 ;
  66. line = line + 1 ;
  67. if bond.effort
  68. ese(line) = specify_ese(branch,{name_counter+1},branch,[2*inbond-1],[]) ;
  69. new_name = 1 ;
  70. else
  71. if strcmp(object.class,'Df')
  72. ese(line) = specify_ese(branch,[2*inbond-1],branch,{1},[]) ;
  73. else
  74. ese(line) = specify_ese(branch,[2*inbond-1],branch,{name_counter+1},[]) ;
  75. new_name = 1 ;
  76. end
  77. end
  78. if new_name
  79. name_counter = name_counter + 1 ;
  80. namelist(name_counter).var = [terminal,'.effort'] ;
  81. namelist(name_counter).domain = specified_domain ;
  82. namelist(name_counter).domain_item = specified_domain_item ;
  83. end
  84. end
  85. if ~isempty(outbond)
  86. bond = model.bond(outbond) ;
  87. [specified_domain,specified_domain_item] = mttGetBondDomain(model,outbond) ;
  88. new_name = 0 ;
  89. if bond.flow
  90. if ~strcmp(object.class,'Se')
  91. line = line + 1 ;
  92. ese(line) = specify_ese(branch,{name_counter+1},branch,[2*outbond],[]) ;
  93. new_name = 1 ;
  94. end
  95. else
  96. line = line + 1 ;
  97. ese(line) = specify_ese(branch,[2*outbond],branch,{name_counter+1},[]) ;
  98. new_name = 1 ;
  99. end
  100. if new_name
  101. name_counter = name_counter + 1 ;
  102. namelist(name_counter).var = [terminal,'.flow'] ;
  103. namelist(name_counter).domain = specified_domain ;
  104. namelist(name_counter).domain_item = specified_domain_item ;
  105. end
  106. new_name = 0 ;
  107. if bond.effort
  108. line = line + 1 ;
  109. ese(line) = specify_ese(branch,[2*outbond-1],branch,{name_counter+1},[]) ;
  110. new_name = 1 ;
  111. else
  112. if ~strcmp(object.class,'Sf')
  113. line = line + 1 ;
  114. ese(line) = specify_ese(branch,{name_counter+1},branch,[2*outbond-1],[]) ;
  115. new_name = 1 ;
  116. end
  117. end
  118. if new_name
  119. name_counter = name_counter + 1 ;
  120. namelist(name_counter).var = [terminal,'.effort'] ;
  121. namelist(name_counter).domain = specified_domain ;
  122. namelist(name_counter).domain_item = specified_domain_item ;
  123. end
  124. end
  125. end
  126. case '0',
  127. imposed_effort = [] ;
  128. resultant_flow = [] ;
  129. for i = 1:mttGetFieldLength(object,'interface')
  130. inbond = object.interface(i).in ;
  131. outbond = object.interface(i).out ;
  132. if isempty(inbond)
  133. bond_number(i) = outbond ;
  134. orientation(i) = 0 ;
  135. else
  136. bond_number(i) = inbond ;
  137. orientation(i) = 1 ;
  138. end
  139. [effort,flow] = mttGetBondCausality(model,bond_number(i)) ;
  140. if effort==orientation(i)
  141. imposed_effort = 2*bond_number(i)-1 ;
  142. end
  143. if flow==orientation(i)
  144. resultant_flow = 2*bond_number(i) ;
  145. resultant_orientation = orientation(i) ;
  146. end
  147. end
  148. for i = 1:mttGetFieldLength(object,'interface')
  149. effort = 2*bond_number(i)-1 ;
  150. if effort~=imposed_effort
  151. derived_effort = effort ;
  152. line = line + 1 ;
  153. ese(line) = specify_ese(branch,derived_effort,branch,imposed_effort,[]) ;
  154. end
  155. end
  156. flow_summation = [] ;
  157. for i = 1:mttGetFieldLength(object,'interface')
  158. flow = 2*bond_number(i) ;
  159. if flow~=resultant_flow
  160. impinging_flow = flow ;
  161. if orientation(i)
  162. if resultant_orientation
  163. flow_summation = [ flow_summation, -impinging_flow ] ;
  164. else
  165. flow_summation = [ flow_summation, impinging_flow ] ;
  166. end
  167. else
  168. if resultant_orientation
  169. flow_summation = [ flow_summation, impinging_flow ] ;
  170. else
  171. flow_summation = [ flow_summation, -impinging_flow ] ;
  172. end
  173. end
  174. end
  175. end
  176. line = line + 1 ;
  177. ese(line) = specify_ese(branch,resultant_flow,branch,flow_summation,[]) ;
  178. case '1',
  179. imposed_flow = [] ;
  180. resultant_effort = [] ;
  181. for i = 1:mttGetFieldLength(object,'interface')
  182. inbond = object.interface(i).in ;
  183. outbond = object.interface(i).out ;
  184. if isempty(inbond)
  185. bond_number(i) = outbond ;
  186. orientation(i) = 0 ;
  187. else
  188. bond_number(i) = inbond ;
  189. orientation(i) = 1 ;
  190. end
  191. [effort,flow] = mttGetBondCausality(model,bond_number(i)) ;
  192. if flow~=orientation(i)
  193. imposed_flow = 2*bond_number(i) ;
  194. end
  195. if effort~=orientation(i)
  196. resultant_effort = 2*bond_number(i)-1 ;
  197. resultant_orientation = orientation(i) ;
  198. end
  199. end
  200. for i = 1:mttGetFieldLength(object,'interface')
  201. flow = 2*bond_number(i) ;
  202. if flow~=imposed_flow
  203. derived_flow = flow ;
  204. line = line + 1 ;
  205. ese(line) = specify_ese(branch,derived_flow,branch,imposed_flow,[]) ;
  206. end
  207. end
  208. effort_summation = [] ;
  209. for i = 1:mttGetFieldLength(object,'interface')
  210. effort = 2*bond_number(i)-1 ;
  211. if effort~=resultant_effort
  212. impinging_effort = effort ;
  213. if orientation(i)
  214. if resultant_orientation
  215. effort_summation = [ effort_summation, -impinging_effort ] ;
  216. else
  217. effort_summation = [ effort_summation, impinging_effort ] ;
  218. end
  219. else
  220. if resultant_orientation
  221. effort_summation = [ effort_summation, impinging_effort ] ;
  222. else
  223. effort_summation = [ effort_summation, -impinging_effort ] ;
  224. end
  225. end
  226. end
  227. end
  228. line = line + 1 ;
  229. ese(line) = specify_ese(branch,resultant_effort,branch,effort_summation,[]) ;
  230. otherwise,
  231. if ~isempty(object.cr)
  232. interface = object.cr.interface ;
  233. port_names = mttGetFieldNames(interface,'port') ;
  234. number_of_ports = length(port_names) ;
  235. link_counter = 0 ;
  236. for i = 1:number_of_ports
  237. port_name = port_names{i} ;
  238. port = getfield(interface,'port',port_name) ;
  239. terminal = [branch,'__',object_name,'___',port_name] ;
  240. inbond = port.in ;
  241. outbond = port.out ;
  242. if ~isempty(inbond)
  243. bond = model.bond(inbond) ;
  244. [specified_domain,specified_domain_item] = mttGetBondDomain(model,inbond) ;
  245. name_counter = name_counter + 1 ;
  246. if port.is_flow_state
  247. namelist(name_counter).var = [terminal,'.flow_state'] ;
  248. else
  249. namelist(name_counter).var = [terminal,'.flow'] ;
  250. end
  251. namelist(name_counter).domain = specified_domain ;
  252. namelist(name_counter).domain_item = specified_domain_item ;
  253. line = line + 1 ;
  254. link_counter = link_counter + 1 ;
  255. if bond.flow
  256. ese(line) = specify_ese(branch,[2*inbond],branch,{name_counter},[]) ;
  257. link(link_counter) = create_link(0,0,1,port_name,port.is_flow_state) ;
  258. else
  259. ese(line) = specify_ese(branch,{name_counter},branch,[2*inbond],[]) ;
  260. link(link_counter) = create_link(1,0,1,port_name,port.is_flow_state) ;
  261. end
  262. name_counter = name_counter + 1 ;
  263. if port.is_effort_state
  264. namelist(name_counter).var = [terminal,'.effort_state'] ;
  265. else
  266. namelist(name_counter).var = [terminal,'.effort'] ;
  267. end
  268. namelist(name_counter).domain = specified_domain ;
  269. namelist(name_counter).domain_item = specified_domain_item ;
  270. line = line + 1 ;
  271. link_counter = link_counter + 1 ;
  272. if bond.effort
  273. ese(line) = specify_ese(branch,{name_counter},branch,[2*inbond-1],[]) ;
  274. link(link_counter) = create_link(1,1,0,port_name,port.is_effort_state) ;
  275. else
  276. ese(line) = specify_ese(branch,[2*inbond-1],branch,{name_counter},[]) ;
  277. link(link_counter) = create_link(0,1,0,port_name,port.is_effort_state) ;
  278. end
  279. end
  280. if ~isempty(outbond)
  281. bond = model.bond(outbond) ;
  282. [specified_domain,specified_domain_item] = mttGetBondDomain(model,outbond) ;
  283. name_counter = name_counter + 1 ;
  284. if port.is_flow_state
  285. namelist(name_counter).var = [terminal,'.flow_state'] ;
  286. else
  287. namelist(name_counter).var = [terminal,'.flow'] ;
  288. end
  289. namelist(name_counter).domain = specified_domain ;
  290. namelist(name_counter).domain_item = specified_domain_item ;
  291. line = line + 1 ;
  292. link_counter = link_counter + 1 ;
  293. if bond.flow
  294. ese(line) = specify_ese(branch,{name_counter},branch,[2*outbond],[]) ;
  295. link(link_counter) = create_link(1,0,1,port_name,port.is_flow_state) ;
  296. else
  297. ese(line) = specify_ese(branch,[2*outbond],branch,{name_counter},[]) ;
  298. link(link_counter) = create_link(0,0,1,port_name,port.is_flow_state) ;
  299. end
  300. name_counter = name_counter + 1 ;
  301. if port.is_effort_state
  302. namelist(name_counter).var = [terminal,'.effort_state'] ;
  303. else
  304. namelist(name_counter).var = [terminal,'.effort'] ;
  305. end
  306. namelist(name_counter).domain = specified_domain ;
  307. namelist(name_counter).domain_item = specified_domain_item ;
  308. line = line + 1 ;
  309. link_counter = link_counter + 1 ;
  310. if bond.effort
  311. ese(line) = specify_ese(branch,[2*outbond-1],branch,{name_counter},[]) ;
  312. link(link_counter) = create_link(0,1,0,port_name,port.is_effort_state) ;
  313. else
  314. ese(line) = specify_ese(branch,{name_counter},branch,[2*outbond-1],[]) ;
  315. link(link_counter) = create_link(1,1,0,port_name,port.is_effort_state) ;
  316. end
  317. end
  318. end
  319. input_mask = zeros(number_of_ports,1) ;
  320. output_mask = zeros(number_of_ports,1) ;
  321. number_of_links = link_counter ;
  322. linked = zeros(number_of_links,1) ;
  323. operators = object.cr.operator ;
  324. number_of_operators = length(operators) ;
  325. object.cr.used_operator = zeros(1,number_of_operators) ;
  326. op_counter = 0 ;
  327. matching = 1 ;
  328. while matching
  329. op_counter = op_counter + 1 ;
  330. operator = operators(op_counter) ;
  331. full_operator_name = [branch,'__',object_name,'___',operator.name] ;
  332. number_of_op_links = length(operator.link) ;
  333. op_linked = zeros(number_of_op_links,1) ;
  334. for j = 1:number_of_op_links
  335. k = 0 ;
  336. comparing = 1 ;
  337. while comparing
  338. k = k + 1 ;
  339. if compare_links(link(k),operator.link(j))
  340. op_linked(j) = k ;
  341. comparing = 0 ;
  342. end
  343. comparing = comparing & (k<number_of_links) ;
  344. end
  345. end
  346. input_counter = 0 ;
  347. output_counter = 0 ;
  348. input = [] ;
  349. output = [] ;
  350. if all(op_linked)
  351. object.cr.used_operator(op_counter) = 1 ;
  352. interface = object.cr.interface ;
  353. assigned_ports = mttGetFieldNames(operator,'assign') ;
  354. for j = 1:length(assigned_ports)
  355. port_name = assigned_ports{j} ;
  356. next = getfield(operator.assign,port_name) ;
  357. actual_port = getfield(interface,'port',port_name) ;
  358. if ~isempty(actual_port.assign)
  359. previous = actual_port.assign ;
  360. for k = 1:length(next.covar)
  361. covar = next.covar{k} ;
  362. index = strmatch(covar,previous.covar,'exact') ;
  363. if ~isempty(index)
  364. mttAssert(strcmp(next.state{k},previous.state{k}),...
  365. ['Conflicting state assignments for port "',port_name,'.',covar,'" in ',here]) ;
  366. else
  367. actual_port.assign.state{index} = next.state{k} ;
  368. end
  369. end
  370. else
  371. actual_port.assign = next ;
  372. end
  373. interface = setfield(interface,'port',port_name,actual_port) ;
  374. end
  375. % operator = mttDeleteField(operator,'assign') ;
  376. % object.cr.operator(op_counter) = operator ;
  377. object.cr.interface = interface ;
  378. model = setfield(model,'obj',object_name,object) ;
  379. for j = 1:number_of_op_links
  380. k = op_linked(j) ;
  381. linked(k) = 1 ;
  382. link(k).is_unconstrained = operator.link(j).is_unconstrained ;
  383. current_link = link(k) ;
  384. port_name = current_link.name ;
  385. port_index = strmatch(port_name,port_names,'exact') ;
  386. terminal = [branch,'__',object_name,'___',port_name] ;
  387. if current_link.is_effort
  388. if current_link.is_state
  389. link_name{j} = [terminal,'.effort_state'] ;
  390. else
  391. link_name{j} = [terminal,'.effort'] ;
  392. end
  393. end
  394. if current_link.is_flow
  395. if current_link.is_state
  396. link_name{j} = [terminal,'.flow_state'] ;
  397. else
  398. link_name{j} = [terminal,'.flow'] ;
  399. end
  400. end
  401. matched_name_counter = strmatch(link_name{j},{namelist.var},'exact') ;
  402. if current_link.is_input
  403. input_mask(port_index) = 1 ;
  404. if current_link.is_unconstrained
  405. input_counter = input_counter + 1 ;
  406. input{input_counter} = matched_name_counter ;
  407. end
  408. else
  409. mttAssert(~output_mask(port_index),...
  410. ['Over-determined output "',port_name,'" in operator ',full_operator_name]) ;
  411. output_mask(port_index) = 1 ;
  412. if current_link.is_unconstrained & ~current_link.is_state
  413. output_counter = output_counter + 1 ;
  414. output{output_counter} = matched_name_counter ;
  415. end
  416. end
  417. end
  418. line = line + 1 ;
  419. ese(line) = specify_ese(branch,output,branch,input,full_operator_name) ;
  420. for j = 1:number_of_op_links
  421. k = op_linked(j) ;
  422. current_link = link(k) ;
  423. matched_name_counter = strmatch(link_name{j},{namelist.var},'exact') ;
  424. if ~current_link.is_input
  425. if ~current_link.is_unconstrained
  426. line = line + 1 ;
  427. ese(line) = specify_ese(branch,{matched_name_counter},branch,{1},[]) ;
  428. end
  429. end
  430. end
  431. end
  432. unused_inputs = ~all(input_mask) ;
  433. unused_outputs = ~all(output_mask) ;
  434. still_counting = op_counter<number_of_operators ;
  435. matching = (unused_inputs | unused_outputs) & (op_counter<number_of_operators) ;
  436. end
  437. mttAssert(all(input_mask),...
  438. ['Unattached input(s) in "cr" implementation in ',here]) ;
  439. mttAssert(all(output_mask),...
  440. ['Unattached output(s) in "cr" implementation in ',here]) ;
  441. mttAssert(all(linked),...
  442. ['Unattached ports in "cr" implementation in ',here]) ;
  443. end
  444. end
  445. end
  446. for n = 1:length(objects)
  447. object_name = objects{n} ;
  448. object = getfield(model,'obj',object_name) ;
  449. here = [branch,':',object_name] ;
  450. if ~isempty(object.cr)
  451. operators = object.cr.operator ;
  452. number_of_operators = length(operators) ;
  453. object.cr = mttDeleteField(object.cr,'operator') ;
  454. used_counter = 0 ;
  455. for op_counter = 1:number_of_operators
  456. operator = operators(op_counter) ;
  457. if object.cr.used_operator(op_counter)
  458. used_counter = used_counter + 1 ;
  459. used_operator = operator ;
  460. % used_operator = mttDeleteField(used_operator,'is_used') ;
  461. used_operator = mttDeleteField(used_operator,'assign') ;
  462. object.cr.operator(used_counter) = used_operator ;
  463. end
  464. end
  465. end
  466. if ~isempty(object.abg)
  467. next_branch = [branch,'__',object_name] ;
  468. for j = 1:mttGetFieldLength(object,'interface')
  469. inbond = object.interface(j).in ;
  470. outbond = object.interface(j).out ;
  471. inmap = object.interface(j).map.in ;
  472. outmap = object.interface(j).map.out ;
  473. interface_class = object.interface(j).class ;
  474. if ~isempty(inbond)
  475. bond = model.bond(inbond) ;
  476. line = line + 1 ;
  477. if bond.flow
  478. if strcmp(interface_class,'Se')
  479. ese(line) = specify_ese(branch,[2*inbond],next_branch,{1},[]) ;
  480. else
  481. ese(line) = specify_ese(branch,[2*inbond],next_branch,[2*inmap],[]) ;
  482. end
  483. else
  484. ese(line) = specify_ese(next_branch,[2*inmap],branch,[2*inbond],[]) ;
  485. end
  486. line = line + 1 ;
  487. if bond.effort
  488. ese(line) = specify_ese(next_branch,[2*inmap-1],branch,[2*inbond-1],[]) ;
  489. else
  490. if strcmp(interface_class,'Sf')
  491. ese(line) = specify_ese(branch,[2*inbond-1],next_branch,{1},[]) ;
  492. else
  493. ese(line) = specify_ese(branch,[2*inbond-1],next_branch,[2*inmap-1],[]) ;
  494. end
  495. end
  496. end
  497. if ~isempty(outbond)
  498. bond = model.bond(outbond) ;
  499. line = line + 1 ;
  500. if bond.flow
  501. if strcmp(interface_class,'De')
  502. ese(line) = specify_ese(next_branch,[2*outmap],branch,{1},[]) ;
  503. else
  504. ese(line) = specify_ese(next_branch,[2*outmap],branch,[2*outbond],[]) ;
  505. end
  506. else
  507. ese(line) = specify_ese(branch,[2*outbond],next_branch,[2*outmap],[]) ;
  508. end
  509. line = line + 1 ;
  510. if bond.effort
  511. ese(line) = specify_ese(branch,[2*outbond-1],next_branch,[2*outmap-1],[]) ;
  512. else
  513. if strcmp(interface_class,'Df')
  514. ese(line) = specify_ese(next_branch,[2*outmap-1],branch,{1},[]) ;
  515. else
  516. ese(line) = specify_ese(next_branch,[2*outmap-1],branch,[2*outbond-1],[]) ;
  517. end
  518. end
  519. end
  520. end
  521. [object,object_ese,object_namelist] = specify_equations(object,next_branch,namelist) ;
  522. model = setfield(model,'obj',object_name,object) ;
  523. ese = [ese, object_ese] ;
  524. line = length(ese) ;
  525. namelist = object_namelist ;
  526. end
  527. object.cr = mttDeleteField(object.cr,'used_operator') ;
  528. model = setfield(model,'obj',object_name,object) ;
  529. end
  530. function equation = specify_ese(LHS_branch,LHS_var,RHS_branch,RHS_var,operator)
  531. equation.branch.LHS = LHS_branch ;
  532. equation.branch.RHS = RHS_branch ;
  533. equation.var.LHS = LHS_var ;
  534. equation.var.RHS = RHS_var ;
  535. equation.operator = operator ;
  536. function [branchlist,branchbond] = identify_branches(model,branch)
  537. is_root_model = (nargin==1) ;
  538. if is_root_model
  539. branch = mttDetachText(model.source,'/') ;
  540. branchlist{1} = branch ;
  541. branchbond = length(model.bond) ;
  542. counter = 1 ;
  543. else
  544. branchlist = [] ;
  545. branchbond = 0 ;
  546. counter = 0 ;
  547. end
  548. objects = mttGetFieldNames(model,'obj') ;
  549. for n = 1:length(objects)
  550. object_name = objects{n} ;
  551. object = getfield(model,'obj',object_name) ;
  552. next_branch = [branch,'__',object_name] ;
  553. [next_branchlist,next_branchbond] = identify_branches(object,next_branch) ;
  554. counter = counter + 1 ;
  555. branchlist{counter} = next_branch ;
  556. if isfield(object,'bond')
  557. branchbond(counter) = length(object.bond) ;
  558. else
  559. branchbond(counter) = 0 ;
  560. end
  561. for i = 1:length(next_branchlist)
  562. counter = counter + 1 ;
  563. branchlist{counter} = next_branchlist{i} ;
  564. branchbond(counter) = next_branchbond(i) ;
  565. end
  566. end
  567. function [sse,sorted_equations] = sort_equations(ese,model,namelist)
  568. mttWriteNewLine ;
  569. mttNotify('...sorting equations') ;
  570. mttWriteNewLine ;
  571. [branchlist,branchbond] = identify_branches(model) ;
  572. lastvar = cumsum(2*branchbond) ;
  573. offsetvar = lastvar - 2*branchbond ;
  574. number_of_equations = length(ese) ;
  575. % number_of_covariables = length(namelist) - 1 ;
  576. % number_of_interface_variables = max(lastvar) ;
  577. number_of_covariables = max(lastvar) ;
  578. number_of_interface_variables = length(namelist) - 1 ;
  579. mttNotifyEquationSummary(number_of_equations,number_of_covariables,number_of_interface_variables) ;
  580. for i = 1:length(ese)
  581. if isempty(ese(i).operator)
  582. var = ese(i).var.LHS ;
  583. switch class(var)
  584. case 'double',
  585. branch_index = strmatch(ese(i).branch.LHS,branchlist,'exact') ;
  586. info(i).LHS = abs(var) + offsetvar(branch_index) ;
  587. case 'cell',
  588. info(i).LHS = ese(i).var.LHS ;
  589. end
  590. var = ese(i).var.RHS ;
  591. switch class(var)
  592. case 'double',
  593. branch_index = strmatch(ese(i).branch.RHS,branchlist,'exact') ;
  594. for j = 1:length(var)
  595. info(i).RHS(j) = abs(var(j)) + offsetvar(branch_index) ;
  596. end
  597. case 'cell',
  598. info(i).RHS = ese(i).var.RHS ;
  599. end
  600. else
  601. info(i).LHS = ese(i).var.LHS ;
  602. info(i).RHS = ese(i).var.RHS ;
  603. end
  604. end
  605. var_known = zeros(max(lastvar),1) ;
  606. name_known = zeros(length(namelist),1) ;
  607. name_known(1) = 1 ;
  608. log = ones(length(ese),1) ;
  609. map = zeros(length(ese),1) ;
  610. counter = 0 ;
  611. for i = 1:length(ese)
  612. if log(i) & isempty(ese(i).operator)
  613. left = info(i).LHS ;
  614. right = info(i).RHS ;
  615. if isnumeric(left) & iscell(right)
  616. name = namelist(right{1}).var ;
  617. is_object_interface = ~isempty(findstr(name,'___')) ;
  618. ok = 1 ;
  619. if is_object_interface
  620. is_effort_state = ~isempty(findstr(name,'.effort_state')) ;
  621. is_flow_state = ~isempty(findstr(name,'.flow_state')) ;
  622. ok = is_effort_state | is_flow_state ;
  623. end
  624. if ok
  625. log(i) = 0 ;
  626. counter = counter + 1 ;
  627. map(counter) = i ;
  628. var_known(left) = 1 ;
  629. name_index = strmatch(name,{namelist.var},'exact') ;
  630. name_known(name_index) = 1 ;
  631. end
  632. end
  633. if iscell(left) & iscell(right)
  634. if right{1}==1
  635. log(i) = 0 ;
  636. counter = counter + 1 ;
  637. map(counter) = i ;
  638. name = namelist(left{1}).var ;
  639. name_index = strmatch(name,{namelist.var},'exact') ;
  640. name_known(name_index) = 1 ;
  641. end
  642. end
  643. end
  644. end
  645. previous_var_known = var_known ;
  646. previous_name_known = name_known ;
  647. sort_iteration = 0 ;
  648. sorting = 1 ;
  649. while sorting
  650. sort_iteration = sort_iteration + 1 ;
  651. for i = 1:length(ese)
  652. if log(i) & isempty(ese(i).operator)
  653. left = info(i).LHS ;
  654. right = info(i).RHS ;
  655. if isnumeric(right)
  656. if all(var_known(right))
  657. log(i) = 0 ;
  658. counter = counter + 1 ;
  659. map(counter) = i ;
  660. if isnumeric(left)
  661. var_known(left) = 1 ;
  662. else
  663. name = namelist(left{1}).var ;
  664. name_index = strmatch(name,{namelist.var},'exact') ;
  665. name_known(name_index) = 1 ;
  666. end
  667. end
  668. else
  669. name = namelist(right{1}).var ;
  670. name_index = strmatch(name,{namelist.var},'exact') ;
  671. if name_known(name_index)
  672. is_object_interface = ~isempty(findstr(name,'___')) ;
  673. if is_object_interface
  674. log(i) = 0 ;
  675. counter = counter + 1 ;
  676. map(counter) = i ;
  677. var_known(left) = 1 ;
  678. end
  679. end
  680. end
  681. end
  682. end
  683. for i = 1:length(ese)
  684. if log(i) & ~isempty(ese(i).operator)
  685. left = info(i).LHS ;
  686. right = info(i).RHS ;
  687. indices = [] ;
  688. for j = 1:length(right)
  689. name = namelist(right{j}).var ;
  690. indices(j) = strmatch(name,{namelist.var},'exact') ;
  691. end
  692. if all(name_known(indices))
  693. log(i) = 0 ;
  694. counter = counter + 1 ;
  695. map(counter) = i ;
  696. for j = 1:length(left)
  697. name = namelist(left{j}).var ;
  698. name_index = strmatch(name,{namelist.var},'exact') ;
  699. name_known(name_index) = 1 ;
  700. end
  701. end
  702. end
  703. end
  704. same_vars_known = sum(var_known)==sum(previous_var_known) ;
  705. same_names_known = sum(name_known)==sum(previous_name_known) ;
  706. previous_var_known = var_known ;
  707. previous_name_known = name_known ;
  708. sorting = ~(same_vars_known & same_names_known) ;
  709. if sorting
  710. mttNotify(['...iteration ',num2str(sort_iteration)]) ;
  711. mttWriteNewLine ;
  712. % is_complete = ...
  713. % mttNotifyEquationSort(sort_iteration,...
  714. % sum(log),number_of_equations,...
  715. % sum(name_known),number_of_covariables,...
  716. % sum(var_known),number_of_interface_variables) ;
  717. is_complete = ...
  718. mttNotifyEquationSort(sort_iteration,...
  719. sum(log),number_of_equations,...
  720. sum(var_known),number_of_covariables,...
  721. sum(name_known),number_of_interface_variables) ;
  722. sorting = sorting & ~is_complete ;
  723. end
  724. end
  725. for i = 1:length(ese)
  726. if log(i) & isempty(ese(i).operator)
  727. left = info(i).LHS ;
  728. right = info(i).RHS ;
  729. if iscell(left) & isnumeric(right)
  730. name = namelist(left{1}).var ;
  731. is_object_interface = ~isempty(findstr(name,'___')) ;
  732. if ~is_object_interface
  733. if var_known(right)
  734. log(i) = 0 ;
  735. counter = counter + 1 ;
  736. map(counter) = i ;
  737. name_index = strmatch(name,{namelist.var},'exact') ;
  738. name_known(name_index) = 1 ;
  739. end
  740. end
  741. end
  742. end
  743. end
  744. sorted_equations = counter ;
  745. if sorted_equations<number_of_equations
  746. mttWriteNewLine ;
  747. mttNotify(['...unable to sort equations completely']) ;
  748. mttWriteNewLine ;
  749. mttNotifyEquationSortProblems(name_known,namelist) ;
  750. end
  751. for i = 1:length(ese)
  752. if log(i)
  753. counter = counter + 1 ;
  754. map(counter) = i ;
  755. end
  756. end
  757. mttAssert(counter==length(ese),'Sort algorithm has failed! Seek expert assistance!') ;
  758. for i = 1:length(ese)
  759. sse(i) = ese(map(i)) ;
  760. end
  761. function link = create_link(is_input,is_effort,is_flow,name,is_state)
  762. link.is_input = is_input ;
  763. link.is_effort = is_effort ;
  764. link.is_flow = is_flow ;
  765. link.name = name ;
  766. link.is_state = is_state ;
  767. link.is_unconstrained = [] ;
  768. function boolean = compare_links(actual_link,op_link)
  769. input_is_same = actual_link.is_input==op_link.is_input ;
  770. effort_is_same = actual_link.is_effort==op_link.is_effort ;
  771. flow_is_same = actual_link.is_flow==op_link.is_flow ;
  772. name_is_same = strcmp(actual_link.name,op_link.name) ;
  773. boolean = input_is_same & effort_is_same & flow_is_same & name_is_same ;