Numerical library for one-dimensional nonlinear diffusion problems in semi-infinite domains
Project description
Fronts is a Python numerical library for solving one-dimensional transient nonlinear diffusion problems in semi-infinite domains.
Fronts finds solutions to initial-boundary value problems of the form:
General problem
Given a scalar-valued positive function D, scalars Si, Sb and ob, and coordinate unit vector ȓ, find a function S of r and t such that:
Fronts works by transforming the governing nonlinear partial differential equation (PDE) into a more manageable (but still nonlinear) ordinary differential equation (ODE), using a technique known as the Boltzmann transformation, which it then solves with a combination of numerical ODE solvers and specialized logic.
For this class of problems, you will find that Fronts can be easier to use, faster, and more robust than the classical numerical PDE solvers you would otherwise have to use.
In some instances, Fronts can also solve the inverse problem of finding D when S is given. And, if you need something a little different, Fronts gives you easy access to the underlying ODE so that you can use your own solving algorithm or boundary condition (which you are then welcome to contribute to the project!).
Fronts is open source and works great with NumPy and SciPy.
Common problem
If the general problem supported by Fronts looks too complicated, note that in the common case where ȓ is a Cartesian unit vector and the boundary is fixed at r=0, the problem can be reduced to what we call the common problem:
Common problem
Given a scalar-valued positive function D, and scalars Si and Sb, find a function S of r and t such that:
The main solver function solve()
will assume that you want to work with this common problem unless you explicitly provide the optional radial
and ob
parameters.
Uses
Problems supported by Fronts appear in many areas of physics. For instance, if we take S as the water content or saturation and D as the moisture diffusivity, the above PDE translates into what is known as the moisture diffusivity equation, which is a special case of the Richards equation that describes capillary flow in porous media.
Of particular interest to the creators of Fronts is the fact that the common problem supported by Fronts can directly model the configuration known as "lateral flow" in the field of paper-based microfluidics. In fact, the name "Fronts" is a reference to the wetting fronts that appear under these conditions, the study of which motivated the creation of this library.
Other problems of this class appear in the study of diffusion of solutions in polymer matrices as well as diffusion problems in solids (e.g. annealing problems in metallurgy).
As mentioned before, if your problem is supported, you can expect Fronts to be easier to use, faster, and more robust than other tools. Try it out!
Installation
Prerequisites
-
Python. Fronts runs on Python 3.5 and later, as well as on the older Python 2.7. It has been tested on various releases of Python 2.7, 3.5, 3.6, 3.7 and 3.8.
-
pip. Installation of Fronts requires the Python package manager pip to be installed on your system.
Installation
Install Fronts by running the following command:
$ pip install fronts
This will install the most recent version of Fronts available on PyPI.
Optional: Matplotlib
Running the bundled examples requires the visualization library Matplotlib. This library is not installed automatically with Fronts, so if you don't already have it, you may want to install it manually by running:
$ pip install matplotlib
Optionally, the --user
option can be added to the previous commands to install the packages for the current user only, which does not require system administrator privileges.
Documentation and features
The following is a complete list of the functions and classes that Fronts provides, with a short description of each. You will find the full details on each object in the reference documentation.
Solvers and solutions
-
fronts.solve()
— meshless solverMain solver.
solve
solves any instance of the general problem. Returns aSolution
object. -
fronts.solve_from_guess()
— mesh-based solverAlternative solver.
solve_from_guess
works likesolve
but it uses a different procedure that starts from a guess of the solution on an initial mesh. It supports the same problems assolve
. Although usually faster,solve_from_guess
is significantly less robust thansolve
—whether it converges will usually depend heavily on the problem, the initial mesh and the guess of the solution. It also returns aSolution
on success. -
fronts.Solution
,fronts.BaseSolution
— continuous solutionsBaseSolution
objects provide the continuous functionsS
,dS_dr
,dS_dt
andflux
that make up the solution to a problem. The solvers in Fronts return aSolution
—a subclass ofBaseSolution
—as part of their results. If you calledode
and solved the ODE yourself, you can create aBaseSolution
orSolution
by passing the solution to the ODE to the appropiate constructor.Note that in problems of the moisture diffusivity equation, the diffusive flux (which can be obtained by calling
flux
on aBaseSolution
object) gives the velocity of the wetting fluid. In particular, ifS
is taken to mean volumetric water content, it is the Darcy velocity; ifS
is saturation, it is the fluid's true velocity. These velocity fields can be used directly in more complex problems of solute transport. -
fronts.inverse()
— solve the inverse problemInverse solver.
inverse
solves the inverse problem of finding D when S is known. For instance,inverse
can extract D from experimental results. The returned D function can be used in Fronts to solve other problems. Use of this function for inverse problems comes with some limitations.
Boltzmann transformation and ODE
-
fronts.o()
,fronts.do_dr()
,fronts.do_dt()
,fronts.r()
,fronts.t()
,fronts.as_o()
— Boltzmann transformationThese are convenience functions for working with the Boltzmann transformation.
-
fronts.ode()
— access the ODEThe
ode
function transforms the PDE into its corresponding ODE using the Boltzmann transformation.ode
returns fun and jac callables that are directly compatible with SciPy's solvers (i.e., those in thescipy.integrate
module). The solvers in Fronts actually use this function internally. You may call this function if you want to solve the ODE yourself instead of using Fronts' solvers, for example if you need to deal with a different boundary condition or want to use your own solving algorithm.
D functions and fronts.D
Many of the functions in Fronts either take or return D functions to work. D functions have to be defined as follows:
D
: callableTwice-differentiable function that maps the range of S to positive values. It can be called as
D(S)
to evaluate it atS
. It can also be called asD(S, derivatives)
withderivatives
equal to 1 or 2, in which case the firstderivatives
derivatives of the function evaluated at the sameS
are included (in order) as additional return values. While mathematically a scalar function,D
operates in a vectorized fashion with the same semantics whenS
is anumpy.ndarray
.
With the above definition you can easily write any functions you need to solve your particular problems.
Fronts also comes with a submodule fronts.D
that lets you access some predefined functions:
-
fronts.D.constant()
— create a constant function: -
fronts.D.power_law()
— create a function of the form: -
fronts.D.van_genuchten()
— create a Van Genuchten moisture diffusivity function:where S is either water content or saturation, and Se is defined as:
-
fronts.D.richards()
— make a moisture diffusivity function from a relative permeability/conductivity function kr and a capillary capacity function C, using the definition:Can be used to convert problems of the Richards equation (for which those two functions are parameters) in horizontal domains into moisture diffusivity problems that can be solved with Fronts.
Examples
Introductory example
Plotting the solution in this example requires Matplotlib.
Let us solve the following initial-boundary value problem defined in a semi-infinite domain:
Example problem
Find S such that:
By comparing the example problem with the common problem introduced above, we see that the parameters are:
In this case it is not necessary to write the function D
it ourselves. The function we need can be obtained from the fronts.D
module:
from fronts.D import power_law
D = power_law(k=4)
We are now ready to solve the problem with fronts.solve
. We simply pass it the parameters D
, Si
and Sb
.
from fronts import solve
solution = solve(D, Si=0.1, Sb=1)
The call to fronts.solve
completes within a second and we get back a Solution
object, which holds the functions S
, dS_dr
, dS_dt
and flux
.
We can now plot S for arbitrary r and t. For example, with r between 0 and 10 and t=60:
import matplotlib.pyplot as plt
r = np.linspace(0, 10, 200)
plt.plot(r, solution.S(r, t=60))
plt.xlabel("r")
plt.ylabel("S")
plt.show()
The plot will look like this:
Finally, let us plot the flux at t=60:
plt.plot(r, solution.flux(r, t=60))
plt.xlabel("r")
plt.ylabel("flux")
plt.show()
More examples
The included examples can be found in the examples
directory of this project. The directory contains the following files:
- subdirectory
powerlaw/
— cases based on the introductory example presented abovesolve.py
: solve the case withfronts.solve()
.radial.py
: solve a radial case (with a moving boundary) usingfronts.solve()
.inverse.py
: more examples of usage offronts.solve()
and offronts.inverse()
.D.py
: plot D for this case.
- subdirectory
1INFILTR/
— the 1INFILTR test case from Hydrus-1D, in horizontalsolve.py
: solve the case withfronts.solve()
.validation.py
: results for the same case obtained using Hydrus for comparison.
- subdirectory
HF135/
— infiltration into an HF135 nitrocellulose membrane (data from the PhD work of J.R. Buser)solve.py
: solve the lateral flow case withfronts.solve()
.refine.py
: get a rough approximation of the solution to the lateral flow case usingfronts.solve()
with a high tolerance, and then refine it with bothfronts.solve()
andfronts.solve_from_guess()
.radial.py
: radial (cylindrical) flow case.- 🐌
inverse1.py
: usefronts.inverse()
to extract D from a solution. Here, the solution is obtained withfronts.solve()
. The extracted D is then used withfronts.solve()
and the same conditions to verify that an equivalent solution is obtained. - 🐌
inverse2.py
: usefronts.inverse()
to obtain D from the validation case and then use it to solve the same problem. validation.py
: results with the same case solved with porousMultiphaseFoam for comparison.D.py
: plot D for this case.
- subdirectory
exact/
— solve a case with a D function proposed by Philip that has an exact solutionsolve.py
: solve the case withfronts.solve()
and compare with the exact solution.fromguess.py
: solve the case withfronts.solve_from_guess()
and compare with the exact solution.D.py
: plot D for this case.
Note: the examples marked with 🐌 are significantly more computationally intensive and may take more than a minute to run to completion. All other cases should finish within a few seconds at the most.
Authors
- Gabriel S. Gerlero @gerlero
- Pablo A. Kler @pabloakler
- Claudio L.A. Berli
Fronts was conceived and is developed by members of the Santa Fe Microfluidics Group (GSaM) at the Research Center for Computational Methods (CIMEC, UNL-CONICET) and the Institute of Technological Development for the Chemical Industry (INTEC, UNL-CONICET) in Santa Fe, Argentina.
License
Fronts is open-source software available under the BSD 3-clause license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.