ラベル Numerical Simulation の投稿を表示しています。 すべての投稿を表示
ラベル Numerical Simulation の投稿を表示しています。 すべての投稿を表示

2013年10月20日日曜日

RCIP


CIPは非常に優秀な移流方程式に対する解法ですが、不連続部に若干のオーバーシュート、アンダーシュートが残ります。

これは補間関数に3次関数を選択したためであり、これを避けるために、別の関数を使えば良いじゃん!というのが、RCIP(Rational CIP)基本的な考え方です。有理関数を使えばオーバーシュートアンダーシュートを抑えられます。

ソースを晒しておきます。まあ、汚いです。

#advection #################################################
# RCIP ########### ########################################
############################################################
#import#####################################################
from pylab import * 
#set parameters ############################################
in_ff = open('test.txt')
imx=100
dx=1.0
dt=0.2
u=0.2
alpha = 1.0
eps = 1.0e-15
print "-"*40
print "u  =",u
print "dx =",dx
print "dt =",dt
print "-"*40
############################################################
#initial condition ################################
f= [0]
fn=  [0]
df = [0]
dfn = [0]
fini=[0]
fl=  [0]
fr=  [0]
x=   [0]
abm= [0]
xl=  [0]
f_tilde = [0]
fex = [0]
i=1
for x in in_ff:
print i
a = x.split(" ")
for k in range(0,1):
print a[k]
xl=xl+[float(a[0])]
f=f+[float(a[1])]
fini=fini+[float(a[1])]
fn=fn+[float(a[1])]
fl=fl+[float(a[1])]
fr=fr+[float(a[1])]
f_tilde = f_tilde + [0]
fex = fex + [0]
df = df + [0]
dfn = dfn + [0]
i=i+1
imx=i
adm=[0.0]
for i in range(1,imx):
adm=adm+[0.0]
print "*"*40
print "xl,f"
for i in range(0,imx-1):
print float(xl[i]),"   ",float(f[i])
# set parameter ####################################
for n in range(0,1000):
###############################
for i in range(1,imx-1):
if u>=0.0:
ip = i - 1
dd = -dx
else:
ip = i + 1
dd = dx
xi = -u*dt
S  = (f[ip]-f[i])/dd
if S - f[ip] >0.0:
isgn = 1.0
else:
isgn = -1.0
TS = f[ip]-S
BB = ((abs(S-df[i])+eps)/(abs(S-df[ip])+eps)-1.0)/dd

a3 = (df[i]-S+(df[ip]-S)*(1.0+alpha*BB*dd))/(dd*dd)
a2 = S*alpha*BB+(S-df[i])/dd-a3*dd
a1 = df[i] +f[i]*alpha * BB
a0 = f[i]
fn[i]  = (a3*xi*xi*xi+a2*xi*xi+a1*xi+a0)/(1.0+alpha*BB*xi)
dfn[i] = (3.0*a3*xi*xi+2.0*a2*xi+a1)/(1.0+alpha*BB*xi)-(alpha*BB)*(fn[i])/(1.0+alpha*BB*xi)
#shift#########################################
for i in range(1,imx-1):
f[i]=fn[i]
df[i]=dfn[i]
print fn
###################################################
# Exact ###########################################
for i in range(0,imx-1):
if i>=50 and i<=60:
fex[i] = 1.0
else:
fex[i] = 0.0
#output############################################
ff=open("output.dat","w")
for i in range(0,imx-1):
ff.write(str(xl[i]))
ff.write("    ")
ff.write(str(f[i]))
ff.write("\n")
ff.close()
#output
#for i in range(0,imx-1):
# print f[i]
print "-"*100
print xl
print f
#####################graph#########################
y1=f
y2=fini
y3=fex
plot(xl,y1,label = 'RCIP')
plot(xl,y2,label = 'INITIAL')
plot(xl,y3,label = 'EXACT')
xlabel('x')
ylabel('f')
title('RCIP')
axis([-0,100.0,-0.2,1.2])
legend()
grid(True)
savefig('RCIP')
show()
###################################################


等間隔WENO

WENOは格子間をラグランジュ補間して、スムーズインジケーターで修正する手法らしいです。ただ、あくまで私の理解であり、正しい認識を提供するものではありません。

