ode-advancer.scm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. #!fold-case
  21. (declare (usual-integrations))
  22. ;;; Default settings
  23. ;;; FBE: make a parameter
  24. (define *ode-integration-method* (make-parameter 'BULIRSCH-STOER))
  25. ;;; (set! *ode-integration-method* 'QCRK4)
  26. ;;; (set! *ode-integration-method* 'BULIRSCH-STOER)
  27. ;;; (set! *ode-integration-method* 'QCCTRAP2)
  28. ;;; (set! *ode-integration-method* 'GEAR)
  29. (define *first-step-scale* 1.0)
  30. (define *corrector-convergence-margin* 1.0e-1)
  31. (define *progress-monitor* #f)
  32. (define *last-state*)
  33. ;;; ode-advancer returns a procedure of the form
  34. ;;; (lambda (state dt continue) ...)
  35. ;;; where
  36. ;;; continue=(lambda (new-state dt-obtained dt-suggested) ...)
  37. #|
  38. (pe ((ode-advancer
  39. (lambda (s) (up 1 (ref s 1)))
  40. 1.e-12
  41. 2)
  42. (up 0 1)
  43. 1
  44. list))
  45. ((up 1. 2.718281828459047) 1 1.5)
  46. |#
  47. (define (ode-advancer sysder local-error-tolerance dimension)
  48. (case (*ode-integration-method*)
  49. ((bulirsch-stoer)
  50. (bs-advancer sysder local-error-tolerance dimension))
  51. ((qcrk4)
  52. (qcrk4-advancer sysder local-error-tolerance))
  53. ((qcctrap2)
  54. (qc-ctrap-advancer sysder local-error-tolerance))
  55. ((qcceuler)
  56. (qc-ceuler-advancer sysder local-error-tolerance))
  57. ((explicit-gear)
  58. ;; actually sysder here is f&df
  59. (gear-advancer sysder local-error-tolerance dimension))
  60. (else
  61. (write-line `(methods: bulirsch-stoer qcrk4 qcctrap2 qcceuler explicit-gear))
  62. (error "Unknown ode integrator" (*ode-integration-method*)))))
  63. (define (set-ode-integration-method! method)
  64. (case method
  65. ((BULIRSCH-STOER bulirsch-stoer Bulirsch-Stoer)
  66. (*ode-integration-method* 'bulirsch-stoer))
  67. ((QCRK4 qcrk4)
  68. (*ode-integration-method* 'qcrk4))
  69. ((QCCTRAP2 qcctrap2)
  70. (*ode-integration-method* 'qcctrap2))
  71. ((QCCEULER qcceuler)
  72. (*ode-integration-method* 'qcceuler))
  73. ((Gear Explicit-Gear gear explicit-gear GEAR)
  74. ;; actually sysder here is f&df
  75. (*ode-integration-method* 'explicit-gear))
  76. (else
  77. (write-line
  78. `(available methods: bulirsch-stoer qcrk4 qcctrap2 qcceuler explicit-gear))
  79. (display
  80. "Note: for x' = f(x), Gear needs f&df, all others need only f.")
  81. (newline)
  82. `(currently: ,(*ode-integration-method*)))))
  83. (define (advance-monitor ns step-achieved step-suggested cont)
  84. (if *progress-monitor* (pp `(,ns ,step-achieved ,step-suggested)))
  85. (set! *last-state* ns)
  86. (cont))
  87. (define (final-step-monitor ns step-achieved step-suggested)
  88. (if *progress-monitor* (pp `(,ns ,step-achieved ,step-suggested)))
  89. (set! *last-state* ns)
  90. ns)
  91. (define (bs-advancer sysder local-error-tolerance dimension)
  92. (bulirsch-stoer-lisptran ;integrator
  93. (system-derivative->lisptran-derivative sysder)
  94. dimension
  95. local-error-tolerance))
  96. (define (qcrk4-advancer sysder local-error-tolerance)
  97. ((quality-control rk4 4)
  98. sysder
  99. local-error-tolerance))
  100. (define (qc-ctrap-advancer sysder local-error-tolerance)
  101. ((quality-control c-trapezoid 2)
  102. sysder
  103. local-error-tolerance
  104. (* *corrector-convergence-margin*
  105. local-error-tolerance)))
  106. (define (qc-ceuler-advancer sysder local-error-tolerance)
  107. ((quality-control c-euler 1)
  108. sysder
  109. local-error-tolerance
  110. (* *corrector-convergence-margin*
  111. local-error-tolerance)))
  112. (define (gear-advancer f&df local-error-tolerance dimension)
  113. (gear-stepper-generator
  114. f&df
  115. dimension
  116. local-error-tolerance))
  117. (define (gear? method)
  118. (memq method '(Gear Explicit-Gear gear explicit-gear GEAR)))