显式欧拉方法对于反应扩散问题太慢了

计算科学 pde 刚性
2021-12-07 05:50:56

我正在使用以下 C++ 代码解决图灵的反应扩散系统。太慢了:对于 128x128 像素纹理,可接受的迭代次数是 200 次——这会导致 2.5 秒的延迟。我需要 400 次迭代才能获得有趣的图像——但 5 秒的等待实在是太多了。此外,纹理的大小实际上应该是 512x512——但这会导致等待时间很长。这些设备是 iPad、iPod。

有没有机会更快地做到这一点?欧拉方法收敛缓慢(维基百科)——拥有更快的方法可以减少迭代次数?

编辑:正如 Thomas Klimpel 指出的那样,这些行:“if( m_An[i][j] < 0.0 ) { ... }”、“if( m_Bn[i][j] < 0.0 ) { ... }”正在延迟收敛:移除后,经过75 次迭代后出现有意义的图像我已经在下面的代码中注释掉了这些行。

void TuringSystem::solve( int iterations, double CA, double CB ) {
    m_iterations = iterations;
    m_CA = CA;
    m_CB = CB;

    solveProcess();
}

void set_torus( int & x_plus1, int & x_minus1, int x, int size ) {
    // Wrap "edges"
    x_plus1 = x+1;
    x_minus1 = x-1;
    if( x == size - 1 ) { x_plus1 = 0; }
    if( x == 0 ) { x_minus1 = size - 1; }
}

void TuringSystem::solveProcess() {
    int n, i, j, i_add1, i_sub1, j_add1, j_sub1;
    double DiA, ReA, DiB, ReB;

    // uses Euler's method to solve the diff eqns
    for( n=0; n < m_iterations; ++n ) {
        for( i=0; i < m_height; ++i ) {
            set_torus(i_add1, i_sub1, i, m_height);

            for( j=0; j < m_width; ++j ) {
                set_torus(j_add1, j_sub1, j, m_width);

                // Component A
                DiA = m_CA * ( m_Ao[i_add1][j] - 2.0 * m_Ao[i][j] + m_Ao[i_sub1][j]   +   m_Ao[i][j_add1] - 2.0 * m_Ao[i][j] + m_Ao[i][j_sub1] );
                ReA = m_Ao[i][j] * m_Bo[i][j] - m_Ao[i][j] - 12.0;
                m_An[i][j] = m_Ao[i][j] + 0.01 * (ReA + DiA);
                // if( m_An[i][j] < 0.0 ) { m_An[i][j] = 0.0; }

                // Component B
                DiB = m_CB * ( m_Bo[i_add1][j] - 2.0 * m_Bo[i][j] + m_Bo[i_sub1][j]   +   m_Bo[i][j_add1] - 2.0 * m_Bo[i][j] + m_Bo[i][j_sub1] );
                ReB = 16.0 - m_Ao[i][j] * m_Bo[i][j];
                m_Bn[i][j] = m_Bo[i][j] + 0.01 * (ReB + DiB);
                // if( m_Bn[i][j] < 0.0 ) { m_Bn[i][j]=0.0; }
            }
        }

        // Swap Ao for An, Bo for Bn
        swapBuffers();
    }
}
3个回答

您似乎受到稳定性的限制,这是意料之中的,因为在您细化网格时扩散是僵硬的。刚性系统的好方法至少部分是隐含的。这将需要一些努力,但您可以实现一个简单的多重网格算法(或使用库)来解决这个系统,其成本不到 10 个“工作单位”(基本上是您的一个时间步的成本)。细化网格时,迭代次数不会增加。

从实用的角度来看:A5处理器并没有那么强大,所以你可以等待几次硬件迭代,或者如果你的ipod/ipad要连接到互联网,远程或在云端解决你的问题。

欧拉确实相对于其他方法收敛缓慢,但我认为这不是你感兴趣的。如果您只是在寻找“有趣”的图像,请增加时间步长并减少迭代次数。正如 Jed 指出的那样,问题在于显式欧拉方法存在与网格大小相关的大时间步长的稳定性问题。您的网格越小(即图像的分辨率越高),您的时间步长必须越小才能考虑到它。

例如,通过使用隐式欧拉而不是显式,您不会获得任何收敛顺序,但解决方案将具有无条件稳定性,允许更大的时间步长。隐式方法实现起来更复杂,每个时间步需要更多的计算,但是你应该看到通过减少总步数获得的收益。