reacteqn.red 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. module reacteqn; % REDUCE support for reaction equations.
  2. % Author: H. Melenk
  3. % January 1991
  4. % Copyright (c) Konrad-Zuse-Zentrum Berlin, all rights reserved.
  5. % Introduce operators for chemical equations.
  6. algebraic operator rightarrow;
  7. newtok '((!- !>) rightarrow);
  8. infix rightarrow;
  9. precedence rightarrow,equal;
  10. algebraic operator doublearrow;
  11. newtok '((!< !>) doublearrow);
  12. infix doublearrow;
  13. precedence doublearrow,equal;
  14. algebraic operator rate;
  15. global '(species); share species;
  16. global '(rates); share rates;
  17. put('reac2ode,'psopfn,'r2oeval);
  18. symbolic procedure r2oeval u;
  19. begin scalar r,k,x,rhs,lhs,ratel,odel,oldorder,lhsl,rhsl;
  20. integer rc;
  21. if eqcar(species,'list) then
  22. odel:=for each x in cdr species collect reval x . 0;
  23. u := reval car u;
  24. if not eqcar(u,'list) then typerr(u,"list of reactions");
  25. u := cdr u;
  26. loop:
  27. if null u then goto finis;
  28. r := reval car u; u := cdr u;
  29. if not pairp r or not memq(car r,'(rightarrow doublearrow))
  30. then goto synerror;
  31. lhs := r2speclist cadr r;
  32. rhs := r2speclist caddr r;
  33. % include new species
  34. for each x in append(lhs,rhs) do
  35. odel:=r2oaddspecies(cdr x,odel);
  36. % generate contribution from forward reaction.
  37. k := if u and (x:=reval car u) and
  38. not(pairp x and memq(car x,'(rightarrow doublearrow)))
  39. then <<u:=cdr u; x>> else list('rate,rc:=rc+1);
  40. ratel := k . ratel;
  41. r2oreaction(lhs,rhs,k,odel);
  42. % eventually generate backward reaction
  43. if car r='doublearrow then
  44. <<k := if u and (x:=reval car u) and
  45. not(pairp x and memq(car x,'(rightarrow doublearrow)))
  46. then <<u:=cdr u; x>> else list('rate,rc:=rc+1);
  47. ratel := k . ratel;
  48. r2oreaction(rhs,lhs,k,odel);
  49. >>;
  50. lhsl := lhs.lhsl; rhsl := rhs.rhsl;
  51. goto loop;
  52. finis:
  53. ratel := reversip ratel;
  54. rates := 'list. ratel;
  55. for each x in ratel do
  56. if numberp x or pairp x and get(car x,'dname) then
  57. ratel := delete(x,ratel);
  58. species := 'list. for each x in odel collect car x;
  59. r2omat(cdr species,reversip lhsl,reversip rhsl);
  60. for each r in ratel do if not idp r then
  61. ratel:=delete(r,ratel);
  62. if ratel then eval list('order,mkquote ratel);
  63. oldorder := setkorder append(ratel,cdr species);
  64. odel := 'list .
  65. for each x in odel collect
  66. list('equal,list('df,car x,'t),reval cdr x);
  67. setkorder oldorder;
  68. return odel;
  69. synerror:
  70. typerr(r,"reaction");
  71. end;
  72. symbolic procedure r2omat(sp,lhsl,rhsl);
  73. % construct input and output matrices in REDUCE syntax.
  74. begin scalar m; integer nreac,nspec,j;
  75. nspec := length sp; nreac:= length lhsl;
  76. apply ('matrix,list list list('inputmat,nreac,nspec));
  77. apply ('matrix,list list list('outputmat,nreac,nspec));
  78. for i:=1:nreac do
  79. << for each x in nth(lhsl,i) do
  80. <<j:=r2findindex(cdr x,sp);
  81. setmatelem(list ('inputmat,i,j),car x);
  82. >>;
  83. for each x in nth(rhsl,i) do
  84. <<j:=r2findindex(cdr x,sp);
  85. setmatelem(list ('outputmat,i,j),car x);
  86. >>;
  87. >>;
  88. end;
  89. symbolic procedure r2findindex(a,l); r2findindex1(a,l,1);
  90. symbolic procedure r2findindex1(a,l,n);
  91. if null l then rederr "index not found" else
  92. if a=car l then n else r2findindex1(a,cdr l,n+1);
  93. symbolic procedure r2speclist u;
  94. % convert lhs/rhs to a list of pairs (multiplicity . spec).
  95. <<u:=if eqcar(u,'plus) then cdr u else list u;
  96. for each x in u collect r2speclist1 x>>;
  97. symbolic procedure r2speclist1 x;
  98. if eqcar(x,'times) then r2speclist2(cadr x,caddr x,cdddr x)
  99. else 1 . x;
  100. symbolic procedure r2speclist2(x1,x2,rst);
  101. if not null rst or not fixp x1 and not fixp x2 then
  102. typerr(append(list('times,x1,x2),rst),"species") else
  103. if fixp x1 then x1.x2 else x2.x1;
  104. symbolic procedure r2oaddspecies(s,odel);
  105. % generate a new (empty) equation for a new species.
  106. if assoc(s,odel) then odel else
  107. <<prin2 "new species: ";prin2t s;
  108. append(odel,list(s.0))>>;
  109. symbolic procedure r2oreaction(lhs,rhs,k,odel);
  110. % add the contribution of one reaction to the ode's.
  111. begin scalar coeff,e;
  112. coeff := k;
  113. for each x in lhs do
  114. coeff:=aeval list('times,coeff,list('expt,cdr x,car x));
  115. for each x in lhs do
  116. <<e := assoc(cdr x,odel);
  117. rplacd(e,reval list('difference,cdr e,list('times,coeff,car x)))
  118. >>;
  119. for each x in rhs do
  120. <<e := assoc(cdr x,odel);
  121. rplacd(e,reval list('plus,cdr e,list('times,coeff,car x)))
  122. >>;
  123. return odel;
  124. end;
  125. endmodule;
  126. end;