Está en la página 1de 13

Maria Paula Osorio Santamaria - 1202448

Simulación de Partículas en una Esfera Contenedora

En este informe, se presenta un análisis detallado de la simulación de partículas en una esfera


contenedora mediante el uso de Unity. La simulación modela el movimiento de dos partículas
esféricas conectadas por un resorte dentro de una esfera de mayor tamaño. El objetivo es
entender el comportamiento dinámico de las partículas y su interacción con la esfera contenedora.

Análisis Matemático

1. Fuerza del Resorte: La fuerza ejercida por el resorte se calcula utilizando la ley de Hooke

donde k es la constante del resorte y x es la elongación o compresión del resorte. Esta fuerza
restauradora asegura que las partículas oscilen alrededor de su posición de equilibrio.

2. Fuerza de Amortiguación: La fuerza de amortiguación modela la resistencia del medio


circundante y se calcula utilizando la ley de resistencia viscosa de Stokes:

donde b es el coeficiente de amortiguación y v es la velocidad de las partículas. Esta fuerza simula


la pérdida de energía cinética debido a la fricción.

3. Colisión con la Esfera: Se utilizan principios de colisiones elásticas para simular la interacción de
las partículas con la esfera contenedora. Cuando una partícula choca con la esfera, se calcula el
vector de reflexión para rebotar la partícula en la dirección opuesta, conservando la energía
cinética total del sistema.

Análisis Físico

1. Movimiento en un Espacio Confinado: El movimiento de las partículas dentro de la esfera


contenedora está restringido por las fuerzas del resorte y las colisiones con la esfera. Esto crea un
entorno confinado que afecta el comportamiento dinámico de las partículas, generando
trayectorias oscilatorias y rebotes controlados.

2. Conservación de la Energía: La simulación garantiza que la energía total del sistema se conserve,
lo que significa que la suma de la energía cinética y potencial de las partículas se mantiene
constante a lo largo del tiempo. Esto es crucial para asegurar una representación física precisa del
movimiento de las partículas.
Maria Paula Osorio Santamaria - 1202448

3. Estabilidad del Sistema: La estabilidad del sistema se mantiene mediante el control de las
fuerzas aplicadas y la precisión del método de integración numérica. Hay que asegurar que las
fuerzas de resorte y amortiguación estén equilibradas permite que las partículas oscilen de manera
controlada sin perder estabilidad.

Explicación del código

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Simulacion : MonoBehaviour

int N = 2; // Número de partículas

float[,] f; // Estado de las partículas (posiciones y velocidades)

float[,] df; // Derivadas del estado de las partículas (velocidades y aceleraciones)

float masa;

float h;

float ke;

float kb;

float tiempo;

float longitudInicial; // Longitud inicial del resorte

GameObject[] misEsferas;

Vector3 gravedad;

float radioEsfera = 5.0f; // Radio de la esfera contenedora (la escala será x=10, y=10, z=10)

float radioParticula = 0.5f; // Radio de las partículas

float kSpring; // Constante del resorte

int particulaDominante = 0; // Índice de la partícula dominante


Maria Paula Osorio Santamaria - 1202448

 Se importan las librerías necesarias y se declara la clase Simulación que hereda de


MonoBehaviour.
 Se definen variables para almacenar información sobre las partículas, como su estado
(posiciones y velocidades), masa, paso de tiempo, constantes de resorte y amortiguación,
entre otros.
 misEsferas es un array de objetos de tipo GameObject que representan las partículas en la
escena.
 particulaDominante indica cuál de las partículas tiene el control de movimiento.

void Start()

misEsferas = new GameObject[N];

misEsferas[0] = GameObject.Find("Sphere1");

misEsferas[1] = GameObject.Find("Sphere2");

// Posición inicial de la Sphere1

Vector3 posicionInicial1 = new Vector3(0, 0, 2);

misEsferas[0].transform.position = posicionInicial1;

// Posición inicial de la Sphere2

Vector3 posicionInicial2 = new Vector3(0, 0, -2);

misEsferas[1].transform.position = posicionInicial2;

longitudInicial = 10.0f; // Longitud inicial del resorte según las condiciones iniciales

Inicializar();

 En el método Start(), se inicializa el array misEsferas con los objetos de la escena


identificados por sus nombres.
 Se asignan posiciones iniciales específicas para Sphere1 y Sphere2.
 Luego se llama al método Inicializar().

// Genera una dirección de movimiento aleatoria dentro de la esfera

Vector3 ObtenerDireccionMovimientoAleatoria()

{
Maria Paula Osorio Santamaria - 1202448

Vector3 direccionAleatoria = new Vector3(

Random.Range(-1f, 1f),

Random.Range(-1f, 1f),

Random.Range(-1f, 1f)

).normalized;

return direccionAleatoria;

// Genera una posición aleatoria dentro de la esfera contenedora

Vector3 ObtenerPosicionAleatoriaDentroEsfera()

Vector3 posicionAleatoria = new Vector3(

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula)

);

