LOOPが抜けられない

 投稿者:島村1243  投稿日:2015年 6月11日(木)11時03分36秒
  下記プログラムの、SUB Vsen(n)内のDO-LOOPによる等電位線作図で、vv=0.16までは正常に線を描くのですが、vv=0.12のときにLOOPが抜けられず、線が僅かずつズレながら継続書きされてしまいます。
その原因がわからず弱っています。お分かりになる方おられましたらお教えください。

!****** 画面領域、電荷(総数・大きさ・座標位置)の設定 *****
DIM Qi(3),xi(3),yi(3)
LET Nq=3        !描画電荷数のセット
LET Qi(1)=2     !第1番電荷の値セット
LET xi(1)=10     !第1番電荷のx座標セット
LET yi(1)=5     !第1番電荷のy座標セット
LET Qi(2)=2    !第2番電荷の値セット
LET xi(2)=-10    !第2番電荷のx座標セット
LET yi(2)=-5     !第2番電荷のy座標セット
LET Qi(3)=-1  !第3番電荷の値セット
LET xi(3)=-10     !第3番電荷のx座標セット
LET yi(3)=0    !第3番電荷のy座標セット

LET windowX=35  !画面X軸の大きさセット
LET windowY=35  !画面Y軸の大きさセット
SET WINDOW -windowX,windowX,-windowY,windowY
DRAW grid
!**** ここまで ***********

!**********************************************
! 第i電荷Qiによる(x,y)点の電界(Exi,Eyi)算出関数
!**********************************************
DEF Exi(Qi,x,xi,ri)=Qi*(x-xi)/ri^3
DEF Eyi(Qi,y,yi,ri)=Qi*(y-yi)/ri^3

!***************************
!   Sub関数とFunction関数
!***************************
FUNCTION V(x,y)!---(x,y)点の合成電位Vの算出関数
   LET Vsum=0
   FOR nk=1 TO Nq
      IF x<>xi(nk) OR y<>yi(nk) THEN
         LET Vsum=Vsum+Qi(nk)/SQR((x-xi(nk))^2+(y-yi(nk))^2)
      ELSE
         PRINT "点電荷位置の電位(無限大)を誤計算したので停止します。"
         STOP
      END IF
   NEXT nk
   LET V=Vsum
END FUNCTION

SUB Denkai(x,y,Ex,Ey)!---(x,y)点の合成電界算出関数
   LET Ex=0
   LET Ey=0
   FOR nk=1 TO Nq
      LET ri=SQR((x-xi(nk))^2+(y-yi(nk))^2)
      LET Ex=Ex+Exi(Qi(nk),x,xi(nk),ri)
      LET Ey=Ey+Eyi(Qi(nk),y,yi(nk),ri)
   NEXT nk
END SUB

SUB Newton(n,vv,x0,y0,xs,ys,over)!---等電位線の描画開始座標の算出
   LET over=0
   LET xs=x0+0.001!DELTA
   LET ys=y0
   DO
      CALL Denkai(xs,ys,Exs,Eys)
      LET Vxs=V(xs,ys)
      LET x1=xs+(Vxs-vv)/Exs
      LET Vx1=V(x1,ys)
      LET xs=x1
      IF vv=0 THEN
         IF ABS(Vx1)<=0.0001 THEN EXIT DO
      ELSEIF ABS((Vx1-vv)/vv)<=0.001 THEN
         EXIT DO
      ELSEIF xs>windowX THEN
         LET over=1
         EXIT DO
      END IF
   LOOP
END SUB

SUB Vsen(n)!---電荷による等電位線の描画関数
   FOR vv=vstart TO vend STEP vstep
      CALL Newton(n,vv,xi(n),yi(n),xs,ys,over)
      IF over=1 THEN GOTO 10
      PLOT LINES:xs,ys;
      LET count=0
      LET x1=xs
      LET y1=ys
      DO
         CALL Denkai(x1,y1,Ex1,Ey1)
         LET kakudo=ANGLE(-Ey1,Ex1)
         LET x2=x1+dlv*COS(kakudo)
         LET y2=y1+dlv*SIN(kakudo)
         LET rck=SQR((x2-xs)^2+(y2-ys)^2)
         IF count>=50 AND rck<=0.1 THEN EXIT DO !書き始め点に到達したら出る。
         IF ABS(x2)>windowX OR ABS(y2)>windowY THEN EXIT DO !画面外になったら出る。
         PLOT LINES:x2,y2;
         LET count=count+1
         LET x1=x2
         LET y1=y2
      LOOP
