Trato un ejemplo de juguete para entender mi punto de vista. En la realidad tengo que lidiar con un modelo mucho más complejo.
Consideremos un problema de valor límite unidimensional utilizando el solucionador bvp5c en Matlab. Dos líquidos entran por puntos diferentes, se mueven en direcciones opuestas y reaccionan entre sí. El líquido 1 entra por $x = 0$ y se mueve en dirección positiva. El líquido 2 entra en $x = 1$ y se mueve en sentido negativo. Nos interesa la distribución de equilibrio de las dos concentraciones sobre el dominio $[0,1]$ .
Sea $c_1(x)$ sea la concentración del líquido 1 en el punto $x$ y lo mismo para el líquido dos. Las ecuaciones diferenciales que hay que resolver son las siguientes
\begin{align} \frac{dc_1(x)}{dx} &= -(c_1(x) + c_2(x)), \\ \frac{dc_2(x)}{dx} &= K c_1(x) c_2(x), \end{align}
con $K$ una constante que podemos elegir. Obsérvese que la $c_1(x)$ baja por aumentando $x$ et $c_2(x)$ baja por disminuyendo $x$ que es exactamente lo que esperábamos. Los dos valores límite son $c_1(0) = 10$ et $c_2(1) = 6$ .
En Matlab, esto se modela como un problema de valor límite con dos límites y dos componentes. Resolviendo este problema para $K = 1$ obtenemos una bonita solución que se muestra en la siguiente figura.
Sin embargo, al aumentar $K$ digamos, $K = 10^5$ nos encontramos con una imprecisión numérica, véase esta figura. También recibo un mensaje de advertencia de Matlab, ver la parte inferior de este post.
La concentración $c_2(x)$ cae por debajo de cero, mientras que eso no debería ser posible según la segunda ecuación diferencial.
Mi intuición es que esto ocurre porque Matlab toma tamaños discretos de $dx$ y calcula la derivada en un punto (que es grande) y actualiza la solución, haciendo que la concentración sea negativa. Se podría combatir este fenómeno aumentando el tamaño máximo de malla permitido, pero no es una solución que se pueda incorporar a mi modelo real debido a los problemas de tiempo de cálculo y de memoria.
Cómo asegurarse de que ambas concentraciones no negativo ?
Código Matlab
El script que ejecuta el solucionador bvp5c
x = linspace(0,1,100); % the mesh
yinit = [ 5 0 ]; % an initial guess for the solution for both liquids
K = 1; % the factor K in the second differential equation
solinit = bvpinit(x,yinit); % setting the mesh and the initial guess
% Calling the bvp solver. First argument are the ODEs, the second argument
% are the boundary conditions at x = 0 (for liquid 1) and at x = 1 (for
% liquid 2), the last argument specifies the mesh and initial guess
sol = bvp5c(@(x,c)Concentrations(x,c,K),@(ca,cb)BoundaryCond(ca,cb),solinit);
La función con las ODE. La dependencia de $x$ está implícito en la entrada de la función.
function dcdx = Concentrations(x,c,K)
dcdx(1) = -(c(1) + c(2)); % differential equation for liquid 1
dcdx(2) = K*c(1)*c(2); % differential equation for liquid 2
La función con valores límite. Cuando hay dos valores límite, Matlab se refiere a ellos como $a$ et $b$ que son $x = 0$ et $x = 1$ respectivamente.
function res = BoundaryCond(ca,cb)
res = [ ca(1)-10; cb(2)-6 ]; % the concentration of liquid 1 at boundary a
is 10 and the concentration of liquid 2 at boundary b is 6.
Mensaje de error para $K = 10^5$
Warning: Unable to meet the tolerance without using more than 5000 mesh points.
The last mesh of 892 points and the solution are available in the output argument.
The maximum error is 536.678, while requested accuracy is 0.001.
> In bvp5c at 339
2 votos
Este problema especial podría resolverse fijando $c_2(x)=\exp(u_2(x))$ . Considere también que con K grande la EDO es rígida, lo que requiere un solucionador para problemas rígidos.
1 votos
Además, el parámetro
x = linspace(0,1,100)
no prescribe el tamaño de paso utilizado en el solucionador ODE, que probablemente se adapte dinámicamente.x
sólo da los puntos de muestra en los que ely
de la solución.0 votos
@LutzL Soy consciente de que es así. Me refería a aumentar realmente la opción 'NMax'. ¿Quieres decir mediante la introducción de una variable diferente $u_2(x)$ que puede tomar cualquier valor en $\mathbb{R}$ ? ¿Qué quiere decir con una EDO "rígida"? ¿Es bvp5c adecuado para problemas "rígidos"?
0 votos
¿Ha probado a ajustar las tolerancias de integración absoluta y relativa mediante
bvpset
en lugar de utilizar los valores por defecto?0 votos
@horchler Sí, pero para mi problema actual esto no es una posibilidad debido al aumento del tiempo de cálculo.
0 votos
Además, ¿no recibió un mensaje de advertencia para el
K = 1e5
(independientemente de la configuración de tolerancias alternativas): "Advertencia: No se puede cumplir la tolerancia sin utilizar más de 5000 puntos de malla. La última malla de 892 puntos y la solución están disponibles en el argumento de salida. El error máximo es 536,678, mientras que la precisión solicitada es 0,001".0 votos
@horchler Sí, me sale exactamente ese mensaje de advertencia. Pero es un problema innato inherente a la derivada muy grande para $c_2(x)$ .
1 votos
Los mensajes de advertencia y los errores deben mencionarse siempre en la pregunta, no dejar que los descubramos nosotros. si ejecutamos su código nosotros mismos. Si puedes convertir esto en un problema de valor inicial y utilizar
ode45
podría utilizarodeset
para especificar el'NonNegative'
opción.0 votos
@horchler Buen comentario, gracias. Lo editaré en el post original.