vector-fields.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. ;;; A vector field is an operator that takes a smooth real-valued
  21. ;;; function of a manifold and produces a new function on the manifold
  22. ;;; which computes the directional derivative of the given function at
  23. ;;; each point of the manifold.
  24. (define (vector-field? vop)
  25. (and (operator? vop)
  26. (eq? (operator-subtype vop) 'vector-field)))
  27. ;;; As with other differential operators such as D, a vector-field
  28. ;;; operator multiplies by composition. Like D it takes the given
  29. ;;; function to another function of a point.
  30. (define* (procedure->vector-field vfp #:optional name)
  31. (if (default-object? name)
  32. (set! name 'unnamed-vector-field))
  33. (let ((the-field (make-operator vfp name 'vector-field)))
  34. (declare-argument-types! the-field (list function?))
  35. the-field))
  36. ;;; A vector field is specified by a function that gives components,
  37. ;;; as an up tuple, relative to a coordinate system, for each point,
  38. ;;; specified in the given coordinate system.
  39. (define* ((vector-field-procedure components coordinate-system) f)
  40. (compose (* (D (compose f (coordinate-system '->point)))
  41. components)
  42. (coordinate-system '->coords)))
  43. (define* (components->vector-field components coordinate-system #:optional name)
  44. (if (default-object? name) (set! name `(vector-field ,components)))
  45. (procedure->vector-field
  46. (vector-field-procedure components coordinate-system)
  47. name))
  48. ;;; We can extract the components function for a vector field, given a
  49. ;;; coordinate system.
  50. (define* ((vector-field->components vf coordinate-system) coords)
  51. (assert (vector-field? vf) "Bad vector field: vector-field->components")
  52. ((vf (coordinate-system '->coords))
  53. ((coordinate-system '->point) coords)))
  54. (define (vf:zero f) zero-manifold-function)
  55. (define (vf:zero-like op)
  56. (assert (vector-field? op) "vf:zero-like")
  57. (make-op vf:zero
  58. 'vf:zero
  59. (operator-subtype op)
  60. (operator-arity op)
  61. (operator-optionals op)))
  62. (define %calculus-vector-fields-dummy-1
  63. (assign-operation 'zero-like vf:zero-like vector-field?))
  64. (define (vf:zero? vf)
  65. (assert (vector-field? vf) "vf:zero?")
  66. (eq? (operator-procedure vf) vf:zero))
  67. (define %calculus-vector-fields-dummy-2
  68. (assign-operation 'zero? vf:zero? vector-field?))
  69. ;;; It is often useful to construct a literal vector field
  70. (define (literal-vector-field name coordinate-system)
  71. (let ((n (coordinate-system 'dimension)))
  72. (let ((function-signature
  73. (if (fix:= n 1) (-> Real Real) (-> (UP* Real n) Real))))
  74. (let ((components
  75. (s:generate n 'up (lambda (i)
  76. (literal-function (string->symbol
  77. (string-append
  78. (symbol->string name)
  79. "^"
  80. (number->string i)))
  81. function-signature)))))
  82. (components->vector-field components coordinate-system name)))))
  83. ;;; For any coordinate system we can make a coordinate basis.
  84. (define* ((coordinate-basis-vector-field-procedure coordinate-system . i) f)
  85. (compose ((apply partial i) (compose f (coordinate-system '->point)))
  86. (coordinate-system '->coords)))
  87. (define (coordinate-basis-vector-field coordinate-system name . i)
  88. (procedure->vector-field
  89. (apply coordinate-basis-vector-field-procedure coordinate-system i)
  90. name))
  91. #|
  92. (define (coordinate-system->vector-basis coordinate-system)
  93. (s:map (lambda (chain)
  94. (apply coordinate-basis-vector-field
  95. coordinate-system
  96. `(e ,@chain)
  97. chain))
  98. (coordinate-system 'dual-chains)))
  99. |#
  100. (define (coordinate-system->vector-basis coordinate-system)
  101. (coordinate-system 'coordinate-basis-vector-fields))
  102. #|
  103. ;;; Doesn't work.
  104. (define ((coordinate-system->vector-basis-procedure coordinate-system) f)
  105. (compose (D (compose f (coordinate-system '->point)))
  106. (coordinate-system '->coords)))
  107. |#
  108. ;;; Given a vector basis, can make a vector field as a linear
  109. ;;; combination. This is for any basis, not just a coordinate basis.
  110. ;;; The components are evaluated at the point, not the coordinates.
  111. (define (basis-components->vector-field components vector-basis)
  112. (procedure->vector-field
  113. (lambda (f)
  114. (lambda (point)
  115. (* ((vector-basis f) point)
  116. (components point))))
  117. `(+ ,@(map (lambda (component basis-element)
  118. `(* ,(diffop-name component)
  119. ,(diffop-name basis-element)))
  120. (s:fringe components)
  121. (s:fringe vector-basis)))))
  122. ;;; And the inverse
  123. (define (vector-field->basis-components v dual-basis)
  124. (s:map/r (lambda (w) (w v)) dual-basis))
  125. #|
  126. ;;; This does not make a vector field, because of operator.
  127. (define (((basis-components->vector-field components vector-basis) f) point)
  128. (* ((vector-basis f) point)
  129. (components point)))
  130. ;;; We note problems, due to tuple arithmetic
  131. (define (basis-components->vector-field components vector-basis)
  132. (* vector-basis components))
  133. |#
  134. #|
  135. (install-coordinates R3-rect (up 'x 'y 'z))
  136. (pec (((* (expt d/dy 2) x y d/dx) (* (sin x) (cos y)))
  137. ((R3-rect '->point)(up 'a 'b 'c))))
  138. #| Result:
  139. (+ (* -1 a b (cos a) (cos b)) (* -2 a (sin b) (cos a)))
  140. |#
  141. |#
  142. #|
  143. (define counter-clockwise (- (* x d/dy) (* y d/dx)))
  144. (define outward (+ (* x d/dx) (* y d/dy)))
  145. (define mr ((R3-rect '->point) (up 'x0 'y0 'z0)))
  146. (pec ((counter-clockwise (sqrt (+ (square x) (square y)))) mr))
  147. #| Result:
  148. 0
  149. |#
  150. (pec ((counter-clockwise (* x y)) mr))
  151. #| Result:
  152. (+ (expt x0 2) (* -1 (expt y0 2)))
  153. |#
  154. (pec ((outward (* x y)) mr))
  155. #| Result:
  156. (* 2 x0 y0)
  157. |#
  158. |#
  159. #|
  160. ;;; From McQuistan: Scalar and Vector Fields, pp. 103-106
  161. ;;; We apparently need cylindrical coordinates too.
  162. (install-coordinates R3-cyl (up 'r 'theta 'zeta))
  163. (define A (+ (* 'A_r d/dr) (* 'A_theta d/dtheta) (* 'A_z d/dzeta)))
  164. (pec ((vector-field->components A R3-rect) (up 'x 'y 'z)))
  165. #| Result:
  166. (up (+ (* -1 A_theta y) (/ (* A_r x) (sqrt (+ (expt x 2) (expt y 2)))))
  167. (+ (* A_theta x) (/ (* A_r y) (sqrt (+ (expt x 2) (expt y 2)))))
  168. A_z)
  169. |#
  170. ;;; This disagrees with McQuistan. Explanation follows.
  171. (pec ((d/dtheta (up x y z))
  172. ((R3-rect '->point) (up 'x 'y 'z))))
  173. #| Result:
  174. (up (* -1 y) x 0)
  175. |#
  176. ;;; has length (sqrt (+ (expt x 2) (expt y 2)))
  177. (pec ((d/dr (up x y z))
  178. ((R3-rect '->point) (up 'x 'y 'z))))
  179. #| Result:
  180. (up (/ x (sqrt (+ (expt x 2) (expt y 2))))
  181. (/ y (sqrt (+ (expt x 2) (expt y 2))))
  182. 0)
  183. |#
  184. ;;; has length 1
  185. (pec ((d/dz (up x y z))
  186. ((R3-rect '->point) (up 'x 'y 'z))))
  187. #| Result:
  188. (up 0 0 1)
  189. |#
  190. ;;; has length 1
  191. ;;; so these coordinate basis vectors are not normalized
  192. ;;; Introduce
  193. (define e-theta (* (/ 1 r) d/dtheta))
  194. (define e-r d/dr)
  195. (define e-z d/dzeta)
  196. ;;; then
  197. (define A (+ (* 'A_r e-r) (* 'A_theta e-theta) (* 'A_z e-z)))
  198. (pec ((vector-field->components A R3-rect) (up 'x 'y 'z)))
  199. #| Result:
  200. (up
  201. (+ (/ (* A_r x) (sqrt (+ (expt x 2) (expt y 2))))
  202. (/ (* -1 A_theta y) (sqrt (+ (expt x 2) (expt y 2)))))
  203. (+ (/ (* A_r y) (sqrt (+ (expt x 2) (expt y 2))))
  204. (/ (* A_theta x) (sqrt (+ (expt x 2) (expt y 2)))))
  205. A_z)
  206. |#
  207. ;;; now agrees with McQuistan.
  208. |#
  209. #|
  210. (pec ((vector-field->components d/dy R3-rect)
  211. (up 'x0 'y0 'z0)))
  212. #| Result:
  213. (up 0 1 0)
  214. |#
  215. (pec ((vector-field->components d/dy R3-rect)
  216. (up 'r0 'theta0 'z0)))
  217. #| Result:
  218. (up 0 1 0)
  219. |#
  220. (pec ((vector-field->components d/dy R3-cyl)
  221. (up 1 pi/2 0)))
  222. #| Result:
  223. (up 1. 6.123031769111886e-17 0)
  224. |#
  225. (pec ((vector-field->components d/dy R3-cyl)
  226. (up 1 0 0)))
  227. #| Result:
  228. (up 0 1 0)
  229. |#
  230. (pec ((vector-field->components d/dy R3-cyl)
  231. (up 'r0 'theta0 'z)))
  232. #| Result:
  233. (up (sin theta0) (/ (cos theta0) r) 0)
  234. |#
  235. |#
  236. #|
  237. (define R3-point ((R3-rect '->point) (up 'x0 'y0 'z0)))
  238. ;;; The following does not work.
  239. ;;; One cannot add to a manifold point.
  240. (series:print
  241. (((exp (* x d/dy))
  242. (literal-function 'f (-> (UP Real Real Real) Real)))
  243. R3-point)
  244. 4)
  245. #|
  246. (f #[manifold-point 42])
  247. ;Wrong type argument -- LITERAL-FUNCTION
  248. |#
  249. |#
  250. ;;; However, one can make a coordinate version of a vector field
  251. (define (coordinatize sfv coordsys)
  252. (define (v f)
  253. (lambda (x)
  254. (let ((b
  255. (compose (sfv (coordsys '->coords))
  256. (coordsys '->point))))
  257. (* ((D f) x) (b x)))))
  258. (make-operator v))
  259. #|
  260. (pec
  261. (((coordinatize (literal-vector-field 'v R3-rect) R3-rect)
  262. (literal-function 'f (-> (UP Real Real Real) Real)))
  263. (up 'x0 'y0 'z0)))
  264. #| Result:
  265. (+ (* (((partial 0) f) (up x0 y0 z0)) (v^0 (up x0 y0 z0)))
  266. (* (((partial 1) f) (up x0 y0 z0)) (v^1 (up x0 y0 z0)))
  267. (* (((partial 2) f) (up x0 y0 z0)) (v^2 (up x0 y0 z0))))
  268. |#
  269. ;;; Consider the following vector field
  270. (define circular (- (* x d/dy) (* y d/dx)))
  271. ;;; The coordinate version can be exponentiated
  272. (series:for-each print-expression
  273. (((exp (coordinatize (* 'a circular) R3-rect))
  274. identity)
  275. (up 1 0 0))
  276. 6)
  277. #|
  278. (up 1 0 0)
  279. (up 0 a 0)
  280. (up (* -1/2 (expt a 2)) 0 0)
  281. (up 0 (* -1/6 (expt a 3)) 0)
  282. (up (* 1/24 (expt a 4)) 0 0)
  283. (up 0 (* 1/120 (expt a 5)) 0)
  284. ;Value: ...
  285. |#
  286. |#
  287. ;;; We can use the coordinatized vector field to build an
  288. ;;; evolution along an integral curve.
  289. (define* ((evolution order)
  290. delta-t vector-field)
  291. (lambda (manifold-function)
  292. (lambda (manifold-point)
  293. (series:sum
  294. (((exp (* delta-t vector-field))
  295. manifold-function)
  296. manifold-point)
  297. order))))
  298. #|
  299. (install-coordinates R2-rect (up 'x 'y))
  300. (define circular (- (* x d/dy) (* y d/dx)))
  301. (pec
  302. ((((evolution 6) 'a circular) (R2-rect '->coords))
  303. ((R2-rect '->point) (up 1 0))))
  304. #| Result:
  305. (up (+ (* -1/720 (expt a 6))
  306. (* 1/24 (expt a 4))
  307. (* -1/2 (expt a 2))
  308. 1)
  309. (+ (* 1/120 (expt a 5))
  310. (* -1/6 (expt a 3))
  311. a)
  312. 0)
  313. |#
  314. |#