10       PLOT LINES
         PRINT "描画完了電位vv=";vv
      NEXT vv
   END SUB

   !**********************
   !      Main関数
   !**********************
   LET dlv=0.004 !等電位線の微小描画素線長さの設定
   LET dlr=0.01 !電気力線の微小描画素線長さの設定

   !---点電荷の位置に赤/青丸印を表示
   LET ren=0.2
   FOR n=1 TO Nq
      IF Qi(n)>0 THEN
         SET AREA COLOR "red"
      ELSEIF Qi(n)<0 THEN
         SET AREA COLOR "blue"
      END IF
      DRAW disk WITH SCALE(ren)*SHIFT(xi(n),yi(n))
   NEXT n

   !*** 等電位線の作図 ***
   SET LINE COLOR "red"
   FOR n=1 TO Nq
      PRINT "--- 第";n;"電荷の作図処理中です。---"
      IF Qi(n)>0 THEN
         SET LINE COLOR "red"
         LET kyokusei=1
      ELSEIF Qi(n)<0 THEN
         SET LINE COLOR "blue"
         LET kyokusei=-1
      END IF
      LET vstart=0.4*kyokusei  !数字は描画する|電位|の最大値
      LET vend=0*kyokusei      !数字は描画する|電位|の最小値
      LET vstep=-0.04*kyokusei !|数字|は等電位幅
      CALL Vsen(n)
   NEXT n
END

 

Re: LOOPが抜けられない

 投稿者:GAI  投稿日:2015年 6月11日(木)15時29分26秒
  > No.3747[元記事へ]

島村1243さんへのお返事です。

私はプログラムには全く素人ですが、物理的に等電荷が原点対称にセットされていたら釣り合う電位が無限に存在できるためにループが無限回繰り返されているんではないでしょうか。
ですから、原点対称に電荷をセットするなら異なる電荷の値にするか、同じ電荷ならセットする位置を
原点対称にならない位置どうしに置いたらよくなると思いました。
 

Re: LOOPが抜けられない

 投稿者:山中和義  投稿日:2015年 6月11日(木)16時19分45秒
  > No.3747[元記事へ]

島村1243さんへのお返事です。

> SUB Vsen(n)!---電荷による等電位線の描画関数
>    FOR vv=vstart TO vend STEP vstep
>       CALL Newton(n,vv,xi(n),yi(n),xs,ys,over)
>       IF over=1 THEN GOTO 10
>       PLOT LINES:xs,ys;
>       LET count=0
>       LET x1=xs
>       LET y1=ys
>       DO
>          CALL Denkai(x1,y1,Ex1,Ey1)
>          LET kakudo=ANGLE(-Ey1,Ex1)
>          LET x2=x1+dlv*COS(kakudo)
>          LET y2=y1+dlv*SIN(kakudo)
>          LET rck=SQR((x2-xs)^2+(y2-ys)^2)
>          IF count>=50 AND rck<=0.1 THEN EXIT DO !書き始め点に到達したら出る。

>          IF ABS(x2)>windowX OR ABS(y2)>windowY THEN EXIT DO !画面外になったら出る。
>          PLOT LINES:x2,y2;
>          LET count=count+1
>          LET x1=x2
>          LET y1=y2
>       LOOP
> 10       PLOT LINES
>          PRINT "描画完了電位vv=";vv
>       NEXT vv
>    END SUB


浮動小数点計算の累積誤差による終点と始点が異なるからです。


2進モードでは、最後の値でループしますが、十進モードなら、
LET rck=(x2-xs)^2+(y2-ys)^2
IF count>500 AND rck<=0.08 THEN EXIT DO !書き始め点に到達したら出る。

0.08は、0.06から0.2の範囲でOKのようです。


したがって、電荷の値や等電位値、幅が違うと調整が必要です。

 

Re: LOOPが抜けられない

 投稿者:島村1243  投稿日:2015年 6月11日(木)19時05分8秒
  > No.3749[元記事へ]

山中和義さんへのお返事です。

> 浮動小数点計算の累積誤差による終点と始点が異なるからです。
> 2進モードでは、最後の値でループしますが、十進モードなら、
> LET rck=(x2-xs)^2+(y2-ys)^2
> IF count>500 AND rck<=0.08 THEN EXIT DO !書き始め点に到達したら出る。
>
> 0.08は、0.06から0.2の範囲でOKのようです。
> したがって、電荷の値や等電位値、幅が違うと調整が必要です。

山中さん、詳しいご回答有難う御座いました。
電荷値や位置、電位幅を変えるとうまく行く場合もあったので、累積誤差が原因とは思い付きませんでした。助かりました。
 

戻る