>>> ## <--- C-d を入れる Process Python[ ... ] finishedという表示が出ればOK. この状態でもう一度 C-c C-z からやり直せば, その時は同じになるはずです.
$ python a.pyのようにした場合は, 毎回pythonは「何も知らない(新たに定義されていない)状態」から始めるのに対し, Emacsのbufferを用いている場合, 過去にC-c C-c で入力したり, 直接プロンプト(>>>)に入力したものは, 明示的に終了するまで覚えているということです. つまりEmacsのbufferを 用いているのは実際には,
$ python >>>とやって, C-c C-cを打つたびに, >>> に向かって ファイルの内容を全て入力しているのに近いです.
$ python a.pyとした場合は, f(x)を消した以降の実行ではfは使えません(まともな動作と言えます)が, Emacs上で続けて実行しているときは, C-d で修了するまで, fは残り続けます. 本当は消してはいけないものを間違えて消してしまった, などという時にそれに気づかない, ということが起こりえます
時間がなくてやらなかった7-3 (バネに吊るされた質点のシミュレーション)を解説します. 他と比べて極端に難しいわけではないですが, 他の人の解答を見るのはためになるということで, それに1つ追加というつもりです.中々慣れないという人のために, 思考過程を示します.
問題は以下でした.
バネで吊るされた質点に,時間と共に変わる外力 f(t) を与えたときの運動を Visual Python を用いて アニメーションせよ(t は時刻, f(t) は垂直方向のベクトル). バネ定数k, 質点の質量が m で,初期状態は自然長の位置に停止しているとする.
y'' = - k/m y - g(y'' は yを2階時間で微分したもの. ややこしい式がHP上で書くのが困難なのでこの記号で)
def spring(k, m): y = 初期位置 y_ = 初期速度 for ... : alpha = -k / m * y - g y = y + y_ * dt y_ = y_ + alpha * dt以下は上記でごまかしているところをなくした,一応動くコードです.
def spring(k, m): y = 0 y_ = 0 g = 9.8 T = 50.0 # 目標時刻 n_steps = 1000 dt = T / n_steps for i in range(n_steps): alpha = -k * y / m - g y = y + y_ * dt y_ = y_ + alpha * dt
def spring(k, m): s = sphere(pos=vector(0,0,0), vel=vector(0,0,0)) h = helix(pos=vector(0,30,0)) h.axis = s.pos - h.pos g = vector(0, 9.8, 0) T = 50.0 # 目標時刻 n_steps = 1000 dt = T / n_steps for i in range(n_steps): rate(1.0 / dt) s.alpha = -k * s.pos / m - g s.pos = s.pos + s.vel * dt s.vel = s.vel + s.alpha * dt h.axis = s.pos - h.posやってみるとバネが細すぎるとか,いくつか見てくれの悪いところが 見つかりますがここでは目をつぶります.
def spring(k, m, f): s = sphere(pos=vector(0,0,0), vel=vector(0,0,0)) h = helix(pos=vector(0,30,0)) h.axis = s.pos - h.pos g = vector(0, 9.8, 0) T = 50.0 # 目標時刻 n_steps = 1000 dt = T / n_steps t = 0 for i in range(n_steps): rate(1.0 / dt) s.alpha = -k * s.pos / m + f(t) / m - g s.pos = s.pos + s.vel * dt s.vel = s.vel + s.alpha * dt h.axis = s.pos - h.pos t = t + dt
#!/usr/bin/python # -*- encoding: utf-8 -*- import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np import math,time # 復習: アニメなしで y = sin(x) def static_1d(): x = np.linspace(0.0, math.pi, 100) y = np.sin(x) plt.plot(x, y) plt.show() # アニメあり y = sin(kx) を k を色々変えながら表示 def anime_1d(): x = np.linspace(0.0, 2.0 * math.pi, 100) # 一度だけプロットして曲線を得る [line] = plt.plot(x, np.sin(x)) for k in range(10): # plotする代わりにデータをセットする y = np.sin(k * x) line.set_data(x, y) # 再描画して欲しいところで yield 変更された曲線のリスト yield [line] # おまじない(コピペして下さい) def go_animation(iterator, **kwargs): def anime_fun(*args): try: return iterator.next() except StopIteration: return [] ani = animation.FuncAnimation(plt.gcf(), anime_fun, **kwargs) plt.show() # sin(kx) のグラフが徐々に変わっていく go_animation(anime_1d(), interval=100)
#!/usr/bin/python # -*- encoding: utf-8 -*- import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np import math,time # 復習 def static_2d(): x = np.linspace(0.0, 1.0, 100) y = np.linspace(0.0, 1.0, 100) x,y = np.meshgrid(x, y) z = x * x + y * y plt.pcolor(x, y, z) plt.show() def shrink(z): m,n = z.shape return z[:m-1,:n-1].reshape((m - 1) * (n - 1)) # アニメあり def anime_2d(): x = np.linspace(0.0, 1.0, 100) y = np.linspace(0.0, 1.0, 100) x,y = np.meshgrid(x, y) z = x * x + y * y field = plt.pcolor(x, y, z) for k in np.linspace(0.0, 1.0, 100): # plotする代わりにデータをセットする z = (x - k) * (x - k) + (y - k) * (y - k) field.set_array(shrink(z)) # 再描画して欲しいところで yield 変更された曲線のリスト yield [field] # おまじない(コピペして下さい) def go_animation(iterator, **kwargs): def anime_fun(*args): try: return iterator.next() except StopIteration: return [] ani = animation.FuncAnimation(plt.gcf(), anime_fun, **kwargs) plt.show() # 2次元の色の場が徐々に変わっていく go_animation(anime_2d(), interval=100)