MBA: Gás simples: mudanças entre as edições
Sem resumo de edição |
Sem resumo de edição |
||
| Linha 63: | Linha 63: | ||
Foi realizado uma simulação com 100 partículas por | Foi realizado uma simulação com 100 partículas por 500.000 de passos em uma grade 100x100 com fronteira toroidal, o resultado encontra-se na figura abaixo assim como o código. | ||
<div class="center">[[Ficheiro:mba_colisao.png|centro|miniaturadaimagem|750x750px|Resultado da simulação com a distribuição de Maxwell-Boltmann para kT=0.7 e m=1.]]</div> | <div class="center">[[Ficheiro:mba_colisao.png|centro|miniaturadaimagem|750x750px|Resultado da simulação com a distribuição de Maxwell-Boltmann para kT=0.7 e m=1.]]</div> | ||
| Linha 97: | Linha 97: | ||
self.vel = (v*np.cos(ang),v*np.sin(ang)) #Velocidade decomposta | self.vel = (v*np.cos(ang),v*np.sin(ang)) #Velocidade decomposta | ||
self.colisao=False | self.colisao=False | ||
self.ac=False | |||
def prox_pos(self): | def prox_pos(self): | ||
| Linha 128: | Linha 129: | ||
nvel1=(self.vel[0]+u1*d[0],self.vel[1]+u1*d[1]) | nvel1=(self.vel[0]+u1*d[0],self.vel[1]+u1*d[1]) | ||
#partícula 2,pela conservação de momento: | #partícula 2,pela conservação de momento: | ||
nvel2=(self.vel[0]+a.vel[0]-nvel1[0],self.vel[1]+a.vel[1]-nvel1[1]) | nvel2=(self.vel[0]+a.vel[0]-nvel1[0],self.vel[1]+a.vel[1]-nvel1[1]) | ||
#Atualiza as velocidades | #Se nenhuma partícula tinha se colidido | ||
if (self.colisao==False and a.colisao==False): | |||
#Atualiza as velocidades | |||
self.vel=nvel1; a.vel=nvel2 | |||
self.ac=True;a.ac=True | |||
#Registra a colisão | #Registra a colisão | ||
self.colisao=True; a.colisao=True | self.colisao=True; a.colisao=True | ||
break | break | ||
return () | return () | ||
| Linha 138: | Linha 142: | ||
def movimento(self): | def movimento(self): | ||
if(self.colisao): | if(self.colisao): | ||
return (self.pos) | return (self.pos) | ||
else: | else: | ||
| Linha 195: | Linha 198: | ||
"""Avançar um passo do modelo""" | """Avançar um passo do modelo""" | ||
self.schedule.step() #Avançamos os agentes | self.schedule.step() #Avançamos os agentes | ||
#Limpamos as colisões | |||
for a in self.schedule.agents: #Vamos percorrer os agentes | |||
a.colisao=False | |||
#Parâmetros | #Parâmetros | ||
MAX = | MAX =1000000 | ||
N=100 | N=100 | ||
modelo = {"Largura": | modelo = {"Largura":100 ,"Altura":100 ,"Seed":1} | ||
M = Modelo(modelo,N) | M = Modelo(modelo,N) | ||
for i in range(MAX): | for i in range(MAX): | ||
| Linha 206: | Linha 211: | ||
#clear_output() | #clear_output() | ||
print(str(100*(1+i)/MAX)+"%") | print(str(100*(1+i)/MAX)+"%") | ||
vel=[] | vel=[] | ||
| Linha 220: | Linha 218: | ||
E+=a.vel[0]**2+a.vel[1]**2 | E+=a.vel[0]**2+a.vel[1]**2 | ||
print(E) | print(E) | ||
a,b,c=plt.hist(vel, | with open('velocidades0.2R100K1000.txt', 'w') as f: | ||
f.write(str(vel)) | |||
</pre> | |||
Para plotar o gráfico, podemos então usar simplesmente: | |||
<pre> | |||
import numpy as np | |||
import matplotlib.pyplot as plt | |||
a,b,c=plt.hist(vel,8, density=True, facecolor='g', alpha=0.75) | |||
m=1 | m=1 | ||
K=0.7 | K=0.7 | ||
x=np.arange(0,2, 0.00001) | x=np.arange(0,2.5, 0.00001) | ||
y = (4/np.sqrt(np.pi))*((m/K)**(3/2))*(x**2)*np.exp(-m*(x**2)/K) | y = (4/np.sqrt(np.pi))*((m/K)**(3/2))*(x**2)*np.exp(-m*(x**2)/K) | ||
plt.plot(x,y) | plt.plot(x,y) | ||
Edição das 07h47min de 22 de julho de 2022
Anterior: Por que usar e o que são modelos baseados em indivíduos | Índice: Ecologia | Próximo: MBA: Caminhante aleatório
Colisão entre partículas
Considerando um modelo simples de gás ideal, não há força atuando sob as partículas, então a interação que ocorre entre as partículas se dá apenas por meio de colisões. Assim é necessário calcular a variação na velocidade de cada partícula após a colisão. Começando em uma dimensão, precisamos garantir a conservação do momento:
Além disso vale lembrar que há a componente da velocidade perpendicular a , que vamos denotar como . Esta componente perpendicular permanece inalterada e pode ser visualizada na figura ao lado.
Sendo assim, a velocidade final é dada por:
Distribuição de velocidades para um gás a certa temperatura
A distribuição das velocidads das molécula de um gá é dada pela distribuição de Maxwell-Boltmann [1]
Foi realizado uma simulação com 100 partículas por 500.000 de passos em uma grade 100x100 com fronteira toroidal, o resultado encontra-se na figura abaixo assim como o código.
Código
Aqui chamamos a atenção que a principal diferença do código discutido para autômatos celulares é que agora não temos mais uma grade, mas um modelo contínuo. Também temos a possibilidade de configuração se as fronteiras serão toroidais (extremidades conectadas) ou não. Quanto aos resultados, precisamos considerar que é um modelo simplificado. O Calculo foi realizado para uma colisão entre duas partículas se dentro do mesmo passo deveria ocorrer mais de uma colisão, ou com mais de uma partícula simultaneamente o código falha, para remediar isso, o ideal é utilizar passos de tempo pequenos e/ou uma caixa relativamente grande em relação a quantidade de partículas. Além disso ao optarmos por uma fronteira toroidal ou não, estamos considerando uma caixa fechada ou não, ao considerarmos precisamos considerar a colisão com as fronteira também. Nesse último caso, uma simplificação simples é considerar que esta colisão ocorre primeiro. Novamente o problema surge se houver duas colisões no mesmo passo (agora podendo colidir com a fronteira), logo a recomendação é a mesma.
#Bibliotecas necessárias
from mesa import Agent, Model #Classes Agente e Modelo
from mesa.time import SimultaneousActivation #Agendador simultâneo
from mesa.space import ContinuousSpace #Malha multigrid
import random #Número aleatórios
from mesa.datacollection import DataCollector #Importamos um coletor de dados
import matplotlib.pyplot as plt #Plotar gráicos
#from IPython.display import clear_output #Configurações de saída do Colab
import numpy as np
#AGENTE---------------------------------------------------------------------------------
class Agente(Agent):
"""Classe do agente"""
def __init__(self, modelo,largura,altura):
"""Bibliotecas necessárias"""
#modelo - Modelo que ao qual o agente pertence
super().__init__(self, modelo) #Necessário para funcionar o modelo
self.ppos = (0,0) #Poição que irá se mover
self.rai= 0.2 #Raio
self.lim=(largura,altura) #Limites da caixa
v=1 #Módulo da velocidade inicial
ang = 2*random.random()*np.pi
self.vel = (v*np.cos(ang),v*np.sin(ang)) #Velocidade decomposta
self.colisao=False
self.ac=False
def prox_pos(self):
dt=0.01
nx=self.pos[0]+self.vel[0]*0.01
ny=self.pos[1]+self.vel[1]*0.01
#Testar os limites
if (nx < 0):
nx = - nx; self.vel=(-self.vel[0],self.vel[1])
if (nx > self.lim[0]):
nx = 2*self.lim[0] - nx; self.vel=(-self.vel[0],self.vel[1])
if (ny < 0):
ny = - ny; self.vel=(self.vel[0], - self.vel[1])
if (ny > self.lim[1]):
ny = 2*self.lim[1] - ny;self.vel=(self.vel[0], - self.vel[1])
return((nx,ny))
def prox_vel(self):
"""Movimentação dos animais"""
#Checamos se há colisão com outro animal:
agentes = self.model.continuous.get_neighbors(pos=self.ppos, radius = 3*self.rai, include_center=True)
for a in agentes: #Percorremos a lista
if (a.unique_id!=self.unique_id):
d=np.sqrt((a.ppos[0]-self.ppos[0])**2+(a.ppos[1]-self.ppos[1])**2)
if (d<=2*self.rai):
#Direção da colisão
d=(a.ppos[0]-self.ppos[0],a.ppos[1]-self.ppos[1])/np.sqrt((a.ppos[0]-self.ppos[0])**2+(a.ppos[1]-self.ppos[1])**2)
#Partícula 1
u1=(a.vel[0]-self.vel[0])*d[0]+(a.vel[1]-self.vel[1])*d[1]
nvel1=(self.vel[0]+u1*d[0],self.vel[1]+u1*d[1])
#partícula 2,pela conservação de momento:
nvel2=(self.vel[0]+a.vel[0]-nvel1[0],self.vel[1]+a.vel[1]-nvel1[1])
#Se nenhuma partícula tinha se colidido
if (self.colisao==False and a.colisao==False):
#Atualiza as velocidades
self.vel=nvel1; a.vel=nvel2
self.ac=True;a.ac=True
#Registra a colisão
self.colisao=True; a.colisao=True
break
return ()
def movimento(self):
if(self.colisao):
return (self.pos)
else:
return(self.ppos)
def step(self):
"""Método obrigatório que prepara as mudanças"""
self.ppos = self.prox_pos()
def advance(self):
"""Método obrigatório que aplica as mudanças"""
self.prox_vel()
self.model.continuous.move_agent(self, self.movimento())
#MODELO
class Modelo(Model):
"""Modelo geral"""
def gerar_particulas(self,N,largura,altura):
"""Função para gerar animais iniciais"""
#N - Número de animais
#largura - Largura da grade
#altura - Altura da grade
for n in range(N):
con=True
while(con):
con=False
a = Agente(self,largura,altura)
X= largura*random.random()
Y= altura*random.random()
if (len(self.schedule.agents)==0):
self.schedule.add(a)
self.continuous.place_agent(a, (X, Y))
else:
agentes = self.continuous.get_neighbors(pos=(X,Y), radius = 2*a.rai, include_center=True)
for viz in agentes:
con = (True) if (len(agentes)==0) else (con) #Precisamos checar se nasceu no mesmo lugar de outro animal
if(con==False):
self.schedule.add(a)
self.continuous.place_agent(a, (X, Y))
return()
def __init__(self, modelo,N,seed=None):
"""Função chamada quando o modelo é inicializazdo"""
# Modelo - Dicionário com especificações do modelo
# N - Número de partículas
# seed - Seed dos números aleatórios do modelo do mesa
# Desempacotar o dicionário
largura = modelo["Largura"];altura=modelo["Altura"]; random.seed(modelo["Seed"])
self.continuous = ContinuousSpace(x_max= largura, y_max=altura, torus= True, x_min=0, y_min= 0) #Configura a grade
self.schedule = SimultaneousActivation(self) #Configura o agendador
self.running = True #Condiçao para seguir executando o modelo
self.gerar_particulas(N,largura,altura) #Distribuir as ovelhas
def step(self):
"""Avançar um passo do modelo"""
self.schedule.step() #Avançamos os agentes
#Limpamos as colisões
for a in self.schedule.agents: #Vamos percorrer os agentes
a.colisao=False
#Parâmetros
MAX =1000000
N=100
modelo = {"Largura":100 ,"Altura":100 ,"Seed":1}
M = Modelo(modelo,N)
for i in range(MAX):
M.step()
if ((i+1)%(MAX/100)==0):
#clear_output()
print(str(100*(1+i)/MAX)+"%")
vel=[]
E=0
for a in M.schedule.agents:
vel.append(np.sqrt(a.vel[0]**2+a.vel[1]**2))
E+=a.vel[0]**2+a.vel[1]**2
print(E)
with open('velocidades0.2R100K1000.txt', 'w') as f:
f.write(str(vel))
Para plotar o gráfico, podemos então usar simplesmente:
import numpy as np import matplotlib.pyplot as plt a,b,c=plt.hist(vel,8, density=True, facecolor='g', alpha=0.75) m=1 K=0.7 x=np.arange(0,2.5, 0.00001) y = (4/np.sqrt(np.pi))*((m/K)**(3/2))*(x**2)*np.exp(-m*(x**2)/K) plt.plot(x,y)
Citações
Anterior: Por que usar e o que são modelos baseados em indivíduos | Índice: Ecologia | Próximo: MBA: Caminhante aleatório
