くだすれFORTRAN(超初心者用)その6
レス数が1000を超えています。これ以上書き込みはできません。
このスレッドは、他のスレッドでは書き込めない超低レベル、
もしくは質問者自身何が何だか分からない質問を勇気を持って書き込むスレッドです。
FORTRAN使いが優しくコメントを返しますが、
お礼はFORTRANの布教と初心者の救済と次期Fortran2008規格でのCOMEFROM文採用をお願いします。
●注意事項
・質問する前にGoogle等の検索サイトで検索しましょう。
・回答者にわかりやすい様に、質問内容はできる限り詳しく書きましょう。
・エラーの場合は起きた状況、環境(OS・コンパイラ・バージョン)、エラーメッセージも詳しく書きましょう。
●前スレ
くだすれFORTRAN(超初心者用)その5
http://toro.2ch.net/test/read.cgi/tech/1269704830/
●過去スレ
くだすれFORTRAN(超初心者用)その4
http://pc12.2ch.net/test/read.cgi/tech/1232789521/
くだすれFORTRAN(超初心者用)その3
http://pc11.2ch.net/test/read.cgi/tech/1196384126/
くだすれFORTRAN(超初心者用)その2
http://pc11.2ch.net/test/read.cgi/tech/1164121236/
くだすれFORTRAN(超初心者用)
http://pc8.2ch.net/test/read.cgi/tech/1138063703/ >>924
藪下信『計算物理(I)』(地人書館、1982)には、
「ルンゲ・クッタ法は弱不安定であることが知られている。ずなわち、ステップ幅hをあまり大きくとり過ぎると
、微分方程式の解と、それに対応する数値解とが、定性的に異なった振舞いをする。ただそれは
弱不安定性なので、hを小さくとることによって、安定にすることができる。理論的に詳しいことは、
ここでは説明しないが、結果だけをまとめて書いておこう。
(1) 一般の従属変数yに対する式
dy.dx=ay+b, (a<0)
に於て、ルンゲ・クッタ法が安定であるための条件は
|ha|<2.7
となることである。
(2) n個の従属変数(y1, y2, ,,,,,,,yn)に対する微分方程式
dy・cx=A;y+b
を考える。ただし、Aはn×nの行列である。Aの固有値の中の負のものがあるとき、
Aの固有値のうち絶対値が最大ものをλとする。
安定性の条件は、
|hλ|<2.7
となることである。」
とあります。参考になるでしょうか。
森口繁一先生の本で、「刻み幅」を自動的に変更するという手法について書かれた本が
あったと思います。『計算数学夜話(?)』とかいう本かもしれません。 >>924
最適解を求める方法は、刻み値の変更方法を含めて
UP応用数学選書7 最小二乗法による実験データ解析 プログラムSALS
https://www.utp.or.jp/bd/978-4-13-064067-1.html
にくわしい。大学系の図書館ならおいてあるはず。
境界値があって、連続計算できない場合に
最小二乗法だと、不安定になりやすいので、収束が悪いけど、絶対値法
残差二乗和の極小値ではなく、残差絶対値和の極小値を求めると、収束まで2-3倍の回数を計算しなければならないけど、安定しやすい。
残差が増加したときに、一旦計算を打ち切って、解を出力する。
出力した解を初期値として、刻み幅を1/10位(2進数の関係で1/8か1/16)に減らして、再度計算する。
収束で、計算機Eの1024倍ぐらいまでが積分を求めた時の1桁の精度になる(こっちの経験値、問題と演算系によっては大幅に変わる)ので
Y=F(X)の、Xを少しずらした時の値を計算して、このくらいずれる値を見つけておいてくれ。
左(0)から近づけた場合と右(∞)から近づけた場合に、不連続点の付近で、制度が大きく変わる。
こっちが取り扱った問題では、右からは1程度、左からは1E-12程度、計算機Eの影響を受ける。
こんな場合には、最小二乗法・絶対値法ともに使えない。OR https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%9A%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BA%E3%83%BB%E3%83%AA%E3%82%B5%E3%83%BC%E3%83%81 を使う。
一次方程式の場合には、計算方法が規定されているが、
他の場合には、
適当な初期値を使って計算して、少しずらした値を計算して、極小値を初期値にして再度計算、
の繰り返しになる。不連続点は計算しない。
「少しずらした値」は1/1024を使って、その後1/2づつ減らした。
収束はかなり悪い。3000-5000回の繰り返し演算が必要だった。
計算機Eによる影響は、この方法で求めた。
なお、温度の変化を追いかける計算ではないので、参考にならないかもしれない。 どなたかご存知の方いらっしゃいますでしょうか?
コンパイラのバグではなく何らかの仕様なのかと思うのですが分かりませんでした。
●質問
実数型の変数をwrite文で桁数を指定して出力させる時、
桁数以下の値は四捨五入されて出力すると思うのですが、
下記プログラム例のように”切り捨て”られる(と思われる)場合があります。
なぜこのような処理がされるかご存じであれば教えて頂きたいです。
●プログラム
PROGRAM TEST
IMPLICIT NONE
REAL*8 VAL1
VAL1=0.125D0
WRITE(6,'(D13.2)')VAL1
END PROGRAM
●結果
0.12D+00
●問題点
・0.125の小数点第3位を四捨五入すると0.13となるが結果は0.12となってしまう
●確認したこと
・変数VAL1の桁を増やして確認すると0.12500000000・・・と続く
・0.125は2進数で正確に表す事ができる
・下記のように2進数で正確に表せない数値だと四捨五入が理解できる
入力値 VAL1=0.555D0
結果 0.56D0
結果(桁を増やす)0.555000000000000048849813083507D+00
・2進数で正確に表せる数値でも正しく四捨五入されるものもある
入力値 VAL1=0.375D0
結果 0.38D0
その他 0.0625D0も正しく四捨五入される ⇒ 0.63D-1 と出力される
・Fortranコンパイラは、Compacfortranやredhatのgfortran、IntelFortranを試したがいずれも同じ結果だった
・単純な数値なので32bitや64bit環境の問題では無いと思います
・.f90でのみ試しています どうもありがとうございます。
ROUNDで丸め誤差を色々定義出来るのですね。
来週試してみます。 fortranにはなんで引用仕様宣言なるものがあるんですか?
関数の引数等を関数の定義からコンパイラ勝手に読み取れば良いと思うんですが、moduleでできて手続きだとわざわざ自前で書かなきゃいけない理由って何かあるんですか? 普段形状引き継ぎ配列を使っているのですが、blasやlapackを使ってarray-temporariesをつけてコンパイルすると、コンパイル時にarray-temporariesのワーニングが出ます。
blasでは形状引き継ぎ配列を使っていないしモジュール内にあるわけでもないので当然と言えば当然なのですが、こういう時にどうするのが良いのか分からず困っています。ベストプラクティスのようなものはあるのでしょうか? 永い時を経て多分自己解決出来ました
Contiguous なんていうオプションがあるのですね 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
SAWKX FORTRAN案件が一部に有るな
鉄道ダイヤシステムだが 何故文関数、
f(x) = 1. / x
のような記法が非推奨と言われるのでしょうか?(nag等のサイトより)
他の言語のlambda式などと比べて、Fortranでは非常に簡潔に簡易な関数を定義できるものだなあ、
と感心していたのですが… >>941
書き易さより読み易さが優先
気象庁の標準コーディングルールより
文関数
文関数は引用仕様が暗黙的であり、デバッグがしずらくなる。また、文関数 自体や文関数定義が後続する文関数を引用してはならないなどの制限がある。 内部関数として書いた方がよい。
http://www.mri-jma.go.jp/Project/mrinpd/coderule.html
関数、変数は明示的な宣言をしてから使うのが今風
個人で読み返さないプログラムなら何やっても正常動作すれば良いよ >>942
ありがとう、正直大きなプログラム書かないので実感が湧かないけど、そういうものか 2018も出たことだし若い血も入ってくる
乗ってるな 本当に初歩的でかつ自分勝手で申し訳ないのですが、fortran90でn次正方行列の逆行列を求めるプログラムを教えていただけませんか? それは数値計算の永遠の課題で万能の処方箋は無い
勉強の為ならWikipediaでも見ながら愚直にガウスの掃き出し法でも実装してみたら 求めたいだけなら大体の環境でmklが一番いいライブラリ
有名なので比較的読みやすいのはLINPACKだけど77仕様
モダンで簡単な実装ならあちこちのブログに載ってるからググれ 一応貼っとく
http://www.netlib.org/linpack/
お好みのシチュ用のソースが読める
インデクスと要素毎演算でDOは殆ど排除できるはず スレ索してみたけどFortranスレもしかしてここしか無くね
ぜひLINPACK読んで逆行列の疑問書いてくれ
布教のチャンス Matrix Computationsに載ってるよ。 質問です。
ファイル名 *.f90 とは別に、プログラム名 program * がありますが、この二つが同じ名前だと、何らかの不具合・不便に繋がったりするのでしょうか。
私は、修正前後を比較するためにバージョン違いを作るような場合を除き、基本的に両者を同じ名前にしているのですが…… ファイルシステムの無い時代、例えばパンチの名残だろうかね 環境はCygwin、f90、gfortranです。
open文のaction指定子に関する質問です。
ミス防止のため、念には念を入れて
「readもwriteもするファイルでも、場面に応じてaction='read'と'write'を切り替える」
と理想的なんじゃないだろうか、とふと思いまして、
open(100,file='foo.dat',status='old',action='read')
〜
open(100,action='write',position='append')
〜
close(100)
という記述を試してみたのですが、実行時にエラーになってしまいました。
(Fortran runtime error: Cannot change ACTION parameter in OPEN statement)
「open文で既に開いているファイルを開き直してもよい」って仕様はこういう用途のためのものではないんですね……
一度closeすれば事は足るのですが、それだと今度は「同じfile名を二回記述しなければならない」という無駄が解消できず……
何か、巧い方法はないのでしょうか。 すみません、一応自己解決しました。
指定子に文字型の変数を与えることができる、ということに先ほど気づきました。
なので「一度closeする」で問題ありませんでした。
name1 = 'foo.dat'としておいて、
open文に file=name1 とでも書けば済む話でした(つまるところ、ファイル名変更時の手間が一番の問題だと考えていたので)。 >>961
mklが手軽かつ最速だがクソでか&環境依存
配布も考えるならソースをnetlibでwget -r url
ラッパのLAPACK95もあると便利 >>956
遅レスだけど、program名って何か意味あるんかね?
program書かないでも動くし(endは必要)、programは他から呼ばれないし
moduleやsubroutineの名前は呼ぶのに大事だけど
ファイル名はinclude "fname"で使うから意味ある 他人が作ったコードで、
real*4 宣言を全部real*8に書き換えたら、
計算結果がNaNになっちゃったんだけど、
どんな原因が考えられますか? Fortranは1956年?だかに作られたそうだけど
当初からクラス設計とかあったの? データベースに合わせたORMみたいな
メンバーとか何かあった気がするが
クラスは無いんじゃね Moduleで継承みたいなことってできないんでしょうか?
module mod1
integer,parameter :: val1 = 20
end
module mod2
use mod1
end
program main
use mod2
print *, val1
end
みたいな
このままだとエラーですけど >>970
gfortran8.1で試したけど普通に動くよ 今更fortran使う必要が出たんですけど宣言全部冒頭でやらなきゃいけないとか読みにくいにもほどがあるなこの言語……
ただdllでもない生のCファイル普通に使えるのちょっと強すぎじゃない。何これ C++に移植する作業をしてるんだが、fortranは配列が1スタートなのと行優先なのまじで糞だと思う 配列の下限もレイアウトも両方オプションで変更できるっしょ read/writeの装置番号というのに衝撃を受けたんだけど
いや整数を振るって……えぇ……他の言語でこんなん見たことねぇよ…… ここで言語仕様に文句言ってもどうしようもないだろ……
整数型の変数も使えるから自分で値を付けれるハンドルと考えれば良い Cでもstdin=0,stdout=1,stderr=2とかやってるやん? subroutineとfunctionの使い分けってどうしてます?FORTRANのコード規約みたいなのがあまり見当たらなくてわかんなくて
たとえばnameとageを持ったpersonタイプを作るとしてsubroutine getperson(name, age, person) intent(in)name, age intent(out)person
なのかgetname(name, age)ファンクションを定義してperson = getPerson(name, age)みたいなのがいいのか
他の言語の言い方になるけど前者は参照渡し的というか。今いじってるのがほぼ全部subroutineで処理してるからこういうのがfortranの書き方なのかなぁって
個人的には後者の方がいいのではと思うんですよね 副作用が無いならfunction、あるならsubroutine
例えばsinやcosはfunctionだけどrandom_numberは内部状態を書き換えるのでsubroutine 前提として初心者がどちらにするか迷った時の話で
非pure関数を同じ文中で複数呼んだら評価順の影響を受けて悩みの種になるというのがあるから
副作用があれば全部subroutineぐらいの割り切りでいいと思う >985
複数の返り値を構造体にすれば、関数でいけるのではないでしょうかね cigwin64ターミナルでコンパイルしようとすると
Winmain関数への定義がされてないって言われるんだけどどうしたらいいですか? macのOSをCatalinaにしてからfortranでコンパイルできなくなりました。
大学の宿題ができなくて困っています。助けてくだいさい!
gfortran main.f90 でコンパイル後のエラー文は以下です。
dyld: Library not loaded: /usr/local/opt/isl/lib/libisl.21.dylib
Referenced from: /usr/local/Cellar/gcc/9.1.0/libexec/gcc/x86_64-apple-darwin18/9.1.0/f951
Reason: image not found
gfortran: internal compiler error: Abort trap: 6 signal terminated program f951
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://github.com/Homebrew/homebrew-core/issues> for instructions. 読んでみました。
libisl.21.dylib を読み込もうとしているのですが、
libisl.22.dylib におそらく対応ファイルが変わってしまったようです。
読み込み先を libisl.21.dylib → libisl.22.dylib に変更するにはどうしたら良いのでしょうか? libisl.22.dylib を libisl.21.dylib に rename コンパイルできるようになりました!
ありがとうございます! 並列計算のコマンドを do loop 内に入れると,配列ごとに計算できないのね。。。
なんか妙案あるのかな ifortで-ipoを指定すると謎のセグフォが発生する このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 2789日 7時間 41分 53秒 レス数が1000を超えています。これ以上書き込みはできません。