International Essays |
¿Cuánto tiempo hervir un huevo? Modelado MEF con Wolfram Language
¿Cuánto tiempo hervir un huevo? Modelado MEF con Wolfram Language
15 de septiembre de 2025
Este cuaderno es una traducción al español del artículo de la Comunidad Wolfram “How Long to Boil an Egg? FEM Modeling with Wolfram Language” producido con ayuda de un LLM y verificado por un traductor profesional
Ricardo López, Practicante en desarrollo de aplicaciones de física, Investigación y desarrollo de algoritmos; Gay Wilson, Curador de datos alimentarios, Contenido científico de Wolfram|Alpha; Oliver Ruebenkoenig, Desarrollador de kernels sénior, Investigación y desarrollo de algoritmos
Es hora de responder la pregunta que todo amante del desayuno se hace: “¿Cuánto tiempo debo hervir un huevo?” Aunque parezca tan sencillo colocar un huevo en agua hirviendo y esperar, sería un error decir que un huevo completamente duro es la única manera de disfrutar de un delicioso aporte de proteína. Podemos utilizar el método de los elementos finitos (MEF) para simular las condiciones de un huevo en agua y encontrar la temperatura y duración ideales para la cocción perfecta, evaluando los cambios de temperatura dentro del propio huevo. Así, podemos predecir cuánto tiempo tarda en alcanzar distintas consistencias, tales como una yema líquida o una yema grumosa y firme.
El primer paso para modelar sistemas físicos complejos a menudo es descomponerlos en partes manejables. Eso es exactamente lo que hace el MEF: divide una estructura complicada en elementos más pequeños y sencillos, resuelve las ecuaciones rectoras localmente, y luego ensambla los resultados para capturar el comportamiento de todo el sistema.
Este enfoque permite simular y analizar escenarios del mundo real sin el costo y esfuerzo de los prototipos físicos. Ahora presentaremos el flujo de trabajo del análisis por elementos finitos en Wolfram Language y recorreremos un ejemplo sencillo que cubre los aspectos básico y resalta problemas comunes que pueden surgir en el proceso.
Nuestro objetivo es proporcionar una comprensión general de cómo resolver ecuaciones diferenciales parciales (EDP) de forma numérica utilizando el MEF, junto con un recurso práctico que podemos usar para construir nuestros propios modelos.
¿Por qué usar elementos finitos?
¿Por qué usar elementos finitos?
Muchas EDP (incluyendo ecuaciones clásicas como las de Poisson o Schrödinger) no siempre tienen una solución analítica, en especial si la región en la que intentamos resolver la ecuación es algo complicada. El MEF es una técnica valiosa para resolver EDP de forma numérica por al menos dos razones: Primero, se pueden resolver EDP en regiones de forma arbitraria. Segundo, se pueden resolver muchos tipos de ecuaciones diferenciales, desde la ecuación de Laplace hasta las ecuaciones de Navier–Stokes.
Herramientas necesarias para el análisis por elementos finitos
Herramientas necesarias para el análisis por elementos finitos
◼
Una región que se discretiza en una malla. Esta malla consta de muchas subregiones pequeñas y simples llamadas elementos. La idea clave del MEF es resolver una versión más simple de la EDP dentro de cada elemento y luego combinar estas soluciones locales en una solución global que aproxime el comportamiento de la EDP original en toda la región.
◼
La EDP específica que queremos resolver.
◼
Condiciones de frontera, las cuales vinculan la EDP con el mundo fuera de la región donde se está calculando la solución.
En Wolfram Language, el MEF está implementado mediante las funciones , y , y utilizaremos NDSolveValue en nuestro escenario del huevo hervido.
Versión 1: Iniciar un flujo de trabajo
Versión 1: Iniciar un flujo de trabajo
Construiremos nuestro modelo paso a paso, pasando por varias versiones y aumentando la complejidad del modelo en incrementos. Comenzaremos con un modelo sencillo, teniendo en cuenta los tamaños de los objetos y las unidades.
El primer paso es definir la geometría o la región de la estructura. Debido a que un huevo tiene simetría axial, supondremos que analizar una sección del huevo es suficiente para describir su comportamiento. Para el MEF, necesitamos discretizar la región en una malla y, ya que una malla bidimensional no requiere tantos elementos para aproximar la geometría como lo haría una malla tridimensional, nuestro cálculo tomará menos tiempo. Esta es una razón importante para utilizar un modelo axisimétrico.
Un huevo promedio puede tener aproximadamente 5 cm de diámetro y 2,5 cm de radio. Ya que la práctica óptima es utilizar unidades SI para los parámetros del modelo, definiremos el radio del huevo como 0,025 m. En este punto, estamos ignorando deliberadamente cualquier diferencia entre el material de la yema y la clara del huevo. Nuestro objetivo es hacer que esta versión inicial del modelo sea lo más simple posible.
Carga el paquete de Elementos Finitos:
In[]:=
Needs["NDSolve`FEM`"]
También estableceremos como 0, lo cual limita el número de resultados previos almacenados en la sesión a cero, ahorrando memoria computacional a un costo mínimo.
Establece $HistoryLength como 0:
In[]:=
$HistoryLength=0;
Crea una geometría sencilla de un huevo:
In[]:=
radius=0.025;Ω=RegionUnion[Circle[{0,0},radius,{-π/2,π/2}],Line[{{0,radius},{0,-radius}}]]
Out[]=
Además, utilizamos ToElementMesh para generar una malla de elementos finitos predeterminada a partir de la geometría que acabamos de crear.
Genera la malla de elementos:
In[]:=
mesh=ToElementMesh[Ω]
Out[]=
ElementMesh[{{0.,0.025},{-0.025,0.025}},{TriangleElement[<492>]}]
Visualiza la malla de elementos finitos:
In[]:=
mesh["Wireframe"]
Out[]=
Para modelar EDP en Wolfram Language, usamos lo que se denominan componentes de EDP, los cuales son bloques de construcción que nos ayudan a especificar las EDP. Estas son funciones que reciben variables y parámetros y devuelven un operador de EDP que luego puede utilizarse con NDSolveValue. Podemos acceder a la lista de todos los componentes de EDP para cualquier campo específico. Para estudiar la evolución de la temperatura dentro del huevo, usaremos para modelar la transferencia de calor a lo largo del tiempo.
La solución que buscamos, la variable dependiente, es la temperatura (kelvin). Para nuestra simetría cilíndrica, tenemos dos variables independientes espaciales: r es la coordenada radial (distancia desde el eje central) y z es la coordenada axial (distancia a lo largo del eje del cilindro). Ambas se expresan en metros. Como la ebullición de un huevo depende del tiempo, también necesitaremos la variable temporal t (segundos).
T
Establece las variables dependientes e independientes del modelo:
In[]:=
vars={T[t,r,z],t,{r,z}};
También necesitamos los parámetros. Para nuestra primera versión simplificada, solo especificaremos la simetría de la región como simétrica respecto al eje, y eso nos dará los términos correctos para la porción de huevo en la que nos estamos enfocando. HeatTransferPDEComponent completará el resto de los parámetros necesarios con valores predeterminados, lo cual está bien por ahora.
Establece los parámetros:
In[]:=
pars=<|"RegionSymmetry"->"Axisymmetric"|>;
A continuación, configuramos el operador EDP. En este caso, es el operador EDP, simplemente el lado izquierdo de la ecuación de calor. Así que cuando escribimos , en realidad solo estamos escribiendo la propia ecuación de calor.
op
op0
Configura el operador de EDP:
In[]:=
op=HeatTransferPDEComponent[vars,pars]
Out[]=
-,0.T[t,r,z]+·{{-1,0},{0,-1}}.T[t,r,z]+[t,r,z]
1
r
∇
{r,z}
∇
{r,z}
∇
{r,z}
(1,0,0)
T
In[]:=
op==0
Out[]=
-,0.T[t,r,z]+·{{-1,0},{0,-1}}.T[t,r,z]+[t,r,z]0
1
r
∇
{r,z}
∇
{r,z}
∇
{r,z}
(1,0,0)
T
Condiciones de frontera
Condiciones de frontera
Las condiciones iniciales y de frontera son partes importantes del modelado de EDP porque contienen información sobre la física subyacente del proceso que se está llevando a cabo. Las condiciones de frontera especifican el comportamiento de la solución en las fronteras. En este caso, una condición de frontera importante es el exterior del huevo, el cual está sometido a la temperatura del agua hirviendo que lo envuelve. La condición inicial es la temperatura inicial del huevo, es decir, si el huevo ha estado refrigerado o almacenado a temperatura ambiente.
Asumiendo que el huevo se encuentra a temperatura ambiente, usaremos 20°C para nuestra condición inicial en el tiempo 0, luego lo convertiremos a la unidad base del SI de kelvin.
Define la temperatura inicial en kelvin:
Establece una condición inicial para la temperatura dentro del huevo:
Es importante recordar que las condiciones de frontera y las condiciones iniciales deben ser consistentes. Uno podría sentirse tentado a simplemente fijar una temperatura de 100°C en el exterior de la región, representando el contacto con el agua hirviendo. Si bien eso no es completamente incorrecto, hay un problema. Según nuestra condición inicial, todo el dominio tiene una temperatura inicial de 20°C, incluso en la frontera externa. Por lo tanto, fijar la frontera exterior a 100°C contradice esto.
Para evitar eso en nuestro caso, usamos una función escalón suave que comienza en la temperatura inicial y rápidamente alcanza la temperatura de ebullición de 100°C. Esto modela efectivamente el acto de colocar el huevo en el agua hirviendo, el cual es un proceso en sí mismo.
Específicamente, definimos la condición de frontera utilizando una función a trozos que equivale a 1 para tiempos mayores que una décima parte (1/10) de un segundo. Para tiempos más cortos, aumenta gradualmente siguiendo una función coseno. Representar gráficamente la función hace que este comportamiento sea más claro. Esto modela cómo la temperatura de frontera aumenta rápidamente, pero con fluidez, durante el primer 1/10 de segundo después de que el huevo es sumergido en agua hirviendo.
Especifica la temperatura de frontera en kelvin:
Especifica el comportamiento temporal de la condición de frontera:
Visualiza el comportamiento temporal de la condición de frontera:
Pero haremos algo diferente que será útil en versiones posteriores de este modelo.
Visualiza el marcador de elemento puntual:
Nuestra visualización de la malla muestra los elementos puntuales y los marcadores de elementos (véase el tutorial Visualización de elementos de malla para más información). Aprovecharemos esto para definir la condición de frontera.
Una ventaja de utilizar la función HeatTemperatureCondition es que considerará los parámetros que hemos definido.
Especifica la condición de frontera en kelvin:
Especifica la condición de simetría:
Observemos que esto evalúa a un valor cero de Neumann. En caso sea necesario un repaso sobre los valores de Neumann, podemos consultar estas fuentes en la documentación:
Un valor cero de Neumann, en términos simples, indica que la derivada de la temperatura, tomada en dirección normal al eje de simetría, es cero. Además, un valor cero de Neumann es el valor predeterminado si no se especifica ninguno. Por lo tanto, omitiremos esto en las siguientes versiones de este modelo, pero es útil tenerlo presente.
Finalmente, definimos qué tan largo será el tiempo de simulación. Como esta es una primera versión sencilla y hemos usado los parámetros predeterminados para nuestra EDP, definimos un tiempo de un segundo, el cual actualizaremos más adelante.
Define el tiempo de simulación:
Para obtener nuestra solución, usamos NDSolveValue.
Calcula la solución y almacénala en una variable:
Examina la solución:
Obtenemos una función de interpolación que representa nuestra solución, la cual luego podemos representar para visualizar la solución.
Llamar a “ValuesOnGrid” da los valores de la función en cada coordenada de la malla, luego podemos extraer los valores mínimo y máximo de la solución.
Para que esto sea más fácil de interpretar, transformemos las temperaturas a grados Celsius, pero los parámetros que ingresan al modelo aún deberán definirse en kelvin. Así que definamos un desplazamiento para convertir más fácilmente entre grados Celsius y kelvin.
Define un desplazamiento:
La representación gráfica parece mostrar que toda la región tiene una temperatura de 100°C en tan solo la mitad del tiempo de simulación (0,5 segundos). Para confirmar eso, vamos a crear una animación de la evolución de la temperatura a lo largo del tiempo.
Para ahorrar tiempo más adelante, vamos a crear una función auxiliar para representar.
Crea una función auxiliar para crear representaciones gráficas de contorno de la temperatura en distintos momentos:
Hemos creado una función de la variable time, la cual nos da la representación gráfica para un tiempo en particular. Luego, podemos aplicar esa función sobre una lista de tiempos.
Define una versión de DensityPlot de la función auxiliar:
Crea varios marcos de representaciones gráficas de contorno:
Rasteriza los fotogramas para hacer que el cuaderno sea más ligero (esto es opcional):
Anima los fotogramas:
La animación demuestra que toda la región comienza en la temperatura inicial y casi instantáneamente se calienta a 100 °C (la temperatura del agua), lo cual no tiene mucho sentido. Pero no esperábamos que esta fuera nuestra solución final. Por ahora, sabemos que no hay errores ni advertencias en nuestra simulación. El propósito de este paso era poner en marcha nuestro flujo de trabajo, y eso es lo que realmente importa en esta etapa del modelo.
Versión 2: Un ejemplo de lo que puede salir mal
Versión 2: Un ejemplo de lo que puede salir mal
Ahora que nuestro flujo de trabajo está establecido, comenzamos esta nueva versión definiendo parámetros más realistas en lugar de los que HeatTransferPDEComponent (la función utilizada para generar la EDP) proporciona de manera predeterminada.
La ecuación de calor incluye tres magnitudes físicas que dependen del tipo de material que estamos modelando: densidad, capacidad calorífica y conductividad térmica:
Usaremos estimaciones de los valores promedio tanto para la clara como para la yema del huevo para establecer los parámetros del material:
Examina los parámetros:
Establece un tiempo de finalización de simulación realista de 10 minutos:
Vuelve a generar las ecuaciones con los nuevos parámetros:
Como hicimos antes, resuelve la EDP:
¡Hasta ahora, todo bien!
Comprobemos los valores mínimo y máximo en la solución en grados Celsius:
Esto es claramente incorrecto. Una temperatura bajo cero no tiene sentido en este caso. Representemos la solución en el momento en que alcanza esa temperatura bajo cero.
Encuentra la posición del valor mínimo en los datos de la solución:
Al llamar a “Coordinates” sobre la solución y tomar la primera parte, obtenemos los pasos de tiempo realizados durante la solución:
Encuentra el paso de tiempo en el cual se almacena el valor mínimo:
En nuestra variable badPosition, la cual es {{18, 386}}, el primer número en el par representa el índice del momento en el que ocurre nuestro valor bajo cero. Podemos extraer el tiempo problemático tomando la posición número dieciocho en los pasos de tiempo:
Ahora podemos visualizar la solución en ese momento exacto.
Visualiza la solución en el paso de tiempo con los valores extremos:
Aquí tenemos claro cómo, al inicio de la simulación, hay muchas oscilaciones cerca de la frontera, y esa es la razón por la cual vemos temperaturas extremas cerca de –2 °C. La representación gráfica 3D muestra sobreimpulsos y subimpulsos.
Magnifica la representación gráfica de la solución y visualiza la malla de elementos finitos subyacente:
Les animo a revisar la documentación de ElementMeshProjection para aprender más sobre cómo visualizar una malla 2D como 3D.
Ahora está claro que los subimpulsos están ocurriendo a pocos elementos de la frontera. ¿Pero, qué podría estar causando estos sobreimpulsos y subimpulsos?
Obtén la longitud mínima de arista de la malla en\b metros:
La distancia entre los elementos es de aproximadamente 1 mm, lo que significa que los primeros elementos cerca de la frontera tienen una longitud de arista de alrededor de 1 mm. Por otro lado, dado que nuestra temperatura inicial es de 20°C y la temperatura de frontera es de 100°C, el cambio de temperatura entre la frontera y el resto de la región es de aproximadamente 80°C.
Intentar resolver ese cambio abrupto de aproximadamente 80 °C en la frontera con elementos de ese tamaño no es suficiente. Esa es probablemente la razón por la cual estamos obteniendo temperaturas muy por debajo de la temperatura inicial, donde no hay disipadores de calor. Por lo tanto, es necesario refinar la malla.
Refinar toda la malla probablemente resolverá nuestro problema, pero el refinamiento no es necesario en el centro del huevo. Refinar toda la malla ahora ralentizará la simulación, así que es mejor refinar la malla solo cerca del borde (la cáscara del huevo).
Crea una función de distancia con signo de toda la región del huevo:
Podemos visualizar la función de distancia con signo y ver cómo disminuye de forma lineal a medida que alcanza la frontera. Este resultado tiene sentido, porque la distancia en la cáscara hacia la cáscara es predeciblemente cero.
Visualiza la función de refinamiento sobre la geometría mallada:
Crea la función de refinamiento de malla:
Luego establecemos la opción MeshRefinementFunction dentro de ToElementMesh a nuestra refinementFunction.
Redefine la malla:
Resuelve la EDP y monitorea el progreso:
Examina el rango de temperaturas de la solución recién encontrada:
¡Genial! Ahora obtenemos un rango de temperaturas que esperaríamos. Por supuesto, habrá un poco de error numérico intrínseco al método. Es decir, el rango no será exactamente {20, 100}, pero esto es prometedor.
Podemos proceder a crear nuestra animación como de costumbre llamando a la función auxiliar que definimos con nuestra nueva solución, rasterizando los fotogramas y luego animándolos.
Crea los fotogramas para la solución:
Rasteriza los fotogramas:
Anima los fotogramas:
Podemos ver que el problema de los sobreimpulsos y subimpulsos ha sido resuelto. Esto demuestra lo importante que es comprobar que nuestras soluciones tengan sentido y cómo podemos modificar la malla según sea necesario.
En este punto tenemos una buena idea de cómo se distribuye la temperatura durante la ebullición del huevo. Calculemos la temperatura en el centro del huevo después de seis minutos de cocción.
El resultado es 41,6°C. Este valor probablemente no representa la temperatura real de la yema de un huevo real, ya que actualmente estamos haciendo demasiadas suposiciones. Sin embargo, es una buena referencia por ahora.
En esta versión, utilizamos un modelo básico que no consideró la existencia de dos regiones distintas, la yema y la clara del huevo. Abordaremos eso en la siguiente versión.
Versión 3: Representar múltiples regiones de materiales
Versión 3: Representar múltiples regiones de materiales
Crea una geometría de múltiples materiales:
Ahora definimos los marcadores de las regiones de materiales para diferenciar los parámetros de las dos regiones más adelante. Esto hará que nuestro código sea más claro, como veremos.
Especifica los marcadores de la región de materiales:
Usamos la opción “RegionMarker” para distinguir las dos regiones asignando un marcador diferente a cada subregión. La opción se proporciona como una lista de listas, donde cada lista interior contiene un punto dentro de la subregión y su marcador de región asociado.
Crea una malla con marcadores de materiales:
Podemos visualizarlo con distintos colores especificando “MeshElementStyle” en las opciones de “Wireframe”.
Visualiza la malla de materiales múltiples:
Visualiza los marcadores de elementos puntuales:
Dado que cambiamos la región, los marcadores de elementos para la frontera también han cambiado. Por lo tanto, podemos redefinir la condición de frontera para los marcadores 2 y 5.
Cabe tener en cuenta que estos son marcadores de elementos para la frontera. Son diferentes de los marcadores de región que definimos anteriormente. No hay que confundirlos.
Vuelve a generar la condición de frontera:
Después de visualizar los marcadores de elementos puntuales, redefinimos la malla especificando la función de refinamiento de malla como antes.
Crea una malla con marcadores de materiales y un refinamiento de malla:
Visualiza la malla refinada de múltiples materiales:
¡Buen resultado! Pero antes de resolver el problema, vamos a redefinir los parámetros para cada material, utilizando estimaciones de los valores promedio de densidad de masa, conductividad térmica y capacidad calorífica para la yema y la clara del huevo según los hallazgos en “Density, Heat Capacity and Thermal Conductivity of Liquid Egg Products”.
Ahora podemos volver a generar y resolver la EDP como hicimos antes.
Vuelve a generar la ecuación diferencial parcial:
Resuelve la EDP:
Examina el rango de temperatura de la nueva solución:
El rango de temperaturas resultante es razonable. Visualicemos la solución.
Crea los fotogramas para la solución:
Rasteriza los fotogramas:
Anima los fotogramas:
Podemos ver un calentamiento uniforme del huevo, similar a nuestra última versión con solo una región. Sin embargo, esta versión es más precisa porque tenemos un mejor modelo de la estructura real del huevo.
En esta solución, el resultado de temperatura de 38°C nuevamente parece demasiado bajo para el tiempo determinado. De hecho, esta temperatura es aún menor que el resultado anterior de aproximadamente 42°C.
Necesitamos una manera de saber cuáles partes del huevo están cocidas después de un tiempo determinado.
Versión 4: Refinar aún más el modelo
Versión 4: Refinar aún más el modelo
En esta versión, refinaremos los datos utilizados para las cantidades físicas involucradas en el modelo. También predeciremos si el huevo está cocido comparando los resultados con las temperaturas de desnaturalización de la yema y la clara (es decir, las temperaturas en las que las proteínas del huevo comienzan a desplegarse y solidificarse).
Para refinar las cantidades físicas (densidad, capacidad calorífica y conductividad térmica), nos basaremos en los datos proporcionados por estos dos estudios:
En la versión anterior, teníamos buenas estimaciones de las cantidades físicas tanto para la yema como para la clara del huevo. Pero en realidad, esas cantidades pueden cambiar con el tiempo a medida que el huevo se calienta. Un modelo mejor es aquel que considera cómo varían estas cantidades con la temperatura.
Utilizando datos de los estudios mencionados anteriormente, vamos a establecer pares de temperaturas y la cantidad física correspondiente (en unidades básicas del SI). Nuestro objetivo es modelar cada cantidad física (densidad, conductividad térmica, capacidad calorífica) como una función de temperatura.
Comencemos con la densidad. Observemos que hay una definición de datos de densidad tanto para la yema como para la clara del huevo.
Comencemos con la densidad. Observemos que hay una definición de datos de densidad tanto para la yema como para la clara del huevo.
Establece los datos de medición para la densidad de masa de la yema y la clara del huevo:
La opción “ExtrapolationHandler” se utiliza para manejar puntos fuera del rango de los datos disponibles. Nuestros datos no son perfectos y no abarcan todo el rango de temperaturas. Dado que propiedades como la densidad varían casi linealmente, extrapolar a partir de los datos existentes proporciona una aproximación razonablemente precisa.
Visualiza los datos medidos y las funciones interpoladas:
Podemos observar cómo la densidad disminuye a medida que la temperatura aumenta. Aunque no contamos con datos de temperatura más allá de 335 kelvin, sí tenemos una extrapolación razonable a partir de los datos.
Ahora repetimos el mismo proceso para la conductividad.
Establece los datos de medición para la conductividad térmica de la yema y la clara del huevo:
Crea una InterpolatingFunction para los datos de conductividad térmica:
Visualiza los datos medidos y las funciones interpoladas:
Podemos observar cómo la conductividad aumenta ligeramente con la temperatura y, nuevamente, tenemos una extrapolación razonable de los datos.
Para la capacidad calorífica específica, tenemos un enfoque ligeramente diferente. Contamos con menos puntos de datos, y la calidad de los puntos no es tan buena como la de las otras dos cantidades. El enfoque óptimo es realizar un ajuste lineal de los datos, lo cual nos proporcionará una función lineal que se ajusta mejor a los datos.
Establece los datos de medición para la capacidad calorífica de la yema y la clara del huevo:
Para explorar con más detalle cómo funciona la función, podemos consultar la documentación de LinearModelFit.
Visualiza los datos medidos y la función lineal que los ajusta:
La representación gráfica muestra una aproximación razonable de los datos y una buena extrapolación a temperaturas más altas.
Ahora que tenemos las funciones para las cantidades físicas, solo necesitamos especificarlas como funciones a trozos, como hicimos antes:
Vuelve a generar la ecuación diferencial parcial:
Una consideración importante: la densidad de masa, la conductividad térmica y la capacidad calorífica ahora son funciones de temperatura T. Al mismo tiempo, T es la variable dependiente para la cual se busca una solución. Esta dependencia mutua significa que los coeficientes en la ecuación varían con la propia solución, haciendo que la EDP sea no lineal. Los modelos no lineales suelen requerir más tiempo y esfuerzo computacional para resolverse, es por eso que a menudo es una buena idea comenzar con una malla poco refinada mientras se configura todo. Una vez que se obtiene una solución razonable, se puede cambiar a una malla refinada para obtener mayor precisión. Sin embargo, en este caso, vamos a seguir adelante y utilizar la malla refinada.
Ahora resolvemos la EDP, monitoreamos el progreso y medimos el tiempo computacional y la memoria que requiere (alrededor de tres minutos en una laptop normal).
Resuelve la EDP:
Este aumento en el tiempo de cálculo se espera para la mayoría de modelos no lineales.
Examina el rango de temperaturas de la nueva solución:
Antes de visualizar nuestra solución, definiremos las temperaturas de desnaturalización de la yema y la clara del huevo. Esto nos dará una buena idea de si las dos regiones del huevo se cocinan en un momento determinado. Estas temperaturas provienen del estudio Journal of Food Measurement and Characterization citado anteriormente.
Establece la temperatura de desnaturalización para la clara del huevo:
Establece la temperatura de desnaturalización para la yema del huevo:
Podemos visualizar las temperaturas de desnaturalización junto con la animación de nuestra solución. La mejor manera de hacerlo es mediante una representación gráfica de contorno con una línea de contorno que indique el punto en la región con la temperatura de desnaturalización.
Prefiero la representación gráfica de densidad, así que aquí definimos una nueva función llamada TemperatureDenatureDensityPlot, que llama a la función auxiliar previamente definida TemperatureDensityPlot. Utilizamos Show para mostrar la representación gráfica como antes, pero con los contornos para las temperaturas de desnaturalización de la yema y la clara del huevo. Los contornos se representan mediante un ContourPlot adicional.
Crea una función auxiliar para generar una representación gráfica de densidad de la distribución de temperaturas y visualizar las temperaturas de desnaturalización:
Crea los fotogramas para la solución:
Rasteriza los fotogramas:
Anima los fotogramas:
La temperatura de desnaturalización de la clara del huevo se muestra con la línea discontinua verde, y la temperatura de desnaturalización de la yema se muestra con la línea discontinua magenta. La representación gráfica muestra la difusión de calor dentro del huevo, tal como esperaríamos.
Al llegar a los seis minutos, podemos ver que toda la clara del huevo ha superado su temperatura de desnaturalización. Este es un resultado prometedor para nuestro modelo.
Sin embargo, si observamos el punto de los 10 minutos, toda la región supera la temperatura de desnaturalización de la clara del huevo, mientras que parte de la yema no ha superado la temperatura de desnaturalización de la yema, lo que indica que la yema no está suficientemente cocida, incluso después de 10 minutos.
Por lo general, los huevos duros se cocinan durante 10–12 minutos, de manera que 10 minutos deberían dar como resultado una yema completamente cuajada. Por lo tanto, nuestro modelo aún no está completo, ya que indica que después de 10 minutos la yema no está completamente cocida.
Examina la temperatura de desnaturalización de la yema:
En las versiones 2 y 3 del modelo obtuvimos temperaturas de 38°C y 42°C, respectivamente. Ahora en la versión 4, obtenemos alrededor de 40°C para la temperatura en el centro del huevo a los seis minutos. En comparación con la temperatura de desnaturalización de la yema, esto todavía parece demasiado bajo. Necesitamos mejorar eso en la próxima versión.
Versión 5: Construir una geometría de huevo realista
Versión 5: Construir una geometría de huevo realista
Cuando el modelo no nos da la respuesta que esperamos, puede ser una buena idea refinarlo aún más. Una manera de hacer esto es revisar las suposiciones que hemos hecho. Una suposición importante es que el huevo tiene una forma circular, lo cual, por supuesto, no es cierto en la realidad. En esta versión, crearemos una geometría más realista para el huevo.
Todavía podemos suponer que la geometría de la yema del huevo está bien modelada por un círculo. Pero podemos aproximar la geometría de la cáscara del huevo de una manera más realista.
Para ello, utilizaremos una ecuación matemática que aproxima la geometría de la cáscara del huevo, según esta referencia.
Crea una función auxiliar para calcular las coordenadas de la forma de una geometría de huevo:
Manipula los parámetros para ver distintas formas:
Examina el valor del radio:
Llamaremos a la nueva función eggShapePoints para un huevo que mide 5 cm de alto y 4 cm de ancho.
Crea coordenadas para la geometría del huevo especificando los parámetros:
Crea un spline:
Luego podemos usar RegionUnion, uniendo un semicírculo con nuestra curva de cáscara de huevo, para crear el esqueleto de nuestra región. Es lo mismo que hicimos antes, pero ahora con la curva spline para la cáscara del huevo.
Crea una geometría de huevo con una subregión:
A continuación, creamos la malla con los marcadores de región, como hicimos antes.
Crea una malla con marcadores de material:
Visualiza el marcador de elemento puntual:
Como podemos ver, los marcadores para el exterior del huevo siguen siendo 2 y 5, por lo que no necesitamos redefinir la condición de frontera.
Examina la condición de frontera:
Examina la refinementFunction:
Ya hemos avanzado bastante, pero tenemos un pequeño problema. Para la versión anterior, creamos una función de refinamiento basada en que la región tuviera forma circular. Ahora necesitamos crear una nueva función de refinamiento para nuestra nueva región:
Podemos refinar los elementos según su distancia radial a la cáscara, la cual se muestra como una línea verde en la imagen. El punto rojo representa un elemento y tiene una distancia radial al eje de simetría (la línea azul) y una distancia radial a la cáscara.
Queremos definir una función de refinamiento basada en la distancia en verde. Cuanto mayor sea la distancia a la cáscara, menor será el refinamiento; cuanto menor sea la distancia a la cáscara, mayor será el refinamiento. Además, para obtener la distancia de la línea verde, restamos la distancia de la línea azul de la distancia desde el eje de simetría hasta la cáscara del huevo (mostrada en magenta):
Primero, definimos una función que devuelve el valor de la coordenada cilíndrica r para un z dado en la curva de la cáscara del huevo.
Realiza una interpolación de las coordenadas de la cáscara:
Simplemente invertimos el orden de los puntos en las coordenadas de la cáscara, reemplazando {r, z} por {z, r}, y luego realizando una interpolación a partir de eso. En este caso, rShell es una función de interpolación que toma z y devuelve r.
Representa la función que da la función rShell:
La representación gráfica de esta función es lo que esperaríamos: la coordenada r para la cáscara del huevo como una función de z.
Entonces, lo único que nos falta hacer es calcular la distancia desde el eje hasta la cáscara menos el valor absoluto de la coordenada r para cada punto. Esto nos dará la distancia desde cada punto hasta la cáscara (mostrada en verde):
Define una función para la distancia radial hasta la cáscara y re\bpreséntala:
La representación gráfica muestra que la distancia desde cada punto hasta la cáscara disminuye casi linealmente, como se esperaría.
Representa la distancia a la cáscara al cubo:
Al representar la distancia al cubo, los valores disminuyen más rápidamente a medida que la distancia a la cáscara se hace más pequeña.
Tengamos en cuenta que encontrar el comportamiento correcto para la función de refinamiento es un proceso de prueba y error.
Define la función de refinamiento:
Ahora definimos la refinementFunction de manera que un elemento se refina si su área es mayor que la distancia a la cáscara al cubo, con un cierto desplazamiento para evitar refinar en exceso. En otras palabras, el tamaño de los elementos es proporcional a la distancia a la cáscara al cubo. Cuanto más cerca de la cáscara, más pequeños son los elementos.
Visualiza la malla con múltiples materiales:
Como podemos ver, los elementos cerca del centro del huevo no están refinados en absoluto, pero obtenemos un refinamiento muy fino cerca de la cáscara del huevo.
Podemos proceder a resolver la EDP como antes, midiendo el tiempo y la memoria utilizados. Este cálculo de un modelo no lineal con esta malla toma unos seis minutos en terminar (¡Igual que los huevos que me gusta comer!). Hay que tener en cuenta el tiempo de cálculo al desarrollar nuestros propios modelos. Por eso Monitor es útil, y por eso utilizar una malla no refinada al principio es una buena idea.
Resuelve la EDP, supervisa el progreso y mide el tiempo computacional y la memoria que utiliza:
Examina el rango de temperaturas de la nueva solución encontrada:
Nuevamente, obtenemos un rango razonable de temperaturas, por lo que podemos continuar con la animación.
Crea los fotogramas para la solución:
Rasteriza los fotogramas:
Anima los fotogramas:
Dos puntos importantes: Primero, a los seis minutos, la yema del huevo todavía no está cocida, lo cual es algo que esperábamos. Segundo, a los 10 minutos, toda la región ha superado las temperaturas de desnaturalización tanto de la clara como de la yema, así que podemos asumir que el huevo está completamente cocido en este momento. El modelo ahora refleja un marco temporal realista para cocer el huevo. ¡Genial!
A los seis minutos, tenemos una temperatura mucho más realista de casi 60°C en el centro del huevo, en comparación con nuestra versión anterior del modelo, en la cual el centro sólo alcanzaba aproximadamente 40°C. Podemos concluir que la geometría juega un papel crucial en la dinámica del calentamiento del huevo.
Versión 6: Usar el modelo
Versión 6: Usar el modelo
Ahora que nuestro modelo está produciendo resultados satisfactorios, podemos usarlo para hacer predicciones.
Anteriormente, nuestro huevo fue introducido en agua hirviendo desde la temperatura ambiente. Ahora, modelemos un caso más realista en el que el huevo se saca directamente del refrigerador, en el cual asumiremos que el huevo tiene una temperatura inicial de 8°C. Para modelar esto, debemos modificar nuestras condiciones iniciales y de frontera. En particular, la condición de frontera debe comenzar desde nuestra nueva temperatura inicial y alcanzar rápidamente los 100°C.
Primero, fijamos la temperatura inicial en 8°C y la convertimos a kelvin.
Establece la temperatura inicial del huevo:
A continuación, definimos nuestra nueva condición inicial.
Establece una condición inicial para la temperatura dentro del huevo:
También es necesario modificar la función de condición de frontera, la cual ahora comienza desde la nueva temperatura inicial.
Especifica el comportamiento temporal de la condición de frontera:
Visualiza el comportamiento temporal de la condición de frontera:
Vuelve a generar la condición de frontera:
Luego resolvemos la EDP como antes. Tengamos en cuenta que aquí almacenamos nuestra solución en una nueva variable llamada solutionFridge, para que podamos compararla con nuestra solución anterior.
Resuelve la EDP, supervisa el progreso y mide el tiempo computacional y la memoria que utiliza:
Examina el rango de temperaturas de la nueva solución:
Obtenemos un rango que es razonable para nuestro huevo refrigerado.
Podemos representar la solución de la misma manera que antes.
Crea los marcos para la solución:
Rasteriza los fotogramas:
Anima los fotogramas:
A los seis minutos, la yema del huevo sigue sin estar cocida, igual que en nuestra versión anterior. A los diez minutos, el huevo parece estar cocido por completo. Es difícil ver solo observando la animación si hay diferencias significativas entre el huevo refrigerado y el que está a temperatura ambiente.
Una buena opción es representar la temperatura para la línea que pasa por el centro de la yema hasta la cáscara del huevo para ambas soluciones, el huevo refrigerado y el que está a temperatura ambiente. Una representación gráfica más sencilla podría revelar aspectos más sutiles que son difíciles de ver en la representación gráfica de densidad.
Estamos representando la temperatura para los valores de r que se encuentran sobre esta línea. Necesitamos el valor de r para la frontera derecha. Con nuestra función rShell que definimos anteriormente, podemos obtener el valor de la coordenada r para el valor de z igual a 0.005, que es el centro de la yema del huevo.
Obtén el valor de r para la línea:
Ahora sabemos el valor de r para la frontera derecha de la línea que nos interesa. A continuación, queremos saber cómo aumenta la temperatura para esa línea, específicamente para los valores de r entre 0. y 0.0179. Podemos crear una representación gráfica sencilla, por ejemplo a los seis minutos, para esos valores de r.
Representa la solución a lo largo de la línea radial desde el centro de la yema hasta el exterior del huevo a los seis minutos:
Podemos ver que la temperatura a los seis minutos es menor para el huevo sacado directamente del refrigerador en comparación con el huevo a temperatura ambiente para todos los valores de r. En particular, podemos ver una diferencia de aproximadamente 5°C en el centro del huevo.
Como nos interesa predecir si el huevo está cocido, también necesitamos una manera de visualizar la temperatura de desnaturalización. Una forma de hacerlo es representando una línea vertical que marque el valor de r en el cual el huevo alcanza la temperatura de desnaturalización.
Obtén el valor de r en el que la solución es igual a la temperatura de desnaturalización:
Observamos que la temperatura de desnaturalización para la yema del huevo, tomada del refrigerador, se alcanza a un radio de aproximadamente 10 mm (1 cm) desde el centro. Podemos representar esto con una línea en nuestra representación gráfica.
Representa la solución a lo largo de la línea radial desde el centro de la yema hasta el exterior del huevo:
Además de la yema del huevo, también necesitamos la temperatura de desnaturalización de la clara del huevo tanto para el huevo a temperatura ambiente como para el huevo refrigerado. En lugar de hacer esto manualmente, podemos definir una función auxiliar.
Esta función toma la solución y el valor de la temperatura de desnaturalización que nos interesa, y utiliza FindRoot para determinar el radio, a lo largo de la línea representada, en el cual ocurre la temperatura de desnaturalización. Finalmente, devuelve una línea vertical, que podemos mostrar en la representación gráfica.
Escribe una función auxiliar para crear una línea de una temperatura de desnaturalización de una solución:
A continuación, creamos una función para la propia representación gráfica, en la cual utilizamos Show para mostrar la representación y las líneas correspondientes a las temperaturas de desnaturalización, llamando a nuestra función auxiliar denatureLine y además una línea que indica el radio de la yema del huevo.
Crea una función auxiliar para representar las posiciones de desnaturalización para las dos soluciones en diversos momentos:
Si observamos la representación gráfica a los seis minutos, podemos notar dos cosas. Primero, está claro que la desnaturalización de la clara del huevo ya ha alcanzado bien el centro del huevo. Segundo, la temperatura de desnaturalización de la yema ha llegado mucho más cerca del centro en el caso del huevo a temperatura ambiente en comparación con el huevo refrigerado.
¿Qué significa esto? Para el huevo a temperatura ambiente, la yema apenas comienza a cocinarse. Pero para el huevo refrigerado, la yema sigue líquida: la temperatura de desnaturalización apenas ha alcanzado el borde de la yema.
Por lo tanto, si queremos una yema líquida, tenemos dos opciones:
1
.Usar un huevo refrigerado y sacarlo del agua hirviendo justo a los seis minutos
2
.Usar un huevo a temperatura ambiente y sacarlo del agua unos segundos antes
Si creamos la misma representación, pero para ocho minutos, podemos ver algo interesante. Alrededor de los ocho minutos, el huevo a temperatura ambiente completo ha superado la temperatura de desnaturalización de la yema, lo que significa que también ha pasado la temperatura de desnaturalización de la clara. Pero todavía hay algunas partes de la yema del huevo refrigerado que no han alcanzado esa temperatura aún.
¿Qué significa esto? Si queremos una yema completamente cocida y estamos utilizando un huevo directamente del refrigerador, dejémoslo en el agua hirviendo algunos segundos después de los ocho minutos. Si usamos un huevo a temperatura ambiente, y el hambre no nos permite esperar, ocho minutos podrían ser justo el tiempo suficiente.
Todo se reduce a esto
Todo se reduce a esto
Comenzamos creando una primera versión sencilla, solo algo para poner en marcha nuestro flujo de trabajo. Si pasamos directamente a programar un modelo complejo, es mucho más probable que cometamos errores, y lo que es peor, esos errores pueden ser difíciles de localizar. Si los resultados no se ven correctos, no siempre queda claro si hay un problema con el propio modelo o si simplemente cometimos un error en el código.
Al comenzar de manera sencilla y agregar complejidad gradualmente, paso a paso, reducimos la posibilidad de introducir errores. Además, obtenemos una comprensión mucho mejor de cómo se comporta nuestro modelo.
Como vimos, el salto abrupto de temperatura entre el exterior y el interior del huevo estaba causando problemas numéricos en una de las primeras versiones de nuestro modelo. Para solucionarlo, refinamos la malla justo en la frontera utilizando una función de refinamiento. Este método es mucho mejor que refinar toda la malla, ya que eso ralentizaría considerablemente nuestro cálculo.
Finalmente, utilizamos datos experimentales de dos maneras. Primero, usamos datos experimentales para construir nuestro modelo estableciendo los parámetros en la ecuación de calor. Segundo, usamos los datos para comparar nuestros resultados con tiempos de cocción reales para huevos reales.
Podemos concluir algunas cosas:
◼
Crear una versión sencilla primero es una buena idea.
◼
Aumentar la complejidad del modelo paso a paso puede facilitar las cosas.
◼
Las transiciones bruscas o discontinuidades en las variables de la solución pueden causar inestabilidad numérica o pérdida de precisión. Hay que usar el refinamiento local de malla o suavizado en esas regiones.
◼
Tener una manera de comparar nuestros resultados con datos del mundo real es útil.
Finalmente, si te ha parecido interesante y deseas implementar tus propios modelos de EDP, puedes consultar este Resumen de PDEModels en la documentación.