• ベストアンサー

フィックの第二法則の刻み時間(フォートラン)

第二法則について数値解析を行い、 フォートランによって dt=1.0 dx=1e-4 d=2e-12 a=d*dt/(dx)**2 do 300 j=0,3600 c(j,0)=0.0 c(j,20)=2.0 do 400 i=1,19 c(j+1,i)=c(j,i)+a*(c(j,i+1)-2.0*c(j,i)+c(j,i-1)) 400 continue 300 continue として一秒ごとに計算し、一時間後までの各時間、各位置の濃度を求めています。 (jは時間、iは位置を表しています。) このとき、刻み時間t=1として計算しているのですが、これを0.1秒で計算したいとき、 do 300 j=0,3600 を do 300 j=0,3600,0.1 c(j+1,i) は c(j+0.1,i) としなくてはいけないのでしょうか? それとも1のままでよいのでしょうか。 どなたか、どうか教えてください。 ちなみに、上のようにかえてもプログラムが通らないことはわかっています。 聞きたいのは、「刻み時間を変えると濃度計算の中身と計算のステップも変えなくてはいけないのか」ということです。 わかりにくくて申し訳ありません。 どうかお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

ANo.2 です。 例えば、物体の速度 v [m/sec] を例にして考えてみます。 物体の位置を l(t) とすると、 l(t) = l(t-dt) + (v * dt) (ただし、dt は単位時間(微小時間)) と書くことができますよね。 dt = 1 のときのプログラムの式を、 ==== code 1 ==== l(0) = 0 do j = 0, 100  l(j+1) = l(j) + (v * dt) continue ==== end of code 1 ==== とすると(インデックスが +1 で時間は +1)、dt = 0.1 のとき(0.1秒刻みで位置を算出するとき)のプログラムの式は、 ==== code 2 ==== l(0) = 0 do j = 0, 100, dt   l(j/dt+1) = l(j/dt) + (v * dt) continue ==== end of code 2 ==== となります(インデックスが +1 で時間は +0.1)。 ただ、これでは j/dt が整数にならないとエラーになってしまいますので、以下のように 書き換えるべきではないかと思います。 ==== code 3 ==== l(0) = 0 do j = 0, 100/dt   l(j+1) = l(j) + (v * dt) continue ==== end of code 3 ==== "code 2" と "code 3" でやっていることは同じなのですが、イメージとしては、 ・"code 2" は dt を元の値の 1/10 にした。 ・"code 3" は dt はそのままで速度を 1/10 にした。 という感じです。 私は、"code 3" のように考えるようにしているので、単位が必要と思ったのです。 (あまり必要なかったですが) う~ん、かえって回りくどい書き方になってしまったかな。。。

dende2
質問者

お礼

早速回答頂き、どうも有難う御座います。 おぉ! このプログラムのほうが、私が書いたものよりスッキリしていていいですね! えぇっと、お書き頂いたプログラムを見る限り、回答としては「時間の刻み幅を変えた場合、濃度計算の時間幅とステップも変えなくてはいけない、ということでよろしいでしょうか・・・?

その他の回答 (2)

回答No.2

>a=d*dt/(dx)**2 この式の各変数の単位(例えば、dt なら [sec])がわかれば、 自ずと決まってくると思います。 もしわからないようでしたら、補足で単位を書き出してみてくれませんか?

dende2
質問者

お礼

回答いただき、ありがとうございます。 単位ですか・・・。 おそらく、 dは定数で、dxはメートル、dtは秒 です。 どうして単位から決まってくるのでしょうか・・・? もしよろしければその理由もお教え下さると幸いです。

  • zettsei
  • ベストアンサー率31% (13/41)
回答No.1

c(*)というのは配列ですよね? 配列の番号に入れるのは整数なので、dtを0.1にしたのならjは1刻みのまま、36000回ループさせるしかありません。

dende2
質問者

お礼

解答ありがとうございます。 はい、dtを0.1にすると、ご指摘の通り、このプログラムでは上手くいきません。 その問題の解決方法としては、read文でdtを読みとり、if文で、dt=0.1ならばdt=1として36000回ループを行おうと思っておりました。 質問の説明が足りなかったようです。 申し訳ありません・・・。 時間の刻み幅は0.1、1、10の三種類設定しようと思っています。 刻み配列子の番号が整数、という問題は上記の方法でいいとして、ここで問題なのは 「刻み時間を変えると濃度計算の中身と計算のステップも変えなくてはいけないのか」 ということです。 つまり、 read(*,*)dt read(*,*)n if(dt.eq.(0.1)) then k=10 dt=1 else k=1 end if do 300 j=0,3600*k,dt もしくは do 300 j=0,3600*k c(j,0)=0.0 c(j,20)=2.0 do 400 i=1,19 c(j+dt,i)=c(j,i)+a*(c(j,i+1)-2.0*c(j,i)+c(j,i-1)) もしくは c(j+1,i)=c(j,i)+a*(c(j,i+1)-2.0*c(j,i)+c(j,i-1)) 400 continue 300 continue 上に二通りのdo文と、二通りの濃度計算がありますが、どちらの計算でやるのか、と言うことです。 回りくどい説明で誠に恐縮なのですが、もう一度お教えいただけたら幸いです。 どうかよろしくお願い致します・・・。

