ルンゲクッタ法によるマクスウェルモデルの微分方程式の解法と修正方法

このQ&Aのポイント
  • この質問は、ルンゲクッタ法を使用してマクスウェルモデルの微分方程式を解く方法についてのものです。
  • 質問者は、プログラムを作成したものの、エラーが表示されて動作しない状態になっています。どこを修正すれば良いかを教えてほしいとしています。
  • また、質問者は、他の微分方程式の解き方を理解しているが、この形の方程式の解き方が分からないと述べています。もっと効果的な解法がある場合は教えてほしいとも言っています。
回答を見る
  • ベストアンサー

ルンゲクッタ法によるマクスウェルモデルの微分方程式

大学の課題で dγ/dt=1/G(dσ/dt)+σ/η (但しt=時刻、Gは弾性要素の定数、ηは粘性要素の定数) に γ=1(t≧0) γ=0(t<0) のような階段状の歪みを加えた時 応力σ(t)の時間変化をルンゲクッタ法を用いて時間の刻み幅0.1 時刻20まで求めるプログラムを作成しろ というのがあります。作ってはみたものの ex.c: In function `main': ex.c:20: called object is not a function ex.c:22: called object is not a function ex.c:24: called object is not a function ex.c:26: called object is not a function と表示されて動きません。だれかどこをどう修正すれば良いか教えてください。 #include <stdio.h> double g(double t,double sigma,double z); double f(double t); int main(void){ double t,sigma,dt,count,tstart,z; double x1,x2,x3,x4; sigma=2.0; /*σの初期値を2とした*/ dt=0.1; /*刻み幅0.1*/ count=20.0; /*20まで表示*/ tstart=0.0; /*0から表示*/ for(t=tstart;t<count;t+=dt){ z=(f(t+dt)-f(t))/dt; /* z=dγ/dt */ x1=dt*g(t,sigma,z,); x2=dt*g(t+dt/2,sigma+x1,z); x3=dt*g(t+dt/2,sigma+x2,z); x4=dt*g(t+dt/2,sigma+x3,z); sigma=sigma+(x1+2.0*x2+2.0*x3+x4)/6.0; t=t+dt; printf("%f %f\n", t, sigma); /*tを表示  σを表示*/ } } double f(double t){ double ganma; if(t>=0)ganma=1; /*  γ=1(t≧0)  */ else ganma=0; /*  γ=0(t<0)  */ return(ganma); } double g(double t,double sigma,double z){ double ita,g,uhen; ita=10.0; g=2.0; /*与式を変形をし dσ/dt=(dγ/dt-σ/η)*G  右辺の関数がg()である*/ uhen=(z-sigma/ita)*g; /*η=10 G=2とした*/ return(uhen); } いろいろ調べてみたのですが、dy/dx=x+y などのような微分方程式の解き方は分かるのですが、上記のような微分方程式の解き方がわかりません。だから無理やりdγ/dtを求めて自分が解ける形にもっていったのですが、もっときれいな求め方があるならそれも教えてください。お願いします。

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

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.1

微分方程式の解き方は全くわかりませんけれど、 >double g(double t,double sigma,double z){ > >double ita,g,uhen; 関数名と同じ名前の変数を使っているのがまずいと思います。

関連するQ&A

  • 常微分方程式、4次のルンゲクッタ法

    (d^2x/dt^2)-2(dy/dt)=f(x) (d^2y/dt^2)+2(dx/dt)=g(y) この連立常微分方程式を4次のルンゲクッタ法で解くためにはどうすればいいのでしょうか?

  • 連立微分方程式の解き方

    d^2x/dt^2=f(t) d^2y/dt^2=g(t, y, dy/dt, z, dz/dt, d^2z/dt^2) d^2z/dt^2=h(t,d^2y/dt^2, z, dz/dt) というような連立微分方程式を解きたいのですが,どのような方法で解くことができるのでしょうか? ルンゲ・クッタは適用できますか? (d^2y/dt^2の式にd^2z/dt^2が変数として出てきたりしているので,わからなくなってしまいました.) 宜しくお願いします.

  • 微分方程式を解くアルゴリズムである ルンゲクッタ法

    微分方程式を解くアルゴリズムである ルンゲクッタ法の課題が出されました。 入力が周期1秒,最大値Eの矩形パルスということで 0.5秒周期でe(初期値10)を0⇒10⇒0⇒10⇒1とクロックさせたいのですが ファイルに出力してみるとずっと10のままで,0にクロックしていません・・・ 何処が原因か教えていただきたいです;; ほかにも問題があればご指摘していただきたいです>< ![イメージ説明](7309564d21bbda3453db49c0ec6147d9.jpeg) #include <stdio.h> #include <stdlib.h> #include <math.h> double clock(double E){ if(E==10) return 0; else return 10; } double dxdt(double x,int E){ double c = 0.001; double r = 50000; return (E-x)/(r*c); } // ルンゲクッタ法(初期条件x0, 区間[t0, tn]) double runge(double x0, double t0, double tn, int n) { FILE *output; FILE *output1;FILE *output2; output=fopen("output.txt","w"); output1=fopen("output1.txt","w"); output2=fopen("output2.txt","w"); double i; double x, t, h, d1, d2, d3, d4,cnt,e; x = x0; t = t0; e = 10; cnt=0; h = 0.01; // 漸化式を計算 for ( i=1; i <= n ; i++){ if(cnt==0.500000){e=clock(e); cnt=0;} t = t0 + i*h; d1 = dxdt(x,e); d2 = dxdt(x + d1*h*0.5,e); d3 = dxdt(x + d2*h*0.5,e); d4 = dxdt(x + d3*h,e); cnt= cnt + h; x += (d1 + 2 * d2 + 2 * d3 + d4)*(h/6.0); fprintf(output,"%f\n",t); fprintf(output1,"%f\n",x); fprintf(output2,"%f\n",e); } return x; } int main(void) { runge(0, 0, 1000, 50000); return 0; } ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

  • ルンゲクッタ法で数値解析(C言語)

    コンピュータ(プログラミング)のカテゴリに投稿しようかとも考えましたが、物理学に関する数値計算ということなので、物理学のカテゴリに投稿しました。 単振動や減衰振動、そして強制振動などを数値解析したいと思い、ルンゲクッタ法を使いシミュレートしてみようとしています。ルンゲクッタ法という方法を全く知らなかったので、インターネットや図書館で調べたのですが、どうしても分からないことろがあるので質問することにしました。 書籍やネットの情報を参考にしながら、単振動の場合を数値解析してみました(C言語を使って)。この単振動はうまくできたのですが、どうしても、その先の、減衰振動の数値解析がうまくいかないので、困っています。 ---- #include <stdio.h> double f1(double t,double x,double v); double f2(double t,double x,double v); int main() { double t,x,v,dt,tmax; double k1[2],k2[2],k3[2],k4[2]; x=1.0; //位置の初期値 v=0.0; //速度の初期値 dt=0.01; //刻み幅 tmax=500.0; //繰り返し最大回数 FILE *output; output=fopen("output.dat","w"); for(t=0;t<tmax;t+=dt) { k1[0]=dt*f1(t,x,v); k1[1]=dt*f2(t,x,v); k2[0]=dt*f1(t+dt/2.0,x+k1[0]/2.0,v+k1[1]/2.0); k2[1]=dt*f2(t+dt/2.0,x+k1[0]/2.0,v+k1[1]/2.0); k3[0]=dt*f1(t+dt/2.0,x+k2[0]/2.0,v+k2[1]/2.0); k3[1]=dt*f2(t+dt/2.0,x+k2[0]/2.0,v+k2[1]/2.0); k4[0]=dt*f1(t+dt,x+k3[0],v+k3[1]); k4[1]=dt*f2(t+dt,x+k3[0],v+k3[1]); x=x+(k1[0]+2.0*k2[0]+2.0*k3[0]+k4[0])/6.0; v=v+(k1[1]+2.0*k2[1]+2.0*k3[1]+k4[1])/6.0; fprintf(output,"%f %f %f\n",t,x,v); } fclose(output); return 0; } double f1(double t,double x,double v) { return v; } double f2(double t,double x,double v) { return (-x); } ---- このソースは単振動のもので、減衰振動のときは、最後の方の ---- double f1(double t,double x,double v) { return v; } double f2(double t,double x,double v) { return (-x); ---- の部分が変わるのだと思うのですが、よく分かりません。 減衰振動は、mx"=-kx-rx'で表されるので、この式を変形(?)したものが、入るのかな、という予想程度にしか分かりません。 ソースをどのように変えれば減衰振動を解析できるのでしょうか。 どなたか詳しい方、教えてください。お願いします。

  • 配列を用いたC言語プログラミングについて

    以下のルンゲクッタ法を用いたプログラムに配列などを使いさらに短くしたいのですが どのような方法が有りますか? #include <stdio.h> #include <math.h> double f1(double t1,double w,double x,double y,double z); double f2(double t1,double w,double x,double y,double z); double f3(double t1,double w,double x,double y,double z); double f4(double t1,double w,double x,double y,double z); //箱Aの関数 double g1(double t1,double a,double b,double c,double d); double g2(double t1,double a,double b,double c,double d); double g3(double t1,double a,double b,double c,double d); double g4(double t1,double a,double b,double c,double d); //箱Bの関数 int main(void) { double t1,w,x,y,z,a,b,c,d,dt,t1max,t2max,lam,gam,lat,dw,dx,dy,dz,da,db,dc,dd ; double k1[4],k2[4],k3[4],k4[4],l1[4],l2[4],l3[4],l4[4] ; ///宣言 t1 = 0.0; dt = 0.3; t1max = 40.0; //時間初期値 w = 200.0; x = 40.0; y = 30.0; z = 30.0; ///箱A初期値(w:感受性人口、x:潜伏人口、y:感染人口、z:隔離人口) a = 20.0; b = 8.0; c = 12.0; d = 10.0; ///箱B初期値(a:感受性人口、b:潜伏人口、c:感染人口,d:隔離人口) for(t1=0.0;t1<=t1max;t1+=dt) { k1[0]=dt*f1(t1,w,x,y,z); k1[1]=dt*f2(t1,w,x,y,z); k1[2]=dt*f3(t1,w,x,y,z); k1[3]=dt*f4(t1,w,x,y,z); k2[0]=dt*f1(t1+dt/2.0,w+k1[0]/2.0,x+k1[1]/2.0,y+k1[2]/2.0,z+k1[3]/2.0); k2[1]=dt*f2(t1+dt/2.0,w+k1[0]/2.0,x+k1[1]/2.0,y+k1[2]/2.0,z+k1[3]/2.0); k2[2]=dt*f3(t1+dt/2.0,w+k1[0]/2.0,x+k1[1]/2.0,y+k1[2]/2.0,z+k1[3]/2.0); k2[3]=dt*f4(t1+dt/2.0,w+k1[0]/2.0,x+k1[1]/2.0,y+k1[2]/2.0,z+k1[3]/2.0); k3[0]=dt*f1(t1+dt/2.0,w+k2[0]/2.0,x+k2[1]/2.0,y+k2[2]/2.0,z+k2[3]/2.0); k3[1]=dt*f2(t1+dt/2.0,w+k2[0]/2.0,x+k2[1]/2.0,y+k2[2]/2.0,z+k2[3]/2.0); k3[2]=dt*f3(t1+dt/2.0,w+k2[0]/2.0,x+k2[1]/2.0,y+k2[2]/2.0,z+k2[3]/2.0); k3[3]=dt*f4(t1+dt/2.0,w+k2[0]/2.0,x+k2[1]/2.0,y+k2[2]/2.0,z+k2[3]/2.0); k4[0]=dt*f1(t1+dt,w+k3[0],x+k3[1],y+k3[2],z+k3[3]); k4[1]=dt*f2(t1+dt,w+k3[0],x+k3[1],y+k3[2],z+k3[3]); k4[2]=dt*f3(t1+dt,w+k3[0],x+k3[1],y+k3[2],z+k3[3]); k4[3]=dt*f4(t1+dt,w+k3[0],x+k3[1],y+k3[2],z+k3[3]); ///箱Aルンゲクッタ l1[0]=dt*g1(t1,a,b,c,d); l1[1]=dt*g2(t1,a,b,c,d); l1[2]=dt*g3(t1,a,b,c,d); l1[3]=dt*g4(t1,a,b,c,d); l2[0]=dt*g1(t1+dt/2.0,a+l1[0]/2.0,b+l1[1]/2.0,c+l1[2]/2.0,d+l1[3]/2.0); l2[1]=dt*g2(t1+dt/2.0,a+l1[0]/2.0,b+l1[1]/2.0,c+l1[2]/2.0,d+l1[3]/2.0); l2[2]=dt*g3(t1+dt/2.0,a+l1[0]/2.0,b+l1[1]/2.0,c+l1[2]/2.0,d+l1[3]/2.0); l2[3]=dt*g4(t1+dt/2.0,a+l1[0]/2.0,b+l1[1]/2.0,c+l1[2]/2.0,d+l1[3]/2.0); l3[0]=dt*g1(t1+dt/2.0,a+l2[0]/2.0,b+l2[1]/2.0,c+l2[2]/2.0,d+l2[3]/2.0); l3[1]=dt*g2(t1+dt/2.0,a+l2[0]/2.0,b+l2[1]/2.0,c+l2[2]/2.0,d+l2[3]/2.0); l3[2]=dt*g3(t1+dt/2.0,a+l2[0]/2.0,b+l2[1]/2.0,c+l2[2]/2.0,d+l2[3]/2.0); l3[3]=dt*g4(t1+dt/2.0,a+l2[0]/2.0,b+l2[1]/2.0,c+l2[2]/2.0,d+l2[3]/2.0); l4[0]=dt*g1(t1+dt,a+l3[0],b+l3[1],c+l3[2],d+l3[3]); l4[1]=dt*g2(t1+dt,a+l3[0],b+l3[1],c+l3[2],d+l3[3]); l4[2]=dt*g3(t1+dt,a+l3[0],b+l3[1],c+l3[2],d+l3[3]); l4[3]=dt*g4(t1+dt,a+l3[0],b+l3[1],c+l3[2],d+l3[3]); ///箱Bルンゲクッタ w=w+((k1[0]+2.0*k2[0]+2.0*k3[0]+k4[0])/6.0); x=x+((k1[1]+2.0*k2[1]+2.0*k3[1]+k4[1])/6.0); y=y+((k1[2]+2.0*k2[2]+2.0*k3[2]+k4[2])/6.0); z=z+((k1[3]+2.0*k2[3]+2.0*k3[3]+k4[3])/6.0); a=a+((l1[0]+2.0*l2[0]+2.0*l3[0]+l4[0])/6.0); b=b+((l1[1]+2.0*l2[1]+2.0*l3[1]+l4[1])/6.0); c=c+((l1[2]+2.0*l2[2]+2.0*l3[2]+l4[2])/6.0); d=d+((l1[3]+2.0*l2[3]+2.0*l3[3]+l4[3])/6.0); } return 0; }

  • 偏微分

    「z=f(x,y),x=x(t),y=y(t)のときd^2z/dt^2を求めよ」という問題なのですが、 dz/dt=(∂z/∂x)(dx/dt)+(∂z/∂y)(dy/dt) まではわかったのですが、最終的な答えが導けません。どなたかご教授願います。

  • 微分方程式

    微分可能な関数f(x)が, ∫[0~x]f(t)dt=x^3-3x^2+x+∫[0~x]tf(x-t)dt をみたしている. このとき, f(x)を求めよ. 与式の左辺をF(x), 右辺をG(x)とおくと, F(x)=G(x) ⇔ F'(x)=G'(x) かつ F(a)=G(a)となるような定数aが存在するー(※) F(0)=G(0)=0より, (※) ⇔ F'(x)=G'(x) h'(x)=f(x), g"(x)=f(x)とすると ∫[0~x]tf(x-t)dt=[-tf(x-t)][0~x]+∫[0~x]F(x-t)dt=-xF(0)-g(0)+g(x) より,与式の両辺をxで微分すると, f(x)=3x^2-6x+1+F(x)-F(0)=3x^2-6x+1+∫[0~x]f(t)dtー(1) 再びxで微分して, f'(x)=6x-6+f(x) f(x)=yとおくと, dy/dx=6x-6+y 6x+y=uとおくと, dy/dx=du/dx-6より, du/dx=u u≠0のとき,  du/u=dx ⇔∫du/u=∫dx ⇔log|u|=x+c (c:積分定数) ⇔u=±e^(x+c) ⇔y=±e^(x+c)-6x (1)にx=0を代入して,f(0)=1 ⇔ ±e^c=1 ⇔ c=0 ∴y=±e^x-6x また, u=0のとき, y=-6xより,(1)に代入すると, -6x=3x^2-6x+1-3x^2 ⇔ 0=1となり, いかなるxについてもこれは成り立たず不適. ∴f(x)=±e^x-6x 添削お願いします.

  • 単振動の微分方程式を刻みhについてルンゲクッタで求める。

    m*d^2x/dt^2=-kx x(0)=1 dx/dt=0 というのが与えられて二階微分だから一階微分にするために dx(t)/dt=v(t) dv(t)/dt=-k*x(t)/mという式を立てました。オイラー法ではできたのですが2次、4次のルンゲクッタだとできません。どなたか回答お願いします。

  • 微分方程式

    こんにちは。微分方程式の問題が解けなくて困っています。 次のx(t)に関する微分方程式 d^2x/dt^2=-1/x^2 ただし初期条件はt=0でx=X0(x0>0),dx/dt=√2であるとする。 (1) 与式の両辺にdx/dtを乗じて積分することにより、初期条件を満たすxについての1階微分方程式をもとめよ。 必要ならば、公式d/dt(dx/dt)^2=2*(dx/dt)*(d^2x/dt^2) (2)0<x0<1のときt(t≧0)餓変化した場合のx(t)の最大値を求めよ。 (1)は与式の両辺にdx/dtをかけて dx/dt(d^2x/dt^2)=-1/x^2*(dx/dt) 与えられた公式をつかい (1/2)*d/dt*(dx/dt)^2=-dx/dt*(1/x^2) (1/2)*d/dx*(dx/dt)^2=-(1/x^2) 両辺xで積分すると (dx/dt)^2=2/x+2(1-1/X0)(初期条件より) (2) は dt/dxが0すなわち1/xが-(1-1/X0)のときかとおもったのですが よくわからないです。 どなたかおねがいします。。

  • 二階の全微分について

    物理でxyの座標を極座標に変換し加速度を計算するなかで、2階の全微分に困っています。あまり、微分積分は慣れていないので、丁寧に教えていただけると助かります。 http://okwave.jp/qa/q2707943.html でも、同じような質問があります。 一階の全微分はわかりますが、2階の全微分で項が増えるのがわかりません。 具体的には、 Z=f(X,Y), X=g(t) Y=h(t)で、 dZ/dt=(∂Z/∂x)dx/dt+(∂Z/∂y)dy/dt まではよくわかり、これを二階にするときはまず、第1項目(∂Z/∂x)dx/dtが {∂/∂x(∂Z/∂x)dx/dt}dx/dt+{∂/∂y(∂Z/∂x)dx/dt}dy/dt となるだと思うのですが、(∂Z/∂x)d/dt(dx/dt)という項も加わるようです。詳しくその考え方を教えていただけますでしょうか?

専門家に質問してみよう