mttWriteSystemEquations.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. function mttWriteSystemEquations(model)
  2. [eqn,ini] = format_equations(model) ;
  3. write_equations(eqn,ini,model) ;
  4. function [eqn,ini] = format_equations(model)
  5. mttNotify('...formating ordinary differential equations') ;
  6. mttWriteNewLine ;
  7. sse = model.equation ;
  8. namelist = model.namelist ;
  9. tab = char(32*ones(1,3)) ;
  10. eqn_counter = 0 ;
  11. ini_counter = 0 ;
  12. eqn = [] ;
  13. ini = [] ;
  14. for i = 1:length(sse)
  15. content = [] ;
  16. indent = 0 ;
  17. if isempty(sse(i).operator)
  18. Lvar = sse(i).var.LHS ;
  19. Rvar = sse(i).var.RHS ;
  20. if isnumeric(Lvar) | isnumeric(Rvar)
  21. if isnumeric(Lvar)
  22. name = sse(i).branch.LHS ;
  23. if mod(Lvar,2)
  24. bond_number = (Lvar+1)/2 ;
  25. else
  26. bond_number = Lvar/2 ;
  27. end
  28. else
  29. name = sse(i).branch.RHS ;
  30. if mod(Rvar,2)
  31. bond_number = (Rvar+1)/2 ;
  32. else
  33. bond_number = Rvar/2 ;
  34. end
  35. end
  36. [hierarchy,interface] = mttCutText(name,'___') ;
  37. level = length(findstr(hierarchy,'__')) ;
  38. [root,hierarchy] = mttCutText(hierarchy,'__') ;
  39. for j = 1:level
  40. [obj{j},hierarchy] = mttCutText(hierarchy,'__') ;
  41. end
  42. if level==0
  43. local_object = model ;
  44. else
  45. local_object = getfield(model,'obj',obj{1}) ;
  46. for j = 2:level
  47. local_object = getfield(local_object,'obj',obj{j}) ;
  48. end
  49. end
  50. [specified_domain,specified_domain_item] = mttGetBondDomain(local_object,bond_number) ;
  51. else
  52. [name,covar] = mttCutText(namelist(Lvar{1}).var,'.') ;
  53. [hierarchy,interface] = mttCutText(name,'___') ;
  54. level = length(findstr(hierarchy,'__')) ;
  55. [root,hierarchy] = mttCutText(hierarchy,'__') ;
  56. for j = 1:level
  57. [obj{j},hierarchy] = mttCutText(hierarchy,'__') ;
  58. end
  59. parent_object = model ;
  60. object = getfield(model,'obj',obj{1}) ;
  61. for j = 2:level
  62. parent_object = object ;
  63. object = getfield(object,'obj',obj{j}) ;
  64. end
  65. index = strmatch(interface,{object.interface.name},'exact') ;
  66. interface_definition = object.interface(index) ;
  67. if isempty(interface_definition.in)
  68. bond_number = interface_definition.out ;
  69. else
  70. bond_number = interface_definition.in ;
  71. end
  72. [specified_domain,specified_domain_item] = mttGetBondDomain(parent_object,bond_number) ;
  73. end
  74. covariables = mttGetCovariables(model.env,specified_domain,specified_domain_item) ;
  75. dimension = length(covariables.effort) ;
  76. var = sse(i).var.LHS ;
  77. branch = sse(i).branch.LHS ;
  78. LHS.name = [] ;
  79. LHS.is_effort = [] ;
  80. switch class(var)
  81. case 'double',
  82. if mod(var,2)
  83. % LHS.name = [branch,'[',num2str((var+1)/2),']'] ;
  84. LHS.name = [branch,'__',num2str((var+1)/2)] ;
  85. LHS.is_effort = 1 ;
  86. else
  87. % LHS.name = [branch,'[',num2str(var/2),']'] ;
  88. LHS.name = [branch,'__',num2str(var/2)] ;
  89. LHS.is_effort = 0 ;
  90. end
  91. case 'cell',
  92. [name,covar] = mttCutText(namelist(var{1}).var,'.') ;
  93. LHS.name = name ;
  94. if strcmp(covar,'effort')
  95. LHS.is_effort = 1 ;
  96. else
  97. LHS.is_effort = 0 ;
  98. end
  99. end
  100. var = sse(i).var.RHS ;
  101. branch = sse(i).branch.RHS ;
  102. RHS.name = [] ;
  103. RHS.is_effort = [] ;
  104. switch class(var)
  105. case 'double',
  106. if mod(abs(var(1)),2)
  107. % RHS.name{1} = [branch,'[',num2str((abs(var(1))+1)/2),']'] ;
  108. RHS.name{1} = [branch,'__',num2str((abs(var(1))+1)/2)] ;
  109. RHS.is_effort(1) = 1 ;
  110. else
  111. % RHS.name{1} = [branch,'[',num2str(abs(var(1))/2),']'] ;
  112. RHS.name{1} = [branch,'__',num2str(abs(var(1))/2)] ;
  113. RHS.is_effort(1) = 0 ;
  114. end
  115. if var(1)<0
  116. RHS.name{1} = ['-',RHS.name{1}] ;
  117. end
  118. for j = 2:length(var)
  119. if mod(abs(var(j)),2)
  120. % RHS.name{j} = [branch,'[',num2str((abs(var(j))+1)/2),']'] ;
  121. RHS.name{j} = [branch,'__',num2str((abs(var(j))+1)/2)] ;
  122. RHS.is_effort(j) = 1 ;
  123. else
  124. % RHS.name{j} = [branch,'[',num2str(abs(var(j))/2),']'] ;
  125. RHS.name{j} = [branch,'__',num2str(abs(var(j))/2)] ;
  126. RHS.is_effort(j) = 0 ;
  127. end
  128. if var(j)>0
  129. RHS.name{j} = [' + ',RHS.name{j}] ;
  130. else
  131. RHS.name{j} = [' - ',RHS.name{j}] ;
  132. end
  133. end
  134. case 'cell',
  135. [name,covar] = mttCutText(namelist(var{1}).var,'.') ;
  136. RHS.name{1} = name ;
  137. if strcmp(covar,'effort') | strcmp(covar,'effort_state')
  138. RHS.is_effort = 1 ;
  139. else
  140. RHS.is_effort = 0 ;
  141. end
  142. end
  143. for k = 1:dimension
  144. if LHS.is_effort
  145. covar = covariables.effort{k} ;
  146. else
  147. covar = covariables.flow{k} ;
  148. end
  149. content = [LHS.name,'.',strrep(covar,'.','__')] ;
  150. indent = char(32*ones(1,length(content)+3)) ;
  151. for j = 1:length(RHS.name)
  152. if RHS.is_effort(j)
  153. covar = covariables.effort{k} ;
  154. else
  155. covar = covariables.flow{k} ;
  156. end
  157. if j==1
  158. if strcmp(RHS.name{1},'0')
  159. content = [content,' = ',RHS.name{1}] ;
  160. else
  161. content = [content,' = ',RHS.name{1},'.',strrep(covar,'.','__')] ;
  162. end
  163. else
  164. content = [content,'\n',indent,RHS.name{j},'.',strrep(covar,'.','__')] ;
  165. end
  166. end
  167. content = [content,' ;'] ;
  168. if ~isempty(content)
  169. eqn_counter = eqn_counter + 1 ;
  170. eqn{eqn_counter} = content ;
  171. end
  172. end
  173. else
  174. op = [sse(i).operator] ;
  175. [cr,operator] = mttCutText(op,'___') ;
  176. if ~strcmp(eqn{eqn_counter},'')
  177. eqn_counter = eqn_counter + 1 ;
  178. eqn{eqn_counter} = [''] ;
  179. end
  180. eqn_counter = eqn_counter + 1 ;
  181. eqn{eqn_counter} = ['// ',op] ;
  182. [root,hierarchy] = mttCutText(cr,'__') ;
  183. level = length(findstr(cr,'__')) ;
  184. for j = 1:level
  185. [obj{j},hierarchy] = mttCutText(hierarchy,'__') ;
  186. end
  187. object = getfield(model,'obj',obj{1}) ;
  188. for j = 2:level
  189. object = getfield(object,'obj',obj{j}) ;
  190. end
  191. index = strmatch(operator,{object.cr.operator.name},'exact') ;
  192. cr_definition = object.cr ;
  193. operator_definition = cr_definition.operator(index) ;
  194. structlist = [] ;
  195. if ~isempty(operator_definition.struct)
  196. struct_names = mttGetFieldNames(operator_definition,'struct') ;
  197. number_of_structs = length(struct_names) ;
  198. for i = 1:number_of_structs
  199. struct_name = struct_names{i} ;
  200. variables = getfield(operator_definition,'struct',struct_name) ;
  201. if i==1
  202. structlist = variables ;
  203. else
  204. structlist = [structlist,variables] ;
  205. end
  206. end
  207. end
  208. reassigned_state_list = [] ;
  209. counter = 0 ;
  210. port_names = mttGetFieldNames(cr_definition.interface,'port') ;
  211. for j = 1:length(port_names)
  212. port_name = port_names{j} ;
  213. port = getfield(cr_definition,'interface','port',port_name) ;
  214. if ~isempty(port.assign)
  215. assignment = port.assign ;
  216. if port.was_generic & ~isempty(port.domain)
  217. covar = mttGetCovariables(model.env,port.domain,port.domain_item) ;
  218. if port.is_effort_state
  219. covar = covariables.effort ;
  220. else
  221. covar = covariables.flow ;
  222. end
  223. for k = 1:length(assignment.state)
  224. counter = counter + 1 ;
  225. reassigned_state_list.name{counter} = assignment.state{k} ;
  226. reassigned_state_list.covar{counter} = covar ;
  227. end
  228. block_size = length(covar) ;
  229. for var = 1:block_size
  230. segment = [] ;
  231. for k = 1:length(assignment.state)
  232. segment{1} = [cr,'___',port_name,'.',strrep(covar{var},'.','__')] ;
  233. segment{2} = [' = '] ;
  234. segment{3} = [cr,'___',assignment.state{k},'___',strrep(covar{var},'.','__'),'.state ;'] ;
  235. ini_counter = ini_counter + 1 ;
  236. ini{ini_counter} = [segment{1},segment{2},segment{3}] ;
  237. end
  238. end
  239. else
  240. for k = 1:length(assignment.state)
  241. segment{1} = [cr,'___',port_name,'.',strrep(assignment.covar{k},'.','__')] ;
  242. segment{2} = [' = '] ;
  243. segment{3} = [cr,'___',assignment.state{k},'.state ;'] ;
  244. ini_counter = ini_counter + 1 ;
  245. ini{ini_counter} = [segment{1},segment{2},segment{3}] ;
  246. end
  247. end
  248. end
  249. end
  250. equations = operator_definition.equation ;
  251. for j = 1:length(equations)
  252. equation = equations(j) ;
  253. number_of_chunks = mttGetFieldLength(equation,'chunk') ;
  254. equation.domain = [] ;
  255. equation.domain_item = [] ;
  256. for k = 1:number_of_chunks
  257. chunk = equation.chunk{k} ;
  258. switch class(chunk)
  259. case 'cell'
  260. type = chunk{1} ;
  261. index = chunk{2} ;
  262. switch type
  263. case 'link'
  264. port_name = operator_definition.link(index).name ;
  265. port = getfield(cr_definition,'interface','port',port_name) ;
  266. if port.was_generic & ~isempty(port.domain)
  267. if isempty(equation.domain)
  268. equation.domain = port.domain ;
  269. equation.domain_item = port.domain_item ;
  270. else
  271. same_domain = equation.domain==port.domain ;
  272. same_domain_item = strcmp(equation.domain_item,port.domain_item) ;
  273. mttAssert(same_domain&same_domain_item,...
  274. ['Attempt to overwrite implicit variables with conflicting domains in "',...
  275. operator_definition.content{j},'"']) ;
  276. end
  277. end
  278. end
  279. end
  280. end
  281. covariables = mttGetCovariables(model.env,equation.domain,equation.domain_item) ;
  282. % if equation.is_effort
  283. % covar = covariables.effort ;
  284. % else
  285. % covar = covariables.flow ;
  286. % end
  287. block_size = length(covariables.effort) ;
  288. for line = 1:block_size
  289. segment = [] ;
  290. content = [] ;
  291. for k = 1:number_of_chunks
  292. chunk = equation.chunk{k} ;
  293. switch class(chunk)
  294. case 'cell'
  295. type = chunk{1} ;
  296. index = chunk{2} ;
  297. switch type
  298. case 'link'
  299. port_variable = [cr,'___',operator_definition.link(index).name] ;
  300. if strcmp(chunk{3},'generic___effort')
  301. segment{k} = [port_variable,'.',strrep(covariables.effort{line},'.','__')] ;
  302. elseif strcmp(chunk{3},'generic___flow')
  303. segment{k} = [port_variable,'.',strrep(covariables.flow{line},'.','__')] ;
  304. else
  305. segment{k} = [port_variable,'.',strrep(chunk{3},'.','__')] ;
  306. end
  307. % if length(chunk)>2
  308. % segment{k} = [port_variable,'.',strrep(chunk{3},'.','__')] ;
  309. % else
  310. % segment{k} = [port_variable,'.',strrep(covar{line},'.','__')] ;
  311. % end
  312. case 'numpar'
  313. segment{k} = [cr,'___',cr_definition.numpar{index}] ;
  314. case 'sympar'
  315. parameter = [cr_definition.parameter{index}] ;
  316. if isnumeric(parameter)
  317. segment{k} = num2str(parameter) ;
  318. else
  319. segment{k} = [cr_definition.parameter{index}] ;
  320. end
  321. case 'var'
  322. segment{k} = [op,'___',operator_definition.var{index}] ;
  323. case 'struct'
  324. segment{k} = [op,'___',structlist{index}] ;
  325. case 'input'
  326. segment{k} = [cr,'___',cr_definition.input{index}] ;
  327. case 'state'
  328. state = cr_definition.state{index} ;
  329. if isempty(reassigned_state_list)
  330. state_reassignment = [] ;
  331. else
  332. state_reassignment = strmatch(state,reassigned_state_list.name,'exact') ;
  333. end
  334. if isempty(state_reassignment)
  335. segment{k} = [cr,'___',state,'.state'] ;
  336. else
  337. state_covar = reassigned_state_list.covar{line} ;
  338. segment{k} = [cr,'___',state,'___',state_covar{1},'.state'] ;
  339. end
  340. % segment{k} = [cr,'___',cr_definition.state{index},'.state'] ;
  341. case 'derivative'
  342. state = cr_definition.state{index} ;
  343. if isempty(reassigned_state_list)
  344. state_reassignment = [] ;
  345. else
  346. state_reassignment = strmatch(state,reassigned_state_list.name,'exact') ;
  347. end
  348. if isempty(state_reassignment)
  349. segment{k} = [cr,'___',state,'.derivative'] ;
  350. else
  351. state_covar = reassigned_state_list.covar{line} ;
  352. segment{k} = [cr,'___',state,'___',state_covar{1},'.derivative'] ;
  353. end
  354. % segment{k} = [cr,'___',cr_definition.state{index},'.derivative'] ;
  355. end
  356. otherwise
  357. chunk = strrep(chunk,':=','=') ;
  358. segment{k} = chunk ;
  359. end
  360. end
  361. content = [tab,segment{1}] ;
  362. for k = 2:length(segment)
  363. content = [content,segment{k}] ;
  364. end
  365. content = [content,' ;'] ;
  366. eqn_counter = eqn_counter + 1 ;
  367. eqn{eqn_counter} = content ;
  368. end
  369. end
  370. eqn_counter = eqn_counter + 1 ;
  371. eqn{eqn_counter} = ['// End of ',op] ;
  372. eqn_counter = eqn_counter + 1 ;
  373. eqn{eqn_counter} = [''] ;
  374. end
  375. end
  376. eqn = eqn' ;
  377. ini = ini' ;
  378. function write_equations(eqn,ini,model)
  379. filename = [model.source,'_include_ode.h'] ;
  380. fid = fopen(filename,'w') ;
  381. mttNotify(['...creating ',filename]) ;
  382. mttWriteNewLine ;
  383. fprintf(fid,['// Ordinary Differential Equations\n']) ;
  384. fprintf(fid,'\n') ;
  385. fprintf(fid,['// file: ',filename,'\n']) ;
  386. fprintf(fid,['// written by MTT on ',datestr(now),'\n']) ;
  387. fprintf(fid,'\n\n') ;
  388. tab = char(32*ones(1,3)) ;
  389. for i = 1:length(ini)
  390. formatted_equation = [tab,ini{i},'\n'] ;
  391. fprintf(fid,formatted_equation) ;
  392. end
  393. fprintf(fid,'\n') ;
  394. for i = 1:length(eqn)
  395. formatted_equation = [tab,eqn{i},'\n'] ;
  396. fprintf(fid,formatted_equation) ;
  397. end
  398. fclose(fid) ;