情報活用基礎 Information Literacy 2019

簡易プログラム環境を用いた物理学の計算

この実習では Processing を使用します。 Processing は、高度なプログラム言語であるPythonと同様の言語体系を持ち、 同時に容易にグラフィックを描ける利便性を兼ね備えており、 プログラムの初歩を学ぶにはとても適切なアプリケーションです。 簡単な目的の計算なら十分にこなす事ができ、 また高度なプログラム環境に移行する必要が生じても、 Processing で勉強した事が無駄になりません。 皆さんの今後の学習にきっと役立つと思います。

この実習では、Processing の使い方の初歩から始めて、 物理学の基本である、ニュートン方程式を数値的に解き、 色々な物理現象が1つの基本原理と1つの解法で説明できる事を体験して頂きます。


注意

情報教育システムにはv3.3.5のProcessingが既にインストールされています。 この実習ではこれを利用して頂きます。

もし自宅のPC等で使用したい場合は、オリジナルサイトから ダウンロードして使う事も可能です。 但し、オリジナルサイトでは最新のv3.5.3があります。バージョンが異なると動作や使い方が変わることがあるので、注意が必要です。

また、レポートで使用するバージョンは情報教育システムと同じバージョンとします。 これは公平性を保つためです。 皆さんが各自でより進んだ内容を勉強する事は大変よいことではありますが、 レポートで使用できるのはv3.3.5である事を忘れないで下さい。


課題1(起動とコンソール出力)

クイック起動バーから「Devel」→「processing」を選択して起動します。

中ほどの白い部分にプログラムを書く。 まずは以下のプログラムを打ち込んでみよ。構文に慣れるために、コピー&ペーストは使用しないこと。


for i in range(11):
println(i)

		
左上に、丸の中に三角があるボタンが、プログラムを走らせるボタンである。押して見よ。

下方の黒い部分に文字の出力が行われる。ここに、0から10の整数が表示された事を確認せよ。

先程のボタンの1つ右にある、丸の中に四角があるボタンがプログラムを止めるボタンである。 押して、プログラムを止めよ。

プログラムの中にある for 文は、繰り返しを行うための構文である。 左から、

である。初期値と終了値を適当に修正し、挙動の変化を確認せよ。

もし終了条件を絶対に満たさないようなプログラムにして実行してしまうと、 当然であるが、プログラムは止まらない。この状況になっても「停止ボタン」を 押して、止める事ができる。

入力している途中で、灰色の部分が赤くなり、そこにエラーメッセージが表示される場合がある。 人間が入力している途中では、一時的に間違った文になるのは当たり前なので、気にしなくてよい。 但し、入力が完了した場合でもエラーメッセージが出ている場合は、それをよく読んで対応すること。 しかし、エラーメッセージが常に適切な指摘をしてくれる訳ではない事にも留意せよ。

尚、初心者はエラーメッセージの内容が理解できない事が多い。 恐らくこういう意味だろうと思って試してみるのは良い事であるが、 一方で、やみくもに多くを試してみるのは効率的ではない。 意味をよく推察してみて、それでも分からない場合は、TAに聞いて下さい。


課題2(描画1)

以下のプログラムを入力して実行してみよ。 コピー&ペーストは使用しないこと。


size(800,600)

for i in range(350):
	print "X=",i*2,"Y=",i
	point(i*2,i)

		
size 文で、描画する範囲を横800ピクセル、縦600ピクセルに指定している。

i を0から349まで、1つづ増やしながら、 X座標はiの2倍、Y座標はiの位置に、点を描画している。 X,Yの値は数値でも出力している。

点が小さくて見にくい場合は、point の代わりに、ellipse を使うと見やすくなる。

  ellipse( i*2, i, 1, 1);

ellipse は楕円を描画する関数である。半径の小さな楕円を描く事で、大きな点を描画している。

以下の事をやってみよ。

尚、Processingで使用できる関数等の説明が

にある。意味が分からないものはこれで調べて見よ。尚、オリジナルサイトや検索サイトなどで調べた場合は、 異なるバージョンの説明が表示されることがあるので、注意せよ。