dende2
質問者

補足

申し訳ありません、{お礼}に書いたプログラムは少し間違っていたので・・・。 do 400 i=1,19 ではなく do 400 i=1,n の間違いでした。 これでフィックの法則を用いる材料の位置を表しています。 下手な質問でお恥ずかしい限りです・・・。 どうかもう一度お力添えをよろしくお願いします・・・。

関連するQ&A

  • フィックの第2法則のラプラス変換による解の求め方

    1次元で、半無限方向に食塩が拡散する現象を考え、時間t、位置x、濃度C、拡散係数Dとして、フィックの第2法則 ∂C/∂t=D×∂^2C/∂x^2 を解く問題です。 食塩部分は常に濃度Cs、無限遠方では濃度は0であることから、 初期条件、 C(x,0)=C∞=0 境界条件、 C(0,t)=Cs C(∞,t)=C∞=0 です。  課題の解法では、ここでθ=C-C∞とおき、拡散方程式を、 ∂θ/∂t=D×∂^2θ/∂x^2 と変形し、初期条件、 θ(x,0)=0 境界条件、 θ(0,t)=Cs θ(∞,t)=0 としています。ここでラプラス変換を行い、  ∞ ∫ e^-pt×θ(x,t)dt=Θ(x,p)  0 とし、拡散方程式を変換するのですが、左辺はpΘ(x,p)になるのは分かったのですが、右辺の変換の仕方がわかりません。ヒントによると、          ∞ D×∂^2/∂x^2∫□dt=□          0 になるそうですが、□に入る式が分かりません。お願いします。

  • フォートラン

    次のような問題 質量mの質点が、次の運動方程式にしたがって1次元的に運動しているとする m*(d^2x/dt^2)=-αx+βx^2 (♯1) ここでxは質点の位置座標、αおよびβは適当な次元を持つ正の定数である。 という問題を 任意の初期条件から出発して数値解を求めるための手順書を作成したいのですが、Fortranで書きたいのですが どのように書けばいいのかわかりません。 考えたこと数値計算に適した形に直すと ((♯1)の無次元化 x=(m^a)(α^b)(β^c)X t=(m^d)(α^e)(β^f)T a,b,c,d,e,fは未知数。これを、微分方程式に代入して(d^2X/dT^2)=X+X^2)

  • VBAでの拡散計算

    エクセルのVBAを使って添付画像のようなグラフを作成しようと考えています。 以下の計算で作成できそうなのですが、⊿tを10-5より小さく設定し、1000sec~の濃度変化が知りたいため表計算ではなくVBAを使ってみました。 表計算では、 t=0のときx0=C0(飽和濃度)、x>x0でC=0とし(初期条件) x0では、 C(j+1,i) = C(j,i) +D * ( C(j,i-1) - C(j,i) ) / dx / dx * dt x >x0では、 C(j+1,i) = C(j,i) +D * ( C(j,i-1) - 2 * C(j,i) + C(j,i+1) ) / dx / dx * dt の計算を行い、セル表記が以下のようになりました。どの時間も物質量は一定です。(たぶん・・・)   t0、t1、t2、t3t、・・・ x1,60、58.8、57.6・・・ x2, 0、 1.2、2.38・・・ x3, 0、 0、0.02・・・ 上の計算をVBAで以下のように書いてみました。 Sub diffusion_dry_up2() Dim n As Integer, nt As Integer Dim i As Integer, j As Integer Dim b As Double, te As Double, dt As Double Dim c0 As Double, cs As Double, d As Double Dim x As Double, dx As Double, t As Double Dim a As Double, cjp As Double, cj0 As Double Dim cjm As Double b = InputBox("配管の長さb(m)") n = InputBox("配管の長さの方向分割数n") te = InputBox("計算する時間長t(sec)") dt = InputBox("時間増分dt(m)") c0 = InputBox("配管底部の濃度c0(vol.%)") cs = InputBox("時刻t=0の時の配管内の濃度cs(vol.%)") d = InputBox("拡散係数d(m^2/sec)") Sheet1.Cells(1, 2) = "配管の長さb(m)" Sheet1.Cells(2, 2) = "配管の長さの方向分割数n" Sheet1.Cells(3, 2) = "計算する時間長t(sec)" Sheet1.Cells(4, 2) = "時間増分dt(sec)" Sheet1.Cells(5, 2) = "配管底部の濃度c0(vol.%)" Sheet1.Cells(6, 2) = "時刻t=0の時の配管内の濃度cs(vol.%)" Sheet1.Cells(7, 2) = "拡散係数(m^2/sec)" Sheet1.Cells(1, 3) = b Sheet1.Cells(2, 3) = n Sheet1.Cells(3, 3) = t Sheet1.Cells(4, 3) = dt Sheet1.Cells(5, 3) = c0 Sheet1.Cells(6, 3) = cs Sheet1.Cells(7, 3) = d nt = te / dt dx = b / n Sheet1.Cells(1, 1) = nt t = 0 a = d * dt / dx ^ 2 Sheet1.Cells(1, 5) = t Sheet1.Cells(1 + 1, 4) = -dx Sheet1.Cells(1 + 2, 5) = c0 Sheet1.Cells(1 + n + 2, 4) = b + dx Sheet1.Cells(1 + n + 3, 5) = cs Sheet1.Cells(3, 5 + i) = a * (-cj0 + cjp) + cj0 For i = 1 To nt t = t + dt Sheet1.Cells(1, 5 + i) = t Sheet1.Cells(1 + n + 3, 5 + i) = a * (cjp - 2 * cjo + cjm) + cj0 For j = 2 To n + 2 cjp = Sheet1.Cells(1 + j + 1, 5 + i - 1) cj0 = Sheet1.Cells(1 + j + 0, 5 + i - 1) cjm = Sheet1.Cells(1 + j - 1, 5 + i - 1) Next j Next i linegraph 2, 4, 4 + n, nt + 2 End Sub Sub linegraph(sr As Integer, sc As Integer, lr As Integer, lc As Integer) ActiveSheet.ChartObjects.Add(200, 10, 240, 200).Select ActiveChart.ChartWizard _ Source:=Range(Cells(sr, sc), Cells(lr, lc)), _ gallery:=xlXYScatter, _ Format:=3, _ PlotBy:=xlColumns, _ categoryLabels:=1, _ SeriesLabels:=0, _ HasLegend:="false", _ Title:="ex2", _ categoryTitle:="t", _ ValueTitle:="y", _ ExtraTitle:="" End Sub しかしまったく表計算のようになりませんでした。 a = d * dt / dx^2以降の書き込みが変だと思うのですが、どのようにすればよいのでしょうか。 また、上のような表記ではtを大きくdtを小さくするとエラーになってしまいます。 質問項目が多いですが、よろしくお願いします。

  • フォートランでの相互相関関数の計算

    酒器について質問です。 ある2つのポイントで計測した実験データがあります。 その2つの実験データの間の時間のずれΔtを相互相関関数を用いて求めたいと考えています。 参考書やインターネットを通して理論は理解できるのですが、それをフォートランを用いた場合どのようにして計算させるのか分かりません。 具体的のどのようにして計算したらよいのでしょうか? どのようなプログラム文を打てばよいか教えていただきたいです。 流れとしてはデータ数1000の場合 2つのファイルをopen データ読み込み f() g() do p=-500,500 do i=1,1000 s=f(i)*g(i+p) ss=ss+s ........... のような流れになるのでしょうか? どなたか分かる方是非教えてください よろしくお願いします

  • Fortranの素数のプログラム

    5000万までの素数を求めるプログラムなのですが、私の作ったプログラムは実行時間26秒くらいかかります。 先生が言うには10秒台が出るとのことですが、私は頑張っても時間を短くすることができません。 下に私の作ったプログラムを載せますので短くする方法を教えて下さい。 integer table(2:50000000),pno(50000000),cnt,m,i,j m=sqrt(50000000.) do 10 i=2,m do 10 j=i*2,50000000,i table(j)=1 10 continue do 20 i=2,50000000 if(table(i).eq.0)then cnt=cnt+1 end if 20 continue write(6,610)cnt 610 format('sosu no goukei =',i8) end

  • FortranをCに書き直すにはどうしたらいいでしょうか?

    Foratranで書かれている下記のコードをCのコードに置き換えたいのですが、分かりません。 お願いします=(^v^)= C *---------------------------------------------------------* C サブルーチンWGEN C *---------------------------------------------------------* SUBROUTINE WGEN(EM,R,NN,IR,ACC,ND,DT,AMAX,VMAX,MXCYCL,ERR,UW1, * UW2) C implicit real*8(a-h,o-z) COMPLEX*16 C(4096) DIMENSION ACC(ND),UW1(ND),UW2(ND) DIMENSION E(33),X(33),EE(33) DIMENSION PDIF(2046),PHI(2049),F(2049),T(2049),SV(2049),H(1), * RES(2049,1),RR(2049) PARAMETER (PI2=6.283185) DATA DX/0.03125/,H0/0./,H/0.05/ C C DO 150 K=1,NN2-2 P=RAND2(IR) C DO 130 J=2,33 IF(P.LE.EE(J)) GO TO 140 C 130 CONTINUE C 140 PDIF(K)=-(X(J-1)+(P-EE(J-1))/(EE(J)-EE(J-1))*DX)*PI2 C 150 CONTINUE C C *---------------------------------------------------------* C ファンクションRAND01 C *---------------------------------------------------------* REAL*8 FUNCTION RAND2(I) C INTEGER*4 L,C,T30 REAL MU PARAMETER(L=843314861,C=453816693,T30=2**30,MU=2.0**31) C I=L*I+C IF(I.LT.0) I=(I+T30)+T30 RAND2=REAL(I)/MU END C

  • Fortran の DO

    Fortran 初心者です。質問があります。よろしくお願いします。 くりかえしのDOについてなのですが、Iを0から360まで30刻みで繰り返す場合は DO 10 I = 0,360,30 10 CONTINUE ですが、30というのをキーボードから入力して任意の刻み幅にしたい場合は READ(5,*) A DO 10 I = 0,360,A 10 CONTINUE としたのですが、エラーになります。なぜなのでしょうか?

  • 途中計算

    ある文章問題の途中計算ですが ∫ 1/(500-x) dx = ∫ k dt → -log[e] l 500-x l = kt+c となるのがわかりません。 私は ∫ 1/(500-x) dx = ∫ k dt → ln l 500-x l = kt+c と違う計算になります。 ∫ 1/(500-x) dx = ∫ k dt → ∫ 1/-(x-500) dx = ∫ k dt → -∫ 1/-(x-500) dx = ∫ k dt と考えても -ln l x-500 l = kt+c となり同じ答えにはなりません。 どうして-log[e] l 500-x l = kt+c になるのか説明して頂けますか? (lnとlog[e] が同じなのは知っています)

  • FORTRAN…これってどんなプログラムになりますか??

    DO 10 I=1,47 CALL SUB1 10 CONTINUE STOP END SUBROUTINE SUB1 DIMENSION B1(3),B2(3),C(3),L(3),P(3) CHARACTER*12 A READ(5,50) A,B1,B2 50 FORMAT(A12,3F8.1,3F7.1) X=1.0 DO 11 K=1,300 Y1=(-1.0) Y2=0.0 DO 12 J=1,3 L(J)=(-NINT(B1(J)*10.0/B2(J))) Y1=Y1+X**L(J) Y2=Y2+L(J)*X**(L(J)-1) 12 CONTINUE W=X-Y1/Y2 IF(ABS(W-X).LT.1E-10) GO TO 13 X=W 11 CONTINUE 13 WO=W DO 14 J=1,3 C(J)=WO**L(J) 14 CONTINUE R1=0.0 DO 15 J=1,3 R2=R1+B2(J) R1=R2 15 CONTINUE D=0.0 DO 16 J=1,3 P(J)=B2(J)/R1 D=D+P(J)*ALOG(P(J)/C(J)) 16 CONTINUE E=0.0 DO 17 J=1,3 E=E+(B1(J)/B2(J)*P(J)) 17 CONTINUE WRITE(*,200) A,B2,P,E,D 200 FORMAT(1H,2X,A12,3X,3(F7.1,2X),4X,3(F9.6,X),4X,F9.6,2X,F9.6) RETURN END

  • Fortranの倍精度実数について

    こんにちは。 現在、Fortran 90でプログラムを作成しています。 その中で、整数の倍精度実数への型変換についての疑問がわきましたので、質問させていただきます。 以下の2つのプログラムで、計算がより速く、より精度よくできるのはAとBどちらなのでしょうか。 実際は下記のプログラムが、ループの中に入っているので少しでも計算時間を短くしたいのです。 よろしくお願いいたします。 program A(毎回dxを足す) ----------------------------- real(8) :: pi, dx real(8), dimension(1000) :: x integer i, j pi=atan(1d0)*4d0 dx=pi/5000d0 x=0d0 j=1 do i=1, 1000 x(i)=x(j)+dx j=i write(*,*)x(i) end do ----------------------------- program B(毎回dx*ループ回数を計算する) ----------------------------- real(8) :: pi, dx real(8), dimension(1000) :: x integer i, j pi=atan(1d0)*4d0 dx=pi/5000d0 x=0d0 do i=1, 1000 x(i)=dx*dble(i) write(*,*)x(i) end do -----------------------------