C言語で非線形偏微分方程式を陽解法による差分法を用いて数値計算しております。
対象となる物体が非常に小さいため、時間刻みを非常に小さくして行っております。
n=40; //分割数
d=30e-6; //物体の長さ
dt=1.0e-15; //時間刻み幅
loop=1.0e+5; //ループ回数(最終的にはもっと増やしますが、今はこの程度)
プログラムの詳細な式や値は省略して
double T[?][?] //?のところがわかりません。
for(i=0;i<=40;i++) {
T[i][0]=・・・ //初期条件
}
for(j=0;j<=loop;j++) {
T[0][j]=・・・ //境界条件
T[40][j]=・・・
}
//差分計算
for(j=0;j<=loop;j++) {
for(i=1;i<40;i++) {
T[i][j+1]=・・・・・・・・・・・・・・・・・
}
}
というような流れなのですが、はじめの配列宣言のT[?][?]の?に入れるべき値はなんでしょうか?
分割の数とでループ回数に1をたしたもの(0があるので)かと思いT[41][100001]としたのですが「Segmentation Fault」となってしまいます。一方、T[50][20000]のようなよくわからない数をいれると一応エラーは出ずに動きますが値が変な気がします。(固定したはずの境界条件が変わってしまいます。)
この境界条件が変わってしまうのは配列の宣言に問題があるからのように感じました。
また、もしこの境界条件が変わってしまうのが他の要因にあるとすればどこであると考えられるでしょうか?
No.1
- 回答日時:
原因と結果が逆ではないか、と予想されます
ループカウンタだけに注目すれば、 T[41][100001] でよいはずですし、
プログラムが正しければ、T[50][20000]としても、余計な部分が使われないだけで、計算結果は同じになるはずだからです。
T[X][Y]のX,Yが常に範囲内か、よく確認してください。
j<=loopのループ内で T[i][j+1] - T[i][j-1] とかやってませんか?
回答ありがとうございます。
>> j<=loopのループ内で T[i][j+1] - T[i][j-1] とかやってませんか?
そのような間違いはしていませんでした。
ループ回数を1.0e+5としたとき、T[50][20000]でプログラムが実行できますがT[x][y]のyがループ回数より少ないのにエラーがでないのが不思議です。
No.2
- 回答日時:
Segmentation Faultになってるのは,単に大きな配列を確保しようとしてるからじゃないのかなあ?
後々のことを考えてもmallocとかで動的に領域を確保すべきだと思うよ。
境界条件が変わってしまうのは,これだけじゃわからんが,確かに20000<1.0e+5だからそのせいかもしれない。それ以外の可能性も大いにあると思うけどね。
ついでに変数loopの型は整数型かな?ループ変数を実数型にするのは気持ち悪いし,整数型だとすると1.0e+5を代入するのはやはり気持ち悪い。
No.3
- 回答日時:
#1です。
訂正です1e+5=100000 > 20000 ですね。
ということは、#2にある「メモリが割り当てられない」というのがまず疑う点となります
> がT[x][y]のyがループ回数より少ない
ということですが、その際に
n=40; //分割数
d=30e-6; //物体の長さ
dt=1.0e-15; //時間刻み幅
loop=1.0e+5; //ループ回数(最終的にはもっと増やしますが、今はこの程度)
というあたりの変数はまったく変えななったのですか?
変えなかったら、同様にSegmentation Faultが 出そうな気がします。よって、プログラム自体が変な可能性があります。
配列に合せて変化調整しているのなら、エラーにはならないかもしれません。
度々の回答ありがとうございます。
症状をまとめますと
n=40; //分割数
d=30e-6; //物体の長さ
dt=1.0e-15; //時間刻み幅
loop=1.0e+5; //ループ回数(最終的にはもっと増やしますが、今はこの程度)
の状態で配列の大きさはT[50][20000]とする。すると、なぜか20000<loopにも関わらず実行ができるが、境界条件が変わってしまう。
上の4つの値は変えずに適切であると考えられる配列の大きさT[41][100001]とするとSegmentation Falt になる。
こんな大きい配列は用意できないということできすかね?最終的には1秒まで、つまり1e+15回ループをしたいのですがそれは無理なんですかね…
No.4ベストアンサー
- 回答日時:
色々と予想はできますが、プログラム全体を見ないことには、確実なことは言えません。
○配列の大きさ
Cのメモリの使い方はやや難しいので、キーワードを元に参考書や解説サイトを見てください。
double T[?][?] ;
のように、特に何も付けずに宣言したものを「自動変数」と言います。
スタック領域というところに確保されることが多いですが、このスタック領域は、そんなに大きなサイズではありません。
T[41][100001] だと、スタック領域では足りない可能性があります。
これの対策には
・ヒープ領域を使う。具体的には、malloc等を使って確保する
・static(静的変数)を使う。
おそらく、単純なプログラムだろうと思うので、staticで対応できそうな気はします。
○ T[50][20000]
Cでは、配列の範囲外を指定しても、それだけではエラーにはなりません。
その指定した添字から計算されたアドレスをアクセスします。
このアドレスが保護領域で、結果としてエラーになることはあります。
逆に、まったく問題無く動作しているように見えることもあります。
例えば
for(j=0;j<=loop;j++) {
T[0][j]=・・・ //境界条件
T[40][j]=・・・
}
で、j>=20000になる
→配列の範囲外にアクセス
→ そこはループ用の変数j の領域
→ 配列へ代入すると、変数jの領域が書き変わる
→ループ終了条件(j<=loop)をたまたま満してしまった
→ループが終了
と、一見何事もなかったように動作している「ように見える」
ということも起りうることです。
No.5
- 回答日時:
回答ではありませんが、少し気になった事があります。
素人が何も分らずに言っているだけかも知れませんが、その場合は申し訳ありません。
>dt=1.0e-15; //時間刻み幅
偏微分方程式で解くような物理現象は、このように時間刻み幅を小さくしなくても十分ではないでしょうか。
psオーダーでも 1.0e-12ですし、........
各ループ毎の変数セーブ域
前回値と新しい値の変数セーブ域、その他があれば計算出来るのだと思われます。
途中経過も残してアニメ表示等に使われるのでしたら、例えば100ループ、1000ループ等毎にセーブしておいて使うようにされたら良いのではと思われます。
ご指摘ありがとうございます。
時間刻み幅については私もこんな細かくしたくありません。しかし、上のプログラムに使われているのは偏微分方程式の陽解法という手法なのですが、これは適切にnとdtを選ばないと解が発散してしまうのです。今回はdがマイクロオーダーで小さいため、時間刻みをここまで小さくしないと行けなくなってしまったのです。
セーブに関しては、いいアイディアだと思います。試してみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- Visual Basic(VBA) Excel のユーザー定義関数でソルバーが動作しない 1 2022/09/05 19:51
- 高校 対数方程式につきまして 4 2022/05/05 07:55
- C言語・C++・C# numpyスライス機能を使った数値計算 2 2023/05/08 16:01
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- 数学 条件付き極値問題といわれる問題です。ラグランジュの乗数法 について、質問したいことがあります。 条件 3 2023/05/15 21:38
- 統計学 どの統計を使えばいいのか教えてください(EZ-Rを使用) 5 2022/10/11 13:28
- 物理学 量子力学 球面調和関数 導出 方位角成分 微分方程式の解 2 2022/07/02 13:40
- C言語・C++・C# LU分解法のピボット選択機能実装について(C言語・gcc-9) 1 2022/07/22 15:20
- Visual Basic(VBA) vba 等間隔の列に対しての計算 6 2022/05/17 20:15
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラミングについて。 1つ...
-
画面を強制的に再描画させる方法
-
DoEventsが必要な理由について
-
pythonでファイルのコメント行...
-
DOSコマンドのループ内のTIMEコ...
-
For文を使った九九表の作成
-
VBAで3秒だけ時間を止めたい
-
vbscriptでIE自動入力(途中で...
-
ループ内での条件処理
-
CSVファイルの特定の行だけを読...
-
GIFアニメをループさせたくない
-
VBA横データを縦にしたいです
-
vb.netからエクセル関数書き込み
-
エクセル関数で1〜12の数字がル...
-
vb.netです。2次元配列の要素を...
-
VBA for文が止まらない
-
アセンブラによるウェイト(WAIT...
-
UWSCの終了の仕方
-
テキストボックスの名前に変数...
-
アクティブセルから、A列最終行...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
画面を強制的に再描画させる方法
-
VBAで3秒だけ時間を止めたい
-
VBAでの一時停止と再開の方法
-
どなたかこのプログラミングを...
-
Escキーを押すと、中断する時と...
-
UWSCの終了の仕方
-
エクセルの当番表を作っていま...
-
VBA for i=1 to lastrow
-
「偶数・奇数の和」のフローチ...
-
アクティブセルから、A列最終行...
-
DoEventsが必要な理由について
-
vb.netからエクセル関数書き込み
-
GIFアニメをループさせたくない
-
DOSコマンドのループ内のTIMEコ...
-
範囲指定したセルを1つずつ飛...
-
流れ図(フローチャート)が分か...
-
乱数の桁数指定、または範囲指定。
-
テキストボックスの名前に変数...
-
CSVファイルの特定の行だけを読...
-
vb.netです。2次元配列の要素を...
おすすめ情報