Library description
Main classes
BVP
The bvp
class is the main class of the library.
It features a minimalistic signature: bvp(domain, vform, bc)
that matches exactly the three main elements on which the formal definition of a boundary-value problem relies on. The three corresponding arguments self.domain
, self.vform
and self.bnd_conds
are set during initiation. They can be adjusted afterwards with specific setters, respectively: self.set_domain()
, self.set_vform()
and self.add_boundary_condition()
.
The self.set_vform()
method, called within self.__init__()
, instanciates the functionspace bases on the mesh specified within the domain argument and the finite element characteristics set within the vform
argument.
The central method of the bvp
class is the solve()
one. This method instanciates the vform.lhs
and vform.rhs
, set the FEniCS solver to use depending on the variational form at stake and runs the simulation. If the considered vform
has a vanishing rhs
term, a non-linear solver will be chosen ; otherwize, a linear one will be picked.
Once bvp.solve()
is called, the argument bvp.solution, initially set to None
, is updated with the fenics.function
computed solution.
The bvp.solution
can then be visualized with the plot()
function of the bvp.utils.visu
module (c.f. description of this module hereafter). A self.info()
method gathers and displays all the parameters of the simulation. This method makes use of the domain.info()
and vform.info()
ones. To performed more in-depth analysis of the simulation results, the whole problem — with its solution — can be saved on disk in the .xdmf format with the self.save_solution()
method. The genericity of the .xdmf format enables then the analysis of the results with powerful softwares such as Paraview <https://www.paraview.org>.
IBVP
The ibvp
class inherits directly from the bvp
one. Its signature features two additional arguments: scheme
and initial_state
.
The former corresponds to the time-integration scheme to use. It must corresponds to a daughter class of the FirstOrderScheme
class within the bvpy.solvers.time_integration
module. Currently, the bvpy library features two such classes ImplicitEuler
and ExplicitEuler
.
The latter corresponds to the initial value from which the solution will be evolving. It must be given as a fenics.function
. Note that the self.initial_state
argument can be set after the ibvp
initialization with the ibvp.set_initial_solution()
method.
The main method of the ibvp
class is self.integrate()
that handles the time-integration loop. During each iteration of the loop, it performs two tasks:
Run a spatial resolution of the problem at the current time as a classic BVP. This is performed by the
self.step()
method that calls theself.solve()
method inherited from thebvp
mother class.Record the solution of this spatial resolution as a “layer” in a temporal stack recorded as an .xdmf file.
Modules
The purpose of the first four modules listed below is to provide the library with dedicated tools to parametrize the previously described classes (bvp
and ibvp
). The fifth one (bvpy.utils
) provides useful functions to handle the simulations, e.g. recording, plotting, etc…
Domains
The bvpy.domains
module contains the classes that can be used to implement the notion of integration domain, \(\body\) in eq.(1). It is built around the (abstract) mother class AbstractDomain
. All domain classes used as arguments for BVPs/IBVPs inherits from it. The AbstractDomain
encompasses two complementary description of the integration domain:
A
gmsh.model
called the geometry of the domain and set by thegeometry()
abstract method.A
fenics.mesh
called the mesh of the domain and produced by thediscretize()
method. Note that this method is not automatically called at instanciation but either by high-end functions such asplot()
(from thebvpy.utils.visu
module) or bvp.solve().
The notion of geometry and the related geometry()
method are of paramount importance, for each domain class corresponds to a specific implementation of the geometry()
method:
The classes contained within the
bvpy.domains.primitives
sub-module are built aroundgeometry()
methods that construct basic geometric elements (such as rectangles, disk, spheres…) exclusively with Gmsh tools.
Note
Basic operators such as __add__()
, __sub__()
and __and__()
have been surcharged so primitives can be combined together to form more complex domains.
The
CustomPolygonalDomain
class (contained within thebvpy.domains.custom_polygonal
sub-module) is built around ageometry()
method that construct piecewise polygonal structures from lists of oriented points. This is also done thanks to Gmsh tools. The purpose of this class is to enable the use of cellularized structures as integration domains. This is an important feature in the context of modeling biological tissues and other multicellular continua.Finally, the
CustomDomain
class (within thebvpy.domains.custom_domain
sub-module) features an emptygeometry()
method for its purpose is to define a domain from an already existing mesh, sorted as a.ply
-formatted file.
Besides a geometry and a mesh, domain classes also encompasses fenics.Measures
elements defined within the domain (self.dx
) and onto its border (self.ds
) and some setter methods to parametrize
Note
Domain examples are given in the following tutorial: domain examples<bvpy_tutorial_domain>
Vforms
The goal of the bvpy.vforms
module is to gather weak formulations of differential equations and systems that can be implemented in Bvpy. The corresponding vform classes constitute the second mandatory argument of the bvp
and ibvp
class signatures. Similarly to the bvpy.domains
module, the bvpy.vforms
module is built around one main (abstract) mother class AbstractVform
, other vform classes contained within sub-modules inherit directly from it.
The heart of the AbstractVform
class is the contruct_form()
abstract method. Its purpose is to instantiate, in FEniCS, the bilinear (fenics.lhs
) and the linear (fenics.rhs
) operators that constitute the variational form of the differential equation (or system) at stake. In that matter, this method has to be written de novo each time a new (set of) differential equation(s) is to be considered.
In the current version of Bvpy, the resulting daughter classes of AbstractVform
are compiled in field-specific sub-modules :
bvpy.vforms.poisson
contains the simplest vform class, the one that encodes the scalar Poisson equation, which stands as the “Hello world !” for numerical analysis. This vform class encompasses equations of the general form:
bvpy.vforms.helmholtz
contains an instanciation of the helmholtz’ equation, namely Poisson’s equation augmented with a linear term:
bvpy.vforms.transport
contains two classes dedicated to transport equations:TransportForm
andCoupledTransportForm
. The former enables the study of equations of the general form:
where the function \(f(\mathbf{x}, \phi(\mathbf{x}))\) is non-linear. This general form has been thought to encompass active transport equations and reaction-diffusion ones.
The second class of sub-module specifically tackles the problem differential systems composed of several interdependent equations of the general form given above. Such system, can be generally written as:
bvpy.vforms.elasticity
encompasses two vform classes: LinearElasticForm and HyperElasticForm implementing respectively linear and hyper-elastic equations. The former encompasses equations of the general form:
where \(\mathbf{u}\) stands for the displacement field. The tensor $stiffness$ accounts for the linear stiffness tensor of the considered material.
The latter encompasses hyper-elastic equations, i.e. valid beyond the linear deformation regime. They corresponds to the same general mathematical definition given above but with another strain definition:
Boundary_conditions
The bvpy.boundary_conditions
enables an easy implementation of boundary conditions through the use of the dirichlet
function. This function takes two mandatory arguments : val
and boundary
. They respectively correspond to the value that one wants to impose on a boundary.
The val
argument can have several types:
int
,``float``,list
,tuple
,numpy.ndarray
. These types will encode constant dirichlet conditions, i.e. a (list of) constant value(s) on a given (list of) subset(s) of the border.Non-constant dirichlet conditions will be encoded with
val
arguments given as strings.
The boundary
argument must be an instance of the Boundary
class defined within the bvpy.boundary_conditions.boundary
module. This class enables the definition of the boundary or a subset of it from a string expression.
Solvers
The bvpy.solvers
module gathers two types of finite element solvers: LinearSolver
and NonLinearSolver
. They are not ment to be set by the user directly. The choice between both types is made automatically by the bvp
class depending on the variational form at stake. More precisely, if the instanced vform
features a non-zero rhs
element a NonLinearSolver
will automatically instanced.
Besides the finite element solvers, the bvpy.solvers
module also feature a time_integration
sub-module that defines, in the current version, two time-integration schemes: ImplicitEuler
and ExplicitEuler
.
Utils
The bvpy.utils
module can be seen as an “house-keeping” module that gathers various useful functions and classes regrouped in thematic sub-modules.
bvpy.utils.io
: Read and write methods.bvpy.utils.post_processing
:bvpy.utils.pre_processing
:bvpy.utils.visu
: