NezumiNoKuni’s blog

日々気になったことをメモしてます。ポケモン、データ分析、育児他を予定してます。

Yade (備忘録)

ここ2か月程度、個別要素法(DEM)のYadeをさわっていました。

yade-dem.org

フリーソフトとは思えないほど使いやすくマニュアルやチュートリアルもそろってるのですが、マニュアルも文良が多かったため、つまづいたところをメモします(基本的にすべて公式のマニュアルに書いてありますが...)。

使用環境

解決済み

NameError

特に使い始めは、Viewerで様子を見ながらIPythonで対話的に使うことが多いと思います。が、なぜかIPython上で、挙動が異なります。

Warning: If a function was declared inside a live yade session (ipython) and PyRunner attribute updateGlobals is set to False then an error NameError: name 'myFunction' is not defined will occur unless python globals() are updated with command:

globals().update(locals())

理解したあとも、結構めんどうです。

他にも、内包表記が苦手なのか(いつもとは限らない)、わざわざfor文で書く必要があります。

O.engines (順番)

The order of engines is important. In majority of cases, you will put any additional engine after InteractionLoop:

  • if it applies force, it should come before NewtonIntegrator, otherwise the force will never be effective.

  • if it makes use of bodies’ positions, it should also come before NewtonIntegrator, otherwise, positions at the next step will be used (this might not be critical in many cases, such as output for visualization with VTKRecorder).

O.engines (更新)

The O.engines sequence must be always assigned at once (the reason is in the fact that although engines themselves are passed by reference, the sequence is copied from c++ to Python or from Python to c++).

wrong
O.engines.append(SomeEngine()) # wrong
ok
O.engines=O.engines+[SomeEngine()] # ok
O.engines=O.engines[:2]+[SomeEngine()]+O.engines[2:]
wrong

①粒子の重力落下、②上載荷重、③やりたいこと(一面せん断とか)、とステップを踏むことがあり、途中でenginesの追加・削除を行います。

その際、条件分けしてしてると、単純な追加が面倒だったので、同じエンジンをゼロからつくってました。(なかなか気付かなかったのですが、)これだとSphere要素がFacetを貫通しはじめました。中身をみると要素同士のinteractionsが認識されていませんでした。

O.engines = O.engines+[SomeEngine()]
O.engines = O.engines[:-1]+[SameEngine()] # wrong
ok

そのようなときは、新たにEngineを定義するのではなく、前のlabelを使って以下でいけました。

O.engines = O.engines+[SomeEngine(label)]
O.engines = O.engines[:-1]+[label] # ok

上以外の壁抜け

前もって下のことが起きてたので、原因確認が難しかった。

  • InsertionSortCollider忘れ
  • O.dtが大きすぎ

plot.plots

これはすぐに気づきますが(dictなので)、スペースをつけないと上書きされます。

plot.plots={ 't':('val1'), 't ':['val2','val3'] }

Warning: There cannot be duplicate names declared in separate plots. This is why spaces were used above to indicate the same variable t.

変更色々

O.bodies[i].state.pos += (0,0,1) # bad for sphere

modifying the position directly is likely to break Yade’s algorithms, especially those related to collision detection and contact laws, as they are based on bodies velocities.

Facet要素を移動するのは問題ないのですが、Sphere要素だとダメでした。いったん動くのですが、次のステップでもとに戻る。なので、そのようなときは、Facet要素のみを動かして相対的な位置関係で対応させました。

O.materials[i].young /= 10**5 # bad?

密詰めしたあとに、粒子径を変更すると反発力が大きすぎて、粒子が拡散します。それをさけるために、ばね定数を一時的にさげて、徐々に大きくするのを試しましたが、どうも挙動が安定しません。これは明らめました。

一方、frictAngleはチュートリアルにもあるので、よさそうです。

# create "dense" packing by setting friction to zero initially
O.materials[0].frictionAngle = 0 # ok

メモリ関連?

pack.randomDensePack後に、O.bodies.replaceByClumpsを実行すると、要素数が多い際には以下エラーがでました。(感覚的には、自分の環境では要素数5万前後が境界)

python3.8: /usr/include/boost/smart_ptr/shared_ptr.hpp:734: typename boost::detail::sp_member_access::type boost::shared_ptr::operator->() const [with T = yade::Body; typename boost::detail::sp_member_access::type = yade::Body*]: Assertion px != 0' failed. Aborted (core dumped)

O.bodies.replaceByClumpsを最後にではなく、複数にわければ問題なく実行できました。

おそらくメモリ問題だと思いますが、ここでそんなにメモリを使用してるのが意外でした。

interactions

ChatGPTに間違われてはまったところ。O.interactionsでも計算まわるのですが、.all()をつけないとなぜかすべてには回りませんでした。

count = 0
for i in O.interactions: # bad
    count += 1
print(len(O.interactions)==count) # False

for i in O.interactions.all(): # ok
    ....

未解決

force

以下のようにして、荷重をかけれます。

O.forces.addF(0,(1,0,0)) #applies for one step
O.forces.setPermF(0,(1,0,0)) #applies permanently

が、O.save()したのち、別でO.load()すると、確かにsetPermFは残ってるのですが(The permanent force on a body can be checked with O.forces.permF(id).)、明らかに挙動がおかしいことがありました。とりあえず、再度荷重をかけなおして対応してます。

threads

yade --threads=4 

TriaxialTest()で試したところ、numberOfGrains=1000, Iteration=100だと、thread=1が最も速くむしろthread数を増やすと遅くなります。 一方で、numberOfGrains=10万程度だと、thread=8程度で最も速くなりました。

InsertionSortCollider()が圧倒的に時間を占めているので、もう少し理解したい。

damping

これはソフトではなくDEM自体ですが、dampingがあまり理解できてません。Yadeでは計算簡易化されているようですが、基本的には他ソフトと同じような仕組みです。

https://yade-dem.org/doc/formulation.html#numerical-damping

計算式からは毎ステップdamping forceが発生してるので、dtに依存しそうですが、実際にはdtには依存していません。

Primary view

GUIから実行した場合は、Primary viewで様子が確認できるのですが、コマンドから実行すると画面が更新してくれません。