課題3(描画2)

以下のプログラムを入力して実行してみよ。 コピー&ペーストは使用しないこと。


def setup():
	size(600,600)
	print "width=",width,"height=",height
	frameRate(30)
	line(sx(-100),sy(0),sx(+100),sy(0))
	line(sx(0),sy(-100),sx(0),sy(100))

x1=float(-100.0)
y1=float(-100.0)
x2=float(+100.0)
y2=float(+100.0)

def sx(x):
	return width*(x-x1)/(x2-x1)

def sy(y):
	return height*(y2-y)/(y2-y1)

x=float(0.0)

def draw():
	global x
	global i


	y=0.01*x*x

	print "X=",x,"Y=",y
	point(sx(x),sy(y)) # elipse(sx(x),sy(y),1,1)
	x+=1.0

	if x>100.0:
		noLoop()

		
9~13行は、座標変換のお膳立てをしている。 size 文で宣言された600×600ピクセルのスクリーンは、いわばXが1~600、Yが1~600の 座標を持っていると言える。但し、Yは下が大きい事に留意せよ。 これだと我々が自由に座標系を使えない。そこで、計算で使用する座標系からスクリーンに表示する座標系への 変換を考える。このプログラムでは計算で使用するXは、-100.0から+100.0まで、 Yも同じ範囲とし、Y軸は上が大きくなるように方向を逆転させる、一次変換を行う関数を定義している。

この関数はX,Y毎に1つづつ定義されている。 計算に使用する座標系は9~10行目で定義されている。 変換に必要なスクリーンのピクセル数は、size 文の実行後に、自動的に、width, height という変数に代入されている。

この関数は、下から4行目の point 関数で使用されている。 この様にすると、point関数が計算座標系のX、Yを引数に持っているかのごとく使える。

プログラムでは、2次関数を計算、描画している。

Xを0から1づつ増やし、100を超えたらループを終了している。 Xの初期値、終了条件、増分、関数形等を変更して、色々試してみよ。

setup関数はプログラムの最初に1度だけ実行される。

draw関数は、何もしなければ、自動的に無限回、実行される。 繰り返し計算し、その結果を描画する場合には、draw関数の中に、1回分の描画するプログラムを書けば、 それを繰り返してくれる。但し、パラメータの更新や、終了条件の判断は自分で書く必要がある。

関数形を変えて、異なるグラフを描け。

初期値、終わり値を変えてみよ。

スクリーンの大きさを変えてみよ。また、計算に使う座標系も変えてみよ。

draw関数はsetup関数の中でframeRate関数で設定された頻度で繰り返される。 このプログラムでは3回/秒としてある。この数値を変えてみよ。


