勉強会お疲れ様でした。
一般座標系平面二次元河床変動計算を書く
3種の座標変換法をピックアップ。 特徴を整理して採用する手法を選定
四分木法
文献収集
単位流域から流出する流量波形のガンマ関数近似について
石原の理論から導出可能。
勉強会お疲れ様でした。
3種の座標変換法をピックアップ。 特徴を整理して採用する手法を選定
文献収集
石原の理論から導出可能。
たまにはコアな土砂水理の話です。
本記事はGitHub、nbviewer、Colabでも公開しています。
※Colabの解説記事はこちら
以下の2論文(ほぼ同じ内容)に記載される粒度分布の関数近似について、以前から気になっていたので少し考えてみました。
気になっていることは、粒度分布の関数形の一つとして論文に示されるTalbot型ですが、河床材料の場合、分級作用が働くため、平衡状態では必ずLog-normal型になるのではという点です。
少しだけ考えてみたのでまとめておきます。
流砂水理の研究者なら知っていて当然ですが、一応整理しておきます。
本論文は、京都大学の藤田正治先生の研究チームがまとめた河床材料の粒度分布と空隙率の関係に関するシリーズの一部になります。 代表的な論文を整理しておきます。
この論文が最初の成果で粒径を球と仮定して数値実験により空隙率と粒度分布の関係をまとめています。
次が前述の論文で、実河川の粒度分布について近似関数を用いて分類し、関数形ごとの空隙率の特性をまとめています。
これまでに得られた粒度分布と空隙率の関係を用いて、一次元河床変動モデルを構築して数値実験を行っております。結論としてはなかなか難しいよねくらいの感じです。
一応、ここまでで研究は終わっているのですが、後に株式会社 建設技術研究所 岩見さんが発展させた研究を行っています。
全てはフォローできていませんが現時点では空隙率の変化を考慮した平面二次元河床変動計算を行っているようです。
以上が関連論文の整理になります。
論文には以下のように示されています。
Riverbed materials have a variety of different characteristic size of bed surface sediment (Bunte and Abt, 2001), but the grain size distribution could be classified into some types. One of the most typical density functions of grain size is a log-normal distribution. The grain size distribution of bed material in most sand-bed streams is unimodal and that in many gravel-bed rivers is bimodal (Parker, 2004). Also in mountainous rivers, the surface bed material has usually Talbot distribution of grain size (Tatsuzawa et al., 1998).
河床材料は、様々な特性を持つ粒径(Bunte and Abt, 2001)を持ちますが、粒径分布はいくつかのタイプに分類することができます。粒径の最も典型的な密度関数の一つは対数正規分布です。ほとんどの砂床河川の河床材料の粒径分布は単峰性で多くの礫床河川では双峰性(bimodal)です(Parker, 2004)。また、山地河川では、表面の河床材料は通常、粒径のタルボット分布を持っています(Tatsuzawa et al., 1998)。
のなかで「山地河川では、表面の河床材料は通常、粒径のタルボット分布を持っています。」部分が引っかかっています。 山地河川でも分級作用があるので、対数正規分布になるのでは?と思っています。
参照文献の
竜澤 宏昌, 林 日出喜, 長谷川 和義 : 渓流河川における河床砂礫の混合特性と階段状河床形の形状特性, 水工学論文集42巻, 1998
をみると、渓流河川の粒度分布はTalbot型関数で表現できるとありますが、分級機構については十分に検討されていません。
ある沖積河川上流域の比較的急流な礫床河川の粒度分布を対象とします。 表層を剥いだ下層、いわゆる交換層の粒度分布になります。
粒度分布をみると最大粒径が100mmとなっていますが、これは材料採取の際に100mm以上を採取していないため?でしょうか。
この粒度分布を対象に各種関数でフィッティングしていきます。
import numpy as np import matplotlib.pyplot as plt from scipy.stats import norm, lognorm
d = np.array([100,75,53,37.5,26.5,19,9.5,4.75,2,0.85,0.425,0.25,0.106,0.075,0.053]) p = np.array([100,94.6,77.9,68,55.9,49.2,37.2,30.1,23.1,14.3,6.4,2.8,0.7,0.5,0]) d = d[::-1] p = p[::-1]
%matplotlib inline fig, ax = plt.subplots() ax.plot(d, p, marker='o') ax.set_xscale('log') ax.grid(which='major',color='black',linestyle='-') ax.grid(which='minor',color='gray',linestyle='--') ax.set_xlabel('diameter[mm]') ax.set_ylabel('percentage of grain size[%]') plt.show()
ここに、:期待値、
:標準偏差とする。
ここに、は相補誤差関数を表す。
これらより、の2パラメータでフィッティングする。
面倒なので、scipy.stats.lognormを使います。
引数の定義が正規分布の場合と異なるのでわからない方は以下を参照下さい。
フィッティング結果は次図のとおりです。
粒度分布が複雑な形状なので、粗めの成分でフィッティングする場合と細かめの成分でフィッティングする場合の2ケースが考えられます。 言い換えると対数正規分布でのフィッティングが難しいと考えられます。 bimodal型に近いかもしれませんね。フィッティングする場合は、対数正規分布の重ね合わせでできそうです。後日やってみます。
%matplotlib inline fig, ax = plt.subplots() ax.plot(d, p, marker='o', label='observed') xd = np.arange(-2, 3.5, 0.1) y = lognorm.cdf(10**xd, s=1, scale=np.exp(3.2), loc=0) ax.plot(10**xd, y*100, label="$\sigma=1, \mu=24.53$") y = lognorm.cdf(10**xd, s=2.5, scale=np.exp(3), loc=0) ax.plot(10**xd, y*100, label="$\sigma=2.5, \mu=20.09$") ax.set_xscale('log') ax.grid(which='major',color='black',linestyle='-') ax.grid(which='minor',color='gray',linestyle='--') ax.set_xlabel('diameter[mm]') ax.set_ylabel('percentage of grain size[%]') ax.legend() plt.show()
そもそものTalbot型の粒度分布について簡単にまとめておきます。
フラー(W.B.Fuller)とトンプソン(S.E.Thompson)によって確立された(1907)、粒子を最密充填にするための粒度分布曲線(Fuller曲線)が次式で示されます。 最大密度を与える理想粒度としてコンクリート骨材分野で提案された式らしいです。
上式の一般形が下式のTalbot式になります。(1923)
著者は河床材料にフィッティングしやすいようにTalbot式を以下のように修正しています。
この式を使ってフィッティングしていきます。パラメータはのみです。
参考文献
フィッティング結果は次図のとおりです。
指数を調整するだけでは、良くフィッティングできています。 これだけフィットすること考えると、Talbot型の粒度分布が形成される物理的要因がありそうです。
%matplotlib inline n = 0.45 f = (d/d[-1])**n nt = 2.7 ft = ((np.log10(d)-np.log10(d[0]))/(np.log10(d[-1])-np.log10(d[0])))**nt fig, ax = plt.subplots() ax.plot(d, p, marker='o', label='observed') ax.plot(d, f*100, label='Talbot $n=0.45$') ax.plot(d, ft*100, label='Talbot_modified $n\_T=2.7$') ax.set_xscale('log') ax.grid(which='major',color='black',linestyle='-') ax.grid(which='minor',color='gray',linestyle='--') ax.set_xlabel('diameter[mm]') ax.set_ylabel('percentage of grain size[%]') ax.legend() plt.show()
勉強会お疲れ様でした。
Talbot型の物理的意味について整理
関連論文
続報記事
computational-sediment-hyd.hatenablog.jp
理論の整理
理論の整理、問題点の整理
久しぶりに書きましょう。我々のモデルが無いのは不便
久しぶりに本質的な議論ができて楽しかったです。
実務では十分にできない物事を細部まで論理的に分析することは重要ですね。
condaの環境を整理した後にconda installを実行した時に以下のOpenSSLに関するエラーが発生したため、その解決方法です。 情報があまりなかったので簡単にまとめておきます。
Collecting package metadata (current_repodata.json): failed CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is required to download and install packages. Exception: HTTPSConnectionPool(host='conda.anaconda.org', port=443): Max retries exceeded with url: /conda-forge/win-64/current_repodata.json (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available."))
参照サイトによると、OpenSSL関連のライブラリが上手く参照できていないことが原因のようです。 そのため、シンボリックリンクを使って以下のコマンドを実行することで解決できます。もちろんコピーしても大丈夫です。
mklink "C:\ProgramData\Anaconda3\DLLs\libcrypto-1_1-x64.dll" "C:\ProgramData\Anaconda3\Library\bin\libcrypto-1_1-x64.dll" mklink "C:\ProgramData\Anaconda3\DLLs\libssl-1_1-x64.dll" "C:\ProgramData\Anaconda3\Library\bin\libssl-1_1-x64.dll"
このブログではおなじみのpythonモジュール:rioxarrayを最新版にアップデートすると、主要なメソッドが変わっていたのでまとめておきます。
rioxarrayを使っている主な記事は以下です。
xarray.open_rasterioは、xarrayの2023.04の更新で完全に廃止されました。
open_rasterioはrioxarrayモジュールが無いと動かないので、わかりやすくなったかと思います。
以前は、
import xarray as xr ds = xr.open_rasterio('A.tif')
でも、readできましたが、今後は、
import rioxarray ds = rioxarray.open_rasterio('A.tif')
のみになります。
上のページのとおりですが、以前は、
cog_url = ( "https://oin-hotosm.s3.amazonaws.com/" "5d7dad0becaf880008a9bc88/0/5d7dad0becaf880008a9bc89.tif" ) import xarray as xr xr.open_rasterio(cog_url).crs # '+init=epsg:3857'
で座標情報を確認できましたが、rioxarrayを用いた場合は、
import rioxarray rioxarray.open_rasterio(cog_url).spatial_ref # <xarray.DataArray 'spatial_ref' ()> # array(0) # Coordinates: # spatial_ref int64 0 # Attributes: # spatial_ref: PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WG... # crs_wkt: PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WG...
のように、spatial_refというCoordinatesを作成されて、そのAttributesに座標情報が格納されています。
epsgを確認する場合は、
ds = rioxarray.open_rasterio(cog_url) ds.rio.crs.to_proj4() # '+init=epsg:3857' ds.rio.crs.to_epsg() # 3857
などになります。
個人的な勉強会で作った資料です。 詳しい方から見たらふざけるな的な内容ですが10分解説なので許して下さい。
本記事はGitHub、nbviewer、Colab、Marp(スライド形式)でも公開しています。
※Colabの解説記事はこちら
※Marpの解説記事はこちら
※ 茨城大学 田中伸厚先生の講義資料を引用 : http://www.mech.ibaraki.ac.jp/~tanaka/Lecture/sim1/part1.pdf
ある現象が次の常微分方程式で表すことができるとする。
ここに、:崩壊定数とする。
上式は連続系でありそのままコンピュータで取り扱うことができない。
そこで上式を
のようにコンピュータ上で取り扱える式(代数方程式=四則演算のみの式)に変換することを離散化(差分法)という。
また、代数方程式は添字を用いて以下のように記述することが多い。以降は以下の表記を使用する。
出典:https://studyphys.com/half-life/
以下の常微分方程式で表すことができる。
ここに、:崩壊定数とする。
差分法を用いると以下のとおりとなる。
この式よりの値(初期条件)を与えて逐次計算を行うことにより数値解を得ることができる。
前出の常微分方程式は厳密解(数値計算を用いずに解析的に得られる解。解析解とも呼ばれる)を求めることができる。
導入過程は省略するとが、変数分離を用いて式変形することにより下式が得られる。
本式による計算結果と数値計算の結果を比較することにより計算の妥当性を評価することができる。
導出した代数方程式を用いて数値解析を実施する。
を0.1,0.5,1.0,1.5と変化させた場合の計算結果と厳密解との比較を示す。
計算条件は、
は100、
は1とする。
import numpy as np import matplotlib.pyplot as plt N0 = 100 k = 1.0 exact = lambda T: N0 * np.exp(-k*T) def simulation(T): N = np.zeros_like(T) N[0] = N0 for i in range(1, len(N)): N[i] = N[i-1] - dt*k*N[i-1] return N def mkfig(ax, T): ax.plot(T, exact(T),label='exact') ax.plot(T, simulation(T),label='simulation') ax.set_xlabel('T') ax.set_ylabel('N') ax.legend(loc = 'upper right')
dt = 0.1 T = np.arange(0, 20, dt) fig, ax = plt.subplots() mkfig(ax, T)
dt = 0.5 T = np.arange(0, 20, dt) fig, ax = plt.subplots() mkfig(ax, T)
dt = 1.0 T = np.arange(0, 20, dt) fig, ax = plt.subplots() mkfig(ax, T)
dt = 1.5 T = np.arange(0, 20, dt) fig, ax = plt.subplots() mkfig(ax, T)
import numpy as np import matplotlib.pyplot as plt N0 = 100 k = 1.0 exact = lambda T: N0 * np.exp(-k*T) def simulation2(T): N = np.zeros_like(T) N[0] = N0 for i in range(1, len(N)): N[i] = N[i-1]/(1+dt*k) return N def mkfig2(ax, T): ax.plot(T, exact(T),label='exact') ax.plot(T, simulation2(T),label='simulation') ax.set_xlabel('T') ax.set_ylabel('N') ax.legend(loc = 'upper right')
dt = 1.5 T = np.arange(0, 20, dt) fig, ax = plt.subplots() mkfig2(ax, T)
移流とは下図のようにある物理量が流れによって運ばれる現象を示す。この現象を計算対象とする。
import numpy as np import matplotlib.pyplot as plt c = 1.0 X = np.linspace(-5,5,101) exact = lambda t: np.exp(-(X-c*t)**2) fig, ax = plt.subplots() ax.plot(X, exact(0),label='0 sec') ax.plot(X, exact(2),label='2 sec') ax.set_xlabel('x') ax.set_ylabel('u') ax.legend(loc = 'upper right')
以下の偏微分方程式で表すことができる。
今回は3つの差分スキームを使用する。
この式よりの値(初期条件,空間分布を持つ)を与えて逐次計算を行うことにより数値解を得ることができる。
なお、境界条件も必要であるが今回は境界付近を計算しないため0とする。
一次元の移流方程式は条件によって厳密解を得ることができる。
を与えると厳密解として次式が得られる。
導出した代数方程式を用いて数値解析を実施する。
計算条件は、、
、
として、厳密解との比較を行なう。
import numpy as np import matplotlib.pyplot as plt c = 1.0 X = np.linspace(-5,5,101) dx = 0.1 exact = lambda t: np.exp(-(X-c*t)**2)
def s01(dt): #前進差分 unew = exact(0) for _ in range(int(2/dt)): u = unew.copy() for i in range(1,len(u)-1): unew[i] = u[i] - c * dt/dx * (u[i+1]-u[i]) return unew def s02(dt): #後退差分 unew = exact(0) for _ in range(int(2/dt)): u = unew.copy() for i in range(1,len(u)-1): unew[i] = u[i] - c * dt/dx * (u[i]-u[i-1]) return unew def s03(dt): #中心差分 unew = exact(0) for _ in range(int(2/dt)): u = unew.copy() for i in range(1,len(u)-1): unew[i] = u[i] - c * dt/dx * (u[i+1]-u[i-1])/2 return unew
適切な解を得ることができない。
fig, ax = plt.subplots() ax.plot(X, exact(0),label='0 sec') ax.plot(X, exact(2),label='exact:2sec') ax.plot(X, s01(0.01),label='simulation:2sec dt=0.01') ax.set_xlabel('x') ax.set_ylabel('u') ax.legend(loc = 'best')
波形が拡散してピークが減衰する。
fig, ax = plt.subplots() ax.plot(X, exact(0),label='0 sec') ax.plot(X, exact(2),label='exact:2sec') ax.plot(X, s02(0.01),label='simulation:2sec dt=0.01') ax.set_xlabel('x') ax.set_ylabel('u') ax.legend(loc = 'best')
若干の差異はあるが他の差分スキームと比較すると厳密解に近い結果になっている。
fig, ax = plt.subplots() ax.plot(X, exact(0),label='0 sec') ax.plot(X, exact(2),label='exact:2sec') ax.plot(X, s03(0.01),label='simulation:2sec dt=0.01') ax.set_xlabel('x') ax.set_ylabel('u') ax.legend(loc = 'best')
一次元移流方程式の陰解法は前出の常微分方程式と比べてかなり複雑な式形となる。
例として陰解法で中心差分の代数方程式を導出すると次式となる。
上式のみでは、の項の値を求めることができない。そのため、他の空間離散点(
など)の式を全て連立させた次式より解を計算する。
左辺の対角行列の逆行列を計算することにより、の項を求めることができる。
ここでは計算は省力するが、陰解法は陽解法と比べて煩雑な計算が必要となることが理解できる。
補足として、上式の左辺の1つ目の行列は三重対角行列となっており、TDMA法を用いて少ない計算ステップ数で逆行列を求めることができる。この方法は不等流計算の平均流速公式レベル3の解法でも使用する。
一般的に精度と安定性は両立しない。目的に応じて差分スキームを選択する必要がある。
⇒ 今回の勉強で実施する不等流計算、貯留関数法では、差分スキームはそれほど重要ではないがの大きさについてはある程度考慮する必要がある。
⇒ 不定流計算などを実施する場合は、差分スキームが重要