Açık Euler yöntemi reaksiyon difüzyon problemi için çok yavaş


10

Turing'in reaksiyon difüzyon sistemini aşağıdaki C ++ koduyla çözüyorum. Çok yavaş: 128x128 piksel doku için kabul edilebilir yineleme sayısı 200'dür - bu 2,5 saniyelik gecikme ile sonuçlanır. İlginç bir görüntü elde etmek için 400 yinelemeye ihtiyacım var - ancak 5 saniye beklemek çok fazla. Ayrıca, dokunun boyutu aslında 512x512 olmalıdır - ancak bu büyük bekleme süresine neden olur. Cihazlar iPad, iPod.

Bunu daha hızlı yapma şansı var mı? Euler yöntemi yavaşça yakınsar (wikipedia) - daha hızlı yönteme sahip olmak yineleme sayısını düşürmeye izin verir mi?

EDIT: Thomas Klimpel'in işaret ettiği gibi, satırlar: "if (m_An [i] [j] <0.0) {...}", "if (m_Bn [i] [j] <0.0) {...}" yakınsamayı geciktiriyor: kaldırıldıktan sonra 75 yinelemeden sonra anlamlı görüntü görünüyor . Aşağıdaki kod satırları yorum yaptık.

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();
    }
}

Ayrıca, durum sizin de çok benzer soruları gündeme görünür çünkü, sen çapraz sonrası soruları yok olması tercih edilir olduğunu belirtmek istiyorum burada ve burada .
Godric Seer

Greg Turk'in bu konudaki çalışmalarını zaten hiç gördünüz mü ?
JM

@JM: Henüz değil. Ben sadece onun kodu çalıştırmak denedim: PseudoColor, yani 8 bit renk derinliği ile X sunucusu gerektirir. Sanırım bunu OSX'te sağlayamıyorum. Çeşitli VNC sunucuları denedim ama şans yok.
TümCoder

Bence hala Türk'ün yaklaşımını eldeki konuya uyarlayabilmelisiniz; reaksiyon difüzyon paternleri günümüzde bilgisayar grafiklerinde oldukça fazla kullanılmaktadır.
JM

1
Yanılıyor olabilirim, ama m_An [i] [j] = 0.0 olan kısım ; aslında bu sisteme sürekli sağ tarafa sahip bir diferansiyel denklemle modellenemeyen bir eleman ekleyebilir. Bu, daha hızlı bir çözücü bulmayı biraz zorlaştırır.
Thomas Klimpel

Yanıtlar:


9

Izgarayı geliştirirken difüzyon sert olduğu için beklenen stabilite ile sınırlı görünüyorsunuz. Sert sistemler için iyi yöntemler en azından kısmen örtüktür. Biraz çaba gerektirecektir, ancak bu sistemi ondan az "çalışma birimi" (temelde zaman adımlarınızdan birinin maliyeti) ile çözmek için basit bir çoklu-manyetik algoritma uygulayabilirsiniz (veya bir kütüphane kullanabilirsiniz). Izgarayı hassaslaştırdığınızda, yineleme sayısı artmaz.


Burada sadece difüzyon sert olsaydı, Douglas-Gunn gibi bir ADI yöntemi kullanabilirdi ve her şey iyi olurdu. Bununla birlikte, kendi tecrübelerime göre, reaksiyon kısmı, kötü doğrusal olmamaya ek olarak sertlik açısından genellikle çok daha kötüdür.
Thomas Klimpel

1
ADI maalesef korkunç bir bellek yerleşimine sahip. Ayrıca, difüzyonun olup olmadığına bakılmaksızın reaksiyonun dolaylı olarak tedavi edilebileceğini de unutmayın. Izgara inceltme altında, difüzyon nihayetinde baskın hale gelecektir, ancak sabitleri bilmeden eşiğin nerede olduğunu söyleyemeyiz.
Jed Brown

Bunun için geriye doğru Euler uygulayan örnek kod (Python'da) burada: scicomp.stackexchange.com/a/2247/123
David Ketcheson

@DavidKetcheson: Örtük yöntemler kullanmak bir denklemi çözmeyi gerektirir mi? Bu yüzden kodda linalg.spsolve () var mı?
AllCoder

1
@AllCoder Evet, bir çözüm gerektirir, ancak çözüm, açık bir yöntemin kararlı olması için gereken tüm zaman adımlarından çok daha hızlı yapılabilir.
Jed Brown

2

Pratik bir bakış açısından: A5 işlemci o kadar güçlü değil, bu yüzden birkaç HW yinelemesi bekleyebilir veya ipod / ipad'iniz internete bağlanacaksa, sorununuzu uzaktan veya bulutta çözün.


A5'in ne kadar küçük bir güç sunduğuna şaşırdım. Pages, Safari ve diğer büyük uygulamalar nasıl bu kadar iyi çalışır? Ben rasgele, soyut görüntüler oluşturmak gerekir, morfogenez yeterince basit olacağını düşündüm ..
AllCoder

A5, web ve video (Sayfalar, Safari vb.) İçin optimize edilmiş enerji tasarruflu bir işlemcidir. Aksine, çoğu sayısal iş yükü tonlarca kayan nokta işlemi ve veri hareketi gerçekleştirir, bu özellikler düşük güçlü bir mobil işlemcinin odağı değildir.
fcruz

0

Euler diğer yöntemlerle yavaşça birleşiyor, ancak ilgilendiğiniz bu değil. Sadece "ilginç" görüntüler arıyorsanız, zaman adımınızın boyutunu artırın ve daha az yineleme yapın. Sorun, Jed'in belirttiği gibi, açık euler yönteminin ızgara boyutuyla ilişkili olarak büyük zaman adımları ile kararlılık sorunları olmasıdır. ızgaranız ne kadar küçükse (yani resminiz o kadar yüksek çözünürlüktedir), bunun için zaman adımınız o kadar küçük olmalıdır.

Örneğin, açık yerine örtük euler kullanarak, herhangi bir yakınsama sırası elde edemezsiniz, ancak çözüm koşulsuz kararlılığa sahip olacak ve çok daha büyük zaman adımlarına izin verecektir. Örtük yöntemler uygulamak ve zaman adımı başına daha fazla hesaplama yapmak için daha karmaşıktır, ancak toplamda daha az adım atarak bunun ötesinde kazançlar görmelisiniz.


Bu sorun kararlılıkla sınırlıdır, bu nedenle zaman adımı boyutunu artırmak işe yaramaz.
Jed Brown

Eğer 0.01 'i örneğin 0.015' e değiştirirsem, o zaman tüm noktalarda "kimyasal konsantrasyon sp. Sıfıra yakın" elde ederim - yani gri bir kare. İşte kodumun
AllCoder

Evet, bu Jed'in bahsettiği istikrar sorunlarının bir sonucu olacaktır. Cevabından bahsettiği gibi, daha iyi kararlılık performansı ile karakterize örtülü bir yöntem kullanmak bu sorunu sizin için çözecektir. Alakasız bilgileri kaldırmak için cevabımı güncelleyeceğim.
Godric Seer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.