FreshmanSeminar2021
アカデミックスキル/プレゼン・ディベート論 2021 計算科学 担当:石井史之
- 短縮アドレス https://bit.ly/3gC4qu6
目的等
- プログラミングの初歩を学び、図形やアニメーションを表示することで、計算科学に関連したプログラミングとその楽しさを体験する。
- プログラミングは2020年度より小学校(新学習指導要領)で必修化(文部科学省)
- 新学習指導要領を中学校は令和3年(2021年)度から全面実施。高等学校は令和4年(2022年)度から学年進行で実施。
- 【物理学系基礎プログラム→計算科学発展プログラム】では物理学を理論とコンピュータを用いて理解する、研究する手法を身につける。
目次
プロセッシングのインストール
- https://processing.org からProcessingをダウンロードする。
- WindowsOSの人は多くがWindows64bitになります。SurfaceProXの人は32bit版にしてください。Macbookの場合はMac。
- Javaがインストールされていない場合はインストールを要求されますのでインストールしてください。
- ダウンロード後に寄付に関する表示(「金額を選ぶ」)がでますが、何もしなくても大丈夫です。
プロセッシングはjavaをベースに作られている。文法はC言語と共通の部分が多い。
- OpenProcessing: 多くのprocessingを用いたプログラムが登録されているhttps://www.openprocessing.org
- 参考文献
- ダニエル・シフマン著:『Nature of Code -Processingではじめる自然現象のシミュレーション』
- 物理や数学の諸原理を組み込み世界を作る最も簡単な方法
- 原著はhttp://natureofcode.com/book/ で公開されています。
- Processingの基礎事項
website "Processing学習ノート"
http://www.d-improvement.jp/learning/processing/
例題1: 動作テスト
rect(45,45,10,10);
windowの真ん中に白い四角が表示されれば成功。
コマンドの終わりにセミコロン";"をつけるのを忘れない様に。C言語でも同じ仕様。
例題2 Hello world
println("Hello world");
コンソールへの出力。" "で囲んだ部分がコンソールへ出力される。C言語ではprintf, fortranではwrite(*,*)
に相当する。
例題3: 1から10までの和
int s=0; for (int i=0; i < 11 ; i++) { s=s+i; if(i==10) break; } println("souwa="+s);
型宣言
- 整数型 int
- 実数型(単精度) float
- 実数型(倍精度) double (算術関数 powなどはfloat型を引数にとる)
int s=0;
としても
int s; s=0;
としても同じである。
繰り返し for文
for(int i=0; i< 11; i++){...}
{...}内をi=0からi=10まで実行する。i++はインクリメントと呼び、iの値を+1する。
代入文
s=s+i;
は s(i)=s(i-1)+i の意味である。
条件分岐 if文
if(i == 10) break;
はif()の()の中が真の時に後ろの文が実行される。breakはそこでループを脱出する。
関係演算子(2つの対象の関係を調べる演算子)
if()等の条件分岐で使う。
演算子 | 意味 | 使用例 | 意味 |
---|---|---|---|
== | 等しい | a==b | aとbが等しい |
!= | 異なる | a!=b | aとbが異なる |
< | 小さい | a<b | aがbより小さい |
<= | 以下 | a<=b | aがb以下 |
> | 大きい | a>b | aがbより大きい |
>= | 以上 | a>=b | aがb以上 |
四則演算など
- 加算 (addition) +
- 減算 (subtraction) -
- 乗算 (multiplication) *
- 除算 (division) /
- 冪演算(exponentiation) aのn乗 : pow(a,n);
例題4:1から10までの和、その2
int i=0; int s=0; while (i+1 <= 10) { i++; s=s+i; } println("souwa="+s);
繰り返し while文
while(){...}
()の中が真であれば{...}を実行する。
例題5: 繰り返しと条件分岐を使って、動く物体
float x; void setup () { size(100,100); x=0; } void draw() { x+=1; if (x > 100) x=-10; rect(x,45,10,10); println(x); }
グローバル変数
全体で使う変数(グローバル変数という)は
float x;
の様に最初に宣言する。
void setup(){..}
void setup(){...}は{...}に絵を描くための初期条件を書く。
size(100,100)は100x100のマス目(ピクセル)を宣言。
size(width, height)の様に、幅(width)と高さ(height)を指定する。
void draw(){...}
絵を描く関数。
if (x > 100) x=-10;
右から出たら、左から出てくる様にする部分。周期境界条件ともいう。
sizeなど、変えて大きく表示してみよう。
四角:rectを丸:ellipseに変えてみよう
float x; void setup () { size(1000,1000); x=0; } void draw() { background(0,0,0); x+=10; if (x > 1000) x=-10; ellipse(x, 450,100,100); println(x); }
ランダムに1次元上を動く丸
float x,y; void setup () { size(1000,1000); x=500; frameRate(20); } void draw() { background(0,0,0); y=random(1); if(y > 0.5) x+=random(10); if(y < 0.5) x-=random(10); if (x > 1000) x=0; if (x < 0) x=999; ellipse(x, 450,100,100); println(x); }
アカデミックスキル/プレゼン・ディベート論 2021 計算科学 (2回目)
例題6:復習
double a=1.02; double b=0.003; double c=2.123; println(a,b,c); double x=a+b-c; println(x);
型宣言、代入文, 簡単な計算, コンソールへの出力。
例題7:復習その2
double a=1.02; println(a); int n=1.02; println(n);
型宣言の意味を理解する。
例題8:閏年の計算 (ファイルから読み込む)
String[] lines; lines = loadStrings("n.in"); int i[]= int(lines); int n=i[0]; if(((n%4==0)&&(n%100!=0))||((n%400)==0)){ println(n+"nen ha uruu-doshi desu."); } else{ println(n+"nen ha uruu-doshi deha arimasen."); }
n.inというファイルを作成し, pde拡張子のファイルと同じディレクトリに入れて、そのファイルに
2017
という様に西暦を一つ記入する。
例題9:閏年の計算 (ファイルなし)
int n=2020; if(((n%4==0)&&(n%100!=0))||((n%400)==0)){ println(n+"nen ha uruu-doshi desu."); } else{ println(n+"nen ha uruu-doshi deha arimasen."); }
例題10:落下後に床で跳ねるボール
- 横方向にも動かして壁で跳ね返るように拡張してみよう!
授業中に説明したのは v=v+a*dt; y=y+v*dt; でオイラー法と呼ばれるものです。
float g=0.1,a=0,y=30, m=1, v=0, E, E0, dt=1; void setup() { size(100, 360); frameRate(60); E0=0.5*v*v+m*g*(height-y); a=g; } void draw() { background(255); v=v+a*dt; y=y+v*dt; stroke(0); fill(175); ellipse(50,y,m*26,m*26); if (y > height) { v *= -1; } E=0.5*m*v*v+m*g*(height-y); println("delta E=",E-E0); }
- 速度Verlet法 (少し違う式になっていますが、同じ結果になります。こちらの方がより正確です。)
float g=0.1,a=0,y=30, m=1, v=0, E, E0, dt=1; void setup() { size(100, 360); frameRate(60); E0=0.5*v*v+m*g*(height-y); a=g; } void draw() { background(255); y=y+v*dt+0.5*a*dt*dt; v=v+a*dt; stroke(0); fill(175); ellipse(50,y,m*26,m*26); if (y > height) { v *= -1; } E=0.5*m*v*v+m*g*(height-y); println("delta E=",E-E0); }
例題11:落下後に床と壁で跳ねるボール
float g=0.1,ax=0,ay=0,y=30, x=30, m=1, vx=5.0,vy=0, E; void setup() { size(600, 360); ay=g; } void draw() { background(255); vx=vx+ax; vy=vy+ay; x=x+vx; y=y+vy; stroke(0); fill(175); ellipse(x,y,m*26,m*26); if (y > height) { //vy = -0.8*vy; vy = -vy; y = height; } if (x > width) { vx = -vx; x = width; } if (x < 0) { vx = -vx; x = 0; } E=0.5*m*(vx*vx+vy*vy)+m*g*(height-y); println("E=",E); }
磁石のシミュレーション(イジング模型)
一行目の 'int N=20;'の数字を変更することで、小さい磁石の数を変化させることができます。
二行目の'float T=1;'の数字を変更することで、温度を変化させることができます。
int N=20; float T=1; int[][] sp; void setup(){ size(600,600); sp=new int[N][N]; for (int i=0; i< N; i++){ for (int j=0; j < N; j++){ float s=random(1); if(s > 0.5) sp[i][j]=1; if(s < 0.5) sp[i][j]=-1; if(sp[i][j] > 0) fill(255,0,0); if(sp[i][j] < 0) fill(0,0,255); int r=height/N; rect(i*r,j*r,r,r); } } } void draw(){ for (int i=0; i<N; i++){ int m= (int) random(N); int n= (int) random(N); float Ediff; int leftS, rightS, topS, bottomS; if(m==0) leftS=sp[N-1][n]; else leftS=sp[m-1][n]; if(m==N-1) rightS=sp[0][n]; else rightS=sp[m+1][n]; if(n==0) topS=sp[0][n]; else topS=sp[m][n-1]; if(n==N-1) bottomS=sp[m][0]; else bottomS=sp[m][n+1]; Ediff= 2.0*sp[m][n]*(leftS+rightS+topS+bottomS); if (Ediff <= 0){ sp[m][n]=-sp[m][n]; } else { if(random(1) < exp (-Ediff/T)) sp[m][n]=-sp[m][n]; } if(sp[m][n] > 0) fill(255, 0,0); if(sp[m][n] < 0) fill(0,0,255); int r=height/N; rect(m*r,n*r,r,r); } }
ライフゲーム
- ライフゲームとは(wikipedia)
- フレームをクリックすると初期化される。
- 1行目の int N=50; の数字を変えるとセル数を変えることができる。
- 1行目の p=0.666の数字を0-1の範囲で変えると最初に表示される色付きタイルの数が変わる(0で0, 1で全塗り)
int N=50; float p=0.666; int[][] sp,sp2; void setup(){ frameRate(5); size(600,600); sp=new int[N+2][N+2]; sp2=new int[N+2][N+2]; for (int i=0; i< N+2; i++){ for (int j=0; j < N+2; j++){ sp[i][j]=0; sp2[i][j]=0; } } for (int i=1; i< N+1; i++){ for (int j=1; j < N+1; j++){ float s=random(1); if(s < p ) sp[i][j]=1; sp2[i][j]=1; if(sp[i][j]==1) fill(255,127,80); if(sp[i][j]== 0) fill(255,255,255); int r=height/N; rect((i-1)*r,(j-1)*r,r,r); } } } void draw(){ int sum=0; for (int i=1; i<N+1; i++){ for (int j=1; j<N+1; j++){ sum=sp[i-1][j]+sp[i+1][j]+sp[i-1][j-1]+sp[i][j-1]+sp[i+1][j-1]+sp[i-1][j+1]+sp[i][j+1]+sp[i+1][j+1]; if(sp[i][j]==0 && sum ==3) sp2[i][j]=1; if(sp[i][j]==1 && sum > 1 && sum < 4) sp2[i][j]=1; if(sp[i][j]==1 && sum < 2) sp2[i][j]=0; if(sp[i][j]==1 && sum > 3) sp2[i][j]=0; } } for (int m=1; m<N+1; m++){ for (int n=1; n<N+1; n++){ sp[m][n]=sp2[m][n]; if(sp2[m][n]==1) fill(255,127,80); if(sp2[m][n]== 0) fill(255,255,255); int r=height/N; rect((m-1)*r,(n-1)*r,r,r); } } if (mousePressed == true){ setup();} }
画像修復
int N=200, t=0; String s; float T=1, Er=0.2, h=0.001, J=3.0; int[][] sp; void setup(){ size(600,600); sp=new int[N][N]; for (int i=0; i< N; i++){ for (int j=0; j < N; j++){ int r2=(i-N/2)*(i-N/2)+(j-N/2)*(j-N/2); if(r2 >6000 && r2 < 10000) { sp[i][j]=-1;} else {sp[i][j]=1;} } } for (int i=0; i< N; i++){ for (int j=0; j < N; j++){ float s=random(1); if(s < Er) sp[i][j]=-sp[i][j]; if(sp[i][j] > 0) fill(0,0,0); if(sp[i][j] < 0) fill(255,255,255); int r=height/N; noStroke(); rect(i*r,j*r,r,r); } } frameRate(30); } void draw(){ for (int i=0; i<N; i++){ int m= (int) random(N); int n= (int) random(N); float Ediff; int leftS, rightS, topS, bottomS; if(m==0) leftS=sp[N-1][n]; else leftS=sp[m-1][n]; if(m==N-1) rightS=sp[0][n]; else rightS=sp[m+1][n]; if(n==0) topS=sp[0][n]; else topS=sp[m][n-1]; if(n==N-1) bottomS=sp[m][0]; else bottomS=sp[m][n+1]; Ediff= 2.0*J*sp[m][n]*(leftS+rightS+topS+bottomS)+2.0*h*sp[m][n]; if (Ediff <= 0){ sp[m][n]=-sp[m][n]; } else { if(random(1) < exp (-Ediff/T)) sp[m][n]=-sp[m][n]; } if(sp[m][n] > 0) fill(0, 0,0); if(sp[m][n] < 0) fill(255,255,255); int r=height/N; noStroke(); rect(m*r,n*r,r,r); } t=t+1; //s=nf(t,6); //text(s,20,20); println("Time step=",t); }