河川の流れを対象とし、RANSを用いた計算だと、WENOのような高級な手法を用いることはありませんが、勉強がてらやってみました。

汚いですが、ソースも晒しておきます。たぶん間違いがあると思いますので、あくまで参考ということで。

あとは不等間隔の場合、係数が異なるように思いますので、座標変換して解くような手法(格子間隔を一定として変換)でない限り、修正が必要かと思います。QUICKと同様ですね。



#advection #################################################
# WENO  ########################################
############################################################
#import#####################################################
from pylab import *
def calflux1(u,f,flm,flp):
alpha = 0.0
for i in range(1,imx-1):
alpha_tmp = u
if abs(alpha_tmp) > abs(alpha):
alpha = alpha_tmp
for i in range(1,imx-1):
flm[i] = 0.5*(f[i]*u - alpha*f[i])
flp[i] = 0.5*(f[i]*u + alpha*f[i])
flm[0] = 0.0
flm[imx-1] = 0.0
flp[0] = 0.0
flp[imx-1] = 0.0
def calflux2(i,omegam,omegap,flm,fip,fl2m,fl2p):
print i
fltmpp = [0]
fltmpm = [0]
for k in range(0,3):
fltmpp = fltmpp + [0]
fltmpm = fltmpm + [0]

fltmpp[0] =  1./3.*flp[i-2] - 7./6.*flp[i-1] + 11./6.*flp[i  ]
fltmpp[1] = -1./6.*flp[i-1] + 5./6.*flp[i  ] +  1./3.*flp[i+1]
fltmpp[2] =  1./3.*flp[i  ] + 5./6.*flp[i+1] -  1./6.*flp[i+2]
fl2p[i] = 0.0
for k in range(0,3):
fl2p[i] = fl2p[i] + omegap[k]*fltmpp[k]

fltmpm[1] = -1./6. * flm[i-1] + 5./6. * flm[i  ] +  2./6. * flm[i+1]
fltmpm[2] =  2./6. * flm[i  ] + 5./6. * flm[i+1] -  1./6. * flm[i+2]
fltmpm[3] = 11./6. * flm[i+1] - 7./6. * flm[i+2] +  2./6. * flm[i+3]
fl2m[i] = 0.0
for k in range(0,3):
fl2m[i] = fl2m[i] + omegam[k]*fltmpm[k]
in_ff = open("test.txt")
dx=1.0
dt=0.2
u=0.2
c1 = 1./10.
c2 = 6./10.
c3 = 3./10.
eps = 1.0e-10
print "-"*40
print "u  =",u
print "dx =",dx
print "dt =",dt
print "-"*40
############################################################
#initial condition ################################
f= [0]
fn=  [0]
fini=[0]
fl=  [0]
fr=  [0]
fex = [0]
x=   [0]
abm= [0]
xl=  [0]
flm = [0]
flp = [0]
flux = [0]
flux1 =[0]
flux2 =[0]
flux3 =[0]
fl2m = [0]
fl2p = [0]
i=1
for x in in_ff:
print i
a = x.split(" ")
for k in range(0,1):
print a[k]
xl=xl+[float(a[0])]
f=f+[float(a[1])]
fini=fini+[float(a[1])]
fn=fn+[float(a[1])]
fl=fl+[float(a[1])]
fr=fr+[float(a[1])]
i=i+1
fex = fex+[float(a[1])]
flux = flux + [0]
flux1 = flux1 + [0]
flux2 = flux2 + [0]
flux3 = flux3 + [0]
flm = flm + [0]
flp = flp + [0]
fl2m = fl2m + [0]
fl2p = fl2p + [0]

imx=i
adm=[0.0]
alpham = [0]
alphap = [0]
omegam = [0]
omegap = [0]


for k in range(0,3):
alpham = alpham + [0]
alphap = alphap + [0]
omegam = omegam + [0]
omegap = omegap + [0]
print "*"*40
print "xl,f"
for i in range(0,imx-1):
print float(xl[i]),"   ",float(f[i])
# set parameter ####################################
# 1st order upwind ####################################
for n in range(0,1000):
calflux1(u,f,flm,flp)

# WENO
for i in range(3,imx-4):

isp1 = 13./12.*(flp[i-2]-2.0*flp[i-1]+flp[i])*(flp[i-2]-2.0*flp[i-1]+flp[i])+1.0/4.0*(flp[i-2]-4.0*flp[i-1]+3.0*flp[i])*(flp[i-2]-4.0*flp[i-1]+3.0*flp[i])
isp2 = 13./12.*(flp[i-1]-2.0*flp[i]+flp[i+1])*(flp[i-1]-2.0*flp[i]+flp[i+1])+1.0/4.0*(flp[i-1]-flp[i+1])*(flp[i-1]-flp[i+1])
isp3 = 13./12.*(flp[i]-2.*flp[i+1]+flp[i+2])*(flp[i]-2.*flp[i+1]+flp[i+2])+1./4.0*(3.*flp[i]-4.*flp[i+1]+flp[i+2])*(3.*flp[i]-4.*flp[i+1]+flp[i+2])

ism1 = 13./12.*(flm[i+1]-2.0*flm[i+2]+flm[i+3])*(flm[i+1]-2.0*flm[i+2]+flm[i+3])+1.0/4.0*(3.0*flm[i+1]-4.0*flm[i+2]+flm[i+3])*(3.0*flm[i+1]-4.0*flm[i+2]+flm[i+3])
ism2 = 13./12.*(flm[i]-2.0*flm[i+1]+flm[i+2])*(flm[i]-2.0*flm[i+1]+flm[i+2])+1.0/4.0*(flm[i]-flm[i+2])*(flm[i]-flm[i+2])
ism3 = 13./12.*(flm[i-1]-2.0*flm[i  ]+flm[i+1])*(flm[i-1]-2.0*flm[i]+flm[i+1])+1./4.0*(flm[i-1]-4.*flm[i]+3.*flm[i+1])*(flm[i-1]-4.*flm[i]+3.*flm[i+1])
#
alpham[0] = c1/(eps + ism1)/(eps+ism1)
alpham[1] = c2/(eps + ism2)/(eps+ism2)
alpham[2] = c3/(eps + ism3)/(eps+ism3)
#
alphap[0] = c1/(eps + isp1)/(eps+isp1)
alphap[1] = c2/(eps + isp2)/(eps+isp2)
alphap[2] = c3/(eps + isp3)/(eps+isp3)
#
sigmaalpham = alpham[0] +alpham[1] +alpham[2]
sigmaalphap = alphap[0] +alphap[1] +alphap[2]
#
omegam[0] = alpham[0] / sigmaalpham
omegam[1] = alpham[1] / sigmaalpham
omegam[2] = alpham[2] / sigmaalpham

omegap[0] = alphap[0] / sigmaalphap
omegap[1] = alphap[1] / sigmaalphap
omegap[2] = alphap[2] / sigmaalphap

calflux2(i,omegam,omegap,flm,flp,fl2m,fl2p)
fl2m[2] = 0.0
fl2m[1] = 0.0
fl2m[0] = 0.0
fl2p[2] = 0.0
fl2p[1] = 0.0
fl2p[0] = 0.0

fl2m[imx-1] = 0.0
fl2m[imx-2] = 0.0
fl2m[imx-3] = 0.0
fl2p[imx-1] = 0.0
fl2p[imx-2] = 0.0
fl2p[imx-3] = 0.0
# EULER ##############################
for i in range(3,imx-4):#0~imx-1
fn[i]=f[i]-dt*(fl2p[i]-fl2p[i-1]+fl2m[i]-fl2m[i-1])/(dx)
#shift#########################################
for i in range(2,imx-2):
f[i]=fn[i]
print fn
###################################################
# Exact ###########################################
for i in range(0,imx-1):
if i>=50 and i<=60:
fex[i] = 1.0
else:
fex[i] = 0.0
#output############################################
ff=open("output.dat","w")
for i in range(0,imx-1):
ff.write(str(xl[i]))
ff.write("    ")
ff.write(str(f[i]))
ff.write("\n")
ff.close()
#output
#for i in range(0,imx-1):
# print f[i]
print "-"*100
print xl
print f
#####################graph#########################
y1=f
y2=fini
y3 = fex
plot(xl,y1,label = 'WENO')
plot(xl,y2,label = 'INITIAL')
plot(xl,y3,label = 'EXACT')
xlabel('x')
ylabel('f')
title('WENO')
axis([-0,100.0,-0.2,1.2])
legend()
grid(True)
savefig('WENO')
show()
###################################################

