Suscetibilidade magnética e calor específico
Ir para navegação
Ir para pesquisar
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
// Função para atribuir as energias do sistema
double W(double w[9], double);
///////////////////////////////////////////////////////////////////////////////////////////////////
// Função de atribuição de vizinhos em horizontais
int vizinhancaj(int l, int **vizinhoj)
{
int i;
for (i = 0; i < l; i++)
{
vizinhoj[i][1] = i+1;
vizinhoj[i][3] = i-1;
vizinhoj[i][2] = i;
vizinhoj[i][4] = i;
}
vizinhoj[0][3] = l-1;
vizinhoj[l-1][1] = 0;
}
// Função de atribuição de vizinhos verticais
int vizinhancai(int l, int **vizinhoi)
{
int i;
for (i = 0; i < l; i++)
{
vizinhoi[i][2] = i+1;
vizinhoi[i][4] = i-1;
vizinhoi[i][1] = i;
vizinhoi[i][3] = i;
}
vizinhoi[0][4] = l-1;
vizinhoi[l-1][2] = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Função responsável por calcular a variação de energia entre dois estados
double Eflip(int l, int** matrix, int i, int j, int **vizinhoi, int **vizinhoj)
{
int k, J = 1;
int E = 0;
for (k = 1; k < 5; k++)
{
E += matrix[vizinhoi[i][k]][vizinhoj[j][k]];
}
E = 2*J*E*matrix[i][j];
return E;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Função responsável por calcular a energia total do sistema
double ETotal(int** matrix, int **vizinhoi, int **vizinhoj, int l)
{
int i, j, k, J = 1;
double E = 0;
for(i = 0; i < l; i++)
for (j = 0; j < l; j++)
{
for (k = 1; k < 5; k++)
{
E += matrix[i][j]*matrix[vizinhoi[i][k]][vizinhoj[j][k]];
}
}
E *= -J;
return E/2.0; //Divisão por 2 por somamos duas vezes cada interação entre vizinhos
}
main()
{
int i, j, k, l = 20, MCS = 0, E; // l = Lado da matrix
int t = 0;
double r, prob, M = 0, T = 2.2, ET, w[9], X, M2 = 0, M_2 = 0, C, E2, E_2; // T = Temperatura
FILE *arq, *arq2;
// Incialização das matrizes utilizadas no sistema
int ** matrix = (int **)malloc(l*sizeof(int*));
int **vizinhoi = (int **)malloc(l*sizeof(int*));
int **vizinhoj = (int **)malloc(l*sizeof(int*));
for(i=0;i<l;i++)
{
vizinhoi[i] = (int*)malloc(5*sizeof(int));
vizinhoj[i] = (int*)malloc(5*sizeof(int));
matrix[i] = (int *) malloc(l*sizeof(int*));
}
vizinhancai(l,vizinhoi);
vizinhancaj(l,vizinhoj);
srand(time(0));
///////////////////////////////////////////////////////////////////////////////////////////////////
arq = fopen("Suscetibilidade", "w");
arq2 = fopen("Calor", "w");
for(T = 2.1; T <= 2.6; T+=0.01) // Laço de variação da temperatura
{
W(w,T); // Inicializar probabilidades de mudar de estado
// Incialização da matriz de spins aleatóriamente para cada temperatura
for (i = 0; i < l; i++)
{
for (j = 0; j < l; j++)
{
r = (double)rand()/RAND_MAX;
if (r < 0.5)
//Cooperadores recebem valor 0
matrix[i][j] = (int)-1;
else
//Desertores ganham valor 1
matrix[i][j] = (int)1;
}
}
ET = ETotal(matrix, vizinhoi, vizinhoj, l); // Calculo da energia total
M = 0;
// Calculo da magnetização total
for (i = 0; i < l; i++)
for (j = 0; j < l; j++)
M += matrix[i][j];
for (MCS = 0; MCS < 1e5; MCS++) // Laço de equilíbrio do sistema
{
for (t = 0; t < l*l; t++)
{
i = rand()%l;
j = rand()%l;
E = Eflip(l, matrix, i, j, vizinhoi, vizinhoj);
if(E <= 0)
{
matrix[i][j] = -matrix[i][j];
ET += E;
M += 2*matrix[i][j];
}
else
{
prob = w[E];
r = 1.*rand()/RAND_MAX;
if(r < prob)
{
matrix[i][j] = -matrix[i][j];
ET += E;
M += 2*matrix[i][j];
}
}
}
}
// Inicialização das variáveis de médias
M2 = 0;
M_2 = 0;
E2 = 0;
E_2 = 0;
for (MCS = 0; MCS < 1e6; MCS++) // Laço de MCS
{
for (t = 0; t < l*l; t++) // Laço de tempo para 1 MCS
{
// Escolha aleatória de um spin
i = rand()%l;
j = rand()%l;
// Calculo da variação de energia
E = Eflip(l, matrix, i, j, vizinhoi, vizinhoj);
// Condicional do método de Metropolis
if(E <= 0)
{
matrix[i][j] = -matrix[i][j];
ET += E;
M += 2*matrix[i][j];
}
else
{
prob = w[E];
r = 1.*rand()/RAND_MAX;
if(r < prob)
{
matrix[i][j] = -matrix[i][j];
ET += E;
M += 2*matrix[i][j];
}
}
}
// Somatórios de média e média quadráticas por spin para magnetização e energia
M2 += (1.*M/(l*l))*(1.*M/(l*l)); // somatório da média quadrática de M
E2 += (1.*ET/(l*l))*(1.*ET/(l*l)); // somatório da média quadrática de E
E_2 += 1.*ET/(l*l); // somatório da média de E
M_2 += fabs(1.*M/(l*l)); // somatório da média de M
}
// Cálculo final das médias e médias quadráticas
M_2 = (M_2/MCS); // Média de M
E_2 = (E_2/MCS); // Média de E
M_2 *= M_2; // Quadrado da média de M
E_2 *= E_2; // Quadrado da média de E
M2 /= MCS; // Média quadrática de M
E2 /= MCS; // Média quadrática de E
X = (l*l)*(M2-M_2)/T; // Calculo da suscetibilidade magnética
C = (l*l)*(E2-E_2)/(T*T); // Calculo do calor específico
// Impressão da suscetibilidade magnética e calor específico
fprintf(arq, "%lf\t%lf\n", T, X);
fprintf(arq2, "%lf\t%lf\n", T, C);
}
fclose(arq);
fclose(arq2);
}
//Função de probabilidade de mudar de estado
double W(double w[9], double T)
{
//return exp(-1.*E/(T));
w[2] = exp(-2.0/T);
w[4] = exp(-4.0/T);
w[6] = exp(-6.0/T);
w[8] = exp(-8.0/T);
}