javascript - metodo - ¿Por qué mi agua explota?
metodo de crianza aleman (2)
Estoy tratando de implementar el método Clavet para simular fluidos en JavaScript, por lo que la depuración es una pesadilla, por eso lo pregunto aquí, esperando que alguien que haya pasado por lo mismo me diga qué estoy haciendo mal.
Lo tengo funcionando bien hasta ahora:
Pero tengo dos problemas:
1) Ya que en este método todo está como "compensado" por medio paso, no estoy seguro de cómo hacer rebotar las partículas de las paredes correctamente. En este momento, tomo la posición de la partícula y la posición anterior y las giro alrededor de la pared cruzada, luego escala alrededor del punto de cruce por un factor de rebote.
Mi lógica me dice que esto debería funcionar. El siguiente paso en el algoritmo es actualizar las velocidades de las partículas, por lo que también reflejo la posición anterior. Pero en la práctica esto me da un resultado que no entiendo:
Esto muestra las "fuerzas" sobre las partículas. Las paredes reflejan demasiada fuerza, lo que mantiene todo en perpetuo movimiento.
La fórmula 4.58 en este documento aparentemente muestra una forma de prevenir esto, pero no he podido hacerlo funcionar.
También hay cosas en el documento que no entiendo, como lo que significa "solo queremos reflejar la velocidad que se omitió en la colisión". ¿Por qué? ¿Podría alguien ELI5 estas cosas para mí por favor?
2) Incluso cuando las paredes no están involucradas, la simulación "explota" periódicamente. Esto sucede más con mayor presión:
Esto es JavaScript, así que hay eso , pero he revisado el código y no hay divisiones por cero o situaciones en las que puedo imaginar que ocurra un NaN.
He visto algunos comentarios en los periódicos sobre la inestabilidad de las simulaciones, y me pregunto si es así. La mayor parte de lo que está en esta literatura está más allá de mí.
Por lo que entendí (creo), una de las formas de eliminar la inestabilidad es la viscosidad, pero la agregué y no ayudó con las explosiones:
Puedo publicar un código, pero en la primera etapa de conseguirlo para trabajar es un poco difícil de leer ahora mismo.
Una última pregunta: ¿cómo puedo averiguar cómo convertir de las pseudo constantes en este método a unidades físicas?
Edit: Descubrí que el simulador se congela ocasionalmente, parece que produce un NaN en algún lugar, pero Chrome lo atrapa demasiado tarde.
Obviamente hay mucho aquí. Estoy seguro de que no puedo responderlo todo, pero aquí hay algunos puntos esperanzadamente significativos:
Acerca de las paredes: lo que has implementado se llama espejo de impulso . En un fluido bajo presión, el espejo de impulso sirve para atraer partículas con una especie de tensión superficial negativa (porque no hay partículas más allá para repeler a las que están cerca del límite). Las partículas más compactas generarán mayores fuerzas y será más probable que causen problemas numéricos (especialmente porque su teletransportación tiende a otorgarles energía potencial).
Sobre el coeficiente de restitución: la escala lineal simple alrededor de la colisión produce una fuerza tangencial en el impacto que no es típica de los espejos de impulso, pero que tiende a producir una condición física antideslizante.
Sobre el segundo artículo que vinculó: creo que están intentando hacer algo inteligente en función de su proyección puntual. Sin embargo, no sé por qué simplemente se proyectan de nuevo a la superficie (en lugar de calcular un momento de colisión y luego una nueva posición basada en la nueva (reducida) velocidad a partir de entonces).
Suponiendo que este es un proyecto de CG sin un significado físico riguroso ...
En primer lugar, realmente debería considerar usar un paso de tiempo fijo para su código de simulación, de lo contrario obtendrá un comportamiento errático (y visualmente perturbador) cuando dt (y error) vibren alrededor. Si no puede obtener una tasa de cuadros consistente según sus requisitos finales, las posiciones deben interpolarse en lugar de simularse en puntos de tiempo no fijos.
con respecto a los cálculos de su muro, depende claramente del efecto que desee lograr en última instancia; por lo tanto, si aplica una condición de espejo más o menos conservadora del impulso (como está haciendo ahora), las partículas continuarán ''circulando'' alrededor incluso si se aplica una amortiguación. Si desea que el fluido se "pegue" a las paredes de alguna manera, necesita introducir fuerzas de pared o algún otro efecto disipativo más fuerte.
Ejecuté su código, y después de establecer un dt y una viscosidad de sintonía uniformes y simplificar el cálculo de la pared a más simple "if (p.px <izquierda) p.px = left + (left - p.px) * canvas.wallBounce; else if () ... "las condiciones me dan un buen comportamiento de ''relajación'' (si esto es lo que estás buscando). Actualizar también la posición anterior es contraproducente ya que aumentará la ''reflectividad'' de la pared, por así decirlo.