課題4(乱数を用いた数値計算(モンテカルロ(Monte Carlo)法)

以下のプログラムを入力して実行してみよ。 これ以降、コピー&ペーストを使用してもよいが、 プログラムの中身をしっかりと 読んで、理解する事。

		

import math
import random

def setup():
	size(600,600)
	print "width=",width,"height=",height
	frameRate(1000)
	colorMode(RGB)

x1=float(-1.0)
y1=float(-1.0)
x2=float(+1.0)
y2=float(+1.0)

def sx(x):
	return width*(x-x1)/(x2-x1)

def sy(y):
	return height*(y2-y)/(y2-y1)


random.seed()

s=float(0)
n=int(50000)
i=int(0)

def f(x,y):
	return x**2+y**2

def draw():

	global s
	global n
	global i

	x=random.uniform(-1,1)
	y=random.uniform(-1,1)

	if f(x,y)<=1:
		s+=1
		stroke(0,255,0)
		ellipse(sx(x),sy(y),2,2)

		else:
		stroke(0,0,255)
		ellipse(sx(x),sy(y),2,2)

		i+=1

		if i>=n:
		noLoop()

		pi=float(4*s/n)

		print "pi=",pi

		
このプログラムは、規則性のない数(乱数)を[-1,1]の区間で2つ(x,y)生成しその数の二乗和、 つまり原点からの距離が円の半径(1)よりも大きいかを判定を行なっている。

この事象判定を複数回(50000)程行う事で、50000回中何回円の内部に点が生成されたか(確率)を計算している。 今回の例では、まず上の確率を計算し、乱数(x,y)の定義域である正方形2×2の面積で規格化する事で円の面積を求めている。 円の半径は1であるので、円の面積が"π"になることを利用することで円周率を見積もっている。

→(乱数の定義域で表される正方形の面積 : 4)/(乱数の生成回数 : 50000)・(円内側に入った回数 : s)

このように、乱数を複数回生成する事で面積を見積もったり、自然界の崩壊現象などを擬似的に再現する事がある。 例えば、放射線検出器に放射線が入射する確率は、放射線検出器と放射線線源の距離や放射線検出器の形などに依存し、手計算で求める時が難しい。 その時、放射線検出器の形を再現し、放射線線源の崩壊を乱数を用いて再現する事で擬似的に放射線が放射線検出器に入射することを再現する事が可能である。


課題5(放物運動)

以下のプログラムを入力して実行してみよ。 これ以降、コピー&ペーストを使用してもよいが、 プログラムの中身をしっかりと 読んで、理解する事。


import math
def setup():
	size(600, 600)
	#frameRate(3)
	line(sx(-1000),sy(0),sx(+1000),sy(0))
	line(sx(0),sy(-1000),sx(0),sy(+1000))



x1=float(-1.0)
y1=float(-100.0) 
x2=float(+10.0)
y2=float(+10.0)
def sx(x):
 return width *(x-x1)/(x2-x1)

def sy(y):
	return height*(y2-y)/(y2-y1)


m=float(1)   #weight
x0=float(0.0)  #initial position of x
y0=float(0.0)  #initial position of y
vx0=float(10.0) #initial velocity of x
vy0=float(10.0) #initial velocity of y
dt=float(0.0050)


x=x0
y=y0
vx=vx0
vy=vy0
t=0.0
i=int(0)
g=float(-9.8)

def draw():
	strokeWeight(3)
	global g
	global x
	global y
	global vx
	global vy
	global t
	global i 

	#    point(sx(t),sy(vx))
	#    point(sx(t),sy(vy))
	#    point(sx(t),sy(x))
	point(sx(t),sy(y))
	#    point(sx(x),sy(y))
	print "vx=",vx,"vy=",vy,"x=",x,"y=",y,"t=",t

	t=t+dt
	vx=vx
	vy=vy+g*dt  
	x=x+vx*dt
	y=y+vy*dt


	i=i+1

	if i>2000:
		noLoop()


		
このプログラムは、質点の放物運動を数値計算で解いている。

物理学で言う、数値計算で問題が「解けた」とは、

をいう。

重力加速度は、-9.8m/s/s(下方へなので符号は負)とし、 質点を座標(0m,0m)から初速度(10m/s、10m/s)で飛ばした時の運動を追跡している。

時間の刻みは0.01秒とし、ある時刻から次の時刻の速度と座標は以下のように求めている。

Vx ← Vx
Vy ← Vy + g・Δt

X ← X + Vx・Δt
Y ← Y + Vy・Δt

これらの式は、速度と加速度の定義から分かると思う。

Vx(t) = ( X(t+Δt) - X(t) ) / Δt (Δt→0)
Ax(t) = ( Vx(t+Δt) - Vx(t) ) / Δt (Δt→0)

この様に1次の極限での近似を用いて数値積分する方法を、オイラー法という。

プログラムの最後の方に、X軸とY軸に何を描画するかが、何行かに渡り書いてあり、 1つを除きコメントアウトされている。これらをそれぞれ描画し、計算の結果を確認せよ。 初速度を変えて試してみよ。

このように、物理現象をシミュレーションする場合には、物理法則に関わる部分には一切修正を加えず、 初期値等の条件を変更する事で、様々な物理現象を再現できる。

Δtは0.01秒で計算したが、これを0.02秒に粗くしてみよ。 グラフでは分からない程度の差しかでないので、出力された数値を比較して、計算誤差が変化する事を確認せよ。

#(シャープ)は、コメント機能である。この記号から行末までは、コメントとなり、プログラムの実行に何の影響も与えない。 また、''' コメント ''' という構造を使用すれば、複数行にまたがったコメントも作成できる。


課題6(地球の公転)

以下のプログラムを入力して実行してみよ。 これ以降、コピー&ペーストを使用してもよいが、 プログラムの中身をしっかりと 読んで、理解する事。


import math

def setup():
	size(600, 600)
	frameRate(1000)
	colorMode(RGB)
	background(0,0,0)
	stroke(255,0,0)
	fill(255,0,0)
	ellipse(sx(0),sy(0),5,5)
	stroke(0,255,0)
	fill(0,255,0)



x1=float(-1.6e11)
y1=float(-1.6e11) 
x2=float(+1.6e11)
y2=float(+1.6e11)
def sx(x):
 return width *(x-x1)/(x2-x1)
def sy(y):
 return height*(y2-y)/(y2-y1) 


t=float(0.0)
dt=float(80000.0)
x=float(1.496e11)
y=float(0.0)
vx=float(0.0)
vy=float(2.979e4)
G=float(6.67384e-11)
Ms=float(1.989e30)

i=int(0)


def draw():
	global x
	global y
	global t
	global i
	global vx
	global vy
	global G
	global Ms

	print "vx=",vx,"vy=",vy,"x=",x,"y=",y,"t=",t
	point(sx(x),sy(y))
	t=t+dt
	r3=(x**2+y**2)**1.5
	vx=vx-G*Ms*dt*x/r3
	vy=vy-G*Ms*dt*y/r3
	x=x+vx*dt
	y=y+vy*dt

	i+=1

	if i>10000:
		noLoop()

		
このプログラムは、太陽の周りを回る地球の動きをシミュレーションしている。

最初の方で、色を指定している。

初期条件として、太陽と地球の距離、地球の速度は、現実的な値を入れてあるが、 この場合、綺麗に円軌道が再現できる。

初速度を変えると楕円軌道になる筈なので、やってみよ。

初速を半分(1.5e4)にすると楕円軌道がだんだんずれていってしまう。 これは計算誤差が蓄積するからである。dtの値を小さくすると計算誤差が減り、 より正しい結果を得られる事を確かめよ。

dtの値を小さくした場合は、frameRate で大きな値を指定すると速く計算する。 指定しなかった時の値は60である。


課題7(スイングバイ)

以下のプログラムを入力して実行してみよ。 これ以降、コピー&ペーストを使用してもよいが、 プログラムの中身をしっかりと 読んで、理解する事。

		

import math

def setup():
	size(600, 600)
	frameRate(100)
	background(0,0,0)
	stroke(255)
	colorMode(HSB,360,100,100)



x1=float(6.784e11)
y1=float(-1.e11) 
x2=float(+8.784e11)
y2=float(+1.e11)
def sx(x):
 return width *(x-x1)/(x2-x1)
def sy(y):
 return height*(y2-y)/(y2-y1) 


G=float(6.674e-11)
pi=float(math.pi)

######## Parameters to chanege an initial condition of the probe ########
theta=float(pi/3) #Direction if momentum
disp=float(1.8e10)     #Radial diplacement between Jupiter abd the probe
#########################################################################

def accel(m,r):
	return G*m/(r**2)

t=float(0.0)
dt=float(10000.0)
x_jup=float(7.784e11*math.cos(-pi/30))
y_jup=float(7.784e11*math.sin(-pi/30))
x_prb=float(7.784e11-disp)
y_prb=float(-7.0e10)
vx_jup=float(1.306e4*(-math.sin(-pi/30)))
vy_jup=float(1.306e4*math.cos(-pi/30))
vx_prb=float(1.0e4*math.cos(theta))
vy_prb=float(1.0e4*math.sin(theta))
m_sol=float(1.989e30)
m_jup=float(1.898e27)
m_prb=float(721.9) #voyger 1 & 2

ax_jup=float(0.0)
ay_jup=float(0.0)
ax_prb=float(0.0)
ay_prb=float(0.0)

## the sun stand still ##

i=int(0)

def draw():

	global t
	global dt
	global x_jup
	global y_jup
	global x_prb
	global y_prb
	global vx_jup
	global vy_jup
	global vx_prb
	global vy_prb
	global m_sol
	global m_jup
	global m_prb
	global ax_jup
	global ay_jup
	global ax_prb
	global ay_prb
	global i

	print "vx_prb=",vx_prb,"vy_prb=",vy_prb,"x_prb=",x_prb,"y_prb=",y_prb,"t=",t

	V_prb=float(vx_prb**2+vy_prb**2)

	stroke(0,0,99)
	point(sx(x_jup),sy(y_jup))
	stroke(180,99,99)
	point(sx(x_prb),sy(y_prb))

	r_sol_jup=float(math.sqrt(x_jup**2+y_jup**2))
	r_sol_prb=float(math.sqrt(x_prb**2+y_prb**2))
	r_jup_prb=float(math.sqrt((x_jup-x_prb)**2+(y_jup-y_prb)**2))

	ax_jup=float(-x_jup/r_sol_jup*accel(m_sol,r_sol_jup))
	ay_jup=float(-y_jup/r_sol_jup*accel(m_sol,r_sol_jup))
	ax_prb=float(-x_prb/r_sol_prb*accel(m_sol,r_sol_prb)+(x_jup-x_prb)/r_jup_prb*accel(m_jup,r_jup_prb))
	ay_prb=float(-y_prb/r_sol_prb*accel(m_sol,r_sol_prb)+(y_jup-y_prb)/r_jup_prb*accel(m_jup,r_jup_prb))

	vx_jup=float(vx_jup+ax_jup*dt)
	vy_jup=float(vy_jup+ay_jup*dt)
	vx_prb=float(vx_prb+ax_prb*dt)
	vy_prb=float(vy_prb+ay_prb*dt)

	x_jup=float(x_jup+vx_jup*dt)
	y_jup=float(y_jup+vy_jup*dt)
	x_prb=float(x_prb+vx_prb*dt)
	y_prb=float(y_prb+vy_prb*dt)

	i+=1

	if i>100000:
		noLoop()

		
このプログラムは、スイングバイをシミュレーションしている。 スイングバイについては、「講義資料(物理)追加」を参照せよ。

課題5は2体問題(2つの質点の運動を扱う)であったが、これは、太陽、木星、探査機の 3体問題である。尚、数学的には3体以上の厳密解はなく、高精度の結果を得るには数値的に 解くしか方法がない。また、3体ではあるが、太陽は座標原点に固定してある事に留意せよ。

「講義資料(物理)追加」を参照して、初期条件を変え、スイングバイが色々なパターンを 取る事を確認せよ。地球に帰還する軌道に載せたり、惑星軌道に載せたり、 次の惑星に向かったり、太陽系を脱出したりする事ができる。


課題8(ルンゲクッタ)

アルゴリズムを改良する事で計算精度を上げる方法がある。

まず、課題5のプログラムを修正して、dtを10000、vyの初期値を、1.0e4にして、 実行してみよ。実行に時間がかかるようになるので、コメントアウトしてある frameRate(1000) を有効にして、 速く計算させよ。 楕円軌道がだんだんずれていく事が分かる。厳密な解ではこれは起きない。

次に、同じ初期条件と時間ステップで、4次のルンゲクッタ法を用いたプログラムを実行してみる。

以下のプログラムを入力して実行してみよ。 これ以降、コピー&ペーストを使用してもよいが、 プログラムの中身をしっかりと 読んで、理解する事。

		
import math

def setup():
	size(600, 600)
	frameRate(1000)
	colorMode(RGB)
	background(0,0,0)
	stroke(255,0,0)
	fill(255,0,0)
	ellipse(sx(0),sy(0),5,5)
	stroke(0,255,0)
	fill(0,255,0)



x1=float(-1.6e11)
y1=float(-1.6e11) 
x2=float(+1.6e11)
y2=float(+1.6e11)
def sx(x):
 return width *(x-x1)/(x2-x1)
def sy(y):
 return height*(y2-y)/(y2-y1) 

t=float(0.0)
dt=float(10000.0)
x=float(1.496e11)
y=float(0.0)
vx=float(0.0)
vy=float(1.0e4)
G=float(6.67384e-11)
Ms=float(1.989e30)

i=0

def draw():

	global t
	global dt
	global x
	global y
	global vx
	global vy
	global G
	global Ms
	global i

	point(sx(x),sy(y))
	print "i=",i," t=",t," Vx=",vx," Vy=",vy," X=",x," Y=",y

	#    for j in range (10000):

	t=t+dt

	#step1

	r3=(x**2+y**2)**1.5
	ax=-G*Ms*x/r3
	ay=-G*Ms*y/r3

	k00=vx*dt
	k10=vy*dt
	k20=ax*dt
	k30=ay*dt 

	#step2

	r3=((x+0.5*k00)**2+(y+0.5*k10)**2)**1.5
	ax=-G*Ms*(x+0.5*k00)/r3
	ay=-G*Ms*(y+0.5*k10)/r3

	k01=(vx+0.5*k20)*dt
	k11=(vy+0.5*k30)*dt
	k21=ax*dt
	k31=ay*dt 

	#step3

	r3=((x+0.5*k01)**2+(y+0.5*k11)**2)**1.5
	ax=-G*Ms*(x+0.5*k01)/r3
	ay=-G*Ms*(y+0.5*k11)/r3

	k02=(vx+0.5*k21)*dt
	k12=(vy+0.5*k31)*dt
	k22=ax*dt
	k32=ay*dt 

	#step4

	r3=((x+k02)**2+(y+k12)**2)**1.5
	ax=-G*Ms*(x+k02)/r3
	ay=-G*Ms*(y+k12)/r3

	k03=(vx+k22)*dt
	k13=(vy+k32)*dt
	k23=ax*dt
	k33=ay*dt 

	#last

	vx=vx+(k20+2*k21+2*k22+k23)/6
	vy=vy+(k30+2*k31+2*k32+k33)/6
	x=x+(k00+2*k01+2*k02+k03)/6
	y=y+(k10+2*k11+2*k12+k13)/6

	i+=1

	if i>10000:
		noLoop()


		
		
ルンゲクッタ法の場合は、見える範囲内では楕円はずれず、計算精度が上がっている事が分かる。

一方で計算量は大幅に増えているが、画面表示にかかる時間の方が大きいので、実際の待ち時間は 変わらない。

オイラー法でもdtを2000とすれば楕円がずれない精度が出せる。 しかし同じ時間をシミュレートするための計算量は5倍となる。

オイラー法は、計算量が少なく、精度が低い。ルンゲクッタ法は、計算量が多く、精度が高い。 今回の例では非常に簡単な例であったため、両者の違いは大きくなかったが、 ほとんどの科学技術計算において、ルンゲクッタ法(更にはその改良版)が使われている。


課題9(連星)

以下のプログラムを入力して実行してみよ。 これ以降、コピー&ペーストを使用してもよいが、 プログラムの中身をしっかりと 読んで、理解する事。

		
import math



i=int(0)
t=float(0.0)
dt=float(10.0)
x=[0,0,0]
y=[0,0,0]
vx=[0,0,0]
vy=[0,0,0]
ax=[0,0,0]
ay=[0,0,0]
r=[[0,0,0],[0,0,0],[0,0, 0]]
m=[5.e30,5.e30,5.e30]
PI=math.pi
def setup():
	x[0]=0. 
	y[0]=5.e10
	x[1]=x[0] *cos(2*PI/3)-y[0]*sin(2*PI/3)
	y[1]=x[0]*sin(2*PI/3)+y[0]*cos(2*PI/3)
	x[2]=x[0]*cos(-2*PI/3)-y[0]*sin(-2*PI/3)
	y[2]=x[0]*sin(-2*PI/3)+y[0]*cos(-2*PI/3)
	vx[0]=5.e4
	vy[0]=2.e4
	vx[1]=vx[0]* cos(2*PI/3)-vy[0]*sin(2*PI/3)
	vy[1]=vx[0]*sin(2*PI/3)+vy[0]*cos(2*PI/3)
	vx[2]=vx[0]*cos(-2*PI/3)-vy[0]*sin(-2*PI/3)
	vy[2]=vx[0]*sin(-2*PI/3)+vy[0]*cos(-2*PI/3)
	size(600, 600)
	print "width=" , width, "height=", height
	background(0)
	stroke(255)
	colorMode(HSB ,360,100,100)
	frameRate(1000)

G=float(6.674e-11)
x1=float(-1.e11)
y1=float(-1.e11)
x2=float(+1.e11)
y2=float(+1.e11)
def sx(x):
	return width *(x-x1)/(x2-x1)
def sy(y):
	return height*(y2-y)/(y2-y1)

def accel(m,r):
	return G*m/sq(r)

def draw():

	global i
	global t
	global dt
	global x
	global y
	global vx
	global vy
	global ax
	global ay
	global r
	global m
	global PI

	for j in range(500):
		t=t+dt
		r[0][1]= sqrt((x[0]-x[1])**2+(y[0]-y[1])**2)
		r[1][2]=sqrt((x[1]-x[2])**2+(y[1]-y[2])**2)
		r[2][0]=sqrt((x[2]-x[0])**2+(y[2]-y[0])**2)
		ax[0]=(x[1]-x[0])/r[0][1]*accel(m[1],r[0][1])+(x[2]-x[0])/r[2][0]*accel(m[2],r[2][0])
		ay[0]=(y[1]-y[0])/r[0][1]*accel(m[1],r[0][1])+(y[2]-y[0])/r[2][0]*accel(m[2],r[2][0])
		ax[1]=(x[2]-x[1])/r[1][2]*accel(m[2],r[1][2])+(x[0]-x[1])/r[0][1]*accel(m[0],r[0][1])
		ay[1]=(y[2]-y[1])/r[1][2]*accel(m[2],r[1][2])+(y[0]-y[1])/r[0][1]*accel(m[0],r[0][1])
		ax[2]=(x[0]-x[2])/r[2][0]*accel(m[0],r[2][0])+(x[1]-x[2])/r[1][2]*accel(m[1],r[1][2])
		ay[2]=(y[0]-y[2])/r[2][0]*accel(m[0],r[2][0])+(y[1]-y[2])/r[1][2]*accel(m[1],r[1][2])
		vx[0]=vx[0]+dt*ax[0]
		vy[0]=vy[0]+dt*ay[0]
		vx[1]=vx[1]+dt*ax[1]
		vy[1]=vy[1]+dt*ay[1]
		vx[2]=vx[2]+dt*ax[2]
		vy[2]=vy[2]+dt*ay[2]
		x[0]=x[0]+dt*vx[0]
		y[0]=y[0]+dt*vy[0]
		x[1]=x[1]+dt*vx[1]
		y[1]=y[1]+dt*vy[1]
		x[2]=x[2]+dt*vx[2]
		y[2]=y[2]+dt*vy[2]

	stroke(0,99,99)
	point( sx(x[0]), sy(y[0]))
	stroke(120,99,99)
	point( sx(x[1]), sy (y[1]))
	stroke(240,99,99)
	point(sx(x[2]),sy (y[2]))
	print"X0=", x[0], "Y0=", y[0], "X1=", x[1], "Y1=", y[1], "X2=", x[2], "Y2=", y[2]

	i+=1

	if i >10000:
		noLoop()
		
		
このような場合、数学的に近似する(つまりモデルを変更する)方法もあるが、 それを行ってしまうと得られた数値の精度がモデルの精度以上にはできないという限界がある。 より高精度な結果を得るには、数学的な近似をせず、計算上の近似を高めていく手法しかない。 それがシミュレーションが必要な理由の1つである。


これで実習は終わりです。