2013年9月16日月曜日

等間隔QUICKEST


# 久々にpython

for i in range(3,imx-3):#0~imx-1
c = u*dt/dx #
if u >0:
fn[i] = f[i] - c/6*(2*f[i+1]+3*f[i]-6*f[i-1]+f[i-2]) \
   + c*c/2*(f[i+1]-2*f[i]+f[i-1]) \
   - c*c*c/6 *(f[i+1]-3*f[i]+3*f[i-1]-f[i-2])
else:
fn[i] = f[i] - c/6*(2*f[i-1]+3*f[i]-6*f[i+1]+f[i+2]) \
   + c*c/2*(f[i+1]-2*f[i]+f[i-1]) \
   - c*c*c/6 *(f[i-1]-3*f[i]+3*f[i+1]-f[i+2])

等間隔にしか使えないですが・・・。
一応、保存則を使っています。

明日中には不等間隔+TVD化されたQUICKを晒したいです。


2013年9月13日金曜日

書籍

藤井先生著「流体力学の数値計算法」について書いておこうと思います。

双曲型の数値計算法(保存性を意識した差分法)がメインです。基礎方程式は圧縮性流体を想定したオイラー方程式です。解析手法はTVD系です。したがって、非圧縮性流体の解析で使われるスタッガード格子やMAC系の解法に関する手法は述べられてません。

ハッキリ言って、これを読んでも実際に解析が出来るようにはなりません。
実用的な解析をするならもっと簡単な本を読んだ方が良いでしょうし、初心者は読まない方が良いかもしれません。

ただし、味わい深い本だと思います。
小生が購入したのは2004年頃ですが、最近ようやく「あ、これのこと言ってたんだ!」と気づかされることが多いです。FDSやFVSの基本的な考え方が書いてある本はこれくらいだと思います。
浅水流方程式への応用はちゃんと鉛筆動かさないとダメですけどね。
正直、まだ、すべてを理解してません(笑)
ただ、「わかんねぇなー」と思いながら、日々少しずつ理解が深まるところに、楽しさを感じてます。


ところで、

「わかりやすいほにゃらら」
「初心者のためのほにゃらら」
「10日でほにゃらら」

等々。分りやすいのでスイスイ読めますが、長くは読めません(否定している訳ではありません)。

結局、簡単に理解できることは、それだけの価値しかありませんし、他人もすぐ理解できます。
苦しんで覚えたことや、時間をかけて学んだことは忘れませんし、他人もすぐには理解できないことです。

良書を見分ける一つの指標として、「古いけど絶版にならない技術書は良い」というのがあります。
ただし、理解に時間がかかるものが多いです。

技術書に限らず、死ぬまでに多くの良書に出会いたいですね。








2013年9月4日水曜日

蛙跳び2


こんな感じでした。鈍るんです。
LeapFrogは空間積分の右辺をf^{n+1}とf^{n-1}の平均値である0.5*(f^{n+1}とf^{n-1})を使うような良い加減な方法なんであまり好きではないのですが、これ見ると、RungeKuttaを使って計算コスト書けるなら、LeapFrogの方が楽だし、鈍らないし、と判断してしまいますね。何か間違ってることを信じたいです(笑)


2013年9月3日火曜日

蛙跳び


