Mathematica Asked on September 27, 2021
I am trying to solve the equations below to find the breakthrough curve in an adsorption process:
∂C/∂t+u* ∂C/∂z+ρ/ϵ * ∂q/∂t= 0
∂q/∂t= -Ks * (q-(qm* b*C)/(1+ b*C))
the IC and BCs are:
q(t=0,z)=0
C(t,z=0)=C0
C(t=0,z) = 0
The parameters are given as:
eps = 0.373
ueps = 6.66
C0 = 892
Ks = 0.0872
rho = 390.04
qm = 7.0136
b = 0.05313
I wrote the equation in Mathematica as below:
s=NDSolve[{∂_t C[t,z]==-ueps*∂_z C[t,z]+(rho⁄eps)*Ks*(q[t,z]-(qm*b*(C[t,z])⁄((1+b*C[t,z])))),∂_t q[t,z]==-Ks*(q[t,z]-(qm*b*(C[t,z])⁄((1+b*C[t,z])))),DirichletCondition[{C[t,0]==C0},True],C[0,z]==0,q[0,z]==0},{C,q},{t,0,60},{z,0,22}]
After evaluating the notebook, I receive this error:
NDSolve: There are fewer dependent variables, {q[t,z]}, than equations, so the system is overdetermined.
I have been trying to fix this problem by rearranging the equations, but no success yet.
I appreciate it if you could please help me solve this issue.
Thanks
In my answer, I adapted the Heat Transfer Tutorial to handle Mass Transport. There is a new and fairly extensive Mass Transport Tutorial that you can use directly. In my answer 227821, I extended the Mass Transport functions in the tutorial to include axisymmetric and optional porosity.
To use the FEM method it is good to cast your equations into coefficient form as shown FEM Tutorial.
$$frac{{{partial ^2}}}{{partial {t^2}}}u + dfrac{partial }{{partial t}}u + nabla cdotleft( { - cnabla u - alpha u + gamma } right) + beta cdotnabla u + au - f = 0$$
The benefits of coefficient form include:
For advective-diffusive problems with and without source terms, the Heat transfer tutorial is a good place to start to learn how to set up these types of problems. It shows how to properly setup the PDE operators in coefficient form. The TimeHeatTransferModel
function in the Heat Transfer Tutorial can help guide you on how to setup the problem.
The following shows how one can setup your coupled system of interphase transport of the fluid and solid using the TimeHeatTransferModel
:
(* From Vitaliy Kaurov for nice display of operators *)
pdConv[f_] :=
TraditionalForm[
f /. Derivative[inds__][g_][vars__] :>
Apply[Defer[D[g[vars], ##]] &,
Transpose[{{vars}, {inds}}] /. {{var_, 0} :>
Sequence[], {var_, 1} :> {var}}]]
(*PDEModels/tutorial/HeatTransfer/HeatTransferVerificationTests#
463435833*)
ClearAll[HeatTransferModel]
HeatTransferModel[T_, X_List, k_, ρ_, Cp_, Velocity_, Source_] :=
Module[{V, Q, a = k},
V = If[Velocity === "NoFlow",
0, ρ*Cp*Velocity.Inactive[Grad][T, X]];
Q = If[Source === "NoSource", 0, Source];
If[ FreeQ[a, _?VectorQ], a = a*IdentityMatrix[Length[X]]];
If[ VectorQ[a], a = DiagonalMatrix[a]];
(* Note the - sign in the operator *)
a = PiecewiseExpand[Piecewise[{{-a, True}}]];
Inactive[Div][a.Inactive[Grad][T, X], X] + V - Q]
TimeHeatTransferModel[T_, TimeVar_, X_List, k_, ρ_, Cp_,
Velocity_, Source_] := ρ*Cp*D[T, {TimeVar, 1}] +
HeatTransferModel[T, X, k, ρ, Cp, Velocity, Source]
(* Create Parametric PDE Operators for Fluid and Solid *)
(* Include Small Diffusive Term to Fluid Otherwise MMA Might Complain
about Being Convection Dominated *)
parmfop =
TimeHeatTransferModel[c[t, x], t, {x}, {d}, 1,
1, {u}, -(ρ/ϵ) Q];
parmsop =
TimeHeatTransferModel[q[t, x], t, {x}, {0}, 1, 1, "NoFlow", Q];
parmfop // pdConv
parmsop // pdConv
Slight rearrangement shows the operators follow coefficient form:
$$begin{matrix} mfrac{{{partial ^2}}}{{partial {t^2}}}u & + dfrac{partial }{{partial t}}u & + nabla cdotleft( { - cnabla u - alpha u + gamma } right) u & + beta cdotnabla u & + au & - f & =0 & (1) & & & & & & & + frac{{partial c(t,x)}}{{partial t}} & + {nabla _{left{ x right}}}cdotleft( {left( {begin{array}{*{20}{c}} { - d} end{array}} right).{nabla _{left{ x right}}}cleft( {t,x} right)} right) & + left{ u right}.{nabla _{left{ x right}}}cleft( {t,x} right) & & + frac{{rho Q}}{varepsilon } & =0 & (2) & & & & & & & + frac{{partial q(t,x)}}{{partial t}} & & & & - Q & =0 & (3) end{matrix}$$
The following workflow uses the PDE operators defined above and produces an annotated plots that can be scrolled frame-by-frame with manipulate.
(* Define Parameters *)
eps = 0.373;
ueps = 6.66;
c0 = 892;
Ks = 0.0872;
rho = 390.04;
qm = 7.0136;
b = 0.05313;
tend = 60;
xend = 22;
Qsource = -Ks*(q[t, x] - (qm*b*c[t, x])/(1 + b*c[t, x]));
timeinc = 0.25; (* Output times *)
(* Critical Breakthrough Fraction *)
btfrac = 0.05;
(* Use CombinePlots For Secondary Axis *)
cp = ResourceFunction["CombinePlots", "Function"];
(* Setup PDE System *)
pdef = (parmfop == 0) /. {ϵ -> eps, u -> ueps, ρ -> rho,
d -> 1, Q -> Qsource};
pdes = (parmsop == 0) /. {Q -> Qsource};
dc = DirichletCondition[c[t, x] == c0 (1 - Exp[-40 t]), x == 0];
icf = c[0, x] == 0;
ics = q[0, x] == 0;
(* Solve PDE *)
{cifn, qifn} =
NDSolveValue[{pdef, pdes, dc, icf, ics}, {c, q}, {t, 0, tend}, {x,
0, xend},
Method -> {"MethodOfLines", "TemporalVariable" -> t,
"SpatialDiscretization" -> {"FiniteElement",
"MeshOptions" -> {"MaxCellMeasure" -> 0.5}}}];
(* Plot Solutions *)
(* Define Plot Function Using Combine Plots *)
bfn = Function[{t},
If[cifn[t, xend] >= btfrac c0, xend,
x /. FindRoot[cifn[t + 0.01, x] - btfrac c0, {x, 0, xend},
Method -> "Brent"]]];
bttemp = With[{xbt = #},
If[xbt == xend, "Sat",
StringTemplate["x=``"][ToString@PaddedForm[xbt, {4, 2}]]]] &;
pltfn = Function[{t}, cp[
With[{xbt = bfn[t]},
Plot[Callout[cifn[t, x], bttemp[xbt], xbt, RoundingRadius -> 5,
Appearance -> "SlantedLabel"], {x, 0, xend},
PlotRange -> {{-2, xend + 1}, {-10, 1.1 c0}}, Frame -> True,
FrameLabel -> {"x", "c"},
PlotLabel ->
Style[StringTemplate[
"Fluid and Solid Concentrations @ time=``"][
ToString@PaddedForm[t, {4, 2}]], 12],
Epilog -> {Green, Thick, Dashed,
Line[{{xbt, -10}, {xbt, 1.1 c0}}]}]],
Plot[qifn[t, x], {x, 0, xend}, PlotPoints -> 100,
PlotRange -> {0, 7},
Frame -> True, FrameStyle -> Red, PlotStyle -> Red,
FrameLabel -> {"x", "q"}],
"AxesSides" -> "TwoY"
], Listable];
(* Create Image List and Manipulate *)
imgs = Rasterize[#, ImageSize -> 340] & /@
pltfn[Range[0, tend, timeinc]];
Manipulate[imgs[[i]], {i, 1, tend/timeinc, 1},
ControlPlacement -> Top]
I would cast the problem using the following workflow:
(* Define Parameters *)
eps = 0.373;
ueps = 6.66;
c0 = 892;
Ks = 0.0872;
rho = 390.04;
qm = 7.0136;
b = 0.05313;
tend = 60;
xend = 22;
Qsource = -Ks*(q[t, x] - (qm*b*c[t, x])/(1 + b*c[t, x]));
(* Use CombinePlots For Secondary Axis *)
cp = ResourceFunction["CombinePlots"];
(* Define Parametric PDE operators *)
(* Include Small Diffusive Term to Fluid Otherwise MMA Might Complain
about Being Convection Dominated *)
parmfop =
D[c[t, x], t] + D[-d D[c[t, x], x], x] + u D[c[t, x], x] + (
Q ρ)/ϵ;
parmsop = D[q[t, x], t] - Q;
(* Setup PDE System *)
pdef = (parmfop == 0) /. {ϵ -> eps, u -> ueps, ρ -> rho,
d -> 1, Q -> Qsource};
pdes = (parmsop == 0) /. {Q -> Qsource};
dc = DirichletCondition[c[t, x] == c0 (1 - Exp[-40 t]), x == 0];
icf = c[0, x] == 0;
ics = q[0, x] == 0;
(* Solve PDE *)
{cifn, qifn} =
NDSolveValue[{pdef, pdes, dc, icf, ics}, {c, q}, {t, 0, tend}, {x,
0, xend},
Method -> {"MethodOfLines", "TemporalVariable" -> t,
"SpatialDiscretization" -> {"FiniteElement",
"MeshOptions" -> {"MaxCellMeasure" -> 0.5}}}];
(* Plot Solutions *)
(* Define Plot Function Using Combine Plots *)
pltfn = Function[{t}, cp[
Plot[cifn[t, x], {x, 0, xend}, PlotRange -> {0, 1.1 c0},
Frame -> True, FrameLabel -> {"x", "c"}],
Plot[qifn[t, x], {x, 0, xend}, PlotPoints -> 100,
PlotRange -> {0, 7},
Frame -> True, FrameStyle -> Red, PlotStyle -> Red,
FrameLabel -> {"x", "q"}],
"AxesSides" -> "TwoY"
], Listable];
(* Create Image List and Animate *)
imgs = Rasterize /@ pltfn[Range[0, tend, 0.25]];
ListAnimate[imgs, ControlPlacement -> Top]
Correct answer by Tim Laska on September 27, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP