ログイン

FreshmanSeminar2021

アカデミックスキル/プレゼン・ディベート論 2021 計算科学 担当:石井史之

目的等

  • プログラミングの初歩を学び、図形やアニメーションを表示することで、計算科学に関連したプログラミングとその楽しさを体験する。
  • プログラミングは2020年度より小学校(新学習指導要領)で必修化(文部科学省)
    • 新学習指導要領を中学校は令和3年(2021年)度から全面実施。高等学校は令和4年(2022年)度から学年進行で実施。
  • 【物理学系基礎プログラム→計算科学発展プログラム】では物理学を理論とコンピュータを用いて理解する、研究する手法を身につける。

目次

プロセッシングのインストール

  • https://processing.org からProcessingをダウンロードする。
  • WindowsOSの人は多くがWindows64bitになります。SurfaceProXの人は32bit版にしてください。Macbookの場合はMac。
  • Javaがインストールされていない場合はインストールを要求されますのでインストールしてください。
  • ダウンロード後に寄付に関する表示(「金額を選ぶ」)がでますが、何もしなくても大丈夫です。

プロセッシングはjavaをベースに作られている。文法はC言語と共通の部分が多い。

  • 参考文献
    • ダニエル・シフマン著:『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);
}