' Leap Frog Method
  dim n as Integer
  dim i as Integer
  dim f(100) as double
  dim fo(100) as double
  dim fn(100) as double
  dim mojiretsu as String

  'Initial Condition
  For i = 1 to ixmx
    if i > 10 And i<20 then
      fo(i) = 1.0
      f(i) = 1.0
      fn(i) = 1.0
    else
      fo(i) = 0.0
      f(i) = 0.0
      fn(i) = 0.0
    end if
  next i
  'Time Marching
  for n =1 to itmx
    'Leap Frog
    for i = 2 to ixmx
      fn(i) = fo(i) - 2*u*dt/dx*(f(i) - f(i-1))
    next i
 
    'Shift Variables
    for i = 2 to ixmx
      f(i) = 0.5*(fn(i)+fo(i))
      fo(i) = fn(i)
    next i
  next n

  'Output
  for i = 1 to ixmx
    mojiretsu = Str(i) +"," + Str(f(i))
    ListBox2.AddRow(mojiretsu)
  next i

4次精度ルンゲクッタと比較すると、2次精度の蛙飛びの方が、鈍りが少ないです。

なぜなんだろう・・・。

2013年7月15日月曜日

QUICK

等間隔格子です。
XOJOです。

必要とあればTVD化のソースや不等間隔TVD-QUICKもあります。

'以下ソース

  dim f1 as double
   if u >= 0 then
    f1 = f-u*dt*(3*fdn1+3*f-7*fup1+fup2)/(8*dx)
  else
    f1 = f-u*dt*(3*fup1+3*f-7*fdn1+fdn2)/(8*dx)
  end if
  return f1

2013年7月7日日曜日

コロケート格子

なんか難しい。。。
巧くイキマセン。。

うまくいったらソース晒すぞ!

2013年7月4日木曜日

ソース

なるべく公開したいですが、出来てなくてすみません。

勉強したいときに何から手をつけたら良いのか分らないことが多いと思います。

ざっくばらんですが、話題提供を出来れば良いと思ってます。

勉強大好きな人間の成果を世の中に反映し、勉強してる人に対してちゃんとペイできる世の中が本来、日本のあるべき姿な気がします。


dam break

河道地形を踏まえたSource Termの修正がが分ってきた。

後は摩擦ですね。

2013年7月3日水曜日

ダムブレイク4

スタッガードスキームはあまり好きではありません。

なんで、定義場所変えんねん!



2013年7月1日月曜日

ダムブレイク3

いろいろ弄って、運動方程式の記述を間違っていることに気づいた。

修正したけど、急変するところでは、1次風上を使っても、振動が残ります。
ただ、ベースは出来たので、ようやくFDSの人工粘性を入れられます。

Leap Frog、1st_Order_upwind、人工粘性でスーパーロバストにしてやる予定。

2013年6月30日日曜日

ダムブレイク2

膨張波と伸縮波がうまく表現できてないことが分りました。

もう少し、考えてみます。

とりあえずCで書いてますが、いろんな言語で書くにします。

履歴書書かなきゃ・・・。

そろそろ会社に行くかな?

ダムブレイク

DamBreakはオイラーの方程式を基礎方程式として、FDS系の解法が一番良い気がします。コロケート格子で。

スタッガードスキームだと、そのまま離散化すれば良いですが、ショックキャプチャリングがうまくいかなくて、若干の数値振動が残ります。

シビルエンジニアリングの世界ではほとんど1次風上が多いですね。
正直気に食わないですが。。。

FDS系の解法はXojoで書いてみることにします。そのうち、ソース晒しますね。
今のところbetter C的なC++で書いてます。

もう少し考えてみます。


2013年6月22日土曜日

名称未設定

TVD法のうち、流束制限関数に関して、ソースを晒したいが、まとまってないので、躊躇してます。

そのうちに。QUICK法とかLaxWendroff法とか、今日ではあまり使わないかもしれませんが、非常に勉強になります。

スキームはこだわりを持って使いたいものですね。
「解ければ何でも良いじゃん!」
はちょっと、バカすぎます。
その場合、1次精度のみでロバスト性を求めるだけで良くて、ぼーっと格子点が増やせるハードが出てくるのを待っているだけです。

CIP法(CSL系)が一番好きですが、既存のコードに対して、フラクショナルステップを使って、移流項のみ改善したい場合は、既存のオイラリアンのスキームの方が良いみたいですね。

ゼロから書くなら、CIP法+その他の項があれば完全陰解法にします。
ロバストかつ高精度。


2013年6月18日火曜日

advection

基本的に

1 中央差分に対して修正する(人工粘性のイメージ)。
2 1次風上に対して修正する(1次精度から高次精度にする)。

