mttParseOperatorEquations.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. function operator = mttParseOperatorEquations(operator,cr,cr_name)
  2. global mtt_environment
  3. operator.equation = [] ;
  4. % operator.is_used = 0 ;
  5. numparlist = cr.numpar ;
  6. symparlist = cr.sympar ;
  7. varlist = operator.var ;
  8. inputlist = cr.input ;
  9. statelist = cr.state ;
  10. structlist = [] ;
  11. if ~isempty(operator.struct)
  12. struct_names = mttGetFieldNames(operator,'struct') ;
  13. number_of_structs = length(struct_names) ;
  14. for i = 1:number_of_structs
  15. struct_name = struct_names{i} ;
  16. variables = getfield(operator,'struct',struct_name) ;
  17. if i==1
  18. structlist = variables ;
  19. else
  20. structlist = [structlist,variables] ;
  21. end
  22. end
  23. end
  24. inlist = [] ;
  25. outlist = [] ;
  26. inlink = [] ;
  27. outlink = [] ;
  28. input_counter = 0 ;
  29. output_counter = 0 ;
  30. for i = 1:length(operator.link)
  31. if operator.link(i).is_input
  32. input_counter = input_counter + 1 ;
  33. inlist{input_counter} = operator.link(i).name ;
  34. inlink(input_counter) = i ;
  35. infree(input_counter) = operator.link(i).is_unconstrained ;
  36. else
  37. output_counter = output_counter + 1 ;
  38. outlist{output_counter} = operator.link(i).name ;
  39. outlink(output_counter) = i ;
  40. outfree(output_counter) = operator.link(i).is_unconstrained ;
  41. end
  42. end
  43. operator.assign = [] ;
  44. ports_with_state_assignment = [] ;
  45. for i = 1:length(operator.set)
  46. [port_covariable,state] = mttCutText(operator.set{i},'=>') ;
  47. mttAssert(~isempty(state),...
  48. ['"set" declarations must use "=>" in cr ',cr_name]) ;
  49. [port_name,covariable] = mttCutText(port_covariable,'.') ;
  50. mttAssert(~isempty(covariable),...
  51. ['"set" declarations must reference effort/flow covariables in cr ',cr_name]) ;
  52. port = strmatch(port_name,outlist,'exact') ;
  53. ports_with_state_assignment = [ports_with_state_assignment,port] ;
  54. mttAssert(~isempty(port),...
  55. ['Output port "',port_name,'" not recognised for "set" declaration in cr ',cr_name]) ;
  56. mttAssert(outfree(port),...
  57. ['Constrained port variable used for "set" declaration in cr ',cr_name]) ;
  58. actual_port = getfield(cr.interface.port,port_name) ;
  59. mttAssert(actual_port.is_effort_state | actual_port.is_flow_state,...
  60. ['"set" declarations must only be used for effort_states or flow_states in cr ',cr_name]) ;
  61. if isempty(actual_port.domain)
  62. if actual_port.is_effort_state
  63. covariables = {'effort'} ;
  64. elseif actual_port.is_flow_state
  65. covariables = {'flow'} ;
  66. end
  67. else
  68. public_domain = mtt_environment.public_domain(actual_port.domain) ;
  69. domain_item = getfield(public_domain.item,actual_port.domain_item) ;
  70. if actual_port.is_effort_state
  71. covariables = domain_item.effort ;
  72. elseif actual_port.is_flow_state
  73. covariables = domain_item.flow ;
  74. end
  75. end
  76. index = strmatch(covariable,covariables,'exact') ;
  77. mttAssert(~isempty(index),...
  78. ['Unrecognised covariable "',covariable,'" used for "set" declaration in cr ',cr_name]) ;
  79. if isfield(operator.assign,port_name)
  80. assignment = getfield(operator,'assign',port_name) ;
  81. mttAssert(isempty(assignment.states{index}),...
  82. ['Repeated covariable "',covariable,'" used for "set" declaration in cr ',cr_name]) ;
  83. else
  84. assignment.covar = covariables ;
  85. assignment.state{length(covariables)} = [] ;
  86. % assignment.domain = actual_port.domain ;
  87. % assignment.domain_item = actual_port.domain_item ;
  88. end
  89. mttAssert(ismember(state,cr.state),...
  90. ['Unrecognised state "',state,'" used for "set" declaration in cr ',cr_name]) ;
  91. assignment.state{index} = state ;
  92. operator = setfield(operator,'assign',port_name,assignment) ;
  93. end
  94. operator = mttDeleteField(operator,'set') ;
  95. port_assignments = mttGetFieldNames(operator,'assign') ;
  96. number_of_assignments = length(port_assignments) ;
  97. for i = 1:number_of_assignments
  98. assignment = getfield(operator,'assign',port_name) ;
  99. for j = 1:length(assignment.state)
  100. mttAssert(~isempty(assignment.state{j}),...
  101. ['Missing covariable "',covariable,'" from "set" declaration in cr ',cr_name]) ;
  102. end
  103. end
  104. for i = 1:length(operator.content)
  105. operator.equation(i).chunk = {[]} ;
  106. % operator.equation(i).was_generic = 1 ;
  107. % operator.equation(i).domain = [] ;
  108. % operator.equation(i).domain_item = [] ;
  109. % operator.equation(i).is_effort = [] ;
  110. % operator.equation(i).covariable = [] ;
  111. counter = 0 ;
  112. line = operator.content{i} ;
  113. if ~isempty(mttClipText(line))
  114. [var,loc] = mttFindEquationVariables(line) ;
  115. if loc(1)>1
  116. front = line(1:loc(1)-1) ;
  117. counter = counter + 1 ;
  118. operator.equation(i).chunk{counter} = front ;
  119. end
  120. last = length(line) ;
  121. for j = 1:length(var)
  122. [name,component] = mttCutText(var{j},'.') ;
  123. if isempty(component)
  124. [name,attribute] = mttCutText(name,'''') ;
  125. numpar = strmatch(name,numparlist,'exact') ;
  126. sympar = strmatch(name,symparlist,'exact') ;
  127. variable = strmatch(name,varlist,'exact') ;
  128. struct = strmatch(name,structlist,'exact') ;
  129. input = strmatch(name,inputlist,'exact') ;
  130. state = strmatch(name,statelist,'exact') ;
  131. ok = ~(isempty(numpar)&isempty(sympar)&isempty(variable)&isempty(struct)&isempty(input)&isempty(state)) ;
  132. mttAssert(ok,['Variable ',var{j},' not recognised in cr ',cr_name]) ;
  133. is_numpar = ~isempty(numpar) ;
  134. is_sympar = ~isempty(sympar) ;
  135. is_var = ~isempty(variable) ;
  136. is_struct = ~isempty(struct) ;
  137. is_input = ~isempty(input) ;
  138. is_state = ~isempty(state) ;
  139. is_derivative = 0 ;
  140. if ~isempty(attribute)
  141. mttAssert(strcmp(attribute,'dt'),...
  142. ['Unrecognised attribute ',attribute,' in cr ',cr_name]) ;
  143. mttAssert(is_state,...
  144. ['Derivative of non-state variable in cr ',cr_name]) ;
  145. is_state = 0 ;
  146. is_derivative = 1 ;
  147. end
  148. counter = counter + 1 ;
  149. if is_numpar
  150. operator.equation(i).chunk{counter} = {'numpar',numpar} ;
  151. end
  152. if is_sympar
  153. operator.equation(i).chunk{counter} = {'sympar',sympar} ;
  154. end
  155. if is_var
  156. operator.equation(i).chunk{counter} = {'var',variable} ;
  157. end
  158. if is_struct
  159. operator.equation(i).chunk{counter} = {'struct',struct} ;
  160. end
  161. if is_input
  162. operator.equation(i).chunk{counter} = {'input',input} ;
  163. end
  164. if is_state
  165. operator.equation(i).chunk{counter} = {'state',state} ;
  166. end
  167. if is_derivative
  168. operator.equation(i).chunk{counter} = {'derivative',state} ;
  169. end
  170. else
  171. if j==1
  172. port = strmatch(name,outlist,'exact') ;
  173. if ~isempty(ports_with_state_assignment)
  174. mttAssert(~any(port==ports_with_state_assignment),...
  175. ['Use "set" declaration to assign output port ',name,' to state in cr ',cr_name]) ;
  176. end
  177. mttAssert(~isempty(port),...
  178. ['Output port ',name,' not recognised in cr ',cr_name]) ;
  179. mttAssert(outfree(port),...
  180. ['Constrained port variable used in cr ',cr_name]) ;
  181. counter = counter + 1 ;
  182. operator.equation(i).chunk{counter} = {'link',outlink(port),component} ;
  183. else
  184. port = strmatch(name,inlist,'exact') ;
  185. mttAssert(~isempty(port),...
  186. ['Input port ',name,' not recognised in cr ',cr_name]) ;
  187. mttAssert(infree(port),...
  188. ['Constrained port variable used in cr ',cr_name]) ;
  189. counter = counter + 1 ;
  190. operator.equation(i).chunk{counter} = {'link',inlink(port),component} ;
  191. end
  192. % equation_domain = mttIdentifyUserDomain(mtt_environment,...
  193. % operator.equation(i).domain,....
  194. % operator.equation(i).domain_item) ;
  195. covariable = component ;
  196. port_name = name ;
  197. port = getfield(cr.interface.port,port_name) ;
  198. if isempty(port.domain)
  199. is_effort = strcmp(covariable,'effort') ;
  200. is_flow = strcmp(covariable,'flow') ;
  201. mttAssert(is_effort|is_flow, ...
  202. ['"',covariable,'" is not a generic covariable']) ;
  203. % mttAssert(isempty(operator.equation(i).domain),...
  204. % ['Generic interface "',port_name,'" referenced in ',equation_domain,' equation']) ;
  205. else
  206. public_domain = mtt_environment.public_domain(port.domain) ;
  207. actual_domain = getfield(public_domain,'item',port.domain_item) ;
  208. port_domain = mttIdentifyUserDomain(mtt_environment,port.domain,port.domain_item) ;
  209. is_effort = ismember(covariable,actual_domain.effort) ;
  210. is_flow = ismember(covariable,actual_domain.flow) ;
  211. mttAssert(is_effort|is_flow, ...
  212. ['"',covariable,'" is not a covariable defined in domain "',port_domain,'"']) ;
  213. % if isempty(equation_domain)
  214. % operator.equation(i).was_generic = 0 ;
  215. % operator.equation(i).domain = port.domain ;
  216. % operator.equation(i).domain_item = port.domain_item ;
  217. % operator.equation(i).covariable = covariable ;
  218. % else
  219. % mttAssert(covariable==operator.equation(i).covariable, ...
  220. % ['Equation cannot combine different covariables: [',covariable,',',operator.equation(i).covariable,']') ;
  221. % end
  222. end
  223. % if isempty(operator.equation(i).is_effort)
  224. % if is_effort
  225. % operator.equation(i).is_effort = 1 ;
  226. % else
  227. % operator.equation(i).is_effort = 0 ;
  228. % end
  229. % else
  230. % mttAssert(operator.equation(i).is_effort==is_effort,...
  231. % ['Effort and flow covariables appear in equation: "',operator.content{i},'"']) ;
  232. % end
  233. end
  234. next = loc(j) + length(var{j}) ;
  235. if j<length(var)
  236. glue = line(next:loc(j+1)-1) ;
  237. counter = counter + 1 ;
  238. operator.equation(i).chunk{counter} = glue ;
  239. if j==1
  240. mttAssert(~isempty(findstr(glue,':=')),...
  241. ['Expect ":=" after first variable in cr ',cr_name]) ;
  242. end
  243. else
  244. if next<=last
  245. back = line(next:last) ;
  246. counter = counter + 1 ;
  247. operator.equation(i).chunk{counter} = back ;
  248. end
  249. end
  250. end
  251. end
  252. end