>>> ## <--- 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)