• 締切済み

fortran 渡す値について

fortranの質問です。 integer ix,iy,maxX,maxY で宣言しており、 do istep=1,100 call B_DIF(☆) do ix=0,maxX do iy=0,maxY B_M(ix,iy)=B_P(ix,iy) end do end do end do のルーチンで悩んでいます。 B_DIFは B_P(ix,iy)=K(係数のことです)*B_M(ix,iy)+B_M(ix+1,iy)-B_M(ix-1,iy) といった感じのサブルーチンです。functionで表していないのは、ややこしい関数があるので、サブルーチンでまとめてメインに返すという手法をとっています。ご了承下さい。 ここで、B_P(☆)の☆には何を入れると適切に動くと思いますか? ☆に データix,iyを入れるだけで意とするB_P(ix,iy)がでてくるのか、 それとも、ix,iy,B_Mのデータを受け渡すべきか・・ 一番の問題は、 B_P(ix,iy)=K(係数のことです)*B_M(ix,iy)+B_M(ix+1,iy)-B_M(ix-1,iy) にix,iyを送ったとき、B_M(ix+1,iy)などが意図する値を吐いてくれるのかということです。 ix=1,iy=2でB_DIFのルーチンにおいて、 B_P(1,2)=K(係数のことです)*B_M(1,2)+B_M(2,2)-B_M(0,2) とパソコンが読み取ってくれるのか疑問です。 ちなみに、B_M(1,2)、B_M(2,2)、B_M(0,2)は既知の値です。 頭がこんがらがって、どうすべきかわかりません。 2次元配列の添字の継承・・ よろしくお願いします。

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

一応「common ブロックで渡す」と書いたけど, 明らかにそんなことをしない方がいいです. あとでプログラムを見たときに苦しむことが目に見えているので, 素直に引数で渡してください.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

「B_P(☆)の☆には何を入れると適切に動くと思いますか」の B_P は B_DIF のことでしょうか? もしそうなら, 「どのような」 (what), 「どのように」 (how) 情報を渡す必要があるのかを決めることになります. まず what については, 必要な情報は K, B_P, B_M, maxX, maxY の 5つでしょうか. それはいいんですが, 次に how の方は, 思い付くのは「引数で渡す」と「common ブロックで渡す」の 2通り. どちらがお好み? あと, 配列の定義のときは副プログラムなら整合配列 (って言うんだっけ?) が使えるはずですし, メインプログラムでも (Fortran なら) allocatable 属性を付けて定義してから適当な大きさで allocate すればいいはず>#2. #1, #2 では「Fortran の勉強」と言われてますが, なんとなくこれは「Fortran の勉強」ではすまないような感じがします. もっとはっきりいうと「(言語の問題ではなく) プログラムを組めない」という感じがします.

BOY12345
質問者

補足

>思い付くのは「引数で渡す」と「common ブロックで渡す」の 2通り. どちらがお好み? 引数で渡す方が好きです。ってか前者しかできません。 common ブロックはやり方がわかりません。(テキスト読んでも??な感じでした)覚えたいとは思っているのですが・・とっかかりが無く、習得できそうな気がしません。便利だとは思うんですけどね。 commonを使ったコードあったら教えてもらえると、嬉しいです。 勉強に役立てたいと思います。

  • equinox2
  • ベストアンサー率48% (321/660)
回答No.2

前回の質問からあまり変わっていないようですが、FORTRANの文法は読まれましたか? ●do istep=1,100 のistepはどの計算で使うのですか?  この値をB_Difの中で使うのであれば渡す必要がありますが、どこにも書かれていません。 (Kの値が istep で変わる場合は istep も渡す必要あり) ●B_DIFF呼び出しの例(未検証) 関連部分のみ記載 注:maxX,maxY の値が定数なら xxxx,yyyy は maxX、maxY の値にする   変数なら、取り得る最大の値にする real*8 B_P(xxxx, yyyy) real*8 B_M(xxxx, yyyy) ・・・ call B_DIF(B_P, B_M, maxX, maxY) ・・・ subroutine B_DIFF(B_P, B_M, ixmax, iymax) real*8 B_P(xxxx, yyyy) real*8 B_M(xxxx, yyyy) do ix=0,ixmax do iy=0,iymax B_P(ix,iy)=K * B_M(ix,iy) + B_M(ix+1,iy) - B_M(ix-1,iy) end do end do ●xxxx,yyyyが大きすぎてエラーになる場合は、配列の要素毎に渡してください。  ・二次元配列の要素で計算に必要な値を渡す。  ・計算結果は1つなのでfunctionが使える B_P(ix,iy) = B_DIF( B_M(ix,iy), B_M(ix+1,iy), B_M(ix-1,iy) ) ・・・ real*8 function B_DIF(a, b, c) B_DIF = K * a + b - c return end

