「リープフロッグ」法は非常に効率的で安定しており、プラズマを含むあらゆる動的粒子/フィールドシステムに適しています。重力については、それは簡単です。これが、単一の惑星での単一の反復に対して行うすべてのことです(1体の問題、静止した太陽の周りの単一の惑星):
public void Push()
{
Position += Gravity.dT * Velocity;
Velocity += Gravity.dT * GravityAccelerationVector(Position);
}
ここで、「Gravity.dT」は、任意の時間の尺度での均一な時間ステップです。System.Windows.Vectorを使用していますが、基本的な乗算と加算をサポートしている限り、任意のカスタムVectorクラスで問題ありません。秘訣は、位置と速度が「同時に」ないことです。これは、ほとんどの積分方法で非常に一般的です。むしろ、それらはよろめきます。反復Nの位置は、反復N-1/2の速度に基づいて更新されますが、反復N + 1/2の速度は、反復Nの位置に基づいて更新されます。
N体バージョンは次のようになります。
public static void PushPlanets(Planet[] planets)
{
// Position Push at iteration N + 0:
foreach(var p in planets)
p.Position += Gravity.dT * p.Velocity; // Velocity from N - 1/2
// Velocity Push at iteration N + 1/2:
foreach (var p in planets)
{
Vector TotalGravity = new Vector(0,0);
foreach (var pN in planets)
{
if (pN == p) continue;
TotalGravity += pN.Mass * p.Mass * GravityAccelerationVector(p.Position - pN.Position);
}
TotalGravity += Sun.Mass * p.Mass * GravityAccelerationVector(p.Position); // Solar acceleration
p.Velocity += Gravity.dT * TotalGravity;
}
どこ
public static Vector GravityAccelerationVector(Vector position)
{
return Vector.Multiply(-G / position.LengthSquared / position.Length, position);
}
N体は、単一の重力源の代わりにいくつかあるため、より複雑になります。ただし、コード形式は同じです。各惑星の位置はN-1 / 2速度によってプッシュされ、次に新しい位置に基づいて各惑星の総重力加速度を計算し、次に各惑星の速度をその総加速度によってプッシュします。 。
他の方法は、高次の方法でさえ、位置と速度に基づいて次のステップを同時に線形に投影するため、不安定なことがよくあります。これは、システムにエネルギーを追加する側で常にエラーになり、軌道は徐々にさらに外側に移動します。他の方法では、この自然なエラーを過剰に補償し、システムからエネルギーを取り除くことができます。一般に、エネルギーに中立なソリューションが必要です。リープフロッグ法は、軌道の位相に関しては徐々に誤りますが、全体的なエネルギーに関しては誤りがありません。