Simulação do Modelo de Gray-Scott
Ir para navegação
Ir para pesquisar
/********************************************************
* Modelo de Gray-Scott *
*******************************************************/
/********************************************************
* Grid de 69 x 69 (L x L) *
********************************************************
* Parâmetros (na ordem): *
* tmax F k Du Dv *
* *
* Exemplo: *
* ./a.out 1000 0.015 0.055 0.00002 0.00001 *
* ./a.out tmax F k Du Dv *
* *
* Saída para gnuplot: *
********************************************************
* compilar com: *
* gcc -DGNU gray-scott.c -lm *
********************************************************
* Executar com pipe: *
* ./a.out PARAMETROS | gnuplot *
* *
********************************************************
* O programa sempre gera um arquivo com o *
* resultado da simulação para tmax. Exemplo: *
* gs_f_0.015_k_0.055_tmax_1000.dat *
********************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
const int L=69;
const int L2=4761;
const double dh=0.014;
const double dt=0.02;
double tmax;
double Du, Dv;
double f, k;
void init(double *, double *, char *[]);
void update(double *, double *, double *, double *);
void gnuplot(double *);
int main(int argc, char *argv[ ])
{
FILE *fp;
char output[100];
double t = 0;
double *u, *v;
double *n_u, *n_v;
int count = 0;
u = (double*)calloc(L2, sizeof(double));
v = (double*)calloc(L2, sizeof(double));
n_u = (double*)calloc(L2, sizeof(double));
n_v = (double*)calloc(L2, sizeof(double));
init(u, v, argv);
while(t < tmax)
{
update(u, v, n_u, n_v);
#ifdef GNU
if(count % 50 == 0)
{
printf("set title 'Tempo %.2lf'\n", t);
gnuplot(u);
}
#endif
t += dt;
count += 1;
}
#ifdef GNU
gnuplot(u);
printf("pause 5\n");
#endif
sprintf(output,"gs_f_%.3f_k_%.3f_tmax_%.0f.dat",f, k, tmax);
fp = fopen(output, "w");
for(int i=0; i<L; i++)
{
for(int j=0; j<L; j++)
fprintf(fp, "%lf ", *(u+i*L+j));
fprintf(fp, "\n");
}
fclose(fp);
free(u);
free(v);
free(n_u);
free(n_v);
return 0;
}
/*INICIALIZAÇÃO:
Escolhendo o ponto do meio do grid para tirar o sistema do equilíbrio,
os demais pontos estão no equilíbrio trivial (u, v) = (1, 0).
Pressupõe-se que L seja ímpar. Se L for par, o ponto inicialmente fora
do equilíbrio não será central.
*/
void init(double *u, double *v, char *argv[ ])
{
for(int i=0; i<L; i++)
for(int j=0; j<L; j++)
{
*(u+i*L+j) = (i*L+j == (L2-1)/2)? 0.0 : 1.0;
*(v+i*L+j) = 1.0-*(u+i*L+j);
}
tmax = atof(argv[1]);
f = atof(argv[2]);
k = atof(argv[3]);
Du = atof(argv[4]);
Dv = atof(argv[5]);
}
/*Atualização das matrizes. Esse é o núcleo do programa. Integram-se as
equações do modelo com FTCS. São usadas as seguintes condições de fronteira
periódicas:
* Se i=0 (primeira linha da matriz), o vizinho da esquerda está na última
linha da matriz, com mesmo j;
* Se j=0 (primeira coluna da matriz), o vizinho de baixo está na última
coluna da matriz, com mesmo i;
* Se j=L-1 (última coluna da matriz), o vizinho de cima está na primeira
coluna da matriz, com mesmo i
* Se i=L-1 (última linha da matriz, o vizinho da direita está na primeira
linha da matriz, com mesmo j).
*/
void update(double *u, double *v, double *n_u, double *n_v)
{
int i, j;
double uLap, vLap;
double uC, uR, uL, uU, uD;
double vC, vR, vL, vU, vD;
for(i=0; i<L; i++)
for(j=0; j<L; j++)
{
/*Condições de fronteira periódicas:*/
uC = *(u+i*L+j);
uU = *(u+i*L+(j+1)%L);
uR = *(u+((i+1)%L)*L+j);
uL = (i==0)? *(u+L2-L+j) : *(u+(i-1)*L+j);
uD = (j==0)? *(u+i*L+(L-1)) : *(u+i*L+(j-1));
vC = *(v+i*L+j);
vU = *(v+i*L+(j+1)%L);
vR = *(v+((i+1)%L)*L+j);
vL = (i==0)? *(v+L2-L+j) : *(v+(i-1)*L+j);
vD = (j==0)? *(v+i*L+(L-1)) : *(v+i*L+(j-1));
/*Laplacianos discretizados*/
uLap = (uR + uL + uU + uD - 4*uC)/(dh*dh);
vLap = (vR + vL + vU + vD - 4*vC)/(dh*dh);
/*Equações do modelo discretizadas*/
*(n_u+i*L+j) = uC + (-uC*vC*vC + f*(1-uC) + Du*uLap)*dt;
*(n_v+i*L+j) = vC + (uC*vC*vC - (f+k)*vC + Dv*vLap)*dt;
}
for(i=0; i<L; i++)
for(j=0; j<L; j++)
{
*(u+i*L+j) = *(n_u+i*L+j);
*(v+i*L+j) = *(n_v+i*L+j);
}
}
/*Visualização no gnuplot. Autoexplicativo. Este módulo é praticamente
igual ao criado pelo grupo do modelo de Turing. Apenas foi acrescentado
o comando set palette gray*/
void gnuplot(double *arr)
{
printf("set xrange [0:%d]\nset yrange [0:%d]\n", (L-1), (L-1));
printf("unset xtics\nunset ytics\n");
printf("unset colorbox\n");
printf("set size square\n");
printf("set key off\n");
printf("set palette gray\n");
printf("set pm3d map\n");
printf("set cbrange [0:1]\n");
printf("splot \"-\" matrix w image\n");
for(int i=0; i<L; i++)
{
for(int j=0; j<L; j++)
printf("%lf ", *(arr+i+j*L));
printf("\n");
}
printf("\n\n\ne\n\n");
}