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, fronts.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 saturation or moisture content 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 models fluid flow in unsaturated porous media.
Of particular interest to the creators of Fronts is the fact that the moisture diffusivity equation as supported by Fronts can directly describe the phenomenon 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 works with all current (as of 2019) versions of Python: it runs on Python 3.5 and later as well as on the older Python 2.7. It has been tested on versions 3.7.4, 3.6.6, 3.5.7, and 2.7.16.
-
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
Documentation and features
This is a complete list of the symbols that Fronts provides, with a short description of each. You can find the full details on each object in the API documentation.
Solvers and solutions
-
fronts.solve()
— meshless solversolve
solves any instance of the general problem. Returns aSemiInfiniteSolution
. -
fronts.solve_from_guess()
— mesh-based solversolve_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 kind of problems thansolve
. 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 aSemiInfiniteSolution
on success. -
fronts.Solution
,fronts.SemiInfiniteSolution
— continuous solutionsSolution
objects provide the continuous functionsS
,dS_dr
,dS_dt
andflux
that build up the solution to a problem. The solvers in Fronts return aSemiInfiniteSolution
(a subclass ofSolution
) as part of their results. If you calledode
and solved the ODE yourself, you can create aSolution
orSemiInfiniteSolution
by passing the solution to the ODE to the appropiate constructor.Recall that when solving the moisture diffusivity/horizonal Richards equation, the diffusive flux (which you can obtain by calling
flux
) is equivalent to the wetting fluid's velocity. Accordingly, this enables the coupling of the results you get from Fronts (in terms of advective velocity) with more complex problems of solute transport. -
fronts.inverse()
— solve the inverse probleminverse
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.
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 the saturation and Se is defined as:
-
fronts.D.richards()
— make a moisture diffusivity function from the hydraulic conductivity function K and the capillary capacity function C using the definition:
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 SemiInfiniteSolution
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()
.
-
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/
— lateral flow case in an HF135 nitrocellulose membrane (data from the PhD work of J.R. Buser)solve.py
: solve the case withfronts.solve()
.fromguess.py
: get a rough approximation of the solution usingfronts.solve()
with a high tolerance, and then refine it with bothfronts.solve()
andfronts.solve_from_guess()
.- 🐌
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.
-
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.
Note: the examples marked with 🐌 are significantly more computationally intensive and may take up to a few minutes to run to completion.
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.