Réaction-Diffusion (2)

A propos du code

Le code dans cet article a été écrit avec Code::Blocks et la SDL 2.
Vous pouvez trouver ici un guide pour installer ces logiciels.
Bien qu'il soit basé sur la SDL, je n'utilise pas ses fonctions directement. J'ai écrit une petite bibliothèque
avec quelques fonctions basiques pour faciliter la compréhension et la portabilité dans un autre langage.
Vous pouvez en apprendre plus sur cette bibliothèque ici.

Mitose

Dans l'article précédent on a vu comment coder une réaction-diffusion et on l'a optimisée du mieux qu'on a pu.
Maintenant on va essayer différentes valeurs pour f et k et voir ce qui se passe.

Dans cet article on initialisera les tables avec plusieurs carrés plutôt qu'un seul:
		for (int i = 0; i < 10; i++)
		{
			int sze = 10 + (rand() % 10);
			int px = sze + (rand() % (SCREEN_WIDTH  - sze * 2));
			int py = sze + (rand() % (SCREEN_HEIGHT - sze * 2));

			for (int y = 0; y < sze; ++y)
				for (int x = 0; x < sze; ++x)
					table[0][1][px + x][py + y] = 1.0;
		}
				
Maintenant essayons ces coefficients:
		double f = 0.038;
		double k = 0.065;

		Télécharger le code source
		Télécharger l'exécutable pour Windows
				
On peut voir de petits points qui se dupliquent jusqu'à ce qu'ils remplissent tout l'écran.


Vers

Avec ces paramètres:
		double f = 0.046;
		double k = 0.065;

		Télécharger le code source
		Télécharger l'exécutable pour Windows
				
Des vers s'étendent lentement, essayant de remplir autant d'espace qu'ils le peuvent tout en s'évitant les uns les
autres.


Trèfles

Avec ces paramètres:
		double f = 0.042;
		double k = 0.061;

		Télécharger le code source
		Télécharger l'exécutable pour Windows
				
Celui là ressemble un peu aux programmes de l'article précédent.
Des trèfles s'étendent, devenant de plus en plus complexes jusqu'à ce qu'ils se rejoignent, créant un motif de
labyrinthe.


Bulles

Avec ces paramètres:
		double f = 0.062;
		double k = 0.061;

		Télécharger le code source
		Télécharger l'exécutable pour Windows
				
Des bulles rouges apparaissent dans un océan bleu clair qui s'étend.


Anneaux

Avec ces paramètres:
		double f = 0.062;
		double k = 0.063;

		Télécharger le code source
		Télécharger l'exécutable pour Windows
				
Des cercles grossissent, se rapprochant lentement de trèfles. Quand ils ne peuvent pas devenir plus complexes, des
vers s'étendent à partir de leurs extrémités.
A la fin on obtient un motif de labyrinthe comme dans l'article précédent.


Instable

Pour celui-ci on va avoir besoin d'un peu plus de carrés au départ, et ils auront une concentration moins forte.
		for (int i = 0; i < 15; i++)
		{
			[...]

			for (int y = 0; y < sze; ++y)
				for (int x = 0; x < sze; ++x)
					table[0][1][px + x][py + y] = 0.6;
		}
				
Maintenant on va utiliser une faible valeur pour f:
		double f = 0.01;
		double k = 0.045;

		Télécharger le code source
		Télécharger l'exécutable pour Windows
				
Celui-ci est intéressant. Des cercles vont grossir rapidement, réapparaissant de façon cyclique.
Jusqu'à ce qu'on obtienne un état où ils apparaissent continuellement.
Le résultat n'est pas garanti. Si vous êtes malchanceux la réaction va s'arrêter et vous obtiendrez un écran
complètement rouge.
Mais ça marche dans 70% des cas.

Ce comportement est similaire à la réaction chimique de Belousov-Zhabotinsky. Regardez la section "liens" pour une
vidéo à propos de ça.


Cartographier les paramètres

Maintenant essayons de produire une image où on peut voir tous ces comportements ensemble.
On a toujours utilisé des valeurs constantes pour f et k. Maintenant on va essayer de leur donner une valeur en
fonction des coordonnées à l'écran.

D'abord on va dessiner une plus grand image cette fois:
		#define SCREEN_WIDTH    800
		#define SCREEN_HEIGHT   800
				
On va initialiser les tables avec un damier de A et de B.
		//  initialize the table
		for (int y = 0; y < SCREEN_HEIGHT+2; ++y)
			for (int x = 0; x < SCREEN_WIDTH+2; ++x)
				for (int t = 0; t < 2; ++t)
				{
					int check = ((x / 10) % 2) ^ ((y / 10) % 2);
					table[t][0][y][x] = check;
					table[t][1][y][x] = 1 - check;
				}
				
Les coefficients f et k seront calculés à l'intérieur des boucles de update():
		for (int y = 1; y < SCREEN_HEIGHT+1; ++y)
			for (int x = 1; x < SCREEN_WIDTH+1; ++x)
			{
				double f = 0.01 + 0.09 * (SCREEN_HEIGHT - y) / (SCREEN_HEIGHT - 1);
				double k = 0.02 + 0.06 * (x - 1) / (SCREEN_WIDTH - 1);
				double ca = 1.0 - f - 1.8 * DA;
				double cb = 1.0 - f - 1.8 * DB - k;
				
A cause de la grande variation des valeurs que f et k peuvent prendre, les concentrations peuvent dépasser 1.
Alors on doit aussi tester ça dans update().
		for (int t = 0; t < 2; ++t)
		{
			if (table[1-curT][t][y][x] < 0.0)
				table[1-curT][t][y][x] = 0.0;
			if (table[1-curT][t][y][x] > 1.0)
				table[1-curT][t][y][x] = 1.0;
		}
				
Enfin, au début de update() on va remplir la colonne la plus à gauche de B et la colonne plus à droite de A pour
éviter des lignes noires sur les bords de l'écran.
		for (int t = 0; t < 2; ++t)
		{
			for (int y = 0; y < SCREEN_HEIGHT + 2; ++y)
			{
				table[curT][t][y][SCREEN_WIDTH - 1] = (t == 0 ? 1.0 : 0.0);
				table[curT][t][y][0] = (t == 0 ? 0.0 : 1);
				table[1-curT][t][y][SCREEN_WIDTH - 1] = (t == 0 ? 1.0 : 0.0);
				table[1-curT][t][y][0] = (t == 0 ? 0.0 : 1);
			}
		}

		Télécharger le code source
		Télécharger l'exécutable pour Windows
				
Et après quelques secondes on peut voir ça:


Vous trouverez une version bien plus détaillé de cette image dans un des liens ci-dessous.

Liens

Vidéo des programmes de cet article

Vidéo à propos de la réaction de Belousov-Zhabotinsky

Une analyse complète du modèle Gray-Scott