の二つの考え方かと思います。

どちらでも構わないですが、海外の書籍だと2が多い気がしてます。
一方、日本は1が多いかなという印象です。

高速流の場合、拡散項が相対的に小さいので、移流項のロバスト性は重要かと。
空間に高次精度を用いる場合、時間積分の精度を上げないと不安定になる場合もあります。





2013年6月16日日曜日

TVD

自由表面流れの乱流モデルを書いてみたが、TVD系のスキームだときれいに乱れが出ない。

やはりCIP、WENO系か(笑)

というのはおいといて、1次精度の風上差分だと駄目だということがよくわかりました。
仕事柄、1次精度でも十分であり、それ以上にロバストであることが重要であることが多いので、2次精度以上でなければならないことが新鮮でした。

まあ、コーディングしたことがない人間が解析やっちゃ駄目ですね。
だいたい「ロバスト」にいろんな意味を入れすぎてます。「猿でもまわせる」のがロバストではないですよ。


2013年6月15日土曜日

QUICK

Quadratic Upstream Interpolation for Kinematics
最近はあまり使われていないようですが、結構好きなスキームです。

TVD化するときはUMIST関数を使いました。
乱流モデル書いてみると、1次風上との違いがよくわかります。

QUICKにはQUICKEST、Ultimate QUICKESTなんかもありますが、
せいぜい2次精度レベルで良いような解析しかしないことが多いです。

2013年6月9日日曜日

解析スキーム

各分野において、解析スキームの種類があるものの、

結局は偏微分方程式を解いているので、共通のスキームになります。



流体の解析をする場合、おそらく機械流体や熱流体を取り扱う人は1次精度のスキームを使うことは避けると思います。



でも、既存のソフトウェアを使った解析はどうでしょうか?

1次精度スキームを選択できないものはないと思います。



要は数値解が飛んじゃ駄目なんです。

結果が得られないと。

間違ってても、解ければ良いんです。

そんな認識の人は数値シミュレーションを辞めた方が良い。

選択できることは重要ですが、真値からの誤差が大きい、下手したら、解きたい現象を解けていない可能性がある、その認識を持ち続けたいものです。


2013年6月8日土曜日

技術屋

民主主義、わらりやすい説明、低コスト、精度向上。

低コスト。これは 異論を挟まない。
精度向上。これも異論を挟まない。

ただし民主主義と分りやすい説明。
これは一部同意しかねます。

専門家は、一般市民出来ない近似精度とコスト感覚のバランスを取るのが大事です。
ただ、その説明は非常に難しい。
さぼってる訳ではなく、先人たちが一生かけてきたことを数年で理解し、他人に説明することなんて無理なんです。説明相手も勉強する余裕がないんです。

だから、専門家は必ず自浄作用をもって、大きく間違わない方向の精度を提示した上で、納税者を納得させるのが必要だと思います。

加えて、一般市民(業界外の方々)に対して、しつこく説明すべきだと思います。そうしないと、技術屋は必ず減ります。魅力がない。やったことが、「税金の無駄遣い!」。
それが世論で、政治家がそれをよしとするなら、誰も目指さないし、下手したら、海外に技術が流出します。自国のグランドデザインを国の民間事業をうまく制御できなれば、荒廃がひどいことになります。

それを受容するだけの納税者がどれだけいるのか?
国家のために自分が何が出来るのか?
真剣に考えましょう。

専門家、非専門家、「そしてそれを短絡的に報道するマスコミ」みんな協力しましょう。信号なくなるかもしれませんよ。道路だって平気で壊れっぱなし。「仕方ないよ。お金内んだもん」あり得ないですね。日本という国家がどんな検討ツールとしての武器をもち、一技術者としてどのような判断が必要なのか。関係者の皆さん、お金を引っ張ることだけなく、グランドデザインとして、日本という国家がどうあるべきなのか?考えましょう。その検討のためにどのような勉強が必要なのか、それを勉強するのが専門学校だったり大学だったりします。

みんな得意、不得意は必ずあります。それが最適化されてるとも思いません。

日本のみなさん、選挙に行って、どう考える、悩みましょう。