9回目


2014年度中間試験の解答

2013年度中間試験の解答

シミュレーションの考え方
計算機シミュレーションは大変便利で,現在の様々な製品を開発する上でなくてはならないものに
なったと言えます.機械工学をバックグラウンドとする技術者にも大変有用なものであり,例えば,
3D CADに様々なシミュレーション機能を組み合わせて解析し,設計に役立てることができます.

もはや機械を設計する上で実務上なくてはならない存在ともいえるのがシミュレーションであり,みな
さんの想像の通り,多くのパラメータ,数多くの要素を一度に演算できるのが大きなメリットです.
設計の初期段階では,仕様を決め,それを満たすための代表値を中心とした計算を中心に取り組む
わけですが,あまりにも多くのパラメータを数学的に綺麗な形で算出することは事実上困難なのです.
ところで,以下のようなキーワードを既に聞いていると思います.

解析的とは,数学的に綺麗,即ち,数式をきちんと立て,その数式を変形すると,解についての方程式
を示せるところまで数式に従って解ける方法と言えます.例えば,パラメータx0〜x9まであってyを知り
たいとき,y=f(x0〜x9)のように表現でき,yを得ることができるような場合を指していると言ってよいと
思います.

これに対し,数値的とは何かを説明します.
数学的に解くことには変わりがないのですが,ここで例えば,材料力学で扱うFEMを考えてみましょう.
材料は,連続体として見なせます.
細かく見ていき,組織あるいは分子まで分解し,それらの相互の関係を計算するという方法もあります
が,常の機械設計においてはそこまではやりません.結果に対する計算コストがかかり過ぎて意味が
ないからです.
単純な構造であれば解析的な解法が使えますが,複雑な形状における応力分布,とりわけ応力集中
などを知りたい場合があります.構造材をメッシュとして捉え,多数の点に関する方程式を立てるわけ
ですが,数千点以上になると,とてもそれらを一意に解くことなど出来ないことは想像に難くないと思い
ます.
詳細は割愛しますが,ある初期状態,ある条件を与えたとき,モデルを構成する多数のパラメータに関し,
一つのパラメータに関して仮に値を与えて解き,その影響をさらに計算して次のパラメータを解き,それを
波及させて解いていくことを繰り返したりします.
コンピュータは知っての通り離散量を扱います.すなわち有限個の要素やパラメータを用いていることが
特徴なのです.以前お話ししたサンプリングを思い出してみて下さい.時間軸で区切って標本化し,振幅
で区切って量子化しています.もともと連続量だったものを時間で区切り,その時の値も有限の段階で
示します.つまりは,あらゆるパラメータに関して,段階的にしか扱うことができず,FEMのように少しずつ
変化させてその様子を観察するという方法を用いるのです.
このような性質から,多数の観測点について連立した方程式を多数解くために有効なものと考えて利用
します.

前置きが長くなりましたが,数値的であることの問題は,中間試験の最後の問題でも答えていただいた
通りなのです.以下にその説明を書いていきます.

切り捨て,丸め誤差
皆さんが使っている変数の型floatやdoubleは約15〜17桁位の精度を持っています.
それ以上の値を入れても勝手に切り捨てられたり,丸められたりします.
数学・物理的には同じ定数であっても,小数点表記だけで表記するのか,10の冪乗と分けて表記するか
によっても,計算精度に違いが生じます.

誤差の蓄積
計算機のお得意は単純な計算を早く繰り返して行うことです.
シミュレーションはその性質を利用して,値を少しずつ変化させて,方程式を解くことを繰り返します.
動力学を解くための連立微分方程式を解く方法など代表例かと思われます.
極端に小さい値と極端に大きな値を掛けたり割ったりすると誤差が生じます.
切り捨てや丸め誤差に起因してしまいます.
またある程度注意深く数値を選択しても,誤差を含んだ計算を繰り返すうち,それが蓄積してしまうことも
あるため,さらに大きな誤差となり,シミュレーションの結果の妥当性が危ぶまれる結果につながります.

シミュレーションの条件
シミュレーションのねらいは,複雑な計算に対し正確な解を早く得られることに他ならないと思います.
計算機負荷に関しては従来は負担になるという都合もあり,刻み幅を大きくしたり,メッシュを大きくしたり
するなどして,データ量や計算量を減らしてきたが,今となってはむしろ,不具合の起きない条件を探す
必要があります.計算のステップを粗くしたところで誤差を発生することもありますが,細かくし過ぎても
やはり解がおかしくなることがあるのです.

参考
シミュレーションの例を挙げると,微分方程式を解くための数値演算を行う場合があります.
時間刻みごとの解の組を計算するわけですが,時間刻みを小さくすることで計算量が増えることを避ける
ため,刻みを粗くすると,困ったことに解が発散するという問題が存在してしまいます.
もちろん刻みを小さくすればきちんと解を持つので,微分方程式の解がないわけではないため,問題は,
刻みを粗くしすぎたことと考えられます.
時間刻みを闇雲に小さくすれば,精度の細かい計算だから良いかというと必ずしもそうではありません.
時間刻みを極端に小さくすると変化が僅少になるため,切り捨てられてしまった故の誤差が発生してしまい
これを繰り返すと誤差を累積することとなるのまた別の問題として発生してしまうのです.
ですので,シミュレーション条件を変えたりする必要があるとともに,解析的に解いた場合の大まかな傾向を
知っておかないとシミュレーションが正しいかどうかも分からなくなってしまうことがあります.


課題1 以下の関数を組み込み,数値微分を行ってみよう.
f(x)=(x * x) / 2
これについて,解析解,プログラム作成,関数電卓による解を比較してみて下さい.
比較した結果と考察をソースファイルのコメントに記述すること

関数の引数について

double diff(double fnc(double), double xx, double x0, double x1, int n)
fnc(double);微分しようとする関数
xx;導関数のxの値(今回はxを指定)
x0;x標本の始点(今回は0くらいを指定)
x1;x標本の終点(今回は1くらいを指定)
n;標本数(今回は10くらいを指定)

関数の入ったソースはこちら→diff.c 20130605一部変更あり(エラーに対応)

メイン関数のソースファイルは以下を参考にしてみて下さい.

#include <stdio.h>
#include <math.h>

double fnc(double x){
 return 0.5*x*x;
}


main(){
 double kai;
 double x;

 x=0.8;/*変えてよい*/
 kai=diff(fnc, xx, x0, x1, n);
}

課題2 以下の関数を組み込み,数値積分を行ってみよう.
f(x) = exp(-x*x)
これについて,解析解,プログラム作成,関数電卓による解を比較してみて下さい.
比較した結果と考察をソースファイルのコメントに記述すること

関数の引数について
double integral(double fnc(double), double a, double b, unsigned int n, double se)
fnc(double型の引数);積分しようとする関数
a;積分の下限
b;積分の上限
n;初期分割数(今回は4くらいを指定)
se;相対許容誤差(今回は0.00001くらいを指定)

関数の入ったソースはこちら→integral.c

メイン関数のソースファイルは以下を参考にしてみて下さい.

#include <stdio.h>
#include <math.h>

double fnc(double x){
 return exp(-x*x);
}


main(){
 double kai;

 kai=integral(fnc, a, b, n, se);

}