Я решаю систему реакции-диффузии Тьюринга с помощью следующего кода C ++. Это слишком медленно: для текстуры 128x128 пикселей допустимое количество итераций составляет 200, что приводит к задержке в 2,5 секунды. Мне нужно 400 итераций, чтобы получить интересное изображение, но 5 секунд ожидания - это слишком много. Кроме того, размер текстуры должен быть на самом деле 512x512 - но это приводит к огромному времени ожидания. Устройства iPad, iPod.
Есть ли шанс сделать это быстрее? Метод Эйлера сходится медленно (википедия) - более быстрый метод позволил бы уменьшить количество итераций?
РЕДАКТИРОВАТЬ: Как отметил Томас Климпел, строки: «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();
}
}
Ответы:
Вы, кажется, ограничены стабильностью, которая ожидается, так как диффузия жесткая, когда вы улучшаете сетку. Хорошие методы для жестких систем по крайней мере частично неявны. Это займет некоторое усилие, но вы можете реализовать простой многосеточный алгоритм (или использовать библиотеку) для решения этой системы со стоимостью менее десяти «рабочих единиц» (по сути, стоимость одного из ваших временных шагов). Когда вы уточняете сетку, количество итераций не будет увеличиваться.
источник
С практической точки зрения: процессор A5 не такой мощный, поэтому вы можете подождать несколько итераций HW или, если ваш ipod / ipad будет подключен к Интернету, решить вашу проблему удаленно или в облаке.
источник
Эйлер медленно сходится по отношению к другим методам, однако я не думаю, что это то, что вас интересует. Если вы просто ищете «интересные» изображения, увеличьте размер своего временного шага и выполняйте меньше итераций. Проблема, как указывает Джед, состоит в том, что явный метод Эйлера имеет проблемы со стабильностью с большими временными шагами по отношению к размеру сетки. чем меньше ваша сетка (т. е. чем выше разрешение вашего изображения), тем меньше должен быть ваш временной шаг для ее учета.
Например, используя неявный эйлер вместо явного, вы не получите никаких порядков сходимости, но решение будет иметь безусловную стабильность, позволяющую гораздо большие временные шаги. Неявные методы являются более сложными для реализации и требуют больше вычислений за такт, но вы должны увидеть преимущества намного выше, если в общем предпринять меньше шагов.
источник