BOY12345
質問者

補足

●do istep=1,100 のistepはどの計算で使うのですか? すいません、書くの忘れてました。 if (mod(istep,nwrite).eq.0) then ic=ic+1 って感じで使っています。 nwrite刻みでファイル出力する形をとっています。 nwriteはintegerで定数定義しています。 上記の後に、 isen=ic/1000 ihun=mod((ic/100),10) iten=mod((ic/10),10) ione=mod(ic,10) * ofile='temp.'//char(48+isen) &//char(48+ihun)//char(48+iten)//char(48+ione) write(6,*) ic,ofile open(16,status='unknown',file=ofile) が続きます。

  • fifaile
  • ベストアンサー率25% (622/2403)
回答No.1

何がしたいのか・・・ subroutineにしてもfunctionにしても、 副関数で定めた引数を渡さないとダメですよ。 >パソコンが読み取ってくれるのか疑問です。 ためしてみました? おそらくFortranの基礎がまったくわかっていないのが問題です。 勉強しなおしてください。

BOY12345
質問者

補足

試しました。 うまく動作しない!!との事実だけがわかりました。 で、デバック作業してるんですが、、、 正直、B_P(ix+1,iy),B_P(ix,iy)とかを別途、functionで定義して、それとのやり取りをして、メインに返すのがいいのかなと思ったんですが、それだとごちゃごちゃするので、もっとスムーズに組めるのではないかと思って、皆さんに尋ねています。

