In this exercise you will build an implicit solver for unsteady convection-dispersion-reaction equations. A one-component unsteady convection-reaction equation with constant coefficients has the form
The solution method will be the method-of-lines where the spatial dependence is discretized first. After discretization you will get a set of ODE’s. Here the unknowns in the system are represented by a column vector. Differential operators become matrices. After spatial discretization we get:
In this equation conventions are used to write (column) vectors as bold roman lowercase symbols. For example, denotes the concentration vector. A component of this column vector corresponds to the concentration in spatial cell . The matrix is the discretized divergence operator, and the gradient matrix. For the discretized gradient operator, inhomogeneous boundary conditions, give rise to vector with non zero entries only near the boundaries. This vector is indicated by . The convective term is also represented by a matrix-vector multiplication () plus a vector ().
In the Python codes we will for example use for the divergence matrix. In SciPy the @ operator is used to indicate matrix multiplication.
For time-discretization we will use
implicit Euler. It looks schematically, in matrix and Python notation, like:
Questions:
Perform the spatial discretization by constructing the sparse matrices for the dispersion and convective terms. Assume a general boundary condition at the inlet,
and a Neumann boundary condition at the outlet
Make use of the pymrm functions construct_grad, construct_conv, and
construct_div.
Perform the time discretization for the convection-dispersion by means of the implicit Euler scheme, and formulate the problem, without reaction, as a root-seeking problem: for each time step.
Provide an Python implementation, that consists of a time-loop, where for each timestep the newton method from the pymrm package is applied to solve the root-seeking problem.
Test your code for only dispersion, only convection, combined etc. Play around with parameters (numerical and physical ones).
Include a first order reaction term. Compare results to the analytical solution (in a semi-infinite domain) for steady state.
Adapt the code for general non-linear kinetics. Make use of the function numjac to compute the Jacobian of such a reaction term.
Verify your code by implementing a reaction kinetics .
Note that for power-law kinetics with values of the derivative of the reaction rate diverges when . This gives issues for numerical solutions with the Newton-Raphson method, which depends on linearized equations. In general, fractional powers are cumbersome, because, within iterations, negative concentrations might occur. Fractional powers of negative numbers are ill defined (i.e.\ give rise to imaginary numbers).
Power-law behavior at small concentrations is also physically unrealistic. A recommended regularization is making the kinetics linear, when concentrations become of the order of a user-supplied small concentration :