while (posicionAleatoria.magnitude > radioEsfera - radioParticula)

// Si la posición aleatoria está fuera de la esfera, generar una nueva posición

posicionAleatoria = new Vector3(

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula)

);

return posicionAleatoria;
Maria Paula Osorio Santamaria - 1202448

 Estos métodos generan direcciones y posiciones aleatorias dentro de la esfera


contenedora.
 ObtenerDireccionMovimientoAleatoria() devuelve una dirección aleatoria normalizada.
 ObtenerPosicionAleatoriaDentroEsfera() genera una posición aleatoria dentro de la esfera,
asegurándose de que esté dentro de ella.

void Inicializar()

// Se inicializan las matrices de estado y derivadas de las partículas

f = new float[N, 6]; // Estado de las partículas (posiciones y velocidades)

df = new float[N, 6]; // Derivadas del estado de las partículas (velocidades y aceleraciones)

h = 0.005f; // Paso de tiempo

tiempo = 0.0f; // Tiempo inicial

masa = 1.0f; // Masa de las partículas

ke = 0.6f; // Constante del resorte

kb = 0.4f; // Constante de amortiguación

gravedad = Vector3.zero; // Gravedad cero

// Calcular la constante del resorte comprimido

float elongacionInicial = longitudInicial - (misEsferas[1].transform.position -


misEsferas[0].transform.position).magnitude;

kSpring = (ke * elongacionInicial) / longitudInicial;

// Asignar las posiciones y velocidades iniciales a las partículas

for (int n = 0; n < N; n++)

Vector3 posicionInicial = ObtenerPosicionAleatoriaDentroEsfera();

Vector3 velocidadInicial = ObtenerDireccionMovimientoAleatoria();

f[n, 0] = posicionInicial.x;

f[n, 1] = posicionInicial.y;

f[n, 2] = posicionInicial.z;
Maria Paula Osorio Santamaria - 1202448

f[n, 3] = velocidadInicial.x;

f[n, 4] = velocidadInicial.y;

f[n, 5] = velocidadInicial.z;

ActualizarVista();

 Este método inicializa las variables de estado de las partículas y calcula la constante del
resorte comprimido.
 Luego, asigna posiciones y velocidades iniciales aleatorias dentro de la esfera a las
partículas.
 Finalmente, llama al método ActualizarVista() para actualizar la representación visual en la
escena.

Código Completo

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Simulacion : MonoBehaviour

int N = 2; // Número de partículas

float[,] f; // Estado de las partículas (posiciones y velocidades)

float[,] df; // Derivadas del estado de las partículas (velocidades y aceleraciones)

float masa;

float h;

float ke;

float kb;

float tiempo;

float longitudInicial; // Longitud inicial del resorte

GameObject[] misEsferas;

Vector3 gravedad;
Maria Paula Osorio Santamaria - 1202448

float radioEsfera = 5.0f; // Radio de la esfera contenedora (la escala será x=10, y=10, z=10)

float radioParticula = 0.5f; // Radio de las partículas

float kSpring; // Constante del resorte

int particulaDominante = 0; // Índice de la partícula dominante

void Start()

misEsferas = new GameObject[N];

misEsferas[0] = GameObject.Find("Sphere1");

misEsferas[1] = GameObject.Find("Sphere2");

// Posición inicial de la Sphere1

Vector3 posicionInicial1 = new Vector3(0, 0, 2);

misEsferas[0].transform.position = posicionInicial1;

// Posición inicial de la Sphere2

Vector3 posicionInicial2 = new Vector3(0, 0, -2);

misEsferas[1].transform.position = posicionInicial2;

longitudInicial = 10.0f; // Longitud inicial del resorte según las condiciones iniciales

Inicializar();

// Genera una dirección de movimiento aleatoria dentro de la esfera

Vector3 ObtenerDireccionMovimientoAleatoria()

Vector3 direccionAleatoria = new Vector3(

Random.Range(-1f, 1f),

Random.Range(-1f, 1f),
Maria Paula Osorio Santamaria - 1202448

Random.Range(-1f, 1f)

).normalized;

return direccionAleatoria;

// Genera una posición aleatoria dentro de la esfera contenedora

Vector3 ObtenerPosicionAleatoriaDentroEsfera()

Vector3 posicionAleatoria = new Vector3(

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula)

);

while (posicionAleatoria.magnitude > radioEsfera - radioParticula)

// Si la posición aleatoria está fuera de la esfera, generar una nueva posición

posicionAleatoria = new Vector3(

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula),

Random.Range(-radioEsfera + radioParticula, radioEsfera - radioParticula)

);

return posicionAleatoria;

void Inicializar()
Maria Paula Osorio Santamaria - 1202448

f = new float[N, 6]; // Estado de las partículas (posiciones y velocidades)

df = new float[N, 6]; // Derivadas del estado de las partículas (velocidades y aceleraciones)

h = 0.005f; // Paso de tiempo

tiempo = 0.0f; // Tiempo inicial

masa = 1.0f; // Masa de las partículas

ke = 0.6f; // Constante del resorte

kb = 0.4f; // Constante de amortiguación

gravedad = Vector3.zero; // Gravedad cero

// Calcular la constante del resorte comprimido

float elongacionInicial = longitudInicial - (misEsferas[1].transform.position -


misEsferas[0].transform.position).magnitude;

kSpring = (ke * elongacionInicial) / longitudInicial;

// Asignar las posiciones y velocidades iniciales a las partículas

for (int n = 0; n < N; n++)

Vector3 posicionInicial = ObtenerPosicionAleatoriaDentroEsfera();

Vector3 velocidadInicial = ObtenerDireccionMovimientoAleatoria();

f[n, 0] = posicionInicial.x;

f[n, 1] = posicionInicial.y;

f[n, 2] = posicionInicial.z;

f[n, 3] = velocidadInicial.x;

f[n, 4] = velocidadInicial.y;

f[n, 5] = velocidadInicial.z;

ActualizarVista();

}
Maria Paula Osorio Santamaria - 1202448

void CalcularVariables()

// Obtener las posiciones y velocidades de las partículas

Vector3[] posicion = new Vector3[N];

Vector3[] velocidad = new Vector3[N];

for (int n = 0; n < N; n++)

posicion[n] = new Vector3(f[n, 0], f[n, 1], f[n, 2]);

velocidad[n] = new Vector3(f[n, 3], f[n, 4], f[n, 5]);

// Calcular las fuerzas que actúan sobre las partículas

Vector3[] fuerza = new Vector3[N];

for (int n = 0; n < N; n++)

fuerza[n] = Vector3.zero; // Inicializamos la fuerza en cero

// Calcular la fuerza del resorte para la partícula dominante

if (n == particulaDominante)

Vector3 direccionResorte = posicion[1 - n] - posicion[n];

float longitudActual = direccionResorte.magnitude;

float elongacion = longitudActual - longitudInicial;

fuerza[n] += kSpring * elongacion * direccionResorte.normalized;

fuerza[n] -= kb * velocidad[n]; // Fuerza de amortiguación

// Verificar colisión con la esfera y aplicar fuerzas de rebote


Maria Paula Osorio Santamaria - 1202448

if (posicion[n].magnitude + radioParticula > radioEsfera)

Vector3 direccionNormalizada = posicion[n].normalized;

velocidad[n] = Vector3.Reflect(velocidad[n], direccionNormalizada);

posicion[n] = direccionNormalizada * (radioEsfera - radioParticula);

else if (posicion[n].magnitude - radioParticula < -radioEsfera)

Vector3 direccionNormalizada = -posicion[n].normalized;

velocidad[n] = Vector3.Reflect(velocidad[n], direccionNormalizada);

posicion[n] = direccionNormalizada * (radioEsfera + radioParticula);

// Asignar las fuerzas calculadas a las derivadas del estado de las partículas

for (int n = 0; n < N; n++)

for (int i = 0; i < 3; i++)

df[n, i] = velocidad[n][i];

df[n, i + 3] = fuerza[n][i] / masa;

// Actualizar las posiciones de las partículas

for (int n = 0; n < N; n++)

f[n, 0] = posicion[n].x;

f[n, 1] = posicion[n].y;
Maria Paula Osorio Santamaria - 1202448

f[n, 2] = posicion[n].z;

f[n, 3] = velocidad[n].x;

f[n, 4] = velocidad[n].y;

f[n, 5] = velocidad[n].z;

void ResolverEcuaciones()

// Integrar las ecuaciones de movimiento usando el método de Euler

for (int n = 0; n < N; n++)

for (int j = 0; j < 6; j++)

f[n, j] += (df[n, j] * h);

tiempo += h;

void ActualizarVista()

// Actualizar la posición visual de las partículas en la escena

for (int n = 0; n < N; n++)

misEsferas[n].transform.position = new Vector3(f[n, 0], f[n, 1], f[n, 2]);

}
Maria Paula Osorio Santamaria - 1202448

void Update()

CalcularVariables();

ResolverEcuaciones();

ActualizarVista();

Conclusiones

 La simulación implementada ofrece una representación precisa y realista del movimiento


de las partículas dentro de una esfera contenedora. Al considerar cuidadosamente los
principios físicos y matemáticos subyacentes, el modelo proporciona una herramienta
efectiva para estudiar el.
 Comportamiento dinámico de sistemas de partículas en un espacio confinado. Este
enfoque tiene aplicaciones en campos como la física, la ingeniería y la animación
computacional, y puede ser utilizado para investigaciones científicas y desarrollo de
aplicaciones interactivas.

También podría gustarte