関連するQ&A

  • 配列が定義されていない??

    今日1日を費やして、fortranの勉強をしました。 まだまだ勉強始めたばかりで、何かと苦労しています。 理解しようと、本にPCとにらめっこしています。 本日の問題は・・以下です。 問題と思われる箇所載せておきます。 subroutine Uno(ya,Mc,nablaMc, & maxX,maxY,numX,numY,dt,dx,dy, & v,v_P,nablaya) implicit real*8 (a-h,o-z) * real*8 v(0:maxX,0:maxY),v_P(0:maxX,0:maxY) * CDK write(6,1000) dx,dy,dt * ic=0 1 continue ic=ic+1 * do ix=1,numX-1 do iy=1,numY-1 C---- nablayaを定義------------------------------------ ★ nablaya=v(ix,iy+1)-v(ix,iy-1))/*dy C ------------------------------------------------------ A=v(ix,iy)*ya+nablaya*v(ix,iy) B=v(ix,iy)*ya C------------------------------------------------------- if (iy.eq.1) then ai=2.0d0*dt*B*(1.0d0/(dx*dx)+1.0d0/(dy*dy) bi=dt*(A/(4.0d0*dy)+B/(2.0d0*dy*dy)) else ai=2.0d0*dt*B+A/(dy*dy) bi=A/(4.0d0*dy)+B/(2.0d0*dy*dy) ・・ といった感じのルーチンを書きました。 そしたら、 『Error: The shapes of the array expressions do not conform. [NABLAYA]』と指摘され、その場所が上記★の行でした。 何がいけないのでしょうか!? 教えて下さい。

  • fortran

    do I = 1,40 do F = 1,4 do L = 1,100 if (I == 1. .OR. L == 1.) then A (I,F,L) = 3. else A (I,F,L) = 3.* B (I-1,F,L) end if end do end do do F = 1,4 do L = 1,100 do M = 1,100 B (I,F,L) = B (I,F,L) + C (I,F,M,L) end do end do end do end do 簡素化したプログラムなので、わかりにくいと思うのですが、後で計算するB(I,F,L)をA(I,F,L)のDOループに最初に持ってくると、I=1orL=1のときは正しい計算をしてくれるのですが、そのほかのときはB(I-1,F,L)に値が入らないのです。ちなみにC(I,F,M,L)はA(I,F,L)のループの後に計算しましたが、省略しました。 ご回答よろしくお願いします。

  • fortran errorについて

    fortranを勉強していたのですがエラーがでてしまい、何時間かけても理解できなかったので質問させてください。 以下プログラム program test !ここからメインルーチン !前準備 配列の用意 implicit none integer N integer,dimension(0:N,0:N) :: A integer :: i,j,k read * ,N !初期状態の代入 do i=0,N do j=0,N A(i,j)=0 end do end do do i=N/2,N-1 A(N/2,i)=1 end do do i=N/2,N-1 A(N/2+1,i)=-1 end do !ループ 50回ループさせる do k=0,50 !状態の表示 call visualize !サブルーチン visualize subroutine visualize do i=0,N do j=0,N if(A(i,j)== 1) write(*,'(A1)',advance='NO') "*" if(A(i,j)== 0) write(*,'(A1)',advance='NO') " " if(A(i,j)==-1) write(*,'(A1)',advance='NO') "+" end do write(*,*) end do !end subroutine visualize call insert !サブルーチン insert subroutine insert do i=0,N do j=0,N if(A(i,j)== 1) A(i,j)=-1 if(A(i,j)== 0) A(i,j)=max(0,A(i-1,j),A(i,j-1),A(i,j+1),A(i+1,j)) if(A(i,j)==-1) A(i,j)=0 end do end do !end subroutine insert end do end program test これでコンパイラすると In file test.f90:48 subroutine visualize 1 Error: Unclassifiable statement at (1) In file test.f90:69 subroutine insert 1 Error: Unclassifiable statement at (1) とでます いろいろ調べたのですが全くわかりませんでした できればよろしくお願いします

  • FORTRAN 初心者です

    以下の連立一次方程式をSOR法で解く問題です。 初心者なりにガウスザイデル法を応用してプログラムしたつもりですが、やはり難しいです(答えは違います)。 どこをどうすれば良いのか分かりませんので、よろしければヒントや助言をいただきたいです。 PROGRAM SOR REAL A(10,10),B(10),X(10),X0(10) INTEGER N,I,J,K,Kmax,w N=3 A(1,1)=4 ;A(1,2)=1 ;A(1,3)=2 A(2,1)=1 ;A(2,2)=3 ;A(2,3)=1 A(3,1)=1 ;A(3,2)=2 ;A(3,3)=5 B(1)=16 B(2)=10 B(3)=12 X0(1)=1 ;X0(2)=1 ;X0(3)=2 w=1.2 Kmax=50 EPS=1.D-5 DO I=1,N D=A(I,I) S=B(I) B(I)=B(I)/D END DO DO K=1,Kmax DO I=1,N DO J=1,N if(J<I) X0(J)=X(J) S=S-A(I,J)*X0(J) END DO X(I)=(1-w)*X(I)+w*S END DO DO I=1,N S=S-(X(I)-X0(I))**2 END DO IF(S<EPS) GOTO 10 DO I=1,N X0(I)=X(I) END DO END DO 10 WRITE(*,*) K DO I=1,N WRITE(*,*) 'SOR法で求めた解は' WRITE(*,*) 'X(',I,')=',X(I) END DO END PROGRAM SOR !------------------------------------ ※wは緩和係数です

  • fortranで・・・

    実行の画面に数字を入力すると、 英語の文章と 0.0 0.0 0.0 -NaN -NaN -NaN という文字が出てくるだけなんですが、これはプログラムが組めていないということなのでしょうか? ちなみに、打ったプログラムは、 C 判別関数 WRITE(*,100) 100 FORMAT(1H1/22X,'判別関数モデル'//19X,'消費量',3X,'消費比率'//19X, +'清酒',5X,'焼酎',5X,'ビール',7X,'清酒',6X,'ビール',7X,'M'10X,'D'/ +/) 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 50 FORMAT(3F8.1,3F7.1) X=1.0 DO 11 K=1,300 Y1=(-1.0) Y2=0.0 DO 12 J=1,3 B2=0.0 B1=0.0 L(J)=(-NINT(B1(J)*10.0/B2(J))) S1=Y1+X**L(J) S2=Y2+L(J)*X**(L(J)-1) Y1=S1 Y2=S2 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 DO=D+P(J)*ALOG(P(J)/C(J)) D=DO 16 CONTINUE E=0.0 DO 17 J=1,3 EO=E+(B1(J)/B2(J)*P(J)) E=EO 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 3次元座標

    四面体の4頂点の3次元座標を設定するプログラムを例にならって以下のように書いたのですが、doループの内容がいまいちよくわかりません。p(1:3,m),p(1:3,n)が表されている値は理解できるのですが、出力されたファイルの内容が2行3列の答えが6つあって、なぜそのように答えが出てくるのかがわかりません。教えて下さい。よろしくお願いします。 rogram list2_11 implicit none integer :: m, n, fno = 10 real(8) p(3,4) call random_seed call random_number(p(1:3,1:4)) open(fno, file = 'tetra.d') do m = 1, 3 do n = m+1, 4 write(fno,*) p(1:3,m) write(fno,*) p(1:3,n) write(fno,*) '' enddo enddo close(fno) end program list2_11

  • fortranについての質問です。

    fortranについての質問です。 このFortranは、頭にそれぞれ14161~14163とつく33個のファイル(1/1~12/31,欠損地あり1年分)を読んでいき、例えば1/1、1/2…と365日分の33年の平均値を導くはずなのですが、下のようなエラーがでます。おそらく、14161が2008までないからではないかと思うのですが、現在勉強中なので、なにかアドバイス、おかしいところ修正できるところがありましたらお願いします。 program sapporo_kikouchi    INTEGER :: sum, no, point INTEGER :: year, mon, day, data INTEGER :: doy REAL,dimension(365) :: temp, ndata REAL :: lon, lat CHARACTER*4 yyyy CHARACTER*5 sssss ndata(:)=0.0 temp(:)=0.0 do ispot=14161,14163 write(sssss,"(i5)") ispot do iwork=1976, 2008 write(yyyy,"(i4.4)") iwork open(50, file=''//sssss//'_temp'//yyyy//'.csv', status='old') ! write(6,*) ispot iwork    do i = 1,366 read(50,*,iostat=io) id,year,mon,day,lon,lat,data if(io < 0) exit if(mon==2 .AND. day==29) then cycle endif call date2doy(year,mon,day,doy) temp(doy) = temp(doy) + data/10.0 ndata(doy) = ndata(doy) + 1 end do close(50) enddo !!! end of year loop enddo do i=1,365 if( ndata(i) == 0 ) then temp(i) = -99999.9 else temp(i)=temp(i)/ndata(i) endif write(6,*) i, temp(i), ndata(i) enddo stop end program subroutine date2doy(iy,im,id,idoy) INTEGER,dimension(12) :: nday INTEGER :: uruu !!uruu=1: うるう年、uruu=0: 通常の年 uruu=0 DATA nday /31,28,31,30,31,30,31,31,30,31,30,31/ if(mod(iy,4)==0 .AND. mod(iy,100)/=0) then uruu=1 endif if(mod(iy,1000)==0) then uruu=1 endif !! うるう年も無視する itotal = 0 if( im /= 1 )then do m=1, im-1 itotal = itotal + nday(m) enddo endif idoy = id + itotal ! write(6,*) iy,im,id, idoy return end ------------------------------------------------------------------------------ At line 18 of file kikouchi.f90 file: "14161_temp1993.csv" Traceback: not available, compile with -ftrace=frame or -ftrace=full Fortran runtime error: 指定されたファイルが見つかりません。 -------------------------------------------------------------------------------

  • Fortranの問題3問目です。急いでます><

    以下のプログラムを実行すると結果がNAN(数値エラー)となり、表示されない。 これは、ガウスの消去法における、ある問題に起因する。 正しい結果がでるようにするには、どうしたらよいか? 答えが正しく表示されない原因を究明し、正しい結果を表示する、 修正済みソースコードを提出しなさい。 ヒント: 一般に、どのような行列でも計算できるプログラムにするためには、 「ピボット」と呼ばれる操作を行う必要があるが、 今回は、ピボットをあらかじめ人間が行うことで回避してよい. プログラムの処理内容(アルゴリズム)を修正する必要はない。 program gauss implicit none c aは係数行列(4x3)、xは解、w は一時変数 double precision a(5,4),x(4),w integer i,j,k c キーボードから読み込む場合 write(6,*) 'input a(5,4)' c read(5,*) a c data文で一括初期化(代入)する方法 data a / & 0d0, 3d0, 7d0, 2d0, 65d0, & 2d0, 8d0, 5d0, 1d0, 65.4d0, & 5d0, 3d0,-5d0, 2d0, 3.8d0, & -2d0, 4d0, 0d0, -6d0, -35.6d0 & / write(6,*) 'データの確認表示' write(6,'(f8.2,f8.2,f8.2,f8.2,f8.2)') a c 前進消去 do k=1,3 do j=k+1,4 w = -a(k,j)/a(k,k) write(6,*) w,'*行',k,'を、行',j,'に足すと' do i=1,5 a(i,j) = a(i,j) + w*a(i,k) end do write(6,'(f8.2,f8.2,f8.2,f8.2,f8.2)') a write(6,*) '' end do end do write(6,*) '前進消去 終了' write(6,'(f8.2,f8.2,f8.2,f8.2,f8.2)') a c 後退代入 do k=4,1,-1 x(k) = a(5,k) do i=k+1,4 c 注:k=3のとき, do i=4,3 となるためループ内は1回も実行しない c k=2のとき, do i=3,3 となり、ループ内はi=3 で1回だけ実行 x(k) = x(k) - a(i,k)*x(i) end do x(k) = x(k) / a(k,k) end do c 解を表示 write(6,*) 'x = ',x stop end

  • fortran 途中まで考えたのですが。。。。

    エラトステネスのふるい(素数の倍数を除いていって残ったのが素数)で3桁の素数を求めて表示したいです。 私が考えたのは、 1・2~99までの数を素数かどうか調べて、素数を配列に入れていく 2・100~999まで素数の配列の中の数で割って、割り切れたらおしまい。割り切れなかったら表示していく ということです。 しかし下のプログラムではうまく素数配列ができていないようなのです。 ここまでかなり時間がかかったのでこのプログラムに手をいれて これ以外におかしくなるところもどこを直せばいいのか教えてくださるとうれしいです。 C C q223.f C PROGRAM q223 C IMPLICIT NONE C INTEGER N,i,K,s,l REAL a(99),b(99),c(99),X,Y C real M C a(1)=2 a(2)=3 l=2 C DO N=2,99,1 M=N**(0.5) S=M DO i=2,S,1 K=MOD(N,i) IF(K ==0)THEN exit ELSE IF(K /=0)THEN l=l+1 a(l)=N ENDIF ENDDO ENDDO C do N=100,999 do l=1,99 X=a(l) Y=N/X if(Y==0)then exit else if(Y/=0)then write(*,*)N end if end do end do c end よろしくおねがいします

  • fortran77教えてください

    fortran77の問題で次のプログラムの作成の仕方を教えてください 整数A,B,Cを読み込み、それを係数とする2次方程式Ax^2+Bx+C=0の解を計算して表示するプログラムを サブルーチン副プログラムを用いて作成せよ(複素数型を使うこと) メインプログラムでは整数A,B,Cの入力および解の出力および解の出力を行い解の計算はサブルーチン副プログラムで行うこと なお'keisan.txt'という名前のデータファイルに結果を出力するように 計算時は以下の3つの方程式を用いること x^2+3x+5=0 X^2+6x+4=0 x^2+x+1=0

専門家に質問してみよう