Sfepy Manual
Sfepy Manual
Sfepy Manual
1 Documentation 3
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.1 Supported Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.2 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2.3 Installing SfePy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2.4 Using SfePy Docker Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2.5 Installing SfePy from Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.6 Testing Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.7 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.8 Using IPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.9 Notes on Multi-platform Python Distributions . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.10 Notes on Installing SfePy Dependencies on Various Platforms . . . . . . . . . . . . . . . . 9
1.3 Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.1 Basic SfePy Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.2 Basic Notions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.3 Running a Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3.4 Example Problem Description File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.5 Interactive Example: Linear Elasticity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.4 User’s Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.4.1 Running a Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.4.2 Visualization of Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.4.3 Problem Description File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.4.4 Building Equations in SfePy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.4.5 Term Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.4.6 Solution Postprocessing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.4.7 Probing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.4.8 Postprocessing filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.4.9 Solvers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
1.4.10 Solving Problems in Parallel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
1.4.11 Isogeometric Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
1.5 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.5.1 Primer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.5.2 Using Salome with SfePy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
1.5.3 Preprocessing: FreeCAD/OpenSCAD + Gmsh . . . . . . . . . . . . . . . . . . . . . . . . . 81
1.5.4 Material Identification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
1.5.5 Mesh parametrization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
1.5.6 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
1.5.7 Example Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
1.6 Useful Code Snippets and FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
i
1.6.1 Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
1.6.2 Mesh-Related Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578
1.6.3 Regions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
1.6.4 Material Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
1.7 Theoretical Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
1.7.1 Notes on solving PDEs by the Finite Element Method . . . . . . . . . . . . . . . . . . . . . 581
1.7.2 Implementation of Essential Boundary Conditions . . . . . . . . . . . . . . . . . . . . . . . 583
1.8 Term Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
1.8.1 Term Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
1.8.2 Term Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587
2 Development 609
2.1 General Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
2.2 Possible Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
2.3 Developer Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 610
2.3.1 Retrieving the Latest Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 610
2.3.2 SfePy Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
2.3.3 Exploring the Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612
2.3.4 How to Contribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 612
2.3.5 How to Regenerate Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
2.3.6 How to Implement a New Term . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618
2.3.7 Multi-linear Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624
2.3.8 How To Make a Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626
2.3.9 Module Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628
Bibliography 1011
Index 1017
ii
SfePy Documentation, Release version: 2022.2
• genindex
• modindex
• search
CONTENTS 1
SfePy Documentation, Release version: 2022.2
2 CONTENTS
CHAPTER
ONE
DOCUMENTATION
1.1 Introduction
SfePy (http://sfepy.org) is a software for solving systems of coupled partial differential equations (PDEs) by the finite
element method in 1D, 2D and 3D. It can be viewed both as black-box PDE solver, and as a Python package which can
be used for building custom applications. The word “simple” means that complex FEM problems can be coded very
easily and rapidly.
There is also a preliminary support for the isogeometric analysis, outlined in Isogeometric Analysis.
The code is written almost entirely in Python, with exception of the most time demanding routines - those are written
in C and wrapped by Cython or written directly in Cython.
SfePy is a free software released under the New BSD License. It relies on NumPy and SciPy (an excellent collection
of tools for scientific computations in Python). It is a multi-platform software that should work on Linux, Mac OS X
and Windows.
SfePy was originally developed as a flexible framework to quickly implement and test the mathematical models devel-
oped during our various research projects. It has evolved, however, to a rather full-featured (yet small) finite element
code. Many terms have been implemented that can be used to build the PDEs, see Term Overview. SfePy comes also
with a number of examples that can get you started, check Examples, Gallery and Tutorial. Some more advanced
features are discussed in Primer.
1.2 Installation
SfePy is known to work on various flavors of recent Linux, Intel-based MacOS and Windows. SfePy requires Python
3. The release 2019.4 was the last with Python 2.7 support.
Note: Depending on Python installation and OS used, replacing python by python3 might be required in all the
commands below (e.g. in Compilation of C Extension Modules) in order to use Python 3.
3
SfePy Documentation, Release version: 2022.2
1.2.2 Requirements
4 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
SfePy should work with any recent Python 3.x (in long-term view Python 3.6+ is recommended). It is only matter of
taste to use either native OS Python installation or any other suitable distribution. We could recommend the following
distributions to use:
• Linux: OS native installation (See Notes on Installing SfePy Dependencies on Various Platforms for further
details.)
• macOS: multi-platform scientific Python distributions Anaconda (See Notes on Multi-platform Python Distri-
butions for further details.)
• Windows: use free versions of commercial multi-platform scientific Python distributions Anaconda or Enthought
Canopy (see Notes on Multi-platform Python Distributions for further details). In addition a completely free
open-source portable distribution WinPython can be used.
On any supported platform we could recommend Anaconda distribution as easy-to-use, stable and up-to-date Python
distribution with all the required dependencies (including pre-built sfepy package).
Note: all SfePy releases are regularly tested on recent Linux distributions (Debian and (K)Ubuntu) using OS Python
installation and Anaconda, macOS 10.12+ using Anaconda and Windows 8.1+ using Anaconda.
For Anaconda and .deb based Linux distributions (Debian, (K)Ubuntu), pre-built SfePy packages are available. You
may directly install them with:
• Anaconda distribution: install sfepy from conda-forge channel:
There are no further steps required to install/configure SfePy (see Notes on Multi-platform Python Distributions for
additional notes).
Besides the classical installation we also provide experimental Docker images with ready-to-run Anaconda and Sfepy
installation.
Before you start using SfePy images, you need to first install and configure Docker on your computer. To do this follow
official Docker documentation.
Currently available images are:
• sfepy/sfepy-notebook - basic command line interface and web browser access to Jupyter notebook/JupyterLab
interface,
• sfepy/sfepy-x11vnc-desktop - optimized Ubuntu desktop environment accessible via standard web browser or
VNC client.
For available runtime options and further information see sfepy-docker project on Github.
As a convenience, use the following Docker compose file, which will start the SfePy image, run Jupyter Lab, and map
the contents of the local directory to the SfePy home directory within the image. Just create an empty folder and add
the following to a file named docker-compose.yml. Then, run docker-compose up in the same directory.
1.2. Installation 5
SfePy Documentation, Release version: 2022.2
The latest stable release can be obtained from the download page. Otherwise, download the development version of
the code from SfePy git repository:
In case you wish to use a specific release instead of the latest master version, use:
git tag -l
to see the available releases - the release tags have form release_<year>.<int>.
See the download page for additional download options.
• for installation:
Installation
SfePy can be used without any installation by running its main scripts and examples from the top-level directory of the
distribution or can be installed locally or system-wide:
• system-wide (may require root privileges):
6 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
After building and/or installing SfePy you should check if all the functions are working properly by running the auto-
mated tests.
in the SfePy top-level directory in case of the in-place build and anywhere else when testing the installed package.
The testing function is based on pytest. Additional pytest options can be passed as arguments to sfepy.test(), for
example:
python -c "import sfepy; sfepy.test('-v', '--durations=0', '-m not slow', '-k test_
˓→assembling.py')"
See pytest usage instructions for other options and usage patterns.
To test an in-place build (e.g. in a cloned git repository), the following simpler command can be used in the sources
top-level directory:
which will also add the current directory to sys.path. If the top-level directory is already in sys.path (e.g. using
export PYTHONPATH=.), the simplest way of invoking pytest is:
pytest sfepy/tests
pytest -v sfepy/tests/test_assembling.py
1.2.7 Debugging
If something goes wrong, edit the site_cfg.py config file and set debug_flags = '-DDEBUG_FMF' to turn on
bound checks in the low level C functions, and recompile the code:
Then re-run your code and report the output to the SfePy mailing list.
1.2. Installation 7
SfePy Documentation, Release version: 2022.2
We generally recommend to use (a customized) IPython interactive shell over the regular Python interpreter when
following Tutorial or Primer (or even for any regular interactive work with SfePy).
Install IPython (as a generic part of your selected distribution) and then customize it to your choice.
Depending on your IPython usage, you can customize your default profile or create a SfePy specific new one as follows:
1. Create a new SfePy profile:
2. Open the ~/.ipython/profile_sfepy/ipython_config.py file in a text editor and add/edit after the c =
get_config() line:
exec_lines = [
'import numpy as nm',
'import matplotlib as mpl',
'mpl.use("WXAgg")',
#
# Add your preferred SfePy customization here...
#
]
c.InteractiveShellApp.exec_lines = exec_lines
c.TerminalIPythonApp.gui = 'wx'
c.TerminalInteractiveShell.colors = 'Linux' # NoColor, Linux, or LightBG
Please note, that generally it is not recommended to use star (*) imports here.
3. Run the customized IPython shell:
ipython --profile=sfepy
Anaconda
Once the conda-forge channel has been enabled, SfePy can be installed with:
8 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
It is possible to list all of the versions of SfePy available on your platform with:
2. installing the SfePy dependencies only - then proceed with the Installing SfePy from Sources instructions.
In this case, install the missing/required packages using built-in conda package manager:
or try:
To build SfePy extension modules, included mingw-w32/64 compiler tools should work fine. If you encounter any
problems, we recommend to install and use Microsoft Visual C++ Build Tools instead (see Anaconda FAQ).
The following information has been provided by users of the listed platforms and may become obsolete over time. The
generic installation instructions above should work in any case, provided the required dependencies are installed.
Gentoo
Archlinux
1.2. Installation 9
SfePy Documentation, Release version: 2022.2
Instructions
Edit Makefile and change all references from python to python2. Edit scripts and change shebangs to point to python2.
Debian
(K)Ubuntu
˓→sparse
1.3 Tutorial
10 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
This section introduces the basics of running SfePy from the command line.
The script simple.py is the most basic starting point in SfePy. It can be invoked in many (similar) ways which de-
pends on used OS, Python distribution and SfePy build method (see Installing SfePy for further info). All (working)
alternatives described below are interchangeable, so don’t panic and feel free to pick your preferred choice (see Basic
Usage for further explanation and more usage examples).
Depending on selected build method and OS used we recommend for:
• In-place build
Use the top-level directory of SfePy source tree as your working directory and use:
./simple.py <problem_description_file>
<path/to/installed/simple.py> <problem_description_file>
You can also use the simple SfePy command-wrapper (ensure that SfePy installation executable directory is
included in your PATH):
Please note, that improper mixing of in-place and install builds on single command line may result in strange runtime
errors.
All functions of SfePy package can be also used interactively (see Interactive Example: Linear Elasticity for instance).
We recommend to use the IPython interactive shell for the best fluent user experience. You can customize your IPython
startup profile as described in Using IPython.
The simplest way of using SfePy is to solve a system of PDEs defined in a problem description file, also referred to
as input file. In such a file, the problem is described using several keywords that allow one to define the equations,
variables, finite element approximations, solvers and solution domain and subdomains (see sec-problem-description-
file for a full list of those keywords).
The syntax of the problem description file is very simple yet powerful, as the file itself is just a regular Python module
that can be normally imported – no special parsing is necessary. The keywords mentioned above are regular Python
variables (usually of the dict type) with special names.
Below we show:
1.3. Tutorial 11
SfePy Documentation, Release version: 2022.2
The following commands should be run in the top-level directory of the SfePy source tree after compiling the C extension
files. See Installation for full installation instructions.
• Download sfepy/examples/diffusion/poisson_short_syntax.py. It represents our sample SfePy sec-
problem-description-file, which defines the problem to be solved in terms SfePy can understand.
• Use the downloaded file in place of <problem_description_file.py> and run simple.py as described above. The
successful execution of the command creates output file cylinder.vtk in the SfePy top-level directory.
• The resview.py script can be used for quick postprocessing and visualization of the SfePy output files. It requires
pyvista installed on your system.
• As a simple example, try:
./resview.py cylinder.vtk
12 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
where Γ ⊆ Ω is a subset of the domain Ω boundary. For simplicity, we set 𝑓 ≡ 0, but we still work with the material
constant 𝑐 even though it has no influence on the solution in this case. We also assume zero fluxes over 𝜕Ω ∖ Γ, i.e.
𝜕𝑛 = 0 there. The particular boundary conditions used below are 𝑇 = 2 on the left side of the cylindrical domain
𝜕𝑇
Comparing the above integral term with the long table in Term Overview, we can see that SfePy contains this term
under name dw_laplace. We are now ready to proceed to the actual problem definition.
Open the sfepy/examples/diffusion/poisson_short_syntax.py file in your favorite text editor. Note that the
file is a regular Python source code.
The filename_mesh variable points to the file containing the mesh for the particular problem. SfePy supports a variety
of mesh formats.
1.3. Tutorial 13
SfePy Documentation, Release version: 2022.2
materials = {
'coef': ({'val' : 1.0},),
}
Here we define just a constant coefficient 𝑐 of the Poisson equation, using the ‘values’ attribute. Other possible attribute
is ‘function’ for material coefficients computed/obtained at runtime.
Many finite element problems require the definition of material parameters. These can be handled in SfePy with material
variables which associate the material parameters with the corresponding region of the mesh.
regions = {
'Omega' : 'all', # or 'cells of group 6'
'Gamma_Left' : ('vertices in (x < 0.00001)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.099999)', 'facet'),
}
Regions assign names to various parts of the finite element mesh. The region names can later be referred to, for
example when specifying portions of the mesh to apply boundary conditions to. Regions can be specified in a variety
of ways, including by element or by node. Here, ‘Omega’ is the elemental domain over which the PDE is solved and
‘Gamma_Left’ and ‘Gamma_Right’ define surfaces upon which the boundary conditions will be applied.
fields = {
'temperature': ('real', 1, 'Omega', 1)
}
A field is used mainly to define the approximation on a (sub)domain, i.e. to define the discrete spaces 𝑉ℎ , where we
seek the solution.
The Poisson equation can be used to compute e.g. a temperature distribution, so let us call our field ‘temperature’. On
the region ‘Omega’ it will be approximated using linear finite elements.
A field in a given region defines the finite element approximation. Several variables can use the same field, see below.
variables = {
't': ('unknown field', 'temperature', 0),
's': ('test field', 'temperature', 't'),
}
One field can be used to generate discrete degrees of freedom (DOFs) of several variables. Here the unknown variable
(the temperature) is called ‘t’, it’s associated DOF name is ‘t.0’ – this will be referred to in the Dirichlet boundary
section (ebc). The corresponding test variable of the weak formulation is called ‘s’. Notice that the ‘dual’ item of a
test variable must specify the unknown it corresponds to.
For each unknown (or state) variable there has to be a test (or virtual) variable defined, as usual in weak formulation of
PDEs.
ebcs = {
't1': ('Gamma_Left', {'t.0' : 2.0}),
't2', ('Gamma_Right', {'t.0' : -2.0}),
}
14 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
integrals = {
'i': 2,
}
Integrals specify which numerical scheme to use. Here we are using a 2nd order quadrature over a 3 dimensional space.
equations = {
'Temperature' : """dw_laplace.i.Omega( coef.val, s, t ) = 0"""
}
The equation above directly corresponds to the discrete version of (1.2), namely: Find 𝑡 ∈ 𝑉ℎ , such that
∫︁
𝑇
𝑠 ( 𝑐 𝐺𝑇 𝐺)𝑡 = 0, ∀𝑠 ∈ 𝑉ℎ0 ,
Ωℎ
where ∇𝑢 ≈ 𝐺𝑢.
The equations block is the heart of the SfePy problem description file. Here, we are specifying that the Laplacian of the
temperature (in the weak formulation) is 0, where coef.val is a material constant. We are using the ‘i’ integral defined
previously, over the domain specified by the region ‘Omega’.
The above syntax is useful for defining custom integrals with user-defined quadrature points and weights, see Integrals.
The above uniform integration can be more easily achieved by:
equations = {
'Temperature' : """dw_laplace.2.Omega( coef.val, s, t ) = 0"""
}
The integration order is specified directly in place of the integral name. The integral definition is superfluous in this
case.
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton',
{'i_max' : 1,
'eps_a' : 1e-10,
}),
}
Here, we specify the linear and nonlinear solver kinds and options. See sfepy.solvers.ls, sfepy.solvers.nls
and sfepy.solvers.ts_solvers for available solvers and their parameters.. Even linear problems are solved by a
nonlinear solver (KISS rule) – only one iteration is needed and the final residual is obtained for free. Note that we do
not need to define a time-stepping solver here - the problem is stationary and the default 'ts.stationary' solver is
created automatically.
options = {
'nls' : 'newton',
'ls' : 'ls',
}
The solvers to use are specified in the options block. We can define multiple solvers with different convergence param-
eters.
That’s it! Now it is possible to proceed as described in Invoking SfePy from the Command Line.
1.3. Tutorial 15
SfePy Documentation, Release version: 2022.2
This example shows how to use SfePy interactively, but also how to make a custom simulation script. We will use
IPython interactive shell which allows more flexible and intuitive work (but you can use standard Python shell as well).
We wish to solve the following linear elasticity problem:
𝜕𝜎𝑖𝑗 (𝑢)
− + 𝑓𝑖 = 0 in Ω, 𝑢 = 0 on Γ1 , ¯1 on Γ2 ,
𝑢1 = 𝑢 (1.3)
𝜕𝑥𝑗
𝜕𝑢
where the stress is defined as 𝜎𝑖𝑗 = 2𝜇𝑒𝑖𝑗 +𝜆𝑒𝑘𝑘 𝛿𝑖𝑗 , 𝜆, 𝜇 are the Lamé’s constants, the strain is 𝑒𝑖𝑗 (𝑢) = 21 ( 𝜕𝑥
𝜕𝑢𝑖
𝑗
+ 𝜕𝑥𝑗𝑖 )
and 𝑓 are volume forces. This can be written in general form as 𝜎𝑖𝑗 (𝑢) = 𝐷𝑖𝑗𝑘𝑙 𝑒𝑘𝑙 (𝑢), where in our case 𝐷𝑖𝑗𝑘𝑙 =
𝜇(𝛿𝑖𝑘 𝛿𝑗𝑙 + 𝛿𝑖𝑙 𝛿𝑗𝑘 ) + 𝜆 𝛿𝑖𝑗 𝛿𝑘𝑙 .
In the weak form the equation (1.3) is
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑘𝑙 (𝑢)𝑒𝑖𝑗 (𝑣) + 𝑓 𝑖 𝑣𝑖 = 0 , (1.4)
Ω Ω
where 𝑣 is the test function, and both 𝑢, 𝑣 belong to a suitable function space.
Hint: Whenever you create a new object (e.g. a Mesh instance, see below), try to print it using the print statement – it
will give you insight about the object internals.
The whole example summarized in a script is available below in Complete Example as a Script.
In the SfePy top-level directory run
ipython
Define the regions – the whole domain Ω, where the solution is sought, and Γ1 , Γ2 , where the boundary conditions will
be applied. As the domain is rectangular, we first get a bounding box to get correct bounds for selecting the boundary
edges.
Next we define the actual finite element approximation using the Field class.
16 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Using the field fu, we can define both the unknown variable 𝑢 and the test variable 𝑣.
Before we can define the terms to build the equation of linear elasticity, we have to create also the materials, i.e. define
the (constitutive) parameters. The linear elastic material m will be defined using the two Lamé constants 𝜆 = 1, 𝜇 = 1.
The volume forces will be defined also as a material as a constant (column) vector [0.02, 0.01]𝑇 .
One more thing needs to be defined – the numerical quadrature that will be used to integrate each term over its domain.
Now we are ready to define the two terms and build the equations.
The equations have to be completed by boundary conditions. Let us clamp the left edge Γ1 , and shift the right edge Γ2
in the 𝑥 direction a bit, depending on the 𝑦 coordinate.
The last thing to define before building the problem are the solvers. Here we just use a sparse direct SciPy solver and
the SfePy Newton solver with default parameters. We also wish to store the convergence statistics of the Newton solver.
As the problem is linear it should converge in one iteration.
1.3. Tutorial 17
SfePy Documentation, Release version: 2022.2
In [31]: ls = ScipyDirect({})
In [32]: nls_status = IndexedStruct()
In [33]: nls = Newton({}, lin_solver=ls, status=nls_status)
The Problem has several handy methods for debugging. Let us try saving the regions into a VTK file.
In [35]: pb.save_regions_as_groups('regions')
Finally, we set the boundary conditions and the top-level solver , solve the problem, save and view the results. For
stationary problems, the top-level solver needs not to be a time-stepping solver - when a nonlinear solver is set instead,
the default 'ts.stationary' time-stepping solver is created automatically.
18 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
This
The default view is not very fancy. Let us show the displacements by shifting the mesh. Close the previous window
and do
1.3. Tutorial 19
SfePy Documentation, Release version: 2022.2
1 #!/usr/bin/env python
2 from argparse import ArgumentParser
3 import numpy as nm
4
5 import sys
6 sys.path.append('.')
7
18
20 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
25 return val
26
27
28 def main():
29 from sfepy import data_dir
30
31 parser = ArgumentParser()
32 parser.add_argument('--version', action='version', version='%(prog)s')
33 options = parser.parse_args()
34
59 t1 = Term.new('dw_lin_elastic(m.D, v, u)',
60 integral, omega, m=m, v=v, u=u)
61 t2 = Term.new('dw_volume_lvf(f.val, v)', integral, omega, f=f, v=v)
62 eq = Equation('balance', t1 + t2)
63 eqs = Equations([eq])
64
71 ls = ScipyDirect({})
72
73 nls_status = IndexedStruct()
74 nls = Newton({}, lin_solver=ls, status=nls_status)
(continues on next page)
1.3. Tutorial 21
SfePy Documentation, Release version: 2022.2
76 pb = Problem('elasticity', equations=eqs)
77 pb.save_regions_as_groups('regions')
78
79 pb.set_bcs(ebcs=Conditions([fix_u, shift_u]))
80
81 pb.set_solver(nls)
82
83 status = IndexedStruct()
84 variables = pb.solve(status=status)
85
89 pb.save_state('linear_elasticity.vtk', variables)
90
91
92 if __name__ == '__main__':
93 main()
The following should be run in the top-level directory of the SfePy source tree after compiling the C extension files.
See Installation for full installation instructions info. The $ indicates the command prompt of your terminal.
Basic Usage
• $ ./simple.py sfepy/examples/diffusion/poisson_short_syntax.py
– Creates cylinder.vtk
• $ ./simple.py sfepy/examples/navier_stokes/stokes.py
– Creates channels_symm944t.vtk
22 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
All top-level SfePy scripts (applications) can be run via single sfepy-run wrapper:
$ ./sfepy-run
usage: sfepy-run [command] [options]
positional arguments:
{extractor,postproc,probe,simple}
Available SfePy command(s).
options Additional options passed directly to selected
[command].
optional arguments:
-h, --help show this help message and exit
-v, --version show program's version number and exit
-w, --window use alternative (pythonw) interpreter
Notes
• This is a “new” supported method. Any SfePy script can be still run as stand-alone (as mentioned above).
• Both “inplace” and “system-wide” installations are supported.
Running Tests
The example problems in the examples directory can be computed by the script simple.py which is in the top-level
directory of the SfePy distribution. If it is run without arguments, a help message is printed:
$ ./simple.py
Usage: simple.py [options] filename_in
Both normal and parametric study runs are supported. A parametric study
allows repeated runs for varying some of the simulation parameters - see
``sfepy/examples/diffusion/poisson_parametric_study.py`` file.
$ python sfepy/examples/large_deformation/compare_elastic_materials.py
$ ./simple.py sfepy/examples/diffusion/poisson_parametric_study.py
24 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Common Tasks
• Run a simulation:
./simple.py sfepy/examples/diffusion/poisson_short_syntax.py
./simple.py sfepy/examples/diffusion/poisson_short_syntax.py -o some_results # ->␣
˓→produces some_results.vtk
./simple.py --list=terms
and break the computation after a while (hit Ctrl-C). The mode --save-restart=-1 is currently the only
supported mode. It saves a restart file for each time step, and only the last computed time step restart file is
kept.
– A file named 'unit_ball.restart-??.h5' should be created, where '??' indicates the last stored time
step. Let us assume it is 'unit_ball.restart-04.h5', i.e. the fifth step.
– Restart the simulation by:
The simulation should continue from the next time step. Verify that by running:
./simple.py sfepy/examples/large_deformation/balloon.py
resview.py
Quick visualisation of the SfePy results can be done by resview.py script, which uses PyVista visualisation toolkit
(need to be installed).
The help message of the script is:
usage: resview.py [-h] [-f field_spec [field_spec ...]] [--fields-map map [map ...]] [-s␣
˓→step] [-l] [-i ISOSURFACES] [-e] [-w field]
[--off-screen] [-2]
filenames [filenames ...]
Examples
--------
The examples assume that
``python -c "import sfepy; sfepy.test('--output-dir=output-tests')"``
has been run successfully and the resulting data files are present.
26 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
positional arguments:
filenames
optional arguments:
-h, --help show this help message and exit
-f field_spec [field_spec ...], --fields field_spec [field_spec ...]
fields to plot, options separated by ":" are possible: "cX" -␣
˓→plot only Xth field component; "e" - print edges;
by factor
--fields-map map [map ...]
map fields and cell groups, e.g. 1:u1,p1 2:u2,p2
-s step, --step step select data in a given time step
-l, --outline plot mesh outline
-i ISOSURFACES, --isosurfaces ISOSURFACES
plot isosurfaces [default: 0]
-e, --edges plot cell edges
-w field, --warp field
warp mesh by vector field
--factor factor scaling factor for mesh warp and glyphs. Append "%" to scale␣
˓→relatively to the minimum bounding box size.
--grid-vector2 grid_vector2
define positions of plots along grid axis 2 [default: "0, 1.6, 0
˓→"]
--max-plots MAX_PLOTS
maximum number of plots along grid axis 1 [default: 4]
--no-labels hide plot labels
--label-position position
define position of plot labels [default: "-1, -1, 0, 0.2"]
--no-scalar-bars hide scalar bars
--scalar-bar-size size
define size of scalar bars [default: "0.15, 0.05"]
--scalar-bar-position position
define position of scalar bars [default: "0.8, 0.02, 0, 1.5"]
-v position, --view position
(continues on next page)
--camera-position camera_position
define camera position
--window-size window_size
define size of plotting window
-a output_file, --animation output_file
create animation, mp4 file type supported
-r rate, --frame-rate rate
set framerate for animation
-o output_file, --screenshot output_file
save screenshot to file
--off-screen off screen plots, e.g. when screenshotting
-2, --2d-view 2d view of XY plane
./resview.py output-tests/test_navier_stokes.vtk
produces:
the output is split into plots plot:0 and plot:1, where these plots contain:
• plot:0: field p, mesh edges are switched on
• plot:1: magnitude of vector field u displayed as the surface with opacity set to 0.4; glyphs related to field u and
scaled by factor 2e-2
28 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Here we discuss the basic items that users have to specify in their input files. For complete examples, see the problem
description files in the sfepy/examples/ directory of SfePy.
Long Syntax
Besides the short syntax described below there is (due to history) also a long syntax which is explained in prob-
lem_desc_file_long. The short and long syntax can be mixed together in one description file.
FE Mesh
filename_mesh = 'meshes/3d/cylinder.vtk'
The VTK and HDF5 formats can be used for storing the results. The format can be selected in options, see Miscella-
neous.
The following geometry elements are supported:
30 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Note the orientation of the vertices matters, the figure displays the correct orientation when interpreted in a right-handed
coordinate system.
Regions
Regions serve to select a certain part of the computational domain using topological entities of the FE mesh. They are
used to define the boundary conditions, the domains of terms and materials etc.
Let us denote D the maximal dimension of topological entities. For volume meshes it is also the dimension of space
the domain is embedded in. Then the following topological entities can be defined on the mesh (notation follows
[Logg2012]):
If D = 2, faces are not defined and facets are edges. If D = 3, facets are faces.
Following the above definitions, a region can be of different kind:
• cell, facet, face, edge, vertex - entities of higher dimension are not included.
• cell_only, facet_only, face_only, edge_only, vertex_only - only the specified entities are included,
other entities are empty sets, so that set-like operators still work, see below.
• The cell kind is the most general and should be used with volume terms. It is also the default if the kind is not
specified in region definition.
• The facet kind (same as edge in 2D and face in 3D) is to be used with boundary (surface integral) terms.
• The vertex (same as vertex_only) kind can be used with point-wise defined terms (e.g. point loads).
The kinds allow a clear distinction between regions of different purpose (volume integration domains, surface domains,
etc.) and could be uses to lower memory usage.
A region definition involves topological entity selections combined with set-like operators. The set-like operators can
result in intermediate regions that have the cell kind. The desired kind is set to the final region, removing unneeded
entities. Most entity selectors are defined in terms of vertices and cells - the other entities are computed as needed.
2 Only if mesh format supports reading boundary condition vertices as vertex sets.
3 <expr> is a logical expression like (y <= 0.1) & (x < 0.2). In 2D use x, y, in 3D use x, y and z. & stands for logical and, | stands for
logical or.
4 <function> is a function with signature fun(coors, domain=None), where coors are coordinates of mesh vertices.
5 <efunction> is a function with signature fun(coors, domain=None), where coors are coordinates of mesh cell centroids.
32 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
regions = {
<name> : (<selection>, [<kind>], [<parent>], [{<misc. options>}]),
}
or:
regions = {
<name> : <selection>,
}
Example definitions:
regions = {
'Omega' : 'all',
'Right' : ('vertices in (x > 0.99)', 'facet'),
'Gamma1' : ("""(cells of group 1 *v cells of group 2)
+v r.Right""", 'facet', 'Omega'),
'Omega_B' : 'vertices by get_ball',
}
The Omega_B region illustrates the selection by a function (see Topological Entity Selection). In this example, the
function is:
import numpy as nm
return flag
functions = {
'get_ball' : (get_ball,),
}
regions = {
'Top': ('r.Y *v r.Surf1', 'facet', 'Y', {'mirror_region': 'Bottom'}),
'Bottom': ('r.Y *v r.Surf2', 'facet', 'Y', {'mirror_region': 'Top'}),
}
Fields
fields = {
<name> : (<data_type>, <shape>, <region_name>, <approx_order>)
}
where
• <data_type> is a numpy type (float64 or complex128) or ‘real’ or ‘complex’
• <shape> is the number of DOFs per node: 1 or (1,) or ‘scalar’, space dimension (2, or (2,) or 3 or (3,)) or
‘vector’; it can be other positive integer than just 1, 2, or 3
• <region_name> is the name of region where the field is defined
• <approx_order> is the FE approximation order, e.g. 0, 1, 2, ‘1B’ (1 with bubble)
Example: scalar P1 elements in 2D on a region Omega:
fields = {
'temperature' : ('real', 1, 'Omega', 1),
}
34 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Variables
variables = {
<name> : (<kind>, <field_name>, <spec>, [<history>])
}
where
• <kind> - ‘unknown field’, ‘test field’ or ‘parameter field’
• <spec> - in case of: primary variable - order in the global vector of unknowns, dual variable - name of
primary variable
• <history> - number of time steps to remember prior to current step
Example:
variables = {
't' : ('unknown field', 'temperature', 0, 1),
's' : ('test field', 'temperature', 't'),
}
Integrals
Define the integral type and quadrature rule. This keyword is optional, as the integration orders can be specified directly
in equations (see below):
integrals = {
<name> : <order>
}
where
• <name> - the integral name - it has to begin with ‘i’!
• <order> - the order of polynomials to integrate, or ‘custom’ for integrals with explicitly given values and
weights
Example:
import numpy as nm
N = 2
integrals = {
'i1' : 2,
'i2' : ('custom', zip(nm.linspace( 1e-10, 0.5, N ),
nm.linspace( 1e-10, 0.5, N )),
[1./N] * N),
}
The essential boundary conditions set values of DOFs in some regions, while the constraints constrain or transform
values of DOFs in some regions.
The Dirichlet, or essential, boundary conditions apply in a given region given by its name, and, optionally, in selected
times. The times can be given either using a list of tuples (t0, t1) making the condition active for t0 <= t < t1, or by a
name of a function taking the time argument and returning True or False depending on whether the condition is active
at the given time or not.
Dirichlet (essential) boundary conditions:
ebcs = {
<name> : (<region_name>, [<times_specification>,]
{<dof_specification> : <value>[,
<dof_specification> : <value>, ...]})
}
Example:
ebcs = {
'u1' : ('Left', {'u.all' : 0.0}),
'u2' : ('Right', [(0.0, 1.0)], {'u.0' : 0.1}),
'phi' : ('Surface', {'phi.all' : 0.0}),
'u_yz' : ('Gamma', {'u.[1,2]' : 'rotate_yz'}),
}
The u_yz condition illustrates calculating the condition value by a function. In this example, it is a function of coordi-
nates coors of region nodes:
import numpy as nm
mtx = rotation_matrix2d(angle)
vec_rotated = nm.dot(vec, mtx)
return displacement
functions = {
'rotate_yz' : (rotate_yz,),
}
36 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
The periodic boundary conditions tie DOFs of a single variable in two regions that have matching nodes. Can be used
with functions in sfepy.discrete.fem.periodic.
Periodic boundary conditions:
epbcs = {
<name> : ((<region1_name>, <region2_name>), [<times_specification>,]
{<dof_specification> : <dof_specification>[,
<dof_specification> : <dof_specification>, ...]},
<match_function_name>)
}
Example:
epbcs = {
'up1' : (('Left', 'Right'), {'u.all' : 'u.all', 'p.0' : 'p.0'},
'match_y_line'),
}
The linear combination boundary conditions (LCBCs) are more general than the Dirichlet BCs or periodic BCs. They
can be used to substitute one set of DOFs in a region by another set of DOFs, possibly in another region and of another
variable. The LCBCs can be used only in FEM with nodal (Lagrange) basis.
Available LCBC kinds:
• 'rigid' - in linear elasticity problems, a region moves as a rigid body;
• 'no_penetration' - in flow problems, the velocity vector is constrained to the plane tangent to the surface;
• 'normal_direction' - the velocity vector is constrained to the normal direction;
• 'edge_direction' - the velocity vector is constrained to the mesh edge direction;
• 'integral_mean_value' - all DOFs in a region are summed to a single new DOF;
• 'shifted_periodic' - generalized periodic BCs that work with two different variables and can have a non-zero
mutual shift.
Only the 'shifted_periodic' LCBC needs the second region and the DOF mapping function, see below.
Linear combination boundary conditions:
lcbcs = {
'shifted' : (('Left', 'Right'),
{'u1.all' : 'u2.all'},
'match_y_line', 'shifted_periodic',
'get_shift'),
'mean' : ('Middle', {'u1.all' : None}, None, 'integral_mean_value'),
}
Initial Conditions
Initial conditions are applied prior to the boundary conditions - no special care must be used for the boundary dofs:
ics = {
<name> : (<region_name>, {<dof_specification> : <value>[,
<dof_specification> : <value>, ...]},...)
}
Example:
ics = {
'ic' : ('Omega', {'T.0' : 5.0}),
}
Materials
Materials are used to define constitutive parameters (e.g. stiffness, permeability, or viscosity), and other non-field
arguments of terms (e.g. known traction or volume forces). Depending on a particular term, the parameters can be
constants, functions defined over FE mesh nodes, functions defined in the elements, etc.
Example:
material = {
'm' : ({'val' : [0.0, -1.0, 0.0]},),
'm2' : 'get_pars',
'm3' : (None, 'get_pars'), # Same as the above line.
}
The functions for defining material parameters can work in two modes, distinguished by the mode argument. The two
modes are ‘qp’ and ‘special’. The first mode is used for usual functions that define parameters in quadrature points
(hence ‘qp’), while the second one can be used for special values like various flags.
The shape and type of data returned in the ‘special’ mode can be arbitrary (depending on the term used). On the other
hand, in the ‘qp’ mode all the data have to be numpy float64 arrays with shape (n_coor, n_row, n_col), where n_coor
is the number of quadrature points given by the coors argument, n_coor = coors.shape[0], and (n_row, n_col) is the
shape of a material parameter in each quadrature point. For example, for scalar parameters, the shape is (n_coor, 1, 1).
The shape is determined by each term.
Example:
38 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
functions = {
'get_pars' : (get_pars,),
}
If a material parameter has the same value in all quadrature points, than it is not necessary to repeat the constant and
the array can be with shape (1, n_row, n_col).
Examples
equations = {
'Temperature' : """dw_laplace.i.Omega( coef.val, s, t ) = 0"""
}
equations = {
'Temperature' : """dw_laplace.2.Omega( coef.val, s, t ) = 0"""
}
equations = {
'Temperature' : """dw_laplace.a.Omega( coef.val, s, t ) = 0"""
}
• Navier-Stokes equations:
equations = {
'balance' :
"""+ dw_div_grad.i2.Omega( fluid.viscosity, v, u )
+ dw_convect.i2.Omega( v, u )
- dw_stokes.i1.Omega( v, p ) = 0""",
'incompressibility' :
"""dw_stokes.i1.Omega( u, q ) = 0""",
}
Configuring Solvers
In SfePy, a non-linear solver has to be specified even when solving a linear problem. The linear problem is/should be
then solved in one iteration of the nonlinear solver.
Linear and nonlinear solver:
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton',
{'i_max' : 1}),
}
Solver selection:
options = {
'nls' : 'newton',
'ls' : 'ls',
}
For the case that a chosen linear solver is not available, it is possible to define the fallback option of the chosen solver
which specifies a possible alternative:
solvers = {
'ls': ('ls.mumps', {'fallback': 'ls2'}),
'ls2': ('ls.scipy_umfpack', {}),
'newton': ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
Another possibility is to use a “virtual” solver that ensures an automatic selection of an available solver, see Virtual
Linear Solvers with Automatic Selection.
Functions
Functions are a way of customizing SfePy behavior. They make it possible to define material properties, boundary
conditions, parametric sweeps, and other items in an arbitrary manner. Functions are normal Python functions declared
in the Problem Definition file, so they can invoke the full power of Python. In order for SfePy to make use of the
functions, they must be declared using the function keyword. See the examples below, and also the corresponding
sections above.
Examples
40 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
functions = {
'get_circle' : (get_circle,),
}
functions = {
'get_p_edge' : (get_p_edge,),
}
ebcs = {
'p' : ('Gamma', {'p.0' : 'get_p_edge'}),
}
The values can be given by a function of time, coordinates and possibly other data, for example:
ebcs = {
'f1' : ('Gamma1', {'u.0' : 'get_ebc_x'}),
'f2' : ('Gamma2', {'u.all' : 'get_ebc_all'}),
}
functions = {
'get_ebc_x' : (lambda ts, coors, bc, problem, **kwargs:
get_ebc_x(coors, 5.0),),
'get_ebc_all' : (lambda ts, coors, bc, problem, **kwargs:
get_ebc_all(ts, coors),),
}
Note that when setting more than one component as in get_ebc_all() above, the function should return either
an array of shape (coors.shape[0], n_components), or the same array flattened to 1D row-by-row (i.e. node-by-
node), where n_components corresponds to the number of components in the boundary condition definition. For
example, with ‘u.[0, 1]’, n_components is 2.
• function for defining usual material parameters:
functions = {
'get_pars' : (get_pars,),
}
The keyword arguments contain both additional use-specified arguments, if any, and the following: equations,
term, problem, for cases when the function needs access to the equations, problem, or term instances that
requested the parameters that are being evaluated. The full signature of the function is:
def get_pars(ts, coors, mode=None,
equations=None, term=None, problem=None, **kwargs)
functions = {
'get_pars1' : (lambda ts, coors, mode=None, **kwargs:
get_pars_special(ts, coors, mode,
extra_arg='hello!'),),
}
if mode == 'special':
val = coors[:,1]
val.shape = (coors.shape[0], 1, 1)
42 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
return out
functions = {
'get_pars_both' : (get_pars_both,),
}
functions = {
'get_load_variable' : (get_load_variable,)
}
Miscellaneous
The options can be used to select solvers, output file format, output directory, to register functions to be called at various
phases of the solution (the hooks), and for other settings.
Additional options (including solver selection):
options = {
# int >= 0, uniform mesh refinement level
'refinement_level : 0',
# save a restart file for each time step, only the last computed time
# step restart file is kept.
'save_restart' : -1,
• post_process_hook enables computing derived quantities, like stress or strain, from the primary unknown
44 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Equations in SfePy are built using terms, which correspond directly to the integral forms of weak formulation of a
problem to be solved. As an example, let us consider the Laplace equation in time interval 𝑡 ∈ [0, 𝑡final ]:
𝜕𝑇
+ 𝑐∆𝑇 = 0 in Ω, 𝑇 (𝑡) = 𝑇¯(𝑡) on Γ . (1.5)
𝜕𝑡
The weak formulation of (1.5) is: Find 𝑇 ∈ 𝑉 , such that
∫︁ ∫︁
𝜕𝑇
𝑠 + 𝑐 ∇𝑇 : ∇𝑠 = 0, ∀𝑠 ∈ 𝑉0 , (1.6)
Ω 𝜕𝑡 Ω
where we assume no fluxes over 𝜕Ω ∖ Γ. In the syntax used in SfePy input files, this can be written as:
which directly corresponds to the discrete version of (1.6): Find 𝑇 ∈ 𝑉ℎ , such that
∫︁ ∫︁
𝜕𝑇
𝑠𝑇 ( 𝜑𝑇 𝜑) + 𝑠𝑇 ( 𝑐 𝐺𝑇 𝐺)𝑇 = 0, ∀𝑠 ∈ 𝑉ℎ0 ,
Ωℎ 𝜕𝑡 Ωℎ
where 𝑢 ≈ 𝜑𝑢, ∇𝑢 ≈ 𝐺𝑢 for 𝑢 ∈ {𝑠, 𝑇 }. The integrals over the discrete domain Ωℎ are approximated by a numerical
quadrature, that is named i in our case.
where <i> denotes an integral name (i.e. a name of numerical quadrature to use) and <r> marks a region (domain
of the integral). In the following, <virtual> corresponds to a test function, <state> to a unknown function and
<parameter> to a known function arguments.
When solving, the individual terms in equations are evaluated in the ‘weak’ mode. The evaluation modes are described
in the next section.
• ‘eval’ : The evaluation mode integrates the term (= integral) over a region. The result has the same dimension
as the quantity being integrated. This mode can be used, for example, to compute some global quantities during
postprocessing such as fluxes or total values of extensive quantities (mass, volume, energy, . . . ).
• ‘el_eval’ : The element evaluation mode results in an array of a quantity integrated over each element of a region.
• ‘el_avg’ : The element average mode results in an array of a quantity averaged in each element of a region. This
is the mode for postprocessing.
• ‘qp’ : The quadrature points mode results in an array of a quantity interpolated into quadrature points of each
element in a region. This mode is used when further point-wise calculations with the result are needed. The
same element type and number of quadrature points in each element are assumed.
Not all terms support all the modes - consult the documentation of the individual terms. There are, however, certain
naming conventions:
• ‘dw_*’ terms support ‘weak’ mode
• ‘dq_*’ terms support ‘qp’ mode
• ‘d_*’, ‘di_*’ terms support ‘eval’ and ‘el_eval’ modes
• ‘ev_*’ terms support ‘eval’, ‘el_eval’, ‘el_avg’ and ‘qp’ modes
Note that the naming prefixes are due to history when the mode argument to Problem.evaluate() and Term.
evaluate() was not available. Now they are often redundant, but are kept around to indicate the evaluation purpose
of each term.
Several examples of using the Problem.evaluate() function are shown below.
A solution to equations given in a problem description file is given by the variables of the ‘unknown field’ kind, that
are set in the solution procedure. By default, those are the only values that are stored into a results file. The solution
postprocessing allows computing additional, derived, quantities, based on the primary variables values, as well as any
other quantities to be stored in the results.
Let us illustrate this using several typical examples. Let us assume that the postprocessing function is
called ‘post_process()’, and is added to options as discussed in Miscellaneous, see ‘post_process_hook’ and
‘post_process_hook_final’. Then:
• compute stress and strain given the displacements (variable u):
Parameters
----------
out : dict
The output dictionary, where this function will store additional
data.
problem : Problem instance
The current Problem instance.
variables : Variables instance
The computed state, containing FE coefficients of all the unknown
variables.
extend : bool
(continues on next page)
46 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Returns
-------
out : dict
The updated output dictionary.
"""
from sfepy.base.base import Struct
return out
return out
mu = pb.evaluate('ev_integrate_mat.2.Omega(nonlinear.mu, u)',
mode='el_avg', copy_materials=False, verbose=False)
out['mu'] = Struct(name='mu', mode='cell', data=mu, dofs=None)
return out
volume = problem.evaluate('ev_volume.2.Omega(u)')
1.4.7 Probing
Probing applies interpolation to output the solution along specified paths. There are two ways of probing:
• VTK probes: It is the simple way of probing using the ‘post_process_hook’. It generates matplotlib figures
with the probing results and previews of the mesh with the probe paths. See Primer or linear_elasticity-its2D_5
example.
• SfePy probes: As mentioned in Miscellaneous, it relies on defining two additional functions, namely the
‘gen_probes’ function, that should create the required probes (see sfepy.discrete.probes), and the
‘probe_hook’ function that performs the actual probing of the results for each of the probes. This function can re-
turn the probing results, as well as a handle to a corresponding matplotlib figure. See linear_elasticity/its2D_4.py
for additional explanation.
Using sfepy.discrete.probes allows correct probing of fields with the approximation order greater than one,
see Interactive Example in Primer or linear_elasticity/its2D_interactive.py for an example of interactive use.
The following postprocessing functions based on the VTK filters are available:
• ‘get_vtk_surface’: extract mesh surface
• ‘get_vtk_edges’: extract mesh edges
• ‘get_vtk_by_group’: extract domain by a material ID
• ‘tetrahedralize_vtk_mesh’: 3D cells are converted to tetrahedral meshes, 2D cells to triangles
The following code demonstrates the use of the postprocessing filters:
mesh = problem.domain.mesh
mesh_name = mesh.name[mesh.name.rfind(osp.sep) + 1:]
matrix_surf = get_vtk_surface(matrix)
matrix_surf_tri = tetrahedralize_vtk_mesh(matrix_surf)
write_vtk_to_file('%s_mat1_surface.vtk' % mesh_name, matrix_surf_tri)
matrix_edges = get_vtk_edges(matrix)
write_vtk_to_file('%s_mat1_edges.vtk' % mesh_name, matrix_edges)
48 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
1.4.9 Solvers
This section describes the time-stepping, nonlinear, linear, eigenvalue and optimization solvers available in SfePy.
There are many internal and external solvers in the sfepy.solvers package that can be called using a uniform interface.
Time-stepping solvers
All PDEs that can be described in a problem description file are solved internally by a time-stepping solver. This holds
even for stationary problems, where the default single-step solver ('ts.stationary') is created automatically. In this
way, all problems are treated in a uniform way. The same holds when building a problem interactively, or when writing
a script, whenever the Problem.solve() function is used for a problem solution.
The following solvers are available:
• ts.adaptive: Implicit time stepping solver with an adaptive time step.
• ts.bathe: Solve elastodynamics problems by the Bathe method.
• ts.euler: Simple forward euler method
• ts.generalized_alpha: Solve elastodynamics problems by the generalized 𝛼 method.
• ts.multistaged: Explicit time stepping solver with multistage solve_step method
• ts.newmark: Solve elastodynamics problems by the Newmark method.
• ts.runge_kutta_4: Classical 4th order Runge-Kutta method,
• ts.simple: Implicit time stepping solver with a fixed time step.
• ts.stationary: Solver for stationary problems without time stepping.
• ts.tvd_runge_kutta_3: 3rd order Total Variation Diminishing Runge-Kutta method
• ts.velocity_verlet: Solve elastodynamics problems by the velocity-Verlet method.
See sfepy.solvers.ts_solvers for available time-stepping solvers and their options.
Nonlinear Solvers
Almost every problem, even linear, is solved in SfePy using a nonlinear solver that calls a linear solver in each iteration.
This approach unifies treatment of linear and non-linear problems, and simplifies application of Dirichlet (essential)
boundary conditions, as the linear system computes not a solution, but a solution increment, i.e., it always has zero
boundary conditions.
The following solvers are available:
• nls.newton: Solves a nonlinear system 𝑓 (𝑥) = 0 using the Newton method.
• nls.oseen: The Oseen solver for Navier-Stokes equations.
• nls.petsc: Interface to PETSc SNES (Scalable Nonlinear Equations Solvers).
• nls.scipy_broyden_like: Interface to Broyden and Anderson solvers from scipy.optimize.
• nls.semismooth_newton: The semi-smooth Newton method.
See sfepy.solvers.nls, sfepy.solvers.oseen and sfepy.solvers.semismooth_newton for all available
nonlinear solvers and their options.
Linear Solvers
Choosing a suitable linear solver is key to solving efficiently stationary as well as transient PDEs. SfePy allows using
a number of external solvers with a unified interface.
The following solvers are available:
• ls.cm_pb: Conjugate multiple problems.
• ls.mumps: Interface to MUMPS solver.
• ls.mumps_par: Interface to MUMPS parallel solver.
• ls.petsc: PETSc Krylov subspace solver.
• ls.pyamg: Interface to PyAMG solvers.
• ls.pyamg_krylov: Interface to PyAMG Krylov solvers.
• ls.schur_mumps: Mumps Schur complement solver.
• ls.scipy_direct: Direct sparse solver from SciPy.
• ls.scipy_iterative: Interface to SciPy iterative solvers.
• ls.scipy_superlu: SuperLU - direct sparse solver from SciPy.
• ls.scipy_umfpack: UMFPACK - direct sparse solver from SciPy.
See sfepy.solvers.ls for all available linear solvers and their options.
A “virtual” solver can be used in case it is not clear which external linear solvers are available. Each “virtual” solver
selects the first available solver from a pre-defined list.
The following solvers are available:
• ls.auto_direct: The automatically selected linear direct solver.
• ls.auto_iterative: The automatically selected linear iterative solver.
See sfepy.solvers.auto_fallback for all available virtual solvers.
50 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Optimization Solvers
The PETSc-based nonlinear equations solver 'nls.petsc' and linear system solver 'ls.petsc' can be used for
parallel computations, together with the modules in sfepy.parallel package. This feature is very preliminary, and can
be used only with the commands for interactive use - problem description files are not supported (yet). The key module
is sfepy.parallel.parallel that takes care of the domain and field DOFs distribution among parallel tasks, as well
as parallel assembling to PETSc vectors and matrices.
• The partitioning of the domain and fields DOFs is not done in parallel and all tasks need to load the whole mesh
and define the global fields - those must fit into memory available to each task.
• While all KSP and SNES solver are supported, in principle, most of their options have to be passed using the
command-line parameters of PETSc - they are not supported yet in the SfePy solver parameters.
• There are no performance statistics yet. The code was tested on a single multi-cpu machine only.
• The global solution is gathered to task 0 and saved to disk serially.
• The vertices of surface region selector does not work in parallel, because the region definition is applied
to a task-local domain.
Examples
The examples demonstrating the use parallel problem solving in SfePy are:
• diffusion/poisson_parallel_interactive.py
• multi_physics/biot_parallel_interactive.py
See their help messages for further information.
Isogeometric analysis (IGA) is a recently developed computational approach that allows using the NURBS-based do-
main description from CAD design tools also for approximation purposes similar to the finite element method.
The implementation is SfePy is based on Bezier extraction of NURBS as developed in1 . This approach allows reusing
the existing finite element assembling routines, as still the evaluation of weak forms occurs locally in “elements” and
the local contributions are then assembled to the global system.
Current Implementation
The IGA code is still very preliminary and some crucial components are missing. The current implementation is also
very slow, as it is in pure Python.
The following already works:
• single patch tensor product domain support in 2D and 3D
• region selection based on topological Bezier mesh, see below
• Dirichlet boundary conditions using projections for non-constant values
• evaluation in arbitrary point in the physical domain
• both scalar and vector volume terms work
• term integration over the whole domain as well as a volume subdomain
• simple linearization (output file generation) based on sampling the results with uniform parametric vectors
• basic domain generation with script/gen_iga_patch.py based on igakit
The following is not implemented yet:
• tests
• theoretical convergence rate verification
• surface terms
• other boundary conditions
• proper (adaptive) linearization for post-processing
• support for multiple NURBS patches
Domain Description
The domain description is in custom HDF5-based files with .iga extension. Such a file contains:
• NURBS patch data (knots, degrees, control points and weights). Those can either be generated using igakit,
created manually or imported from other tools.
• Bezier extraction operators and corresponding DOF connectivity (computed by SfePy).
• Bezier mesh control points, weights and connectivity (computed by SfePy).
The Bezier mesh is used to create a topological Bezier mesh - a subset of the Bezier mesh containing the Bezier
element corner vertices only. Those vertices are interpolatory (are on the exact geometry) and so can be used for region
selections.
1 Michael J. Borden, Michael A. Scott, John A. Evans, Thomas J. R. Hughes: Isogeometric finite element data structures based on Bezier
extraction of NURBS, Institute for Computational Engineering and Sciences, The University of Texas at Austin, Austin, Texas, March 2010.
52 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Region Selection
The domain description files contain vertex sets for regions corresponding to the patch sides, named 'xiIJ', where I
is the parametric axis (0, 1, or 2) and J is 0 or 1 for the beginning and end of the axis knot span. Other regions can be
defined in the usual way, using the topological Bezier mesh entities.
Examples
fields = {
't1' : ('real', 1, 'Omega', None, 'H1', 'iga'),
't2' : ('real', 1, 'Omega', 'iga', 'H1', 'iga'),
't3' : ('real', 1, 'Omega', 'iga+%d', 'H1', 'iga'),
}
The approximation order in the first definition is None as it is given by the NURBS degrees in the domain
description. The second definition is equivalent to the first one. The third definition, where %d should be a non-
negative integer, illustrates how to increase the field’s NURBS degrees (while keeping the continuity) w.r.t. the
domain NURBS description. It is applied in the navier_stokes/navier_stokes2d_iga.py example to the velocity
field.
1.5 Examples
This section contains domain-specific tutorials as well as the automatically generated list of the standard examples that
come with SfePy.
1.5.1 Primer
Introduction
This primer presents a step-by-step walk-through of the process to solve a simple mechanics problem. The typical
process to solve a problem using SfePy is followed: a model is meshed, a problem definition file is drafted, SfePy is run
to solve the problem and finally the results of the analysis are visualised.
1.5. Examples 53
SfePy Documentation, Release version: 2022.2
Problem statement
A popular test to measure the tensile strength of concrete or asphalt materials is the indirect tensile strength (ITS) test
pictured below. In this test a cylindrical specimen is loaded across its diameter to failure. The test is usually run by
loading the specimen at a constant deformation rate of 50 mm/minute (say) and measuring the load response. When
the tensile stress that develops in the specimen under loading exceeds its tensile strength then the specimen will fail.
To model this problem using finite elements the indirect tensile test can be simplified to represent a diametrically point
loaded disk as shown in the schematic.
The tensile and compressive stresses that develop in the specimen as a result of the point loads P are a function of the
diameter 𝐷 and thickness 𝑡 of the cylindrical specimen. At the centre of the specimen, the compressive stress is 3 times
the tensile stress and the analytical formulation for these are, respectively:
2𝑃
𝜎𝑡 = (1.7)
𝜋𝑡𝐷
6𝑃
𝜎𝑐 = (1.8)
𝜋𝑡𝐷
These solutions may be approximated using finite element methods. To solve this problem using SfePy the first step is
meshing a suitable model.
Meshing
Assuming plane strain conditions, the indirect tensile test may be modelled using a 2D finite element mesh. Further-
more, the geometry of the model is symmetrical about the x- and y-axes passing through the centre of the circle. To
take advantage of this symmetry only one quarter of the 2D model will be meshed and boundary conditions will be
established to indicate this symmetry. The meshing program Gmsh is used here to very quickly mesh the model. Follow
these steps to model the ITS:
1. The ITS specimen has a diameter of 150 mm. Using Gmsh add three new points (geometry elementary entities)
at the following coordinates: (0.00.0), (75.0, 0.0) and (0.0, 75.0).
2. Next add two straight lines connecting the points.
54 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
3. Next add a Circle arc connecting two of the points to form the quarter circle segment.
4. Still under Geometry add a ruled surface.
5. With the geometry of the model defined, add a mesh by clicking on the 2D button under the Mesh functions.
The figures that follow show the various stages in the model process.
That’s the meshing done. Save the mesh in a format that SfePy recognizes. For now use the medit .mesh format e.g.
its2D.mesh.
Hint: Check the drop down in the Save As dialog for the different formats that Gmsh can save to.
1.5. Examples 55
SfePy Documentation, Release version: 2022.2
If you open the its2D.mesh file using a text editor you’ll notice that Gmsh saves the mesh in a 3D format and includes
some extra geometry items that should be deleted. Reformatted the mesh file to a 2D format and delete the Edges block.
Note that when you do this the file cannot be reopened by Gmsh so it is always a good idea to also save your meshes in
Gmsh’s native format as well (Shift-Ctrl-S). Click here to download the reformatted mesh file that will be used in the
tutorial.
You’ll notice that the mesh contains 55 vertices (nodes) and 83 triangle elements. The mesh file provides the coordinates
of the nodes and the element connectivity. It is important to note that node and element numbering in SfePy start at 0
and not 1 as is the case in Gmsh and some other meshing programs.
To view .mesh files you can use a demo of medit. After loading your mesh file with medit you can see the node and
element numbering by pressing P and F respectively. The numbering in medit starts at 1 as shown. Thus the node
at the center of the model in SfePy numbering is 0, and elements 76 and 77 are connected to this node. Node and
element numbers can also be viewed in Gmsh – under the mesh option under the Visibility tab enable the node and
surface labels. Note that the surface labels as numbered in Gmsh follow on from the line numbering. So to get the
corresponding element number in SfePy you’ll need to subtract the number of lines in the Gmsh file + 1. Confused yet?
Luckily, SfePy provides some useful mesh functions to indicate which elements are connected to which nodes. Nodes
and elements can also be identified by defining regions, which is addressed later.
Another open source python option to view .mesh files is the appropriately named Python Mesh Viewer.
The next step in the process is coding the SfePy problem definition file.
Problem description
The programming of the problem description file is well documented in the SfePy User’s Guide. The problem descrip-
tion file used in the tutorial follows:
r"""
Diametrically point loaded 2-D disk. See :ref:`sec-primer`.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
56 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
from sfepy.mechanics.matcoefs import stiffness_from_youngpoisson
from sfepy.discrete.fem.utils import refine_mesh
from sfepy import data_dir
# Fix the mesh file name if you run this file outside the SfePy directory.
filename_mesh = data_dir + '/meshes/2d/its2D.mesh'
refinement_level = 0
filename_mesh = refine_mesh(filename_mesh, refinement_level)
output_dir = '.' # set this to a valid directory you have write access to
options = {
'output_dir' : output_dir,
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Bottom' : ('vertices in (y < 0.001)', 'facet'),
'Top' : ('vertex 2', 'vertex'),
}
materials = {
'Asphalt' : ({'D': stiffness_from_youngpoisson(2, young, poisson)},),
'Load' : ({'.val' : [0.0, -1000.0]},),
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
equations = {
'balance_of_forces' :
"""dw_lin_elastic.2.Omega(Asphalt.D, v, u)
= dw_point_load.0.Top(Load.val, v)""",
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
(continues on next page)
1.5. Examples 57
SfePy Documentation, Release version: 2022.2
ebcs = {
'XSym' : ('Bottom', {'u.1' : 0.0}),
'YSym' : ('Left', {'u.0' : 0.0}),
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-6,
}),
}
Download the Problem description file and open it in your favourite Python editor. Note that you may wish to
change the location of the output directory to somewhere on your drive. You may also need to edit the mesh file name.
For the analysis we will assume that the material of the test specimen is linear elastic and isotropic. We define two
material constants i.e. Young’s modulus and Poisson’s ratio. The material is assumed to be asphalt concrete having a
Young’s modulus of 2,000 MPa and a Poisson’s ration of 0.4.
Note: Be consistent in your choice and use of units. In the tutorial we are using Newton (N), millimeters (mm) and
megaPascal (MPa). The sfepy.mechanics.units module might help you in determining which derived units correspond
to given basic units.
The following block of code defines regions on your mesh:
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Bottom' : ('vertices in (y < 0.001)', 'facet'),
'Top' : ('vertex 2', 'vertex'),
}
ebcs = {
'XSym' : ('Bottom', {'u.1' : 0.0}),
'YSym' : ('Left', {'u.0' : 0.0}),
}
Now the power of the regions entity becomes apparent. To ensure symmetry about the x-axis, the vertical or y-
displacement of the nodes in the ‘Bottom’ region are prevented or set to zero. Similarly, for symmetry about the
y-axis, any horizontal or displacement in the x-direction of the nodes in the ‘Left’ region or y-axis is prevented.
The load is specified in terms of the ‘Load’ material as follows:
58 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
materials = {
'Asphalt' : ({
'lam' : lame_from_youngpoisson(young, poisson)[0],
'mu' : lame_from_youngpoisson(young, poisson)[1],
},),
'Load' : ({'.val' : [0.0, -1000.0]},),
}
Note the dot in ‘.val’ – this denotes a special material value, i.e., a value that is not to be evaluated in quadrature points.
The load is then applied in equations using the ‘dw_point_load.0.Top(Load.val, v)’ term in the topmost node (region
‘Top’).
We provided the material constants in terms of Young’s modulus and Poisson’s ratio, but the linear elastic isotropic
equation used requires as input Lamé’s parameters. The lame_from_youngpoisson() function is thus used for conver-
sion. Note that to use this function it was necessary to import the function into the code, which was done up front:
Hint: Check out the sfepy.mechanics.matcoefs module for other useful material related functions.
That’s it – we are now ready to solve the problem.
Running SfePy
One option to solve the problem is to run the SfePy simple.py script from the command line:
./simple.py its2D_1.py
Note: For the purpose of this tutorial it is assumed that the problem description file (its2D_1.py) is in the same
directory as the simple.py script. If you have the its2D_1.py file in another directory then make sure you include the
path to this file as well.
SfePy solves the problem and outputs the solution to the output path (output_dir) provided in the script. The output file
will be in the VTK format by default if this is not explicitly specified and the name of the output file will be the same
as that used for the mesh file except with the ‘.vtk’ extension i.e. its2D.vtk.
The VTK format is an ASCII format. Open the file using a text editor. You’ll notice that the output file includes separate
sections:
• POINTS (these are the model nodes),
• CELLS (the model element connectivity),
• VECTORS (the node displacements in the x-, y- and z- directions).
SfePy provides a script (resview.py) to quickly view the solution. To run this script you need to have pyvista installed.
From the command line issue the following (assuming the correct paths):
./resview.py its2D.vtk -2
The resview.py script generates the image shown below, which shows by default the displacements in the model as
arrows and their magnitude as color scale. Cool, but we are more interested in the stresses. To get these we need to
modify the problem description file and do some post-processing.
1.5. Examples 59
SfePy Documentation, Release version: 2022.2
Post-processing
SfePy provides functions to calculate stresses and strains. We’ll include a function to calculate these and update the
problem material definition and options to call this function as a post_process_hook(). Save this file as its2D_2.py.
r"""
Diametrically point loaded 2-D disk with postprocessing. See
:ref:`sec-primer`.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
ev = pb.evaluate
strain = ev('ev_cauchy_strain.2.Omega(u)', mode='el_avg')
stress = ev('ev_cauchy_stress.2.Omega(Asphalt.D, u)', mode='el_avg',
copy_materials=False)
60 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
return out
asphalt = materials['Asphalt'][0]
asphalt.update({'D' : stiffness_from_youngpoisson(2, young, poisson)})
options.update({'post_process_hook' : 'stress_strain',})
The updated file imports all of the previous definitions in its2D_1.py. The stress function (de_cauchy_stress())
requires as input the stiffness tensor – thus it was necessary to update the materials accordingly. The problem options
were also updated to call the stress_strain() function as a post_process_hook().
Run SfePy to solve the updated problem and view the solution (assuming the correct paths):
./simple.py its2D_2.py
./resview.py its2D.vtk -2 --max-plots 2
In addition to the node displacements, the VTK output shown below now also includes the stresses and strains averaged
in the elements:
Remember the objective was to determine the stresses at the centre of the specimen under a load 𝑃 . The solution as
currently derived is expressed in terms of a global displacement vector 𝑢. The global (residual) force vector 𝑓 is a
function of the global displacement vector and the global stiffness matrix 𝐾 as: 𝑓 = 𝐾𝑢. Let’s determine the force
vector interactively.
In addition to solving problems using the simple.py script you can also run SfePy interactively (we will use IPython
interactive shell in following examples).
In the SfePy top-level directory run
ipython
1.5. Examples 61
SfePy Documentation, Release version: 2022.2
The problem is solved and the problem definition and solution are provided in the pb and variables variables respec-
tively. The solution, or in this case, the global displacement vector 𝑢, contains the x- and y-displacements at the nodes
in the 2D model:
In [3]: u = variables()
In [4]: u
Out[4]:
array([ 0. , 0. , 0.37376671, ..., -0.19923848,
0.08820237, -0.11201528])
In [5]: u.shape
Out[5]: (110,)
In [7]: u
Out[7]:
array([[ 0. , 0. ],
[ 0.37376671, 0. ],
[ 0. , -1.65318152],
...,
[ 0.08716448, -0.23069047],
[ 0.27741356, -0.19923848],
[ 0.08820237, -0.11201528]])
Note: We have used the fact, that the state vector contains only one variable (u). In general, the following can be used:
In [8]: u = variables.get_state_parts()['u']
In [9]: u
Out[9]:
array([[ 0. , 0. ],
[ 0.37376671, 0. ],
[ 0. , -1.65318152],
...,
[ 0.08716448, -0.23069047],
[ 0.27741356, -0.19923848],
[ 0.08820237, -0.11201528]])
Both variables() and variables.get_state_parts() return a view of the DOF vector, that is why in Out[8] the vector is
reshaped according to Out[6]. It is thus possible to set the values of state variables by manipulating the state vector,
but shape changes such as the one above are not advised (see In [15] below) - work on a copy instead.
From the above it can be seen that u holds the displacements at the 55 nodes in the model and that the displacement
at node 2 (on which the load is applied) is (0, −1.65318152). The global stiffness matrix is saved in pb as a sparse
matrix:
In [10]: K = pb.mtx_a
62 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
In [12]: print(K)
(0, 0) 2443.95959851
(0, 7) -2110.99917491
(0, 14) -332.960423597
(0, 15) 1428.57142857
(1, 1) 2443.95959852
(1, 13) -2110.99917492
(1, 32) 1428.57142857
(1, 33) -332.960423596
(2, 2) 4048.78343529
(2, 3) -1354.87004384
(2, 52) -609.367453538
(2, 53) -1869.0018791
(2, 92) -357.41672785
(2, 93) 1510.24654193
(3, 2) -1354.87004384
(3, 3) 4121.03202907
(3, 4) -1696.54911732
(3, 48) 76.2400806561
(3, 49) -1669.59247304
(3, 52) -1145.85294856
(3, 53) 2062.13955556
(4, 3) -1696.54911732
(4, 4) 4410.17902905
(4, 5) -1872.87344838
(4, 42) -130.515009576
: :
(91, 81) -1610.0550578
(91, 86) -199.343680224
(91, 87) -2330.41406097
(91, 90) -575.80373408
(91, 91) 7853.23899229
(92, 2) -357.41672785
(92, 8) 1735.59411191
(92, 50) -464.976034459
(92, 51) -1761.31189004
(92, 52) -3300.45367361
(92, 53) 1574.59387937
(92, 88) -250.325600254
(92, 89) 1334.11823335
(92, 92) 9219.18643706
(92, 93) -2607.52659081
(93, 2) 1510.24654193
(93, 8) -657.361661955
(93, 50) -1761.31189004
(93, 51) 54.1134516246
(93, 52) 1574.59387937
(continues on next page)
1.5. Examples 63
SfePy Documentation, Release version: 2022.2
In [13]: K.shape
Out[13]: (94, 94)
One would expect the shape of the global stiffness matrix 𝐾 to be (110, 110) i.e. to have the same number of rows and
columns as u. This matrix has been reduced by the fixed degrees of freedom imposed by the boundary conditions set
at the nodes on symmetry axes. To restore the matrix, temporarily remove the imposed boundary conditions:
In [14]: pb.remove_bcs()
In [15]: f = pb.evaluator.eval_residual(u)
ValueError: shape mismatch: value array of shape (55,2) could not be broadcast to␣
˓→indexing result of shape (110,)
In [17]: f = pb.evaluator.eval_residual(u)
In [18]: f.shape
Out[18]: (110,)
In [19]: f
Out[19]:
array([ -4.73618436e+01, 1.42752386e+02, 1.56921124e-13, ...,
-2.06057393e-13, 2.13162821e-14, -2.84217094e-14])
Remember to restore the original boundary conditions previously removed in step [14]:
In [20]: pb.time_update()
To view the residual force vector, we can save it to a VTK file. This requires setting f to (a copy of) the variables as
follows:
Running the resview.py script on file.vtk displays the average nodal forces as shown below:
64 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Great, we have an almost zero residual vertical load or force apparent at node 2 i.e. -1.13686838e-13 Newton. Let us
now check the stress at node 0, the centre of the specimen.
Previously we had calculated the stresses in the model but these were averaged from those calculated at Gauss quadrature
points within the elements. It is possible to provide custom integrals to allow the calculation of stresses with the Gauss
quadrature points at the element nodes. This will provide us a more accurate estimate of the stress at the centre of the
specimen located at node 0. The code below outlines one way to achieve this.
r"""
Diametrically point loaded 2-D disk with nodal stress calculation. See
:ref:`sec-primer`.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import print_function
from __future__ import absolute_import
from sfepy.examples.linear_elasticity.its2D_1 import *
1.5. Examples 65
SfePy Documentation, Release version: 2022.2
gdata = geometry_data['2_3']
nc = len(gdata.coors)
# Point load.
mat = pb.get_materials()['Load']
P = 2.0 * mat.get_data('special', 'val')[1]
print('\n==================================================================')
print('Given load = %.2f N' % -P)
print('\nAnalytical solution')
print('===================')
print('Horizontal tensile stress = %.5e MPa/mm' % (-2.*P/(nm.pi*150.)))
print('Vertical compressive stress = %.5e MPa/mm' % (-6.*P/(nm.pi*150.)))
print('\nFEM solution')
print('============')
print('Horizontal tensile stress = %.5e MPa/mm' % (svar()[0]))
print('Vertical compressive stress = %.5e MPa/mm' % (-svar()[1]))
print('==================================================================')
return out
asphalt = materials['Asphalt'][0]
asphalt.update({'D' : stiffness_from_youngpoisson(2, young, poisson)})
options.update({'post_process_hook' : 'nodal_stress',})
integrals = {
'ivn' : ('custom', gdata.coors, [gdata.volume / nc] * nc),
}
The output:
66 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
==================================================================
Given load = 2000.00 N
Analytical solution
===================
Horizontal tensile stress = 8.48826e+00 MPa/mm
Vertical compressive stress = 2.54648e+01 MPa/mm
FEM solution
============
Horizontal tensile stress = 7.57220e+00 MPa/mm
Vertical compressive stress = 2.58660e+01 MPa/mm
==================================================================
Not bad for such a coarse mesh! Re-running the problem using a finer mesh provides a more accurate solution:
==================================================================
Given load = 2000.00 N
Analytical solution
===================
Horizontal tensile stress = 8.48826e+00 MPa/mm
Vertical compressive stress = 2.54648e+01 MPa/mm
FEM solution
============
Horizontal tensile stress = 8.50042e+00 MPa/mm
Vertical compressive stress = 2.54300e+01 MPa/mm
To see how the FEM solution approaches the analytical one, try to play with the uniform mesh refinement level in the
Problem description file, namely lines 25, 26:
refinement_level = 0
filename_mesh = refine_mesh(filename_mesh, refinement_level)
1.5. Examples 67
SfePy Documentation, Release version: 2022.2
Probing
As a bonus for sticking to the end of this tutorial see the following Problem description file that provides SfePy
functions to quickly and neatly probe the solution.
r"""
Diametrically point loaded 2-D disk with postprocessing and probes. See
:ref:`sec-primer`.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
from sfepy.examples.linear_elasticity.its2D_1 import *
import os
from six.moves import range
(continues on next page)
68 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
ev = pb.evaluate
strain = ev('ev_cauchy_strain.2.Omega(u)', mode='el_avg')
stress = ev('ev_cauchy_stress.2.Omega(Asphalt.D, u)', mode='el_avg')
labels = ['%s -> %s' % (p0, p1) for p0, p1 in zip(ps0, ps1)]
probes = []
for ip in range(len(ps0)):
p0, p1 = ps0[ip], ps1[ip]
probes.append('line%d' % ip)
probe.add_line_probe('line%d' % ip, p0, p1, n_point)
plt.subplot(312)
pars, vals = probe(ip, 'cauchy_strain')
for ii in range(vals.shape[1]):
plt.plot(pars, vals[:, ii], label=r'$e_{%s}$' % sym_labels[ii],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy strain')
(continues on next page)
1.5. Examples 69
SfePy Documentation, Release version: 2022.2
plt.subplot(313)
pars, vals = probe(ip, 'cauchy_stress')
for ii in range(vals.shape[1]):
plt.plot(pars, vals[:, ii], label=r'$\sigma_{%s}$' % sym_labels[ii],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy stress')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', prop=fm.FontProperties(size=8))
opts = pb.conf.options
filename_results = os.path.join(opts.get('output_dir'),
'its2D_probe_%s.png' % ip)
fig.savefig(filename_results)
return out
options.update({
'post_process_hook' : 'stress_strain',
})
Probing applies interpolation to output the solution along specified paths. For the tutorial, line probing is done along
the x- and y-axes of the model.
Run SfePy to solve the problem and apply the probes:
./simple.py its2D_5.py
The probing function will generate the following figures that show the displacements, normal stresses and strains as
well as shear stresses and strains along the probe paths. Note that you need matplotlib installed to run this example.
70 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
The probing function also generates previews of the mesh with the probe paths.
Interactive Example
SfePy can be used also interactively by constructing directly the classes that corresponds to the keywords in the problem
description files. The following listing shows a script with the same (and more) functionality as the above examples:
#!/usr/bin/env python
"""
Diametrically point loaded 2-D disk, using commands for interactive use. See
:ref:`sec-primer`.
The script combines the functionality of all the ``its2D_?.py`` examples and
(continues on next page)
1.5. Examples 71
SfePy Documentation, Release version: 2022.2
- material parameters
- displacement field approximation order
- uniform mesh refinement level
In the SfePy top-level directory the following command can be used to get usage
information::
python sfepy/examples/linear_elasticity/its2D_interactive.py -h
"""
from __future__ import absolute_import
import sys
from six.moves import range
sys.path.append('.')
from argparse import ArgumentParser, RawDescriptionHelpFormatter
import numpy as nm
import matplotlib.pyplot as plt
def gen_lines(problem):
"""
Define two line probes.
72 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
labels = ['%s -> %s' % (p0, p1) for p0, p1 in zip(ps0, ps1)]
probes = []
for ip in range(len(ps0)):
p0, p1 = ps0[ip], ps1[ip]
probes.append(LineProbe(p0, p1, n_point))
fig = plt.figure()
plt.clf()
fig.subplots_adjust(hspace=0.4)
plt.subplot(311)
pars, vals = results['u']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$u_{%d}$' % (ic + 1),
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('displacements')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', fontsize=10)
plt.subplot(312)
pars, vals = results['cauchy_strain']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$e_{%s}$' % sym_indices[ic],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy strain')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', fontsize=10)
plt.subplot(313)
pars, vals = results['cauchy_stress']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$\sigma_{%s}$' % sym_indices[ic],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy stress')
plt.xlabel('probe %s' % label, fontsize=8)
(continues on next page)
1.5. Examples 73
SfePy Documentation, Release version: 2022.2
helps = {
'young' : "the Young's modulus [default: %(default)s]",
'poisson' : "the Poisson's ratio [default: %(default)s]",
'load' : "the vertical load value (negative means compression)"
" [default: %(default)s]",
'order' : 'displacement field approximation order [default: %(default)s]',
'refine' : 'uniform mesh refinement level [default: %(default)s]',
'probe' : 'probe the results',
}
def main():
from sfepy import data_dir
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('--version', action='version', version='%(prog)s')
parser.add_argument('--young', metavar='float', type=float,
action='store', dest='young',
default=2000.0, help=helps['young'])
parser.add_argument('--poisson', metavar='float', type=float,
action='store', dest='poisson',
default=0.4, help=helps['poisson'])
parser.add_argument('--load', metavar='float', type=float,
action='store', dest='load',
default=-1000.0, help=helps['load'])
parser.add_argument('--order', metavar='int', type=int,
action='store', dest='order',
default=1, help=helps['order'])
parser.add_argument('-r', '--refine', metavar='int', type=int,
action='store', dest='refine',
default=0, help=helps['refine'])
parser.add_argument('-p', '--probe',
action="store_true", dest='probe',
default=False, help=helps['probe'])
options = parser.parse_args()
output('using values:')
output(" Young's modulus:", options.young)
output(" Poisson's ratio:", options.poisson)
output(' vertical load:', options.load)
output('uniform mesh refinement level:', options.refine)
74 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
if options.refine > 0:
for ii in range(options.refine):
output('refine %d...' % ii)
domain = domain.refine()
output('... %d nodes %d elements'
% (domain.shape.n_nod, domain.shape.n_el))
t1 = Term.new('dw_lin_elastic(Asphalt.D, v, u)',
integral, omega, Asphalt=asphalt, v=v, u=u)
t2 = Term.new('dw_point_load(Load.val, v)',
integral0, top, Load=load, v=v)
eq = Equation('balance', t1 - t2)
eqs = Equations([eq])
ls = AutoDirect({})
nls_status = IndexedStruct()
nls = Newton({}, lin_solver=ls, status=nls_status)
pb = Problem('elasticity', equations=eqs)
pb.set_bcs(ebcs=Conditions([xsym, ysym]))
pb.set_solver(nls)
1.5. Examples 75
SfePy Documentation, Release version: 2022.2
gdata = geometry_data['2_3']
nc = len(gdata.coors)
if options.probe:
# Probe the solution.
probes, labels = gen_lines(pb)
ev = pb.evaluate
order = 2 * (options.order - 1)
strain_qp = ev('ev_cauchy_strain.%d.Omega(u)' % order, mode='qp')
stress_qp = ev('ev_cauchy_stress.%d.Omega(Asphalt.D, u)' % order,
mode='qp', copy_materials=False)
all_results = []
for ii, probe in enumerate(probes):
fig, results = probe_results(u, strain, stress, probe, labels[ii])
fig.savefig('its2D_interactive_probe_%d.png' % ii)
all_results.append(results)
76 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
if __name__ == '__main__':
main()
The script can be run from the SfePy top-level directory, assuming the in-place build, as follows:
python sfepy/examples/linear_elasticity/its2D_interactive.py
The script allows setting several parameters that influence the solution, see:
python sfepy/examples/linear_elasticity/its2D_interactive.py -h
for the complete list. Besides the material parameters, a uniform mesh refinement level and the displacement field
approximation order can be specified. The script demonstrates how to
• project a derived quantity, that is evaluated in quadrature points (e.g. a strain or stress), into a field variable;
• probe the solution defined in the field variables.
Using sfepy.discrete.probes allows correct probing of fields with the approximation order greater than one.
The end.
Introduction
Salome is a powerful open-source tool for generating meshes for numerical simulation and post processing the results.
This is a short tutorial on using Salome as a preprocessor for preparing meshes for use with SfePy.
Tutorial prerequisites
This tutorial assumes that you have a working copy of Salome. It is possible to build Salome from source code.
Fortunately, for the less brave, many pre-compiled binaries for different platforms are available at the Salome download
page. Registration for a free account may be required to download from the preceding site.
In addition, this tutorial assumes you have a working copy of SfePy with MED read support. See the Installation for
help. Note that it is not actually necessary to “install” SfePy; one may run the code from the source directory (see
notation below) after compilation of the C extension modules (again, see the installation notes if you are confused).
1.5. Examples 77
SfePy Documentation, Release version: 2022.2
Salome has its own set of tutorials and community resources. It is suggested you look around on Salome web site to
familiarize yourself with the available resources.
This tutorial follows the EDF Exercise 1 available from the Salome Tutorial Site. Go ahead and complete this tutorial
now. We will use the result from there in the following.
This is the mesh you should end up with:
78 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
In the Salome MESH module, right click on the mesh object Mesh_Partition_Hexa you created in the Salome EDF
Exercise 1 Tutorial and click Export to MED file. Save the file as Mesh_Partition_Hexa.med in your working
directory <work_dir>.
In this tutorial, we will assume that we need to solve a linear elasticity problem on the mesh generated by Salome. Since
the Salome mesh looks a bit like a fish, we will try to simulate the fish waving its tail.
Copy the file <sfepy_root>/sfepy/examples/linear_elasticity/linear_elastic.py to <work_dir>. Use
your favorite python editor to load this file. We will customize this file for our purposes.
Mesh specification
The first thing we have to do is tell SfePy to use our new mesh. Change the line
to
filename_mesh = 'Mesh_Partition_Hexa.med'
Region specification
Next, we have to define sensible Regions for the mesh. We will apply a displacement to the Tail and keep the Top and
Bottom of the fish fixed. Change the lines
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
'SomewhereTop' : ('vertices in (z > 0.017) & (x > 0.03) & (x < 0.07)', 'vertex'),
}
to
regions = {
'Omega' : 'all',
'Tail' : ('vertices in (x < -94)', 'facet'),
'TopFixed' : ('vertices in (z > 9.999) & (x > 54)', 'facet'),
'BotFixed' : ('vertices in (z < 0.001) & (x > 54)', 'facet'),
}
1.5. Examples 79
SfePy Documentation, Release version: 2022.2
Field specification
The Salome mesh uses hexahedral linear order elements; in SfePy notation these are called 3_8, see User’s Guide.
Just keep the lines
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
In this section, we tell SfePy to fix the top and bottom parts of the “head” of the fish and move the tail 10 units to the
side (z direction).
Change the lines
ebcs = {
'Fixed' : ('Left', {'u.all' : 0.0}),
'Displaced' : ('Right', {'u.0' : 0.01, 'u.[1,2]' : 0.0}),
'PerturbedSurface' : ('SomewhereTop', {'u.2' : 0.005}),
}
to
ebcs = {
'TopFixed' : ('TopFixed', {'u.all' : 0.0}),
'BotFixed' : ('BotFixed', {'u.all' : 0.0}),
'Displaced' : ('Tail', {'u.2' : 10, 'u.[0,1]' : 0.0}),
}
Save your changes to linear_elastic.py. Now it’s time to run the SfePy calculation. In your <work_dir> in your
terminal type:
./simple.py linear_elastic.py
This will run the SfePy calculation. Some progress information is printed to your screen and the residual (a measure
of the convergence of the solution) is printed for each iteration of the solver. The solver terminates when this residual
is less than a certain value. It should only take 1 iteration since we are solving a linear problem. The results will be
saved to Mesh_Partition_Hexa.vtk.
Now we can view the results of our work. In your terminal, type:
You should get the plot with the deformed and undeformed meshs. Notice how the fish is bending its tail in response
to the applied displacement.
Now you should be able to use meshes created in Salome with SfePy!
80 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Introduction
There are several open source tools for preparing 2D and 3D finite element meshes like Salome, FreeCAD, Gmsh,
Netgen, etc. Most of them are GUI based geometrical modeling and meshing environments/tools but they also usually
allow using their libraries in user scripts. Some of the above mentioned tools are handy for solid modeling, some
of them are great for meshing. This tutorial shows how to combine solid geometry modeling functions provided by
FreeCAD or OpenSCAD with meshing functions of Gmsh.
The collaboration of modeling, meshing and conversion tools and the workflow are illustrated in the following scheme.
Functionalities of FreeCAD are accessible to Python and can be used to define geometrical models in simple Python
scripts. There is a tutorial related to Python scripting in FreeCAD.
The first step in creating a Python script is to set up a path to the FreeCAD libraries and import all required modules:
1 import sys
2 FREECADPATH = '/usr/lib/freecad/lib/'
3 sys.path.append(FREECADPATH)
4
1.5. Examples 81
SfePy Documentation, Release version: 2022.2
doc = newDocument()
All new objects describing the geometry will be added to this document.
In the following lines a geometrical model of a screwdriver handle will be created. Let’s start by defining a sphere and
a cylinder and join these objects into the one called uni:
1 radius = 0.01
2 height = 0.1
3
Create a polygon, revolve it around the z-axis to create a solid and use the result as the cutting tool applied to uni
object:
Create a cylinder, make a polar array of the cylinder objects and subtract it from the previous result:
82 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Finally, recompute the geometry, export the part to the STEP file and save the document in FreeCAD format (not really
needed for subsequent mesh generation, but may be useful for visualization and geometry check):
1 doc.recompute()
2
3 Part.export([dif3], 'screwdriver_handle.step')
4
5 doc.saveAs('screwdriver_handle.FCStd')
A finite element mesh can be generated directly in FreeCAD using MeshPart module:
1 import MeshPart
2
The meshing function of MeshPart module is limited to triangular grids so it is better to use Gmsh mesh generator
which can provide triangular and quadrilateral meshes in 2D or tetrahedral and hexahedral meshes in 3D. Gmsh allows
to control the meshing process through a wide range of parameters. Meshing by Gmsh will be described in section
Gmsh - generating finite element mesh.
1.5. Examples 83
SfePy Documentation, Release version: 2022.2
The alternative tool for solid geometrical modeling is OpenSCAD - “The Programmers Solid 3D CAD Modeller”.
It has its own description language based on functional programming that is used to construct solid models using
geometrical primitives similar to FreeCAD. Solid geometries can be exported to several file formats including STL and
CSG. OpenSCAD allows solid modeling based on Constructive Solid Geometry (CSG) principles and extrusion of 2D
objects into 3D. The model of a screwdriver handle presented in the previous section can be defined in OpenSCAD by
the following code (screwdriver_handle.scad):
1 radius = 0.01;
2 height = 0.1;
3 $fn = 50;
4
5 difference() {
6 difference() {
7 difference() {
8 union() {
9 cylinder(center=false, h=height, r=radius);
10 sphere(radius);
(continues on next page)
84 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
15 }
16 cylinder(center=false, h=1.1*height, r=0.3*radius);
17 }
18 for (i = [1:6]) {
19 rotate([0, 0, 360/6*i])
20 translate([-1.1*radius, 0.0, -0.2*height])
21 cylinder(center=false, h=1.1*height, r=0.2*radius);
22 }
23 }
To generate a finite element mesh of the solid geometry the model must be exported to a suitable file format. OpenSCAD
has limited export options, but by using FreeCAD import/export functions, it is possible to find a workaround. The
OpenSCAD model can be exported to the CSG file format and FreeCAD can be used as a mesh converter to the STEP
format:
1 import sys
2 sys.path.append('/usr/lib/freecad/lib/')
3 sys.path.append('/usr/lib/freecad/Mod/OpenSCAD/')
4
5 import FreeCAD
6 import Part
7 import importCSG
8
9 importCSG.open('screwdriver_handle.csg')
10 Part.export([FreeCAD.ActiveDocument.Objects[-1]], 'screwdriver_handle.step')
1.5. Examples 85
SfePy Documentation, Release version: 2022.2
Gmsh can create finite element meshes using geometrical models imported from STEP, IGES and BRep files (has to
be compiled with OpenCASCADE support).
The following GEO file imports screwdriver_handle.step file and defines a field controlling the mesh size
(screwdriver_handle.geo):
1 Merge "screwdriver_handle.step";
2
3 Field[1] = MathEval;
4 Field[1].F = "0.002";
5 Background Field = 1;
Now, run Gmsh generator and export the mesh into the MSH format in which all surface and volumetric elements are
stored:
By converting the MSH file into the VTK format using script/convert_mesh.py:
the surface elements are discarded and only the volumetric mesh is preserved.
86 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
that can be described by this Gmsh code, the mesh generator can be called as follows:
This, however is not enough to create a truly 2D mesh - the created mesh vertices still have the third, 𝑧, component
which is equal to zero. In order to remove the third component, use:
Now, in the resulting circle_in_square.h5, each vertex has only two coordinates. Another way of generating the
2D mesh is to use the legacy VTK format as follows:
This is due to the fact that the legacy VTK does not support 2D vertices and so the VTKMeshIO reader tries to detect
the planar geometry by comparing the 𝑧 components to zero - the --2d option of script/convert_mesh.py is not
needed in this case.
Multipart models
Meshing models composed of parts with different material groups is a little bit tricky task. But there are some more or
less general ways of doing that. Here, the method using functions of Gmsh for periodic meshes will be shown.
The screwdriver handle example is extended by adding a screwdriver shank. The new part is composed of a cylinder
trimmed at one end:
1.5. Examples 87
SfePy Documentation, Release version: 2022.2
The handle and shank are exported to the STEP file as two separated parts:
1 doc.recompute()
2
1 Merge "screwdriver_full.step";
2
88 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
9 Field[1] = MathEval;
10 Field[1].F = "0.0015";
11 Background Field = 1;
where the first pair of periodic surfaces corresponds to the common circle faces (bottom of the shank) and the second
pair to the common cylindrical surfaces. See Gmsh Reference manual for details on periodic meshing.
Using the above stated GEO file, Gmsh creates a mesh containing duplicate vertices on the handle/shank interface.
These duplicate vertices can be removed during the conversion to the VTK format by giving --merge (or just -m)
argument to convert_mesh.py script:
In order to extract the cells by the physical groups use the conversion script with --save-per-mat argument:
It produces screwdriver.vtk contaning the original mesh and screwdriver_matid_1.vtk, screwdriver_matid_2.vtk files
containing only the cells of a given physical group and all vertices of the original mesh.
1 radius = 0.01;
2 height = 0.1;
3 $fn = 50;
4
5 module tip() {
6 rotate([0, -10, 0])
7 translate([0, -radius, -3*radius])
8 cube([radius, 2*radius, 3*radius], center=false);
9 }
10
11 difference() {
12 difference() {
13 difference() {
(continues on next page)
1.5. Examples 89
SfePy Documentation, Release version: 2022.2
21 }
22 cylinder(center=false, h=height, r=0.3*radius);
23 }
24 for (i = [1:6]) {
25 rotate([0, 0, 360/6*i])
26 translate([-1.1*radius, 0.0, -0.2*height])
27 cylinder(center=false, h=1.1*height, r=0.2*radius);
28 }
29 }
30
31 union() {
32 difference() {
33 translate([0, 0, height])
34 cylinder(center=false, h=height, r=0.3*radius);
35 translate([0, 0, 1.71*height + 3*radius])
36 union() {
37 tip();
38 mirror ([1, 0, 0]) tip();
39 }
40 }
41 cylinder(center=false, h=height, r=0.3*radius);
42 }
1 importCSG.open('screwdriver_full.csg')
2 top_group = FreeCAD.ActiveDocument.Objects[-1]
3 Part.export(top_group.OutList, 'screwdriver_full.step')
Since the different tools for geometry definition have been used, the numbering of geometric objects may differ and the
surface and edge numbers have to be changed in the GEO file:
Note: The numbering of objects may vary between FreeCAD, OpenSCAD and Gmsh versions.
90 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Introduction
This tutorial shows identification of material parameters of a composite structure using data (force-displacement curves)
obtained by a standard tensile test.
Composite structure
The unidirectional long fiber carbon-epoxy composite is considered. Its microstructure was analysed by the scanning
electron microscopy and the data, volume fractions and fibers cross-sections, were used to generate a periodic finite
element mesh (representative volume element - RVE) representing the random composite structure at the microscopic
level (the random structure generation algorithm is described in1 ):
This RVE is used in the micromechanical FE analysis which is based on the two-scale homogenization method.
Material testing
Several carbon-expoxy specimens with different fiber orientations (0, 30, 60 and 90 degrees) were subjected to the
tensile test in order to obtain force-elongation dependencies, see2 . The slopes of the linearized dependencies were used
in an objective function of the identification process.
1 Lubachevsky B. D., How to Simulate Billiards and Similar Systems, Journal of Computational Physics, 94(2), 1991. http://arxiv.org/PS_cache/
cond-mat/pdf/0503/0503627v2.pdf
2 Srbová H., Kroupa T., Zemčík R., Identification of the Material Parameters of a Unidirectional Fiber Composite Using a Micromodel, Materiali
1.5. Examples 91
SfePy Documentation, Release version: 2022.2
Numerical simulation
The linear isotropic material model is used for both components (fiber and matrix) of the composite so only four material
parameters (Young’s modulus and Poisson’s ratio for each component) are necessary to fully describe the mechanical
behavior of the structure.
The numerical simulations of the tensile tests are based on the homogenization method applied to the linear elastic prob-
lem3 . The homogenization procedure results in the microscopic problem solved within the RVE and the macroscopic
problem that involves the homogenized elastic coefficients.
3 Pinho-da-Cruz L., Oliveira J. A. and Teixeira-Dias F., Asymptotic homogenization in linear elasticity. Part I: Mathematical formulation and
92 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
Homogenized coefficients
The problem at the microscopic level is formulated in terms of characteristic response functions and its solution is used
to evaluate the homogenized elasticity tensor. The microscopic problem has to be solved with the periodic boundary
conditions.
The following SfePy description file is used for definition of the microscopic problem: homogenization_opt_src.
In the case of the identification process function get_mat() obtains the material parameters (Young’s modules, Poisson’s
ratios) from the outer identification loop. Otherwise these parameters are given by values.
Notice the use of parametric_hook (Miscellaneous) to pass around the optimization parameters.
Macroscopic simulation
The homogenized elasticity problem is solved for the unknown macroscopic displacements and the elongation of the
composite specimen is evaluated for a given loading. These values are used to determine the slopes of the calculated
force-elongation dependencies which are required by the objective function.
The SfePy description file for the macroscopic analysis: linear_elasticity_opt_src.
Identification procedure
The identification of material parameters, i.e. the Young’s modulus and Poisson’s ratio, of the epoxy matrix (𝐸𝑚 , 𝜈𝑚 )
and carbon fibers (𝐸𝑓 , 𝜈𝑓 ) can be formulated as a minimization of the following objective function:
(︃ )︃2
𝑖
∑︁ 𝑘𝑐𝑜𝑚𝑝 (x)
Φ(x) = 1− 𝑖
, (1.9)
𝑘𝑒𝑥𝑝
𝑖∈{0,30,60,90}
where 𝑘𝑐𝑜𝑚𝑝
𝑖
and 𝑘𝑒𝑥𝑝
𝑖
are the computed and measured slopes of the force-elongation tangent lines for a given fiber ori-
entation. This function is minimized using scipy.optimize.fmin_tnc(), considering bounds of the identified parameters.
Tho following steps are performed in each iteration of the optimization loop:
1. Solution of the microscopic problem, evaluation of the homogenized elasticity tensor.
2. Solution of the macroscopic problems for different fiber orientations (0, 30, 60, 90), this is incorporated by
appropriate rotation of the elasticity tensor.
3. Evaluation of the objective function.
Python script for material identification: material_opt_src.
Run the script from the command shell as (from the top-level directory of SfePy):
$ python sfepy/examples/homogenization/material_opt.py
The iteration process is monitored using graphs where the values of the objective function and material parameters are
plotted.
1.5. Examples 93
SfePy Documentation, Release version: 2022.2
The resulting values of 𝐸𝑓 , 𝜈𝑓 , 𝐸𝑚 , 𝜈𝑚 can be found at the end of the script output:
So that:
𝐸𝑓 = 171.13 GPa
𝜈𝑓 = 3.21
𝐸𝑚 = 2.34 GPa
𝜈𝑚 = 0.20
Note: The results may vary across SciPy versions and related libraries.
Introduction
When dealing with shape optimization we usually need to modify a FE mesh using a few optimization parameters
describing the mesh geometry. The B-spline parametrization offers an efficient way to do that. A mesh region (2D or
3D) that is to be parametrized is enclosed in the so called spline-box and the positions of all vertices inside the box can
be changed by moving the control points of the B-spline curves.
There are two different classes for the B-spline parametrization implemented in SfePy (module sfepy.mesh.
splinebox): SplineBox and SplineRegion2D. The first one defines a rectangular parametrization box in 2D or
3D while the second one allows to set up an arbitrary shaped region of parametrization in 2D.
94 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
SplineBox
the first parameter defines the range of the box in each dimension, the second parameter is the array of coordinates
(vertices) to be parametrized and the last one (optional) determines the number of control points in each dimension.
The number of the control points (𝑛𝑐𝑝) is calculated as:
where 𝑑𝑒𝑔𝑟𝑒𝑒 is the degree of the B-spline curve (default value: 3 = cubic spline) and 𝑛𝑠𝑔 is the number of the spline
segments (default value: [1,1(,1)] = 4 control points for all dimensions).
The position of the vertices can be modified by moving the control points:
spb.move_control_point(<cpoint>, <val>)
where <cpoint> is the index or position of the control point, for explanation see the following figure.
The displacement is given by <val>. The modified coordinates of the vertices are evaluated by:
new_coors = spb.evaluate()
Example
• Create a new 2D SplineBox with the left bottom corner at [-1,-1] and the right top corner at [1, 0.6] which has
5 control points in x-direction and 4 control points in y-direction:
4 mesh = Mesh.from_file('meshes/2d/square_tri1.mesh')
5 spb = SplineBox([[-1, 1], [-1, 0.6]], mesh.coors, nsg=[2,1])
• Modify the position of mesh coordinates by moving three control points (with indices 1,2 and 3):
1.5. Examples 95
SfePy Documentation, Release version: 2022.2
mesh.cmesh.coors[:] = spb.evaluate()
• Write the deformed mesh and the spline control net (the net of control points) into vtk files:
spb.write_control_net('square_tri1_spbox.vtk')
mesh.write('square_tri1_deform.vtk')
The following figures show the undeformed (left) and deformed (right) mesh and the control net.
SplineRegion2D
In this case, the region (only in 2D) of parametrization is defined by four B-spline curves:
The curves must form a closed loop, must be oriented counterclockwise and the opposite curves (<bspl1>, <bspl3>
and <bspl2>, <bspl4>) must have the same number of control points and the same knot vectors, see the figure below,
on the left.
96 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
The position of the selected vertices, depicted in the figure on the right, are driven by the control points in the same
way as explained above for SplineBox.
Note: Initializing SplineRegion2D may be time consuming due to the fact that for all vertex coordinates the spline
parameters have to be found using an optimization method in which the B-spline basis is repeatedly evaluated.
Example
• First of all, define four B-spline curves (the default degree of the spline curve is 3) representing the boundary of
a parametrization area:
7 sp_l = BSpline()
8 sp_l.approximate(line_l, ncp=4)
9 kn_lr = sp_l.get_knot_vector()
10
11 sp_r = BSpline()
12 sp_r.approximate(line_r, knots=kn_lr)
13
18 sp_b = BSpline()
19 sp_b.approximate(line_b, ncp=5)
20 kn_bt = sp_b.get_knot_vector()
21
22 sp_t = BSpline()
23 sp_t.approximate(line_t, knots=kn_bt)
1.5. Examples 97
SfePy Documentation, Release version: 2022.2
mesh.cmesh.coors[:] = spb.evaluate()
The figures below show the undeformed (left) and deformed (right) mesh and the control net.
1.5.6 Examples
acoustics
acoustics/acoustics.py
Description
Acoustic pressure distribution.
This example shows how to solve a problem in complex numbers, note the ‘accoustic_pressure’ field definition.
Find 𝑝 such that:
∫︁ ∫︁ ∫︁ ∫︁
𝑐2 ∇𝑞 · ∇𝑝 − 𝑤2 𝑞𝑝 − 𝑖𝑤𝑐 𝑞𝑝 = 𝑖𝑤𝑐2 𝜌𝑣𝑛 𝑞, ∀𝑞 .
Ω Ω Γ𝑜𝑢𝑡 Γ𝑖𝑛
98 Chapter 1. Documentation
SfePy Documentation, Release version: 2022.2
source code
r"""
Acoustic pressure distribution.
This example shows how to solve a problem in complex numbers, note the
'accoustic_pressure' field definition.
.. math::
c^2 \int_{\Omega} \nabla q \cdot \nabla p
- w^2 \int_{\Omega} q p
- i w c \int_{\Gamma_{out}} q p
= i w c^2 \rho v_n \int_{\Gamma_{in}} q
\;, \quad \forall q \;.
"""
from __future__ import absolute_import
from sfepy import data_dir
1.5. Examples 99
SfePy Documentation, Release version: 2022.2
options = {
'nls' : 'newton',
'ls' : 'ls',
}
materials = {
'one' : ({'one' : 1.0},),
}
regions = {
'Omega' : 'all',
'Gamma_in' : ('vertices in (x < 0.01)', 'facet'),
'Gamma_out' : ('vertices in (x > 0.99)', 'facet'),
}
fields = {
'accoustic_pressure' : ('complex', 1, 'Omega', 1),
}
variables = {
'p' : ('unknown field', 'accoustic_pressure', 0),
'q' : ('test field', 'accoustic_pressure', 'p'),
}
ebcs = {
}
integrals = {
'i' : 2,
}
equations = {
'Acoustic pressure' :
"""%s * dw_laplace.i.Omega( one.one, q, p )
- %s * dw_dot.i.Omega( q, p )
- %s * dw_dot.i.Gamma_out( q, p )
= %s * dw_integrate.i.Gamma_in( q )"""
% (c*c, w*w, 1j*w*c, 1j*w*c*c*rho*v_n)
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-1,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-1, # Linear system error < (eps_a * lin_red).
(continues on next page)
acoustics/acoustics3d.py
Description
Acoustic pressure distribution in 3D.
Two Laplace equations, one in Ω1 , other in Ω2 , connected on the interface region Γ12 using traces of variables.
Find two complex acoustic pressures 𝑝1 , 𝑝2 such that:
∫︁ ∫︁
𝑘 2 𝑞𝑝 − ∇𝑞 · ∇𝑝
Ω
∫︁ ∫︁ ∫︁ Ω
−𝑖𝑤/𝑐 𝑞𝑝 + 𝑖𝑤𝜌/𝑍 𝑞(𝑝2 − 𝑝1 ) + 𝑖𝑤𝜌/𝑍 𝑞(𝑝1 − 𝑝2 )
Γ𝑜𝑢𝑡 Γ2
∫︁ Γ1
= 𝑖𝑤𝜌 𝑣𝑛 𝑞 , ∀𝑞 .
Γ𝑖𝑛
source code
r"""
Acoustic pressure distribution in 3D.
.. math::
\int_{\Omega} k^2 q p - \int_{\Omega} \nabla q \cdot \nabla p \\
- i w/c \int_{\Gamma_{out}} q p
+ i w \rho/Z \int_{\Gamma_2} q (p_2 - p_1)
+ i w \rho/Z \int_{\Gamma_1} q (p_1 - p_2) \\
= i w \rho \int_{\Gamma_{in}} v_n q
\;, \quad \forall q \;.
"""
freq = 1200
v_n = 1.0 # m/s
c = 343.0 # m/s
rho = 1.55 # kg/m^3
R = 1000
w = 2.0 * freq
k1 = w / c
rhoc1 = rho * c
k2 = k1 * coef_k
rhoc2 = rhoc1 * coef_r
# acoustic impedance
Z = rho * c / por * (0.006 + 1j * k1 * (tw + 0.375 * dh
* (1 + rhoc2/rhoc1 * k2/k1)))
regions = {
'Omega' : 'all',
'Omega_1' : 'cells of group 1',
'Omega_2' : 'cells of group 2',
'Gamma_12' : ('r.Omega_1 *v r.Omega_2', 'facet'),
'Gamma_12_1' : ('copy r.Gamma_12', 'facet', 'Omega_1'),
'Gamma_12_2' : ('copy r.Gamma_12', 'facet', 'Omega_2'),
'Gamma_in' : ('vertices in (z < 0.001)', 'facet'),
'Gamma_out' : ('vertices in (z > 0.157)', 'facet'),
}
materials = {
}
fields = {
'accoustic_pressure_1' : ('complex', 'scalar', 'Omega_1', 1),
'accoustic_pressure_2' : ('complex', 'scalar', 'Omega_2', 1),
}
variables = {
'p_1' : ('unknown field', 'accoustic_pressure_1'),
'q_1' : ('test field', 'accoustic_pressure_1', 'p_1'),
'p_2' : ('unknown field', 'accoustic_pressure_2'),
(continues on next page)
ebcs = {
}
integrals = {
'i' : 2,
}
equations = {
'Acoustic pressure' :
"""%s * dw_dot.i.Omega_1(q_1, p_1)
+ %s * dw_dot.i.Omega_2(q_2, p_2)
- dw_laplace.i.Omega_1(q_1, p_1)
- dw_laplace.i.Omega_2(q_2, p_2)
- %s * dw_dot.i.Gamma_out(q_1, p_1)
+ %s * dw_jump.i.Gamma_12_1(q_1, p_1, tr(p_2))
+ %s * dw_jump.i.Gamma_12_2(q_2, p_2, tr(p_1))
= %s * dw_integrate.i.Gamma_in(q_1)"""
% (k1*k1, k2*k2,
1j*k1,
1j*k1*rhoc1 / Z, 1j*k2*rhoc2 / Z,
1j*k1*rhoc1 * v_n)
}
options = {
'nls': 'newton',
'ls': 'ls',
'file_per_var': True,
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-1,
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-6,
})
}
acoustics/vibro_acoustic3d.py
Description
Vibro-acoustic problem
3D acoustic domain with 2D perforated deforming interface.
Master problem: defined in 3D acoustic domain (vibro_acoustic3d.py)
Slave subproblem: 2D perforated interface (vibro_acoustic3d_mid.py)
Master 3D problem - find 𝑝 (acoustic pressure) and 𝑔 (transversal acoustic velocity) such that:
∫︁ ∫︁ ∫︁ ∫︁ ∫︁ ∫︁
𝑐2 ∇𝑞 · ∇𝑝 − 𝜔 2 𝑞𝑝 + 𝑖𝜔𝑐 𝑞𝑝 + 𝑖𝜔𝑐 𝑞𝑝 − 𝑖𝜔𝑐2 (𝑞 + − 𝑞 − )𝑔 = 2𝑖𝜔𝑐 𝑞 𝑝¯ , ∀𝑞 ,
Ω Ω Γ𝑖𝑛 Γ𝑜𝑢𝑡 Γ0 Γ𝑖𝑛
∫︁ ∫︁ ∫︁
−𝑖𝜔 𝑓 (𝑝+ − 𝑝− ) − 𝜔 2 𝐹 𝑓 𝑔 + 𝜔2 𝐶𝑓 𝑤 = 0 , ∀𝑓 ,
Γ0 Γ0 Γ0
source code
r"""
Vibro-acoustic problem
.. math::
c^2 \int_{\Omega} \nabla q \cdot \nabla p
- \omega^2 \int_{\Omega} q p
+ i \omega c \int_{\Gamma_{in}} q p
+ i \omega c \int_{\Gamma_{out}} q p
- i \omega c^2 \int_{\Gamma_0} (q^+ - q^-) g
= 2i \omega c \int_{\Gamma_{in}} q \bar{p}
\;, \quad \forall q \;,
.. math::
\omega^2 \int_{\Gamma_0} C z g
- \omega^2 \int_{\Gamma_0} S z w
+ \int_{\Gamma_0} \nabla z \cdot \ull{G} \cdot \nabla w
- \int_{\Gamma_0} \ul{\theta} \cdot \ull{G} \cdot \nabla z
= 0
\;, \quad \forall z \;,
sound_speed = 343.0
wave_num = 5.5
p_inc = 300
c = sound_speed
c2 = c**2
w = wave_num * c
w2 = w**2
wc = w * c
wc2 = w * c2
regions = {
'Omega1': 'cells of group 1',
'Omega2': 'cells of group 2',
'GammaIn': ('vertices of group 1', 'face'),
'GammaOut': ('vertices of group 2', 'face'),
'Gamma_aux': ('r.Omega1 *v r.Omega2', 'face'),
'Gamma0_1': ('copy r.Gamma_aux', 'face', 'Omega1'),
'Gamma0_2': ('copy r.Gamma_aux', 'face', 'Omega2'),
'aux_Left': ('vertices in (x < 0.001)', 'face'),
'aux_Right': ('vertices in (x > 0.299)', 'face'),
'Gamma0_1_Left': ('r.Gamma0_1 *v r.aux_Left', 'edge'),
'Gamma0_1_Right': ('r.Gamma0_1 *v r.aux_Right', 'edge'),
}
(continues on next page)
fields = {
'pressure1': ('complex', 'scalar', 'Omega1', 1),
'pressure2': ('complex', 'scalar', 'Omega2', 1),
'tvelocity': ('complex', 'scalar', 'Gamma0_1', 1),
'deflection': ('complex', 'scalar', 'Gamma0_1', 1),
}
variables = {
'p1': ('unknown field', 'pressure1', 0),
'q1': ('test field', 'pressure1', 'p1'),
'p2': ('unknown field', 'pressure2', 1),
'q2': ('test field', 'pressure2', 'p2'),
'g0': ('unknown field', 'tvelocity', 2),
'f0': ('test field', 'tvelocity', 'g0'),
'w': ('unknown field', 'deflection', 3),
'z': ('test field', 'deflection', 'w'),
}
ebcs = {
'fixed_l': ('Gamma0_1_Left', {'w.0': 0.0}),
'fixed_r': ('Gamma0_1_Right', {'w.0': 0.0}),
}
options = {
'file_per_var': True,
}
functions = {
}
materials = {
'ac' : ({'F': -2.064e+00, 'c': -1.064e+00}, ),
}
equations = {
'eq_1' : """
%e * dw_laplace.5.Omega1(q1, p1)
+ %e * dw_laplace.5.Omega2(q2, p2)
- %e * dw_dot.5.Omega1(q1, p1)
- %e * dw_dot.5.Omega2(q2, p2)
+ %s * dw_dot.5.GammaIn(q1, p1)
+ %s * dw_dot.5.GammaOut(q2, p2)
- %s * dw_dot.5.Gamma0_1(q1, g0)
+ %s * dw_dot.5.Gamma0_2(q2, tr(g0))
= %s * dw_integrate.5.GammaIn(q1)"""\
% (c2, c2, w2, w2,
1j * wc, 1j * wc,
1j * wc2, 1j * wc2,
2j * wc * p_inc),
'eq_2' : """
- %s * dw_dot.5.Gamma0_1(f0, p1)
(continues on next page)
solvers = {
'ls': ('ls.cm_pb',
{'others': [base_dir
+ '/examples/acoustics/vibro_acoustic3d_mid.py'],
'coupling_variables': ['g0', 'w'],
}),
'nls': ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-6,
'eps_r' : 1e-6,
})
}
dg
dg/advection_1D.py
Description
Transient advection equation in 1D solved using discontinous galerkin method.
𝑑𝑝
+ 𝑎 · 𝑑𝑝/𝑑𝑥 = 0
𝑑𝑡
𝑝(𝑡, 0) = 𝑝(𝑡, 1)
Usage Examples
To view animated results use script/dg_plot_1D.py specifing name of the output in output/ folder, default is
dg/advection_1D:
source code
r"""
Transient advection equation in 1D solved using discontinous galerkin method.
p(t,0) = p(t,1)
Usage Examples
--------------
Run with simple.py script::
"""
from sfepy.examples.dg.example_dg_common import *
from sfepy.discrete.dg.limiters import MomentLimiter1D
dim = 1
def define(filename_mesh=None,
approx_order=2,
adflux=0.0,
limit=True,
cw=None,
diffcoef=None,
diffscheme="symmetric",
cfl=0.4,
dt=None,
t1=0.1
):
t0 = 0
transient = True
mstart = 0
mend = 1
diffcoef = None
cw = None
example_name = "advection_1D"
dim = 1
if filename_mesh is None:
filename_mesh = get_gen_1D_mesh_hook(0, 1, 100)
materials = {
'a': ({'val': [1.0], '.flux': adflux},),
regions = {
'Omega': 'all',
'Gamma': ('vertices of surface', 'facet'),
'left': ('vertices in x == 0', 'vertex'),
'right': ('vertices in x == 1', 'vertex')
}
fields = {
(continues on next page)
variables = {
'p': ('unknown field', 'f', 0, 1),
'v': ('test field', 'f', 'p'),
}
dgebcs = {
'u_left': ('left', {'p.all': 0}),
'u_righ': ('right', {'p.all': 0}),
}
dgepbc_1 = {
'name' : 'u_rl',
'region': ['right', 'left'],
'dofs': {'p.all': 'p.all'},
'match': 'match_y_line',
}
integrals = {
'i': 2 * approx_order,
}
equations = {
'Advection': """
dw_dot.i.Omega(v, p)
- dw_s_dot_mgrad_s.i.Omega(a.val, p[-1], v)
+ dw_dg_advect_laxfrie_flux.i.Omega(a.flux, a.val, v, p[-1]) = 0
"""
}
solvers = {
"tss": ('ts.tvd_runge_kutta_3',
{"t0" : t0,
"t1" : t1,
'limiters': {"f": MomentLimiter1D} if limit else {}
}),
'nls': ('nls.newton', {}),
'ls' : ('ls.scipy_direct', {})
}
options = {
'ts' : 'tss',
'nls' : 'newton',
'ls' : 'ls',
'save_times' : 100,
'active_only' : False,
'pre_process_hook': get_cfl_setup(cfl)
if dt is None else
get_cfl_setup(dt=dt),
'output_dir' : 'output/dg/' + example_name,
(continues on next page)
functions = {}
def local_register_function(fun):
try:
functions.update({fun.__name__: (fun,)})
return fun
def four_step_p(x):
"""
piecewise constant (-inf, 1.8],(1.8, a + 4](a+4, a + 5](a + 5, inf)
"""
return nm.piecewise(x,
[x <= mstart,
x <= mstart + .4,
mstart + .4 < x,
mstart + .5 <= x],
[0, 0, .5, 0])
@local_register_function
def get_ic(x, ic=None):
return four_step_p(x)
@local_register_function
def sol_fun(ts, coors, mode="qp", **kwargs):
t = ts.time
if mode == "qp":
return {"p": analytic_sol(coors, t)[..., None, None]}
ics = {
'ic': ('Omega', {'p.0': 'get_ic'}),
}
return locals()
globals().update(define())
dg/advection_2D.py
Description
Transient advection equation in 2D solved by discontinous Galerkin method.
𝑑𝑝
+ 𝑎 · 𝑔𝑟𝑎𝑑 𝑝 = 0
𝑑𝑡
Usage Examples
Results are saved to output/dg/advection_2D folder by default as .msh files, the best way to view them is through GMSH
(http://gmsh.info/) version 4.6 or newer. Start GMSH and use File | Open menu or Crtl + O shortcut, navigate to the
output folder, select all .msh files and hit Open, all files should load as one item in Post-processing named p_cell_nodes.
GMSH is capable of rendering high order approximations in individual elements, to modify fidelity of rendering, double
click the displayed mesh, quick options menu should pop up, click on All view options.... This brings up the
Options window with View [0] selected in left column. Under the tab General ensure that Adapt visualization
grid is ticked, then you can adjust Maximum recursion depth and `Target visualization error to tune the
visualization. To see visualization elements (as opposed to mesh elements) go to Visibility tab and tick Draw
element outlines, this option is also available from quick options menu as View element outlines or under
shortcut Alt+E. In the quick options menu, you can also modify normal raise by clicking View Normal Raise to see
solution rendered as surface above the mesh. Note that for triangular meshes normal raise -1 produces expected raise
above the mesh. This is due to the opposite orientation of the reference elements in GMSH and Sfepy and might get
patched in the future.
source code
r"""
Transient advection equation in 2D solved by discontinous Galerkin method.
Usage Examples
--------------
def define(filename_mesh=None,
approx_order=2,
adflux=0,
limit=True,
cw=None,
diffcoef=None,
diffscheme="symmetric",
cfl=0.4,
dt=None,
t1=0.01
):
example_name = "advection_2D"
dim = 2
diffcoef = None
cw = None
if filename_mesh is None:
filename_mesh = get_gen_block_mesh_hook((1., 1.), (20, 20), (.5, .5))
t0 = 0.
angle = 0
# get_common(approx_order, cfl, t0, t1, None, get_ic)
rotm = nm.array([[nm.cos(angle), -nm.sin(angle)],
(continues on next page)
regions = {
'Omega' : 'all',
'left': ('vertices in x == 0', 'edge'),
'right': ('vertices in x == 1', 'edge'),
'top': ('vertices in y == 1', 'edge'),
'bottom': ('vertices in y == 0', 'edge')
}
fields = {
'f': ('real', 'scalar', 'Omega', str(approx_order) + 'd', 'DG', 'legendre') #
}
variables = {
'p': ('unknown field', 'f', 0, 1),
'v': ('test field', 'f', 'p'),
}
def gsmooth(x):
"""
.. :math: C_0^{\inf}
"""
return .3 * nm.piecewise(x, [x <= 0.1, x >= 0.1, .3 < x],
[0, lambda x:
nm.exp(1 / ((10 * (x - .2)) ** 2 - 1) + 1),
0])
@local_register_function
def sol_fun(ts, coors, mode="qp", **kwargs):
t = ts.time
if mode == "qp":
return {"p": analytic_sol(coors, t)[..., None, None]}
ics = {
'ic': ('Omega', {'p.0': 'get_ic'}),
}
dgepbc_1 = {
'name': 'u_rl',
'region': ['right', 'left'],
'dofs': {'p.all': 'p.all'},
'match': 'match_y_line',
}
integrals = {
'i': 3 * approx_order,
}
equations = {
'Advection': """
dw_dot.i.Omega(v, p)
- dw_s_dot_mgrad_s.i.Omega(a.val, p[-1], v)
+ dw_dg_advect_laxfrie_flux.i.Omega(a.flux, a.val, v, p[-1]) = 0
"""
}
solvers = {
"tss": ('ts.tvd_runge_kutta_3',
{"t0" : t0,
"t1" : t1,
'limiters': {"f": MomentLimiter2D} if limit else {}}),
'nls': ('nls.newton',{}),
'ls' : ('ls.scipy_direct', {})
}
options = {
'ts' : 'tss',
'nls' : 'newton',
'ls' : 'ls',
'save_times' : 100,
'active_only' : False,
'output_dir' : 'output/dg/' + example_name,
'output_format' : 'msh',
'file_format' : 'gmsh-dg',
'pre_process_hook': get_cfl_setup(cfl) if dt is None else get_cfl_setup(dt=dt)
}
return locals()
globals().update(define())
dg/advection_diffusion_2D.py
Description
Static advection-diffusion equation in 2D solved by discontinous Galerkin method.
𝑎 · 𝑔𝑟𝑎𝑑 𝑝 − 𝑑𝑖𝑣(𝑔𝑟𝑎𝑑 𝑝) = 0
Based on
Antonietti, P., & Quarteroni, A. (2013). Numerical performance of discontinuous and stabilized continuous
Galerkin methods for convection-diffusion problems.
Usage Examples
Results are saved to output/dg/advection_diffusion_2D folder by default as ` .msh` files, the best way to view them is
through GMSH (http://gmsh.info/) version 4.6 or newer. Start GMSH and use File | Open menu or Crtl + O shortcut,
navigate to the output folder, select all .msh files and hit Open, all files should load as one item in Post-processing named
p_cell_nodes.
GMSH is capable of rendering high order approximations in individual elements, to modify fidelity of rendering, double
click the displayed mesh, quick options menu should pop up, click on All view options.... This brings up the
Options window with View [0] selected in left column. Under the tab General ensure that Adapt visualization
grid is ticked, then you can adjust Maximum recursion depth and `Target visualization error to tune the
visualization. To see visualization elements (as opposed to mesh elements) go to Visibility tab and tick Draw
element outlines, this option is also available from quick options menu as View element outlines or under
shortcut Alt+E. In the quick options menu, you can also modify normal raise by clicking View Normal Raise to see
solution rendered as surface above the mesh. Note that for triangular meshes normal raise -1 produces expected raise
above the mesh. This is due to the opposite orientation of the reference elements in GMSH and Sfepy and might get
patched in the future.
source code
r"""
Static advection-diffusion equation in 2D solved by discontinous Galerkin method.
Based on
Usage Examples
--------------
def define(filename_mesh=None,
approx_order=3,
adflux=0,
limit=False,
cw=1000,
diffcoef=1,
diffscheme="symmetric",
cfl=None,
dt=None,
):
cfl = None
dt = None
functions = {}
def local_register_function(fun):
try:
functions.update({fun.__name__: (fun,)})
example_name = "advection_diffusion_2D"
dim = 2
if filename_mesh is None:
filename_mesh = get_gen_block_mesh_hook((1., 1.), (20, 20), (.5, .5))
regions = {
'Omega' : 'all',
'left' : ('vertices in x == 0', 'edge'),
'right': ('vertices in x == 1', 'edge'),
'top' : ('vertices in y == 1', 'edge'),
'bottom': ('vertices in y == 0', 'edge')
}
fields = {
'f': ('real', 'scalar', 'Omega', str(approx_order) + 'd', 'DG', 'legendre')
}
variables = {
'p': ('unknown field', 'f', 0),
'v': ('test field', 'f', 'p'),
}
integrals = {
'i': 2 * approx_order,
}
@local_register_function
def bc_funs(ts, coors, bc, problem):
# return 2*coors[..., 1]
t = ts.dt*ts.step
x_1 = coors[..., 0]
x_2 = coors[..., 1]
res = nm.zeros(nm.shape(x_1))
sin = nm.sin
cos = nm.cos
exp = nm.exp
pi = nm.pi
if bc.diff == 0:
if "left" in bc.name:
(continues on next page)
elif bc.diff == 1:
if "left" in bc.name:
res = nm.stack((-2*pi*(x_2**2 - x_2),
res),
axis=-2)
elif "right" in bc.name:
res = nm.stack((-2*pi*(x_2**2 - x_2), res,),
axis=-2)
elif "bot" in bc.name:
res = nm.stack((res,
sin(2*pi*x_1)),
axis=-2)
elif "top" in bc.name:
res = nm.stack((res,
-sin(2*pi*x_1)),
axis=-2)
return res
@local_register_function
def source_fun(ts, coors, mode="qp", **kwargs):
# t = ts.dt * ts.step
eps = diffcoef
sin = nm.sin
cos = nm.cos
exp = nm.exp
sqrt = nm.sqrt
pi = nm.pi
if mode == "qp":
x_1 = coors[..., 0]
x_2 = coors[..., 1]
res = -2*pi*(x_2**2 - x_2)*cos(2*pi*x_1)\
- 2*(2*pi**2*(x_2**2 - x_2)*sin(2*pi*x_1) - sin(2*pi*x_1))*eps\
- (2*x_2 - 1)*sin(2*pi*x_1)
return {"val": res[..., None, None]}
@local_register_function
def sol_fun(ts, coors, mode="qp", **kwargs):
t = ts.time
if mode == "qp":
return {"p": analytic_sol(coors, t)[..., None, None]}
dgebcs = {
'u_left' : ('left', {'p.all': "bc_funs", 'grad.p.all' : "bc_funs"}),
'u_top' : ('top', {'p.all': "bc_funs", 'grad.p.all' : "bc_funs"}),
'u_bot' : ('bottom', {'p.all': "bc_funs", 'grad.p.all' : "bc_funs"}),
'u_right': ('right', {'p.all': "bc_funs", 'grad.p.all' : "bc_funs"}),
}
materials = {
'a' : ({'val': [velo], '.flux': adflux},),
'D' : ({'val': [diffcoef], '.cw': cw},),
'g' : 'source_fun'
}
equations = {
'balance': """
- dw_s_dot_mgrad_s.i.Omega(a.val, p, v)
+ dw_dg_advect_laxfrie_flux.i.Omega(a.flux, a.val, v, p)
"""
+
" + dw_laplace.i.Omega(D.val, v, p) " +
diffusion_schemes_implicit[diffscheme] +
" + dw_dg_interior_penalty.i.Omega(D.val, D.cw, v, p)" +
" - dw_volume_lvf.i.Omega(g.val, v)" +
"= 0"
}
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 5,
'eps_a' : 1e-8,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
(continues on next page)
options = {
'nls' : 'newton',
'ls' : 'ls',
'output_dir' : 'output/dg/' + example_name,
'output_format' : 'msh',
'file_format' : 'gmsh-dg'
}
return locals()
globals().update(define())
pass
dg/burgers_2D.py
Description
Burgers equation in 2D solved using discontinous Galerkin method
𝑑𝑝
+ 𝑑𝑖𝑣 𝑓 (𝑝) − 𝑑𝑖𝑣(𝑔𝑟𝑎𝑑 𝑝) = 0
𝑑𝑡
Based on
Kučera, V. (n.d.). Higher order methods for the solution of compressible flows. Charles University. p. 21 eq. (1.39)
Usage Examples
Results are saved to output/dg/burgers_2D folder by default as .msh files, the best way to view them is through GMSH
(http://gmsh.info/) version 4.6 or newer. Start GMSH and use File | Open menu or Crtl + O shortcut, navigate to the
output folder, select all .msh files and hit Open, all files should load as one item in Post-processing named p_cell_nodes.
GMSH is capable of rendering high order approximations in individual elements, to modify fidelity of rendering, double
click the displayed mesh, quick options menu should pop up, click on All view options.... This brings up the
Options window with View [0] selected in left column. Under the tab General ensure that Adapt visualization
grid is ticked, then you can adjust Maximum recursion depth and `Target visualization error to tune the
visualization. To see visualization elements (as opposed to mesh elements) go to Visibility tab and tick Draw
element outlines, this option is also available from quick options menu as View element outlines or under
shortcut Alt+E. In the quick options menu, you can also modify normal raise by clicking View Normal Raise to see
solution rendered as surface above the mesh. Note that for triangular meshes normal raise -1 produces expected raise
above the mesh. This is due to the opposite orientation of the reference elements in GMSH and Sfepy and might get
patched in the future.
source code
r"""
Burgers equation in 2D solved using discontinous Galerkin method
Based on
Kučera, V. (n.d.). Higher order methods for the solution of compressible flows.
Charles University. p. 21 eq. (1.39)
Usage Examples
--------------
mesh_center = (0, 0)
mesh_size = (2, 2)
def define(filename_mesh=None,
approx_order=2,
(continues on next page)
adflux=0,
limit=False,
cw=10,
diffcoef=0.002,
diffscheme="symmetric",
cfl=None,
dt=1e-5,
t1=0.01
):
functions = {}
def local_register_function(fun):
try:
functions.update({fun.__name__: (fun,)})
return fun
example_name = "burgers_2D"
dim = 2
if filename_mesh is None:
filename_mesh = data_dir + "/meshes/2d/square_tri2.mesh"
t0 = 0.
if dt is None and cfl is None:
dt = 1e-5
angle = 0 # - nm.pi / 5
rotm = nm.array([[nm.cos(angle), -nm.sin(angle)],
[nm.sin(angle), nm.cos(angle)]])
velo = nm.sum(rotm.T * nm.array(velo), axis=-1)[:, None]
burg_velo = velo.T / nm.linalg.norm(velo)
regions = {
'Omega': 'all',
'left' : ('vertices in x == -1', 'edge'),
'right': ('vertices in x == 1', 'edge'),
'top' : ('vertices in y == 1', 'edge'),
'bottom': ('vertices in y == -1', 'edge')
}
fields = {
(continues on next page)
variables = {
'p': ('unknown field', 'f', 0, 1),
'v': ('test field', 'f', 'p'),
}
integrals = {
'i': 5,
}
@local_register_function
def sol_fun(ts, coors, mode="qp", **kwargs):
t = ts.time
if mode == "qp":
return {"p": analytic_sol(coors, t)[..., None, None]}
@local_register_function
def bc_funs(ts, coors, bc, problem):
# return 2*coors[..., 1]
t = ts.dt*ts.step
x_1 = coors[..., 0]
x_2 = coors[..., 1]
sin = nm.sin
cos = nm.cos
exp = nm.exp
if bc.diff == 0:
if "left" in bc.name:
res = -(exp(-t) - 1)*(sin(-5*x_2) + sin(8*x_2 - 4))
elif "bottom" in bc.name:
res = -(exp(-t) - 1) * (sin(-5 * x_1) + sin(8 * x_1 - 4))
elif "right" in bc.name:
res = -(exp(-t) - 1)*(sin(4) + sin(5*x_2))
elif "top" in bc.name:
res = -(exp(-t) - 1)*(sin(4) + sin(5*x_1))
elif bc.diff == 1:
if "left" in bc.name:
res = nm.stack(((4*(x_2 - 1)*cos(4) - 5*x_2*cos(5*x_2))*
(exp(-t) - 1),
-5*(exp(-t) - 1)*cos(5*x_2)),
(continues on next page)
return res
@local_register_function
def source_fun(ts, coors, mode="qp", **kwargs):
if mode == "qp":
t = ts.dt * ts.step
x_1 = coors[..., 0]
x_2 = coors[..., 1]
sin = nm.sin
cos = nm.cos
exp = nm.exp
res = (
+ (5 * x_1 * cos(5 * x_1 * x_2)
- 4 * (x_1 - 1) * cos(4 * x_1 * x_2 - 4 * x_1 - 4 * x_2)) *
(exp(-t) - 1) ** 2 * (sin(5 * x_1 * x_2)
- sin(4 * x_1 * x_2 - 4 * x_1 - 4 * x_2))
+ (5 * x_2 * cos(5 * x_1 * x_2)
- 4 * (x_2 - 1) * cos(4 * x_1 * x_2 - 4 * x_1 - 4 * x_2)) *
(exp(-t) - 1) ** 2 * (sin(5 * x_1 * x_2)
- sin(4 * x_1 * x_2 - 4 * x_1 - 4 * x_2))
- diffcoef *
((25 * x_1 ** 2 * sin(5 * x_1 * x_2) - 16 * (x_1 - 1) ** 2 *
sin(4 * x_1 * x_2 - 4 * x_1 - 4 * x_2)) * (exp(-t) - 1)
+ (25 * x_2 ** 2 * sin(5 * x_1 * x_2) - 16 * (x_2 - 1) ** 2 *
sin(4 * x_1 * x_2 - 4 * x_1 - 4 * x_2)) * (exp(-t) - 1))
+ (sin(5 * x_1 * x_2) - sin(4 * x_1 * x_2 - 4 * x_1 - 4 * x_2))*
exp(-t)
)
return {"val": res[..., None, None]}
def adv_fun(p):
vu = velo.T * p[..., None]
return vu
def burg_fun(p):
vu = .5*burg_velo * p[..., None] ** 2
return vu
def burg_fun_d(p):
v1 = burg_velo * p[..., None]
return v1
materials = {
'a' : ({'val': [velo], '.flux':adflux},),
'D' : ({'val': [diffcoef], '.Cw': cw},),
'g' : 'source_fun'
}
ics = {
'ic': ('Omega', {'p.0': 0}),
}
dgebcs = {
'u_left' : ('left', {'p.all': 'bc_funs', 'grad.p.all': 'bc_funs'}),
'u_right' : ('right', {'p.all': 'bc_funs', 'grad.p.all': 'bc_funs'}),
'u_bottom' : ('bottom', {'p.all': 'bc_funs', 'grad.p.all': 'bc_funs'}),
'u_top' : ('top', {'p.all': 'bc_funs', 'grad.p.all': 'bc_funs'}),
}
equations = {
'balance':
"dw_dot.i.Omega(v, p)" +
# non-linear hyperbolic terms
" - dw_ns_dot_grad_s.i.Omega(burg_fun, burg_fun_d, p[-1], v)" +
" + dw_dg_nonlinear_laxfrie_flux.i.Omega(a.flux, burg_fun, burg_fun_d, v, p[-1])
˓→" +
# diffusion
" + dw_laplace.i.Omega(D.val, v, p[-1])" +
diffusion_schemes_explicit[diffscheme] +
" - dw_dg_interior_penalty.i.Omega(D.val, D.Cw, v, p[-1])"
# source
+ " - dw_volume_lvf.i.Omega(g.val, v)"
" = 0"
}
solvers = {
"tss.tvd_runge_kutta_3": ('ts.tvd_runge_kutta_3',
{"t0": t0,
"t1": t1,
'limiters': {
"f": MomentLimiter2D} if limit else {}}),
(continues on next page)
options = {
'ts' : 'tss.euler',
'nls' : 'nls.newton',
'ls' : 'ls.mumps',
'save_times' : 100,
'output_dir' : 'output/dg/' + example_name,
'output_format' : 'msh',
'file_format' : 'gmsh-dg',
'pre_process_hook': get_cfl_setup(CFL=cfl, dt=dt)
}
return locals()
globals().update(define())
dg/example_dg_common.py
Description
Functions common to DG examples
source code
"""
Functions common to DG examples
"""
import os
from glob import glob
import numpy as nm
diffusion_schemes_implicit = {
"symmetric":
" + dw_dg_diffusion_flux.i.Omega(D.val, p, v)"
+ " + dw_dg_diffusion_flux.i.Omega(D.val, v, p)",
"non-symmetric":
" + dw_dg_diffusion_flux.i.Omega(D.val, p, v)"
+ " - dw_dg_diffusion_flux.i.Omega(D.val, v, p)",
(continues on next page)
diffusion_schemes_explicit = {
"symmetric":
" - dw_dg_diffusion_flux.i.Omega(D.val, p[-1], v)"
+ " - dw_dg_diffusion_flux.i.Omega(D.val, v, p[-1])",
"non-symmetric":
" - dw_dg_diffusion_flux.i.Omega(D.val, p[-1], v)"
+ " + dw_dg_diffusion_flux.i.Omega(D.val, v, p[-1])",
"incomplete":
" - dw_dg_diffusion_flux.i.Omega(D.val, p[-1], v)"}
functions = {}
def local_register_function(fun):
try:
functions.update({fun.__name__: (fun,)})
return fun
Parameters
----------
CFL : float, optional
dt: float, optional
Returns
-------
setup_cfl_condition : callable
expects sfepy.discrete.problem as argument
"""
def setup_cfl_condition(problem):
"""
Sets up CFL condition for problem ts_conf in problem
Parameters
----------
(continues on next page)
try:
# make this more general?
# maybe require material name in parameter
diffusion = problem.conf_materials['material_D__0'].values["val"]
max_diffusion = nm.max(nm.linalg.norm(diffusion))
except KeyError:
max_diffusion = None
dx = nm.min(problem.domain.mesh.cmesh.get_volumes(dim))
if dt is None:
adv_dt = get_cfl_advection(max_velo, dx, approx_order, CFL)
diff_dt = get_cfl_diffusion(max_diffusion, dx, approx_order, CFL)
_dt = min(adv_dt, diff_dt)
else:
output("CFL coefficient {0} ignored, dt specified directly"
.format(CFL))
_dt = dt
ts_conf.dt = _dt
ts_conf.n_step = tn
ts_conf.cour = max_velo * dtdx
output("Time divided into {0} nodes, {1} steps, step size is {2}"
.format(tn - 1, tn, _dt))
output("Courant number c = max(norm(a)) * dt/dx = {0}"
(continues on next page)
return setup_cfl_condition
Parameters
----------
max_velo : float
dx : float
approx_order : int
CFL : CFL
Returns
-------
dt : float
"""
order_corr = 1. / (2 * approx_order + 1)
if not (nm.isfinite(dt)):
dt = 1
output(("CFL advection: CFL coefficient was {0} " +
"and order correction 1/{1} = {2}")
.format(CFL, (2 * approx_order + 1), order_corr))
output("CFL advection: resulting dt={}".format((dt)))
return dt
Parameters
----------
max_diffusion : float
dx : float
approx_order : int
CFL : float
do_order_corr : bool
Returns
-------
dt : float
"""
(continues on next page)
if do_order_corr:
order_corr = 1. / (2 * approx_order + 1)
else:
order_corr = 1
if not (nm.isfinite(dt)):
dt = 1
output(("CFL diffusion: CFL coefficient was {0} " +
"and order correction 1/{1} = {2}")
.format(CFL, (2 * approx_order + 1), order_corr))
output("CFL diffusion: resulting dt={}".format(dt))
return dt
Parameters
----------
XS : float
leftmost coordinate
XE : float
rightmost coordinate
n_nod : int
number of nodes, number of cells is then n_nod - 1
Returns
-------
mio : UserMeshIO instance
"""
def mesh_hook(mesh, mode):
"""
Generate the 1D mesh.
"""
if mode == 'read':
mio = UserMeshIO(mesh_hook)
return mio
Parameters
----------
dims : array of 2 or 3 floats
Dimensions of the block.
shape : array of 2 or 3 ints
Shape (counts of nodes in x, y, z) of the block mesh.
centre : array of 2 or 3 floats
Centre of the block.
mat_id : int, optional
The material id of all elements.
name : string
Mesh name.
verbose : bool
If True, show progress of the mesh generation.
Returns
-------
mio : UserMeshIO instance
"""
def mesh_hook(mesh, mode):
"""
Generate the 1D mesh.
"""
if mode == 'read':
mio = UserMeshIO(mesh_hook)
return mio
Parameters
----------
clear_format : str
confirm : bool
(continues on next page)
Returns
-------
deleted_anything :
True if there was something to delete
"""
files = glob(clear_format)
if confirm:
for file in files:
output("Will delete file {}".format(file))
doit = input("--------------\nDelete files [Y/n]? ").strip() == "Y"
if doit:
for file in files:
os.remove(file)
return bool(files)
dg/imperative_burgers_1D.py
Description
Burgers equation in 1D solved using discontinous Galerkin method
source code
#!/usr/bin/env python
"""
Burgers equation in 1D solved using discontinous Galerkin method
"""
import argparse
import sys
sys.path.append('.')
from os.path import join as pjoin
import numpy as nm
# sfepy imports
from sfepy.base.base import IndexedStruct
from sfepy.base.base import Struct, configure_output, output
from sfepy.discrete import (FieldVariable, Material, Integral, Function,
Equation, Equations, Problem)
from sfepy.discrete.conditions import InitialCondition, EssentialBC, Conditions
from sfepy.discrete.dg.fields import DGField
from sfepy.discrete.dg.limiters import MomentLimiter1D
from sfepy.discrete.fem import FEDomain
from sfepy.solvers.ls import ScipyDirect
(continues on next page)
def parse_args(argv=None):
if argv is None:
argv = sys.argv
parser = argparse.ArgumentParser(
description='Solve Burgers equation and display animated results, '
'change script code to modify the problem.',
epilog='(c) 2019 T. Zitka , Man-machine Interaction at NTC UWB')
parser.add_argument('-o', '--output-dir', default='.',
help='output directory')
parser.add_argument('-p', '--plot',
action='store_true', dest='plot',
default=False, help='plot animated results')
options = parser.parse_args(argv[1:])
return options
def main(argv=None):
options = parse_args(argv=argv)
# vvvvvvvvvvvvvvvv #
approx_order = 2
# ^^^^^^^^^^^^^^^^ #
domain_name = "domain_1D"
problem_name = "iburgers_1D"
output_folder = pjoin(outputs_folder, problem_name, str(approx_order))
output_format = "vtk"
save_timestn = 100
clear_folder(pjoin(output_folder, "*." + output_format))
configure_output({'output_screen': True,
'output_log_name':
pjoin(output_folder,
f"last_run_{problem_name}_{approx_order}.txt")})
# ------------
# | Get mesh |
# ------------
X1 = 0.
XN = 1.
n_nod = 100
n_el = n_nod - 1
mesh = get_gen_1D_mesh_hook(X1, XN, n_nod).read(None)
# -----------------------------
# | Create problem components |
(continues on next page)
velo = nm.array(1.0)
def adv_fun(u):
vu = velo.T * u[..., None]
return vu
def adv_fun_d(u):
v1 = velo.T * nm.ones(u.shape + (1,))
return v1
def burg_fun(u):
vu = burg_velo * u[..., None] ** 2
return vu
def burg_fun_d(u):
v1 = 2 * burg_velo * u[..., None]
return v1
# ------------------------------
# | Create boundary conditions |
# ------------------------------
left_fix_u = EssentialBC('left_fix_u', left, {'u.all': 1.0})
right_fix_u = EssentialBC('right_fix_u', right, {'u.all': 0.0})
# ----------------------------
# | Create initial condition |
# ----------------------------
def ghump(x):
"""
Nice gaussian.
"""
return nm.exp(-200 * x ** 2)
# ------------------
# | Create problem |
# ------------------
pb = Problem(problem_name,
equations=eqs,
conf=Struct(options={"save_times": save_timestn},
ics={}, ebcs={}, epbcs={}, lcbcs={},
materials={}),
active_only=False)
pb.setup_output(output_dir=output_folder, output_format=output_format)
pb.set_ics(Conditions([ics]))
# ------------------
# | Create limiter |
# ------------------
limiter = MomentLimiter1D
# ---------------------------
# | Set time discretization |
(continues on next page)
# ------------------
# | Create solver |
# ------------------
ls = ScipyDirect({})
nls_status = IndexedStruct()
nls = Newton({'is_linear': True}, lin_solver=ls, status=nls_status)
tss = TVDRK3StepSolver(tss_conf,
nls=nls, context=pb, verbose=True)
# ---------
# | Solve |
# ---------
pb.set_solver(tss)
state_end = pb.solve()
# ----------
# | Plot 1D|
# ----------
if options.plot:
(continues on next page)
if __name__ == '__main__':
main()
dg/laplace_2D.py
Description
Laplace equation solved in 2d by discontinous Galerkin method
−𝑑𝑖𝑣(𝑔𝑟𝑎𝑑 𝑝) = 0
on rectangle
p = 0 p_y = 0
[0,b]—————————–[a, b]
|
|
p_x = -a | p(x,y) | p_x = 0 p = 0 | | p = 0
|
[0,0]—————————–[a, 0] p_y = b p = 0
solution to this is
Usage Examples
Results are saved to output/dg/laplace_2D folder by default as .msh files, the best way to view them is through GMSH
(http://gmsh.info/) version 4.6 or newer. Start GMSH and use File | Open menu or Crtl + O shortcut, navigate to the
output folder, select all .msh files and hit Open, all files should load as one item in Post-processing named p_cell_nodes.
GMSH is capable of rendering high order approximations in individual elements, to modify fidelity of rendering, double
click the displayed mesh, quick options menu should pop up, click on All view options.... This brings up the
Options window with View [0] selected in left column. Under the tab General ensure that Adapt visualization
grid is ticked, then you can adjust Maximum recursion depth and `Target visualization error to tune the
visualization. To see visualization elements (as opposed to mesh elements) go to Visibility tab and tick Draw
element outlines, this option is also available from quick options menu as View element outlines or under
shortcut Alt+E. In the quick options menu, you can also modify normal raise by clicking View Normal Raise to see
solution rendered as surface above the mesh. Note that for triangular meshes normal raise -1 produces expected raise
above the mesh. This is due to the opposite orientation of the reference elements in GMSH and Sfepy and might get
patched in the future.
source code
r"""
Laplace equation solved in 2d by discontinous Galerkin method
.. math:: - div(grad\,p) = 0
on rectangle
p = 0
p_y = 0
[0,b]-----------------------------[a, b]
| |
| |
p_x = -a | p(x,y) | p_x = 0
p = 0 | | p = 0
| |
[0,0]-----------------------------[a, 0]
p_y = b
p = 0
solution to this is
.. math:: p(x,y) = 1/2*x**2 - 1/2*y**2 - a*x + b*y
Usage Examples
--------------
def define(filename_mesh=None,
approx_order=2,
adflux=None,
limit=False,
cw=100,
diffcoef=1,
diffscheme="symmetric",
cfl=None,
dt=None,
):
cfl = None
dt = None
functions = {}
def local_register_function(fun):
try:
functions.update({fun.__name__: (fun,)})
return fun
example_name = "laplace_2D"
dim = 2
if filename_mesh is None:
filename_mesh = get_gen_block_mesh_hook((1., 1.), (16, 16), (.5, .5))
a = 1
b = 1
c = 0
regions = {
'Omega' : 'all',
'left' : ('vertices in x == 0', 'edge'),
'right': ('vertices in x == 1', 'edge'),
'top' : ('vertices in y == 1', 'edge'),
'bottom': ('vertices in y == 0', 'edge')
}
fields = {
'f': ('real', 'scalar', 'Omega', str(approx_order) + 'd', 'DG', 'legendre') #
}
variables = {
(continues on next page)
@local_register_function
def sol_fun(ts, coors, mode="qp", **kwargs):
t = ts.time
if mode == "qp":
return {"p": analytic_sol(coors, t)[..., None, None]}
@local_register_function
def bc_funs(ts, coors, bc, problem):
t = ts.time
x_1, x_2 = coors[..., 0], coors[..., 1]
res = nm.zeros(x_1.shape)
if bc.diff == 0:
res[:] = analytic_sol(coors, t)
elif bc.diff == 1:
res = nm.stack((x_1 - a, -x_2 + b),
axis=-2)
return res
materials = {
'D' : ({'val': [diffcoef], '.Cw': cw},),
}
dgebcs = {
'u_left' : ('left', {'p.all': "bc_funs", 'grad.p.all': "bc_funs"}),
'u_right' : ('right', {'p.all': "bc_funs", 'grad.p.all': "bc_funs"}),
'u_bottom' : ('bottom', {'p.all': "bc_funs", 'grad.p.all': "bc_funs"}),
'u_top' : ('top', {'p.all': "bc_funs", 'grad.p.all': "bc_funs"}),
integrals = {
'i': 2 * approx_order,
}
equations = {
'laplace': " dw_laplace.i.Omega(D.val, v, p) " +
diffusion_schemes_implicit[diffscheme] +
" + dw_dg_interior_penalty.i.Omega(D.val, D.Cw, v, p)" +
" = 0"
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
# 'i_max' : 5,
# 'eps_a' : 1e-8,
# 'eps_r' : 1.0,
# 'macheps' : 1e-16,
# 'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
# 'ls_red' : 0.1,
# 'ls_red_warp' : 0.001,
# 'ls_on' : 0.99999,
# 'ls_min' : 1e-5,
# 'check' : 0,
# 'delta' : 1e-6,
}
options = {
'nls' : 'newton',
'ls' : 'ls',
'output_dir' : 'output/dg/' + example_name,
'output_format' : 'msh',
'file_format' : 'gmsh-dg',
# 'pre_process_hook': get_cfl_setup(cfl)
}
return locals()
globals().update(define())
diffusion
diffusion/cube.py
Description
Laplace equation (e.g. temperature distribution) on a cube geometry with different boundary condition values on the
cube sides. This example was used to create the SfePy logo.
Find 𝑇 such that:
∫︁
𝑐∇𝑠 · ∇𝑇 = 0 , ∀𝑠 .
Ω
source code
r"""
Laplace equation (e.g. temperature distribution) on a cube geometry with
different boundary condition values on the cube sides. This example was
used to create the SfePy logo.
.. math::
\int_{\Omega} c \nabla s \cdot \nabla T
= 0
\;, \quad \forall s \;.
"""
from __future__ import absolute_import
from sfepy import data_dir
############# Laplace.
material_1 = {
(continues on next page)
field_1 = {
'name' : 'temperature',
'dtype' : 'real',
'shape' : (1,),
'region' : 'Omega',
'approx_order' : 1,
}
if filename_mesh.find('cube_medium_hexa.mesh') >= 0:
region_1000 = {
'name' : 'Omega',
'select' : 'cells of group 0',
}
integral_1 = {
'name' : 'i',
'order' : 1,
}
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
'method' : 'cg',
'i_max' : 1000,
'eps_r' : 1e-12,
}
variable_1 = {
'name' : 'T',
'kind' : 'unknown field',
'field' : 'temperature',
'order' : 0, # order in the global vector of unknowns
}
(continues on next page)
variable_2 = {
'name' : 's',
'kind' : 'test field',
'field' : 'temperature',
'dual' : 'T',
}
region_0 = {
'name' : 'Surface',
'select' : 'vertices of surface',
'kind' : 'facet',
}
region_1 = {
'name' : 'Bottom',
'select' : 'vertices in (z < -0.4999999)',
'kind' : 'facet',
}
region_2 = {
'name' : 'Top',
'select' : 'vertices in (z > 0.4999999)',
'kind' : 'facet',
}
region_03 = {
'name' : 'Left',
'select' : 'vertices in (x < -0.4999999)',
'kind' : 'facet',
}
ebc_1 = {
'name' : 'T0',
'region' : 'Surface',
'dofs' : {'T.0' : -3.0},
}
ebc_4 = {
'name' : 'T1',
'region' : 'Top',
'dofs' : {'T.0' : 1.0},
}
ebc_3 = {
'name' : 'T2',
'region' : 'Bottom',
'dofs' : {'T.0' : -1.0},
}
ebc_2 = {
'name' : 'T3',
'region' : 'Left',
'dofs' : {'T.0' : 2.0},
}
equations = {
'nice_equation' : """dw_laplace.i.Omega( coef.val, s, T ) = 0""",
(continues on next page)
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-6,
}
diffusion/darcy_flow_multicomp.py
Description
Each of the two equations describes a flow in one compartment of a porous medium. The equations are based on the
Darcy flow and the i-th compartment is defined in Ω𝑖 .
∫︁ ∫︁ ∑︁ ∫︁
𝐾 𝑖 ∇𝑝𝑖 · ∇𝑞 𝑖 + ¯ 𝑘 𝑝𝑖 − 𝑝𝑗 𝑞 𝑖 = 𝑓 𝑖 𝑞𝑖 ,
(︀ )︀
𝐺𝛼
Ω𝑖 Ω𝑖 𝑗 Ω𝑖
∀𝑞 𝑖 ∈ 𝑄𝑖 , 𝑖, 𝑗 = 1, 2 and 𝑖 ̸= 𝑗,
where 𝐾 is the local permeability of the i-th compartment, 𝐺𝛼
𝑖 ¯ 𝑘 = 𝐺𝑖 is the perfusion coefficient related to the
𝑗
compartments 𝑖 and 𝑗, 𝑓 𝑖 are sources or sinks which represent the external flow into the i-th compartment and 𝑝𝑖 is the
pressure in the i-th compartment.
source code
r"""
Each of the two equations describes a flow in one compartment of a porous
medium. The equations are based on the Darcy flow and the i-th compartment is
defined in :math:`\Omega_{i}`.
.. math::
\int_{\Omega_{i}} K^{i} \nabla p^{i} \cdot \nabla q^{i}+\int_{\Omega_{i}}
\sum_{j} \bar{G}\alpha_{k} \left( p^{i}-p^{j} \right)q^{i}
= \int_{\Omega_{i}} f^{i} q^{i},
.. math::
\forall q^{i} \in Q^{i}, \quad i,j=1,2 \quad \mbox{and} \quad i\neq j,
materials = {
'mat': ('mat_fun')
}
regions = {
'Omega': 'cells of group 0',
'Sigma_1': ('vertex 0', 'vertex'),
'Omega1': ('copy r.Omega', 'cell', 'Omega'),
'Omega2': ('copy r.Omega', 'cell', 'Omega'),
'Source': 'cell 24',
'Sink': 'cell 1',
}
fields = {
'pressure':('real', 1, 'Omega', 1)
}
variables = {
'p1': ('unknown field', 'pressure'),
'q1': ('test field', 'pressure', 'p1'),
'p2': ('unknown field', 'pressure'),
'q2': ('test field', 'pressure', 'p2'),
}
ebcs = {
'P1': ('Sigma_1', {'p1.0' : 0.0}),
}
equations = {
'komp1': """dw_diffusion.5.Omega1(mat.K, q1, p1)
+ dw_dot.5.Omega1(mat.G_alfa, q1, p1)
- dw_dot.5.Omega1(mat.G_alfa, q1, p2)
= dw_integrate.5.Source(mat.f_1, q1)""",
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton',
{'i_max' : 1,
(continues on next page)
return out
functions = {
'mat_fun': (mat_fun,),
}
options = {
'post_process_hook': 'postproc',
}
diffusion/laplace_1d.py
Description
Laplace equation in 1D with a variable coefficient.
Because the mesh is trivial in 1D, it is generated by mesh_hook(), and registered using UserMeshIO.
Find 𝑡 such that:
∫︁
d𝑠 d𝑡
𝑐(𝑥) =0, ∀𝑠 ,
Ω d𝑥 d𝑥
source code
r"""
Laplace equation in 1D with a variable coefficient.
.. math::
\int_{\Omega} c(x) \tdiff{s}{x} \tdiff{t}{x}
= 0
\;, \quad \forall s \;,
filename_mesh = UserMeshIO(mesh_hook)
materials = {
'coef' : 'get_coef',
}
functions = {
'get_coef' : (get_coef,),
}
regions = {
'Omega' : 'all',
'Gamma_Left' : ('vertices in (x < 0.00001)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.99999)', 'facet'),
}
fields = {
(continues on next page)
variables = {
't' : ('unknown field', 'temperature', 0),
's' : ('test field', 'temperature', 't'),
}
ebcs = {
't1' : ('Gamma_Left', {'t.0' : 0.3}),
't2' : ('Gamma_Right', {'t.0' : -0.3}),
}
integrals = {
'i' : 2,
}
equations = {
'Temperature' : """dw_laplace.i.Omega(coef.val, s, t) = 0"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
options = {
'nls' : 'newton',
'ls' : 'ls',
}
diffusion/laplace_coupling_lcbcs.py
Description
Two Laplace equations with multiple linear combination constraints.
The two equations are coupled by a periodic-like boundary condition constraint with a shift, given as a non-
homogeneous linear combination boundary condition.
where 𝑎(𝑥), 𝑏(𝑦) are given functions (shifts), 𝑃 is the periodic coordinate mapping and 𝑐11 , 𝑐12 and 𝑐2 are unknown
constant values - the unknown DOFs in Ω𝑚11 , Ω𝑚12 and Ω𝑚2 are replaced by the integral mean values.
View the results using:
source code
r"""
Two Laplace equations with multiple linear combination constraints.
.. math::
\int_{\Omega_1} \nabla v_1 \cdot \nabla u_1
= 0
\;, \quad \forall v_1 \;,
options = {
'nls' : 'newton',
(continues on next page)
return val
return val
functions = {
'get_shift1' : (get_shift1,),
'get_shift2' : (get_shift2,),
'match_y_line' : (per.match_y_line,),
'match_x_line' : (per.match_x_line,),
}
fields = {
'scalar1': ('real', 1, 'Omega1', 1),
'scalar2': ('real', 1, 'Omega2', 1),
}
materials = {
}
variables = {
'u1' : ('unknown field', 'scalar1', 0),
'v1' : ('test field', 'scalar1', 'u1'),
'u2' : ('unknown field', 'scalar2', 1),
'v2' : ('test field', 'scalar2', 'u2'),
}
regions = {
'Omega1' : 'cells of group 1',
'Omega2' : 'cells of group 2',
'Omega_m1' : 'r.Omega1 -v (r.Gamma +s vertices of surface)',
'Omega_m11' : 'r.Omega_m1 *v vertices in (x < 0)',
'Omega_m12' : 'r.Omega_m1 *v vertices in (x > 0)',
'Omega_m2' : 'r.Omega2 -v (r.Gamma +s vertices of surface)',
'Left' : ('vertices in (x < -0.499)', 'facet'),
'Right' : ('vertices in (x > 0.499)', 'facet'),
'Bottom' : ('vertices in ((y < -0.499))', 'facet'),
'Top' : ('vertices in ((y > 0.499))', 'facet'),
'Gamma' : ('r.Omega1 *v r.Omega2 -v vertices of surface', 'facet'),
'Gamma1' : ('copy r.Gamma', 'facet', 'Omega1'),
'Gamma2' : ('copy r.Gamma', 'facet', 'Omega2'),
}
lcbcs = {
'shifted1' : (('Gamma1', 'Gamma2'),
{'u1.all' : 'u2.all'},
'match_x_line', 'shifted_periodic',
'get_shift1'),
'shifted2' : (('Left', 'Right'),
{'u1.all' : 'u1.all'},
'match_y_line', 'shifted_periodic',
'get_shift2'),
'mean11' : ('Omega_m11', {'u1.all' : None}, None, 'integral_mean_value'),
'mean12' : ('Omega_m12', {'u1.all' : None}, None, 'integral_mean_value'),
'mean2' : ('Omega_m2', {'u2.all' : None}, None, 'integral_mean_value'),
}
integrals = {
'i1' : 2,
}
equations = {
'eq1' : """
dw_laplace.i1.Omega1(v1, u1) = 0
""",
'eq2' : """
dw_laplace.i1.Omega2(v2, u2) = 0
""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
diffusion/laplace_fluid_2d.py
Description
A Laplace equation that models the flow of “dry water” around an obstacle shaped like a Citroen CX.
Description
∇ · ∇𝜑 = ∆𝜑 = 0
where 𝑣 0 is the 2D vector defining the far field velocity that generates the incompressible flow.
Since the value of the potential is defined up to a constant value, a Dirichlet boundary condition is set at a single vertex
to avoid having a singular matrix.
Usage examples
This example can be run with the simple.py script with the following:
source code
r"""
A Laplace equation that models the flow of "dry water" around an obstacle
shaped like a Citroen CX.
Description
-----------
.. math::
\nabla \cdot \ul{\nabla}\,\phi = \Delta\,\phi = 0
The weak formulation for this problem is to find :math:`\phi` such that:
.. math::
\int_{\Omega} \nabla \psi \cdot \nabla \phi
= \int_{\Gamma_{left}} \ul{v}_0 \cdot n \, \psi
(continues on next page)
where :math:`\ul{v}_0` is the 2D vector defining the far field velocity that
generates the incompressible flow.
Usage examples
--------------
This example can be run with the ``simple.py`` script with the following::
"""
import numpy as nm
from sfepy import data_dir
v0 = nm.array([1, 0.25])
materials = {
'm': ({'v0': v0.reshape(-1, 1)},),
}
regions = {
'Omega': 'all',
'Gamma_Left': ('vertices in (x < 0.1)', 'facet'),
'Gamma_Right': ('vertices in (x > 1919.9)', 'facet'),
'Gamma_Top': ('vertices in (y > 917.9)', 'facet'),
'Gamma_Bottom': ('vertices in (y < 0.1)', 'facet'),
'Vertex': ('vertex in r.Gamma_Left', 'vertex'),
}
fields = {
'u': ('real', 1, 'Omega', 1),
}
(continues on next page)
variables = {
'phi': ('unknown field', 'u', 0),
'psi': ('test field', 'u', 'phi'),
}
# these EBCS prevent the matrix from being singular, see description
ebcs = {
'fix': ('Vertex', {'phi.0': 0.0}),
}
integrals = {
'i': 2,
}
equations = {
'Laplace equation':
"""dw_laplace.i.Omega( psi, phi )
= dw_surface_ndot.i.Gamma_Left( m.v0, psi )
+ dw_surface_ndot.i.Gamma_Right( m.v0, psi )
+ dw_surface_ndot.i.Gamma_Top( m.v0, psi )
+ dw_surface_ndot.i.Gamma_Bottom( m.v0, psi )"""
}
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {
'i_max': 1,
'eps_a': 1e-10,
}),
}
diffusion/laplace_iga_interactive.py
Description
Laplace equation with Dirichlet boundary conditions solved in a single patch NURBS domain using the isogeometric
analysis (IGA) approach, using commands for interactive use.
This script allows the creation of a customisable NURBS surface using igakit built-in CAD routines, which is then
saved in custom HDF5-based files with .iga extension.
Notes
The create_patch function creates a NURBS-patch of the area between two coplanar nested circles using igakit
CAD built-in routines. The created patch is not connected in the orthoradial direction. This is a problem when the
disconnected boundary is not perpendicular to the line connecting the two centres of the circles, as the solution then
exhibits a discontinuity along this line. A workaround for this issue is to enforce perpendicularity by changing the start
angle in function igakit.cad.circle (see the code down below for the actual trick). The discontinuity disappears.
Usage Examples
Command line options for tweaking the geometry of the NURBS-patch & more:
$ python3 sfepy/examples/diffusion/laplace_iga_interactive.py --R1=0.7 --C2=0.1,0.1 --
˓→viewpatch
source code
#!/usr/bin/env python
r"""
Laplace equation with Dirichlet boundary conditions solved in a single patch
NURBS domain using the isogeometric analysis (IGA) approach, using commands
for interactive use.
This script allows the creation of a customisable NURBS surface using igakit
built-in CAD routines, which is then saved in custom HDF5-based files with
.iga extension.
Notes
-----
Usage Examples
--------------
$ python3 sfepy/examples/diffusion/laplace_iga_interactive.py
(continues on next page)
Command line options for tweaking the geometry of the NURBS-patch & more::
import os
import sys
sys.path.append('.')
import numpy as nm
from sfepy import data_dir
from sfepy.base.ioutils import ensure_path
from sfepy.base.base import IndexedStruct
from sfepy.discrete import (FieldVariable, Integral, Equation,Equations,
Problem)
from sfepy.discrete.iga.domain import IGDomain
from sfepy.discrete.common.fields import Field
from sfepy.terms import Term
from sfepy.discrete.conditions import Conditions, EssentialBC
from sfepy.solvers.ls import ScipyDirect
from sfepy.solvers.nls import Newton
Parameters
----------
R1 : float
Radius of the inner circle.
R2 : float
Radius of the outer circle.
C1 : list of two floats
Coordinates of the center of the inner circle given as [x1, y1].
C2 : list of two floats
Coordinates of the center of the outer circle given as [x2, y2].
order : int, optional
Degree of the NURBS basis functions. The default is 2.
viewpatch : bool, optional
When set to True, display the NURBS patch. The default is False.
Returns
-------
(continues on next page)
"""
# Geometry Creation
centers_direction = [C2[0]-C1[0], C2[1]-C1[1]]
if centers_direction[0]==0 and centers_direction[1]==0:
start_angle = 0.0
else:
start_angle = nm.arctan2(centers_direction[1], centers_direction[0])
c1 = circle(radius=R1, center=C1, angle=(start_angle, start_angle + 2*pi))
c2 = circle(radius=R2, center=C2, angle=(start_angle, start_angle + 2*pi))
srf = ruled(c1,c2).transpose() # make the radial direction first
# Refinement
insert_U = insert_uniformly(srf.knots[0], 6)
insert_V = insert_uniformly(srf.knots[1], 6)
srf.refine(0, insert_U).refine(1, insert_V)
if viewpatch:
iplt.use('matplotlib')
iplt.figure()
iplt.plot(srf)
iplt.show()
Parameters
----------
U : numpy.ndarray
Original knot vector for a C^p-1 space.
n : int
Target number of uniformly-spaced knot spans.
Returns
-------
Knots to be inserted into U
"""
U0 = U
dU=(U.max()-U.min())/float(n) # target dU in knot vector
idone=0
while idone == 0:
# Add knots in middle of spans which are too large
Uadd=[]
for i in range(len(U)-1):
if U[i+1]-U[i] > dU:
Uadd.append(0.5*(U[i+1]+U[i]))
# Now we add these knots (once only, assumes C^(p-1))
if len(Uadd) > 0:
U = nm.sort(nm.concatenate([U,nm.asarray(Uadd)]))
else:
idone=1
# And now a little Laplacian smoothing
for num_iterations in range(5):
for i in range(len(U)-2):
if abs(U0[U0.searchsorted(U[i+1])]-U[i+1]) > 1.0e-14:
U[i+1] = 0.5*(U[i]+U[i+2])
return nm.setdiff1d(U,U0)
helps = {
'output_dir' :
'output directory',
'R1' :
'Inner circle radius [default: %(default)s]',
'R2' :
'Outer circle radius [default: %(default)s]',
'C1' :
'centre of the inner circle [default: %(default)s]',
'C2' :
'centre of the outer circle [default: %(default)s]',
'order' :
'field approximation order [default: %(default)s]',
'viewpatch' :
'generate a plot of the NURBS-patch',
(continues on next page)
def main():
parser = ArgumentParser(description=__doc__.rstrip(),
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('-o', '--output-dir', default='.',
help=helps['output_dir'])
parser.add_argument('--R1', metavar='R1',
action='store', dest='R1',
default='0.5', help=helps['R1'])
parser.add_argument('--R2', metavar='R2',
action='store', dest='R2',
default='1.0', help=helps['R2'])
parser.add_argument('--C1', metavar='C1',
action='store', dest='C1',
default='0.0,0.0', help=helps['C1'])
parser.add_argument('--C2', metavar='C2',
action='store', dest='C2',
default='0.0,0.0', help=helps['C2'])
parser.add_argument('--order', metavar='int', type=int,
action='store', dest='order',
default=2, help=helps['order'])
parser.add_argument('-v', '--viewpatch',
action='store_true', dest='viewpatch',
default=False, help=helps['viewpatch'])
options = parser.parse_args()
# Sub-domains
omega = domain.create_region('Omega', 'all')
Gamma_out = domain.create_region('Gamma_out', 'vertices of set xi01',
kind='facet')
Gamma_in = domain.create_region('Gamma_in', 'vertices of set xi00',
kind='facet')
# Variables
u = FieldVariable('u', 'unknown', field) # unknown function
v = FieldVariable('v', 'test', field, primary_var_name='u') # test function
# Integral
integral = Integral('i', order=2*field.approx_order)
# Term
t = Term.new('dw_laplace( v, u )', integral, omega, v=v, u=u)
# Equation
eq = Equation('laplace', t)
eqs = Equations([eq])
# Boundary Conditions
u_in = EssentialBC('u_in', Gamma_in, {'u.all' : 7.0})
u_out = EssentialBC('u_out', Gamma_out, {'u.all' : 3.0})
# solvers
ls = ScipyDirect({})
nls_status = IndexedStruct()
nls = Newton({}, lin_solver=ls, status=nls_status)
# problem instance
pb = Problem('potential', equations=eqs, active_only=True)
# solving
pb.set_solver(nls)
status = IndexedStruct()
state = pb.solve(status=status, save_results=True, verbose=True)
if __name__ == '__main__':
main()
diffusion/laplace_refine_interactive.py
Description
Example of solving Laplace’s equation on a block domain refined with level 1 hanging nodes.
The domain is progressively refined towards the edge/face of the block, where Dirichlet boundary conditions are pre-
scribed by an oscillating function.
Find 𝑢 such that:
∫︁
∇𝑣 · ∇𝑢 = 0 , ∀𝑠 .
Ω
Notes
The implementation of the mesh refinement with level 1 hanging nodes is a proof-of-concept code with many unresolved
issues. The main problem is the fact that a user needs to input the cells to refine at each level, while taking care of the
following constraints:
• the level 1 hanging nodes constraint: a cell that has a less-refined neighbour cannot be refined;
• the implementation constraint: a cell with a refined neighbour cannot be refined.
The hanging nodes are treated by a basis transformation/DOF substitution, which has to be applied explicitly by the
user:
• call field.substitute_dofs(subs) before assembling and solving;
• then call field.restore_dofs() before saving results.
Usage Examples
source code
#!/usr/bin/env python
r"""
Example of solving Laplace's equation on a block domain refined with level 1
hanging nodes.
The domain is progressively refined towards the edge/face of the block, where
Dirichlet boundary conditions are prescribed by an oscillating function.
.. math::
\int_{\Omega} \nabla v \cdot \nabla u = 0
\;, \quad \forall s \;.
Notes
-----
The implementation of the mesh refinement with level 1 hanging nodes is a
proof-of-concept code with many unresolved issues. The main problem is the fact
that a user needs to input the cells to refine at each level, while taking care
of the following constraints:
Usage Examples
--------------
import os
import sys
sys.path.append('.')
import numpy as nm
region = domain.create_region('aux',
'vertices in (%s %.10f )' % (axis, coor),
add_to_regions=False)
refine[region.cells] = 1
helps = {
'output_dir' :
'output directory',
'dims' :
'dimensions of the block [default: %(default)s]',
'shape' :
'shape (counts of nodes in x, y[, z]) of the block [default: %(default)s]',
(continues on next page)
def main():
parser = ArgumentParser(description=__doc__.rstrip(),
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('output_dir', help=helps['output_dir'])
parser.add_argument('--dims', metavar='dims',
action='store', dest='dims',
default='1.0,1.0,1.0', help=helps['dims'])
parser.add_argument('--shape', metavar='shape',
action='store', dest='shape',
default='7,7,7', help=helps['shape'])
parser.add_argument('--centre', metavar='centre',
action='store', dest='centre',
default='0.0,0.0,0.0', help=helps['centre'])
parser.add_argument('-3', '--3d',
action='store_true', dest='is_3d',
default=False, help=helps['3d'])
parser.add_argument('--order', metavar='int', type=int,
action='store', dest='order',
default=1, help=helps['order'])
options = parser.parse_args()
output('dimensions:', dims)
output('shape: ', shape)
output('centre: ', centre)
bbox = domain0.get_mesh_bounding_box()
min_x, max_x = bbox[:, 0]
eps = 1e-8 * (max_x - min_x)
cnt = (shape[0] - 1) // 2
g0 = 0.5 * dims[0]
grading = nm.array([g0 / 2**ii for ii in range(cnt)]) + eps + centre[0] - g0
gamma1 = domain.create_region('Gamma1',
'vertices in (x < %.10f )' % (min_x + eps),
'facet')
gamma2 = domain.create_region('Gamma2',
'vertices in (x > %.10f )' % (max_x - eps),
'facet')
t1 = Term.new('dw_laplace(v, u)',
integral, omega, v=v, u=u)
eq = Equation('eq', t1)
eqs = Equations([eq])
else:
min_y, max_y = bbox[:, 1]
min_z, max_z = bbox[:, 2]
y = (coors[:, 1] - min_y) / (max_y - min_y)
z = (coors[:, 2] - min_z) / (max_z - min_z)
return val
ls = ScipyDirect({})
pb = Problem('heat', equations=eqs)
pb.set_bcs(ebcs=Conditions([fix1, fix2]))
pb.set_solver(nls)
state = pb.solve(save_results=False)
pb.save_state(filename, state)
if options.order > 1:
pb.save_state(filename, state, linearization=Struct(kind='adaptive',
min_level=0,
max_level=8,
eps=1e-3))
if __name__ == '__main__':
main()
diffusion/laplace_shifted_periodic.py
Description
Laplace equation with shifted periodic BCs.
Display using:
source code
#!/usr/bin/env python
"""
Laplace equation with shifted periodic BCs.
Display using::
t1 = Term.new('dw_laplace(v, u)',
integral, omega, v=v, u=u)
eq = Equation('eq', t1)
eqs = Equations([eq])
ls = ScipyDirect({})
nls = Newton({}, lin_solver=ls)
pb = Problem('laplace', equations=eqs)
pb.set_output_dir(output_dir)
pb.set_solver(nls)
state = pb.solve()
helps = {
'dims' :
'dimensions of the block [default: %(default)s]',
'centre' :
'centre of the block [default: %(default)s]',
'shape' :
'numbers of vertices along each axis [default: %(default)s]',
}
def main():
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('--version', action='version', version='%(prog)s')
parser.add_argument('-d', '--dims', metavar='dims',
action='store', dest='dims',
default='[1.0, 1.0]', help=helps['dims'])
parser.add_argument('-c', '--centre', metavar='centre',
action='store', dest='centre',
default='[0.0, 0.0]', help=helps['centre'])
parser.add_argument('-s', '--shape', metavar='shape',
action='store', dest='shape',
default='[11, 11]', help=helps['shape'])
options = parser.parse_args()
output('dimensions:', dims)
output('centre: ', centre)
output('shape: ', shape)
if __name__ == '__main__':
main()
diffusion/laplace_time_ebcs.py
Description
Example explaining how to change Dirichlet boundary conditions depending on time. It is shown on the stationary
Laplace equation for temperature, so there is no dynamics, only the conditions change with time.
Five time steps are solved on a cube domain, with the temperature fixed to zero on the bottom face, and set to other
values on the left, right and top faces in different time steps.
Find 𝑡 such that:
∫︁
𝑐∇𝑠 · ∇𝑡 = 0 , ∀𝑠 .
Ω
source code
r"""
Example explaining how to change Dirichlet boundary conditions depending
on time. It is shown on the stationary Laplace equation for temperature,
so there is no dynamics, only the conditions change with time.
Five time steps are solved on a cube domain, with the temperature fixed
to zero on the bottom face, and set to other values on the left, right
and top faces in different time steps.
.. math::
\int_{\Omega} c \nabla s \cdot \nabla t
= 0
\;, \quad \forall s \;.
"""
from __future__ import absolute_import
from sfepy import data_dir
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'active_only' : False,
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -0.499)', 'facet'),
'Right' : ('vertices in (x > 0.499)', 'facet'),
'Bottom' : ('vertices in (z < -0.499)', 'facet'),
'Top' : ('vertices in (z > 0.499)', 'facet'),
}
materials = {
'one' : ({'val' : 1.0},),
}
fields = {
'temperature' : ('real', 1, 'Omega', 1),
}
variables = {
't' : ('unknown field', 'temperature', 0),
's' : ('test field', 'temperature', 't'),
}
ebcs = {
'fixed' : ('Bottom', {'t.all' : 0}),
't_t02' : ('Left', [(-0.5, 0.5), (2.5, 3.5)], {'t.all' : 1.0}),
(continues on next page)
def is_ebc(ts):
if ts.step in (2, 4):
return True
else:
return False
functions = {
'is_ebc' : (is_ebc,),
}
equations = {
'eq' : """dw_laplace.2.Omega( one.val, s, t ) = 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
'ts' : ('ts.simple', {
't0' : 0.0,
't1' : 4.0,
'dt' : None,
'n_step' : 5, # has precedence over dt!
'quasistatic' : True,
'verbose' : 1,
}),
}
diffusion/poisson.py
Description
Laplace equation using the long syntax of keywords.
See the tutorial section Example Problem Description File for a detailed explanation. See diffu-
sion/poisson_short_syntax.py for the short syntax version.
Find 𝑡 such that:
∫︁
𝑐∇𝑠 · ∇𝑡 = 0 , ∀𝑠 .
Ω
source code
r"""
Laplace equation using the long syntax of keywords.
.. math::
\int_{\Omega} c \nabla s \cdot \nabla t
= 0
\;, \quad \forall s \;.
"""
from __future__ import absolute_import
from sfepy import data_dir
material_2 = {
'name' : 'coef',
(continues on next page)
region_1000 = {
'name' : 'Omega',
'select' : 'cells of group 6',
}
region_03 = {
'name' : 'Gamma_Left',
'select' : 'vertices in (x < 0.00001)',
'kind' : 'facet',
}
region_4 = {
'name' : 'Gamma_Right',
'select' : 'vertices in (x > 0.099999)',
'kind' : 'facet',
}
field_1 = {
'name' : 'temperature',
'dtype' : 'real',
'shape' : (1,),
'region' : 'Omega',
'approx_order' : 1,
}
variable_1 = {
'name' : 't',
'kind' : 'unknown field',
'field' : 'temperature',
'order' : 0, # order in the global vector of unknowns
}
variable_2 = {
'name' : 's',
'kind' : 'test field',
'field' : 'temperature',
'dual' : 't',
}
ebc_1 = {
'name' : 't1',
'region' : 'Gamma_Left',
'dofs' : {'t.0' : 2.0},
}
ebc_2 = {
'name' : 't2',
'region' : 'Gamma_Right',
'dofs' : {'t.0' : -2.0},
(continues on next page)
integral_1 = {
'name' : 'i',
'order' : 2,
}
equations = {
'Temperature' : """dw_laplace.i.Omega( coef.val, s, t ) = 0"""
}
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
'method' : 'auto',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-6,
}
options = {
'nls' : 'newton',
'ls' : 'ls',
}
diffusion/poisson_field_dependent_material.py
Description
Laplace equation with a field-dependent material parameter.
Find 𝑇 (𝑡) for 𝑡 ∈ [0, 𝑡final ] such that:
∫︁
𝑐(𝑇 )∇𝑠 · ∇𝑇 = 0 , ∀𝑠 .
Ω
where 𝑐(𝑇 ) is the 𝑇 dependent diffusion coefficient. Each iteration calculates 𝑇 and adjusts 𝑐(𝑇 ).
source code
r"""
Laplace equation with a field-dependent material parameter.
Find :math:`T(t)` for :math:`t \in [0, t_{\rm final}]` such that:
.. math::
\int_{\Omega} c(T) \nabla s \cdot \nabla T
= 0
\;, \quad \forall s \;.
t0 = 0.0
t1 = 0.1
(continues on next page)
materials = {
'coef' : 'get_conductivity',
}
fields = {
'temperature' : ('real', 1, 'Omega', 1),
}
variables = {
'T' : ('unknown field', 'temperature', 0),
's' : ('test field', 'temperature', 'T'),
}
regions = {
'Omega' : 'all',
'Gamma_Left' : ('vertices in (x < 0.00001)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.099999)', 'facet'),
}
ebcs = {
'T1' : ('Gamma_Left', {'T.0' : 2.0}),
'T2' : ('Gamma_Right', {'T.0' : -2.0}),
}
functions = {
'get_conductivity' : (get_conductivity,),
}
ics = {
'ic' : ('Omega', {'T.0' : 0.0}),
}
integrals = {
(continues on next page)
equations = {
'Temperature' : """dw_laplace.i.Omega( coef.val, s, T ) = 0"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
}),
'ts' : ('ts.simple', {
't0' : t0,
't1' : t1,
'dt' : None,
'n_step' : n_step, # has precedence over dt!
'quasistatic' : True,
'verbose' : 1,
}),
}
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 'all',
}
diffusion/poisson_functions.py
Description
Poisson equation with source term.
Find 𝑢 such that:
∫︁ ∫︁ ∫︁
𝑐∇𝑣 · ∇𝑢 = − 𝑏𝑣 = − 𝑓 𝑣𝑝 , ∀𝑣 ,
Ω Ω𝐿 Ω𝐿
where 𝑏(𝑥) = 𝑓 (𝑥)𝑝(𝑥), 𝑝 is a given FE field and 𝑓 is a given general function of space.
This example demonstrates use of functions for defining material parameters, regions, parameter variables or boundary
conditions. Notably, it demonstrates the following:
1. How to define a material parameter by an arbitrary function - see the function get_pars() that evaluates 𝑓 (𝑥)
in quadrature points.
2. How to define a known function that belongs to a given FE space (field) - this function, 𝑝(𝑥), is defined in a FE
sense by its nodal values only - see the function get_load_variable().
In order to define the load 𝑏(𝑥) directly, the term dw_dot should be replaced by dw_integrate.
source code
r"""
Poisson equation with source term.
.. math::
\int_{\Omega} c \nabla v \cdot \nabla u
= - \int_{\Omega_L} b v = - \int_{\Omega_L} f v p
\;, \quad \forall v \;,
options = {
'nls' : 'newton',
'ls' : 'ls',
}
materials = {
'm' : ({'c' : 1.0},),
'load' : 'get_pars',
}
regions = {
'Omega' : 'all',
'Omega_L' : 'vertices by get_middle_ball',
'Gamma_Left' : ('vertices in (x < 0.00001)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.099999)', 'facet'),
}
fields = {
'temperature' : ('real', 1, 'Omega', 1),
'velocity' : ('real', 'vector', 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'temperature', 0),
'v' : ('test field', 'temperature', 'u'),
'p' : ('parameter field', 'temperature',
{'setter' : 'get_load_variable'}),
'w' : ('parameter field', 'velocity',
{'setter' : 'get_convective_velocity'}),
}
ebcs = {
'u1' : ('Gamma_Left', {'u.0' : 'get_ebc'}),
'u2' : ('Gamma_Right', {'u.0' : -2.0}),
}
integrals = {
'i' : 1,
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
val.shape = (coors.shape[0], 1, 1)
return {'f' : val}
return flag
val = 5e5 * y
return val
return val
functions = {
'get_pars' : (get_pars,),
'get_load_variable' : (get_load_variable,),
'get_convective_velocity' : (get_convective_velocity,),
'get_middle_ball' : (get_middle_ball,),
'get_ebc' : (lambda ts, coor, bc, problem, **kwargs: get_ebc(coor, 5.0),),
}
diffusion/poisson_iga.py
Description
Poisson equation solved in a single patch NURBS domain using the isogeometric analysis (IGA) approach.
Find 𝑡 such that:
∫︁ ∫︁
𝑐∇𝑠 · ∇𝑡 = 𝑓𝑠 , ∀𝑠 .
Ω Ω0
Try setting the Dirichlet boundary condition (ebcs) on various sides of the domain ('Gamma1', . . . , 'Gamma4').
View the results using:
source code
r"""
Poisson equation solved in a single patch NURBS domain using the isogeometric
analysis (IGA) approach.
.. math::
\int_{\Omega} c \nabla s \cdot \nabla t
= \int_{\Omega_0} f s
\;, \quad \forall s \;.
Try setting the Dirichlet boundary condition (ebcs) on various sides of the
domain (``'Gamma1'``, ..., ``'Gamma4'``).
materials = {
'm' : ({'c' : 1.0, 'f' : -10.0},),
}
regions = {
'Omega' : 'all',
'Omega_0' : 'vertices in (x > 1.5)',
'Gamma1' : ('vertices of set xi00', 'facet'),
'Gamma2' : ('vertices of set xi01', 'facet'),
'Gamma3' : ('vertices of set xi10', 'facet'),
'Gamma4' : ('vertices of set xi11', 'facet'),
}
fields = {
'temperature' : ('real', 1, 'Omega', None, 'H1', 'iga'),
}
variables = {
't' : ('unknown field', 'temperature', 0),
's' : ('test field', 'temperature', 't'),
}
ebcs = {
't1' : ('Gamma3', {'t.0' : 2.0}),
't2' : ('Gamma4', {'t.0' : -2.0}),
}
integrals = {
'i' : 3,
}
equations = {
'Temperature' : """dw_laplace.i.Omega(m.c, s, t)
= dw_volume_lvf.i.Omega_0(m.f, s)"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
options = {
'nls' : 'newton',
'ls' : 'ls',
}
diffusion/poisson_neumann.py
Description
The Poisson equation with Neumann boundary conditions on a part of the boundary.
Find 𝑇 such that:
∫︁ ∫︁
𝐾𝑖𝑗 ∇𝑖 𝑠∇𝑗 𝑝𝑇 = 𝑠𝑔 , ∀𝑠 ,
Ω Γ𝑁
where 𝑔 is the given flux, 𝑔 = 𝑛 · 𝐾𝑖𝑗 ∇𝑗 𝑇¯, and 𝐾𝑖𝑗 = 𝑐𝛿𝑖𝑗 (an isotropic medium). See the tutorial section Strong form
of Poisson’s equation and its integration for a detailed explanation.
The diffusion velocity and fluxes through various parts of the boundary are computed in the post_process() function.
On ‘Gamma_N’ (the Neumann condition boundary part), the flux/length should correspond to the given value 𝑔 = −50,
while on ‘Gamma_N0’ the flux should be zero. Use the ‘refinement_level’ option (see the usage examples below) to
check the convergence of the numerical solution to those values. The total flux and the flux through ‘Gamma_D’ (the
Dirichlet condition boundary part) are shown as well.
Usage Examples
source code
r"""
The Poisson equation with Neumann boundary conditions on a part of the
boundary.
.. math::
\int_{\Omega} K_{ij} \nabla_i s \nabla_j p T
= \int_{\Gamma_N} s g
\;, \quad \forall s \;,
where :math:`g` is the given flux, :math:`g = \ul{n} \cdot K_{ij} \nabla_j
\bar{T}`, and :math:`K_{ij} = c \delta_{ij}` (an isotropic medium). See the
tutorial section :ref:`poisson-weak-form-tutorial` for a detailed explanation.
The diffusion velocity and fluxes through various parts of the boundary are
computed in the :func:`post_process()` function. On 'Gamma_N' (the Neumann
condition boundary part), the flux/length should correspond to the given value
:math:`g = -50`, while on 'Gamma_N0' the flux should be zero. Use the
'refinement_level' option (see the usage examples below) to check the
convergence of the numerical solution to those values. The total flux and the
(continues on next page)
Usage Examples
--------------
totals = nm.zeros(3)
for gamma in ['Gamma_N', 'Gamma_N0', 'Gamma_D']:
return out
materials = {
'flux' : ({'val' : -50.0},),
(continues on next page)
regions = {
'Omega' : 'all',
'Gamma_D' : ('vertices in (x < -0.4999)', 'facet'),
'Gamma_N0' : ('vertices in (y > 0.4999)', 'facet'),
'Gamma_N' : ('vertices of surface -s (r.Gamma_D +v r.Gamma_N0)',
'facet'),
}
fields = {
'temperature' : ('real', 1, 'Omega', 1),
}
variables = {
't' : ('unknown field', 'temperature', 0),
's' : ('test field', 'temperature', 't'),
}
ebcs = {
't1' : ('Gamma_D', {'t.0' : 5.3}),
}
integrals = {
'i' : 2
}
equations = {
'Temperature' : """
dw_diffusion.i.Omega(m.K, s, t)
= dw_integrate.i.Gamma_N(flux.val, s)
"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
options = {
'nls' : 'newton',
'ls' : 'ls',
'refinement_level' : 0,
'post_process_hook' : 'post_process',
}
diffusion/poisson_parallel_interactive.py
Description
Parallel assembling and solving of a Poisson’s equation, using commands for interactive use.
Find 𝑢 such that:
∫︁ ∫︁
∇𝑣 · ∇𝑢 = 𝑣𝑓 , ∀𝑠 .
Ω Ω
Important Notes
• This example requires petsc4py, mpi4py and (optionally) pymetis with their dependencies installed!
• This example generates a number of files - do not use an existing non-empty directory for the output_dir
argument.
• Use the --clear option with care!
Notes
• Each task is responsible for a subdomain consisting of a set of cells (a cell region).
• Each subdomain owns PETSc DOFs within a consecutive range.
• When both global and task-local variables exist, the task-local variables have _i suffix.
• This example does not use a nonlinear solver.
• This example can serve as a template for solving a linear single-field scalar problem - just replace the equations
in create_local_problem().
• The command line options are saved into <output_dir>/options.txt file.
Usage Examples
$ python sfepy/examples/diffusion/poisson_parallel_interactive.py -h
Parallel runs:
source code
#!/usr/bin/env python
r"""
Parallel assembling and solving of a Poisson's equation, using commands for
interactive use.
.. math::
\int_{\Omega} \nabla v \cdot \nabla u
= \int_{\Omega} v f
\;, \quad \forall s \;.
Important Notes
---------------
- This example requires petsc4py, mpi4py and (optionally) pymetis with their
dependencies installed!
- This example generates a number of files - do not use an existing non-empty
directory for the ``output_dir`` argument.
- Use the ``--clear`` option with care!
Notes
-----
Usage Examples
--------------
$ python sfepy/examples/diffusion/poisson_parallel_interactive.py -h
Parallel runs::
import numpy as nm
import matplotlib.pyplot as plt
import sfepy.parallel.parallel as pl
import sfepy.parallel.plot_parallel_dofs as ppd
gamma1_i = domain_i.create_region('Gamma1',
'vertices in (x < %.10f )'
% (min_x + eps_x),
'facet', allow_empty=True)
gamma2_i = domain_i.create_region('Gamma2',
'vertices in (x > %.10f )'
% (max_x - eps_x),
'facet', allow_empty=True)
def _get_load(coors):
val = nm.ones_like(coors[:, 0])
for coor in coors.T:
val *= nm.sin(4 * nm.pi * coor)
return val
t2 = Term.new('dw_volume_lvf(load.val, v_i)',
integral, omega_i, load=load, v_i=v_i)
return pb
order = options.order
mesh = field.domain.mesh
filename = os.path.join(options.output_dir,
'para-domains-dofs.h5')
if field.is_higher_order():
out['aux'].mesh.write(filename, out=out)
else:
mesh.write(filename, out=out)
stats = Struct()
timer = Timer('solve_timer')
timer.start()
(continues on next page)
timer.start()
if rank == 0:
cell_tasks = pl.partition_mesh(mesh, size, use_metis=options.metis,
verbose=True)
else:
cell_tasks = None
stats.t_partition_mesh = timer.stop()
stats.t_create_global_fields = timer.stop()
output('...done in', timer.dt)
distribute = pl.distribute_fields_dofs
lfds, gfds = distribute([field], cell_tasks,
is_overlap=True,
save_inter_regions=options.save_inter_regions,
output_dir=options.output_dir,
comm=comm, verbose=True)
lfd = lfds[0]
stats.t_distribute_fields_dofs = timer.stop()
output('...done in', timer.dt)
if rank == 0:
dof_maps = gfds[0].dof_maps
id_map = gfds[0].id_map
if options.verify:
verify_save_dof_maps(field, cell_tasks,
dof_maps, id_map, options, verbose=True)
if options.plot:
ppd.plot_partitioning([None, None], field, cell_tasks, gfds[0],
options.output_dir, size)
pb = create_local_problem(omega_gi, order)
variables = pb.get_initial_state()
eqs = pb.equations
u_i = variables['u_i']
field_i = u_i.field
stats.t_create_local_problem = timer.stop()
output('...done in', timer.dt)
if options.plot:
ppd.plot_local_dofs([None, None], field, field_i, omega_gi,
options.output_dir, rank)
output('pdofs:', pdofs)
stats.t_allocate_global_system = timer.stop()
output('...done in', timer.dt)
variables.fill_state(0.0)
variables.apply_ebc()
rhs_i = eqs.eval_residuals(variables())
# This must be after pl.create_petsc_system() call!
mtx_i = eqs.eval_tangent_matrices(variables(), pb.mtx_a)
stats.t_evaluate_local_problem = timer.stop()
output('...done in', timer.dt)
apply_ebc_to_matrix(mtx_i, u_i.eq_map.eq_ebc)
pl.assemble_rhs_to_petsc(prhs, rhs_i, pdofs, drange, is_overlap=True,
comm=comm, verbose=True)
pl.assemble_mtx_to_petsc(pmtx, mtx_i, pdofs, drange, is_overlap=True,
comm=comm, verbose=True)
stats.t_assemble_global_system = timer.stop()
output('...done in', timer.dt)
output('creating solver...')
timer.start()
stats.t_create_solver = timer.stop()
output('...done in', timer.dt)
output('solving...')
timer.start()
psol_i = pl.create_local_petsc_vector(pdofs)
gather, scatter = pl.create_gather_scatter(pdofs, psol_i, psol, comm=comm)
scatter(psol_i, psol)
gather(psol, psol_i)
stats.t_solve = timer.stop()
output('...done in', timer.dt)
output('saving solution...')
timer.start()
variables.set_state(sol0_i)
out = u_i.create_output()
gather_to_zero = pl.create_gather_to_zero(psol)
psol_full = gather_to_zero(psol)
else:
out = u.create_output(sol, linearization=Struct(kind='adaptive',
min_level=0,
max_level=order,
eps=1e-3))
stats.t_save_solution = timer.stop()
output('...done in', timer.dt)
stats.t_total = timer.total
stats.n_dof = sizes[1]
stats.n_dof_local = sizes[0]
stats.n_cell = omega.shape.n_cell
stats.n_cell_local = omega_gi.shape.n_cell
if options.show:
plt.show()
return stats
out['size'] = comm.size
out['rank'] = rank
out['dim'] = pars.dim
out.update(shape_dict)
out['order'] = pars.order
helps = {
'output_dir' :
'output directory',
'dims' :
'dimensions of the block [default: %(default)s]',
'shape' :
'shape (counts of nodes in x, y, z) of the block [default: %(default)s]',
'centre' :
'centre of the block [default: %(default)s]',
'2d' :
'generate a 2D rectangle, the third components of the above'
' options are ignored',
'order' :
'field approximation order',
'linearization' :
'linearization used for storing the results with approximation order > 1'
' [default: %(default)s]',
'metis' :
'use metis for domain partitioning',
'verify' :
'verify domain partitioning, save cells and DOFs of tasks'
' for visualization',
'plot' :
'make partitioning plots',
'save_inter_regions' :
'save inter-task regions for debugging partitioning problems',
'show' :
'show partitioning plots (implies --plot)',
'stats_filename' :
'name of the stats file for storing elapsed time statistics',
'new_stats' :
'create a new stats file with a header line (overwrites existing!)',
'silent' : 'do not print messages to screen',
'clear' :
'clear old solution files from output directory'
' (DANGEROUS - use with care!)',
}
def main():
parser = ArgumentParser(description=__doc__.rstrip(),
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('output_dir', help=helps['output_dir'])
parser.add_argument('--dims', metavar='dims',
action='store', dest='dims',
default='1.0,1.0,1.0', help=helps['dims'])
parser.add_argument('--shape', metavar='shape',
action='store', dest='shape',
(continues on next page)
if options.show:
options.plot = True
comm = pl.PETSc.COMM_WORLD
output_dir = options.output_dir
if comm.rank == 0:
from sfepy.mesh.mesh_generators import gen_block_mesh
if options.clear:
remove_files_patterns(output_dir,
['*.h5', '*.mesh', '*.txt', '*.png'],
ignores=['output_log_%02d.txt' % ii
for ii in range(comm.size)],
verbose=True)
save_options(os.path.join(output_dir, 'options.txt'),
[('options', vars(options))])
comm.barrier()
if options.stats_filename:
if comm.rank == 0:
ensure_path(options.stats_filename)
comm.barrier()
if __name__ == '__main__':
main()
diffusion/poisson_parametric_study.py
Description
Poisson equation.
This example demonstrates parametric study capabilities of Application classes. In particular (written in the strong
form):
𝑐∆𝑡 = 𝑓 in Ω,
𝑡 = 2 on Γ1 , 𝑡 = −2 on Γ2 , 𝑓 = 1 in Ω1 , 𝑓 = 0 otherwise,
$ ./resview.py output/r_omega1/circles_in_square*.vtk -2
Remark: this simple case could be achieved also by defining Ω1 by a time-dependent function and solve the static
problem as a time-dependent problem. However, the approach below is much more general.
Find 𝑡 such that:
∫︁
𝑐∇𝑠 · ∇𝑡 = 0 , ∀𝑠 .
Ω
source code
r"""
Poisson equation.
.. math::
c \Delta t = f \mbox{ in } \Omega,
Run::
$ ./resview.py output/r_omega1/circles_in_square*.vtk -2
.. math::
\int_{\Omega} c \nabla s \cdot \nabla t
= 0
\;, \quad \forall s \;.
"""
from __future__ import absolute_import
import os
import numpy as nm
# Mesh.
filename_mesh = data_dir + '/meshes/2d/special/circles_in_square.vtk'
'parametric_hook' : 'vary_omega1_size',
'output_dir' : 'output/r_omega1',
}
equations = {
'Poisson' : """dw_laplace.i.Omega( coef.val, s, t )
= dw_volume_lvf.i.Omega_1( source.val, s )"""
}
# Solvers.
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-6,
}
functions = {
'select_circ': (lambda coors, domain=None:
select_circ(coors[:,0], coors[:,1], 0, default_diameter),),
}
# Functions.
def select_circ( x, y, z, diameter ):
"""Select circular subdomain of a given diameter."""
r = nm.sqrt( x**2 + y**2 )
n = out.shape[0]
if n <= 3:
raise ValueError( 'too few vertices selected! (%d)' % n )
return out
Input:
problem: Problem instance
Return:
a generator object:
1. creates new (modified) problem
2. yields the new (modified) problem and output container
3. use the output container for some logging
4. yields None (to signal next iteration to Application)
"""
from sfepy.discrete import Problem
from sfepy.solvers.ts import get_print_info
output.prefix = 'vary_omega1_size:'
conf = problem.conf
cf = conf.get_raw( 'functions' )
n_digit, aux, d_format = get_print_info( len( diameters ) + 1 )
for ii, diameter in enumerate( diameters ):
output( 'iteration %d: diameter %3.2f ' % (ii, diameter) )
out = []
yield problem, out
yield None
diffusion/poisson_periodic_boundary_condition.py
Description
Transient Laplace equation with a localized power source and periodic boundary conditions.
This example is using a mesh generated by gmsh. Both the .geo script used by gmsh to generate the file and the .mesh
file can be found in meshes.
The mesh is suitable for periodic boundary conditions. It consists of a cylinder enclosed by a box in the x and y
directions.
The cylinder will act as a power source.
The transient Laplace equation will be solved in time interval 𝑡 ∈ [0, 𝑡final ].
Find 𝑇 (𝑡) for 𝑡 ∈ [0, 𝑡final ] such that:
∫︁ ∫︁ ∫︁
𝜕𝑇
𝑐𝑠 + 𝜎2 ∇𝑠 · ∇𝑇 = 𝑃3 𝑇 , ∀𝑠 .
Ω 𝜕𝑡 Ω Ω2
source code
r"""
Transient Laplace equation with a localized power source and
periodic boundary conditions.
(continues on next page)
Find :math:`T(t)` for :math:`t \in [0, t_{\rm final}]` such that:
.. math::
\int_{\Omega}c s \pdiff{T}{t}
+ \int_{\Omega} \sigma_2 \nabla s \cdot \nabla T
= \int_{\Omega_2} P_3 T
\;, \quad \forall s \;.
"""
t0 = 0.0
t1 = 1.
n_step = 11
power_per_volume =1.e2 # Heating power per volume of the cylinder
capacity_cylinder = 1. # Heat capacity of cylinder
capacity_fill = 1. # Heat capacity of filling material
conductivity_cylinder = 1. # Heat conductivity of cylinder
conductivity_fill = 1. # Heat conductivity of filling material
else:
(continues on next page)
materials = {
'cylinder' : 'cylinder_material_func',
'fill' : ({'capacity' : capacity_fill,
'conductivity' : conductivity_fill,},),
}
fields = {
'temperature' : ('real', 1, 'Omega', 1),
}
variables = {
'T' : ('unknown field', 'temperature', 1, 1),
's' : ('test field', 'temperature', 'T'),
}
regions = {
'Omega' : 'all',
'cylinder' : 'cells of group 444',
'fill' : 'cells of group 555',
'Gamma_Left' : ('vertices in (x < -2.4999)', 'facet'),
'y+' : ('vertices in (y >2.4999)', 'facet'),
'y-' : ('vertices in (y <-2.4999)', 'facet'),
'z+' : ('vertices in (z >0.4999)', 'facet'),
'z-' : ('vertices in (z <-0.4999)', 'facet'),
}
ebcs = {
'T1' : ('Gamma_Left', {'T.0' : 0.0}),
}
# The matching functions link the elements on each side with that on the
# opposing side.
functions = {
'cylinder_material_func' : (cylinder_material_func,),
"match_y_plane" : (per.match_y_plane,),
"match_z_plane" : (per.match_z_plane,),
}
epbcs = {
# In the y-direction
'periodic_y' : (['y+', 'y-'], {'T.0' : 'T.0'}, 'match_y_plane'),
# and in the z-direction. Due to the symmetry of the problem, this periodic
# boundary condition is actually not necessary, but we include it anyway.
'periodic_z' : (['z+', 'z-'], {'T.0' : 'T.0'}, 'match_z_plane'),
(continues on next page)
ics = {
'ic' : ('Omega', {'T.0' : 0.0}),
}
integrals = {
'i' : 1,
}
equations = {
'Temperature' :
"""dw_dot.i.cylinder( cylinder.capacity, s, dT/dt )
dw_dot.i.fill( fill.capacity, s, dT/dt )
dw_laplace.i.cylinder( cylinder.conductivity, s, T )
dw_laplace.i.fill( fill.conductivity, s, T )
= dw_integrate.i.cylinder( cylinder.power, s )"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
}),
'ts' : ('ts.simple', {
't0' : t0,
't1' : t1,
'dt' : None,
'n_step' : n_step, # has precedence over dt!
'quasistatic' : False,
'verbose' : 1,
}),
}
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'output_dir' : 'output',
'save_times' : 'all',
'active_only' : False,
}
diffusion/poisson_short_syntax.py
Description
Laplace equation using the short syntax of keywords.
See diffusion/poisson.py for the long syntax version.
Find 𝑡 such that:
∫︁
𝑐∇𝑠 · ∇𝑡 = 0 , ∀𝑠 .
Ω
source code
r"""
Laplace equation using the short syntax of keywords.
.. math::
\int_{\Omega} c \nabla s \cdot \nabla t
= 0
(continues on next page)
materials = {
'coef' : ({'val' : 1.0},),
}
regions = {
'Omega' : 'all', # or 'cells of group 6'
'Gamma_Left' : ('vertices in (x < 0.00001)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.099999)', 'facet'),
}
fields = {
'temperature' : ('real', 1, 'Omega', 1),
}
variables = {
't' : ('unknown field', 'temperature', 0),
's' : ('test field', 'temperature', 't'),
}
ebcs = {
't1' : ('Gamma_Left', {'t.0' : 2.0}),
't2' : ('Gamma_Right', {'t.0' : -2.0}),
}
integrals = {
'i' : 2,
}
equations = {
'Temperature' : """dw_laplace.i.Omega( coef.val, s, t ) = 0"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton',
{'i_max' : 1,
'eps_a' : 1e-10,
}),
}
options = {
'nls' : 'newton',
'ls' : 'ls',
}
diffusion/sinbc.py
Description
Laplace equation with Dirichlet boundary conditions given by a sine function and constants.
Find 𝑡 such that:
∫︁
𝑐∇𝑠 · ∇𝑡 = 0 , ∀𝑠 .
Ω
The sfepy.discrete.fem.meshio.UserMeshIO class is used to refine the original two-element mesh before the
actual solution.
The FE polynomial basis and the approximation order can be chosen on the command-line. By default, the fifth order
Lagrange polynomial space is used, see define() arguments.
This example demonstrates how to visualize higher order approximations of the continuous solution. The adaptive
linearization is applied in order to save viewable results, see both the options keyword and the post_process()
function that computes the solution gradient. The linearization parameters can also be specified on the command line.
The Lagrange or Bernstein polynomial bases support higher order DOFs in the Dirichlet boundary conditions, unlike
the hierarchical Lobatto basis implementation, compare the results of:
Use the following commands to view each of the results of the above commands (assuming default output directory
and names):
source code
r"""
Laplace equation with Dirichlet boundary conditions given by a sine function
and constants.
.. math::
\int_{\Omega} c \nabla s \cdot \nabla t
= 0
\;, \quad \forall s \;.
The FE polynomial basis and the approximation order can be chosen on the
command-line. By default, the fifth order Lagrange polynomial space is used,
see ``define()`` arguments.
Use the following commands to view each of the results of the above commands
(assuming default output directory and names)::
domain.mesh.name = '2_4_2_refined'
return domain.mesh
return out
filename_mesh = UserMeshIO(mesh_hook)
options = {
'nls' : 'newton',
'ls' : 'ls',
'post_process_hook' : 'post_process',
'linearization' : {
'kind' : 'adaptive',
'min_level' : min_level, # Min. refinement level applied everywhere.
'max_level' : max_level, # Max. refinement level.
'eps' : eps, # Relative error tolerance.
},
}
materials = {
'coef' : ({'val' : 1.0},),
}
regions = {
'Omega' : 'all',
}
regions.update(define_box_regions(dim, bbox[0], bbox[1], 1e-5))
fields = {
'temperature' : ('real', 1, 'Omega', order, 'H1', basis),
}
variables = {
't' : ('unknown field', 'temperature', 0),
's' : ('test field', 'temperature', 't'),
}
ebcs = {
't1' : ('Left', {'t.0' : 'ebc_sin'}),
't2' : ('Right', {'t.0' : -0.5}),
't3' : ('Top', {'t.0' : 1.0}),
}
functions = {
'ebc_sin' : (ebc_sin,),
}
equations = {
'Temperature' : """dw_laplace.10.Omega(coef.val, s, t) = 0"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
return locals()
diffusion/time_advection_diffusion.py
Description
The transient advection-diffusion equation with a given divergence-free advection velocity.
Find 𝑢 such that:
∫︁ ∫︁ ∫︁
𝜕𝑢
𝑠 + 𝑠∇ · (𝑣𝑢) + 𝐷∇𝑠 · ∇𝑢 = 0 , ∀𝑠 .
Ω 𝜕𝑡 Ω Ω
source code
r"""
The transient advection-diffusion equation with a given divergence-free
advection velocity.
.. math::
\int_{\Omega} s \pdiff{u}{t}
+ \int_{\Omega} s \nabla \cdot \left(\ul{v} u \right)
+ \int_{\Omega} D \nabla s \cdot \nabla u
= 0
\;, \quad \forall s \;.
regions = {
'Omega' : 'all', # or 'cells of group 6'
'Gamma_Left' : ('vertices in (x < -0.99999)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.99999)', 'facet'),
}
fields = {
'concentration' : ('real', 1, 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'concentration', 0, 1),
's' : ('test field', 'concentration', 'u'),
}
ebcs = {
'u1' : ('Gamma_Left', {'u.0' : 2.0}),
'u2' : ('Gamma_Right', {'u.0' : 0.0}),
}
integrals = {
'i' : 2,
}
equations = {
'advection-diffusion' :
"""
dw_dot.i.Omega(s, du/dt)
+ dw_advect_div_free.i.Omega(m.v, s, u)
+ dw_laplace.i.Omega(m.D, s, u)
= 0
"""
}
solvers = {
'ts' : ('ts.simple', {
't0' : 0.0,
't1' : 10.0,
'dt' : None,
'n_step' : 11, # Has precedence over dt.
'verbose' : 1,
}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
(continues on next page)
options = {
'ts' : 'ts',
'nls' : 'newton',
'ls' : 'ls',
'save_times' : 'all',
}
diffusion/time_poisson.py
Description
Transient Laplace equation with non-constant initial conditions given by a function.
Find 𝑇 (𝑡) for 𝑡 ∈ [0, 𝑡final ] such that:
∫︁ ∫︁
𝜕𝑇
𝑠 + 𝑐∇𝑠 · ∇𝑇 = 0 , ∀𝑠 .
Ω 𝜕𝑡 Ω
source code
r"""
Transient Laplace equation with non-constant initial conditions given by a
function.
Find :math:`T(t)` for :math:`t \in [0, t_{\rm final}]` such that:
.. math::
\int_{\Omega} s \pdiff{T}{t}
+ \int_{\Omega} c \nabla s \cdot \nabla T
= 0
\;, \quad \forall s \;.
"""
from __future__ import absolute_import
from sfepy import data_dir
t0 = 0.0
t1 = 0.1
n_step = 11
material_2 = {
'name' : 'coef',
'values' : {'val' : 0.01},
'kind' : 'stationary', # 'stationary' or 'time-dependent'
}
field_1 = {
'name' : 'temperature',
'dtype' : 'real',
'shape' : (1,),
'region' : 'Omega',
'approx_order' : 1,
}
variable_1 = {
'name' : 'T',
'kind' : 'unknown field',
'field' : 'temperature',
'order' : 0,
'history' : 1,
}
variable_2 = {
'name' : 's',
'kind' : 'test field',
'field' : 'temperature',
'dual' : 'T',
}
regions = {
'Omega' : 'all',
'Gamma_Left' : ('vertices in (x < 0.00001)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.099999)', 'facet'),
(continues on next page)
ebcs = {
'T1': ('Gamma_Left', {'T.0' : 2.0}),
'T2': ('Gamma_Right', {'T.0' : -2.0}),
}
functions = {
'get_ic' : (get_ic,),
}
ics = {
'ic' : ('Omega', {'T.0' : 'get_ic'}),
}
integral_1 = {
'name' : 'i',
'order' : 1,
}
equations = {
'Temperature' :
"""dw_dot.i.Omega( s, dT/dt )
+ dw_laplace.i.Omega( coef.val, s, T ) = 0"""
}
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
'use_presolve' : True,
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 1.1,
(continues on next page)
solver_2 = {
'name' : 'ts',
'kind' : 'ts.simple',
't0' : t0,
't1' : t1,
'dt' : None,
'n_step' : n_step, # has precedence over dt!
'verbose' : 1,
}
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 'all',
}
diffusion/time_poisson_explicit.py
Description
Transient Laplace equation.
The same example as time_poisson.py, but using the short syntax of keywords, and explicit time-stepping.
Find 𝑇 (𝑡) for 𝑡 ∈ [0, 𝑡final ] such that:
∫︁ ∫︁
𝜕𝑇
𝑠 + 𝑐∇𝑠 · ∇𝑇 = 0 , ∀𝑠 .
Ω 𝜕𝑡 Ω
source code
r"""
Transient Laplace equation.
The same example as time_poisson.py, but using the short syntax of keywords,
and explicit time-stepping.
Find :math:`T(t)` for :math:`t \in [0, t_{\rm final}]` such that:
.. math::
\int_{\Omega} s \pdiff{T}{t}
+ \int_{\Omega} c \nabla s \cdot \nabla T
= 0
\;, \quad \forall s \;.
"""
from __future__ import absolute_import
from sfepy import data_dir
regions = {
'Omega' : 'all',
'Gamma_Left' : ('vertices in (x < 0.00001)', 'facet'),
'Gamma_Right' : ('vertices in (x > 0.099999)', 'facet'),
}
fields = {
'temperature' : ('real', 1, 'Omega', 1),
}
variables = {
'T' : ('unknown field', 'temperature', 0, 1),
's' : ('test field', 'temperature', 'T'),
}
ebcs = {
't1' : ('Gamma_Left', {'T.0' : 2.0}),
't2' : ('Gamma_Right', {'T.0' : -2.0}),
}
ics = {
'ic' : ('Omega', {'T.0' : 'get_ic'}),
}
functions = {
'get_ic' : (get_ic,),
}
integrals = {
'i' : 1,
}
equations = {
'Temperature' :
"""dw_dot.i.Omega( s, dT/dt )
+ dw_laplace.i.Omega( coef.val, s, T[-1] ) = 0"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'is_linear' : True,
}),
'ts' : ('ts.simple', {
't0' : 0.0,
't1' : 0.07,
'dt' : 0.00002,
(continues on next page)
options = {
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 100,
'output_format' : 'h5',
}
diffusion/time_poisson_interactive.py
Description
Transient Laplace equation (heat equation) with non-constant initial conditions given by a function, using commands
for interactive use.
The script allows setting various simulation parameters, namely:
• the diffusivity coefficient
• the max. initial condition value
• temperature field approximation order
• uniform mesh refinement
The example shows also how to probe the results.
In the SfePy top-level directory the following command can be used to get usage information:
python sfepy/examples/diffusion/time_poisson_interactive.py -h
source code
#!/usr/bin/env python
"""
Transient Laplace equation (heat equation) with non-constant initial conditions
given by a function, using commands for interactive use.
In the SfePy top-level directory the following command can be used to get usage
information::
python sfepy/examples/diffusion/time_poisson_interactive.py -h
(continues on next page)
import numpy as nm
import matplotlib.pyplot as plt
def gen_probes(problem):
"""
Define a line probe and a circle probe.
"""
# Use enough points for higher order approximations.
n_point = 1000
fig = plt.figure(1)
ax = plt.subplot(2, 2, 2 * ax_num + 1)
ax.cla()
pars, vals = results['T']
ax.plot(pars, vals, label=r'$T$', lw=1, ls='-', marker='+', ms=3)
dx = 0.05 * (pars[-1] - pars[0])
ax.set_xlim(pars[0] - dx, pars[-1] + dx)
ax.set_ylabel('temperature')
ax.set_xlabel('probe %s' % label, fontsize=8)
ax.legend(loc='best', fontsize=10)
ax = plt.subplot(2, 2, 2 * ax_num + 2)
ax.cla()
pars, vals = results['dvel']
for ic in range(vals.shape[1]):
ax.plot(pars, vals[:, ic], label=r'$w_{%d}$' % (ic + 1),
lw=1, ls='-', marker='+', ms=3)
dx = 0.05 * (pars[-1] - pars[0])
ax.set_xlim(pars[0] - dx, pars[-1] + dx)
ax.set_ylabel('diffusion velocity')
ax.set_xlabel('probe %s' % label, fontsize=8)
ax.legend(loc='best', fontsize=10)
helps = {
'diffusivity' : 'the diffusivity coefficient [default: %(default)s]',
'ic_max' : 'the max. initial condition value [default: %(default)s]',
'order' : 'temperature field approximation order [default: %(default)s]',
'refine' : 'uniform mesh refinement level [default: %(default)s]',
'probe' : 'probe the results',
'show' : 'show the probing results figure, if --probe is used',
}
def main():
from sfepy import data_dir
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('--version', action='version', version='%(prog)s')
parser.add_argument('--diffusivity', metavar='float', type=float,
action='store', dest='diffusivity',
default=1e-5, help=helps['diffusivity'])
parser.add_argument('--ic-max', metavar='float', type=float,
(continues on next page)
output('using values:')
output(' diffusivity:', options.diffusivity)
output(' max. IC value:', options.ic_max)
output('uniform mesh refinement level:', options.refine)
if options.refine > 0:
for ii in range(options.refine):
output('refine %d...' % ii)
domain = domain.refine()
output('... %d nodes %d elements'
% (domain.shape.n_nod, domain.shape.n_el))
t1 = Term.new('dw_diffusion(m.diffusivity, s, T)',
integral, omega, m=m, s=s, T=T)
(continues on next page)
# Boundary conditions.
ebc1 = EssentialBC('T1', left, {'T.0' : 2.0})
ebc2 = EssentialBC('T2', right, {'T.0' : -2.0})
# Initial conditions.
def get_ic(coors, ic):
x, y, z = coors.T
return 2 - 40.0 * x + options.ic_max * nm.sin(4 * nm.pi * x / 0.1)
ic_fun = Function('ic_fun', get_ic)
ic = InitialCondition('ic', omega, {'T.0' : ic_fun})
pb = Problem('heat', equations=eqs)
pb.set_bcs(ebcs=Conditions([ebc1, ebc2]))
pb.set_ics(Conditions([ic]))
variables = pb.get_initial_state()
init_fun, prestep_fun, _poststep_fun = pb.get_tss_functions()
ls = ScipyDirect({})
nls_status = IndexedStruct()
nls = Newton({'is_linear' : True}, lin_solver=ls, status=nls_status)
tss = SimpleTimeSteppingSolver({'t0' : 0.0, 't1' : 100.0, 'n_step' : 11},
nls=nls, context=pb, verbose=True)
pb.set_solver(tss)
if options.probe:
# Prepare probe data.
probes, labels = gen_probes(pb)
ev = pb.evaluate
order = 2 * (options.order - 1)
suffix = tss.ts.suffix
def poststep_fun(ts, vec):
_poststep_fun(ts, vec)
all_results = []
for ii, probe in enumerate(probes):
fig, results = probe_results(ii, T, dvel, probe, labels[ii])
all_results.append(results)
plt.tight_layout()
fig.savefig('time_poisson_interactive_probe_%s.png'
% (suffix % ts.step), bbox_inches='tight')
else:
poststep_fun = _poststep_fun
pb.time_update(tss.ts)
variables.apply_ebc()
tss_status = IndexedStruct()
tss(variables.get_state(pb.active_only, force=True),
init_fun=init_fun, prestep_fun=prestep_fun, poststep_fun=poststep_fun,
status=tss_status)
output(tss_status)
if options.show:
plt.show()
if __name__ == '__main__':
main()
homogenization
homogenization/homogenization_opt.py
Description
missing description!
source code
# material function
def get_mat(coors, mode, pb):
if mode == 'qp':
cnf = pb.conf
# get material coefficients
if hasattr(cnf, 'opt_data'):
# from optim.
E_f, nu_f, E_m, nu_m = cnf.opt_data['mat_params']
else:
# given values
E_f, nu_f, E_m, nu_m = 160.e9, 0.28, 5.e9, 0.45
nqp = coors.shape[0]
nel = pb.domain.mesh.n_el
nqpe = nqp // nel
out = nm.zeros((nqp, 6, 6), dtype=nm.float64)
def optimization_hook(pb):
cnf = pb.conf
out = []
yield pb, out
if hasattr(cnf, 'opt_data'):
# store homogenized tensor
pb.conf.opt_data['D_homog'] = out[-1].D.copy()
yield None
def define(is_opt=False):
filename_mesh = data_dir + '/meshes/3d/matrix_fiber_rand.vtk'
mesh = Mesh.from_file(filename_mesh)
bbox = mesh.get_bounding_box()
regions = {
'Y' : 'all',
'Ym' : ('cells of group 7', 'cell'),
'Yf' : ('r.Y -c r.Ym', 'cell'),
}
functions = {
'get_mat': (lambda ts, coors, mode=None, problem=None, **kwargs:
get_mat(coors, mode, problem),),
'match_x_plane' : (per.match_x_plane,),
'match_y_plane' : (per.match_y_plane,),
'match_z_plane' : (per.match_z_plane,),
}
materials = {
'mat': 'get_mat',
}
fields = {
'corrector' : ('real', 3, 'Y', 1),
}
variables = {
'u': ('unknown field', 'corrector'),
'v': ('test field', 'corrector', 'u'),
'Pi': ('parameter field', 'corrector', 'u'),
'Pi1': ('parameter field', 'corrector', '(set-to-None)'),
'Pi2': ('parameter field', 'corrector', '(set-to-None)'),
}
epbcs = {
'periodic_x' : (['Left', 'Right'], {'u.all' : 'u.all'}, 'match_x_plane'),
'periodic_y' : (['Near', 'Far'], {'u.all' : 'u.all'}, 'match_y_plane'),
'periodic_z' : (['Top', 'Bottom'], {'u.all' : 'u.all'}, 'match_z_plane'),
}
options = {
'coefs': 'coefs',
'requirements': 'requirements',
'volume': { 'variables' : ['u'], 'expression' : 'ev_volume.5.Y( u )' },
'output_dir': 'output',
'coefs_filename': 'coefs_le',
}
equation_corrs = {
'balance_of_forces':
"""dw_lin_elastic.5.Y(mat.D, v, u)
= - dw_lin_elastic.5.Y(mat.D, v, Pi)"""
}
coefs = {
'D' : {
'requires' : ['pis', 'corrs_rs'],
'expression' : 'dw_lin_elastic.5.Y(mat.D, Pi1, Pi2 )',
'set_variables': [('Pi1', ('pis', 'corrs_rs'), 'u'),
('Pi2', ('pis', 'corrs_rs'), 'u')],
'class' : cb.CoefSymSym,
},
'vol': {
'regions': ['Ym', 'Yf'],
'expression': 'ev_volume.5.%s(u)',
'class': cb.VolumeFractions,
},
'filenames' : {},
}
requirements = {
'pis' : {
'variables' : ['u'],
'class' : cb.ShapeDimDim,
},
'corrs_rs' : {
'requires' : ['pis'],
'ebcs' : ['fixed_u'],
'epbcs' : all_periodic,
'equations' : equation_corrs,
(continues on next page)
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-4,
'problem': 'linear',
})
}
if is_opt:
options.update({
'parametric_hook': 'optimization_hook',
'float_format': '%.16e',
})
return locals()
homogenization/linear_elastic_mM.py
Description
missing description!
source code
if isinstance(state, dict):
pass
else:
stress = pb.evaluate('ev_cauchy_stress.i.Omega(solid.D, u)',
mode='el_avg')
strain = pb.evaluate('ev_cauchy_strain.i.Omega(u)',
mode='el_avg')
out['cauchy_strain'] = Struct(name='output_data',
mode='cell', data=strain,
dofs=None)
(continues on next page)
if pb.conf.options.get('recover_micro', False):
rname = pb.conf.options.recovery_region
region = pb.domain.regions[rname]
filename = os.path.join(os.path.dirname(pb.get_output_name()),
'recovery_region.vtk')
save_recovery_region(pb, rname, filename=filename);
recover_micro_hook(pb.conf.options.micro_filename,
region, {'strain' : rstrain},
output_dir=pb.conf.options.output_dir)
return out
regenerate = True
return out
functions = {
'get_elements' : (get_elements,),
'get_homog' : (get_homog,),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
'Recovery' : 'cells by get_elements',
}
materials = {
(continues on next page)
fields = {
'3_displacement' : ('real', 3, 'Omega', 1),
}
integrals = {
'i' : 1,
}
variables = {
'u' : ('unknown field', '3_displacement', 0),
'v' : ('test field', '3_displacement', 'u'),
}
ebcs = {
'Fixed' : ('Left', {'u.all' : 0.0}),
'PerturbedSurface' : ('Right', {'u.0' : 0.02, 'u.1' : 0.0, 'u.2' : 0.0}),
}
equations = {
'balance_of_forces' :
"""dw_lin_elastic.i.Omega(solid.D, v, u) = 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-6,
}),
}
micro_filename = base_dir \
+ '/examples/homogenization/linear_homogenization_up.py'
options = {
'nls' : 'newton',
'ls' : 'ls',
'output_dir' : 'output',
'post_process_hook' : 'post_process',
'output_prefix' : 'macro:',
'recover_micro': True,
'recovery_region' : 'Recovery',
'micro_filename' : micro_filename,
}
homogenization/linear_elasticity_opt.py
Description
missing description!
source code
def optimization_hook(pb):
cnf = pb.conf
out = []
yield pb, out
state = out[-1][1].get_state_parts()
coors = pb.domain.cmesh.coors
displ = state['u'].reshape((coors.shape[0],3))
# elongation
mcoors = coors[cnf.mnodes, 2]
mdispl = displ[cnf.mnodes, 2]
dl = (mdispl[1] - mdispl[0]) / (mcoors[1] - mcoors[0])
if hasattr(cnf, 'opt_data'):
# compute slope of the force-elongation curve
cnf.opt_data['k'] = cnf.F / dl
yield None
nqp = coors.shape[0]
return {'D': nm.tile(D, (nqp, 1, 1))}
def define(is_opt=False):
filename_mesh = UserMeshIO(mesh_hook)
mnodes = (107, 113) # nodes for elongation eval.
regions = {
'Omega': 'all',
'Bottom': ('vertices in (z < 0.001)', 'facet'),
'Top': ('vertices in (z > 0.099)', 'facet'),
}
functions = {
'get_mat': (lambda ts, coors, mode=None, problem=None, **kwargs:
get_mat(coors, mode, problem),),
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
variables = {
'u': ('unknown field', 'displacement', 0),
'v': ('test field', 'displacement', 'u'),
}
ebcs = {
'FixedBottom': ('Bottom', {'u.all': 0.0}),
'FixedTop': ('Top', {'u.0': 0.0, 'u.1': 0.0}),
}
equations = {
'balance_of_forces' :
"""dw_lin_elastic.5.Omega(solid.D, v, u)
= dw_surface_ltr.5.Top(load.val, v)""",
}
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {'eps_a': 1e-6, 'eps_r': 1.e-6,
'check': 0, 'problem': 'nonlinear'}),
}
return locals()
homogenization/linear_homogenization.py
Description
Compute homogenized elastic coefficients for a given heterogeneous linear elastic microstructure, see [1] for details or
[2] and [3] for a quick explanation.
[1] D. Cioranescu, J.S.J. Paulin: Homogenization in open sets with holes. Journal of Mathematical Analysis and
Applications 71(2), 1979, pages 590-607. https://doi.org/10.1016/0022-247X(79)90211-7
[2] J. Pinho-da-Cruz, J.A. Oliveira, F. Teixeira-Dias: Asymptotic homogenisation in linear elasticity. Part I: Mathe-
matical formulation and finite element modelling. Computational Materials Science 45(4), 2009, pages 1073-1080.
http://dx.doi.org/10.1016/j.commatsci.2009.02.025
[3] J. Pinho-da-Cruz, J.A. Oliveira, F. Teixeira-Dias: Asymptotic homogenisation in linear elasticity. Part II: Finite
element procedures and multiscale applications. Computational Materials Science 45(4), 2009, pages 1081-1096.
http://dx.doi.org/10.1016/j.commatsci.2009.01.027
source code
r"""
Compute homogenized elastic coefficients for a given heterogeneous linear
elastic microstructure, see [1] for details or [2] and [3] for a quick
explanation.
out = {}
dim = corrs['corrs_le']['u_00'].shape[1]
mic_u = - compute_micro_u(corrs['corrs_le'], macro['strain'], 'u', dim)
out['u_mic'] = Struct(name='output_data',
mode='vertex', data=mic_u,
var_name='u', dofs=None)
stress_Y, strain_Y = \
compute_stress_strain_u(pb, 'i', 'Y', 'mat.D', 'u', mic_u)
stress_Y += \
compute_mac_stress_part(pb, 'i', 'Y', 'mat.D', 'u', macro['strain'])
out['cauchy_strain'] = Struct(name='output_data',
mode='cell', data=strain,
dofs=None)
out['cauchy_stress'] = Struct(name='output_data',
mode='cell', data=stress_Y,
dofs=None)
return out
regions = {
'Y': 'all',
'Ym': 'cells of group 1',
'Yc': 'cells of group 2',
}
regions.update(define_box_regions(dim, region_lbn, region_rtf))
materials = {
'mat': ({'D': {'Ym': stiffness_from_youngpoisson(dim, 7.0e9, 0.4),
'Yc': stiffness_from_youngpoisson(dim, 70.0e9, 0.2)}},),
}
fields = {
(continues on next page)
variables = {
'u': ('unknown field', 'corrector', 0),
'v': ('test field', 'corrector', 'u'),
'Pi': ('parameter field', 'corrector', 'u'),
'Pi1': ('parameter field', 'corrector', '(set-to-None)'),
'Pi2': ('parameter field', 'corrector', '(set-to-None)'),
}
functions = {
'match_x_plane': (per.match_x_plane,),
'match_y_plane': (per.match_y_plane,),
'match_z_plane': (per.match_z_plane,),
}
ebcs = {
'fixed_u': ('Corners', {'u.all': 0.0}),
}
if dim == 3:
epbcs = {
'periodic_x': (['Left', 'Right'], {'u.all': 'u.all'},
'match_x_plane'),
'periodic_y': (['Near', 'Far'], {'u.all': 'u.all'},
'match_y_plane'),
'periodic_z': (['Top', 'Bottom'], {'u.all': 'u.all'},
'match_z_plane'),
}
else:
epbcs = {
'periodic_x': (['Left', 'Right'], {'u.all': 'u.all'},
'match_x_plane'),
'periodic_y': (['Bottom', 'Top'], {'u.all': 'u.all'},
'match_y_plane'),
}
integrals = {
'i': 2,
}
options = {
'coefs': 'coefs',
'requirements': 'requirements',
'ls': 'ls', # linear solver to use
'volume': {'expression': 'ev_volume.i.Y(u)'},
'output_dir': 'output',
'coefs_filename': 'coefs_le',
'recovery_hook': 'recovery_le',
(continues on next page)
equation_corrs = {
'balance_of_forces':
"""dw_lin_elastic.i.Y(mat.D, v, u) =
- dw_lin_elastic.i.Y(mat.D, v, Pi)"""
}
coefs = {
'D': {
'requires': ['pis', 'corrs_rs'],
'expression': expr_coefs,
'set_variables': [('Pi1', ('pis', 'corrs_rs'), 'u'),
('Pi2', ('pis', 'corrs_rs'), 'u')],
'class': cb.CoefSymSym,
},
'filenames': {},
}
requirements = {
'pis': {
'variables': ['u'],
'class': cb.ShapeDimDim,
'save_name': 'corrs_pis',
},
'corrs_rs': {
'requires': ['pis'],
'ebcs': ['fixed_u'],
'epbcs': all_periodic,
'equations': equation_corrs,
'set_variables': [('Pi', 'pis', 'u')],
'class': cb.CorrDimDim,
'save_name': 'corrs_le',
'is_linear': True,
},
}
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {
'i_max': 1,
'eps_a': 1e-4,
})
}
homogenization/linear_homogenization_postproc.py
Description
This example shows how to use the VTK postprocessing functions.
source code
"""
This example shows how to use the VTK postprocessing functions.
"""
options.update({
'post_process_hook' : 'post_process',
})
mesh = problem.domain.mesh
mesh_name = mesh.name[mesh.name.rfind(osp.sep) + 1:]
matrix_surf = get_vtk_surface(matrix)
matrix_surf_tri = tetrahedralize_vtk_mesh(matrix_surf)
write_vtk_to_file('%s_mat1_surface.vtk' % mesh_name, matrix_surf_tri)
matrix_edges = get_vtk_edges(matrix)
write_vtk_to_file('%s_mat1_edges.vtk' % mesh_name, matrix_edges)
return out
homogenization/linear_homogenization_up.py
Description
Compute homogenized elastic coefficients for a given heterogeneous linear elastic microstructure, see [1] for details or
[2] and [3] for a quick explanation. The mixed formulation, where displacements and pressures are as unknowns, is
used in this example.
[1] D. Cioranescu, J.S.J. Paulin: Homogenization in open sets with holes. Journal of Mathematical Analysis and
Applications 71(2), 1979, pages 590-607. https://doi.org/10.1016/0022-247X(79)90211-7
[2] J. Pinho-da-Cruz, J.A. Oliveira, F. Teixeira-Dias: Asymptotic homogenisation in linear elasticity. Part I: Mathe-
matical formulation and finite element modelling. Computational Materials Science 45(4), 2009, pages 1073-1080.
http://dx.doi.org/10.1016/j.commatsci.2009.02.025
[3] J. Pinho-da-Cruz, J.A. Oliveira, F. Teixeira-Dias: Asymptotic homogenisation in linear elasticity. Part II: Finite
element procedures and multiscale applications. Computational Materials Science 45(4), 2009, pages 1081-1096.
http://dx.doi.org/10.1016/j.commatsci.2009.01.027
source code
r"""
Compute homogenized elastic coefficients for a given heterogeneous linear
elastic microstructure, see [1] for details or [2] and [3] for a quick
explanation. The mixed formulation, where displacements and pressures are
as unknowns, is used in this example.
out['u_mic'] = Struct(name='output_data',
mode='vertex', data=mic_u,
var_name='u', dofs=None)
out['p_mic'] = Struct(name='output_data',
(continues on next page)
stress_Y, strain_Y = \
compute_stress_strain_u(pb, 'i', 'Y', 'mat.D', 'u', mic_u)
stress_Y += \
compute_mac_stress_part(pb, 'i', 'Y', 'mat.D', 'u', macro['strain'])
add_stress_p(stress_Y, pb, 'i', 'Y', 'p', mic_p)
out['cauchy_strain'] = Struct(name='output_data',
mode='cell', data=strain,
dofs=None)
out['cauchy_stress'] = Struct(name='output_data',
mode='cell', data=stress_Y,
dofs=None)
return out
dim = 3
filename_mesh = data_dir + '/meshes/3d/matrix_fiber.mesh'
region_lbn = (0, 0, 0)
region_rtf = (1, 1, 1)
regions = {
'Y': 'all',
'Ym': 'cells of group 1',
'Yc': 'cells of group 2',
}
regions.update(define_box_regions(dim, region_lbn, region_rtf))
materials = {
'mat': ({'D': {'Ym': stiffness_from_youngpoisson_mixed(dim, 7.0e9, 0.4),
'Yc': stiffness_from_youngpoisson_mixed(dim, 70.0e9, 0.2)},
'gamma': {'Ym': 1.0/bulk_from_youngpoisson(7.0e9, 0.4),
'Yc': 1.0/bulk_from_youngpoisson(70.0e9, 0.2)}},),
}
fields = {
'corrector_u': ('real', dim, 'Y', 1),
'corrector_p': ('real', 1, 'Y', 0),
}
variables = {
'u': ('unknown field', 'corrector_u'),
'v': ('test field', 'corrector_u', 'u'),
'p': ('unknown field', 'corrector_p'),
'q': ('test field', 'corrector_p', 'p'),
'Pi': ('parameter field', 'corrector_u', 'u'),
(continues on next page)
functions = {
'match_x_plane': (per.match_x_plane,),
'match_y_plane': (per.match_y_plane,),
'match_z_plane': (per.match_z_plane,),
}
ebcs = {
'fixed_u': ('Corners', {'u.all': 0.0}),
}
if dim == 3:
epbcs = {
'periodic_x': (['Left', 'Right'], {'u.all': 'u.all'},
'match_x_plane'),
'periodic_y': (['Near', 'Far'], {'u.all': 'u.all'},
'match_y_plane'),
'periodic_z': (['Top', 'Bottom'], {'u.all': 'u.all'},
'match_z_plane'),
}
else:
epbcs = {
'periodic_x': (['Left', 'Right'], {'u.all': 'u.all'},
'match_x_plane'),
'periodic_y': (['Bottom', 'Top'], {'u.all': 'u.all'},
'match_y_plane'),
}
integrals = {
'i': 2,
}
options = {
'coefs': 'coefs',
'requirements': 'requirements',
'ls': 'ls', # linear solver to use
'volume': {'value': get_box_volume(dim, region_lbn, region_rtf), },
'output_dir': 'output',
'coefs_filename': 'coefs_le_up',
'recovery_hook': 'recovery_le',
'multiprocessing': False,
}
equation_corrs = {
'balance_of_forces':
(continues on next page)
coefs = {
'elastic_u': {
'requires': ['pis', 'corrs_rs'],
'expression': 'dw_lin_elastic.i.Y(mat.D, Pi1u, Pi2u)',
'set_variables': [('Pi1u', ('pis', 'corrs_rs'), 'u'),
('Pi2u', ('pis', 'corrs_rs'), 'u')],
'class': cb.CoefSymSym,
},
'elastic_p': {
'requires': ['corrs_rs'],
'expression': 'dw_dot.i.Y(mat.gamma, Pi1p, Pi2p)',
'set_variables': [('Pi1p', 'corrs_rs', 'p'),
('Pi2p', 'corrs_rs', 'p')],
'class': cb.CoefSymSym,
},
'D': {
'requires': ['c.elastic_u', 'c.elastic_p'],
'class': cb.CoefSum,
},
'filenames': {},
}
requirements = {
'pis': {
'variables': ['u'],
'class': cb.ShapeDimDim,
},
'corrs_rs': {
'requires': ['pis'],
'ebcs': ['fixed_u'],
'epbcs': all_periodic,
'equations': equation_corrs,
'set_variables': [('Pi', 'pis', 'u')],
'class': cb.CorrDimDim,
'save_name': 'corrs_le',
'is_linear': True,
},
}
solvers = {
'ls': ('ls.auto_iterative', {}),
'newton': ('nls.newton', {
'i_max': 1,
(continues on next page)
homogenization/material_opt.py
Description
See the Material Identification tutorial for a comprehensive description of this example.
source code
#!/usr/bin/env python
"""
See the :ref:`sec-mat_optim` tutorial for a comprehensive description of this
example.
"""
from __future__ import print_function
from __future__ import absolute_import
import sys
sys.path.append('.')
import numpy as nm
from scipy.optimize import fmin_tnc
import sfepy
from sfepy.base.base import Struct
from sfepy.base.log import Log
class MaterialOptimizer(object):
@staticmethod
def create_app(filename, is_homog=False, **kwargs):
from sfepy.base.conf import ProblemConf, get_standard_keywords
from sfepy.homogenization.homogen_app import HomogenizationApp
from sfepy.applications import PDESolverApp
if is_homog:
(continues on next page)
else:
app = PDESolverApp(conf, options, 'material_opt_macro:')
app.conf.opt_data = {}
opts = conf.options
if hasattr(opts, 'parametric_hook'): # Parametric study.
parametric_hook = conf.get_function(opts.parametric_hook)
app.parametrize(parametric_hook)
return app
@staticmethod
def rotate_mat(D, angle):
s = nm.sin(angle)
c = nm.cos(angle)
s2 = s**2
c2 = c**2
sc = s * c
T = nm.array([[c2, 0, s2, 0, 2*sc,0],
[0, 1, 0, 0, 0, 0],
[s2, 0, c2, 0, -2*sc, 0],
[0, 0, 0, c, 0, -s],
[-sc, 0, sc, 0, c2 - s2, 0],
[0, 0, 0, s, 0, c]])
mic_od['coefs'] = {}
mic_od['mat_params'] = x
self.micro_app()
(continues on next page)
D = mic_od['D_homog']
val = 0.0
aux = []
for phi, exp_k in self.exp_data:
print('phi = %d' % phi)
comp_k = mac_od['k']
val += (1.0 - comp_k / exp_k)**2
aux.append((comp_k, exp_k))
val = nm.sqrt(val)
self.x.append(x)
self.eval_f.append(val)
return val
def material_optimize(self):
x0 = self.x0
bnds = zip(self.x_real2norm(self.x_L), self.x_real2norm(self.x_U))
feval = lambda x: self.matopt_eval(self.x_norm2real(x))
istep = lambda x: self.iter_step(self.x_norm2real(x))
self.iter_step(self.x_norm2real(x0), first_step=True)
self.log(finished=True)
return self.x_norm2real(xopt[0])
def main():
srcdir = sfepy.base_dir + '/examples/homogenization/'
micro_filename = srcdir + 'homogenization_opt.py'
(continues on next page)
optim_par = mo.material_optimize()
print('optimized parameters: ', optim_par)
if __name__ == '__main__':
main()
homogenization/nonlinear_homogenization.py
Description
missing description!
source code
# -*- coding: utf-8 -*-
import numpy as nm
from sfepy.homogenization.utils import define_box_regions
import sfepy.homogenization.coefs_base as cb
import sfepy.discrete.fem.periodic as per
from sfepy.base.base import Struct
from sfepy.terms.terms_hyperelastic_ul import\
HyperElasticULFamilyData, NeoHookeanULTerm, BulkPenaltyULTerm
from sfepy.terms.extmods.terms import sym2nonsym
from sfepy.discrete.functions import ConstantFunctionByRegion
from sfepy import data_dir
import sfepy.linalg as la
out['cauchy_stress'] = Struct(name='output_data',
mode='cell',
(continues on next page)
out['green_strain'] = Struct(name='output_data',
mode='cell',
data=strain,
dofs=None)
out['displacement'] = Struct(name='output_data',
mode='vertex',
data=ncoors[ii] - pb.get_mesh_coors(),
dofs=None)
micro_name = pb.get_output_name(extra='recovered_'
+ recovery_file_tag + suffix)
filename = op.join(output_dir, op.basename(micro_name))
fpv = pb.conf.options.get('file_per_var', False)
pb.save_state(filename, out=out, file_per_var=fpv)
update_var = pb.conf.options.mesh_update_variable
if pb.equations is None:
state_u = pb.create_variables([update_var])[update_var]
else:
state_u = pb.get_variables()[update_var]
if state_u.data[0] is None:
state_u.init_data()
state_u.set_data(
pb.domain.get_mesh_coors(actual=True) - pb.domain.get_mesh_coors())
state_u.field.clear_mappings()
family_data = pb.family_data(state_u, term.region,
term.integral, term.integration)
if len(state_u.field.mappings0) == 0:
state_u.field.save_mappings()
(continues on next page)
conf_mat = pb.conf.materials
solid_key = [key for key in conf_mat.keys() if 'solid' in key][0]
solid_mat = conf_mat[solid_key].values
mat = {}
for mat_key in ['mu', 'K']:
if isinstance(solid_mat[mat_key], dict):
mat_fun = ConstantFunctionByRegion({mat_key: solid_mat[mat_key]})
mat[mat_key] = mat_fun.function(ts=ts, coors=coors, mode='qp',
term=term, problem=pb)[mat_key].reshape((n_el, n_qp, 1, 1))
else:
mat[mat_key] = nm.ones((n_el, n_qp, 1, 1)) * solid_mat[mat_key]
shape = family_data.green_strain.shape[:2]
sym = family_data.green_strain.shape[-2]
dim2 = dim**2
fargs = [family_data.get(name)
for name in NeoHookeanULTerm.family_data_names]
stress = nm.empty(shape + (sym, 1), dtype=nm.float64)
tanmod = nm.empty(shape + (sym, sym), dtype=nm.float64)
NeoHookeanULTerm.stress_function(stress, mat['mu'], *fargs)
NeoHookeanULTerm.tan_mod_function(tanmod, mat['mu'], *fargs)
fargs = [family_data.get(name)
for name in BulkPenaltyULTerm.family_data_names]
stress_p = nm.empty(shape + (sym, 1), dtype=nm.float64)
tanmod_p = nm.empty(shape + (sym, sym), dtype=nm.float64)
BulkPenaltyULTerm.stress_function(stress_p, mat['K'], *fargs)
BulkPenaltyULTerm.tan_mod_function(tanmod_p, mat['K'], *fargs)
npts = nm.prod(shape)
J = family_data.det_f
mtx_f = family_data.mtx_f.reshape((npts, dim, dim))
out = {
'E': 0.5 * (la.dot_sequences(mtx_f, mtx_f, 'ATB') - nm.eye(dim)),
'A': ((tanmod_ns + stress_ns) / J).reshape((npts, dim2, dim2)),
'S': ((stress + stress_p) / J).reshape((npts, sym, 1)),
}
return out
options = {
'coefs': 'coefs',
'requirements': 'requirements',
'volume': {'expression': 'ev_volume.5.Y(u)'},
'output_dir': './output',
'coefs_filename': 'coefs_hyper_homog',
'multiprocessing': True,
'chunks_per_worker': 2,
'micro_update': {'coors': [('corrs_rs', 'u', 'mtx_e')]},
'mesh_update_variable': 'u',
'recovery_hook': 'recovery_hook',
'store_micro_idxs': [49, 81],
}
fields = {
'displacement': ('real', 'vector', 'Y', 1),
}
functions = {
'match_x_plane': (per.match_x_plane,),
'match_y_plane': (per.match_y_plane,),
'mat_fce': (lambda ts, coors, mode=None, term=None, problem=None, **kwargs:
def_mat(ts, mode, coors, term, problem),),
}
materials = {
'mat_he': 'mat_fce',
'solid': ({'K': 1000,
'mu': {'Ym': 100, 'Yc': 10},
},),
}
variables = {
'u': ('unknown field', 'displacement'),
'v': ('test field', 'displacement', 'u'),
'Pi': ('parameter field', 'displacement', 'u'),
'Pi1u': ('parameter field', 'displacement', '(set-to-None)'),
'Pi2u': ('parameter field', 'displacement', '(set-to-None)'),
}
regions = {
'Y': 'all',
'Ym': 'cells of group 1',
'Yc': 'cells of group 2',
}
epbcs = {
'periodic_ux': (['Left', 'Right'], {'u.all': 'u.all'}, 'match_x_plane'),
'periodic_uy': (['Bottom', 'Top'], {'u.all': 'u.all'}, 'match_y_plane'),
}
coefs = {
'A': {
'requires': ['pis', 'corrs_rs'],
'expression': 'dw_nonsym_elastic.3.Y(mat_he.A, Pi1u, Pi2u)',
'set_variables': [('Pi1u', ('pis', 'corrs_rs'), 'u'),
('Pi2u', ('pis', 'corrs_rs'), 'u')],
'class': cb.CoefNonSymNonSym,
},
'S': {
'expression': 'ev_integrate_mat.3.Y(mat_he.S, u)',
'class': cb.CoefOne,
}
}
requirements = {
'pis': {
'variables': ['u'],
'class': cb.ShapeDimDim,
},
'corrs_rs': {
'requires': ['pis'],
'ebcs': ['fixed_u'],
'epbcs': ['periodic_ux', 'periodic_uy'],
'equations': {
'balance_of_forces':
"""dw_nonsym_elastic.3.Y(mat_he.A, v, u)
= - dw_nonsym_elastic.3.Y(mat_he.A, v, Pi)"""
},
'set_variables': [('Pi', 'pis', 'u')],
'class': cb.CorrDimDim,
'save_name': 'corrs_hyper_homog',
},
}
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {
'i_max': 1,
'eps_a': 1e-4,
'problem': 'nonlinear',
}),
}
homogenization/nonlinear_hyperelastic_mM.py
Description
missing description!
source code
import numpy as nm
import six
hyperelastic_data = {}
out['cauchy_stress'] = Struct(name='output_data',
mode='cell',
data=stress,
dofs=None)
out['green_strain'] = Struct(name='output_data',
mode='cell',
data=strain,
dofs=None)
pb.update_materials_flag = 0
if pb.conf.options.get('recover_micro', False):
happ = pb.homogen_app
if pb.ts.step == 0:
rname = pb.conf.options.recovery_region
rcells = pb.domain.regions[rname].get_cells()
sh = hyperelastic_data['homog_mat_shape']
return out
output('get_homog_mat')
dim = problem.domain.mesh.dim
update_var = problem.conf.options.mesh_update_variables[0]
state_u = problem.equations.variables[update_var]
state_u.field.clear_mappings()
family_data = problem.family_data(state_u, term.region,
term.integral, term.integration)
mtx_f = family_data.mtx_f.reshape((coors.shape[0],)
+ family_data.mtx_f.shape[-2:])
if hasattr(problem, 'mtx_f_prev'):
rel_mtx_f = la.dot_sequences(mtx_f, nm.linalg.inv(problem.mtx_f_prev),
'AB')
else:
rel_mtx_f = mtx_f
problem.mtx_f_prev = mtx_f.copy()
hyperelastic_data['time'] = ts.step
hyperelastic_data['homog_mat_shape'] = family_data.det_f.shape[:2]
hyperelastic_data['homog_mat'] = \
(continues on next page)
return out
pb.iiter = it
pb.update_materials_flag = True
pb.update_materials()
pb.update_materials_flag = False
class MyEvaluator(Evaluator):
def eval_residual(self, vec, is_full=False):
if not is_full:
vec = self.problem.equations.make_full_vec(vec)
vec_r = self.problem.equations.eval_residuals(vec * 0)
return vec_r
def ulf_init(pb):
pb.family_data = HyperElasticULFamilyData()
pb_vars = pb.get_variables()
pb_vars['u'].init_data()
pb.update_materials_flag = True
pb.iiter = 0
options = {
'output_dir': 'output',
'mesh_update_variables': ['u'],
'nls_iter_hook': ulf_iteration_hook,
'pre_process_hook': ulf_init,
'micro_filename': 'examples/homogenization/nonlinear_homogenization.py',
'recover_micro': True,
'recovery_region': 'Recovery',
'post_process_hook': post_process,
'user_evaluator': MyEvaluator,
}
materials = {
'solid': 'get_homog',
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
regions = {
'Omega': 'all',
'Left': ('vertices in (x < 0.001)', 'facet'),
'Bottom': ('vertices in (y < 0.001 )', 'facet'),
'Recovery': ('cell 49, 81', 'cell'),
}
ebcs = {
'l': ('Left', {'u.all': 0.0}),
'b': ('Bottom', {'u.all': 'move_bottom'}),
}
return out
functions = {
'move_bottom': (move_bottom,),
'get_homog': (get_homog_mat,),
}
equations = {
'balance_of_forces':
"""dw_nonsym_elastic.1.Omega(solid.A, v, u)
= - dw_lin_prestress.1.Omega(solid.S, v)""",
}
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {
'eps_a': 1e-3,
'eps_r': 1e-3,
'i_max': 20,
(continues on next page)
homogenization/perfusion_micro.py
Description
Homogenization of the Darcy flow in a thin porous layer. The reference cell is composed of the matrix representing
the dual porosity and of two disconnected channels representing the primary porosity, see paper [1].
[1] E. Rohan, V. Lukeš: Modeling Tissue Perfusion Using a Homogenized Model with Layer-wise Decomposition.
IFAC Proceedings Volumes 45(2), 2012, pages 1029-1034. https://doi.org/10.3182/20120215-3-AT-3016.00182
source code
return m1, m2
slev = ''
micro_nnod = pb.domain.mesh.n_nod
channels = {}
for k in six.iterkeys(macro):
if 'press' in k:
channels[k[-1]] = 1
channels = list(channels.keys())
varnames = ['pM']
for ch in channels:
nodes_Y[ch] = pb.domain.regions['Y' + ch].vertices
varnames.append('p' + ch)
pvars = pb.create_variables(varnames)
press = {}
# matrix
press['M'] = \
corrs['corrs_%s_gamma_p' % pb_def['name']]['pM'] * macro['g_p'] + \
corrs['corrs_%s_gamma_m' % pb_def['name']]['pM'] * macro['g_m']
out = {}
# channels
for ch in channels:
press_mac = macro['press' + ch][0, 0]
press_mac_grad = macro['pressg' + ch]
nnod = corrs['corrs_%s_pi%s' % (pb_def['name'], ch)]\
['p%s_0' % ch].shape[0]
press_mic += \
compute_p_from_macro(press_mac_grad[nm.newaxis,nm.newaxis, :, :],
(continues on next page)
pvars['p' + ch].set_data(press_mic)
dvel = pb.evaluate('ev_diffusion_velocity.iV.Y%s(mat1%s.k, p%s)'
% (ch, ch, ch),
var_dict={'p' + ch: pvars['p' + ch]},
mode='el_avg')
pvars['pM'].set_data(press['M'])
dvel = pb.evaluate('%e * ev_diffusion_velocity.iV.YM(mat1M.k, pM)' % eps0,
var_dict={'pM': pvars['pM']}, mode='el_avg')
return out
geoms = {
'2_4': ['2_4_Q1', '2', 5],
'3_8': ['3_8_Q1', '4', 5],
'3_4': ['3_4_P1', '3', 3],
}
pb_def = {
(continues on next page)
filename_mesh = pb_def['mesh_filename']
eps0 = pb_def['eps0']
param_h = pb_def['param_h']
# integrals
integrals = {
'iV': 2,
'iS': 2,
}
functions = {
'match_x_plane': (match_x_plane,),
'match_y_plane': (match_y_plane,),
}
aux = []
for ch, val in six.iteritems(pb_def['channels']):
aux.append('r.bYM' + ch)
# basic regions
regions = {
'Y': 'all',
'YM': 'cells of group %d' % pb_def['matrix_mat_el_grp'],
# periodic boundaries
'Pl': ('vertices in (x < 0.001)', 'facet'),
'Pr': ('vertices in (x > 0.999)', 'facet'),
'PlYM': ('r.Pl *v r.YM', 'facet'),
'PrYM': ('r.Pr *v r.YM', 'facet'),
(continues on next page)
# matrix/channel boundaries
regions.update({
'bYMchs': (' +v '.join(aux), 'facet', 'YM'),
'YMmchs': 'r.YM -v r.bYMchs',
})
if pb_def['dim'] == 2:
regions.update({
'bYm': ('vertices in (y < 0.001)', 'facet'),
'bYp': ('vertices in (y > 0.999)', 'facet'),
})
if pb_def['dim'] == 3:
regions.update({
'Pn': ('vertices in (y < 0.001)', 'facet'),
'Pf': ('vertices in (y > 0.999)', 'facet'),
'PnYM': ('r.Pn *v r.YM', 'facet'),
'PfYM': ('r.Pf *v r.YM', 'facet'),
'bYm': ('vertices in (z < 0.001)', 'facet'),
'bYp': ('vertices in (z > 0.999)', 'facet'),
})
# periodic boundary conditions - matrix, Y-direction
epbcs.update({
'periodic_yYM': (['PnYM', 'PfYM'], {'pM.0': 'pM.0'}, 'match_y_plane'),
})
reg_io = {}
ebcs_eta = {}
ebcs_gamma = {}
if 'fix_nd_grp' in val:
regions.update({
'fixedY' + ch: ('vertices of group %d' % val['fix_nd_grp'][0],
'vertex'),
})
ebcs_eta[ch] = []
for ch2, val2 in six.iteritems(pb_def['channels']):
aux = 'eta%s_bYM%s' % (ch, ch2)
if ch2 == ch:
ebcs.update({aux: ('bYM' + ch2, {'pM.0': 1.0})})
else:
ebcs.update({aux: ('bYM' + ch2, {'pM.0': 0.0})})
ebcs_eta[ch].append(aux)
# boundary conditions
# periodic boundary conditions - channels, X-direction
epbcs.update({
'periodic_xY' + ch: (['PlY' + ch, 'PrY' + ch],
{'p%s.0' % ch: 'p%s.0' % ch},
'match_x_plane'),
})
if pb_def['dim'] == 3:
regions.update({
'PnY' + ch: ('r.Pn *v r.Y' + ch, 'facet'),
'PfY' + ch: ('r.Pf *v r.Y' + ch, 'facet'),
})
# periodic boundary conditions - channels, Y-direction
epbcs.update({
'periodic_yY' + ch: (['PnY' + ch, 'PfY' + ch],
{'p%s.0' % ch: 'p%s.0' % ch},
'match_y_plane'),
})
reg_io[ch] = []
aux_bY = []
# channel: inputs/outputs
for i_io in range(len(val['io_nd_grp'])):
io = '%s_%d' % (ch, i_io+1)
# regions
(continues on next page)
aux_bY.append('r.bY%s' % io)
reg_io[ch].append('bY%s' % io)
regions.update({
'bY' + ch: (' +v '.join(aux_bY), 'facet', 'Y' + ch),
})
# channel: inputs/outputs
for i_io in range(len(val['io_nd_grp'])):
io = '%s_%d' % (ch, i_io + 1)
ion = '%s_n%d' % (ch, i_io + 1)
regions.update({
'bY%s' % ion: ('r.bY%s -v r.bY%s' % (ch, io), 'facet', 'Y%s' % ch),
})
# boundary conditions
aux = 'fix_p%s_bY%s' % (ch, ion)
ebcs.update({
aux: ('bY%s' % ion, {'p%s.0' % ch: 0.0}),
})
lcbcs.update({
'imv' + ch: ('Y' + ch, {'ls%s.all' % ch: None}, None,
'integral_mean_value')
})
materials = {
'mat1M': ({'k': matk1},),
'mat2M': ({'k': matk2},),
}
fields = {
'corrector_M': ('real', 'scalar', 'YM', 1),
'vel_M': ('real', 'vector', 'YM', 1),
'vol_all': ('real', 'scalar', 'Y', 1),
}
fields.update({
'corrector_' + ch: ('real', 'scalar', 'Y' + ch, 1),
'vel_' + ch: ('real', 'vector', 'Y' + ch, 1),
})
variables.update({
'p' + ch: ('unknown field', 'corrector_' + ch),
'q' + ch: ('test field', 'corrector_' + ch, 'p' + ch),
'Pi_' + ch: ('parameter field', 'corrector_' + ch, '(set-to-None)'),
'corr1_' + ch: ('parameter field', 'corrector_' + ch, '(set-to-None)'),
'corr2_' + ch: ('parameter field', 'corrector_' + ch, '(set-to-None)'),
'w' + ch: ('unknown field', 'vel_' + ch),
# lagrange mutltipliers - integral mean value
'ls' + ch: ('unknown field', 'corrector_' + ch),
'lv' + ch: ('test field', 'corrector_' + ch, 'ls' + ch),
})
options = {
'coefs': 'coefs',
'requirements': 'requirements',
'ls': 'ls', # linear solver to use
'volumes': {
'total': {
'variables': ['vol_all'],
'expression': """ev_volume.iV.Y(vol_all)""",
},
'one': {
'value': 1.0,
}
},
'output_dir': './output',
(continues on next page)
for ch in six.iterkeys(reg_io):
for ireg in reg_io[ch]:
options['volumes'].update({
ireg: {
'variables': ['p' + ch],
'expression': "ev_volume.iS.%s(p%s)" % (ireg, ch),
}
})
coefs = {
'vol_bYMpm': {
'regions': ['bYMp', 'bYMm'],
'expression': 'ev_volume.iS.%s(pM)',
'class': cb.VolumeFractions,
},
'filenames': {},
}
requirements = {
'corrs_one_YM': {
'variable': ['pM'],
'ebcs': ['gamma_pm_YMmchs', 'gamma_pm_bYMchs'],
'epbcs': [],
'save_name': 'corrs_one_YM',
'class': cb.CorrSetBCS,
},
}
return None
if mode == 'row':
val = pis.states[ir]['p' + ch] + corrs_pi.states[ir]['p' + ch]
variables['corr1_' + ch].set_data(val)
elif mode == 'col':
val = pis.states[ic]['p' + ch] + corrs_pi.states[ic]['p' + ch]
variables['corr2_' + ch].set_data(val)
pi = pis.states[ir]['p' + ch]
(continues on next page)
pi = pis.states[ir]['p' + ch]
pi = pi - nm.mean(pi)
val = pi + corrs_pi.states[ir]['p' + ch]
variables['corr1_' + ch].set_data(val)
requirements.update({
'pis_' + ch: {
'variables': ['p' + ch],
'class': cb.ShapeDim,
},
'corrs_one' + ch: {
'variable': ['pM'],
'ebcs': ebcs_eta[ch],
'epbcs': [],
'save_name': 'corrs_%s_one%s' % (pb_def['name'], ch),
'class': cb.CorrSetBCS,
},
'corrs_eta' + ch: {
'ebcs': ebcs_eta[ch],
'epbcs': all_periodicYM,
'equations': {
'eq_eta': 'dw_diffusion.iV.YM(mat2M.k, qM, pM) = 0',
(continues on next page)
coefs.update({
'S' + io: { # [Rohan1] (4.28), test+
'requires': ['corrs_gamma_' + io, 'pis_' + ch],
'set_variables': set_corr_S,
'expression': 'dw_diffusion.iV.Y%s(mat2%s.k,corr1_%s,corr2_%s)'
% ((ch,) * 4),
(continues on next page)
requirements.update({
'corrs_gamma_' + io: {
'requires': [],
'variables': ['p' + ch, 'q' + ch],
'ebcs': [],
'epbcs': all_periodicY[ch],
'lcbcs': ['imv' + ch],
'equations': {
'eq_gamma': """dw_diffusion.iV.Y%s(mat2%s.k, q%s, p%s)
+ dw_dot.iV.Y%s(q%s, ls%s)
= %e * dw_integrate.iS.bY%s(q%s)"""
% ((ch,) * 7 + (1.0/param_h, io, ch)),
'eq_imv': 'dw_dot.iV.Y%s(lv%s, p%s) = 0'
% ((ch,) * 3),
},
'class': cb.CorrOne,
'save_name': 'corrs_%s_gamma_%s' % (pb_def['name'], io),
},
})
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {
'i_max': 1,
})
}
homogenization/rs_correctors.py
Description
Compute homogenized elastic coefficients for a given microstructure.
source code
#!/usr/bin/env python
"""
Compute homogenized elastic coefficients for a given microstructure.
"""
from __future__ import print_function
from __future__ import absolute_import
from argparse import ArgumentParser
import sys
import six
sys.path.append('.')
import numpy as nm
def define_regions(filename):
"""
Define various subdomains for a given mesh file.
"""
regions = {}
dim = 2
regions['Y'] = 'all'
out = {}
# in 1e+10 [Pa]
lam = 1.7
mu = 0.3
o = nm.array([1.] * dim + [0.] * (sym - dim), dtype = nm.float64)
oot = nm.outer(o, o)
out['D'] = lam * oot + mu * nm.diag(o + 1.0)
channels_cells = term.region.domain.regions['Yc'].cells
n_cell = term.region.get_n_cells()
val = out['D'].reshape((n_cell, -1, 3, 3))
val[channels_cells] *= 1e-1
return out
##
# Mesh file.
filename_mesh = data_dir + '/meshes/2d/special/osteonT1_11.mesh'
##
# Define regions (subdomains, boundaries) - $Y$, $Y_i$, ...
# depending on a mesh used.
dim, regions = define_regions(filename_mesh)
functions = {
'get_pars' : (lambda ts, coors, **kwargs:
get_pars(ts, coors, **kwargs),),
'match_x_plane' : (per.match_x_plane,),
'match_y_plane' : (per.match_y_plane,),
'match_z_plane' : (per.match_z_plane,),
'match_x_line' : (per.match_x_line,),
'match_y_line' : (per.match_y_line,),
(continues on next page)
##
# Define fields: 'displacement' in $Y$,
# 'pressure_m' in $Y_m$.
fields = {
'displacement' : ('real', dim, 'Y', 1),
}
##
# Define corrector variables: unknown displaements: uc, test: vc
# displacement-like variables: Pi, Pi1, Pi2
variables = {
'uc' : ('unknown field', 'displacement', 0),
'vc' : ('test field', 'displacement', 'uc'),
'Pi' : ('parameter field', 'displacement', 'uc'),
'Pi1' : ('parameter field', 'displacement', None),
'Pi2' : ('parameter field', 'displacement', None),
}
##
# Periodic boundary conditions.
if dim == 3:
epbcs = {
'periodic_x' : (['Left', 'Right'], {'uc.all' : 'uc.all'},
'match_x_plane'),
'periodic_y' : (['Near', 'Far'], {'uc.all' : 'uc.all'},
'match_y_plane'),
'periodic_z' : (['Top', 'Bottom'], {'uc.all' : 'uc.all'},
'match_z_plane'),
}
else:
epbcs = {
'periodic_x' : (['Left', 'Right'], {'uc.all' : 'uc.all'},
'match_y_line'),
'periodic_y' : (['Bottom', 'Top'], {'uc.all' : 'uc.all'},
'match_x_line'),
}
##
# Dirichlet boundary conditions.
ebcs = {
'fixed_u' : ('Corners', {'uc.all' : 0.0}),
}
##
# Material defining constitutive parameters of the microproblem.
materials = {
'm' : 'get_pars',
}
##
(continues on next page)
##
# Homogenized coefficients to compute.
def set_elastic(variables, ir, ic, mode, pis, corrs_rs):
mode2var = {'row' : 'Pi1', 'col' : 'Pi2'}
variables[mode2var[mode]].set_data(val)
coefs = {
'E' : {
'requires' : ['pis', 'corrs_rs'],
'expression' : 'dw_lin_elastic.i3.Y(m.D, Pi1, Pi2)',
'set_variables' : set_elastic,
},
}
##
# Solvers.
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-8,
'eps_r' : 1e-2,
})
}
(continues on next page)
############################################
# Mini-application below, computing the homogenized elastic coefficients.
helps = {
'no_pauses' : 'do not make pauses',
}
def main():
import os
from sfepy.base.base import spause, output
from sfepy.base.conf import ProblemConf, get_standard_keywords
from sfepy.discrete import Problem
import sfepy.homogenization.coefs_base as cb
parser = ArgumentParser(description=__doc__)
parser.add_argument('--version', action='version', version='%(prog)s')
parser.add_argument('-n', '--no-pauses',
action="store_true", dest='no_pauses',
default=False, help=helps['no_pauses'])
options = parser.parse_args()
if options.no_pauses:
def spause(*args):
output(*args)
nm.set_printoptions(precision=3)
spause(r""">>>
First, this file will be read in place of an input
(problem description) file.
Press 'q' to quit the example, press any other key to continue...""")
required, other = get_standard_keywords()
required.remove('equations')
# Use this file as the input file.
conf = ProblemConf.from_file(__file__, required, other)
print(list(conf.to_dict().keys()))
spause(r""">>>
...the read input as a dict (keys only for brevity).
['q'/other key to quit/continue...]""")
spause(r""">>>
Now the input will be used to create a Problem instance.
['q'/other key to quit/continue...]""")
problem = Problem.from_conf(conf, init_equations=False)
# The homogenization mini-apps need the output_dir.
output_dir = ''
problem.output_dir = output_dir
print(problem)
spause(r""">>>
...the Problem instance.
['q'/other key to quit/continue...]""")
spause(r""">>>
Next, $E_{ijkl}$ needs so called steady state correctors $\bar{\omega}^{rs}$,
computed now.
['q'/other key to quit/continue...]""")
req = conf.requirements['corrs_rs']
spause(r""">>>
Then the volume of the domain is needed.
['q'/other key to quit/continue...]""")
volume = problem.evaluate('ev_volume.i3.Y(uc)')
print(volume)
spause(r""">>>
...the volume.
['q'/other key to quit/continue...]""")
spause(r""">>>
Finally, $E_{ijkl}$ can be computed.
['q'/other key to quit/continue...]""")
(continues on next page)
if __name__ == '__main__':
main()
large_deformation
large_deformation/active_fibres.py
Description
Nearly incompressible hyperelastic material model with active fibres.
Large deformation is described using the total Lagrangian formulation. Models of this kind can be used in biomechanics
to model biological tissues, e.g. muscles.
Find 𝑢 such that:
∫︁ (︁ )︁
𝑆 eff (𝑢) + 𝐾(𝐽 − 1) 𝐽𝐶 −1 : 𝛿𝐸(𝑣) d𝑉 = 0 , ∀𝑣 ,
Ω(0)
where
The effective stress 𝑆 eff (𝑢) incorporates also the effects of the active fibres in two preferential directions:
2
− 32 1 ∑︁
eff
𝑆 (𝑢) = 𝜇𝐽 (𝐼 − tr(𝐶)𝐶 −1 ) + 𝜏 𝑘 𝜔𝑘 .
3
𝑘=1
The first term is the neo-Hookean term and the sum add contributions of the two fibre systems. The tensors 𝜔 𝑘 = 𝑑𝑘 𝑑𝑘
are defined by the fibre system direction vectors 𝑑𝑘 (unit).
For the one-dimensional tensions 𝜏 𝑘 holds simply (𝑘 omitted):
{︂ }︂
𝜖 − 𝜀opt 2
𝜏 = 𝐴𝑓max exp −( ) ,𝜖=𝐸 :𝜔.
𝑠
source code
.. math::
\intl{\Omega\suz}{} \left( \ull{S}\eff(\ul{u})
+ K(J-1)\; J \ull{C}^{-1} \right) : \delta \ull{E}(\ul{v}) \difd{V}
= 0
\;, \quad \forall \ul{v} \;,
where
.. list-table::
:widths: 20 80
.. math::
\ull{S}\eff(\ul{u}) = \mu J^{-\frac{2}{3}}(\ull{I}
- \frac{1}{3}\tr(\ull{C}) \ull{C}^{-1})
+ \sum_{k=1}^2 \tau^k \ull{\omega}^k
\;.
The first term is the neo-Hookean term and the sum add contributions of
the two fibre systems. The tensors :math:`\ull{\omega}^k =
\ul{d}^k\ul{d}^k` are defined by the fibre system direction vectors
:math:`\ul{d}^k` (unit).
.. math::
\tau = A f_{\rm max} \exp{\left\{-(\frac{\epsilon - \varepsilon_{\rm
opt}}{s})^2\right\}} \mbox{ , } \epsilon = \ull{E} : \ull{\omega}
\;.
"""
from __future__ import print_function
from __future__ import absolute_import
import numpy as nm
vf_matrix = 0.5
vf_fibres1 = 0.2
vf_fibres2 = 0.3
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 'all',
'post_process_hook' : 'stress_strain',
(continues on next page)
fields = {
'displacement': (nm.float64, 3, 'Omega', 1),
}
materials = {
'solid' : ({
'K' : vf_matrix * 1e3, # bulk modulus
'mu' : vf_matrix * 20e0, # shear modulus of neoHookean term
},),
'f1' : 'get_pars_fibres1',
'f2' : 'get_pars_fibres2',
}
fmax = 10.0
eps_opt = 0.01
s = 1.0
if which == 0: # system 1
fdir = nm.array([1.0, 0.0, 0.0], dtype=nm.float64)
act = 0.5 * (1.0 + nm.sin(tt - (0.5 * nm.pi)))
else:
raise ValueError('unknown fibre system! (%d)' % which)
fdir.shape = (3, 1)
fdir /= nm.linalg.norm(fdir)
(continues on next page)
print(act)
shape = (coors.shape[0], 1, 1)
out = {
'fmax' : vf * nm.tile(fmax, shape),
'eps_opt' : nm.tile(eps_opt, shape),
's' : nm.tile(s, shape),
'fdir' : nm.tile(fdir, shape),
'act' : nm.tile(act, shape),
}
return out
functions = {
'get_pars_fibres1' : (lambda ts, coors, mode=None, **kwargs:
get_pars_fibres(ts, coors, mode=mode, which=0,
vf=vf_fibres1, **kwargs),),
'get_pars_fibres2' : (lambda ts, coors, mode=None, **kwargs:
get_pars_fibres(ts, coors, mode=mode, which=1,
vf=vf_fibres2, **kwargs),),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
}
##
# Dirichlet BC.
ebcs = {
'l' : ('Left', {'u.all' : 0.0}),
}
##
# Balance of forces.
integral_1 = {
'name' : 'i',
'order' : 1,
}
equations = {
'balance'
: """dw_tl_he_neohook.i.Omega( solid.mu, v, u )
+ dw_tl_bulk_penalty.i.Omega( solid.K, v, u )
+ dw_tl_fib_a.i.Omega( f1.fmax, f1.eps_opt, f1.s, f1.fdir, f1.act,
v, u )
(continues on next page)
ev = problem.evaluate
strain = ev('dw_tl_he_neohook.i.Omega( solid.mu, v, u )',
mode='el_avg', term_mode='strain')
out['green_strain'] = Struct(name='output_data',
mode='cell', data=strain, dofs=None)
return out
##
# Solvers etc.
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 7,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp': 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-6,
}
solver_2 = {
'name' : 'ts',
(continues on next page)
't0' : 0,
't1' : 1,
'dt' : None,
'n_step' : 21, # has precedence over dt!
'verbose' : 1,
}
large_deformation/balloon.py
Description
Inflation of a Mooney-Rivlin hyperelastic balloon.
This example serves as a verification of the membrane term (dw_tl_membrane, TLMembraneTerm) implementation.
Following Rivlin 1952 and Dumais, the analytical relation between a relative stretch 𝐿 = 𝑟/𝑟0 of a thin (membrane)
sphere made of the Mooney-Rivlin material of the undeformed radius 𝑟0 , membrane thickness ℎ0 and the inner pressure
𝑝 is
ℎ0 1 1
𝑝=4 ( − 7 )(𝑐1 + 𝑐2 𝐿2 ) ,
𝑟0 𝐿 𝐿
where 𝑐1 , 𝑐2 are the Mooney-Rivlin material parameters.
In the equations below, only the surface of the domain is mechanically important - a stiff 2D membrane is embedded
in the 3D space and coincides with the balloon surface. The volume is very soft, to simulate a fluid-filled cavity. A
similar model could be used to model e.g. plant cells. The balloon surface is loaded by prescribing the inner volume
change 𝜔(𝑡). The fluid pressure in the cavity is a single scalar value, enforced by the 'integral_mean_value' linear
combination condition.
Find 𝑢(𝑋) and a constant 𝑝 such that:
• balance of forces:
∫︁ (︁ )︁ ∫︁
𝑆 eff (𝑢) − 𝑝 𝐽𝐶 −1 : 𝛿𝐸(𝑣; 𝑣) d𝑉 + 𝑆 eff (˜
𝑢)𝛿𝐸(˜
𝑢; 𝑣˜)ℎ0 d𝑆 = 0 , ∀𝑣 ∈ [𝐻01 (Ω)]3 ,
Ω(0) Γ(0)
• volume conservation:
∫︁
[𝜔(𝑡) − 𝐽(𝑢)] 𝑞 𝑑𝑥 = 0 ∀𝑞 ∈ 𝐿2 (Ω) ,
Ω0
where
2 1 4 2
𝑆 eff (𝑢) = 𝜇𝐽 − 3 (𝐼 − tr(𝐶)𝐶 −1 ) + 𝜅𝐽 − 3 (tr(𝐶𝐼 − 𝐶 − ((tr 𝐶)2 − tr (𝐶 2 ))𝐶 −1 ) .
3 6
The 𝑢
˜ and 𝑣˜ variables correspond to 𝑢, 𝑣, respectively, transformed to the membrane coordinate frame.
Use the following command to show a comparison of the FEM solution with the above analytical relation (notice the
nonlinearity of the dependence):
The agreement should be very good, even though the mesh is coarse.
View the results using:
This example uses the adaptive time-stepping solver ('ts.adaptive') with the default adaptivity function
adapt_time_step(). Plot the used time steps by:
source code
r"""
Inflation of a Mooney-Rivlin hyperelastic balloon.
.. math::
- balance of forces:
.. math::
\intl{\Omega\suz}{} \left( \ull{S}\eff(\ul{u})
- p\; J \ull{C}^{-1} \right) : \delta \ull{E}(\ul{v}; \ul{v}) \difd{V}
+ \intl{\Gamma\suz}{} \ull{S}\eff(\tilde{\ul{u}}) \delta
\ull{E}(\tilde{\ul{u}}; \tilde{\ul{v}}) h_0 \difd{S}
= 0 \;, \quad \forall \ul{v} \in [H^1_0(\Omega)]^3 \;,
- volume conservation:
.. math::
\int\limits_{\Omega_0} \left[\omega(t)-J(u)\right] q\, dx = 0
\qquad \forall q \in L^2(\Omega) \;,
where
.. list-table::
:widths: 20 80
* - :math:`\ull{F}`
- deformation gradient :math:`F_{ij} = \pdiff{x_i}{X_j}`
* - :math:`J`
- :math:`\det(F)`
* - :math:`\ull{C}`
(continues on next page)
.. math::
\ull{S}\eff(\ul{u}) = \mu J^{-\frac{2}{3}}(\ull{I}
- \frac{1}{3}\tr(\ull{C}) \ull{C}^{-1})
+ \kappa J^{-\frac{4}{3}} (\tr(\ull{C}\ull{I} - \ull{C}
- \frac{2}{6}((\tr{\ull{C}})^2 - \tr{(\ull{C}^2)})\ull{C}^{-1})
\;.
Use the following command to show a comparison of the FEM solution with the
above analytical relation (notice the nonlinearity of the dependence)::
The agreement should be very good, even though the mesh is coarse.
output = Output('balloon:')
else:
raise ValueError('unknown mode %s!' % mode)
rv = get_rel_volume(rs)
output('relative stretch:', rs)
output('relative volume:', rv)
return out
def get_rel_volume(rel_stretch):
"""
Get relative volume V/V0 from relative stretch r/r0 of a ball.
"""
return nm.power(rel_stretch, 3.0)
def get_rel_stretch(rel_volume):
"""
Get relative stretch r/r0 from relative volume V/V0 of a ball.
"""
return nm.power(rel_volume, 1.0/3.0)
P = 4*h0/r0 * (1/L-1/L^7).*(C1+L^2*C2)
"""
L = rel_stretch
p = 4.0 * h0 / r0 * (1.0/L - 1.0/L**7) * (c1 + c2 * L**2)
return p
plt.rcParams['lines.linewidth'] = 3
plt.rcParams['font.size'] = 16
plt.legend(loc='best')
fig = plt.gcf()
fig.savefig('balloon_pressure_stretch.pdf')
plt.show()
def define(plot=False):
filename_mesh = data_dir + '/meshes/3d/unit_ball.mesh'
conf_dir = os.path.dirname(__file__)
io = MeshIO.any_from_filename(filename_mesh, prefix_dir=conf_dir)
bbox = io.read_bounding_box()
dd = bbox[1] - bbox[0]
radius = bbox[1, 0]
eps = 1e-8 * dd[0]
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 'all',
'output_dir' : '.',
'output_format' : 'h5',
}
if plot:
options['post_process_hook_final'] = plot_radius
fields = {
'displacement': (nm.float64, 3, 'Omega', 1),
'pressure': (nm.float64, 1, 'Omega', 0),
}
materials = {
(continues on next page)
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
'omega' : ('parameter field', 'pressure', {'setter' : 'get_volume'}),
}
regions = {
'Omega' : 'all',
'Ax1' : ('vertices by get_ax1', 'vertex'),
'Ax2' : ('vertices by get_ax2', 'vertex'),
'Equator' : ('vertices by get_equator', 'vertex'),
'Surface' : ('vertices of surface', 'facet'),
}
ebcs = {
'fix1' : ('Ax1', {'u.all' : 0.0}),
'fix2' : ('Ax2', {'u.[0, 1]' : 0.0}),
'fix3' : ('Equator', {'u.1' : 0.0}),
}
lcbcs = {
'pressure' : ('Omega', {'p.all' : None}, None, 'integral_mean_value'),
}
equations = {
'balance'
: """dw_tl_he_neohook.2.Omega(solid.mu, v, u)
+ dw_tl_he_mooney_rivlin.2.Omega(solid.kappa, v, u)
+ dw_tl_membrane.2.Surface(walls.mu, walls.kappa, walls.h0, v, u)
+ dw_tl_bulk_pressure.2.Omega(v, u, p)
= 0""",
'volume'
: """dw_tl_volume.2.Omega(q, u)
= dw_dot.2.Omega(q, omega)""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
(continues on next page)
'dt_red_factor' : 0.8,
'dt_red_max' : 1e-3,
'dt_inc_factor' : 1.25,
'dt_inc_on_iter' : 4,
'dt_inc_wait' : 3,
'verbose' : 1,
'quasistatic' : True,
}),
}
functions = {
'get_ax1' : (lambda coors, domain:
get_nodes(coors, radius, eps, 'ax1'),),
'get_ax2' : (lambda coors, domain:
get_nodes(coors, radius, eps, 'ax2'),),
'get_equator' : (lambda coors, domain:
get_nodes(coors, radius, eps, 'equator'),),
'get_volume' : (get_volume,),
}
return locals()
large_deformation/compare_elastic_materials.py
Description
Compare various elastic materials w.r.t. uniaxial tension/compression test.
Requires Matplotlib.
source code
#!/usr/bin/env python
"""
Compare various elastic materials w.r.t. uniaxial tension/compression test.
Requires Matplotlib.
"""
from __future__ import absolute_import
from argparse import ArgumentParser, RawDescriptionHelpFormatter
import sys
import six
sys.path.append('.')
import numpy as nm
def define():
"""Define the problem to solve."""
from sfepy.discrete.fem.meshio import UserMeshIO
from sfepy.mesh.mesh_generators import gen_block_mesh
from sfepy.mechanics.matcoefs import stiffness_from_lame
filename_mesh = UserMeshIO(mesh_hook)
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 'all',
}
functions = {
'linear_tension' : (linear_tension,),
'linear_compression' : (linear_compression,),
(continues on next page)
fields = {
'displacement' : ('real', 3, 'Omega', 1),
}
# Coefficients are chosen so that the tangent stiffness is the same for all
# material for zero strains.
# Young modulus = 10 kPa, Poisson's ratio = 0.3
materials = {
'solid' : ({
'K' : 8.333, # bulk modulus
'mu_nh' : 3.846, # shear modulus of neoHookean term
'mu_mr' : 1.923, # shear modulus of Mooney-Rivlin term
'kappa' : 1.923, # second modulus of Mooney-Rivlin term
# elasticity for LE term
'D' : stiffness_from_lame(dim=3, lam=5.769, mu=3.846),
},),
'load' : 'empty',
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Bottom' : ('vertices in (z < 0.1)', 'facet'),
'Top' : ('vertices in (z > 2.9)', 'facet'),
}
ebcs = {
'fixb' : ('Bottom', {'u.all' : 0.0}),
'fixt' : ('Top', {'u.[0,1]' : 0.0}),
}
integrals = {
'i' : 1,
'isurf' : 2,
}
equations = {
'linear' : """dw_lin_elastic.i.Omega(solid.D, v, u)
= dw_surface_ltr.isurf.Top(load.val, v)""",
'neo-Hookean' : """dw_tl_he_neohook.i.Omega(solid.mu_nh, v, u)
+ dw_tl_bulk_penalty.i.Omega(solid.K, v, u)
= dw_surface_ltr.isurf.Top(load.val, v)""",
'Mooney-Rivlin' : """dw_tl_he_neohook.i.Omega(solid.mu_mr, v, u)
+ dw_tl_he_mooney_rivlin.i.Omega(solid.kappa, v, u)
+ dw_tl_bulk_penalty.i.Omega(solid.K, v, u)
= dw_surface_ltr.isurf.Top(load.val, v)""",
(continues on next page)
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 5,
'eps_a' : 1e-10,
'eps_r' : 1.0,
}),
'ts' : ('ts.simple', {
't0' : 0,
't1' : 1,
'dt' : None,
'n_step' : 101, # has precedence over dt!
'verbose' : 1,
}),
}
return locals()
##
# Pressure tractions.
def linear_tension(ts, coor, mode=None, **kwargs):
if mode == 'qp':
val = nm.tile(0.1 * ts.step, (coor.shape[0], 1, 1))
return {'val' : val}
def store_top_u(displacements):
"""Function _store() will be called at the end of each loading step. Top
displacements will be stored into `displacements`."""
def _store(problem, ts, state):
top = problem.domain.regions['Top']
top_u = problem.get_variables()['u'].get_state_in_region(top)
displacements.append(nm.mean(top_u[:,-1]))
return _store
load = problem.get_materials()['load']
load.set_function(branch_function)
return displacements
helps = {
'no_plot' : 'do not show plot window',
}
def main():
from sfepy.base.base import output
from sfepy.base.conf import ProblemConf, get_standard_keywords
from sfepy.discrete import Problem
from sfepy.base.plotutils import plt
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('--version', action='version', version='%(prog)s')
parser.add_argument('-n', '--no-plot',
action="store_true", dest='no_plot',
default=False, help=helps['no_plot'])
options = parser.parse_args()
plt.legend(legend, loc = 2)
plt.xlabel('tension [kPa]')
plt.ylabel('displacement [mm]')
plt.grid(True)
plt.gcf().savefig('pressure_displacement.png')
if not options.no_plot:
plt.show()
if __name__ == '__main__':
main()
large_deformation/gen_yeoh_tl_up_interactive.py
Description
This example shows the use of the dw_tl_he_genyeoh hyperelastic term, whose contribution to the deformation energy
density per unit reference volume is given by
(︀ )︀𝑝
𝑊 = 𝐾 𝐼1 − 3
where 𝐼 1 is the first main invariant of the deviatoric part of the right Cauchy-Green deformation tensor 𝐶 and K and p
are its parameters.
This term may be used to implement the generalized Yeoh hyperelastic material model [1] by adding three such terms:
(︀ )︀𝑚 (︀ )︀𝑝 (︀ )︀𝑞
𝑊 = 𝐾1 𝐼 1 − 3 + 𝐾2 𝐼 1 − 3 + 𝐾3 𝐼 1 − 3
where the coefficients 𝐾1 , 𝐾2 , 𝐾3 and exponents 𝑚, 𝑝, 𝑞 are material parameters. Only a single term is used in this
example for the sake of simplicity.
Components of the second Piola-Kirchhoff stress are in the case of an incompressible material
𝜕𝑊 −1 −𝑇
𝑆𝑖𝑗 = 2 − 𝑝 𝐹𝑖𝑘 𝐹𝑘𝑗 ,
𝜕𝐶𝑖𝑗
The following formula holds for the axial true (Cauchy) stress in the case of uniaxial stress:
(︂ )︂𝑚−1 (︂ )︂
2 2 1
𝜎(𝜆) = 𝑚 𝐾1 𝜆2 + −3 𝜆− 2 ,
3 𝜆 𝜆
where 𝜆 = 𝑙/𝑙0 is the prescribed stretch (𝑙0 and 𝑙 being the original and deformed specimen length respectively).
The boundary conditions are set so that a state of uniaxial stress is achieved, i.e. appropriate components of displace-
ment are fixed on the “Left”, “Bottom”, and “Near” faces and a monotonously increasing displacement is prescribed
on the “Right” face. This prescribed displacement is then used to calculate 𝜆 and to convert the second Piola-Kirchhoff
stress to the true (Cauchy) stress.
The three-term generalized Yeoh model is meant to be used for modelling of filled rubbers. The following choice of
parameters is suggested [1] based on experimental data and stability considerations:
𝐾1 > 0,
𝐾2 < 0,
𝐾3 > 0,
0.7 < 𝑚 < 1,
𝑚 < 𝑝 < 𝑞.
Usage Examples
Default options:
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py -p
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
--shape "5, 5, 5"
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
--dims "2, 1, 3"
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
-t 0,15,21
Use higher approximation order (the -t option to decrease the time step is required for convergence here):
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
--order 2 -t 0,2,21
[1] Travis W. Hohenberger, Richard J. Windslow, Nicola M. Pugno, James J. C. Busfield. Aconstitutive Model For
Both Lowand High Strain Nonlinearities In Highly Filled Elastomers And Implementation With User-Defined Material
Subroutines In Abaqus. Rubber Chemistry And Technology, Vol. 92, No. 4, Pp. 653-686 (2019)
source code
#!/usr/bin/env python
r"""
This example shows the use of the `dw_tl_he_genyeoh` hyperelastic term, whose
contribution to the deformation energy density per unit reference volume is
given by
.. math::
W = K \, \left( \overline I_1 - 3 \right)^{p}
where :math:`\overline I_1` is the first main invariant of the deviatoric part
of the right Cauchy-Green deformation tensor :math:`\ull{C}` and `K` and `p`
are its parameters.
This term may be used to implement the generalized Yeoh hyperelastic material
model [1] by adding three such terms:
.. math::
W =
K_1 \, \left( \overline I_1 - 3 \right)^{m}
+K_2 \, \left( \overline I_1 - 3 \right)^{p}
+K_3 \, \left( \overline I_1 - 3 \right)^{q}
where the coefficients :math:`K_1, K_2, K_3` and exponents :math:`m, p, q` are
material parameters. Only a single term is used in this example for the sake of
simplicity.
(continues on next page)
.. math::
S_{ij} = 2 \, \pdiff{W}{C_{ij}} - p \, F^{-1}_{ik} \, F^{-T}_{kj} \;,
.. math::
\intl{\Omega\suz}{} \ull{S}\eff(\ul{u}, p) : \ull{E}(\ul{v})
\difd{V} = 0
\;, \quad \forall \ul{v} \;,
The following formula holds for the axial true (Cauchy) stress in the case of
uniaxial stress:
.. math::
\sigma(\lambda) =
\frac{2}{3} \, m \, K_1 \,
\left( \lambda^2 + \frac{2}{\lambda} - 3 \right)^{m-1} \,
\left( \lambda - \frac{1}{\lambda^2} \right) \;,
The boundary conditions are set so that a state of uniaxial stress is achieved,
i.e. appropriate components of displacement are fixed on the "Left", "Bottom",
and "Near" faces and a monotonously increasing displacement is prescribed on
the "Right" face. This prescribed displacement is then used to calculate
:math:`\lambda` and to convert the second Piola-Kirchhoff stress to the true
(Cauchy) stress.
Usage Examples
--------------
Default options::
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py -p
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
--shape "5, 5, 5"
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
--dims "2, 1, 3"
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
-t 0,15,21
Use higher approximation order (the ``-t`` option to decrease the time step is
required for convergence here)::
$ python sfepy/examples/large_deformation/gen_yeoh_tl_up_interactive.py \
--order 2 -t 0,2,21
SFEPY_DIR = '.'
sys.path.append(SFEPY_DIR)
DIMENSION = 3
def plot_graphs(
material_parameters, global_stress, global_displacement,
undeformed_length):
"""
Plot a comparison of the nominal stress computed by the FEM and using the
(continues on next page)
Parameters
----------
material_parameters : list or tuple of float
The K_1 coefficient and exponent m.
global_displacement
The total displacement for each time step, from the FEM.
global_stress
The true (Cauchy) stress for each time step, from the FEM.
undeformed_length : float
The length of the undeformed specimen.
"""
coef, exp = material_parameters
ax_stress.legend(loc='best').set_draggable(True)
ax_stress.set_ylabel(r'nominal stress $\mathrm{[Pa]}$')
ax_stress.grid()
def stress_strain(
out, problem, _state, order=1, global_stress=None,
global_displacement=None, **_):
"""
Compute the stress and the strain and add them to the output.
Parameters
----------
out : dict
Holds the results of the finite element computation.
problem : sfepy.discrete.Problem
order : int
The approximation order of the displacement field.
(continues on next page)
Returns
-------
out : dict
"""
strain = problem.evaluate(
'dw_tl_he_genyeoh.%d.Omega(m1.par, v, u)' % (2*order),
mode='el_avg', term_mode='strain', copy_materials=False)
out['green_strain'] = Struct(
name='output_data', mode='cell', data=strain, dofs=None)
stress_1 = problem.evaluate(
'dw_tl_he_genyeoh.%d.Omega(m1.par, v, u)' % (2*order),
mode='el_avg', term_mode='stress', copy_materials=False)
stress_p = problem.evaluate(
'dw_tl_bulk_pressure.%d.Omega(v, u, p)' % (2*order),
mode='el_avg', term_mode='stress', copy_materials=False)
stress = stress_1 + stress_p
out['stress'] = Struct(
name='output_data', mode='cell', data=stress, dofs=None)
global_stress.append(stress[0, 0, 0, 0])
global_displacement.append(get_displacement(
problem.ts, np.array([[1., 0, 0]]))[0])
return out
def main(cli_args):
dims = parse_argument_list(cli_args.dims, float)
shape = parse_argument_list(cli_args.shape, int)
centre = parse_argument_list(cli_args.centre, float)
material_parameters = parse_argument_list(cli_args.material_parameters,
float)
order = cli_args.order
ts_vals = cli_args.ts.split(',')
ts = {
't0' : float(ts_vals[0]), 't1' : float(ts_vals[1]),
'n_step' : int(ts_vals[2])}
do_plot = cli_args.plot
term_1 = Term.new(
'dw_tl_he_genyeoh(m1.par, v, u)',
integral, omega, m1=m_1, v=v, u=u)
term_pressure = Term.new(
'dw_tl_bulk_pressure(v, u, p)',
integral, omega, v=v, u=u, p=p)
term_volume_change = Term.new(
'dw_tl_volume(q, u)',
integral, omega, q=q, u=u, term_mode='volume')
term_volume = Term.new(
'dw_integrate(q)',
integral, omega, q=q)
(continues on next page)
pb.solve(save_results=True, post_process_hook=stress_strain_fun)
if do_plot:
plot_graphs(
material_parameters, axial_stress, axial_displacement,
undeformed_length=dims[0])
Parameters
----------
cli_arg : str
type_fun : function
A function to be called on each substring of `cli_arg`; default: str.
value_separator : str
"""
if type_fun is None:
type_fun = str
out = [type_fun(value) for value in cli_arg.split(value_separator)]
return out
def parse_args():
(continues on next page)
if __name__ == '__main__':
args = parse_args()
main(args)
large_deformation/hyperelastic.py
Description
Nearly incompressible Mooney-Rivlin hyperelastic material model.
Large deformation is described using the total Lagrangian formulation. Models of this kind can be used to model e.g.
rubber or some biological materials.
Find 𝑢 such that:
∫︁ (︁ )︁
𝑆 eff (𝑢) + 𝐾(𝐽 − 1) 𝐽𝐶 −1 : 𝛿𝐸(𝑣) d𝑉 = 0 , ∀𝑣 ,
Ω(0)
where
2 1 4 2
𝑆 eff (𝑢) = 𝜇𝐽 − 3 (𝐼 − tr(𝐶)𝐶 −1 ) + 𝜅𝐽 − 3 (tr(𝐶𝐼 − 𝐶 − ((tr 𝐶)2 − tr (𝐶 2 ))𝐶 −1 ) .
3 6
source code
.. math::
\intl{\Omega\suz}{} \left( \ull{S}\eff(\ul{u})
+ K(J-1)\; J \ull{C}^{-1} \right) : \delta \ull{E}(\ul{v}) \difd{V}
= 0
\;, \quad \forall \ul{v} \;,
where
.. list-table::
:widths: 20 80
* - :math:`\ull{F}`
- deformation gradient :math:`F_{ij} = \pdiff{x_i}{X_j}`
* - :math:`J`
- :math:`\det(F)`
* - :math:`\ull{C}`
- right Cauchy-Green deformation tensor :math:`C = F^T F`
* - :math:`\ull{E}(\ul{u})`
- Green strain tensor :math:`E_{ij} = \frac{1}{2}(\pdiff{u_i}{X_j} +
\pdiff{u_j}{X_i} + \pdiff{u_m}{X_i}\pdiff{u_m}{X_j})`
* - :math:`\ull{S}\eff(\ul{u})`
- effective second Piola-Kirchhoff stress tensor
.. math::
\ull{S}\eff(\ul{u}) = \mu J^{-\frac{2}{3}}(\ull{I}
- \frac{1}{3}\tr(\ull{C}) \ull{C}^{-1})
+ \kappa J^{-\frac{4}{3}} (\tr(\ull{C}\ull{I} - \ull{C}
- \frac{2}{6}((\tr{\ull{C}})^2 - \tr{(\ull{C}^2)})\ull{C}^{-1})
\;.
"""
from __future__ import print_function
from __future__ import absolute_import
import numpy as nm
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 'all',
'post_process_hook' : 'stress_strain',
}
field_1 = {
'name' : 'displacement',
(continues on next page)
material_1 = {
'name' : 'solid',
'values' : {
'K' : 1e3, # bulk modulus
'mu' : 20e0, # shear modulus of neoHookean term
'kappa' : 10e0, # shear modulus of Mooney-Rivlin term
}
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
}
##
# Dirichlet BC + related functions.
ebcs = {
'l' : ('Left', {'u.all' : 0.0}),
'r' : ('Right', {'u.0' : 0.0, 'u.[1,2]' : 'rotate_yz'}),
}
return displacement
functions = {
'rotate_yz' : (rotate_yz,),
(continues on next page)
ev = problem.evaluate
strain = ev('dw_tl_he_neohook.i.Omega( solid.mu, v, u )',
mode='el_avg', term_mode='strain')
out['green_strain'] = Struct(name='output_data',
mode='cell', data=strain, dofs=None)
return out
##
# Balance of forces.
integral_1 = {
'name' : 'i',
'order' : 1,
}
equations = {
'balance' : """dw_tl_he_neohook.i.Omega( solid.mu, v, u )
+ dw_tl_he_mooney_rivlin.i.Omega( solid.kappa, v, u )
+ dw_tl_bulk_penalty.i.Omega( solid.K, v, u )
= 0""",
}
##
# Solvers etc.
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
solver_2 = {
'name' : 'ts',
'kind' : 'ts.simple',
't0' : 0,
't1' : 1,
'dt' : None,
'n_step' : 11, # has precedence over dt!
'verbose' : 1,
}
large_deformation/hyperelastic_tl_up_interactive.py
Description
Incompressible Mooney-Rivlin hyperelastic material model. In this model, the deformation energy density per unit
reference volume is given by
(︀ )︀ (︀ )︀
𝑊 = 𝐶(10) 𝐼 1 − 3 + 𝐶(01) 𝐼 2 − 3 ,
where 𝐼 1 and 𝐼 2 are the first and second main invariants of the deviatoric part of the right Cauchy-Green deformation
tensor 𝐶. The coefficients 𝐶(10) and 𝐶(01) are material parameters.
Components of the second Piola-Kirchhoff stress are in the case of an incompressible material
𝜕𝑊 −1 −𝑇
𝑆𝑖𝑗 = 2 − 𝑝 𝐹𝑖𝑘 𝐹𝑘𝑗 ,
𝜕𝐶𝑖𝑗
The following formula holds for the axial true (Cauchy) stress in the case of uniaxial stress:
(︂ )︂ (︂ )︂
𝐶(01) 2 1
𝜎(𝜆) = 2 𝐶(10) + 𝜆 − ,
𝜆 𝜆
where 𝜆 = 𝑙/𝑙0 is the prescribed stretch (𝑙0 and 𝑙 being the original and deformed specimen length respectively).
The boundary conditions are set so that a state of uniaxial stress is achieved, i.e. appropriate components of displace-
ment are fixed on the “Left”, “Bottom”, and “Near” faces and a monotonously increasing displacement is prescribed
on the “Right” face. This prescribed displacement is then used to calculate 𝜆 and to convert the second Piola-Kirchhoff
stress to the true (Cauchy) stress.
The relationship between material parameters used in the SfePy hyperelastic terms (NeoHookeanTLTerm,
MooneyRivlinTLTerm) and the ones used in this example is:
𝜇 = 2 𝐶(10) ,
𝜅 = 2 𝐶(01) .
Usage Examples
Default options:
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py -p
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
--shape "5, 5, 5"
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
--dims "2, 1, 3"
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
-t 0,15,21
Use higher approximation order (the -t option to decrease the time step is required for convergence here):
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
--order 2 -t 0,2,21
source code
#!/usr/bin/env python
r"""
Incompressible Mooney-Rivlin hyperelastic material model.
In this model, the deformation energy density per unit reference volume is
given by
.. math::
W = C_{(10)} \, \left( \overline I_1 - 3 \right)
+ C_{(01)} \, \left( \overline I_2 - 3 \right) \;,
.. math::
S_{ij} = 2 \, \pdiff{W}{C_{ij}} - p \, F^{-1}_{ik} \, F^{-T}_{kj} \;,
.. math::
\intl{\Omega\suz}{} \ull{S}\eff(\ul{u}, p) : \ull{E}(\ul{v})
\difd{V} = 0
\;, \quad \forall \ul{v} \;,
The following formula holds for the axial true (Cauchy) stress in the case of
uniaxial stress:
.. math::
\sigma(\lambda) =
2\, \left( C_{(10)} + \frac{C_{(01)}}{\lambda} \right) \,
\left( \lambda^2 - \frac{1}{\lambda} \right) \;,
The boundary conditions are set so that a state of uniaxial stress is achieved,
i.e. appropriate components of displacement are fixed on the "Left", "Bottom",
and "Near" faces and a monotonously increasing displacement is prescribed on
(continues on next page)
.. math::
\mu = 2\, C_{(10)} \;,
Usage Examples
--------------
Default options::
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py -p
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
--shape "5, 5, 5"
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
--dims "2, 1, 3"
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
-t 0,15,21
Use higher approximation order (the ``-t`` option to decrease the time step is
required for convergence here)::
$ python sfepy/examples/large_deformation/hyperelastic_tl_up_interactive.py \
--order 2 -t 0,2,21
SFEPY_DIR = '.'
sys.path.append(SFEPY_DIR)
DIMENSION = 3
def plot_graphs(
material_parameters, global_stress, global_displacement,
undeformed_length):
"""
Plot a comparison of the true stress computed by the FEM and using the
analytic formula.
Parameters
----------
material_parameters : list or tuple of float
The C10 and C01 coefficients.
global_displacement
The total displacement for each time step, from the FEM.
global_stress
The true (Cauchy) stress for each time step, from the FEM.
undeformed_length : float
The length of the undeformed specimen.
"""
(continues on next page)
fig = plt.figure()
ax_stress = fig.add_subplot(211)
ax_difference = fig.add_subplot(212)
ax_stress.legend(loc='best').set_draggable(True)
ax_stress.set_ylabel(r'true stress $\mathrm{[Pa]}$')
ax_stress.grid()
def stress_strain(
out, problem, _state, order=1, global_stress=None,
global_displacement=None, **_):
"""
Compute the stress and the strain and add them to the output.
Parameters
----------
out : dict
Holds the results of the finite element computation.
problem : sfepy.discrete.Problem
order : int
The approximation order of the displacement field.
global_displacement
Total displacement for each time step, current value will be appended.
global_stress
The true (Cauchy) stress for each time step, current value will be
appended.
Returns
-------
out : dict
"""
strain = problem.evaluate(
'dw_tl_he_neohook.%d.Omega(m.mu, v, u)' % (2*order),
(continues on next page)
out['green_strain'] = Struct(
name='output_data', mode='cell', data=strain, dofs=None)
stress_10 = problem.evaluate(
'dw_tl_he_neohook.%d.Omega(m.mu, v, u)' % (2*order),
mode='el_avg', term_mode='stress', copy_materials=False)
stress_01 = problem.evaluate(
'dw_tl_he_mooney_rivlin.%d.Omega(m.kappa, v, u)' % (2*order),
mode='el_avg', term_mode='stress', copy_materials=False)
stress_p = problem.evaluate(
'dw_tl_bulk_pressure.%d.Omega(v, u, p)' % (2*order),
mode='el_avg', term_mode='stress', copy_materials=False)
stress = stress_10 + stress_01 + stress_p
out['stress'] = Struct(
name='output_data', mode='cell', data=stress, dofs=None)
global_stress.append(stress[0, 0, 0, 0])
global_displacement.append(np.max(out['u'].data[:, 0]))
return out
def main(cli_args):
dims = parse_argument_list(cli_args.dims, float)
shape = parse_argument_list(cli_args.shape, int)
centre = parse_argument_list(cli_args.centre, float)
material_parameters = parse_argument_list(cli_args.material_parameters,
float)
order = cli_args.order
ts_vals = cli_args.ts.split(',')
ts = {
't0' : float(ts_vals[0]), 't1' : float(ts_vals[1]),
'n_step' : int(ts_vals[2])}
do_plot = cli_args.plot
term_neohook = Term.new(
'dw_tl_he_neohook(m.mu, v, u)',
integral, omega, m=m, v=v, u=u)
term_mooney = Term.new(
'dw_tl_he_mooney_rivlin(m.kappa, v, u)',
integral, omega, m=m, v=v, u=u)
term_pressure = Term.new(
'dw_tl_bulk_pressure(v, u, p)',
integral, omega, v=v, u=u, p=p)
term_volume_change = Term.new(
'dw_tl_volume(q, u)',
integral, omega, q=q, u=u, term_mode='volume')
term_volume = Term.new(
'dw_integrate(q)',
integral, omega, q=q)
pb.solve(save_results=True, post_process_hook=stress_strain_fun)
if do_plot:
plot_graphs(
material_parameters, axial_stress, axial_displacement,
undeformed_length=dims[0])
Parameters
----------
cli_arg : str
type_fun : function
A function to be called on each substring of `cli_arg`; default: str.
value_separator : str
"""
if type_fun is None:
type_fun = str
out = [type_fun(value) for value in cli_arg.split(value_separator)]
return out
def parse_args():
"""Parse command line arguments."""
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
'--order', type=int, default=1, help='The approximation order of the '
'displacement field [default: %(default)s]')
(continues on next page)
if __name__ == '__main__':
args = parse_args()
main(args)
large_deformation/hyperelastic_ul.py
Description
Nearly incompressible Mooney-Rivlin hyperelastic material model.
Large deformation is described using the updated Lagrangian formulation. Models of this kind can be used to model
e.g. rubber or some biological materials.
source code
options = {
'nls': 'newton',
'ls': 'ls',
'ts': 'ts',
'ulf': True,
'mesh_update_variables': ['u'],
(continues on next page)
fields = {
'displacement': ('real', 3, 'Omega', 1),
}
materials = {
'solid': ({'K': 1e3, # bulk modulus
'mu': 20e0, # shear modulus of neoHookean term
'kappa': 10e0, # shear modulus of Mooney-Rivlin term
},),
}
variables = {
'u': ('unknown field', 'displacement', 0),
'v': ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
}
##
# Dirichlet BC + related functions.
ebcs = {
'l' : ('Left', {'u.all' : 0.0}),
'r' : ('Right', {'u.0' : 0.0, 'u.[1,2]' : 'rotate_yz'}),
}
return displacement
functions = {
'rotate_yz' : (rotate_yz,),
(continues on next page)
ev = problem.evaluate
strain = ev('dw_ul_he_neohook.3.Omega( solid.mu, v, u )',
mode='el_avg', term_mode='strain')
out['green_strain'] = Struct(name='output_data',
mode='cell', data=strain, dofs=None)
return out
equations = {
'balance': """dw_ul_he_neohook.3.Omega( solid.mu, v, u )
+ dw_ul_he_mooney_rivlin.3.Omega(solid.kappa, v, u)
+ dw_ul_bulk_penalty.3.Omega( solid.K, v, u )
= 0""",
}
##
# Solvers etc.
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {
'i_max': 25,
'eps_a': 1e-8,
'eps_r': 1.0,
'macheps': 1e-16,
'lin_red': 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red': 0.1,
'ls_red_warp': 0.001,
'ls_on': 1.1,
'ls_min': 1e-5,
'check': 0,
'delta': 1e-6,
}),
(continues on next page)
large_deformation/hyperelastic_ul_up.py
Description
Compressible Mooney-Rivlin hyperelastic material model.
Large deformation is described using the updated Lagrangian formulation. Incompressibility is treated by mixed
displacement-pressure formulation. Models of this kind can be used to model e.g. rubber or some biological ma-
terials.
source code
options = {
'nls': 'newton',
'ls': 'ls',
'ts': 'ts',
'ulf': True,
'mesh_update_variables': ['u'],
'output_dir': 'output',
'post_process_hook': 'stress_strain',
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
'pressure': ('real', 'scalar', 'Omega', 0),
}
materials = {
'solid': ({'iK': 1.0 / 1e3, # bulk modulus
'mu': 20e0, # shear modulus of neoHookean term
'kappa': 10e0, # shear modulus of Mooney-Rivlin term
},),
}
variables = {
'u': ('unknown field', 'displacement', 0),
'v': ('test field', 'displacement', 'u'),
'p': ('unknown field', 'pressure', 1),
'q': ('test field', 'pressure', 'p'),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
}
##
# Dirichlet BC + related functions.
(continues on next page)
return displacement
functions = {
'rotate_yz' : (rotate_yz,),
}
ev = problem.evaluate
strain = ev('dw_ul_he_neohook.3.Omega( solid.mu, v, u )',
mode='el_avg', term_mode='strain')
out['green_strain'] = Struct(name='output_data',
mode='cell', data=strain, dofs=None)
return out
##
# Solvers etc.
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton', {
'i_max': 25,
'eps_a': 1e-8,
'eps_r': 1.0,
'macheps': 1e-16,
'lin_red': 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red': 0.1,
'ls_red_warp': 0.001,
'ls_on': 1.1,
'ls_min': 1e-5,
'check': 0,
'delta': 1e-6,
}),
'ts': ('ts.simple', {
't0': 0,
't1': 1,
'dt': None,
'n_step': 11, # has precedence over dt!
'verbose' : 1,
}),
}
large_deformation/perfusion_tl.py
Description
Porous nearly incompressible hyperelastic material with fluid perfusion.
Large deformation is described using the total Lagrangian formulation. Models of this kind can be used in biomechanics
to model biological tissues, e.g. muscles.
Find 𝑢 such that:
(equilibrium equation with boundary tractions)
∫︁ (︁ )︁ ∫︁
𝑆 eff − 𝑝𝐽𝐶 −1 : 𝛿𝐸(𝑣) d𝑉 + 𝜈 · 𝐹 −1 · 𝜎 · 𝑣𝐽 d𝑆 = 0 , ∀𝑣 ,
Ω(0) Γ0
(0)
where
2 1
𝑆 eff (𝑢) = 𝜇𝐽 − 3 (𝐼 − tr(𝐶)𝐶 −1 ) .
3
The linearized deformation-dependent permeability is defined as 𝐾(𝑢) = 𝐽𝐹 −1 𝑘𝑓 (𝐽)𝐹 −𝑇 , where 𝑢 relates to the
(︁ (︁ )︁)︁2
previous time step (𝑛 − 1) and 𝑓 (𝐽) = max 0, 1 + (𝐽−1) 𝑁𝑓 expresses the dependence on volume compres-
sion/expansion.
source code
.. math::
\intl{\Omega\suz}{} \left( \ull{S}\eff - p J \ull{C}^{-1}
\right) : \delta \ull{E}(\ul{v}) \difd{V}
+ \intl{\Gamma_0\suz}{} \ul{\nu} \cdot \ull{F}^{-1} \cdot \ull{\sigma}
\cdot \ul{v} J \difd{S}
= 0
\;, \quad \forall \ul{v} \;,
.. math::
\intl{\Omega\suz}{} q J(\ul{u})
+ \intl{\Omega\suz}{} \ull{K}(\ul{u}\sunm) : \pdiff{q}{X} \pdiff{p}{X}
= \intl{\Omega\suz}{} q J(\ul{u}\sunm)
\;, \quad \forall q \;,
where
.. list-table::
:widths: 20 80
* - :math:`\ull{F}`
- deformation gradient :math:`F_{ij} = \pdiff{x_i}{X_j}`
* - :math:`J`
- :math:`\det(F)`
* - :math:`\ull{C}`
- right Cauchy-Green deformation tensor :math:`C = F^T F`
* - :math:`\ull{E}(\ul{u})`
- Green strain tensor :math:`E_{ij} = \frac{1}{2}(\pdiff{u_i}{X_j} +
\pdiff{u_j}{X_i} + \pdiff{u_m}{X_i}\pdiff{u_m}{X_j})`
* - :math:`\ull{S}\eff(\ul{u})`
- effective second Piola-Kirchhoff stress tensor
.. math::
\ull{S}\eff(\ul{u}) = \mu J^{-\frac{2}{3}}(\ull{I}
- \frac{1}{3}\tr(\ull{C}) \ull{C}^{-1})
\;.
(continues on next page)
# Time-stepping parameters.
t0 = 0.0
t1 = 1.0
n_step = 21
options = {
'nls' : 'newton',
'ls' : 'ls',
'ts' : 'ts',
'save_times' : 'all',
'post_process_hook' : 'post_process',
}
fields = {
'displacement': ('real', 3, 'Omega', 1),
'pressure' : ('real', 1, 'Omega', 1),
}
materials = {
# Perfused solid.
'ps' : ({
'mu' : 20e0, # shear modulus of neoHookean term
'k' : ts.dt * nm.eye(3, dtype=nm.float64), # reference permeability
'N_f' : 1.0, # reference porosity
},),
# Surface pressure traction.
'traction' : 'get_traction',
}
variables = {
'u' : ('unknown field', 'displacement', 0, 1),
'v' : ('test field', 'displacement', 'u'),
'p' : ('unknown field', 'pressure', 1),
(continues on next page)
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
}
##
# Dirichlet BC.
ebcs = {
'l' : ('Left', {'u.all' : 0.0, 'p.0' : 'get_pressure'}),
}
##
# Balance of forces.
integrals = {
'i1' : 1,
'i2' : 2,
}
equations = {
'force_balance'
: """dw_tl_he_neohook.i1.Omega( ps.mu, v, u )
+ dw_tl_bulk_pressure.i1.Omega( v, u, p )
+ dw_tl_surface_traction.i2.Right( traction.pressure, v, u )
= 0""",
'mass_balance'
: """dw_tl_volume.i1.Omega( q, u )
+ dw_tl_diffusion.i1.Omega( ps.k, ps.N_f, q, p, u[-1])
= dw_tl_volume.i1.Omega( q, u[-1] )"""
}
return out
##
# Solvers etc.
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 7,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp': 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-6,
}
solver_2 = {
'name' : 'ts',
'kind' : 'ts.simple',
't0' : t0,
't1' : t1,
'dt' : None,
'n_step' : n_step, # has precedence over dt!
'verbose' : 1,
}
##
# Functions.
def get_traction(ts, coors, mode=None):
"""
Pressure traction.
Parameters
----------
ts : TimeStepper
Time stepping info.
(continues on next page)
dim = coors.shape[1]
val = 0.05 * nm.sin(tt) * nm.eye(dim, dtype=nm.float64)
val[1,0] = val[0,1] = 0.5 * val[0,0]
shape = (coors.shape[0], 1, 1)
out = {
'pressure' : nm.tile(val, shape),
}
return out
return val
functions = {
'get_traction' : (lambda ts, coors, mode=None, **kwargs:
get_traction(ts, coors, mode=mode),),
'get_pressure' : (get_pressure,),
}
linear_elasticity
linear_elasticity/dispersion_analysis.py
Description
Dispersion analysis of a heterogeneous finite scale periodic cell.
The periodic cell mesh has to contain two subdomains Y1 (with the cell ids 1), Y2 (with the cell ids 2), so that different
material properties can be defined in each of the subdomains (see --pars option). The command line parameters can
be given in any consistent unit set, for example the basic SI units. The --unit-multipliers option can be used to
rescale the input units to ones more suitable to the simulation, for example to prevent having different matrix blocks
with large differences of matrix entries magnitudes. The results are then in the rescaled units.
Usage Examples
Default material parameters, a square periodic cell with a spherical inclusion, logs also standard pressure dilatation
and shear waves, no eigenvectors:
As above, with custom eigenvalue solver parameters, and different number of eigenvalues, mesh size and units used in
the calculation:
Default material parameters, a square periodic cell with a square inclusion, and a very small mesh to allow comparing
the omega and kappa modes (full matrix solver required!):
˓→3 -o output/omega
In contrast to the heterogeneous square periodic cell, a homogeneous square periodic cell (the region Y2 is empty):
˓→3 -o output/omega-h
Additional arguments can be passed to the problem configuration’s define() function using the --define-kwargs
option. In this file, only the mesh vertex separation parameter mesh_eps can be used:
˓→regions
source code
#!/usr/bin/env python
"""
Dispersion analysis of a heterogeneous finite scale periodic cell.
The periodic cell mesh has to contain two subdomains Y1 (with the cell ids 1),
Y2 (with the cell ids 2), so that different material properties can be defined
in each of the subdomains (see ``--pars`` option). The command line parameters
can be given in any consistent unit set, for example the basic SI units. The
``--unit-multipliers`` option can be used to rescale the input units to ones
more suitable to the simulation, for example to prevent having different
matrix blocks with large differences of matrix entries magnitudes. The results
are then in the rescaled units.
Usage Examples
--------------
˓→2,1e-3 -o output/omega
˓→2,1e-3 -o output/omega-h
"""
from __future__ import absolute_import
import os
import sys
sys.path.append('.')
import gc
from copy import copy
from argparse import ArgumentParser, RawDescriptionHelpFormatter
pars_kinds = {
'young1' : 'stress',
'poisson1' : 'one',
'density1' : 'density',
'young2' : 'stress',
'poisson2' : 'one',
'density2' : 'density',
}
options = {
'absolute_mesh_path' : True,
'refinement_level' : refinement_level,
'allow_empty_regions' : True,
'post_process_hook' : 'compute_von_mises' if post_process else None,
}
fields = {
'displacement': ('complex', dim, 'Omega', approx_order),
}
materials = {
'm' : ({
'D' : {'Y1' : stiffness(dim,
young=pars.young1,
poisson=pars.poisson1,
plane=plane),
(continues on next page)
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Y1': 'cells of group 1',
'Y2': 'cells of group 2',
}
regions.update(define_box_regions(dim,
bbox[0], bbox[1], mesh_eps))
ebcs = {
}
if dim == 3:
epbcs = {
'periodic_x' : (['Left', 'Right'], {'u.all' : 'u.all'},
'match_x_plane'),
'periodic_y' : (['Near', 'Far'], {'u.all' : 'u.all'},
'match_y_plane'),
'periodic_z' : (['Top', 'Bottom'], {'u.all' : 'u.all'},
'match_z_plane'),
}
else:
epbcs = {
'periodic_x' : (['Left', 'Right'], {'u.all' : 'u.all'},
'match_y_line'),
'periodic_y' : (['Bottom', 'Top'], {'u.all' : 'u.all'},
'match_x_line'),
}
per.set_accuracy(mesh_eps)
functions = {
'match_x_plane' : (per.match_x_plane,),
'match_y_plane' : (per.match_y_plane,),
'match_z_plane' : (per.match_z_plane,),
'match_x_line' : (per.match_x_line,),
'match_y_line' : (per.match_y_line,),
'get_wdir' : (get_wdir,),
}
equations = {
'K' : 'dw_lin_elastic.i.Omega(m.D, v, u)',
'S' : 'dw_elastic_wave.i.Omega(m.D, wave.vec, v, u)',
'R' : """1j * dw_elastic_wave_cauchy.i.Omega(m.D, wave.vec, u, v)
- 1j * dw_elastic_wave_cauchy.i.Omega(m.D, wave.vec, v, u)""",
'M' : 'dw_dot.i.Omega(m.density, v, u)',
}
solver_0 = solver_conf.copy()
solver_0['name'] = 'eig'
return locals()
out = {}
out['young'] = Struct(name='young', mode='cell',
data=young[..., None, None])
out['poisson'] = Struct(name='poisson', mode='cell',
data=poisson[..., None, None])
out['density'] = Struct(name='density', mode='cell', data=density)
materials_filename = os.path.join(output_dir, 'materials.vtk')
pb.save_state(materials_filename, out=out)
if options.mode == 'omega':
fun = lambda wmag, wdir: (cp * wmag, cs * wmag)
else:
fun = lambda wmag, wdir: (wmag / cp, wmag / cs)
bbox = pb.domain.mesh.get_bounding_box()
num = rng[2] // 3
class BrillouinStepper(Struct):
"""
Step over 1. Brillouin zone in xy plane.
"""
def __init__(self, t0, t1, dt=None, n_step=None, step=None, **kwargs):
Struct.__init__(self, t0=t0, t1=t1, dt=dt, n_step=n_step, step=step)
def __iter__(self):
ts = TimeStepper(0, bzone[0], dt=None, n_step=num)
for ii, val in ts:
yield ii, val, nm.array([1.0, 0.0])
if ii == (num-2): break
return stepper
vms = get_von_mises_stress(stress.squeeze())
vms.shape = (vms.shape[0], 1, 1, 1)
out['von_mises_stress'] = Struct(name='output_data', mode='cell',
data=vms)
return out
variables = pb.set_default_state()
# Make full eigenvectors (add DOFs fixed by boundary conditions).
vecs = nm.empty((variables.di.ptr[-1], svecs.shape[1]),
dtype=svecs.dtype)
for ii in range(svecs.shape[1]):
vecs[:, ii] = variables.make_full_vec(svecs[:, ii])
pp_name = pb.conf.options.get('post_process_hook')
pp = getattr(pb.conf.funmod, pp_name if pp_name is not None else '',
lambda out, *args, **kwargs: out)
for ii in range(svecs.shape[1]):
variables.set_state(vecs[:, ii])
aux = variables.create_output()
aux2 = {}
pp(aux2, pb, variables, wmag=wmag, wdir=wdir)
aux.update(convert_complex_output(aux2))
(continues on next page)
pb.save_state(filename, out=out)
pb = Problem.from_conf(conf)
pb.dispersion_options = options
pb.set_output_dir(options.output_dir)
dim = pb.domain.shape.dim
bbox = pb.domain.mesh.get_bounding_box()
size = (bbox[1] - bbox[0]).max()
scaling0 = apply_unit_multipliers([1.0], ['length'],
options.unit_multipliers)[0]
scaling = scaling0
if options.mesh_size is not None:
scaling *= options.mesh_size / size
output('scaling factor of periodic cell mesh coordinates:', scaling)
output('new mesh size with applied unit multipliers:', scaling * size)
pb.domain.mesh.coors[:] *= scaling
pb.set_mesh_coors(pb.domain.mesh.coors, update_fields=True)
pb.time_update()
pb.update_materials()
output('symmetry checks:')
output('%s - %s^T:' % (key, key), max_diff_csr(mtx, mtx.T))
output('%s - %s^H:' % (key, key), max_diff_csr(mtx, mtx.H))
else:
if options.n_eigs > 2 * n_dof:
n_eigs = 2 * n_dof
solver_n_eigs = None
else:
evp_mtxs = (mtxs['S'], mtxs['R'], mtxs['K'] - val**2 * mtxs['M'])
return evp_mtxs
output('eigs, omegas:')
for ii, om in enumerate(omegas):
output('{:>3}. {: .10e}, {:.10e}'.format(ii, eigs[ii], om))
if options.stepper == 'linear':
out = tuple(eigs) + tuple(omegas)
else:
out = tuple(val * wdir) + tuple(omegas)
else:
kappas = eigs.copy()
rks = kappas.copy()
helps = {
'pars' :
'material parameters in Y1, Y2 subdomains in basic units.'
' The default parameters are:'
' young1, poisson1, density1, young2, poisson2, density2'
' [default: %(default)s]',
(continues on next page)
def main():
# Aluminium and epoxy.
default_pars = '70e9,0.35,2.799e3,3.8e9,0.27,1.142e3'
(continues on next page)
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('--pars', metavar='name1=value1,name2=value2,...'
' or value1,value2,...',
action='store', dest='pars',
default=default_pars, help=helps['pars'])
parser.add_argument('--conf', metavar='filename',
action='store', dest='conf',
default=None, help=helps['conf'])
parser.add_argument('--define-kwargs', metavar='dict-like',
action='store', dest='define_kwargs',
default=None, help=helps['define_kwargs'])
parser.add_argument('--mesh-size', type=float, metavar='float',
action='store', dest='mesh_size',
default=None, help=helps['mesh_size'])
parser.add_argument('--unit-multipliers',
metavar='c_time,c_length,c_mass',
action='store', dest='unit_multipliers',
default='1.0,1.0,1.0', help=helps['unit_multipliers'])
parser.add_argument('--plane', action='store', dest='plane',
choices=['strain', 'stress'],
default='strain', help=helps['plane'])
parser.add_argument('--wave-dir', metavar='float,float[,float]',
action='store', dest='wave_dir',
default='1.0,0.0,0.0', help=helps['wave_dir'])
parser.add_argument('--mode', action='store', dest='mode',
choices=['omega', 'kappa'],
default='omega', help=helps['mode'])
parser.add_argument('--stepper', action='store', dest='stepper',
choices=['linear', 'brillouin'],
default='linear', help=helps['stepper'])
parser.add_argument('--range', metavar='start,stop,count',
action='store', dest='range',
default='0,6.4,33', help=helps['range'])
parser.add_argument('--order', metavar='int', type=int,
action='store', dest='order',
default=1, help=helps['order'])
parser.add_argument('--refine', metavar='int', type=int,
action='store', dest='refine',
default=0, help=helps['refine'])
parser.add_argument('-n', '--n-eigs', metavar='int', type=int,
action='store', dest='n_eigs',
default=6, help=helps['n_eigs'])
group = parser.add_mutually_exclusive_group()
group.add_argument('--eigs-only',
action='store_true', dest='eigs_only',
default=False, help=helps['eigs_only'])
group.add_argument('--post-process',
action='store_true', dest='post_process',
(continues on next page)
output_dir = options.output_dir
output.set_output(filename=os.path.join(output_dir,'output_log.txt'),
combined=options.silent == False)
else:
mod = sys.modules[__name__]
pars_kinds = mod.pars_kinds
define = mod.define
set_wave_dir = mod.set_wave_dir
setup_n_eigs = mod.setup_n_eigs
build_evp_matrices = mod.build_evp_matrices
save_materials = mod.save_materials
get_std_wave_fun = mod.get_std_wave_fun
get_stepper = mod.get_stepper
process_evp_results = mod.process_evp_results
(continues on next page)
try:
options.pars = dict_from_string(options.pars)
except:
aux = [float(ii) for ii in options.pars.split(',')]
options.pars = {key : aux[ii]
for ii, key in enumerate(pars_kinds.keys())}
options.unit_multipliers = [float(ii)
for ii in options.unit_multipliers.split(',')]
options.wave_dir = [float(ii)
for ii in options.wave_dir.split(',')]
aux = options.range.split(',')
options.range = [float(aux[0]), float(aux[1]), int(aux[2])]
options.solver_conf = dict_from_string(options.solver_conf)
options.define_kwargs = dict_from_string(options.define_kwargs)
if options.clear:
remove_files_patterns(output_dir,
['*.h5', '*.vtk', '*.txt'],
ignores=['output_log.txt'],
verbose=True)
pars = Struct(**pars)
if options.mode == 'omega':
rng = copy(options.range)
rng[:2] = apply_unit_multipliers(options.range[:2],
['wave_number', 'wave_number'],
options.unit_multipliers)
output('wave number range with applied unit multipliers:', rng)
else:
if options.stepper == 'brillouin':
raise ValueError('Cannot use "brillouin" stepper in kappa mode!')
rng = copy(options.range)
rng[:2] = apply_unit_multipliers(options.range[:2],
(continues on next page)
if dim != 2:
options.plane = 'strain'
if options.save_regions:
pb.save_regions_as_groups(os.path.join(output_dir, 'regions'))
if options.save_materials:
save_materials(output_dir, pb, options)
conf = pb.solver_confs['eig']
eig_solver = Solver.any_from_conf(conf)
log_names = []
log_plot_kwargs = []
if options.log_std_waves:
std_wave_fun, log_names, log_plot_kwargs = get_std_wave_fun(
pb, options)
else:
std_wave_fun = None
if options.mode == 'omega':
eigenshapes_filename = os.path.join(output_dir,
'frequency-eigenshapes-%s.vtk'
% stepper.suffix)
if options.stepper == 'linear':
log = Log([[r'$\lambda_{%d}$' % ii for ii in range(options.n_eigs)],
[r'$\omega_{%d}$'
% ii for ii in range(options.n_eigs)] + log_names],
plot_kwargs=[plot_kwargs, plot_kwargs + log_plot_kwargs],
formats=[['{:.12e}'] * options.n_eigs,
(continues on next page)
else:
log = Log([[r'$\kappa_{%d}$'% ii for ii in range(dim)],
[r'$\omega_{%d}$'
% ii for ii in range(options.n_eigs)] + log_names],
plot_kwargs=[plot_kwargs_dim,
plot_kwargs + log_plot_kwargs],
formats=[['{:.12e}'] * dim,
['{:.12e}'] * (options.n_eigs + len(log_names))],
yscales=['linear', 'linear'],
xlabels=[r'', r''],
ylabels=[r'wave vector $\kappa$',
r'frequencies $\omega_i$'],
show_legends=options.show_legends,
is_plot=options.show,
log_filename=os.path.join(output_dir, 'frequencies.txt'),
aggregate=1000, sleep=0.1)
else:
iv, wmag, wdir = aux
if options.stepper == 'brillouin':
pb, _, bzone, mtxs = assemble_matrices(
define, mod, pars, set_wave_dir, options, wdir=wdir)
if options.eigs_only:
eigs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
eigenvectors=False)
svecs = None
else:
eigs, svecs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
eigenvectors=True)
else:
log(*out, x=[iv, iv])
gc.collect()
log(save_figure=os.path.join(output_dir, 'frequencies.png'))
log(finished=True)
else:
eigenshapes_filename = os.path.join(output_dir,
'wave-number-eigenshapes-%s.vtk'
% stepper.suffix)
if options.eigs_only:
eigs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
eigenvectors=False)
svecs = None
else:
eigs, svecs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
eigenvectors=True)
gc.collect()
log(save_figure=os.path.join(output_dir, 'wave-numbers.png'))
log(finished=True)
if __name__ == '__main__':
main()
linear_elasticity/elastic_contact_planes.py
Description
Elastic contact planes simulating an indentation test.
Four contact planes bounded by polygons (triangles in this case) form a very rigid pyramid shape simulating an indentor.
Find 𝑢 such that:
∫︁ 4 ∫︁
∑︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) + 𝑣 · 𝑓 𝑖 (𝑑(𝑢))𝑛𝑖 = 0 ,
Ω 𝑖=1 Γ𝑖
where
Notes
Even though the material is linear elastic and small deformations are used, the problem is highly nonlinear due to
contacts with the planes.
Checking the tangent matrix by finite differences by setting ‘check’ in ‘nls’ solver configuration to nonzero is rather
tricky - the active contact points must not change during the test. This can be ensured by a sufficient initial penetration
and large enough contact boundary polygons (hard!), or by tweaking the dw_contact_plane term to mask points only
by undeformed coordinates.
source code
r"""
Elastic contact planes simulating an indentation test.
Four contact planes bounded by polygons (triangles in this case) form a very
rigid pyramid shape simulating an indentor.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
+ \sum_{i=1}^4 \int_{\Gamma_i} \ul{v} \cdot f^i(d(\ul{u})) \ul{n^i}
= 0 \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl} + \delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
Notes
(continues on next page)
Even though the material is linear elastic and small deformations are used, the
problem is highly nonlinear due to contacts with the planes.
options = {
'ts' : 'ts',
'nls' : 'newton',
'ls' : 'lsd',
'output_format': 'vtk',
}
fields = {
'displacement': ('real', 3, 'Omega', 1),
}
materials = {
'solid' : ({
'D': stiffness_from_lame(dim=3, lam=5.769, mu=3.846),
},),
'cp0' : ({
'f' : [k, f0],
'.n' : [dn, 0.0, 1.0],
'.a' : [0.0, 0.0, az],
'.bs' : [[0.0, 0.0, az],
[-ds, -ds, az],
[-ds, ds, az]],
},),
'cp1' : ({
'f' : [k, f0],
'.n' : [-dn, 0.0, 1.0],
'.a' : [0.0, 0.0, az],
(continues on next page)
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Bottom' : ('vertices in (z < -0.499)', 'facet'),
'Top' : ('vertices in (z > 0.499)', 'facet'),
}
ebcs = {
'fixed' : ('Bottom', {'u.all' : 0.0}),
}
equations = {
'elasticity' :
"""dw_lin_elastic.2.Omega(solid.D, v, u)
+ dw_contact_plane.2.Top(cp0.f, cp0.n, cp0.a, cp0.bs, v, u)
+ dw_contact_plane.2.Top(cp1.f, cp1.n, cp1.a, cp1.bs, v, u)
+ dw_contact_plane.2.Top(cp2.f, cp2.n, cp2.a, cp2.bs, v, u)
+ dw_contact_plane.2.Top(cp3.f, cp3.n, cp3.a, cp3.bs, v, u)
= 0""",
}
solvers = {
'lsd' : ('ls.scipy_direct', {}),
'lsi' : ('ls.petsc', {
'method' : 'cg',
'eps_r' : 1e-8,
(continues on next page)
def main():
import os
import numpy as nm
import matplotlib.pyplot as plt
conf_dir = os.path.dirname(__file__)
io = MeshIO.any_from_filename(filename_mesh, prefix_dir=conf_dir)
bb = io.read_bounding_box()
outline = [vv for vv in la.combine(zip(*bb))]
v1, v2 = la.get_perpendiculars(cp.normal)
ax = plot_polygon(ax, cp.bounds)
ax = plot_polygon(ax, nm.r_[cp.anchor[None, :],
cp.anchor[None, :] + cp.normal[None, :]])
ax = plot_polygon(ax, nm.r_[cp.anchor[None, :],
cp.anchor[None, :] + v1])
ax = plot_polygon(ax, nm.r_[cp.anchor[None, :],
cp.anchor[None, :] + v2])
plt.show()
if __name__ == '__main__':
main()
linear_elasticity/elastic_contact_sphere.py
Description
Elastic contact sphere simulating an indentation test.
Find 𝑢 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) + 𝑣 · 𝑓 (𝑑(𝑢))𝑛(𝑢) = 0 ,
Ω Γ
where
Notes
Even though the material is linear elastic and small deformations are used, the problem is highly nonlinear due to
contacts with the sphere. See also elastic_contact_planes.py example.
source code
r"""
Elastic contact sphere simulating an indentation test.
(continues on next page)
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
+ \int_{\Gamma} \ul{v} \cdot f(d(\ul{u})) \ul{n}(\ul{u})
= 0 \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl} + \delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
Notes
-----
Even though the material is linear elastic and small deformations are used, the
problem is highly nonlinear due to contacts with the sphere. See also
elastic_contact_planes.py example.
"""
from __future__ import absolute_import
from sfepy import data_dir
from sfepy.mechanics.matcoefs import stiffness_from_lame
options = {
'nls' : 'newton',
'ls' : 'ls',
'output_format': 'vtk',
}
fields = {
'displacement': ('real', 3, 'Omega', 1),
}
materials = {
'solid' : ({
'D': stiffness_from_lame(dim=3, lam=5.769, mu=3.846),
},),
'cs' : ({
'f' : [k, f0],
'.c' : [0.0, 0.0, 1.2],
'.r' : 0.8,
},),
}
(continues on next page)
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Bottom' : ('vertices in (z < -0.499)', 'facet'),
'Top' : ('vertices in (z > 0.499)', 'facet'),
}
ebcs = {
'fixed' : ('Bottom', {'u.all' : 0.0}),
}
equations = {
'elasticity' :
"""dw_lin_elastic.2.Omega(solid.D, v, u)
+ dw_contact_sphere.2.Top(cs.f, cs.c, cs.r, v, u)
= 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 20,
'eps_a' : 1e-1,
'ls_on' : 2.0,
'check' : 0,
'delta' : 1e-6,
}),
}
def main():
import os
import numpy as nm
import matplotlib.pyplot as plt
conf_dir = os.path.dirname(__file__)
io = MeshIO.any_from_filename(filename_mesh, prefix_dir=conf_dir)
bb = io.read_bounding_box()
outline = [vv for vv in la.combine(zip(*bb))]
plt.show()
if __name__ == '__main__':
main()
linear_elasticity/elastic_shifted_periodic.py
Description
Linear elasticity with linear combination constraints and periodic boundary conditions.
The linear combination constraints are used to apply periodic boundary conditions with a shift in the second axis
direction.
Find 𝑢 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = − 𝑣·𝜎·𝑛, ∀𝑣 ,
Ω Γ𝑏𝑜𝑡𝑡𝑜𝑚
𝑢 = 0 on Γ𝑙𝑒𝑓 𝑡 ,
𝑢1 = 𝑢2 = 0 on Γ𝑟𝑖𝑔ℎ𝑡 ,
𝑢(𝑥) = 𝑢(𝑦) for 𝑥 ∈ Γ𝑏𝑜𝑡𝑡𝑜𝑚 , 𝑦 ∈ Γ𝑡𝑜𝑝 , 𝑦 = 𝑃1 (𝑥) ,
𝑢(𝑥) = 𝑢(𝑦) + 𝑎(𝑦) for 𝑥 ∈ Γ𝑛𝑒𝑎𝑟 , 𝑦 ∈ Γ𝑓 𝑎𝑟 , 𝑦 = 𝑃2 (𝑥) ,
where
and the traction 𝜎 · 𝑛 = 𝑝¯𝐼 · 𝑛 is given in terms of traction pressure 𝑝¯. The function 𝑎(𝑦) is given (the shift), 𝑃1 and
𝑃2 are the periodic coordinate mappings.
View the results using:
source code
r"""
Linear elasticity with linear combination constraints and periodic boundary
conditions.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= - \int_{\Gamma_{bottom}} \ul{v} \cdot \ull{\sigma} \cdot \ul{n}
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;,
options = {
'nls' : 'newton',
'ls' : 'ls',
'post_process_hook' : 'post_process'
}
ev = pb.evaluate
stress = ev('ev_cauchy_stress.2.Omega(solid.D, u)', mode='el_avg')
vms = get_von_mises_stress(stress.squeeze())
vms.shape = (vms.shape[0], 1, 1, 1)
out['von_mises_stress'] = Struct(name='output_data', mode='cell',
data=vms, dofs=None)
return out
(continues on next page)
functions = {
'get_shift' : (get_shift,),
'linear_tension' : (linear_tension,),
'match_y_plane' : (per.match_y_plane,),
'match_z_plane' : (per.match_z_plane,),
}
fields = {
'displacement': ('real', 3, 'Omega', 1),
}
materials = {
'solid' : ({
'D' : stiffness_from_lame(3, lam=5.769, mu=3.846),
},),
'load' : (None, 'linear_tension')
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -4.99)', 'facet'),
'Right' : ('vertices in (x > 4.99)', 'facet'),
'Bottom' : ('vertices in (z < -0.99)', 'facet'),
'Top' : ('vertices in (z > 0.99)', 'facet'),
'Near' : ('vertices in (y < -0.99)', 'facet'),
'Far' : ('vertices in (y > 0.99)', 'facet'),
}
ebcs = {
'fix1' : ('Left', {'u.all' : 0.0}),
'fix2' : ('Right', {'u.[1,2]' : 0.0}),
}
epbcs = {
(continues on next page)
lcbcs = {
'shifted' : (('Near', 'Far'),
{'u.all' : 'u.all'},
'match_y_plane', 'shifted_periodic',
'get_shift'),
}
equations = {
'elasticity' : """
dw_lin_elastic.2.Omega(solid.D, v, u)
= -dw_surface_ltr.2.Bottom(load.val, v)
""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
linear_elasticity/elastodynamic.py
Description
The linear elastodynamics solution of an iron plate impact problem.
Find 𝑢 such that:
𝜕2𝑢
∫︁ ∫︁
𝜌𝑣 2 + 𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω 𝜕𝑡 Ω
where
Notes
The used elastodynamics solvers expect that the total vector of DOFs contains three blocks in this order: the dis-
placements, the velocities, and the accelerations. This is achieved by defining three unknown variables 'u', 'du',
'ddu' and the corresponding test variables, see the variables definition. Then the solver can automatically extract
the mass, damping (zero here), and stiffness matrices as diagonal blocks of the global matrix. Note also the use of
the 'dw_zero' (do-nothing) term that prevents the velocity-related variables to be removed from the equations in the
absence of a damping term.
Usage Examples
Run with the default settings (the Newmark method, 3D problem, results stored in output/ed/):
source code
r"""
The linear elastodynamics solution of an iron plate impact problem.
.. math::
\int_{\Omega} \rho \ul{v} \pddiff{\ul{u}}{t}
+ \int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
(continues on next page)
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
Notes
-----
The used elastodynamics solvers expect that the total vector of DOFs contains
three blocks in this order: the displacements, the velocities, and the
accelerations. This is achieved by defining three unknown variables ``'u'``,
``'du'``, ``'ddu'`` and the corresponding test variables, see the `variables`
definition. Then the solver can automatically extract the mass, damping (zero
here), and stiffness matrices as diagonal blocks of the global matrix. Note
also the use of the ``'dw_zero'`` (do-nothing) term that prevents the
velocity-related variables to be removed from the equations in the absence of a
damping term.
Usage Examples
--------------
Run with the default settings (the Newmark method, 3D problem, results stored
in ``output/ed/``)::
import numpy as nm
import sfepy.mechanics.matcoefs as mc
from sfepy.discrete.fem.meshio import UserMeshIO
from sfepy.mesh.mesh_generators import gen_block_mesh
plane = 'strain'
dim = 3
# Material parameters.
(continues on next page)
# Initial velocity.
v0 = 1.0
shape = [21, 6, 6]
#shape = [101, 26, 26]
else:
L = 2 * d
dims = [L, 2 * d]
# Element size.
H = L / (shape[0] - 1)
# Time-stepping parameters.
# Note: the Courant number C0 = dt * cl / H
dt = H / cl # C0 = 1
if dim == 3:
t1 = 0.9 * L / cl
else:
t1 = 1.5 * d / cl
ev = problem.evaluate
strain = ev('ev_cauchy_strain.i.Omega(u)', mode='el_avg', verbose=False)
stress = ev('ev_cauchy_stress.i.Omega(solid.D, u)', mode='el_avg',
copy_materials=False, verbose=False)
return out
filename_mesh = UserMeshIO(mesh_hook)
regions = {
'Omega' : 'all',
'Impact' : ('vertices in (x < 1e-12)', 'facet'),
}
if dim == 3:
regions.update({
'Symmetry-y' : ('vertices in (y < 1e-12)', 'facet'),
'Symmetry-z' : ('vertices in (z < 1e-12)', 'facet'),
})
# Iron.
materials = {
'solid' : ({
'D': mc.stiffness_from_youngpoisson(dim=dim, young=E, poisson=nu,
plane=plane),
'rho': rho,
},),
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
integrals = {
'i' : 2,
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'du' : ('unknown field', 'displacement', 1),
'ddu' : ('unknown field', 'displacement', 2),
(continues on next page)
ebcs = {
'Impact' : ('Impact', {'u.0' : 0.0, 'du.0' : 0.0, 'ddu.0' : 0.0}),
}
if dim == 3:
ebcs.update({
'Symmtery-y' : ('Symmetry-y',
{'u.1' : 0.0, 'du.1' : 0.0, 'ddu.1' : 0.0}),
'Symmetry-z' : ('Symmetry-z',
{'u.2' : 0.0, 'du.2' : 0.0, 'ddu.2' : 0.0}),
})
return val
functions = {
'get_ic_u' : (get_ic,),
'get_ic_du' : (lambda coor, ic: get_ic(coor, None, mode='du'),),
}
ics = {
'ic' : ('Omega', {'u.all' : 'get_ic_u', 'du.all' : 'get_ic_du'}),
}
equations = {
'balance_of_forces' :
"""dw_dot.i.Omega(solid.rho, ddv, ddu)
+ dw_zero.i.Omega(dv, du)
+ dw_lin_elastic.i.Omega(solid.D, v, u) = 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {
'use_presolve' : True,
}),
'ls-i' : ('ls.petsc', {
'method' : 'cg',
'precond' : 'icc',
'i_max' : 150,
'eps_a' : 1e-32,
'eps_r' : 1e-8,
(continues on next page)
'is_linear' : True,
'verbose' : 1,
}),
'tsn' : ('ts.newmark', {
't0' : 0.0,
't1' : t1,
'dt' : dt,
'n_step' : None,
'is_linear' : True,
'beta' : 0.25,
'gamma' : 0.5,
'verbose' : 1,
}),
'tsga' : ('ts.generalized_alpha', {
't0' : 0.0,
't1' : t1,
'dt' : dt,
'n_step' : None,
'is_linear' : True,
'rho_inf' : 0.5,
'alpha_m' : None,
'alpha_f' : None,
'beta' : None,
'gamma' : None,
'verbose' : 1,
}),
'tsb' : ('ts.bathe', {
't0' : 0.0,
't1' : t1,
'dt' : dt,
(continues on next page)
'is_linear' : True,
'verbose' : 1,
}),
}
options = {
'ts' : 'tsn',
# 'ts' : 'tsb',
'nls' : 'newton',
# 'ls' : 'ls-i',
'ls' : 'ls',
'save_times' : 20,
'active_only' : False,
'output_format' : 'h5',
'output_dir' : 'output/ed',
'post_process_hook' : 'post_process',
}
linear_elasticity/its2D_1.py
Description
Diametrically point loaded 2-D disk. See Primer.
Find 𝑢 such that:
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω
where
source code
r"""
Diametrically point loaded 2-D disk. See :ref:`sec-primer`.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
from sfepy.mechanics.matcoefs import stiffness_from_youngpoisson
from sfepy.discrete.fem.utils import refine_mesh
from sfepy import data_dir
(continues on next page)
# Fix the mesh file name if you run this file outside the SfePy directory.
filename_mesh = data_dir + '/meshes/2d/its2D.mesh'
refinement_level = 0
filename_mesh = refine_mesh(filename_mesh, refinement_level)
output_dir = '.' # set this to a valid directory you have write access to
options = {
'output_dir' : output_dir,
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Bottom' : ('vertices in (y < 0.001)', 'facet'),
'Top' : ('vertex 2', 'vertex'),
}
materials = {
'Asphalt' : ({'D': stiffness_from_youngpoisson(2, young, poisson)},),
'Load' : ({'.val' : [0.0, -1000.0]},),
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
equations = {
'balance_of_forces' :
"""dw_lin_elastic.2.Omega(Asphalt.D, v, u)
= dw_point_load.0.Top(Load.val, v)""",
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
ebcs = {
'XSym' : ('Bottom', {'u.1' : 0.0}),
'YSym' : ('Left', {'u.0' : 0.0}),
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
(continues on next page)
linear_elasticity/its2D_2.py
Description
Diametrically point loaded 2-D disk with postprocessing. See Primer.
Find 𝑢 such that:
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω
where
source code
r"""
Diametrically point loaded 2-D disk with postprocessing. See
:ref:`sec-primer`.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
ev = pb.evaluate
strain = ev('ev_cauchy_strain.2.Omega(u)', mode='el_avg')
stress = ev('ev_cauchy_stress.2.Omega(Asphalt.D, u)', mode='el_avg',
copy_materials=False)
return out
asphalt = materials['Asphalt'][0]
asphalt.update({'D' : stiffness_from_youngpoisson(2, young, poisson)})
options.update({'post_process_hook' : 'stress_strain',})
linear_elasticity/its2D_3.py
Description
Diametrically point loaded 2-D disk with nodal stress calculation. See Primer.
Find 𝑢 such that:
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω
where
source code
r"""
Diametrically point loaded 2-D disk with nodal stress calculation. See
:ref:`sec-primer`.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
(continues on next page)
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import print_function
from __future__ import absolute_import
from sfepy.examples.linear_elasticity.its2D_1 import *
gdata = geometry_data['2_3']
nc = len(gdata.coors)
# Point load.
mat = pb.get_materials()['Load']
P = 2.0 * mat.get_data('special', 'val')[1]
print('\n==================================================================')
print('Given load = %.2f N' % -P)
print('\nAnalytical solution')
print('===================')
print('Horizontal tensile stress = %.5e MPa/mm' % (-2.*P/(nm.pi*150.)))
print('Vertical compressive stress = %.5e MPa/mm' % (-6.*P/(nm.pi*150.)))
print('\nFEM solution')
(continues on next page)
asphalt = materials['Asphalt'][0]
asphalt.update({'D' : stiffness_from_youngpoisson(2, young, poisson)})
options.update({'post_process_hook' : 'nodal_stress',})
integrals = {
'ivn' : ('custom', gdata.coors, [gdata.volume / nc] * nc),
}
linear_elasticity/its2D_4.py
Description
Diametrically point loaded 2-D disk with postprocessing and probes. See Primer.
Use it as follows (assumes running from the sfepy directory; on Windows, you may need to prefix all the commands
with “python ” and remove “./”):
1. solve the problem:
./simple.py sfepy/examples/linear_elasticity/its2D_4.py
./resview.py its2D.h5 -2
./extractor.py -d its2D.h5
./resview.py its2D.0.vtk -2
where
source code
r"""
Diametrically point loaded 2-D disk with postprocessing and probes. See
:ref:`sec-primer`.
Use it as follows (assumes running from the sfepy directory; on Windows, you
may need to prefix all the commands with "python " and remove "./"):
./simple.py sfepy/examples/linear_elasticity/its2D_4.py
./resview.py its2D.h5 -2
./extractor.py -d its2D.h5
./resview.py its2D.0.vtk -2
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
from sfepy.examples.linear_elasticity.its2D_1 import *
ev = pb.evaluate
strain = ev('ev_cauchy_strain.2.Omega(u)', mode='el_avg')
stress = ev('ev_cauchy_stress.2.Omega(Asphalt.D, u)', mode='el_avg')
return out
def gen_lines(problem):
from sfepy.discrete.probes import LineProbe
ps0 = [[0.0, 0.0], [ 0.0, 0.0]]
ps1 = [[75.0, 0.0], [ 0.0, 75.0]]
labels = ['%s -> %s' % (p0, p1) for p0, p1 in zip(ps0, ps1)]
probes = []
for ip in range(len(ps0)):
p0, p1 = ps0[ip], ps1[ip]
(continues on next page)
results = {}
results['u'] = get_it('u', 'u')
results['cauchy_strain'] = get_it('cauchy_strain', 's')
results['cauchy_stress'] = get_it('cauchy_stress', 's')
fig = plt.figure()
plt.clf()
fig.subplots_adjust(hspace=0.4)
plt.subplot(311)
pars, vals = results['u']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$u_{%d}$' % (ic + 1),
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('displacements')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', prop=fm.FontProperties(size=10))
plt.subplot(312)
pars, vals = results['cauchy_strain']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$e_{%s}$' % sym_indices[ic],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy strain')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', prop=fm.FontProperties(size=8))
plt.subplot(313)
pars, vals = results['cauchy_stress']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$\sigma_{%s}$' % sym_indices[ic],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy stress')
plt.xlabel('probe %s' % label, fontsize=8)
(continues on next page)
variables.update({
's' : ('parameter field', 'sym_tensor', None),
})
options.update({
'output_format' : 'h5', # VTK reader cannot read cell data yet for probing
'post_process_hook' : 'stress_strain',
'gen_probes' : 'gen_lines',
'probe_hook' : 'probe_hook',
})
linear_elasticity/its2D_interactive.py
Description
Diametrically point loaded 2-D disk, using commands for interactive use. See Primer.
The script combines the functionality of all the its2D_?.py examples and allows setting various simulation parameters,
namely:
• material parameters
• displacement field approximation order
• uniform mesh refinement level
The example shows also how to probe the results as in linear_elasticity/its2D_4.py. Using sfepy.discrete.probes
allows correct probing of fields with the approximation order greater than one.
In the SfePy top-level directory the following command can be used to get usage information:
python sfepy/examples/linear_elasticity/its2D_interactive.py -h
source code
#!/usr/bin/env python
"""
Diametrically point loaded 2-D disk, using commands for interactive use. See
:ref:`sec-primer`.
The script combines the functionality of all the ``its2D_?.py`` examples and
allows setting various simulation parameters, namely:
In the SfePy top-level directory the following command can be used to get usage
information::
python sfepy/examples/linear_elasticity/its2D_interactive.py -h
"""
from __future__ import absolute_import
import sys
from six.moves import range
sys.path.append('.')
from argparse import ArgumentParser, RawDescriptionHelpFormatter
import numpy as nm
import matplotlib.pyplot as plt
def gen_lines(problem):
"""
Define two line probes.
labels = ['%s -> %s' % (p0, p1) for p0, p1 in zip(ps0, ps1)]
(continues on next page)
fig = plt.figure()
plt.clf()
fig.subplots_adjust(hspace=0.4)
plt.subplot(311)
pars, vals = results['u']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$u_{%d}$' % (ic + 1),
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('displacements')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', fontsize=10)
plt.subplot(312)
pars, vals = results['cauchy_strain']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$e_{%s}$' % sym_indices[ic],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy strain')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', fontsize=10)
plt.subplot(313)
pars, vals = results['cauchy_stress']
for ic in range(vals.shape[1]):
plt.plot(pars, vals[:,ic], label=r'$\sigma_{%s}$' % sym_indices[ic],
lw=1, ls='-', marker='+', ms=3)
plt.ylabel('Cauchy stress')
plt.xlabel('probe %s' % label, fontsize=8)
plt.legend(loc='best', fontsize=10)
helps = {
'young' : "the Young's modulus [default: %(default)s]",
'poisson' : "the Poisson's ratio [default: %(default)s]",
'load' : "the vertical load value (negative means compression)"
" [default: %(default)s]",
'order' : 'displacement field approximation order [default: %(default)s]',
'refine' : 'uniform mesh refinement level [default: %(default)s]',
'probe' : 'probe the results',
}
def main():
from sfepy import data_dir
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('--version', action='version', version='%(prog)s')
parser.add_argument('--young', metavar='float', type=float,
action='store', dest='young',
default=2000.0, help=helps['young'])
parser.add_argument('--poisson', metavar='float', type=float,
action='store', dest='poisson',
default=0.4, help=helps['poisson'])
parser.add_argument('--load', metavar='float', type=float,
action='store', dest='load',
default=-1000.0, help=helps['load'])
parser.add_argument('--order', metavar='int', type=int,
action='store', dest='order',
default=1, help=helps['order'])
parser.add_argument('-r', '--refine', metavar='int', type=int,
action='store', dest='refine',
default=0, help=helps['refine'])
parser.add_argument('-p', '--probe',
action="store_true", dest='probe',
default=False, help=helps['probe'])
options = parser.parse_args()
output('using values:')
output(" Young's modulus:", options.young)
output(" Poisson's ratio:", options.poisson)
output(' vertical load:', options.load)
output('uniform mesh refinement level:', options.refine)
if options.refine > 0:
for ii in range(options.refine):
output('refine %d...' % ii)
domain = domain.refine()
output('... %d nodes %d elements'
% (domain.shape.n_nod, domain.shape.n_el))
t1 = Term.new('dw_lin_elastic(Asphalt.D, v, u)',
integral, omega, Asphalt=asphalt, v=v, u=u)
t2 = Term.new('dw_point_load(Load.val, v)',
integral0, top, Load=load, v=v)
eq = Equation('balance', t1 - t2)
eqs = Equations([eq])
ls = AutoDirect({})
nls_status = IndexedStruct()
nls = Newton({}, lin_solver=ls, status=nls_status)
pb = Problem('elasticity', equations=eqs)
pb.set_bcs(ebcs=Conditions([xsym, ysym]))
pb.set_solver(nls)
gdata = geometry_data['2_3']
nc = len(gdata.coors)
if options.probe:
# Probe the solution.
probes, labels = gen_lines(pb)
ev = pb.evaluate
order = 2 * (options.order - 1)
strain_qp = ev('ev_cauchy_strain.%d.Omega(u)' % order, mode='qp')
stress_qp = ev('ev_cauchy_stress.%d.Omega(Asphalt.D, u)' % order,
mode='qp', copy_materials=False)
all_results = []
for ii, probe in enumerate(probes):
fig, results = probe_results(u, strain, stress, probe, labels[ii])
fig.savefig('its2D_interactive_probe_%d.png' % ii)
all_results.append(results)
if __name__ == '__main__':
main()
linear_elasticity/linear_elastic.py
Description
Linear elasticity with given displacements.
Find 𝑢 such that:
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω
where
This example models a cylinder that is fixed at one end while the second end has a specified displacement of 0.01 in the
x direction (this boundary condition is named 'Displaced'). There is also a specified displacement of 0.005 in the z
direction for points in the region labeled 'SomewhereTop'. This boundary condition is named 'PerturbedSurface'.
The region 'SomewhereTop' is specified as those vertices for which:
The displacement field (three DOFs/node) in the 'Omega region' is approximated using P1 (four-node tetrahedral)
finite elements. The material is linear elastic and its properties are specified as Lamé parameters 𝜆 and 𝜇 (see http:
//en.wikipedia.org/wiki/Lam%C3%A9_parameters)
The output is the displacement for each vertex, saved by default to cylinder.vtk. View the results using:
source code
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
This example models a cylinder that is fixed at one end while the second end
has a specified displacement of 0.01 in the x direction (this boundary
condition is named ``'Displaced'``). There is also a specified displacement of
(continues on next page)
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
'SomewhereTop' : ('vertices in (z > 0.017) & (x > 0.03) & (x < 0.07)',
'vertex'),
}
materials = {
'solid' : ({'D': stiffness_from_lame(dim=3, lam=1e1, mu=1e0)},),
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
integrals = {
'i' : 1,
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
ebcs = {
'Fixed' : ('Left', {'u.all' : 0.0}),
'Displaced' : ('Right', {'u.0' : 0.01, 'u.[1,2]' : 0.0}),
(continues on next page)
equations = {
'balance_of_forces' :
"""dw_lin_elastic.i.Omega(solid.D, v, u) = 0""",
}
solvers = {
'ls': ('ls.auto_direct', {}),
'newton': ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
linear_elasticity/linear_elastic_damping.py
Description
Time-dependent linear elasticity with a simple damping.
Find 𝑢 such that:
∫︁ ∫︁
𝜕𝑢
𝑐𝑣· + 𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω 𝜕𝑡 Ω
where
source code
r"""
Time-dependent linear elasticity with a simple damping.
.. math::
\int_{\Omega} c\ \ul{v} \cdot \pdiff{\ul{u}}{t}
+ \int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import print_function
from __future__ import absolute_import
from copy import deepcopy
(continues on next page)
import numpy as nm
from sfepy.examples.linear_elasticity.linear_elastic import \
filename_mesh, materials, regions, fields, ebcs, \
integrals, solvers
options = {
'ts' : 'ts',
'save_times' : 'all',
'post_process_hook_final' : print_times,
'output_format' : 'h5',
}
variables = {
'u' : ('unknown field', 'displacement', 0, 1),
'v' : ('test field', 'displacement', 'u'),
}
equations = {
'balance_of_forces in time' :
"""dw_dot.i.Omega( solid.c, v, du/dt )
+ dw_lin_elastic.i.Omega( solid.D, v, u ) = 0""",
}
return True
ls = solvers['ls']
ls[1].update({'use_presolve' : True})
functions = {
'ebc_sin' : (ebc_sin,),
}
linear_elasticity/linear_elastic_iga.py
Description
Linear elasticity solved in a single patch NURBS domain using the isogeometric analysis (IGA) approach.
Find 𝑢 such that:
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω
where
source code
r"""
Linear elasticity solved in a single patch NURBS domain using the isogeometric
analysis (IGA) approach.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
regions = {
'Omega' : 'all',
'Gamma1' : ('vertices of set xi00', 'facet'),
'Gamma2' : ('vertices of set xi01', 'facet'),
}
materials = {
'solid' : ({
'D' : stiffness_from_lame(3, lam=5.769, mu=3.846),
},),
}
fields = {
'displacement': ('real', 'vector', 'Omega', None, 'H1', 'iga'),
}
integrals = {
'i' : 3,
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
ebcs = {
'u1' : ('Gamma1', {'u.all' : 0.0}),
'u2' : ('Gamma2', {'u.0' : 0.1, 'u.[1,2]' : 'get_ebcs'}),
}
return aux
functions = {
'get_ebcs' : (get_ebcs,),
(continues on next page)
equations = {
'balance_of_forces' : """dw_lin_elastic.i.Omega(solid.D, v, u) = 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
linear_elasticity/linear_elastic_interactive.py
Description
missing description!
source code
#!/usr/bin/env python
from argparse import ArgumentParser
import numpy as nm
import sys
sys.path.append('.')
return val
def main():
from sfepy import data_dir
t1 = Term.new('dw_lin_elastic(m.D, v, u)',
integral, omega, m=m, v=v, u=u)
t2 = Term.new('dw_volume_lvf(f.val, v)', integral, omega, f=f, v=v)
eq = Equation('balance', t1 + t2)
eqs = Equations([eq])
ls = ScipyDirect({})
nls_status = IndexedStruct()
nls = Newton({}, lin_solver=ls, status=nls_status)
pb = Problem('elasticity', equations=eqs)
pb.save_regions_as_groups('regions')
pb.set_bcs(ebcs=Conditions([fix_u, shift_u]))
pb.set_solver(nls)
pb.save_state('linear_elasticity.vtk', variables)
if __name__ == '__main__':
main()
linear_elasticity/linear_elastic_tractions.py
Description
Linear elasticity with pressure traction load on a surface and constrained to one-dimensional motion.
Find 𝑢 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = − 𝑣·𝜎·𝑛, ∀𝑣 ,
Ω Γ𝑟𝑖𝑔ℎ𝑡
where
• refine once:
source code
r"""
Linear elasticity with pressure traction load on a surface and constrained to
one-dimensional motion.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= - \int_{\Gamma_{right}} \ul{v} \cdot \ull{\sigma} \cdot \ul{n}
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
- refine once::
load_force = problem.evaluate(
'ev_integrate_mat.2.Right(load.val, u)'
)
output('surface load force:', load_force)
def eval_force(region_name):
strain = problem.evaluate(
'ev_cauchy_strain.i.%s(u)' % region_name, mode='qp',
verbose=False,
)
D = problem.evaluate(
'ev_integrate_mat.i.%s(solid.D, u)' % region_name,
mode='qp',
(continues on next page)
s2f = get_full_indices(len(normal))
stress = nm.einsum('cqij,cqjk->cqik', D, strain)
# Full (matrix) form of stress.
mstress = stress[..., s2f, 0]
middle_force = - problem.evaluate(
'ev_integrate_mat.i.%s(aux.force, u)' % region_name,
aux=aux,
verbose=False,
)
output('%s section axial force:' % region_name, middle_force)
eval_force('Left')
eval_force('Middle')
eval_force('Right')
return out
def define(approx_order=1):
"""Define the problem to solve."""
from sfepy import data_dir
options = {
'nls' : 'newton',
'ls' : 'ls',
'post_process_hook' : 'verify_tractions',
}
functions = {
'linear_tension' : (linear_tension,),
}
fields = {
'displacement': ('real', 3, 'Omega', approx_order),
}
materials = {
(continues on next page)
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -4.99)', 'facet'),
# Use a parent region to select only facets belonging to cells in the
# parent region. Otherwise, each facet is in the region two times, with
# opposite normals.
'Middle' : ('vertices in (x > -1e-10) & (x < 1e-10)', 'facet', 'Rhalf'),
'Rhalf' : 'vertices in x > -1e-10',
'Right' : ('vertices in (x > 4.99)', 'facet'),
}
ebcs = {
'fixb' : ('Left', {'u.all' : 0.0}),
'fixt' : ('Right', {'u.[1,2]' : 0.0}),
}
integrals = {
'i' : 2 * approx_order,
}
##
# Balance of forces.
equations = {
'elasticity' :
"""dw_lin_elastic.i.Omega( solid.D, v, u )
= - dw_surface_ltr.i.Right( load.val, v )""",
}
##
# Solvers etc.
solvers = {
'ls' : ('ls.auto_direct', {}),
'newton' : ('nls.newton',
{ 'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
'macheps' : 1e-16,
# Linear system error < (eps_a * lin_red).
'lin_red' : 1e-2,
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
(continues on next page)
return locals()
linear_elasticity/linear_elastic_up.py
Description
Nearly incompressible linear elasticity in mixed displacement-pressure formulation with comments.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − 𝑝∇·𝑣 =0, ∀𝑣 ,
Ω Ω
∫︁ ∫︁
− 𝑞∇·𝑢− 𝛾𝑞𝑝 = 0 , ∀𝑞 .
Ω Ω
source code
r"""
Nearly incompressible linear elasticity in mixed displacement-pressure
formulation with comments.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} p\ \nabla \cdot \ul{v}
= 0
\;, \quad \forall \ul{v} \;,
#! This file models a cylinder that is fixed at one end while the
#! second end has a specified displacement of 0.02 in the x direction
#! (this boundary condition is named PerturbedSurface).
#! The output is the displacement for each node, saved by default to
#! simple_out.vtk. The material is linear elastic.
from __future__ import absolute_import
from sfepy import data_dir
#! Mesh
#! ----
dim = 3
approx_u = '3_4_P1'
approx_p = '3_4_P0'
order = 2
filename_mesh = data_dir + '/meshes/3d/cylinder.mesh'
#! Regions
#! -------
#! Whole domain 'Omega', left and right ends.
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
}
#! Materials
#! ---------
#! The linear elastic material model is used.
materials = {
(continues on next page)
linear_elasticity/linear_viscoelastic.py
Description
Linear viscoelasticity with pressure traction load on a surface and constrained to one-dimensional motion.
The fading memory terms require an unloaded initial configuration, so the load starts in the second time step. The load
is then held for the first half of the total time interval, and released afterwards.
This example uses exponential fading memory kernel ℋ𝑖𝑗𝑘𝑙 (𝑡) = ℋ𝑖𝑗𝑘𝑙 (0)𝑒−𝑑𝑡 with decay 𝑑. Two equation kinds
are supported - ‘th’ and ‘eth’. In ‘th’ mode the tabulated kernel is linearly interpolated to required times using
interp_conv_mat(). In ‘eth’ mode, the computation is exact for exponential kernels.
Find 𝑢 such that:
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
Ω
∫︁ [︂∫︁ 𝑡 ]︂
𝜕𝑢
+ ℋ𝑖𝑗𝑘𝑙 (𝑡 − 𝜏 ) 𝑒𝑘𝑙 ( (𝜏 )) d𝜏 𝑒𝑖𝑗 (𝑣)
Ω 0 𝜕𝜏
∫︁
=− 𝑣 · 𝜎 · 𝑛 , ∀𝑣 ,
Γ𝑟𝑖𝑔ℎ𝑡
where
ℋ𝑖𝑗𝑘𝑙 (0) has the same structure as 𝐷𝑖𝑗𝑘𝑙 and 𝜎 · 𝑛 = 𝑝¯𝐼 · 𝑛 with given traction pressure 𝑝¯.
Notes
Because this example is run also as a test, it uses by default very few time steps. Try changing that.
Visualization
The output file is assumed to be ‘block.h5’ in the working directory. Change it appropriately for your situation.
Deforming mesh
$ python sfepy/examples/linear_elasticity/linear_viscoelastic.py -h
$ python sfepy/examples/linear_elasticity/linear_viscoelastic.py block.h5
Try comparing ‘th’ and ‘eth’ versions, e.g., for n_step = 201, and f_n_step = 51. There is a visible notch on viscous
stress curves in the ‘th’ mode, as the fading memory kernel is cut off before it goes close enough to zero.
source code
#!/usr/bin/env python
r"""
Linear viscoelasticity with pressure traction load on a surface and constrained
to one-dimensional motion.
The fading memory terms require an unloaded initial configuration, so the load
starts in the second time step. The load is then held for the first half of the
total time interval, and released afterwards.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u}) \\
+ \int_{\Omega} \left [\int_0^t
(continues on next page)
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;,
Notes
-----
Because this example is run also as a test, it uses by default very few time
steps. Try changing that.
Visualization
-------------
Deforming mesh
^^^^^^^^^^^^^^
$ python sfepy/examples/linear_elasticity/linear_viscoelastic.py -h
$ python sfepy/examples/linear_elasticity/linear_viscoelastic.py block.h5
Try comparing 'th' and 'eth' versions, e.g., for n_step = 201, and f_n_step =
51. There is a visible notch on viscous stress curves in the 'th' mode, as the
fading memory kernel is cut off before it goes close enough to zero.
"""
from __future__ import absolute_import
import numpy as nm
if verbose:
output('load:', val)
if mode == 'special':
out['H'] = interp_conv_mat(kernel, ts, times)
return out
## Configure below. ##
decay = 0.8
mode = 'eth'
(continues on next page)
## Configure above. ##
ev = pb.evaluate
strain = ev('ev_cauchy_strain.2.Omega(u)', mode='el_avg')
out['cauchy_strain'] = Struct(name='output_data', mode='cell',
data=strain, dofs=None)
ts = pb.get_timestepper()
if mode == 'th':
vstress = ev('ev_cauchy_stress_th.2.Omega(ts, th.H, du/dt)',
ts=ts, mode='el_avg')
out['viscous_stress'] = Struct(name='output_data', mode='cell',
data=vstress, dofs=None)
else:
# The eth terms require 'preserve_caches=True' in order to have correct
# fading memory history.
vstress = ev('ev_cauchy_stress_eth.2.Omega(ts, th.H0, th.Hd, du/dt)',
ts=ts, mode='el_avg', preserve_caches=True)
out['viscous_stress'] = Struct(name='output_data', mode='cell',
data=vstress, dofs=None)
return out
options = {
'ts' : 'ts',
'nls' : 'newton',
'ls' : 'ls',
'output_format' : 'h5',
(continues on next page)
functions = {
'linear_tension' : (linear_tension,),
'get_pars' : (lambda ts, coors, mode=None, **kwargs:
get_th_pars(ts, coors, mode, times=times, kernel=kernel,
**kwargs),),
}
fields = {
'displacement': ('real', 3, 'Omega', 1),
}
materials = {
'solid' : ({
'D' : stiffness_from_lame(3, lam=5.769, mu=3.846),
},),
'th' : 'get_pars',
'load' : 'linear_tension',
}
variables = {
'u' : ('unknown field', 'displacement', 0, fading_memory_length),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -4.99)', 'facet'),
'Right' : ('vertices in (x > 4.99)', 'facet'),
}
ebcs = {
'fixb' : ('Left', {'u.all' : 0.0}),
'fixt' : ('Right', {'u.[1,2]' : 0.0}),
}
if mode == 'th':
# General form with tabulated kernel.
equations = {
'elasticity' :
"""dw_lin_elastic.2.Omega( solid.D, v, u )
+ dw_lin_elastic_th.2.Omega( ts, th.H, v, du/dt )
= - dw_surface_ltr.2.Right( load.val, v )""",
}
else:
# Fast form that is exact for exponential kernels.
equations = {
'elasticity' :
"""dw_lin_elastic.2.Omega( solid.D, v, u )
(continues on next page)
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
'ts' : ('ts.simple', {
't0' : t0,
't1' : t1,
'dt' : None,
'n_step' : n_step,
'quasistatic' : True,
'verbose' : 1,
}),
}
def main():
"""
Plot the load, displacement, strain and stresses w.r.t. time.
"""
from argparse import ArgumentParser, RawDescriptionHelpFormatter
import matplotlib.pyplot as plt
import sfepy.postprocess.time_history as th
msgs = {
'node': 'plot displacements in given node [default: %(default)s]',
'element': 'plot tensors in given element [default: %(default)s]',
}
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument(metavar='OUTPUT_FILE', dest='output_file',
help='output file in HDF5 format')
parser.add_argument('-n', '--node', type=int, metavar='ii',
action='store', dest='node',
default=512, help=msgs['node'])
parser.add_argument('-e', '--element', type=int, metavar='ii',
action='store', dest='element',
default=299, help=msgs['element'])
options = parser.parse_args()
filename = options.output_file
tensor_names = ['cauchy_strain',
'cauchy_stress', 'viscous_stress', 'total_stress']
extract = ('u n %d, ' % options.node) \
+ ', '.join('%s e %d' % (name, options.element)
(continues on next page)
plt.subplot(311)
plt.plot(times, normalized_kernel, lw=3)
plt.title('fading memory decay')
plt.xlabel('time')
plt.subplot(312)
plt.plot(ts.times, load, lw=3)
plt.title('load')
plt.xlabel('time')
displacements = ths['u'][options.node]
plt.subplot(313)
plt.plot(ts.times, displacements, lw=3)
plt.title('displacement components, node %d' % options.node)
plt.xlabel('time')
plt.subplot(411 + ii)
plt.plot(ts.times, tensor, lw=3)
plt.title('%s components, element %d' % (tensor_name, options.element))
plt.xlabel('time')
plt.show()
if __name__ == '__main__':
main()
linear_elasticity/material_nonlinearity.py
Description
Example demonstrating how a linear elastic term can be used to solve an elasticity problem with a material nonlinearity.
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = 0 , ∀𝑣 ,
Ω
where
source code
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= 0
\;, \quad \forall \ul{v} \;,
(continues on next page)
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
import numpy as nm
mu = pb.evaluate('ev_integrate_mat.2.Omega(nonlinear.mu, u)',
mode='el_avg', copy_materials=False, verbose=False)
out['mu'] = Struct(name='mu', mode='cell', data=mu, dofs=None)
return out
strains = [None]
order = term.integral.order
uvar = equations.variables['u']
else:
strain0 = strain
(continues on next page)
norm = norm_l2_along_axis(dstrain)
val += norm
# Store history.
strains[0] = strain
return {'D': stiffness_from_lame(dim=3, lam=1e1, mu=val),
'mu': val.reshape(-1, 1, 1)}
return val
functions = {
'get_pars' : (get_pars,),
'pull' : (pull,),
}
options = {
'ts' : 'ts',
'output_format' : 'h5',
'save_times' : 'all',
'post_process_hook' : 'post_process',
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < 0.001)', 'facet'),
'Right' : ('vertices in (x > 0.099)', 'facet'),
}
materials = {
'nonlinear' : 'get_pars',
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
ebcs = {
(continues on next page)
equations = {
'balance_of_forces in time' :
"""dw_lin_elastic.2.Omega(nonlinear.D, v, u) = 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton',
{'i_max' : 1,
'eps_a' : 1e-10,
'eps_r' : 1.0,
}),
'ts' : ('ts.simple',
{'t0' : 0.0,
't1' : 1.0,
'dt' : None,
'n_step' : 5,
'quasistatic' : True,
'verbose' : 1,
}),
}
linear_elasticity/modal_analysis.py
Description
Modal analysis of a linear elastic block in 2D or 3D.
The dimension of the problem is determined by the length of the vector in --dims option.
Optionally, a mesh file name can be given as a positional argument. In that case, the mesh generation options are
ignored.
The default material properties correspond to aluminium in the following units:
• length: m
• mass: kg
• stiffness / stress: Pa
• density: kg / m^3
Examples
• Use 3D domain:
python sfepy/examples/linear_elasticity/modal_analysis.py -d 1,1,1 -c 0,0,0 -s 8,8,8
- length: m
- mass: kg
- stiffness / stress: Pa
- density: kg / m^3
Examples
--------
python sfepy/examples/linear_elasticity/modal_analysis.py
- Use 3D domain::
import numpy as nm
import scipy.sparse.linalg as sla
helps = {
'dims' :
'dimensions of the block [default: %(default)s]',
'centre' :
'centre of the block [default: %(default)s]',
'shape' :
'numbers of vertices along each axis [default: %(default)s]',
'bc_kind' :
'kind of Dirichlet boundary conditions on the bottom and top surfaces,'
' one of: free, cantilever, fixed [default: %(default)s]',
'axis' :
'the axis index of the block that the bottom and top surfaces are related'
' to [default: %(default)s]',
'young' : "the Young's modulus [default: %(default)s]",
'poisson' : "the Poisson's ratio [default: %(default)s]",
'density' : "the material density [default: %(default)s]",
'order' : 'displacement field approximation order [default: %(default)s]',
(continues on next page)
def main():
parser = ArgumentParser(description=__doc__,
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('--version', action='version', version='%(prog)s')
parser.add_argument('-d', '--dims', metavar='dims',
action='store', dest='dims',
default='[1.0, 1.0]', help=helps['dims'])
parser.add_argument('-c', '--centre', metavar='centre',
action='store', dest='centre',
default='[0.0, 0.0]', help=helps['centre'])
parser.add_argument('-s', '--shape', metavar='shape',
action='store', dest='shape',
default='[11, 11]', help=helps['shape'])
parser.add_argument('-b', '--bc-kind', metavar='kind',
action='store', dest='bc_kind',
choices=['free', 'cantilever', 'fixed'],
default='free', help=helps['bc_kind'])
parser.add_argument('-a', '--axis', metavar='0, ..., dim, or -1',
type=int, action='store', dest='axis',
default=-1, help=helps['axis'])
parser.add_argument('--young', metavar='float', type=float,
action='store', dest='young',
default=6.80e+10, help=helps['young'])
parser.add_argument('--poisson', metavar='float', type=float,
action='store', dest='poisson',
default=0.36, help=helps['poisson'])
parser.add_argument('--density', metavar='float', type=float,
action='store', dest='density',
default=2700.0, help=helps['density'])
parser.add_argument('--order', metavar='int', type=int,
action='store', dest='order',
default=1, help=helps['order'])
parser.add_argument('-n', '--n-eigs', metavar='int', type=int,
action='store', dest='n_eigs',
default=6, help=helps['n_eigs'])
parser.add_argument('-i', '--ignore', metavar='int', type=int,
action='store', dest='ignore',
default=None, help=helps['ignore'])
parser.add_argument('--solver', metavar='solver', action='store',
dest='solver',
default= \
"eig.scipy,method:'eigsh',tol:1e-5,maxiter:1000",
help=helps['solver'])
(continues on next page)
aux = options.solver.split(',')
kwargs = {}
for option in aux[1:]:
key, val = option.split(':')
kwargs[key.strip()] = eval(val)
eig_conf = Struct(name='evp', kind=aux[0], **kwargs)
output('using values:')
output(" Young's modulus:", options.young)
output(" Poisson's ratio:", options.poisson)
output(' density:', options.density)
output('displacement field approximation order:', options.order)
output('requested %d eigenvalues' % options.n_eigs)
output('using eigenvalue problem solver:', eig_conf.kind)
output.level += 1
for key, val in six.iteritems(kwargs):
output('%s: %r' % (key, val))
output.level -= 1
filename = options.filename
if filename is not None:
mesh = Mesh.from_file(filename)
dim = mesh.dim
dims = nm.diff(mesh.get_bounding_box(), axis=0)
else:
dims = nm.array(eval(options.dims), dtype=nm.float64)
dim = len(dims)
output('dimensions:', dims)
output('centre: ', centre)
output('shape: ', shape)
eig_solver = Solver.any_from_conf(eig_conf)
bbox = domain.get_mesh_bounding_box()
min_coor, max_coor = bbox[:, options.axis]
eps = 1e-8 * (max_coor - min_coor)
ax = 'xyz'[:dim][options.axis]
pb = Problem('modal', equations=lhs_eqs)
if options.bc_kind == 'free':
pb.time_update()
n_rbm = dim * (dim + 1) // 2
else:
(continues on next page)
pb.update_materials()
try:
eigs, svecs = eig_solver(mtx_k, mtx_m, options.n_eigs + n_rbm,
eigenvectors=True)
eigs = eigs[n_rbm:]
svecs = svecs[:, n_rbm:]
omegas = nm.sqrt(eigs)
freqs = omegas / (2 * nm.pi)
pb.save_state('eigenshapes.vtk', out=out)
pb.save_regions_as_groups('regions')
if __name__ == '__main__':
main()
linear_elasticity/nodal_lcbcs.py
Description
Linear elasticity with nodal linear combination constraints.
Find 𝑢 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) = − 𝑣·𝜎·𝑛, ∀𝑣 ,
Ω Γ𝑟𝑖𝑔ℎ𝑡
where
and 𝜎 · 𝑛 = 𝑝¯𝐼 · 𝑛 with given traction pressure 𝑝¯. The constraints are given in terms of coefficient matrices and
right-hand sides, see the lcbcs keyword below. For instance, 'nlcbc1' in the 3D mesh case corresponds to
𝑢0 − 𝑢1 + 𝑢2 = 0
𝑢0 + 0.5𝑢1 + 0.1𝑢2 = 0.05
to use a 3D mesh, instead of the default 2D mesh. The example also shows that the nodal constraints can be used in
place of the Dirichlet boundary conditions. Try:
to replace ebcs with the 'nlcbc4' constraints. The results should be the same for the two cases. Both options can be
combined:
The post_process() function is used both to compute the von Mises stress and to verify the linear combination
constraints.
View the 2D results using:
source code
r"""
Linear elasticity with nodal linear combination constraints.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
= - \int_{\Gamma_{right}} \ul{v} \cdot \ull{\sigma} \cdot \ul{n}
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
(continues on next page)
and :math:`\ull{\sigma} \cdot \ul{n} = \bar{p} \ull{I} \cdot \ul{n}` with given
traction pressure :math:`\bar{p}`. The constraints are given in terms of
coefficient matrices and right-hand sides, see the ``lcbcs`` keyword below. For
instance, ``'nlcbc1'`` in the 3D mesh case corresponds to
.. math::
u_0 - u_1 + u_2 = 0 \\
u_0 + 0.5 u_1 + 0.1 u_2 = 0.05
to use a 3D mesh, instead of the default 2D mesh. The example also shows that
the nodal constraints can be used in place of the Dirichlet boundary
conditions. Try::
ev = pb.evaluate
stress = ev('ev_cauchy_stress.2.Omega(m.D, u)', mode='el_avg')
vms = get_von_mises_stress(stress.squeeze())
vms.shape = (vms.shape[0], 1, 1, 1)
out['von_mises_stress'] = Struct(name='output_data', mode='cell',
data=vms, dofs=None)
dim = pb.domain.shape.dim
us = state().reshape((-1, dim))
field = pb.fields['displacement']
if dim == 2:
ii = field.get_dofs_in_region(pb.domain.regions['Top'])
output('top LCBC (u.0 - u.1 = 0):')
output('\n', nm.c_[us[ii], nm.diff(us[ii], 1)])
ii = field.get_dofs_in_region(pb.domain.regions['Bottom'])
output('bottom LCBC (u.0 + u.1 = -0.1):')
output('\n', nm.c_[us[ii], nm.sum(us[ii], 1)])
ii = field.get_dofs_in_region(pb.domain.regions['Right'])
output('right LCBC (u.0 + u.1 = linspace(0, 0.1)):')
output('\n', nm.c_[us[ii], nm.sum(us[ii], 1)])
else:
ii = field.get_dofs_in_region(pb.domain.regions['Top'])
output('top LCBC (u.0 - u.1 + u.2 = 0):')
output('\n', nm.c_[us[ii], us[ii, 0] - us[ii, 1] + us[ii, 2]])
output('top LCBC (u.0 + 0.5 u.1 + 0.1 u.2 = 0.05):')
output('\n', nm.c_[us[ii],
us[ii, 0] + 0.5 * us[ii, 1] + 0.1 * us[ii, 2]])
ii = field.get_dofs_in_region(pb.domain.regions['Bottom'])
output('bottom LCBC (u.2 - 0.1 u.1 = 0.2):')
output('\n', nm.c_[us[ii], us[ii, 2] - 0.1 * us[ii, 1]])
ii = field.get_dofs_in_region(pb.domain.regions['Right'])
output('right LCBC (u.0 + u.1 + u.2 = linspace(0, 0.1)):')
output('\n', nm.c_[us[ii], nm.sum(us[ii], 1)])
return out
else:
filename_mesh = data_dir + '/meshes/3d/cube_medium_tetra.mesh'
options = {
'nls' : 'newton',
'ls' : 'ls',
'post_process_hook' : 'post_process'
}
functions = {
'get_constraints' : (get_constraints,),
}
fields = {
'displacement': ('real', dim, 'Omega', 1),
}
materials = {
'm' : ({
'D' : stiffness_from_lame(dim, lam=5.769, mu=3.846),
},),
'load' : ({'val' : -1.0},),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
regions = {
'Omega' : 'all',
'Bottom' : ('vertices in (y < -0.499) -v r.Left', 'facet'),
'Top' : ('vertices in (y > 0.499) -v r.Left', 'facet'),
'Left' : ('vertices in (x < -0.499)', 'facet'),
'Right' : ('vertices in (x > 0.499) -v (r.Bottom +v r.Top)', 'facet'),
}
if dim == 2:
lcbcs = {
'nlcbc1' : ('Top', {'u.all' : None}, None, 'nodal_combination',
(continues on next page)
else:
lcbcs = {
'nlcbc1' : ('Top', {'u.all' : None}, None, 'nodal_combination',
([[1.0, -1.0, 1.0], [1.0, 0.5, 0.1]], [0.0, 0.05])),
'nlcbc2' : ('Bottom', {'u.[2,1]' : None}, None, 'nodal_combination',
([[1.0, -0.1]], [0.2])),
'nlcbc3' : ('Right', {'u.all' : None}, None, 'nodal_combination',
'get_constraints'),
}
if use_ebcs:
ebcs = {
'fix' : ('Left', {'u.all' : 0.0}),
}
else:
ebcs = {}
lcbcs.update({
'nlcbc4' : ('Left', {'u.all' : None}, None, 'nodal_combination',
(nm.eye(dim), nm.zeros(dim))),
})
equations = {
'elasticity' : """
dw_lin_elastic.2.Omega(m.D, v, u)
= -dw_surface_ltr.2.Right(load.val, v)
""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
return locals()
linear_elasticity/prestress_fibres.py
Description
Linear elasticity with a given prestress in one subdomain and a (pre)strain fibre reinforcement in the other.
Find 𝑢 such that:
∫︁ ∫︁ ∫︁
𝑓
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) + 𝜎𝑖𝑗 𝑒𝑖𝑗 (𝑣) + 𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣) (𝑑𝑘 𝑑𝑙 ) = 0 , ∀𝑣 ,
Ω Ω1 Ω2
where
Visualization
Use the following to see the deformed structure with 10x magnified displacements:
source code
r"""
Linear elasticity with a given prestress in one subdomain and a (pre)strain
fibre reinforcement in the other.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
+ \int_{\Omega_1} \sigma_{ij} e_{ij}(\ul{v})
+ \int_{\Omega_2} D^f_{ijkl} e_{ij}(\ul{v}) \left(d_k d_l\right)
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
Visualization
-------------
Use the following to see the deformed structure with 10x magnified
displacements::
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -4.99)', 'facet'),
'Omega1' : 'vertices in (x < 0.001)',
'Omega2' : 'vertices in (x > -0.001)',
}
materials = {
'solid' : ({
'D' : stiffness_from_lame(3, lam=1e2, mu=1e1),
'prestress' : 0.1 * nm.array([[1.0], [1.0], [1.0],
[0.5], [0.5], [0.5]],
dtype=nm.float64),
'DF' : stiffness_from_lame(3, lam=8e0, mu=8e-1),
(continues on next page)
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
ebcs = {
'Fixed' : ('Left', {'u.all' : 0.0}),
}
equations = {
'balance_of_forces' :
"""dw_lin_elastic.2.Omega( solid.D, v, u )
+ dw_lin_prestress.2.Omega1( solid.prestress, v )
+ dw_lin_strain_fib.2.Omega2( solid.DF, solid.nu, v )
= 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
linear_elasticity/shell10x_cantilever.py
Description
Bending of a long thin cantilever beam computed using the dw_shell10x term.
Find displacements of the central plane 𝑢, and rotations 𝛼 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣, 𝛽)𝑒𝑘𝑙 (𝑢, 𝛼) = − 𝑣·𝑓 , ∀𝑣 ,
Ω Γ𝑟𝑖𝑔ℎ𝑡
where 𝐷𝑖𝑗𝑘𝑙 is the isotropic elastic tensor, given using the Young’s modulus 𝐸 and the Poisson’s ratio 𝜈.
The variable u below holds both 𝑢 and 𝛼 DOFs. For visualization, it is saved as two fields u_disp and u_rot, corre-
sponding to 𝑢 and 𝛼, respectively.
See also linear_elasticity/shell10x_cantilever_interactive.py example.
View the results using:
source code
r"""
Bending of a long thin cantilever beam computed using the
:class:`dw_shell10x <sfepy.terms.terms_shells.Shell10XTerm>` term.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}, \ul{\beta})
e_{kl}(\ul{u}, \ul{\alpha})
= - \int_{\Gamma_{right}} \ul{v} \cdot \ul{f}
\;, \quad \forall \ul{v} \;,
where :math:`D_{ijkl}` is the isotropic elastic tensor, given using the Young's
modulus :math:`E` and the Poisson's ratio :math:`\nu`.
# Beam dimensions.
dims = [0.2, 0.01, 0.001]
thickness = dims[2]
# Material parameters.
young = 210e9
poisson = 0.3
# Loading force.
force = -1.0
dofs = u.get_state_in_region(gamma2)
output('DOFs along the loaded edge:')
output('\n%s' % dofs)
if transform != 'twist':
label, ii = {None : ('u_3', 2), 'bend' : ('u_1', 0)}[transform]
return out
filename_mesh = UserMeshIO(mesh_hook)
options = {
'nls' : 'newton',
'ls' : 'ls',
'post_process_hook' : 'post_process',
}
if transform is None:
pload = [[0.0, 0.0, force / shape[1], 0.0, 0.0, 0.0]] * shape[1]
materials = {
'm' : ({
'D' : sh.create_elastic_tensor(young=young, poisson=poisson),
'.drill' : 1e-7,
},),
'load' : ({
'.val' : pload,
},)
}
regions = {
'Omega' : 'all',
'Gamma1' : ('vertices in (x < %.14f )' % xmin, 'facet'),
'Gamma2' : ('vertices in (x > %.14f )' % xmax, 'facet'),
}
fields = {
'fu': ('real', 6, 'Omega', 1, 'H1', 'shell10x'),
}
variables = {
'u' : ('unknown field', 'fu', 0),
'v' : ('test field', 'fu', 'u'),
}
ebcs = {
'fix' : ('Gamma1', {'u.all' : 0.0}),
(continues on next page)
# Custom integral.
aux = Integral('i', order=3)
qp_coors, qp_weights = aux.get_qp('3_8')
qp_coors[:, 2] = thickness * (qp_coors[:, 2] - 0.5)
qp_weights *= thickness
integrals = {
'i' : ('custom', qp_coors, qp_weights),
}
equations = {
'elasticity' :
"""dw_shell10x.i.Omega(m.D, m.drill, v, u)
= dw_point_load.i.Gamma2(load.val, v)""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-7,
}),
}
linear_elasticity/shell10x_cantilever_interactive.py
Description
Bending of a long thin cantilever beam computed using the dw_shell10x term.
Find displacements of the central plane 𝑢, and rotations 𝛼 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣, 𝛽)𝑒𝑘𝑙 (𝑢, 𝛼) = − 𝑣·𝑓 , ∀𝑣 ,
Ω Γ𝑟𝑖𝑔ℎ𝑡
where 𝐷𝑖𝑗𝑘𝑙 is the isotropic elastic tensor, given using the Young’s modulus 𝐸 and the Poisson’s ratio 𝜈.
The variable u below holds both 𝑢 and 𝛼 DOFs. For visualization, it is saved as two fields u_disp and u_rot, corre-
sponding to 𝑢 and 𝛼, respectively.
The material, loading and discretization parameters can be given using command line options.
Besides the default straight beam, two coordinate transformations can be applied (see the --transform option):
• bend: the beam is bent
• twist: the beam is twisted
For the straight and bent beam a comparison with the analytical solution coming from the Euler-Bernoulli theory is
shown.
See also linear_elasticity/shell10x_cantilever.py example.
Usage Examples
Apply the bending transformation to the beam domain coordinates, plot convergence curves w.r.t. number of elements:
Apply the twisting transformation to the beam domain coordinates, change number of cells:
python sfepy/examples/linear_elasticity/shell10x_cantilever_interactive.py output -t␣
˓→twist -n 2,51,3
source code
#!/usr/bin/env python
r"""
Bending of a long thin cantilever beam computed using the
:class:`dw_shell10x <sfepy.terms.terms_shells.Shell10XTerm>` term.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}, \ul{\beta})
e_{kl}(\ul{u}, \ul{\alpha})
= - \int_{\Gamma_{right}} \ul{v} \cdot \ul{f}
\;, \quad \forall \ul{v} \;,
where :math:`D_{ijkl}` is the isotropic elastic tensor, given using the Young's
modulus :math:`E` and the Poisson's ratio :math:`\nu`.
The material, loading and discretization parameters can be given using command
line options.
Besides the default straight beam, two coordinate transformations can be applied
(see the ``--transform`` option):
For the straight and bent beam a comparison with the analytical solution
coming from the Euler-Bernoulli theory is shown.
Usage Examples
(continues on next page)
python sfepy/examples/linear_elasticity/shell10x_cantilever_interactive.py -h
Apply the twisting transformation to the beam domain coordinates, change number of␣
˓→cells::
import numpy as nm
if transform == 'bend':
bbox = mesh.get_bounding_box()
x0, x1 = bbox[:, 0]
coors = mesh.coors.copy()
coors[:, 0] = 0
coors[:, 2] = (x1 - x0)
return mesh
return domain
omega = domain.regions['Omega']
gamma1 = domain.regions['Gamma1']
gamma2 = domain.regions['Gamma2']
thickness = dims[2]
if transform is None:
pload = [[0.0, 0.0, force / shape[1], 0.0, 0.0, 0.0]] * shape[1]
nls_status = IndexedStruct()
nls = Newton({}, lin_solver=ls, status=nls_status)
state = pb.solve()
if transform is None:
moment = b * h**3 / 12.0
u = force * l**3 / (3 * young * moment)
return u
helps = {
'output_dir' : 'output directory',
'dims' :
'dimensions of the cantilever [default: %(default)s]',
'nx' :
'the range for the numbers of cells in the x direction'
' [default: %(default)s]',
'transform' :
'the transformation of the domain coordinates [default: %(default)s]',
'young' : "the Young's modulus [default: %(default)s]",
'poisson' : "the Poisson's ratio [default: %(default)s]",
'force' : "the force load [default: %(default)s]",
'plot' : 'plot the max. displacement w.r.t. number of cells',
'silent' : 'do not print messages to screen',
}
def main():
parser = ArgumentParser(description=__doc__.rstrip(),
formatter_class=RawDescriptionHelpFormatter)
parser.add_argument('output_dir', help=helps['output_dir'])
parser.add_argument('-d', '--dims', metavar='l,w,t',
action='store', dest='dims',
default='0.2,0.01,0.001', help=helps['dims'])
parser.add_argument('-n', '--nx', metavar='start,stop,step',
action='store', dest='nx',
default='2,103,10', help=helps['nx'])
parser.add_argument('-t', '--transform', choices=['none', 'bend', 'twist'],
action='store', dest='transform',
default='none', help=helps['transform'])
parser.add_argument('--young', metavar='float', type=float,
action='store', dest='young',
default=210e9, help=helps['young'])
parser.add_argument('--poisson', metavar='float', type=float,
action='store', dest='poisson',
default=0.3, help=helps['poisson'])
parser.add_argument('--force', metavar='float', type=float,
action='store', dest='force',
(continues on next page)
output_dir = options.output_dir
filename = odir('output_log.txt')
ensure_path(filename)
output.set_output(filename=filename, combined=options.silent == False)
if options.transform == 'none':
options.transform = None
if options.transform is None:
ilog = 2
labels = ['u_3']
log = []
for nx in range(*nxs):
shape = (nx, 2)
dofs = u.get_state_in_region(gamma2)
output('DOFs along the loaded edge:')
output('\n%s' % dofs)
pb.save_state(odir('shell10x_cantilever.vtk'), state)
log = nm.array(log)
if options.plot:
import matplotlib.pyplot as plt
plt.rcParams.update({
'lines.linewidth' : 3,
'font.size' : 16,
})
ax2 = ax1.twinx()
# Assume single log column.
ax2.semilogy(log[:, 0], nm.abs(log[:, 1] - u_exact), 'g',
label=r'$|%s - %s^{analytical}|$' % (label, label))
ax2.set_ylabel(r'$|%s - %s^{analytical}|$' % (label, label))
else:
lines2, labels2 = [], []
plt.tight_layout()
ax1.set_xlim([log[0, 0] - 2, log[-1, 0] + 2])
plt.show()
if __name__ == '__main__':
main()
linear_elasticity/two_bodies_contact.py
Description
Contact of two elastic bodies with a penalty function for enforcing the contact constraints.
Find 𝑢 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) + 𝜀𝑁 ⟨𝑔𝑁 (𝑢)⟩𝑛𝑣 = 0 , ∀𝑣 ,
Ω Γ𝑐
where 𝜀𝑁 ⟨𝑔𝑁 (𝑢)⟩ is the penalty function, 𝜀𝑁 is the normal penalty parameter, ⟨𝑔𝑁 (𝑢)⟩ are the Macaulay’s brackets of
the gap function 𝑔𝑁 (𝑢) and
Usage examples:
./script/plot_logs.py log.txt
./resview.py two_bodies.mesh_ebc_nodes.vtk -2
./resview.py two_bodies.mesh_regions.vtk -2
source code
r"""
Contact of two elastic bodies with a penalty function for enforcing the contact
constraints.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
+ \int_{\Gamma_{c}} \varepsilon_N \langle g_N(\ul{u}) \rangle \ul{n} \ul{v}
= 0
\;, \quad \forall \ul{v} \;,
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
(continues on next page)
Usage examples::
./script/plot_logs.py log.txt
./resview.py two_bodies.mesh_ebc_nodes.vtk -2
./resview.py two_bodies.mesh_regions.vtk -2
"""
from sfepy.mechanics.matcoefs import stiffness_from_youngpoisson
from sfepy.discrete.fem.meshio import UserMeshIO
import numpy as nm
dim = 2
if dim == 2:
dims0 = [1.0, 0.5]
shape0 = [4, 4]
centre0 = [0, -0.25]
else:
dims0 = [1.0, 1.0, 0.5]
shape0 = [2, 2, 2]
centre0 = [0, 0, -0.25]
desc = m0.descs[0]
c0 = m0.get_conn(desc)
c1 = m1.get_conn(desc)
conn = nm.concatenate((c0, c1 + m0.n_nod), axis=0)
name = 'two_bodies.mesh'
return mesh
ev = pb.evaluate
gap = ev('dw_contact.i.Contact(contact.epss, v, u)',
mode='el_avg', term_mode='gap')
gap = extend_cell_data(gap, pb.domain, 'Contact', val=0.0, is_surface=True)
out['gap'] = Struct(name='output_data',
mode='cell', data=gap, dofs=None)
return out
filename_mesh = UserMeshIO(mesh_hook)
options = {
'nls' : 'newton',
'ls' : 'ls',
'post_process_hook' : 'post_process',
}
materials = {
'solid' : ({'D': stiffness_from_youngpoisson(dim,
young=1.0, poisson=0.3)},),
'contact' : ({'.epss' : 1e1},),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
}
if dim == 2:
regions = {
'Omega' : 'all',
'Omega0' : 'cells of group 0',
'Omega1' : 'cells of group 1',
'Bottom' : ('vertices in (y < %f )' % bbox0[0, 1], 'facet'),
'Top' : ('vertices in (y > %f )' % bbox1[1, 1], 'facet'),
'Contact0' : ('(vertices in (y > %f ) *v r.Omega0)' % bbox0[1, 1],
'facet'),
'Contact1' : ('(vertices in (y < %f ) *v r.Omega1)' % bbox1[0, 1],
'facet'),
'Contact' : ('r.Contact0 +s r.Contact1', 'facet')
}
else:
regions = {
'Omega' : 'all',
'Omega0' : 'cells of group 0',
'Omega1' : 'cells of group 1',
'Bottom' : ('vertices in (z < %f )' % bbox0[0, 2], 'facet'),
'Top' : ('vertices in (z > %f )' % bbox1[1, 2], 'facet'),
'Contact0' : ('(vertices in (z > %f ) *v r.Omega0)' % bbox0[1, 2],
'facet'),
'Contact1' : ('(vertices in (z < %f ) *v r.Omega1)' % bbox1[0, 2],
'facet'),
'Contact' : ('r.Contact0 +s r.Contact1', 'facet')
}
ebcs = {
'fixb' : ('Bottom', {'u.all' : 0.0}),
'fixt' : ('Top', {'u.all' : 0.0}),
}
integrals = {
(continues on next page)
equations = {
'elasticity' :
"""dw_lin_elastic.2.Omega(solid.D, v, u)
+ dw_contact.i.Contact(contact.epss, v, u)
= 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 5,
'eps_a' : 1e-6,
'eps_r' : 1.0,
'macheps' : 1e-16,
# Linear system error < (eps_a * lin_red).
'lin_red' : 1e-2,
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 100.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-8,
# 'log' : {'text' : 'log.txt', 'plot' : None},
})
}
miscellaneous
miscellaneous/live_plot.py
Description
missing description!
source code
from __future__ import print_function
from __future__ import absolute_import
import os
import sys
sys.path.append( '.' )
import numpy as nm
def main():
cwd = os.path.split(os.path.join(os.getcwd(), __file__))[0]
(continues on next page)
added = 0
for x in nm.linspace(0, 4.0 * nm.pi, 200):
output('x: ', x)
else:
if added:
log(nm.sin(x)+1j*nm.sin(x**2), nm.cos(x), nm.exp(x), x**2,
x=[x, None, x])
else:
log.plot_vlines(color='r', linewidth=2)
log.add_group(['x^2'], yscale='linear', xlabel='new x',
ylabel='square', formats=['%+g'])
added += 1
log2(x*x*x, x=[x])
print(log)
print(log2)
pause()
log(finished=True)
log2(finished=True)
if __name__ == '__main__':
main()
multi_physics
multi_physics/biot.py
Description
Biot problem - deformable porous medium.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − 𝑝 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑣) = 0 , ∀𝑣 ,
Ω
∫︁ ∫︁ Ω
𝑞 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑢) + 𝐾𝑖𝑗 ∇𝑖 𝑞∇𝑗 𝑝 = 0 , ∀𝑞 ,
Ω Ω
where
source code
r"""
Biot problem - deformable porous medium.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} p\ \alpha_{ij} e_{ij}(\ul{v})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
import numpy as nm
regions = {
'Omega' : 'all',
'Bottom' : ('vertices in (z < -0.4999999)', 'facet'),
'Top' : ('vertices in (z > 0.4999999)', 'facet'),
'Left' : ('vertices in (x < -0.4999999)', 'facet'),
}
field_1 = {
'name' : 'displacement',
'dtype' : nm.float64,
'shape' : (3,),
'region' : 'Omega',
'approx_order' : 1,
}
field_2 = {
'name' : 'pressure',
'dtype' : nm.float64,
'shape' : (1,),
'region' : 'Omega',
'approx_order' : 1,
}
variables = {
'u' : ('unknown field', 'displacement', 0),
(continues on next page)
ebcs = {
'fix_u' : ('Bottom', {'u.all' : 0.0}),
'load_u' : ('Top', {'u.2' : 0.2}),
'load_p' : ('Left', {'p.all' : 1.0}),
}
material_1 = {
'name' : 'm',
'values' : {
'D': stiffness_from_lame(dim=3, lam=1.7, mu=0.3),
'alpha' : nm.array( [[0.132], [0.132], [0.132],
[0.092], [0.092], [0.092]],
dtype = nm.float64 ),
'K' : nm.array( [[2.0, 0.2, 0.0], [0.2, 1.0, 0.0], [0.0, 0.0, 0.5]],
dtype = nm.float64 ),
}
}
integral_1 = {
'name' : 'i1',
'order' : 1,
}
integral_2 = {
'name' : 'i2',
'order' : 2,
}
equations = {
'eq_1' :
"""dw_lin_elastic.i2.Omega( m.D, v, u )
- dw_biot.i1.Omega( m.alpha, v, p )
= 0""",
'eq_2' :
"""dw_biot.i1.Omega( m.alpha, u, q ) + dw_diffusion.i1.Omega( m.K, q, p )
= 0""",
}
solver_0 = {
'name' : 'ls_d',
'kind' : 'ls.scipy_direct',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
multi_physics/biot_npbc.py
Description
Biot problem - deformable porous medium with the no-penetration boundary condition on a boundary region.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − 𝑝 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑣) = 0 , ∀𝑣 ,
Ω
∫︁ ∫︁ Ω
𝑞 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑢) + 𝐾𝑖𝑗 ∇𝑖 𝑞∇𝑗 𝑝 = 0 , ∀𝑞 ,
Ω Ω
𝑢 · 𝑛 = 0 on Γ𝑤𝑎𝑙𝑙𝑠 ,
where
source code
r"""
Biot problem - deformable porous medium with the no-penetration boundary
condition on a boundary region.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} p\ \alpha_{ij} e_{ij}(\ul{v})
= 0
\;, \quad \forall \ul{v} \;,
where
def define():
from sfepy import data_dir
return get_coors_in_tube(coors,
centre, axis, -1, radius, length)
def define_regions(filename):
if filename.find('simple.mesh'):
dim = 3
regions = {
'Omega' : 'all',
'Walls' : ('vertices of surface -v (r.Outlet +f r.Inlet)', 'facet'),
'Inlet' : ('vertices by cinc_simple0', 'facet'),
'Outlet' : ('vertices by cinc_simple1', 'facet'),
'Rigid' : 'vertices by cinc_simple2',
}
else:
raise ValueError('unknown mesh %s!' % filename)
(continues on next page)
out = {}
out['D'] = nm.tile(stiffness_from_lame(dim, lam=1.7, mu=0.3),
(coor.shape[0], 1, 1))
return out
filename_mesh = filename
options = {
'output_dir' : output_dir,
'output_format' : 'vtk',
'post_process_hook' : 'post_process',
'ls' : 'ls',
'nls' : 'newton',
}
functions = {
'cinc_simple0' : (lambda coors, domain:
cinc_simple(coors, 0),),
'cinc_simple1' : (lambda coors, domain:
(continues on next page)
field_1 = {
'name' : 'displacement',
'dtype' : nm.float64,
'shape' : dim,
'region' : 'Omega',
'approx_order' : 1,
}
field_2 = {
'name' : 'pressure',
'dtype' : nm.float64,
'shape' : 1,
'region' : 'Omega',
'approx_order' : 1,
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
}
ebcs = {
'inlet' : ('Inlet', {'p.0' : 1.0, 'u.all' : 0.0}),
'outlet' : ('Outlet', {'p.0' : -1.0}),
}
lcbcs = {
'rigid' : ('Outlet', {'u.all' : None}, None, 'rigid'),
'no_penetration' : ('Walls', {'u.all' : None}, None,
'no_penetration', None),
}
material_1 = {
'name' : 'm',
'function' : 'get_pars',
}
integral_1 = {
'name' : 'i',
'order' : 2,
}
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct', # Direct solver.
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
}
return locals()
multi_physics/biot_npbc_lagrange.py
Description
Biot problem - deformable porous medium with the no-penetration boundary condition on a boundary region enforced
using Lagrange multipliers.
The non-penetration condition is enforced weakly using the Lagrange multiplier 𝜆. There is also a rigid body movement
constraint imposed on the Γ𝑜𝑢𝑡𝑙𝑒𝑡 region using the linear combination boundary conditions.
Find 𝑢, 𝑝 and 𝜆 such that:
∫︁ ∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − 𝑝 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑣) + 𝜆𝑛 · 𝑣 = 0 , ∀𝑣 ,
Ω Ω Γ
∫︁ ∫︁ 𝑤𝑎𝑙𝑙𝑠
𝑞 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑢) + 𝐾𝑖𝑗 ∇𝑖 𝑞∇𝑗 𝑝 = 0 , ∀𝑞 ,
Ω Ω
∫︁
ˆ ·𝑢=0,
𝜆𝑛 ˆ,
∀𝜆
Γ𝑤𝑎𝑙𝑙𝑠
𝑢 · 𝑛 = 0 on Γ𝑤𝑎𝑙𝑙𝑠 ,
where
source code
r"""
Biot problem - deformable porous medium with the no-penetration boundary
condition on a boundary region enforced using Lagrange multipliers.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} p\ \alpha_{ij} e_{ij}(\ul{v})
+ \int_{\Gamma_{walls}} \lambda \ul{n} \cdot \ul{v}
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
from sfepy.examples.multi_physics.biot_npbc import (cinc_simple,
define_regions, get_pars)
def define():
from sfepy import data_dir
filename_mesh = filename
options = {
'output_dir' : output_dir,
'output_format' : 'vtk',
'post_process_hook' : 'post_process',
## 'file_per_var' : True,
'ls' : 'ls',
'nls' : 'newton',
}
(continues on next page)
functions = {
'cinc_simple0' : (lambda coors, domain:
cinc_simple(coors, 0),),
'cinc_simple1' : (lambda coors, domain:
cinc_simple(coors, 1),),
'cinc_simple2' : (lambda coors, domain:
cinc_simple(coors, 2),),
'get_pars' : (lambda ts, coors, mode=None, **kwargs:
get_pars(ts, coors, mode,
output_dir=output_dir, **kwargs),),
}
regions, dim = define_regions(filename_mesh)
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
'pressure': ('real', 'scalar', 'Omega', 1),
'multiplier': ('real', 'scalar', 'Walls', 1),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
'ul' : ('unknown field', 'multiplier', 2),
'vl' : ('test field', 'multiplier', 'ul'),
}
ebcs = {
'inlet' : ('Inlet', {'p.0' : 1.0, 'u.all' : 0.0}),
'outlet' : ('Outlet', {'p.0' : -1.0}),
}
lcbcs = {
'rigid' : ('Outlet', {'u.all' : None}, None, 'rigid'),
}
materials = {
'm' : 'get_pars',
}
equations = {
'eq_1' :
"""dw_lin_elastic.2.Omega( m.D, v, u )
- dw_biot.2.Omega( m.alpha, v, p )
+ dw_non_penetration.2.Walls( v, ul )
= 0""",
'eq_2' :
"""dw_biot.2.Omega( m.alpha, u, q )
+ dw_diffusion.2.Omega( m.K, q, p )
= 0""",
(continues on next page)
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {}),
}
return locals()
multi_physics/biot_parallel_interactive.py
Description
Parallel assembling and solving of a Biot problem (deformable porous medium), using commands for interactive use.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − 𝑝 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑣) = 0 , ∀𝑣 ,
Ω
∫︁ ∫︁ Ω
𝑞 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑢) + 𝐾𝑖𝑗 ∇𝑖 𝑞∇𝑗 𝑝 = 0 , ∀𝑞 ,
Ω Ω
where
Important Notes
• This example requires petsc4py, mpi4py and (optionally) pymetis with their dependencies installed!
• This example generates a number of files - do not use an existing non-empty directory for the output_dir
argument.
• Use the --clear option with care!
Notes
• Each task is responsible for a subdomain consisting of a set of cells (a cell region).
• Each subdomain owns PETSc DOFs within a consecutive range.
• When both global and task-local variables exist, the task-local variables have _i suffix.
• This example shows how to use a nonlinear solver from PETSc.
• This example can serve as a template for solving a (non)linear multi-field problem - just replace the equations in
create_local_problem().
• The material parameter 𝛼𝑖𝑗 is artificially high to be able to see the pressure influence on displacements.
• The command line options are saved into <output_dir>/options.txt file.
Usage Examples
$ python sfepy/examples/multi_physics/biot_parallel_interactive.py -h
Parallel runs:
˓→ksp_monitor
˓→fieldsplit
source code
#!/usr/bin/env python
r"""
Parallel assembling and solving of a Biot problem (deformable porous medium),
using commands for interactive use.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} p\ \alpha_{ij} e_{ij}(\ul{v})
= 0
\;, \quad \forall \ul{v} \;,
(continues on next page)
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
Important Notes
---------------
- This example requires petsc4py, mpi4py and (optionally) pymetis with their
dependencies installed!
- This example generates a number of files - do not use an existing non-empty
directory for the ``output_dir`` argument.
- Use the ``--clear`` option with care!
Notes
-----
Usage Examples
--------------
$ python sfepy/examples/multi_physics/biot_parallel_interactive.py -h
Parallel runs::
import numpy as nm
import sfepy.parallel.parallel as pl
from sfepy.parallel.evaluate import PETScParallelEvaluator
mesh = omega_gi.domain.mesh
gamma1_i = domain_i.create_region('Gamma1',
'vertices in (x < %.10f )'
% (min_x + eps_x),
'facet', allow_empty=True)
gamma2_i = domain_i.create_region('Gamma2',
'vertices in (x > %.10f )'
% (max_x - eps_x),
'facet', allow_empty=True)
gamma3_i = domain_i.create_region('Gamma3',
'vertices in (y < %.10f )'
% (min_y + eps_y),
'facet', allow_empty=True)
if mesh.dim == 2:
alpha = 1e2 * nm.array([[0.132], [0.132], [0.092]])
else:
alpha = 1e2 * nm.array([[0.132], [0.132], [0.132],
(continues on next page)
return pb
stats = Struct()
timer = Timer('solve_timer')
timer.start()
mesh = Mesh.from_file(mesh_filename)
stats.t_read_mesh = timer.stop()
timer.start()
if rank == 0:
cell_tasks = pl.partition_mesh(mesh, size, use_metis=options.metis,
(continues on next page)
else:
cell_tasks = None
stats.t_partition_mesh = timer.stop()
stats.t_create_global_fields = timer.stop()
output('...done in', timer.dt)
output('distributing fields...')
timer.start()
distribute = pl.distribute_fields_dofs
lfds, gfds = distribute(fields, cell_tasks,
is_overlap=True,
use_expand_dofs=True,
save_inter_regions=options.save_inter_regions,
output_dir=options.output_dir,
comm=comm, verbose=True)
stats.t_distribute_fields_dofs = timer.stop()
output('...done in', timer.dt)
cells = lfds[0].cells
variables = pb.get_initial_state()
variables.fill_state(0.0)
variables.apply_ebc()
stats.t_create_local_problem = timer.stop()
(continues on next page)
stats.t_allocate_global_system = timer.stop()
output('...done in', timer.dt)
output('creating solver...')
timer.start()
field_ranges = {}
for ii, variable in enumerate(variables.iter_state(ordered=True)):
field_ranges[variable.name] = lfds[ii].petsc_dofs_range
ls.set_field_split(field_ranges, comm=comm)
nls_status = {}
conf = Struct(method='newtonls',
i_max=5, eps_a=0, eps_r=1e-5, eps_s=0.0,
verbose=True)
nls = PETScNonlinearSolver(conf, pmtx=pmtx, prhs=prhs, comm=comm,
fun=ev.eval_residual,
fun_grad=ev.eval_tangent_matrix,
lin_solver=ls, status=nls_status)
stats.t_create_solver = timer.stop()
output('...done in', timer.dt)
output('solving...')
timer.start()
variables.apply_ebc()
ev.psol_i[...] = variables()
ev.gather(psol, ev.psol_i)
ev.scatter(ev.psol_i, psol)
sol0_i = ev.psol_i[...]
stats.t_solve = timer.stop()
output('...done in', timer.dt)
output('saving solution...')
timer.start()
variables.set_state(sol0_i)
out = variables.create_output()
gather_to_zero = pl.create_gather_to_zero(psol)
psol_full = gather_to_zero(psol)
if comm.rank == 0:
sol = psol_full[...].copy()
else:
out = u.create_output(ug, linearization=Struct(kind='adaptive',
min_level=0,
max_level=order_u,
eps=1e-3))
stats.t_save_solution = timer.stop()
output('...done in', timer.dt)
stats.t_total = timer.total
stats.n_dof = sizes[1]
stats.n_dof_local = sizes[0]
stats.n_cell = omega.shape.n_cell
stats.n_cell_local = omega_gi.shape.n_cell
return stats
helps = {
'output_dir' :
'output directory',
'dims' :
'dimensions of the block [default: %(default)s]',
'shape' :
'shape (counts of nodes in x, y, z) of the block [default: %(default)s]',
'centre' :
'centre of the block [default: %(default)s]',
'2d' :
'generate a 2D rectangle, the third components of the above'
' options are ignored',
'u-order' :
'displacement field approximation order',
'p-order' :
'pressure field approximation order',
'linearization' :
'linearization used for storing the results with approximation order > 1'
' [default: %(default)s]',
'metis' :
'use metis for domain partitioning',
'save_inter_regions' :
'save inter-task regions for debugging partitioning problems',
'stats_filename' :
'name of the stats file for storing elapsed time statistics',
'new_stats' :
'create a new stats file with a header line (overwrites existing!)',
'silent' : 'do not print messages to screen',
'clear' :
'clear old solution files from output directory'
' (DANGEROUS - use with care!)',
}
def main():
(continues on next page)
comm = pl.PETSc.COMM_WORLD
output_dir = options.output_dir
output('dimensions:', dims)
output('shape: ', shape)
output('centre: ', centre)
if comm.rank == 0:
from sfepy.mesh.mesh_generators import gen_block_mesh
if options.clear:
remove_files_patterns(output_dir,
['*.h5', '*.mesh', '*.txt'],
ignores=['output_log_%02d.txt' % ii
for ii in range(comm.size)],
verbose=True)
save_options(os.path.join(output_dir, 'options.txt'),
[('options', vars(options))])
comm.barrier()
if options.stats_filename:
from sfepy.examples.diffusion.poisson_parallel_interactive import save_stats
if comm.rank == 0:
ensure_path(options.stats_filename)
comm.barrier()
if __name__ == '__main__':
main()
multi_physics/biot_short_syntax.py
Description
Biot problem - deformable porous medium with a no-penetration boundary condition imposed in the weak sense on a
boundary region, using the short syntax of keywords.
The Biot coefficient tensor 𝛼𝑖𝑗 is non-symmetric. The mesh resolution can be changed by editing the shape variable.
This example demonstrates how to set up various linear solvers and preconditioners (see solvers dict):
• ‘direct’ (a direct solver from SciPy), ‘iterative-s’ (an iterative solver from SciPy), ‘iterative-p’ (an iterative solver
from PETSc) solvers can be used as the main linear solver.
• ‘direct’, ‘cg-s’ (several iterations of CG from SciPy), ‘cg-p’ (several iterations of CG from PETSc), ‘pyamg’ (an
algebraic multigrid solver) solvers can be used as preconditioners for the matrix blocks on the diagonal.
See setup_precond() and try to modify it.
The PETSc solvers can be configured also using command line options. For example, set 'ls' : 'iterative-p'
in options, and run:
or simply run:
to monitor the PETSc iterative solver convergence. It will diverge without preconditioning, see matvec_bj(),
matvec_j() for further details.
The PETSc options can also be set in the solver configuration - try uncommenting the 'ksp_*' or 'pc_*' parameters
in 'iterative-p'. Uncommenting all the lines leads to, among other things, using the GMRES method with no
preconditioning and the condition number estimate computation. Compare the condition number estimates with and
without a preconditioning (try, for example, using 'precond' : 'mg' or 'pc_type' : 'mg').
Find 𝑢, 𝑝 such that:
∫︁ ∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − 𝑝 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑣) + 𝜀(𝑛 · 𝑣)(𝑛 · 𝑢) = 0 , ∀𝑣 ,
Ω Ω Γ𝑇 𝐵
∫︁ ∫︁
− 𝑞 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑢) − 𝐾𝑖𝑗 ∇𝑖 𝑞∇𝑗 𝑝 = 0 , ∀𝑞 ,
Ω Ω
where
source code
r"""
Biot problem - deformable porous medium with a no-penetration boundary
condition imposed in the weak sense on a boundary region, using the short
syntax of keywords.
The PETSc solvers can be configured also using command line options. For
(continues on next page)
or simply run::
The PETSc options can also be set in the solver configuration - try
uncommenting the ``'ksp_*'`` or ``'pc_*'`` parameters in ``'iterative-p'``.
Uncommenting all the lines leads to, among other things, using the GMRES method
with no preconditioning and the condition number estimate computation. Compare
the condition number estimates with and without a preconditioning (try, for
example, using ``'precond' : 'mg'`` or ``'pc_type' : 'mg'``).
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} p\ \alpha_{ij} e_{ij}(\ul{v})
+ \int_{\Gamma_{TB}} \varepsilon (\ul{n} \cdot \ul{v}) (\ul{n} \cdot \ul{u})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;.
"""
from __future__ import absolute_import
import numpy as nm
out = {}
out['D'] = stiffness_from_lame(dim, lam=1.7, mu=0.3)[None, ...]
out['np_eps'] = nm.array([[[1e5]]])
return out
return out
# Mesh dimensions.
dims = [0.1, 0.1]
filename_mesh = UserMeshIO(mesh_hook)
(continues on next page)
materials = {
'coef' : ({'val' : 1.0},),
}
regions = {
'Omega' : 'all', # or 'cells of group 6'
'GammaL' : ('vertices in (x < -0.0499)', 'facet'),
'GammaR' : ('vertices in (x > 0.0499)', 'facet'),
'GammaTB' : ('vertices of surface -s (r.GammaL +s r.GammaR)', 'facet')
}
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
'pressure': ('real', 'scalar', 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
}
ebcs = {
'inlet' : ('GammaL', {'p.0' : 1.0, 'u.all' : 0.0}),
'outlet' : ('GammaR', {'p.0' : 0.0}),
}
integrals = {
'i' : 2,
}
materials = {
'm' : 'get_pars',
}
functions = {
'get_pars' : (get_pars,),
}
equations = {
'eq_1' :
"""+ dw_lin_elastic.i.Omega(m.D, v, u)
- dw_biot.i.Omega(m.alpha, v, p)
+ dw_non_penetration_p.i.GammaTB(m.np_eps, v, u)
= 0""",
'eq_2' :
"""- dw_biot.i.Omega(m.alpha, u, q)
- dw_diffusion.i.Omega(m.K, q, p)
= 0""",
}
(continues on next page)
def matvec_bj(vec):
"""
The application of the Block Jacobi preconditioner.
The exact version (as with the `'direct'` solver) can be obtained also
by using the following PETSs command-line options, together with the
`'iterative-p'` solver::
"""
vu = ls1(vec[iu])
vp = ls2(vec[ip])
The same effect can be obtained also by using the following PETSs
command-line options, together with the `'iterative-p'` solver::
return vec / D
return precond
method = 'gmres'
i_max = 20
eps_r = 1e-8
solvers = {
'direct' : ('ls.scipy_direct', {}),
'iterative-s' : ('ls.scipy_iterative', {
'method' : method,
'i_max' : i_max,
'eps_r' : eps_r,
'setup_precond': setup_precond,
'verbose' : 2,
}),
'cg-s' : ('ls.scipy_iterative', {
'method' : 'cg',
'i_max' : 20,
'eps_r' : 1e-6,
'verbose' : 0,
}),
'iterative-p' : ('ls.petsc', {
'method' : method,
'precond' : 'none',
'i_max' : i_max,
'eps_r' : eps_r,
'verbose' : 2,
# 'ksp_converged_reason' : None,
# 'ksp_monitor_true_residual' : None,
# 'ksp_monitor_singular_value' : None,
# 'ksp_final_residual' : None,
# 'ksp_type' : 'gmres', # Overrides `method`.
# 'ksp_max_it' : 500,
(continues on next page)
'pyamg' : ('ls.pyamg', {
'method' : 'smoothed_aggregation_solver',
'i_max' : 20,
'eps_r' : 1e-6,
'verbose' : 0,
}),
'newton' : ('nls.newton',
{'i_max' : 1,
'eps_r' : 1e-6,
'eps_a' : 1.0,
}),
}
options = {
'nls' : 'newton',
'ls' : 'iterative-s',
'post_process_hook' : 'post_process',
}
multi_physics/piezo_elasticity.py
Description
Piezo-elasticity problem - linear elastic material with piezoelectric effects.
Find 𝑢, 𝜑 such that:
∫︁ ∫︁ ∫︁
−𝜔 2 𝜌𝑣·𝑢+ 𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − 𝑔𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑣)∇𝑘 𝜑 = 0 , ∀𝑣 ,
𝑌 𝑌 𝑌2
∫︁ ∫︁
𝑔𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑢)∇𝑘 𝜓 + 𝐾𝑖𝑗 ∇𝑖 𝜓∇𝑗 𝜑 = 0 , ∀𝜓 ,
𝑌2 𝑌
where
source code
r"""
Piezo-elasticity problem - linear elastic material with piezoelectric
effects.
.. math::
- \omega^2 \int_{Y} \rho\ \ul{v} \cdot \ul{u}
+ \int_{Y} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{Y_2} g_{kij}\ e_{ij}(\ul{v}) \nabla_k \phi
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
(continues on next page)
ev = pb.evaluate
strain = ev('ev_cauchy_strain.i.Y(u)', mode='el_avg')
stress = ev('ev_cauchy_stress.i.Y(inclusion.D, u)', mode='el_avg')
return out
omega = 1
omega_squared = omega**2
options = {
'post_process_hook' : 'post_process',
}
regions = {
'Y' : 'all',
'Y1' : 'cells of group 1',
'Y2' : 'cells of group 2',
'Y2_Surface': ('r.Y1 *v r.Y2', 'facet'),
'Left' : ('vertices in (x < %f )' % (x_left + 1e-3), 'facet'),
'Right' : ('vertices in (x > %f )' % (x_right - 1e-3), 'facet'),
}
fields = {
'displacement' : ('real', dim, 'Y', 1),
'potential' : ('real', 1, 'Y', 1),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
'phi' : ('unknown field', 'potential', 1),
'psi' : ('test field', 'potential', 'phi'),
}
ebcs = {
'u1' : ('Left', {'u.all' : 0.0}),
'u2' : ('Right', {'u.0' : 0.1}),
'phi' : ('Y2_Surface', {'phi.all' : 0.0}),
}
out = {
(continues on next page)
return out
materials = {
'inclusion' : (None, 'get_inclusion_pars')
}
functions = {
'get_inclusion_pars' : (get_inclusion_pars,),
}
integrals = {
'i' : 2,
}
equations = {
'1' : """- %f * dw_dot.i.Y(inclusion.density, v, u)
+ dw_lin_elastic.i.Y(inclusion.D, v, u)
- dw_piezo_coupling.i.Y2(inclusion.coupling, v, phi)
= 0""" % omega_squared,
'2' : """dw_piezo_coupling.i.Y2(inclusion.coupling, u, psi)
+ dw_diffusion.i.Y(inclusion.dielectric, psi, phi)
= 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton',
{'i_max' : 1,
'eps_a' : 1e-10,
}),
}
multi_physics/piezo_elasticity_macro.py
Description
Piezo-elasticity problem - homogenization of a piezoelectric linear elastic matrix with embedded metalic electrodes,
see [1] for details.
[1] E.Rohan, V.Lukes: Homogenization of the fluid-saturated piezoelectric porous media. International Journal of
Solids and Structures 147, 2018, pages 110-125. https://doi.org/10.1016/j.ijsolstr.2018.05.017
source code
r"""
Piezo-elasticity problem - homogenization of a piezoelectric linear elastic
matrix with embedded metalic electrodes, see [1] for details.
import numpy as nm
from sfepy import data_dir, base_dir
from sfepy.base.base import Struct
(continues on next page)
return nm.ascontiguousarray(nm.array(aux).T)
# micro recovery
rreg = pb.domain.regions['Recovery']
dim = rreg.dim
state_dict = state.get_state_parts()
displ = state_dict['u']
strain_qp = pb.evaluate('ev_cauchy_strain.i2.Omega(u)', mode='qp')
nodal_data = {
'u': displ.reshape((displ.shape[0] // dim, dim)), # displacement
'strain': linear_projection(pb, strain_qp), # strain
}
const_data = {
'phi': pb.conf.phi, # el. potentials
}
def_args = {
'eps0': pb.conf.eps0,
'filename_mesh': pb.conf.filename_mesh_micro,
}
pvar = pb.create_variables(['svar'])
recover_micro_hook_eps(pb.conf.filename_micro, rreg,
pvar['svar'], nodal_data, const_data, pb.conf.eps0,
define_args=def_args)
return out
def get_homog_fun(fname):
return lambda ts, coors, mode=None, problem=None, **kwargs:\
(continues on next page)
nqp = coors.shape[0]
coefs_filename = osp.join(pb.conf.options.get('output_dir', '.'),
'coefs_piezo.h5')
def_args = {
'eps0': pb.conf.eps0,
'filename_mesh': pb.conf.filename_mesh_micro,
}
out = {
'A': nm.tile(coefs['A'], (nqp, 1, 1)),
'Vf': nm.tile(Vf[:, nm.newaxis], (nqp, 1, 1)),
}
return out
def define():
eps0 = 1. / 30 # real size of the reference cell
fields = {
'displacement': ('real', 'vector', 'Omega', 1),
'sfield': ('real', 'scalar', 'Omega', 1),
}
variables = {
'u': ('unknown field', 'displacement'),
'v': ('test field', 'displacement', 'u'),
'svar': ('parameter field', 'sfield', 'set-to-none'),
(continues on next page)
materials = {
'hom': 'get_homog',
}
integrals = {
'i2': 2,
}
regions = {
'Omega': 'all',
'Left': ('vertices in (x < -0.4999)', 'facet'),
'Recovery': ('cell 266'),
}
ebcs = {
'fixed_u': ('Left', {'u.all': 0.0}),
}
equations = {
'balance_of_forces': """
dw_lin_elastic.i2.Omega(hom.A, v, u)
=
- dw_lin_prestress.i2.Omega(hom.Vf, v)""",
}
solvers = {
'ls': ('ls.scipy_direct', {}),
'newton': ('nls.newton',
{'i_max': 10,
'eps_a': 1e-3,
'eps_r': 1e-3,
'problem': 'nonlinear',
})
}
options = {
'output_dir': 'output',
'nls': 'newton',
'post_process_hook': 'post_process',
}
return locals()
multi_physics/piezo_elasticity_micro.py
Description
Piezo-elasticity problem - homogenization of a piezoelectric linear elastic matrix with embedded metalic electrodes,
see [1] for details.
[1] E.Rohan, V.Lukes: Homogenization of the fluid-saturated piezoelectric porous media. International Journal of
Solids and Structures 147, 2018, pages 110-125. https://doi.org/10.1016/j.ijsolstr.2018.05.017
source code
r"""
Piezo-elasticity problem - homogenization of a piezoelectric linear elastic
matrix with embedded metalic electrodes, see [1] for details.
import numpy as nm
from sfepy.mechanics.matcoefs import stiffness_from_youngpoisson
from sfepy.homogenization.utils import coor_to_sym, define_box_regions
from sfepy.discrete.fem.mesh import Mesh
from sfepy.base.base import Struct
import sfepy.discrete.fem.periodic as per
import sfepy.homogenization.coefs_base as cb
for ii in range(2):
u1 += corrs['corrs_k%d' % ii]['u'] * macro['phi'][ii]
phi += corrs['corrs_k%d' % ii]['r'] * macro['phi'][ii]
for ii in range(dim):
for jj in range(dim):
kk = coor_to_sym(ii, jj, dim)
phi += corrs['corrs_rs']['r_%d%d' % (ii, jj)]\
* nm.expand_dims(macro['strain'][Ym_map, kk], axis=1)
u1 += corrs['corrs_rs']['u_%d%d' % (ii, jj)]\
* nm.expand_dims(macro['strain'][Ymc_map, kk], axis=1)
u = macro['u'][Ymc_map, :] + eps0 * u1
(continues on next page)
for ii in range(dim):
for jj in range(dim):
kk = coor_to_sym(ii, jj, dim)
mvar['svar'].set_data(macro['strain'][:, kk])
mac_e_Ymc = pb.evaluate('ev_integrate.i2.Ymc(svar)',
mode='el_avg',
var_dict={'svar': mvar['svar']})
e_mac_Ymc[kk] = mac_e_Ymc.squeeze()
mvar['r'].set_data(phi)
E_mic = pb.evaluate('ev_grad.i2.Ym(r)',
mode='el_avg',
var_dict={'r': mvar['r']}) / eps0
mvar['u'].set_data(u1)
e_mic = pb.evaluate('ev_cauchy_strain.i2.Ymc(u)',
mode='el_avg',
var_dict={'u': mvar['u']})
e_mic += e_mac_Ymc
out = {
'u0': (macro['u'][Ymc_map, :], 'u', 'p'),
'u': (u, 'u', 'p'),
'u1': (u1, 'u', 'p'),
'e_mic': (e_mic, 'u', 'c'),
'phi': (phi, 'r', 'p'),
'E_mic': (E_mic, 'r', 'c'),
}
out_struct = {}
for k, v in out.items():
out_struct[k] = Struct(name='output_data',
mode='cell' if v[2] == 'c' else 'vertex',
data=v[0],
var_name=v[1],
dofs=None)
return out_struct
mesh = Mesh.from_file(filename_mesh)
bbox = mesh.get_bounding_box()
(continues on next page)
regions.update({
'Ymc': 'all',
# matrix
'Ym': 'cells of group 1',
'Ym_left': ('r.Ym *v r.Left', 'vertex'),
'Ym_right': ('r.Ym *v r.Right', 'vertex'),
'Ym_bottom': ('r.Ym *v r.Bottom', 'vertex'),
'Ym_top': ('r.Ym *v r.Top', 'vertex'),
'Ym_far': ('r.Ym *v r.Far', 'vertex'),
'Ym_near': ('r.Ym *v r.Near', 'vertex'),
'Gamma_ms': ('r.Ym *v r.Yc', 'facet', 'Ym'),
# conductors
'Yc': ('r.Yc1 +c r.Yc2', 'cell'),
'Yc1': 'cells of group 2',
'Yc2': 'cells of group 3',
'Gamma_s1': ('r.Ym *v r.Yc1', 'facet', 'Ym'),
'Gamma_s2': ('r.Ym *v r.Yc2', 'facet', 'Ym'),
})
options = {
'coefs_filename': 'coefs_piezo',
'volume': {'value': nm.prod(bbox[1] - bbox[0])},
'coefs': 'coefs',
'requirements': 'requirements',
'output_dir': 'output',
'file_per_var': True,
'absolute_mesh_path': True,
'multiprocessing': False,
'recovery_hook': recovery_micro,
}
fields = {
'displacement': ('real', 'vector', 'Ymc', 1),
'potential': ('real', 'scalar', 'Ym', 1),
'sfield': ('real', 'scalar', 'Ymc', 1),
}
variables = {
# displacement
'u': ('unknown field', 'displacement'),
'v': ('test field', 'displacement', 'u'),
'Pi_u': ('parameter field', 'displacement', 'u'),
'U1': ('parameter field', 'displacement', '(set-to-None)'),
'U2': ('parameter field', 'displacement', '(set-to-None)'),
# potential
'r': ('unknown field', 'potential'),
's': ('test field', 'potential', 'r'),
'Pi_r': ('parameter field', 'potential', 'r'),
'R1': ('parameter field', 'potential', '(set-to-None)'),
'R2': ('parameter field', 'potential', '(set-to-None)'),
(continues on next page)
epbcs = {
'p_ux': (['Left', 'Right'], {'u.all': 'u.all'}, 'match_x_plane'),
'p_uy': (['Near', 'Far'], {'u.all': 'u.all'}, 'match_y_plane'),
'p_uz': (['Bottom', 'Top'], {'u.all': 'u.all'}, 'match_z_plane'),
'p_rx': (['Ym_left', 'Ym_right'], {'r.0': 'r.0'}, 'match_x_plane'),
'p_ry': (['Ym_near', 'Ym_far'], {'r.0': 'r.0'}, 'match_y_plane'),
'p_rz': (['Ym_bottom', 'Ym_top'], {'r.0': 'r.0'}, 'match_z_plane'),
}
periodic = {
'per_u': ['per_u_x', 'per_u_y', 'per_u_z'],
'per_r': ['per_r_x', 'per_r_y', 'per_r_z'],
}
materials = {
'elastic': ({
'D': {
'Ym': nm.array([[1.504, 0.656, 0.659, 0, 0, 0],
[0.656, 1.504, 0.659, 0, 0, 0],
[0.659, 0.659, 1.455, 0, 0, 0],
[0, 0, 0, 0.424, 0, 0],
[0, 0, 0, 0, 0.439, 0],
[0, 0, 0, 0, 0, 0.439]]) * 1e11,
'Yc': stiffness_from_youngpoisson(3, 200e9, 0.25)}},),
'piezo': ({
'g': nm.array([[0, 0, 0, 0, 11.404, 0],
[0, 0, 0, 0, 0, 11.404],
[-4.322, -4.322, 17.360, 0, 0, 0]]) / mat_g_sc,
'd': nm.array([[1.284, 0, 0],
[0, 1.284, 0],
[0, 0, 1.505]]) * 1e-8 / mat_d_sc},),
}
functions = {
'match_x_plane': (per.match_x_plane,),
'match_y_plane': (per.match_y_plane,),
'match_z_plane': (per.match_z_plane,),
}
ebcs = {
'fixed_u': ('Corners', {'u.all': 0.0}),
'fixed_r': ('Gamma_ms', {'r.all': 0.0}),
'fixed_r1_s1': ('Gamma_s1', {'r.0': 1.0}),
'fixed_r0_s1': ('Gamma_s1', {'r.0': 0.0}),
'fixed_r1_s2': ('Gamma_s2', {'r.0': 1.0}),
(continues on next page)
integrals = {
'i2': 2,
}
solvers = {
'ls_d': ('ls.scipy_direct', {}),
'ls_i': ('ls.scipy_iterative', {}),
'ns_ea6': ('nls.newton', {'eps_a': 1e6, 'eps_r': 1e-3,}),
'ns_ea0': ('nls.newton', {'eps_a': 1e0, 'eps_r': 1e-3,}),
}
coefs = {
'A1': {
'status': 'auxiliary',
'requires': ['pis_u', 'corrs_rs'],
'expression': 'dw_lin_elastic.i2.Ymc(elastic.D, U1, U2)',
'set_variables': [('U1', ('corrs_rs', 'pis_u'), 'u'),
('U2', ('corrs_rs', 'pis_u'), 'u')],
'class': cb.CoefSymSym,
},
'A2': {
'status': 'auxiliary',
'requires': ['corrs_rs'],
'expression': 'dw_diffusion.i2.Ym(piezo.d, R1, R2)',
'set_variables': [('R1', 'corrs_rs', 'r'),
('R2', 'corrs_rs', 'r')],
'class': cb.CoefSymSym,
},
'A': {
'requires': ['c.A1', 'c.A2'],
'expression': 'c.A1 + c.A2',
'class': cb.CoefEval,
},
'vol': {
'regions': ['Ym', 'Yc1', 'Yc2'],
'expression': 'ev_volume.i2.%s(svar)',
'class': cb.VolumeFractions,
},
'eps0': {
'requires': [],
'expression': '%e' % eps0,
'class': cb.CoefEval,
},
'filenames': {},
}
requirements = {
'pis_u': {
'variables': ['u'],
(continues on next page)
for k in range(2):
sk = '%d' % k
requirements.update({
'corrs_k' + sk: {
'requires': ['pis_r'],
'ebcs': ['fixed_u'] + bc_conductors[k],
'epbcs': ['p_ux', 'p_uy', 'p_uz', 'p_rx', 'p_ry', 'p_rz'],
'equations': {
'eq1':
"""dw_lin_elastic.i2.Ymc(elastic.D, v, u)
- dw_piezo_coupling.i2.Ym(piezo.g, v, r)
= 0""",
'eq2':
"""
- dw_piezo_coupling.i2.Ym(piezo.g, u, s)
- dw_diffusion.i2.Ym(piezo.d, s, r)
= 0"""
(continues on next page)
coefs.update({
'V1_' + sk: {
'status': 'auxiliary',
'requires': ['pis_u', 'corrs_k' + sk],
'expression': 'dw_lin_elastic.i2.Ymc(elastic.D, U1, U2)',
'set_variables': [('U1', 'corrs_k' + sk, 'u'),
('U2', 'pis_u', 'u')],
'class': cb.CoefSym,
},
'V2_' + sk: {
'status': 'auxiliary',
'requires': ['pis_u', 'corrs_k' + sk],
'expression': 'dw_piezo_coupling.i2.Ym(piezo.g, U1, R1)',
'set_variables': [('R1', 'corrs_k' + sk, 'r'),
('U1', 'pis_u', 'u')],
'class': cb.CoefSym,
},
'V' + sk: {
'requires': ['c.V1_' + sk, 'c.V2_' + sk],
'expression': 'c.V1_%s - c.V2_%s' % (sk, sk),
'class': cb.CoefEval,
},
})
return locals()
multi_physics/thermal_electric.py
Description
First solve the stationary electric conduction problem. Then use its results to solve the evolutionary heat conduction
problem.
Run this example as on a command line:
$ python <path_to_this_file>/thermal_electric.py
source code
#!/usr/bin/env python
"""
First solve the stationary electric conduction problem. Then use its
results to solve the evolutionary heat conduction problem.
$ python <path_to_this_file>/thermal_electric.py
"""
from __future__ import absolute_import
import sys
sys.path.append( '.' )
import os
# Material parameters.
specific_heat = 1.2
##########
options = {
'absolute_mesh_path' : True,
'output_dir' : os.path.join(cwd, 'output')
}
regions = {
'Omega' : 'all',
'Omega1' : 'cells of group 1',
'Omega2' : 'cells of group 2',
'Omega2_Surface': ('r.Omega1 *v r.Omega2', 'facet'),
'Left' : ('vertices in (x < %f )' % -0.4999, 'facet'),
'Right' : ('vertices in (x > %f )' % 0.4999, 'facet'),
}
materials = {
'm' : ({
'thermal_conductivity' : 2.0,
'electric_conductivity' : 1.5,
},),
}
# The fields use the same approximation, so a single field could be used
# instead.
fields = {
'temperature': ('real', 1, 'Omega', 1),
'potential' : ('real', 1, 'Omega', 1),
}
ics = {
'ic' : ('Omega', {'T.0' : 0.0}),
}
ebcs = {
'left' : ('Left', {'T.0' : 0.0, 'phi.0' : 0.0}),
'right' : ('Right', {'T.0' : 2.0, 'phi.0' : 0.0}),
'inside' : ('Omega2_Surface', {'phi.0' : 'set_electric_bc'}),
}
def set_electric_bc(coor):
y = coor[:,1]
ymin, ymax = y.min(), y.max()
val = 2.0 * (((y - ymin) / (ymax - ymin)) - 0.5)
return val
functions = {
'set_electric_bc' : (lambda ts, coor, bc, problem, **kwargs:
set_electric_bc(coor),),
}
equations = {
'2' : """%.12e * dw_dot.2.Omega( s, dT/dt )
+ dw_laplace.2.Omega( m.thermal_conductivity, s, T )
= dw_electric_source.2.Omega( m.electric_conductivity,
s, phi_known ) """ % specific_heat,
'1' : """dw_laplace.2.Omega( m.electric_conductivity, psi, phi ) = 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
'problem' : 'nonlinear',
}),
'ts' : ('ts.simple', {
't0' : t0,
't1' : t1,
'dt' : None,
'n_step' : n_step, # has precedence over dt!
'verbose' : 1,
}),
}
(continues on next page)
def main():
from sfepy.base.base import output
from sfepy.base.conf import ProblemConf, get_standard_keywords
from sfepy.discrete import Problem
output.prefix = 'therel:'
if __name__ == '__main__':
main()
multi_physics/thermo_elasticity.py
Description
Thermo-elasticity with a given temperature distribution.
Uses dw_biot term with an isotropic coefficient for thermo-elastic coupling.
For given body temperature 𝑇 and background temperature 𝑇0 find 𝑢 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − (𝑇 − 𝑇0 ) 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑣) = 0 , ∀𝑣 ,
Ω Ω
where
𝐷𝑖𝑗𝑘𝑙 = 𝜇(𝛿𝑖𝑘 𝛿𝑗𝑙 + 𝛿𝑖𝑙 𝛿𝑗𝑘 ) + 𝜆 𝛿𝑖𝑗 𝛿𝑘𝑙 ,
source code
r"""
Thermo-elasticity with a given temperature distribution.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} (T - T_0)\ \alpha_{ij} e_{ij}(\ul{v})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;, \\
# Material parameters.
lam = 10.0
mu = 5.0
thermal_expandability = 1.25e-5
T0 = 20.0 # Background temperature.
out['total_stress'] = Struct(name='output_data',
mode='cell', data=e_stress + t_stress,
dofs=None)
(continues on next page)
val = pb.get_variables()['T']()
val.shape = (val.shape[0], 1)
out['T'] = Struct(name='output_data',
mode='vertex', data=val + T0,
dofs=None)
return out
options = {
'post_process_hook' : 'post_process',
'nls' : 'newton',
'ls' : 'ls',
}
functions = {
'get_temperature_load' : (get_temperature_load,),
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -4.99)', 'facet'),
}
fields = {
'displacement': ('real', 3, 'Omega', 1),
'temperature': ('real', 1, 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'displacement', 0),
'v' : ('test field', 'displacement', 'u'),
'T' : ('parameter field', 'temperature',
{'setter' : 'get_temperature_load'}),
}
ebcs = {
'fix_u' : ('Left', {'u.all' : 0.0}),
}
equations = {
'balance_of_forces' :
"""dw_lin_elastic.2.Omega( solid.D, v, u )
- dw_biot.2.Omega( solid.alpha, v, T )
= 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
multi_physics/thermo_elasticity_ess.py
Description
Thermo-elasticity with a computed temperature demonstrating equation sequence solver.
Uses dw_biot term with an isotropic coefficient for thermo-elastic coupling.
The equation sequence solver ('ess' in solvers) automatically solves first the temperature distribution and then the
elasticity problem with the already computed temperature.
Find 𝑢, 𝑇 such that:
∫︁ ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢) − (𝑇 − 𝑇0 ) 𝛼𝑖𝑗 𝑒𝑖𝑗 (𝑣) = 0 , ∀𝑣 ,
Ω Ω
∫︁
∇𝑠 · ∇𝑇 = 0 , ∀𝑠 .
Ω
where
𝐷𝑖𝑗𝑘𝑙 = 𝜇(𝛿𝑖𝑘 𝛿𝑗𝑙 + 𝛿𝑖𝑙 𝛿𝑗𝑘 ) + 𝜆 𝛿𝑖𝑗 𝛿𝑘𝑙 ,
Notes
source code
r"""
Thermo-elasticity with a computed temperature demonstrating equation sequence
solver.
.. math::
\int_{\Omega} D_{ijkl}\ e_{ij}(\ul{v}) e_{kl}(\ul{u})
- \int_{\Omega} (T - T_0)\ \alpha_{ij} e_{ij}(\ul{v})
= 0
\;, \quad \forall \ul{v} \;,
where
.. math::
D_{ijkl} = \mu (\delta_{ik} \delta_{jl}+\delta_{il} \delta_{jk}) +
\lambda \ \delta_{ij} \delta_{kl}
\;, \\
Notes
-----
The gallery image was produced by (plus proper view settings)::
# Material parameters.
lam = 10.0
mu = 5.0
thermal_expandability = 1.25e-5
T0 = 20.0 # Background temperature.
options = {
'nls' : 'newton',
'ls' : 'ls',
'block_solve' : True,
}
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -4.99)', 'facet'),
'Right' : ('vertices in (x > 4.99)', 'facet'),
'Bottom' : ('vertices in (z < -0.99)', 'facet'),
}
fields = {
'displacement': ('real', 3, 'Omega', 1),
'temperature': ('real', 1, 'Omega', 1),
}
ebcs = {
'u0' : ('Left', {'u.all' : 0.0}),
't0' : ('Left', {'T.0' : 20.0}),
't2' : ('Bottom', {'T.0' : 0.0}),
't1' : ('Right', {'T.0' : 30.0}),
}
equations = {
'balance_of_forces' : """
+ dw_lin_elastic.2.Omega(solid.D, v, u)
- dw_biot.2.Omega(solid.alpha, v, T)
= 0
""",
'temperature' : """
+ dw_laplace.1.Omega(s, T)
= 0
"""
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
navier_stokes
navier_stokes/navier_stokes.py
Description
Navier-Stokes equations for incompressible fluid flow.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁ ∫︁
𝜈 ∇𝑣 : ∇𝑢 + ((𝑢 · ∇)𝑢) · 𝑣 − 𝑝∇·𝑣 =0, ∀𝑣 ,
Ω Ω
∫︁Ω
𝑞∇·𝑢=0, ∀𝑞 .
Ω
source code
r"""
Navier-Stokes equations for incompressible fluid flow.
.. math::
\int_{\Omega} \nu\ \nabla \ul{v} : \nabla \ul{u}
(continues on next page)
options = {
'nls' : 'newton',
'ls' : 'ls',
'post_process_hook' : 'verify_incompressibility',
field_1 = {
'name' : '3_velocity',
'dtype' : 'real',
'shape' : (3,),
'region' : 'Omega',
'approx_order' : '1B',
}
field_2 = {
'name' : 'pressure',
'dtype' : 'real',
'shape' : (1,),
'region' : 'Omega',
'approx_order' : 1,
}
region_0 = {
'name' : 'Walls',
'select' : 'vertices of surface -v (r.Outlet +v r.Inlet)',
'kind' : 'facet',
}
region_1 = {
'name' : 'Inlet',
'select' : 'vertices by cinc0', # In
'kind' : 'facet',
}
region_2 = {
'name' : 'Outlet',
'select' : 'vertices by cinc1', # Out
'kind' : 'facet',
}
ebc_1 = {
'name' : 'Walls',
'region' : 'Walls',
'dofs' : {'u.all' : 0.0},
}
ebc_2 = {
'name' : 'Inlet',
'region' : 'Inlet',
'dofs' : {'u.1' : 1.0, 'u.[0,2]' : 0.0},
}
material_1 = {
'name' : 'fluid',
'values' : {
'viscosity' : 1.25e-3,
'density' : 1e0,
},
}
variable_1 = {
'name' : 'u',
'kind' : 'unknown field',
'field' : '3_velocity',
'order' : 0,
}
variable_2 = {
'name' : 'v',
'kind' : 'test field',
'field' : '3_velocity',
'dual' : 'u',
}
variable_3 = {
'name' : 'p',
'kind' : 'unknown field',
(continues on next page)
integral_1 = {
'name' : 'i1',
'order' : 2,
}
integral_2 = {
'name' : 'i2',
'order' : 3,
}
##
# Stationary Navier-Stokes equations.
equations = {
'balance' :
"""+ dw_div_grad.i2.Omega( fluid.viscosity, v, u )
+ dw_convect.i2.Omega( v, u )
- dw_stokes.i1.Omega( v, p ) = 0""",
'incompressibility' :
"""dw_stokes.i1.Omega( u, q ) = 0""",
}
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 5,
'eps_a' : 1e-8,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
(continues on next page)
return out
##
# Functions.
import os.path as op
import sys
functions = {
'cinc0' : (lambda coors, domain=None: cinc(coors, 0),),
'cinc1' : (lambda coors, domain=None: cinc(coors, 1),),
}
navier_stokes/navier_stokes2d.py
Description
Navier-Stokes equations for incompressible fluid flow in 2D.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁ ∫︁
𝜈 ∇𝑣 : ∇𝑢 + ((𝑢 · ∇)𝑢) · 𝑣 − 𝑝∇·𝑣 =0, ∀𝑣 ,
Ω Ω Ω
∫︁
𝑞∇·𝑢=0, ∀𝑞 .
Ω
$ ./resview.py user_block.vtk -2
source code
.. math::
\int_{\Omega} \nu\ \nabla \ul{v} : \nabla \ul{u}
+ \int_{\Omega} ((\ul{u} \cdot \nabla) \ul{u}) \cdot \ul{v}
- \int_{\Omega} p\ \nabla \cdot \ul{v}
= 0
\;, \quad \forall \ul{v} \;,
$ ./resview.py user_block.vtk -2
"""
from __future__ import absolute_import
from sfepy.discrete.fem.meshio import UserMeshIO
from sfepy.mesh.mesh_generators import gen_block_mesh
# Mesh dimensions.
dims = [0.1, 0.1]
filename_mesh = UserMeshIO(mesh_hook)
regions = {
'Omega' : 'all',
'Left' : ('vertices in (x < -0.0499)', 'facet'),
'Right' : ('vertices in (x > 0.0499)', 'facet'),
'Bottom' : ('vertices in (y < -0.0499)', 'facet'),
'Top' : ('vertices in (y > 0.0499)', 'facet'),
'Walls' : ('r.Left +v r.Right +v r.Bottom', 'facet'),
}
materials = {
'fluid' : ({'viscosity' : 1.00e-2},),
}
fields = {
'velocity': ('real', 'vector', 'Omega', 2),
'pressure': ('real', 'scalar', 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'velocity', 0),
'v' : ('test field', 'velocity', 'u'),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
}
(continues on next page)
ebcs = {
'1_Walls' : ('Walls', {'u.all' : 0.0}),
'0_Driven' : ('Top', {'u.0' : 1.0, 'u.1' : 0.0}),
'Pressure' : ('Bottom', {'p.0' : 0.0}),
}
integrals = {
'i' : 4,
}
equations = {
'balance' :
"""+ dw_div_grad.i.Omega(fluid.viscosity, v, u)
+ dw_convect.i.Omega(v, u)
- dw_stokes.i.Omega(v, p) = 0""",
'incompressibility' :
"""dw_stokes.i.Omega(u, q) = 0""",
}
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 15,
'eps_a' : 1e-10,
'eps_r' : 1.0,
}),
}
navier_stokes/navier_stokes2d_iga.py
Description
Navier-Stokes equations for incompressible fluid flow in 2D solved in a single patch NURBS domain using the isoge-
ometric analysis (IGA) approach.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁ ∫︁
𝜈 ∇𝑣 : ∇𝑢 + ((𝑢 · ∇)𝑢) · 𝑣 − 𝑝∇·𝑣 =0, ∀𝑣 ,
Ω Ω Ω
∫︁
𝑞∇·𝑢=0, ∀𝑞 .
Ω
$ ./resview.py block2d.vtk -2
source code
.. math::
\int_{\Omega} \nu\ \nabla \ul{v} : \nabla \ul{u}
+ \int_{\Omega} ((\ul{u} \cdot \nabla) \ul{u}) \cdot \ul{v}
- \int_{\Omega} p\ \nabla \cdot \ul{v}
= 0
\;, \quad \forall \ul{v} \;,
$ ./resview.py block2d.vtk -2
"""
from __future__ import absolute_import
from sfepy import data_dir
regions = {
'Omega' : 'all',
'Left' : ('vertices of set xi00', 'facet'),
'Right' : ('vertices of set xi01', 'facet'),
'Bottom' : ('vertices of set xi10', 'facet'),
'Top' : ('vertices of set xi11', 'facet'),
'Walls' : ('r.Left +v r.Right +v r.Bottom', 'facet'),
}
materials = {
'fluid' : ({'viscosity' : 1.00e-2},),
}
fields = {
'velocity': ('real', 'vector', 'Omega', 'iga+1', 'H1', 'iga'),
'pressure': ('real', 'scalar', 'Omega', 'iga', 'H1', 'iga'),
}
variables = {
'u' : ('unknown field', 'velocity', 0),
'v' : ('test field', 'velocity', 'u'),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
}
ebcs = {
'1_Walls' : ('Walls', {'u.all' : 0.0}),
'0_Driven' : ('Top', {'u.0' : 1.0, 'u.1' : 0.0}),
'Pressure' : ('Bottom', {'p.0' : 0.0}),
}
integrals = {
'i' : 6,
}
equations = {
'balance' :
"""+ dw_div_grad.i.Omega(fluid.viscosity, v, u)
+ dw_convect.i.Omega(v, u)
- dw_stokes.i.Omega(v, p) = 0""",
'incompressibility' :
(continues on next page)
solvers = {
'ls' : ('ls.scipy_direct', {}),
'newton' : ('nls.newton', {
'i_max' : 15,
'eps_a' : 1e-10,
'eps_r' : 1.0,
}),
}
navier_stokes/stabilized_navier_stokes.py
Description
Stabilized Navier-Stokes problem with grad-div, SUPG and PSPG stabilization solved by a custom Oseen solver.
The stabilization terms are described in [1].
[1] G. Matthies and G. Lube. On streamline-diffusion methods of inf-sup stable discretisations of the generalised Oseen
problem. Number 2007-02 in Preprint Series of Institut fuer Numerische und Angewandte Mathematik, Georg-August-
Universitaet Goettingen, 2007.
Find 𝑢, 𝑝 such that:
∫︀ ∫︀ ∫︀
Ω
𝜈∫︀ ∇𝑣 : ∇𝑢 Ω ((𝑏 · ∇)𝑢) · 𝑣 − Ω 𝑝 ∇ · 𝑣
+𝛾∑︀Ω (∇ · ∫︀𝑢) · (∇ · 𝑣)
+ 𝐾∈ℐℎ ∫︀𝑇𝐾 𝛿𝐾 ((𝑏 · ∇)𝑢) · ((𝑏 · ∇)𝑣)
∑︀
+ 𝐾∈ℐℎ 𝑇𝐾 𝛿𝐾 ∇𝑝 · ((𝑏 · ∇)𝑣) = 0 , ∀𝑣 ,
∫︀
𝑞 ∇ · 𝑢 ∫︀
Ω∑︀
+ 𝐾∈ℐℎ ∫︀𝑇𝐾 𝜏𝐾 ((𝑏 · ∇)𝑢) · ∇𝑞
∑︀
+ 𝐾∈ℐℎ 𝑇𝐾 𝜏𝐾 ∇𝑝 · ∇𝑞 = 0 , ∀𝑞 .
source code
r"""
Stabilized Navier-Stokes problem with grad-div, SUPG and PSPG stabilization
solved by a custom Oseen solver.
.. math::
\begin{array}{l}
\int_{\Omega} \nu\ \nabla \ul{v} : \nabla \ul{u}
\int_{\Omega} ((\ul{b} \cdot \nabla) \ul{u}) \cdot \ul{v}
- \int_{\Omega} p\ \nabla \cdot \ul{v} \\
+ \gamma \int_{\Omega} (\nabla\cdot\ul{u}) \cdot (\nabla\cdot\ul{v}) \\
+ \sum_{K \in \Ical_h}\int_{T_K} \delta_K\ ((\ul{b} \cdot \nabla)
\ul{u})\cdot ((\ul{b} \cdot \nabla) \ul{v}) \\
(continues on next page)
\begin{array}{l}
\int_{\Omega} q\ \nabla \cdot \ul{u} \\
+ \sum_{K \in \Ical_h}\int_{T_K} \tau_K\ ((\ul{b} \cdot \nabla) \ul{u})
\cdot \nabla q \\
+ \sum_{K \in \Ical_h}\int_{T_K} \tau_K\ \nabla p \cdot \nabla q
= 0
\;, \quad \forall q \;.
\end{array}
"""
from __future__ import absolute_import
from sfepy.solvers.oseen import StabilizationFunction
from sfepy import data_dir
options = {
'solution' : 'steady',
'nls' : 'oseen',
'ls' : 'ls',
}
regions = {
'Omega' : 'all',
'Walls' : ('vertices of surface -v (r.Outlet +v r.Inlet)', 'facet'),
'Inlet' : ('vertices by cinc0', 'facet'),
'Outlet' : ('vertices by cinc1', 'facet'),
}
fields = {
'velocity' : ('real', 3, 'Omega', 1),
'pressure' : ('real', 1, 'Omega', 1),
}
variables = {
'u' : ('unknown field', 'velocity', 0),
'v' : ('test field', 'velocity', 'u'),
'b' : ('parameter field', 'velocity', 'u'),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
}
ebcs = {
'Walls_velocity' : ('Walls', {'u.all' : 0.0}),
'Inlet_velocity' : ('Inlet', {'u.1' : 1.0, 'u.[0,2]' : 0.0}),
}
integrals = {
'i1' : 2,
'i2' : 3,
}
##
# Stationary Navier-Stokes equations with grad-div, SUPG and PSPG stabilization.
equations = {
'balance' :
""" dw_div_grad.i2.Omega( fluid.viscosity, v, u )
+ dw_lin_convect.i2.Omega( v, b, u )
- dw_stokes.i1.Omega( v, p )
+ dw_st_grad_div.i1.Omega( stabil.gamma, v, u )
+ dw_st_supg_c.i1.Omega( stabil.delta, v, b, u )
+ dw_st_supg_p.i1.Omega( stabil.delta, v, b, p )
= 0""",
'incompressibility' :
""" dw_stokes.i1.Omega( u, q )
+ dw_st_pspg_c.i1.Omega( stabil.tau, q, b, u )
+ dw_st_pspg_p.i1.Omega( stabil.tau, q, p )
= 0""",
}
solver_1 = {
'name' : 'oseen',
'kind' : 'nls.oseen',
'stabil_mat' : 'stabil',
'adimensionalize' : False,
'check_navier_stokes_residual' : False,
'i_max' : 10,
'eps_a' : 1e-8,
'eps_r' : 1.0,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
solver_2 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
(continues on next page)
##
# Functions.
import os.path as op
import sys
name_map = {'p' : 'p', 'q' : 'q', 'u' : 'u', 'b' : 'b', 'v' : 'v',
'fluid' : 'fluid', 'omega' : 'omega', 'i1' : 'i1', 'i2' : 'i2',
'viscosity' : 'viscosity', 'velocity' : 'velocity',
'gamma' : 'gamma', 'delta' : 'delta', 'tau' : 'tau'}
functions = {
'cinc0' : (lambda coors, domain=None: cinc(coors, 0),),
'cinc1' : (lambda coors, domain=None: cinc(coors, 1),),
'stabil' : (StabilizationFunction(name_map),),
}
navier_stokes/stokes.py
Description
Stokes equations for incompressible fluid flow.
This example demonstrates fields defined on subdomains as well as use of periodic boundary conditions.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁
𝜈 ∇𝑣 : ∇𝑢 − 𝑝∇·𝑣 =0, ∀𝑣 ,
𝑌1 ∪𝑌2 𝑌1 ∪𝑌2
∫︁
𝑞∇·𝑢=0, ∀𝑞 .
𝑌1 ∪𝑌2
source code
r"""
Stokes equations for incompressible fluid flow.
.. math::
\int_{Y_1 \cup Y_2} \nu\ \nabla \ul{v} : \nabla \ul{u}
- \int_{Y_1 \cup Y_2} p\ \nabla \cdot \ul{v}
= 0
\;, \quad \forall \ul{v} \;,
if filename_mesh.find( 'symm' ):
region_1 = {
'name' : 'Y1',
'select' : """cells of group 3""",
}
region_2 = {
'name' : 'Y2',
'select' : """cells of group 4 +c cells of group 6
+c cells of group 8""",
}
region_4 = {
'name' : 'Y1Y2',
'select' : """r.Y1 +c r.Y2""",
}
region_5 = {
'name' : 'Walls',
'select' : """r.EBCGamma1 +v r.EBCGamma2""",
'kind' : 'facet',
}
region_310 = {
'name' : 'EBCGamma1',
'select' : """(cells of group 1 *v cells of group 3)
+v
(cells of group 2 *v cells of group 3)
""",
'kind' : 'facet',
}
region_320 = {
'name' : 'EBCGamma2',
'select' : """(cells of group 5 *v cells of group 4)
+v
(cells of group 1 *v cells of group 4)
+v
(cells of group 7 *v cells of group 6)
+v
(cells of group 2 *v cells of group 6)
+v
(cells of group 9 *v cells of group 8)
+v
(cells of group 2 *v cells of group 8)
""",
'kind' : 'facet',
}
w2 = 0.499
# Sides.
region_20 = {
'name' : 'Left',
(continues on next page)
field_1 = {
'name' : '2_velocity',
'dtype' : 'real',
'shape' : (2,),
'region' : 'Y1Y2',
'approx_order' : 2,
}
field_2 = {
'name' : 'pressure',
'dtype' : 'real',
'shape' : (1,),
'region' : 'Y1Y2',
'approx_order' : 1,
}
variable_1 = {
'name' : 'u',
'kind' : 'unknown field',
'field' : '2_velocity',
'order' : 0,
}
variable_2 = {
'name' : 'v',
'kind' : 'test field',
'field' : '2_velocity',
'dual' : 'u',
}
variable_3 = {
'name' : 'p',
'kind' : 'unknown field',
'field' : 'pressure',
'order' : 1,
(continues on next page)
integral_1 = {
'name' : 'i',
'order' : 2,
}
equations = {
'balance' :
"""dw_div_grad.i.Y1Y2( fluid.viscosity, v, u )
- dw_stokes.i.Y1Y2( v, p ) = 0""",
'incompressibility' :
"""dw_stokes.i.Y1Y2( u, q ) = 0""",
}
material_1 = {
'name' : 'fluid',
'values' : {
'viscosity' : 1.0,
'density' : 1e0,
},
}
ebc_1 = {
'name' : 'walls',
'region' : 'Walls',
'dofs' : {'u.all' : 0.0},
}
ebc_2 = {
'name' : 'top_velocity',
'region' : 'Top',
'dofs' : {'u.1' : -1.0, 'u.0' : 0.0},
}
ebc_10 = {
'name' : 'bottom_pressure',
'region' : 'Bottom',
'dofs' : {'p.0' : 0.0},
}
epbc_1 = {
'name' : 'u_rl',
'region' : ['Left', 'Right'],
'dofs' : {'u.all' : 'u.all', 'p.0' : 'p.0'},
'match' : 'match_y_line',
}
solver_0 = {
'name' : 'ls',
'kind' : 'ls.scipy_direct',
}
solver_1 = {
'name' : 'newton',
'kind' : 'nls.newton',
'i_max' : 2,
'eps_a' : 1e-8,
'eps_r' : 1e-2,
'macheps' : 1e-16,
'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
'ls_red' : 0.1,
'ls_red_warp' : 0.001,
'ls_on' : 1.1,
'ls_min' : 1e-5,
'check' : 0,
'delta' : 1e-6,
}
navier_stokes/stokes_slip_bc.py
Description
Incompressible Stokes flow with Navier (slip) boundary conditions, flow driven by a moving wall and a small diffusion
for stabilization.
This example demonstrates the use of no-penetration and edge direction boundary conditions together with Navier or
slip boundary conditions. Alternatively the no-penetration boundary conditions can be applied in a weak sense using
the penalty term dw_non_penetration_p.
Find 𝑢, 𝑝 such that:
∫︁ ∫︁ ∫︁ ∫︁
𝜈 ∇𝑣 : ∇𝑢 − 𝑝∇·𝑣+ 𝛽𝑣 · (𝑢 − 𝑢𝑑 ) + 𝛽𝑣 · 𝑢 = 0 , ∀𝑣 ,
Ω Ω Γ1 Γ
∫︁ ∫︁ 2
𝜇∇𝑞 · ∇𝑝 + 𝑞∇·𝑢=0, ∀𝑞 ,
Ω Ω
where 𝜈 is the fluid viscosity, 𝛽 is the slip coefficient, 𝜇 is the (small) numerical diffusion coefficient, Γ1 is the top wall
that moves with the given driving velocity 𝑢𝑑 and Γ2 are the remaining walls. The Navier conditions are in effect on
both Γ1 , Γ2 and are expressed by the corresponding integrals in the equations above.
The no-penetration boundary conditions are applied on Γ1 , Γ2 , except the vertices of the block edges, where the edge
direction boundary conditions are applied.
The penalty term formulation is given by the following equations.
where 𝜖 is the penalty coefficient (sufficiently large). The no-penetration boundary conditions are applied on Γ1 , Γ2 .
Optionally, Dirichlet boundary conditions can be applied on the inlet in the both cases, see below.
For large meshes use the 'ls_i' linear solver - PETSc + petsc4py are needed in that case.
Several parameters can be set using the --define option of simple.py, see define() and the examples below.
Examples
Use the penalty term formulation and einsum-based terms with the default (numpy) backend:
Change backend to opt_einsum (needs to be installed) and use the quadratic velocity approximation order:
Note the pressure field distribution improvement w.r.t. the previous examples. IfPETSc + petsc4py are installed, try
using the iterative solver to speed up the solution:
source code
r"""
Incompressible Stokes flow with Navier (slip) boundary conditions, flow driven
by a moving wall and a small diffusion for stabilization.
.. math::
\int_{\Omega} \nu\ \nabla \ul{v} : \nabla \ul{u}
- \int_{\Omega} p\ \nabla \cdot \ul{v}
+ \int_{\Gamma_1} \beta \ul{v} \cdot (\ul{u} - \ul{u}_d)
+ \int_{\Gamma_2} \beta \ul{v} \cdot \ul{u}
+ \int_{\Gamma_1 \cup \Gamma_2} \epsilon (\ul{n} \cdot \ul{v})
(\ul{n} \cdot \ul{u})
= 0
\;, \quad \forall \ul{v} \;,
For large meshes use the ``'ls_i'`` linear solver - PETSc + petsc4py are needed
in that case.
(continues on next page)
Examples
--------
Use the penalty term formulation and einsum-based terms with the default
(numpy) backend::
Change backend to opt_einsum (needs to be installed) and use the quadratic velocity␣
˓→approximation order::
Note the pressure field distribution improvement w.r.t. the previous examples. IfPETSc +␣
˓→petsc4py are installed, try using the iterative solver to speed up the solution::
filename_mesh = UserMeshIO(mesh_hook)
fields = {
'velocity' : ('real', 3, 'Omega', u_order),
'pressure' : ('real', 1, 'Omega', 1),
}
return out
functions = {
'get_u_d' : (get_u_d,),
}
variables = {
'u' : ('unknown field', 'velocity', 0),
'v' : ('test field', 'velocity', 'u'),
'u_d' : ('parameter field', 'velocity',
{'setter' : 'get_u_d'}),
'p' : ('unknown field', 'pressure', 1),
'q' : ('test field', 'pressure', 'p'),
}
materials = {
'm' : ({
'nu' : 1e-3,
'beta' : 1e-2,
'mu' : 1e-10,
},),
}
if mode == 'lcbc':
lcbcs = {
'walls' : ('Gamma_v', {'u.all' : None}, None, 'no_penetration',
indir('normals_Gamma.vtk') if save_lcbc_vecs else None),
'edges' : ('Edges_v', [(-0.5, 1.5)], {'u.all' : None}, None,
'edge_direction',
indir('edges_Edges.vtk') if save_lcbc_vecs else None),
}
if term_mode == 'original':
equations = {
'balance' :
"""dw_div_grad.5.Omega(m.nu, v, u)
- dw_stokes.5.Omega(v, p)
+ dw_dot.5.Gamma1_f(m.beta, v, u)
+ dw_dot.5.Gamma2_f(m.beta, v, u)
=
+ dw_dot.5.Gamma1_f(m.beta, v, u_d)""",
'incompressibility' :
"""dw_laplace.5.Omega(m.mu, q, p)
+ dw_stokes.5.Omega(u, q) = 0""",
}
else:
equations = {
'balance' :
"""de_div_grad.5.Omega(m.nu, v, u)
- de_stokes.5.Omega(v, p)
+ de_dot.5.Gamma1_f(m.beta, v, u)
+ de_dot.5.Gamma2_f(m.beta, v, u)
=
+ de_dot.5.Gamma1_f(m.beta, v, u_d)""",
'incompressibility' :
"""de_laplace.5.Omega(m.mu, q, p)
+ de_stokes.5.Omega(u, q) = 0""",
}
else:
materials['m'][0]['np_eps'] = 1e3
if term_mode == 'original':
equations = {
'balance' :
"""dw_div_grad.5.Omega(m.nu, v, u)
- dw_stokes.5.Omega(v, p)
(continues on next page)
else:
equations = {
'balance' :
"""de_div_grad.5.Omega(m.nu, v, u)
- de_stokes.5.Omega(v, p)
+ de_dot.5.Gamma1_f(m.beta, v, u)
+ de_dot.5.Gamma2_f(m.beta, v, u)
+ de_non_penetration_p.5.Gamma1_f(m.np_eps, v, u)
+ de_non_penetration_p.5.Gamma2_f(m.np_eps, v, u)
=
+ de_dot.5.Gamma1_f(m.beta, v, u_d)""",
'incompressibility' :
"""de_laplace.5.Omega(m.mu, q, p)
+ de_stokes.5.Omega(u, q) = 0""",
}
solvers = {
'ls_d' : ('ls.auto_direct', {}),
'ls_i' : ('ls.petsc', {
'method' : 'bcgsl', # ksp_type
'precond' : 'bjacobi', # pc_type
'sub_precond' : 'ilu', # sub_pc_type
'eps_a' : 0.0, # abstol
'eps_r' : 1e-12, # rtol
'eps_d' : 1e10, # Divergence tolerance.
'i_max' : 200, # maxits
}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-10,
}),
}
options = {
'nls' : 'newton',
'ls' : ls,
'eterm': {
'verbosity' : verbosity,
'backend_args' : {
'backend' : backend,
'optimize' : optimize,
(continues on next page)
return locals()
navier_stokes/utils.py
Description
missing description!
source code
##
# Functions.
from __future__ import absolute_import
import numpy as nm
phononic
phononic/band_gaps.py
Description
Acoustic band gaps in a strongly heterogeneous elastic body, detected using homogenization techniques.
A reference periodic cell contains two domains: the stiff matrix 𝑌𝑚 and the soft (but heavy) inclusion 𝑌𝑐 .
source code
"""
Acoustic band gaps in a strongly heterogeneous elastic body, detected using
homogenization techniques.
A reference periodic cell contains two domains: the stiff matrix :math:`Y_m`
and the soft (but heavy) inclusion :math:`Y_c`.
"""
from __future__ import absolute_import
from sfepy import data_dir
from sfepy.base.base import Struct
from sfepy.base.ioutils import InDir
from sfepy.homogenization.coefficients import Coefficients
incwd = InDir(__file__)
output_dir = incwd('output/band_gaps')
# aluminium, SI units
D_m = get_pars(2, 5.898e10, 2.681e10)
density_m = 2799.0
# epoxy, SI units
D_c = get_pars(2, 1.798e9, 1.48e9)
density_c = 1142.0
options = {
'plot_transform_angle' : None,
'plot_transform_wave' : ('clip_sqrt', (0, 7000)),
'plot_transform' : ('clip', (-7000, 7000)),
'fig_name' : 'band_gaps',
'fig_name_angle' : 'band_gaps_angle',
'fig_name_wave' : 'band_gaps_wave',
'fig_suffix' : '.pdf',
'coefs_filename' : 'coefs.txt',
'plot_options' : {
'show' : True,
'legend' : True,
},
'plot_labels' : {
'band_gaps' : {
'resonance' : r'$\lambda^r$',
'masked' : r'masked $\lambda^r$',
'eig_min' : r'min eig($M$)',
'eig_max' : r'max eig($M$)',
'x_axis' : r'$\sqrt{\lambda}$, $\omega$',
'y_axis' : r'eigenvalues of mass matrix $M$',
},
},
'plot_rsc' : {
'params' : {'axes.labelsize': 'x-large',
'font.size': 14,
'legend.fontsize': 'large',
'legend.loc': 'upper right',
'xtick.labelsize': 'large',
'ytick.labelsize': 'large',
'text.usetex': True},
},
'multiprocessing' : False,
'float_format' : '%.16e',
}
evp_options = {
'eigensolver' : 'eig.sgscipy',
'save_eig_vectors' : (12, 0),
'scale_epsilon' : 1.0,
'elasticity_contrast' : 1.0,
}
eigenmomenta_options = {
(continues on next page)
band_gaps_options = {
'eig_range' : (0, 30), # -> freq_range
# = sqrt(eigs[slice(*eig_range)][[0, -1]])
# 'fixed_freq_range' : (0.1, 3e7),
'freq_margins' : (10, 10), # % of freq_range
'freq_eps' : 1e-7, # frequency
'zero_eps' : 1e-12, # zero finding
'freq_step' : 0.0001, # % of freq_range
'log_save_name' : 'band_gaps.log',
'raw_log_save_name' : 'raw_eigensolution.npz',
}
phononic/band_gaps_conf.py
Description
Configuration classes for acoustic band gaps in a strongly heterogeneous elastic body.
source code
"""
Configuration classes for acoustic band gaps in a strongly heterogeneous
elastic body.
"""
from __future__ import absolute_import
import numpy as nm
per.set_accuracy(1e-8)
return c
variables[mode2var[mode]].set_data(val)
class BandGapsConf(Struct):
"""
Configuration class for acoustic band gaps in a strongly heterogeneous
elastic body.
"""
self.conf = Struct()
self.conf.filename_mesh = self.incwd(filename)
io = MeshIO.any_from_filename(self.conf.filename_mesh)
self.bbox, self.dim = io.read_bounding_box(ret_dim=True)
rpc_axes = nm.eye(self.dim, dtype=nm.float64) \
* (self.bbox[1] - self.bbox[0])
(continues on next page)
self.conf.options = options
self.conf.options.update({
'output_dir' : output_dir,
'volume' : {
'value' : get_lattice_volume(rpc_axes),
},
'coefs' : 'coefs',
'requirements' : 'requirements',
'coefs_filename' : coefs_save_name,
})
self.conf.mat_pars = mat_pars
self.conf.solvers = self.define_solvers()
self.conf.regions = self.define_regions()
self.conf.materials = self.define_materials()
self.conf.fields = self.define_fields()
self.conf.variables = self.define_variables()
(self.conf.ebcs, self.conf.epbcs,
self.conf.lcbcs, self.all_periodic) = self.define_bcs()
self.conf.functions = self.define_functions()
self.conf.integrals = self.define_integrals()
def __call__(self):
return ProblemConf.from_dict(self.conf.__dict__,
import_file(__file__))
def define_solvers(self):
solvers = {
'ls_d' : ('ls.scipy_direct', {}),
'ls_i' : ('ls.scipy_iterative', {
'method' : 'cg',
'i_max' : 1000,
'eps_a' : 1e-12,
}),
'newton' : ('nls.newton', {
'i_max' : 1,
'eps_a' : 1e-4,
}),
}
return solvers
def define_regions(self):
(continues on next page)
regions.update(define_box_regions(self.dim,
self.bbox[0], self.bbox[1], 1e-5))
return regions
def define_materials(self):
materials = {
'm' : ({
'D_m' : self.mat_pars.D_m,
'density_m' : self.mat_pars.density_m,
'D_c' : self.mat_pars.D_c,
'density_c' : self.mat_pars.density_c,
}, None, None, {'special_constant' : True}),
}
return materials
def define_fields(self):
fields = {
'vector_Y_m' : ('real', self.dim, 'Y_m', self.approx),
'vector_Y_c' : ('real', self.dim, 'Y_c', self.approx),
def define_variables(self):
variables = {
'u_m' : ('unknown field', 'vector_Y_m'),
'v_m' : ('test field', 'vector_Y_m', 'u_m'),
'Pi' : ('parameter field', 'vector_Y_m', '(set-to-None)'),
'u1_m' : ('parameter field', 'vector_Y_m', '(set-to-None)'),
'u2_m' : ('parameter field', 'vector_Y_m', '(set-to-None)'),
def define_bcs(self):
ebcs = {
'fixed_corners' : ('Corners', {'u_m.all' : 0.0}),
'fixed_gamma_mc' : ('Gamma_mc', {'u_c.all' : 0.0}),
}
(continues on next page)
epbcs = {}
all_periodic = []
for vn in ['u_m']:
val = {'%s.all' % vn : '%s.all' % vn}
epbcs.update({
'periodic_%s_x' % vn : (['Left', 'Right'], val,
'match_y_line'),
'periodic_%s_y' % vn : (['Top', 'Bottom'], val,
'match_x_line'),
})
all_periodic.extend(['periodic_%s_x' % vn, 'periodic_%s_y' % vn])
lcbcs = {}
def define_functions(self):
functions = {
'match_x_line' : (per.match_x_line,),
'match_y_line' : (per.match_y_line,),
}
return functions
def define_integrals(self):
integrals = {
'i' : 2,
}
return integrals
def define_equations(self):
equations = {}
equations['corrs_rs'] = {
'balance_of_forces' :
"""dw_lin_elastic.i.Y_m( m.D_m, v_m, u_m )
= - dw_lin_elastic.i.Y_m( m.D_m, v_m, Pi )""",
}
equations['evp'] = {
'lhs' : """dw_lin_elastic.i.Y_c( m.D_c, v_c, u_c )""",
'rhs' : """dw_dot.i.Y_c( m.density_c, v_c, u_c )""",
}
expr_coefs = {
'D' : """dw_lin_elastic.i.Y_m( m.D_m, u1_m, u2_m )""",
'VF' : """ev_volume.i.%s(aux)""",
'ema' : """ev_integrate.i.Y_c( m.density_c, u_c )""",
}
def define_coefs(self):
from copy import copy
ema_options = copy(self.eigenmomenta_options)
ema_options.update({'var_name' : 'u_c'})
coefs = {
# Basic.
'VF' : {
'regions' : ['Y_m', 'Y_c'],
'expression' : self.expr_coefs['VF'],
'class' : cb.VolumeFractions,
},
'dv_info' : {
'requires' : ['c.VF'],
'region_to_material' : {'Y_m' : ('m', 'density_m'),
'Y_c' : ('m', 'density_c'),},
'class' : cp.DensityVolumeInfo,
},
'eigenmomenta' : {
'requires' : ['evp', 'c.dv_info'],
'expression' : self.expr_coefs['ema'],
'options' : ema_options,
'class' : cp.Eigenmomenta,
},
'M' : {
'requires' : ['evp', 'c.dv_info', 'c.eigenmomenta'],
'class' : cp.AcousticMassTensor,
},
'band_gaps' : {
'requires' : ['evp', 'c.eigenmomenta', 'c.M'],
'options' : self.band_gaps_options,
'class' : cp.BandGaps,
},
# Dispersion.
'D' : {
'requires' : ['pis', 'corrs_rs'],
'expression' : self.expr_coefs['D'],
'set_variables' : set_coef_d,
'class' : cb.CoefSymSym,
},
'Gamma' : {
'requires' : ['c.D'],
'options' : {
'mode' : 'simple',
'incident_wave_dir' : None,
},
'class' : cp.ChristoffelAcousticTensor,
},
(continues on next page)
# Phase velocity.
'phase_velocity' : {
'requires' : ['c.dv_info', 'c.Gamma'],
'options' : {
'eigensolver' : 'eig.sgscipy',
},
'class' : cp.PhaseVelocity,
},
'filenames' : {},
}
return coefs
def define_requirements(self):
requirements = {
# Basic.
'evp' : {
'ebcs' : ['fixed_gamma_mc'],
'epbcs' : None,
'equations' : self.equations['evp'],
'save_name' : self.corrs_save_names['evp'],
'options' : self.evp_options,
'class' : cp.SimpleEVP,
},
# Dispersion.
'pis' : {
'variables' : ['u_m'],
'class' : cb.ShapeDimDim,
},
'corrs_rs' : {
'requires' : ['pis'],
'ebcs' : ['fixed_corners'],
'epbcs' : self.all_periodic,
'equations' : self.equations['corrs_rs'],
'set_variables' : [('Pi', 'pis', 'u_m')],
'save_name' : self.corrs_save_names['corrs_rs'],
'is_linear' : True,
'class' : cb.CorrDimDim,
(continues on next page)
class BandGapsRigidConf(BandGapsConf):
"""
Configuration class for acoustic band gaps in a strongly heterogeneous
elastic body with rigid inclusions.
"""
def define_regions(self):
regions = BandGapsConf.define_regions(self)
regions['Y_cr'] = regions['Y_c']
regions.update({
'Y_r' : 'vertices by select_yr',
'Y_c' : 'r.Y_cr -c r.Y_r',
})
return regions
def define_materials(self):
materials = BandGapsConf.define_materials(self)
materials['m'][0].update({
'D_r' : self.mat_pars.D_r,
'density_r' : self.mat_pars.density_r,
})
return materials
def define_fields(self):
fields = {
'vector_Y_cr' : ('real', self.dim, 'Y_cr', self.approx),
def define_variables(self):
variables = {
'u' : ('unknown field', 'vector_Y_cr'),
'v' : ('test field', 'vector_Y_cr', 'u'),
def define_bcs(self):
ebcs = {
'fixed_gamma_mc' : ('Gamma_mc', {'u.all' : 0.0}),
}
lcbcs ={
'rigid' : ('Y_r',{'u.all' : None}, None, 'rigid'),
}
def define_functions(self):
functions = BandGapsConf.define_functions(self)
functions.update({
'select_yr' : (self.select_yr,),
})
return functions
def define_equations(self):
equations = {}
expr_coefs = {
'VF' : """ev_volume.i.%s(aux)""",
'ema' : """ev_integrate.i.Y_c( m.density_c, u )
+ ev_integrate.i.Y_r( m.density_r, u )""",
}
def define_coefs(self):
from copy import copy
ema_options = copy(self.eigenmomenta_options)
ema_options.update({'var_name' : 'u'})
coefs = {
# Basic.
'VF' : {
'regions' : ['Y_m', 'Y_cr', 'Y_c', 'Y_r'],
'expression' : self.expr_coefs['VF'],
'class' : cb.VolumeFractions,
},
'dv_info' : {
'requires' : ['c.VF'],
'region_to_material' : {'Y_m' : ('m', 'density_m'),
'Y_c' : ('m', 'density_c'),
'Y_r' : ('m', 'density_r'),},
'class' : cp.DensityVolumeInfo,
},
'eigenmomenta' : {
'requires' : ['evp', 'c.dv_info'],
(continues on next page)
'filenames' : {},
}
return coefs
def define_requirements(self):
requirements = {
# Basic.
'evp' : {
'ebcs' : ['fixed_gamma_mc'],
'epbcs' : None,
'lcbcs' : ['rigid'],
'equations' : self.equations['evp'],
'save_name' : self.corrs_save_names['evp'],
'options' : self.evp_options,
'class' : cp.SimpleEVP,
},
}
return requirements
phononic/band_gaps_rigid.py
Description
Acoustic band gaps in a strongly heterogeneous elastic body with a rigid inclusion, detected using homogenization
techniques.
A reference periodic cell contains three domains: the stiff matrix 𝑌𝑚 and the soft inclusion 𝑌𝑐 enclosing the rigid heavy
sub-inclusion 𝑌𝑟 .
source code
"""
Acoustic band gaps in a strongly heterogeneous elastic body with a rigid
inclusion, detected using homogenization techniques.
A reference periodic cell contains three domains: the stiff matrix :math:`Y_m`
and the soft inclusion :math:`Y_c` enclosing the rigid heavy sub-inclusion
:math:`Y_r`.
"""
from __future__ import absolute_import
import numpy as nm
incwd = InDir(__file__)
dim = 2
if dim == 3:
filename = data_dir + '/meshes/3d/special/cube_sphere.mesh'
else:
filename = data_dir + '/meshes/2d/special/circle_in_square.mesh'
output_dir = incwd('output/band_gaps_rigid')
# aluminium, SI units
D_m = get_pars(2, 5.898e10, 2.681e10)
density_m = 2799.0
(continues on next page)
# epoxy, SI units
D_c = get_pars(2, 1.798e9, 1.48e9)
density_c = 1142.0
evp_options = {
'eigensolver' : 'eig.sgscipy',
'save_eig_vectors' : (12, 0),
'scale_epsilon' : 1.0,
'elasticity_contrast' : 1.0,
}
eigenmomenta_options = {
# eigenmomentum threshold,
'threshold' : 1e-1,
# eigenmomentum threshold is relative w.r.t. largest one,
'threshold_is_relative' : True,
}
band_gaps_options = {
'fixed_freq_range' : (0., 35000.), # overrides eig_range!
'log_save_name' : 'band_gaps.log',
'raw_log_save_name' : 'raw_eigensolution.npz',
}
options = {
'post_process_hook' : 'post_process',
'fig_name' : 'band_gaps',
'fig_suffix' : '.pdf',
'coefs_filename' : 'coefs.txt',
(continues on next page)
'plot_options' : {
'show' : True, # Show figure.
'legend' : True, # Show legend.
},
'float_format' : '%.16e',
}
if out.shape[0] <= 3:
raise ValueError('too few nodes selected! (%d)' % out.shape[0])
return out
strain = problem.evaluate('ev_cauchy_strain.i.Y_c(u)',
verbose=False, mode='el_avg')
strain = extend_cell_data(strain, problem.domain, 'Y_c')
out['strain%03d' % ii] = Struct(name='output_data',
mode='cell', data=strain,
dofs=None)
return out
quantum
quantum/boron.py
Description
Boron atom with 1 electron.
See quantum/quantum_common.py.
source code
"""
Boron atom with 1 electron.
See :ref:`quantum-quantum_common`.
"""
from __future__ import absolute_import
from sfepy.linalg import norm_l2_along_axis
elif dim == 3:
eigs = [-float(Z)**2/2/n**2 for n in [1] + [2]*2**2 + [3]*3**2]
return eigs
out = {}
C = 0.5
r = norm_l2_along_axis(coor, axis=1)
V = - C * 5.0 / r
V.shape = (V.shape[0], 1, 1)
out['V'] = V
return out
quantum/hydrogen.py
Description
Hydrogen atom.
See quantum/quantum_common.py.
source code
"""
Hydrogen atom.
See :ref:`quantum-quantum_common`.
"""
from __future__ import absolute_import
from sfepy.linalg import norm_l2_along_axis
elif dim == 3:
eigs = [-float(Z)**2/2/n**2 for n in [1] + [2]*2**2 + [3]*3**2]
return eigs
out = {}
C = 0.5
r = norm_l2_along_axis(coor, axis=1)
V = - C * 1.0 / r
V.shape = (V.shape[0], 1, 1)
out['V'] = V
return out
quantum/oscillator.py
Description
Quantum oscillator.
See quantum/quantum_common.py.
source code
"""
Quantum oscillator.
See :ref:`quantum-quantum_common`.
"""
from __future__ import absolute_import
from sfepy.linalg import norm_l2_along_axis
elif dim == 3:
eigs = [float(1)/2 + x for x in [1] + [2]*3 + [3]*6 + [4]*10]
return eigs
out = {}
C = 0.5
val = C * norm_l2_along_axis(coor, axis=1, squared=True)
val.shape = (val.shape[0], 1, 1)
out['V'] = val
return out
quantum/quantum_common.py
Description
Common code for basic electronic structure examples.
It covers only simple single electron problems, e.g. well, oscillator, hydrogen atom and boron atom with 1 electron -
see the corresponding files in this directory, where potentials (fun_v()) as well as exact solutions (get_exact()) for
those problems are defined.
Notes
The same code should work also with a 3D (box) mesh, but a very fine mesh would be required. Also in the 2D case,
finer mesh and/or higher approximation order means higher accuracy.
Try changing C, F and L parameters in meshes/quantum/square.geo and regenerate the mesh using gmsh:
The script/convert_mesh.py call makes the mesh planar, as gmsh saves 2D medit meshes including the zero z
coordinates.
Also try changing approximation order (‘approx_order’) of the field below.
Usage Examples
The following examples are available and can be run using the simple.py script:
source code
"""
Common code for basic electronic structure examples.
It covers only simple single electron problems, e.g. well, oscillator, hydrogen
atom and boron atom with 1 electron - see the corresponding files in this
directory, where potentials (:func:`fun_v()`) as well as exact solutions
(:func:`get_exact()`) for those problems are defined.
Notes
-----
The same code should work also with a 3D (box) mesh, but a very fine mesh would
be required. Also in the 2D case, finer mesh and/or higher approximation order
means higher accuracy.
Usage Examples
--------------
The following examples are available and can be run using the `simple.py`
script::
bounding_box = pb.domain.mesh.get_bounding_box()
box_size = bounding_box[1][0] - bounding_box[0][0]
output('box_size: %f ' % box_size)
output('eigenvalues:')
else:
output('n FEM')
for ie, eig in enumerate(evp.eigs):
output('%d: %.8f ' % (ie, eig))
options = {
'n_eigs' : n_eigs,
'eigs_only' : False,
'post_process_hook_final' : 'report_eigs',
'evps' : 'eig',
}
regions = {
'Omega' : 'all',
'Surface' : ('vertices of surface', 'facet'),
}
materials = {
'm' : ({'val' : 0.5},),
'mat_v' : 'fun_v',
}
functions = {
'fun_v' : (fun_v,),
}
approx_order = 2
fields = {
'field_Psi' : ('real', 'scalar', 'Omega', approx_order),
}
variables = {
'Psi' : ('unknown field', 'field_Psi', 0),
'v' : ('test field', 'field_Psi', 'Psi'),
}
ebcs = {
'ZeroSurface' : ('Surface', {'Psi.0' : 0.0}),
(continues on next page)
integrals = {
'i' : 2 * approx_order,
}
equations = {
'lhs' : """dw_laplace.i.Omega(m.val, v, Psi)
+ dw_dot.i.Omega(mat_v.V, v, Psi)""",
'rhs' : """dw_dot.i.Omega(v, Psi)""",
}
solvers = {
'eig' : ('eig.scipy', {
'method' : 'eigsh',
'tol' : 1e-10,
'maxiter' : 150,
return locals()
quantum/well.py
Description
Quantum potential well.
See quantum/quantum_common.py.
source code
"""
Quantum potential well.
See :ref:`quantum-quantum_common`.
"""
from __future__ import absolute_import
if dim == 2:
eigs = [pi**2/(2*box_size**2)*x
for x in [2, 5, 5, 8, 10, 10, 13, 13, 17, 17, 18, 20, 20]]
elif dim == 3:
eigs = [pi**2/(2*box_size**2)*x
for x in [3, 6, 6, 6, 9, 9, 9, 11, 11, 11,
12, 14, 14, 14, 14, 14, 14, 17, 17, 17]]
out = {}
val = zeros_like(coor[:,0])
val.shape = (val.shape[0], 1, 1)
out['V'] = val
return out
1.6.1 Miscellaneous
export PYTHONPATH=.
or add the following code prior to sfepy imports into the module:
import sys
sys.path.append('.')
approx_order = 2
# The finite element approximation order.
fields = {
'displacement': ('real', 3, 'Omega', approx_order),
}
# The numerical quadrature order.
integrals = {
'i' : 2 * approx_order,
}
4. Higher order DOF visualization when using an approximation order greater than one.
By default, the additional, higher order DOFs, are not used in the VTK/HDF5 results files ('strip' lineariza-
tion kind). To see the influence of those DOFs, 'adaptive' linearization has to be used, see diffusion/sinbc.py
(declarative API) and diffusion/laplace_refine_interactive.py or multi_physics/biot_parallel_interactive.py (im-
perative API, search linearization).
5. Numbering of DOFs.
Locally (in a connectivity row), the DOFs are stored DOF-by-DOF (u_0 in all local nodes, u_1 in all local nodes,
. . . ).
Globally (in a state vector), the DOFs are stored node-by-node (u_0, u_1, ..., u_X in node 0, u_0, u_1,
..., u_X in node 1, . . . ).
See also create_adof_conn().
6. Visualization of various FEM-related information.
• Quadrature rules:
python3 script/plot_quadratures.py
• Facet orientations - run in the source code directory and make sure the current directory is in the Python’s
path list (see Miscellaneous):
python3 sfepy/postprocess/plot_facets.py
• Global and local numberings of mesh topological entities (cells, faces, edges, vertices):
The global numbers serve as indices into connectivities. In the plot, the global numbers are on the entities,
the cell-local ones are inside the cells next to each entity towards the cell centroids.
7. How to work with solvers/preconditioners?
See multi_physics/biot_short_syntax.py (user-defined preconditioners) or navier_stokes/stokes_slip_bc.py (petsc
solver setup).
8. How to get the linear system components: the matrix and the right-hand side?
To get the residual vector r (see Implementation of Essential Boundary Conditions) and the tangent matrix K,
the imperative API can be used as follows:
# pb is a Problem instance,
pb.set_bcs(ebcs=Conditions([...])) # Set Dirichlet boundary conditions.
pb.set_ics(Conditions([...])) # Set initial conditions (if any).
variables = pb.get_initial_state()
pb.time_update()
variables.apply_ebc()
r = pb.equations.eval_residuals(variables())
K = pb.equations.eval_tangent_matrices(variables(), pb.mtx_a)
problem.save_regions_as_groups('regions')
1.6.3 Regions
1. How to define a region using a function of coordinates in the interactive mode (imperative API)?
Examples:
• A facet region defined using a function of mesh vertex coordinates:
# ...
region = domain.create_region(
'Region', 'cells by get_region', 'cell',
functions=Functions([get_region]),
)
1. How to set material parameters per region in the interactive mode (imperative API)?
Example: define rho, D to have different values in regions omega1, omega2:
Thus it has access to term.region.cells, hence access to the cells that correspond to the coordinates. The
length of the coors is n_cell * n_qp, where n_qp is the number of quadrature points per cell, and n_cell =
len(term.region.cells), so that coors.reshape((n_cell, n_qp, -1)) can be used.
This part introduces parts the theoretical mathematical background necessary to use SfePy effectively. It also discusses
some implementation choices done in SfePy.
Contents:
The Finite Element Method (FEM) is the numerical method for solving Partial Differential Equations (PDEs). FEM
was developed in the middle of XX. century and now it is widely used in different areas of science and engineering,
including mechanical and structural design, biomedicine, electrical and power design, fluid dynamics and other. FEM
is based on a very elegant mathematical theory of weak solution of PDEs. In this section we will briefly discuss basic
ideas underlying FEM.
Let us start our discussion about FEM with the strong form of Poisson’s equation
∆𝑇 = 𝑓 (𝑥), 𝑥 ∈ Ω, (1.11)
𝑇 = 𝑢(𝑥), 𝑥 ∈ Γ𝐷 , (1.12)
∇𝑇 · n = 𝑔(𝑥), 𝑥 ∈ Γ𝑁 , (1.13)
where Ω ⊂ R𝑛 is the solution domain with the boundary 𝜕Ω, Γ𝐷 is the part of the boundary where Dirichlet boundary
conditions are given, Γ𝑁 is the part of the boundary where Neumann boundary conditions are given, 𝑇 (𝑥) is the
unknown function to be found, 𝑓 (𝑥), 𝑢(𝑥), 𝑔(𝑥) are known functions.
FEM is based on a weak formulation. The weak form of the equation (1.11) is
∫︁
(∆𝑇 − 𝑓 ) · 𝑠 dΩ = 0,
Ω
or
∫︁ ∫︁ ∫︁
∇𝑇 · ∇𝑠 dΩ = 𝑠 · (∇𝑇 · n) dΓ − 𝑓 · 𝑠 dΩ.
Ω Γ𝐷 ∪Γ𝑁 Ω
The surface integral term can be split into two integrals, one over the Dirichlet part of the surface and second over the
Neumann part
∫︁ ∫︁ ∫︁ ∫︁
∇𝑇 · ∇𝑠 dΩ = 𝑠 · (∇𝑇 · n) dΓ + 𝑠 · (∇𝑇 · n) dΓ − 𝑓 · 𝑠 dΩ. (1.14)
Ω Γ𝐷 Γ𝑁 Ω
The equation (1.14) is the initial weak form of the Poisson’s problem (1.11)–(1.13). But we can not work with it without
applying the boundary conditions. So it is time to talk about the boundary conditions.
On the Dirichlet part of the surface we have two restrictions. One is the Dirichlet boundary conditions 𝑇 (𝑥) = 𝑢(𝑥)
as they are, and the second is the integral term over Γ𝐷 in equation (1.14). To be consistent we have to use only the
Dirichlet conditions and avoid the integral term. To implement this we can take the function 𝑇 ∈ 𝑉 (Ω) and the test
function 𝑠 ∈ 𝑉0 (Ω), where
𝑇 (𝑥) = 𝑢(𝑥), 𝑥 ∈ Γ𝐷 .
That is why Dirichlet conditions in FEM terminology are called Essential Boundary Conditions. These conditions
are not a part of the weak form and they are used as they are.
The Neumann boundary conditions correspond to the known flux 𝑔(𝑥) = ∇𝑇 · n. The integral term over the Neumann
surface in the equation (1.14) contains exactly the same flux. So we can use the known function 𝑔(𝑥) in the integral
term:
∫︁ ∫︁ ∫︁
∇𝑇 · ∇𝑠 dΩ = 𝑔 · 𝑠 dΓ − 𝑓 · 𝑠 dΩ,
Ω Γ𝑁 Ω
Now we can write the resulting weak form for the Poisson’s problem (1.11)–(1.13). For any test function 𝑠 ∈ 𝑉0 (Ω)
find 𝑇 ∈ 𝑉 (Ω) such that
∫︁ ∫︁ ∫︁
∇𝑇 · ∇𝑠 dΩ = 𝑔 · 𝑠 dΓ − 𝑓 · 𝑠 dΩ, and
Ω Γ𝑁 Ω (1.15)
𝑇 (𝑥) = 𝑢(𝑥), 𝑥 ∈ Γ𝐷 .
It is planned to have an example of the discretization based on the Poisson’s equation weak form (1.15). For now, please
refer to the wikipedia page Finite Element Method for a basic description of the disretization and meshing.
To solve numerically given problem based on the weak form (1.15) we have to go through 5 steps:
1. Define geometry of the domain Ω and surfaces Γ𝐷 and Γ𝑁 .
2. Define the known functions 𝑓 , 𝑢 and 𝑔.
3. Define the unknown function 𝑇 and the test functions 𝑠.
4. Define essential boundary conditions (Dirichlet conditions) 𝑇 (𝑥) = 𝑢(𝑥), 𝑥 ∈ Γ𝐷 .
5. Define equation and natural boundary conditions (Neumann conditions) as the set of all integral terms ∇𝑇 ·
∫︀
∫︀ ∫︀ Ω
∇𝑠 dΩ, 𝑔 · 𝑠 dΓ, 𝑓 · 𝑠 dΩ.
Γ𝑁 Ω
The essential boundary conditions can be applied in several ways. Here we describe the implementation used in SfePy.
Motivation
Let us solve a linear system 𝐴𝑥 = 𝑏 with 𝑛 × 𝑛 matrix 𝐴 with 𝑛𝑓 values in the 𝑥 vector known. The known values can
be for example EBC values on a boundary, if 𝐴 comes from a PDE discretization. If we put the known fixed values into
a vector 𝑥𝑓 , that has the same size as 𝑥, and has zeros in positions that are not fixed, we can easily construct a 𝑛 × 𝑛𝑟
matrix 𝑇 that maps the reduced vector 𝑥𝑟 of size 𝑛𝑟 = 𝑛 − 𝑛𝑓 , where the fixed values are removed, to the full vector
𝑥:
𝑥 = 𝑇 𝑥𝑟 + 𝑥𝑓 .
With that the reduced linear system with a 𝑛𝑟 × 𝑛𝑟 can be formed:
𝑇 𝑇 𝐴𝑇 𝑥𝑟 = 𝑇 𝑇 (𝑏 − 𝐴𝑥𝑓 )
that can be solved by a linear solver. We can see, that the (non-zero) known values are now on the right-hand side of
the linear system. When the known values are all zero, we have simply
𝑇 𝑇 𝐴𝑇 𝑥𝑟 = 𝑇 𝑇 𝑏 ,
which is convenient, as it allows simply throwing away the A and b entries corresponding to the known values already
during the finite element assembling.
Implementation
All PDEs in SfePy are solved in a uniform way as a system of non-linear equations
𝑓 (𝑢) = 0 ,
where 𝑓 is the nonlinear function and 𝑢 the vector of unknown DOFs. This system is solved iteratively by the Newton
method
d𝑓 −1
𝑢𝑛𝑒𝑤 = 𝑢𝑜𝑙𝑑 − ( ) 𝑓 (𝑢𝑜𝑙𝑑 )
d𝑢𝑜𝑙𝑑
until a convergence criterion is met. Each iteration involves solution of the system of linear equations
𝐾∆𝑢 = 𝑟 ,
Then
𝑢𝑛𝑒𝑤 = 𝑢𝑜𝑙𝑑 − ∆𝑢 .
If the initial (old) vector 𝑢𝑜𝑙𝑑 contains the values of EBCs at correct positions, the increment ∆𝑢 is zero at those
positions. This allows us to assemble directly the reduced matrix 𝑇 𝑇 𝐾𝑇 , the right-hand side 𝑇 𝑇 𝑟, and ignore the
values of EBCs during assembling. The EBCs are satisfied automatically by applying them to the initial guess 𝑢0 , that
is given to the Newton solver.
Linear Problems
𝑓 (𝑢) ≡ 𝐴𝑢 − 𝑏 = 0 ,
d𝑓
=𝐴,
d𝑢
and so the Newton method converges in a single iteration:
The evaluation of the residual 𝑓 as well as the tangent matrix 𝐾 within the Newton solver proceeds in the following
steps:
• The EBCs are applied to the full DOF vector 𝑢.
• The reduced vector 𝑢𝑟 is passed to the Newton solver.
• Newton iteration loop:
– Evaluation of 𝑓𝑟 or 𝐾𝑟 :
1. 𝑢 is reconstructed from 𝑢𝑟 ;
Table 1: Notation.
symbol meaning
Ω volume (sub)domain
Γ surface (sub)domain
𝒟 volume or surface (sub)domain
𝑑 dimension of space
𝑡 time
𝑦 any function
𝑦 any vector function
𝑛 unit outward normal
𝑞 scalar test or parameter function
𝑝 scalar unknown or parameter function
𝑣 vector test or parameter function
𝑤, 𝑢 vector unknown or parameter function
𝑒(𝑢) Cauchy strain tensor ( 21 ((∇𝑢) + (∇𝑢)𝑇 ))
𝐹 deformation gradient 𝐹𝑖𝑗 = 𝜕𝑋 𝜕𝑥𝑖
𝑗
𝐽 det(𝐹 )
𝐶 right Cauchy-Green deformation tensor 𝐶 = 𝐹 𝑇 𝐹
𝜕𝑢
𝐸(𝑢) Green strain tensor 𝐸𝑖𝑗 = 21 ( 𝜕𝑋
𝜕𝑢𝑖
𝑗
+ 𝜕𝑋𝑗𝑖 + 𝜕𝑢 𝑚 𝜕𝑢𝑚
𝜕𝑋𝑖 𝜕𝑋𝑗 )
𝑆 second Piola-Kirchhoff stress tensor
𝑓 vector volume forces
𝑓 scalar volume force (source)
𝜌 density
𝜈 kinematic viscosity
𝑐, 𝑐, 𝑐 any constant
𝛿𝑖𝑗 , 𝐼 Kronecker delta, identity matrix
∑︀𝑑
tr ∙ trace of a second order tensor ( 𝑖=1 ∙𝑖𝑖 )
dev ∙ deviator of a second order tensor (∙ − 𝑑1 tr ∙)
𝑇𝐾 ∈ 𝒯ℎ 𝐾-th element of triangulation (= mesh) 𝒯ℎ of domain Ω
𝐾 ← ℐℎ 𝐾 is assigned values from {0, 1, . . . , 𝑁ℎ − 1} ≡ ℐℎ in ascending order
‘qp’ (·)|𝑞𝑝
Below we list all the terms available in automatically generated tables. The first column lists the name, the second
column the argument lists and the third column the mathematical definition of each term. The terms are devided into
the following tables:
• Table of basic terms
• Table of large deformation terms (total/updated Lagrangian formulation)
• Table of sensitivity terms
• Table of special terms
• Table of multi-linear terms
The notation <virtual> corresponds to a test function, <state> to a unknown function and <parameter> to a known
function. By <material> we denote material (constitutive) parameters, or, in general, any given function of space and
time that parameterizes a term, for example a given traction force vector.
dw_bc_newton <material_1>,
BCNewtonTerm <material_2>, ∫︁
<virtual>, 𝛼𝑞(𝑝 − 𝑝outer )
<state> Γ
ev_cauchy_strain <parameter>
CauchyStrainTerm ∫︁
𝑒(𝑤)
𝒟
ev_cauchy_stress <material>,
CauchyStressTerm<parameter> ∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑘𝑙 (𝑤)
𝒟
<virtual>,
<state>
continues on next page
<state>
dw_convect <virtual>, nav.sto,
ConvectTerm <state> ∫︁ nav.sto.iga,
((𝑢 · ∇)𝑢) · 𝑣 nav.sto
Ω
dw_convect_v_grad_s
<virtual>, poi.fun
ConvectVGradSTerm<state_v>, ∫︁
<state_s> 𝑞(𝑢 · ∇𝑝)
Ω
ev_def_grad <parameter>
DeformationGradientTerm
𝜕𝑥 𝜕𝑢
𝐹 = |𝑞𝑝 = 𝐼 + |𝑞𝑝 ,
𝜕𝑋 𝜕𝑋
𝑥 = 𝑋 + 𝑢 , 𝐽 = det (𝐹 )
dw_dg_advect_laxfrie_flux
<opt_material>, adv.2D,
AdvectionDGFluxTerm
<material_advelo>, ∫︁ adv.dif.2D,
<virtual>, 𝑛 · 𝑓 * (𝑝𝑖𝑛 , 𝑝𝑜𝑢𝑡 )𝑞 adv.1D
<state> 𝜕𝑇𝐾
where
𝑝𝑖𝑛 + 𝑝𝑜𝑢𝑡 𝑝𝑖𝑛 − 𝑝𝑜𝑢𝑡
𝑓 * (𝑝𝑖𝑛 , 𝑝𝑜𝑢𝑡 ) = 𝑎 + (1 − 𝛼)𝑛𝐶 ,
2 2
dw_dg_diffusion_flux
<material>, bur.2D,
DiffusionDGFluxTerm<state>, ∫︁ ∫︁ adv.dif.2D,
<virtual> 𝐷⟨∇𝑝⟩[𝑞] , 𝐷⟨∇𝑞⟩[𝑝] lap.2D
<material>, 𝜕𝑇𝐾 𝜕𝑇𝐾
<virtual>, where
<state>
∇𝜑𝑖𝑛 + ∇𝜑𝑜𝑢𝑡
⟨∇𝜑⟩ =
2
[𝜑] = 𝜑𝑖𝑛 − 𝜑𝑜𝑢𝑡
where
dw_dg_nonlinear_laxfrie_flux
<opt_material>, bur.2D
NonlinearHyperbolicDGFluxTerm
<fun>, ∫︁
<fun_d>, 𝑛 · 𝑓 * (𝑝𝑖𝑛 , 𝑝𝑜𝑢𝑡 )𝑞
<virtual>, 𝜕𝑇𝐾
<state> where
𝑓 (𝑝𝑖𝑛 ) + 𝑓 (𝑝𝑜𝑢𝑡 ) 𝑝𝑖𝑛 − 𝑝𝑜𝑢𝑡
𝑓 * (𝑝𝑖𝑛 , 𝑝𝑜𝑢𝑡 ) = + (1 − 𝛼)𝑛𝐶 ,
2 2
param_2>
<material>,
<state>,
<virtual>
dw_diffusion_r <material>,
DiffusionRTerm <virtual> ∫︁
𝐾𝑗 ∇𝑗 𝑞
Ω
ev_diffusion_velocity<material>,
DiffusionVelocityTerm<parameter> ∫︁
− 𝐾𝑖𝑗 ∇𝑗 𝑝
𝒟
dw_div <opt_material>,
DivOperatorTerm <virtual> ∫︁ ∫︁
∇ · 𝑣 or 𝑐∇ · 𝑣
Ω Ω
dw_elastic_wave_cauchy
<material_1>,
ElasticWaveCauchyTerm
<material_2>, ∫︁
<virtual>, 𝐷𝑖𝑗𝑘𝑙 𝑔𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
<state> ∫︁Ω
<material_1>, 𝐷𝑖𝑗𝑘𝑙 𝑔𝑖𝑗 (𝑢)𝑒𝑘𝑙 (𝑣)
<material_2>, Ω
<state>,
<virtual>
dw_electric_source <material>, the.ele
ElectricSourceTerm <virtual>, ∫︁
<parameter> 𝑐𝑠(∇𝜑)2
Ω
ev_grad <opt_material>,
GradTerm <parameter> ∫︁ ∫︁
∇𝑝 or ∇𝑢
𝒟 𝒟
∫︁ ∫︁
𝑐∇𝑝 or 𝑐∇𝑢
𝒟 𝒟
ev_integrate <opt_material>,
IntegrateTerm <parameter> ∫︁ ∫︁ ∫︁
𝑦, 𝑦, 𝑦·𝑛
∫︁ ∫︁ 𝒟 ∫︁𝒟 Γ
𝑐𝑦 , 𝑐𝑦 , 𝑐𝑦 · 𝑛 flux
𝒟 𝒟 Γ
ev_integrate_mat <material>,
IntegrateMatTerm<parameter> ∫︁
𝑐
𝒟
((𝑤 · ∇)𝑢)|𝑞𝑝
((𝑐 · ∇)𝑢)|𝑞𝑝
<state/ with
param_2> 𝐷𝑖𝑗𝑘𝑙 = 𝜇(𝛿𝑖𝑘 𝛿𝑗𝑙 + 𝛿𝑖𝑙 𝛿𝑗𝑘 ) + 𝜆 𝛿𝑖𝑗 𝛿𝑘𝑙
dw_non_penetration_p
<material>, bio.sho.syn
NonPenetrationPenaltyTerm
<virtual>, ∫︁
<state> 𝑐(𝑛 · 𝑣)(𝑛 · 𝑢)
Γ
param_2>
dw_ns_dot_grad_s <fun>, bur.2D
NonlinearScalarDotGradTerm
<fun_d>, ∫︁ ∫︁ ∫︁
<virtual>, 𝑞 · ∇ · 𝑓 (𝑝) = 𝑞 · div𝑓 (𝑝) , 𝑓 (𝑝) · ∇𝑞
<state> Ω Ω Ω
<fun>,
<fun_d>,
<state>,
<virtual>
dw_piezo_coupling <material>, pie.ela
PiezoCouplingTerm <virtual/ ∫︁
param_v>, 𝑔𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑣)∇𝑘 𝑝
<state/ ∫︁ Ω
param_s> 𝑔𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑢)∇𝑘 𝑞
<material>, Ω
<state>,
<virtual>
ev_piezo_strain <material>,
PiezoStrainTerm <parameter> ∫︁
𝑔𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑢)
Ω
ev_piezo_stress <material>,
PiezoStressTerm <parameter> ∫︁
𝑔𝑘𝑖𝑗 ∇𝑘 𝑝
Ω
dw_s_dot_grad_i_s <material>,
ScalarDotGradIScalarTerm
<virtual>, ∫︁
𝑖
<state> 𝑍 = 𝑞∇𝑖 𝑝
Ω
<state>,
<virtual>
dw_shell10x <material_d>, she.can
Shell10XTerm <material_drill>, ∫︁
<virtual>, 𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
<state> Ω
dw_stokes_wave_div<material>,
StokesWaveDivTerm <virtual>, ∫︁ ∫︁
<state> (𝜅 · 𝑣)(∇ · 𝑢) , (𝜅 · 𝑢)(∇ · 𝑣)
<material>, Ω Ω
<state>,
<virtual>
ev_sum_vals <parameter>
SumNodalValuesTerm
dw_surface_flux <opt_material>,
SurfaceFluxOperatorTerm
<virtual>, ∫︁
<state> 𝑞𝑛 · 𝐾 · ∇𝑝
Γ
dw_v_dot_grad_s <opt_material>,
VectorDotGradScalarTerm
<virtual/ ∫︁ ∫︁
param_v>, 𝑣 · ∇𝑝 , 𝑢 · ∇𝑞
<state/ Ω Ω
∫︁ ∫︁
param_s> 𝑐𝑣 · ∇𝑝 , 𝑐𝑢 · ∇𝑞
<opt_material>, ∫︁ Ω
∫︁ Ω
<state>,
𝑣 · (𝑐∇𝑝) , 𝑢 · (𝑐∇𝑞)
<virtual> Ω Ω
dw_vm_dot_s <material>,
VectorDotScalarTerm
<virtual/ ∫︁ ∫︁
param_v>, 𝑣 · 𝑐𝑝 , 𝑢 · 𝑐𝑞
<state/ Ω Ω
param_s>
<material>,
<state>,
<virtual>
ev_volume <parameter>
VolumeTerm ∫︁
1
𝒟
dw_adj_convect2 <virtual>,
AdjConvect2Term <state>, ∫︁
<parameter> ((𝑢 · ∇)𝑣) · 𝑤
Ω
dw_adj_div_grad <material_1>,
AdjDivGradTerm <material_2>,
<virtual>, 𝑤𝛿𝑢 Ψ(𝑢) ∘ 𝑣
<parameter>
ev_sd_convect <parameter_u>,
SDConvectTerm <parameter_w>, ∫︁
𝜕𝑢𝑖 𝜕𝒱𝑗 𝜕𝑢𝑖
<parameter_mv> [𝑢𝑘 𝑤𝑖 (∇ · 𝒱) − 𝑢𝑘 𝑤𝑖 ]
Ω 𝜕𝑥𝑘 𝜕𝑥𝑘 𝜕𝑥𝑗
ev_sd_diffusion <material>,
SDDiffusionTerm <parameter_q>, ∫︁
<parameter_p>, ˆ 𝑖𝑗 ∇𝑖 𝑞 ∇𝑗 𝑝
𝐾
<parameter_mv> Ω
(︂ )︂
ˆ 𝜕𝒱𝑗 𝜕𝒱𝑖
𝐾𝑖𝑗 = 𝐾𝑖𝑗 𝛿𝑖𝑘 𝛿𝑗𝑙 ∇ · 𝒱 − 𝛿𝑖𝑘 − 𝛿𝑗𝑙
𝜕𝑥𝑙 𝜕𝑥𝑘
de_sd_diffusion <material>,
ESDDiffusionTerm<virtual/ ∫︁
param_1>, ˆ 𝑖𝑗 ∇𝑖 𝑞 ∇𝑗 𝑝
𝐾
<state/ Ω
param_2>, (︂
𝜕𝒱𝑗 𝜕𝒱𝑖
)︂
<parameter_mv> ˆ
𝐾𝑖𝑗 = 𝐾𝑖𝑗 𝛿𝑖𝑘 𝛿𝑗𝑙 ∇ · 𝒱 − 𝛿𝑖𝑘 − 𝛿𝑗𝑙
𝜕𝑥𝑙 𝜕𝑥𝑘
ev_sd_div <parameter_u>,
SDDivTerm <parameter_p>, ∫︁
𝜕𝒱𝑘 𝜕𝑤𝑖
<parameter_mv> 𝑝[(∇ · 𝑤)(∇ · 𝒱) − ]
Ω 𝜕𝑥𝑖 𝜕𝑥𝑘
𝜕𝒱𝑙 𝜕𝒱𝑘
𝐼ˆ𝑖𝑗𝑘𝑙 = 𝛿𝑖𝑘 𝛿𝑗𝑙 ∇ · 𝒱 − 𝛿𝑖𝑘 𝛿𝑗𝑠 − 𝛿𝑖𝑠 𝛿𝑗𝑙
𝜕𝑥𝑠 𝜕𝑥𝑠
de_sd_div_grad <opt_material>,
ESDDivGradTerm <virtual/ ∫︁ ∫︁
param_1>, ˆ
𝐼∇𝑣 : ∇𝑢 , ˆ
𝜈 𝐼∇𝑣 : ∇𝑢
<state/ Ω Ω
ev_sd_dot <parameter_1>,
SDDotTerm <parameter_2>, ∫︁ ∫︁
<parameter_mv> 𝑝𝑞(∇ · 𝒱) , (𝑢 · 𝑤)(∇ · 𝒱)
Ω Ω
de_sd_dot <opt_material>,
ESDDotTerm <virtual/ ∫︁ ∫︁
param_1>, 𝑞𝑝(∇ · 𝒱) , (𝑣 · 𝑢)(∇ · 𝒱)
<state/ ∫︁ Ω ∫︁ Ω
param_2>, 𝑐𝑞𝑝(∇ · 𝒱) , 𝑐(𝑣 · 𝑢)(∇ · 𝒱)
<parameter_mv> Ω
∫︁ Ω
𝑣 · (𝑀 𝑢)(∇ · 𝒱)
Ω
de_sd_lin_elastic <material>,
ESDLinearElasticTerm
<virtual/ ∫︁
param_1>, ˆ 𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
𝐷
<state/ Ω
param_2>,
<parameter_mv> ˆ 𝑖𝑗𝑘𝑙 = 𝐷𝑖𝑗𝑘𝑙 (∇ · 𝒱) − 𝐷𝑖𝑗𝑘𝑞 𝜕𝒱𝑙 − 𝐷𝑖𝑞𝑘𝑙 𝜕𝒱𝑗
𝐷
𝜕𝑥𝑞 𝜕𝑥𝑞
ev_sd_lin_elastic <material>,
SDLinearElasticTerm
<parameter_w>, ∫︁
<parameter_u>, ˆ 𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
𝐷
<parameter_mv> Ω
𝜕𝒱𝑗 𝜕𝒱𝑘
𝑔ˆ𝑘𝑖𝑗 = 𝑔𝑘𝑖𝑗 (∇ · 𝒱) − 𝑔𝑘𝑖𝑙 − 𝑔𝑙𝑖𝑗
𝜕𝑥𝑙 𝜕𝑥𝑙
de_sd_piezo_coupling
<material>,
ESDPiezoCouplingTerm
<virtual/ ∫︁ ∫︁
param_v>, 𝑔ˆ𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑣)∇𝑘 𝑝 , 𝑔ˆ𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑢)∇𝑘 𝑞
<state/ Ω Ω
de_sd_surface_ltr <opt_material>,
ESDLinearTractionTerm
<virtual/ ∫︁
[︀(︀ )︀ ]︀
param>, 𝑣· 𝜎ˆ∇·𝒱 −𝜎
ˆ ∇𝒱 𝑛
<parameter_mv> Γ
ˆ =𝐼 ,𝜎
𝜎 ˆ = 𝑐 𝐼 or 𝜎
ˆ=𝜎
ev_sd_surface_ltr <opt_material>,
SDLinearTractionTerm
<parameter>, ∫︁ ∫︁
<parameter_mv> 𝑣 · (𝜎 𝑛), 𝑣 · 𝑛,
Γ Γ
<material_5>,
<virtual>,
<state>
dw_tl_he_genyeoh <material>,
GenYeohTLTerm <virtual>, ∫︁
<state> 𝑆𝑖𝑗 (𝑢)𝛿𝐸𝑖𝑗 (𝑢; 𝑣)
Ω
dw_tl_he_mooney_rivlin
<material>, com.ela.mat, bal,
MooneyRivlinTLTerm
<virtual>, ∫︁ hyp
<state> 𝑆𝑖𝑗 (𝑢)𝛿𝐸𝑖𝑗 (𝑢; 𝑣)
Ω
dw_tl_surface_traction
<opt_material>, per.tl
SurfaceTractionTLTerm
<virtual>, ∫︁
<state> 𝜈 · 𝐹 −1 · 𝜎 · 𝑣𝐽
Γ
ev_tl_volume_surface
<parameter>
VolumeSurfaceTLTerm ∫︁
1/𝐷 𝜈 · 𝐹 −1 · 𝑥𝐽
Γ
dw_ul_bulk_pressure<virtual>, hyp.ul.up
BulkPressureULTerm <state>, ∫︁
<state_p> ℒ𝜏𝑖𝑗 (𝑢)𝑒𝑖𝑗 (𝛿𝑣)/𝐽
Ω
dw_ul_compressible<material>, hyp.ul.up
CompressibilityULTerm
<virtual>, ∫︀
<state>, 1 Ω
<parameter_u> 𝛾𝑝 𝑞
ev_cauchy_stress_th <ts>,
CauchyStressTHTerm <material>, ∫︁ ∫︁ 𝑡
<parameter> ℋ𝑖𝑗𝑘𝑙 (𝑡 − 𝜏 ) 𝑒𝑘𝑙 (𝑤(𝜏 )) d𝜏
Ω 0
ev_of_ns_surf_min_d_press
<material_1>,
NSOFSurfMinDPressTerm
<material_2>, (︂∫︁ ∫︁ )︂
<parameter> 𝛿Ψ(𝑝) = 𝛿 𝑝− 𝑏𝑝𝑟𝑒𝑠𝑠
Γ𝑖𝑛 Γ𝑜𝑢𝑡
ev_sd_st_grad_div <material>,
SDGradDivStabilizationTerm
<parameter_u>,∫︁
𝜕𝑢𝑖 𝜕𝒱𝑘 𝜕𝑤𝑖 𝜕𝒱𝑘
𝛾 [(∇ · 𝑢)(∇ · 𝑤)(∇ · 𝒱) −
<parameter_w>, (∇ · 𝑤) − (∇ · 𝑢) ]
<parameter_mv> Ω 𝜕𝑥𝑘 𝜕𝑥𝑖 𝜕𝑥𝑘 𝜕𝑥𝑖
ev_sd_st_pspg_c <material>,
SDPSPGCStabilizationTerm
<parameter_b>,
∑︁ ∫︁ 𝜕𝑟 𝜕𝑟 𝜕𝒱𝑘 𝜕𝑟 𝜕𝑢𝑖
<parameter_u>, 𝛿𝐾 [ (𝑏 · ∇𝑢𝑖 )(∇ · 𝒱) − (𝑏 · ∇𝑢𝑖 ) − (𝑏 · ∇𝒱𝑘 ) ]
𝜕𝑥𝑖 𝜕𝑥𝑘 𝜕𝑥𝑖 𝜕𝑥𝑘 𝜕𝑥𝑘
𝐾∈ℐℎ 𝑇𝐾
<parameter_r>,
<parameter_mv>
ev_sd_st_pspg_p <material>,
SDPSPGPStabilizationTerm
<parameter_r>,
∑︁ ∫︁ 𝜕𝑟 𝜕𝑝
<parameter_p>, 𝜏𝐾 [(∇𝑟 · ∇𝑝)(∇ · 𝒱) − (∇𝒱𝑘 · ∇𝑝) − (∇𝑟 · ∇𝒱𝑘 ) ]
𝜕𝑥𝑘 𝜕𝑥𝑘
𝐾∈ℐℎ 𝑇𝐾
<parameter_mv>
ev_sd_st_supg_c <material>,
SDSUPGCStabilizationTerm
<parameter_b>,
∑︁ ∫︁ 𝜕𝑢𝑘 𝜕𝑤𝑘
<parameter_u>, 𝛿𝐾 [(𝑏 · ∇𝑢𝑘 )(𝑏 · ∇𝑤𝑘 )(∇ · 𝒱) − (𝑏 · ∇𝒱𝑖 ) (𝑏 · ∇𝑤𝑘 ) − (𝑢 · ∇𝑢𝑘 )(𝑏 · ∇𝒱𝑖 ) ]
𝜕𝑥𝑖 𝜕𝑥𝑖
𝐾∈ℐℎ 𝑇𝐾
<parameter_w>,
<parameter_mv>
dw_st_adj1_supg_p <material>,
SUPGPAdj1StabilizationTerm
<virtual>, ∑︁ ∫︁
<state>, 𝛿𝐾 ∇𝑝(𝑣 · ∇𝑤)
<parameter> 𝐾∈ℐℎ 𝑇𝐾
dw_st_adj2_supg_p <material>,
SUPGPAdj2StabilizationTerm
<virtual>, ∑︁ ∫︁
<parameter>, 𝜏𝐾 ∇𝑟(𝑣 · ∇𝑢)
<state> 𝐾∈ℐℎ 𝑇𝐾
dw_st_adj_supg_c <material>,
SUPGCAdjStabilizationTerm
<virtual>, ∑︁ ∫︁
<parameter>, 𝛿𝐾 [((𝑣 · ∇)𝑢)((𝑢 · ∇)𝑤) + ((𝑢 · ∇)𝑢)((𝑣 · ∇)𝑤)]
<state> 𝐾∈ℐℎ 𝑇𝐾
param_2>
dw_st_supg_c <material>, sta.nav.sto
SUPGCStabilizationTerm
<virtual>, ∑︁ ∫︁
<parameter>, 𝛿𝐾 ((𝑏 · ∇)𝑢) · ((𝑏 · ∇)𝑣)
<state> 𝐾∈ℐℎ 𝑇𝐾
dw_volume_dot_w_scalar_eth
<ts>,
DotSProductVolumeOperatorWETHTerm
<material_0>, ∫︁ [︂∫︁ 𝑡 ]︂
<material_1>, 𝒢(𝑡 − 𝜏 )𝑝(𝜏 ) d𝜏 𝑞
<virtual>, Ω 0
<state>
dw_volume_dot_w_scalar_th
<ts>,
DotSProductVolumeOperatorWTHTerm
<material>, ∫︁ [︂∫︁ 𝑡 ]︂
<virtual>, 𝒢(𝑡 − 𝜏 )𝑝(𝜏 ) d𝜏 𝑞
<state> Ω 0
de_convect <virtual/
EConvectTerm param_1>, ∫︁
<state/ ((𝑢 · ∇)𝑢) · 𝑣
param_2> Ω
de_diffusion <material>,
EDiffusionTerm <virtual/ ∫︁
param_1>, 𝐾𝑖𝑗 ∇𝑖 𝑞 ∇𝑗 𝑝
<state/ Ω
param_2>
de_div <opt_material>,
EDivTerm <virtual/ ∫︁ ∫︁
param> ∇·𝑣, 𝑐∇ · 𝑣
Ω Ω
de_div_grad <opt_material>,
EDivGradTerm <virtual/ ∫︁ ∫︁
param_1>, ∇𝑣 : ∇𝑢 , 𝜈 ∇𝑣 : ∇𝑢
<state/ Ω Ω
param_2>
de_dot <opt_material>,
EDotTerm <virtual/ ∫︁ ∫︁
param_1>, 𝑞𝑝 , 𝑣·𝑢
𝒟
<state/ ∫︁ ∫︁ 𝒟
param_2> 𝑐𝑞𝑝 , 𝑐𝑣 · 𝑢
𝒟 𝒟
∫︁
𝑣 · (𝑐 𝑢)
𝒟
de_grad <opt_material>,
EGradTerm <parameter> ∫︁ ∫︁
∇𝑣 , 𝑐∇𝑣
Ω Ω
de_integrate <opt_material>,
EIntegrateOperatorTerm
<virtual> ∫︁ ∫︁
𝑞 or 𝑐𝑞
𝒟 𝒟
param_2>
de_lin_convect <virtual/
ELinearConvectTerm param_1>, ∫︁
<parameter>, ((𝑤 · ∇)𝑢) · 𝑣
<state/ Ω
param_3>
de_lin_elastic <material>,
ELinearElasticTerm <virtual/ ∫︁
param_1>, 𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
<state/ Ω
param_2>
de_non_penetration_p
<material>,
ENonPenetrationPenaltyTerm
<virtual>, ∫︁
<state> 𝑐(𝑛 · 𝑣)(𝑛 · 𝑢)
Γ
de_nonsym_elastic <material>,
ENonSymElasticTerm<virtual/ ∫︁
param_1>, 𝐷∇𝑣 : ∇𝑢
<state/ Ω
param_2>
de_s_dot_mgrad_s <material>,
EScalarDotMGradScalarTerm
<virtual/ ∫︁ ∫︁
param_1>, 𝑞𝑦 · ∇𝑝 , 𝑝𝑦 · ∇𝑞
<state/ Ω Ω
param_2>
<material>,
<state>,
<virtual>
de_stokes <opt_material>,
EStokesTerm <virtual/ ∫︁ ∫︁
param_v>, 𝑝∇ · 𝑣 , 𝑞∇·𝑢
Ω
<state/ ∫︁ ∫︁ Ω
param_s> 𝑐𝑝∇ · 𝑣 , 𝑐𝑞∇ · 𝑢
<opt_material>, Ω Ω
<state>,
<virtual>
de_surface_ltr <opt_material>,
ELinearTractionTerm
<virtual/ ∫︁ ∫︁
param> 𝑣·𝑛, 𝑐𝑣 · 𝑛
Γ Γ
∫︁ ∫︁
𝑣 · (𝜎 𝑛) , 𝑣·𝑓
Γ Γ
TWO
DEVELOPMENT
The SfePy development takes place in the sfepy/sfepy repository on Github. The users and developers can also com-
municate using the mailing list.
We are interested in any contribution. There are many ways how you can contribute:
• You can report bugs using our mailing list. You can also add a bug report (or a comment) into the issues.
• You can contribute interesting examples/tutorials.
• You can blog about how you use SfePy (let us know!).
• You can help with improving our documentation and these pages.
• ...
To get acquainted with SfePy, you can start by reading the Tutorial and Primer sections of the documentation and trying
out the examples that come with the sources. Your first contribution could be pinpointing anything that is not clear in
the docs.
We also recommend reading the How to Contribute section of our Developer Guide.
Several specific topics that we wish to address in the future are listed below. If you would like to contribute code/advice
to our project with respect to these topics, do not hesitate to contact us (either directly: cimrman3(at)ntc.zcu.cz, or on
our mailing list)
• finish/improve IGA implementation (see Isogeometric Analysis):
– support multiple patches
– efficient quadrature formulas
– local refinement?
• discretization methods:
– implement vector elements (Nedelec, Raviart-Thomas, . . . )
– implement the discontinuous Galerkin method
• material models: plasticity, viscoplasticity, damage, . . .
• improve parallelization (see Solving Problems in Parallel):
609
SfePy Documentation, Release version: 2022.2
This section purports to document the SfePy internals. It is mainly useful for those who wish to contribute to the
development of SfePy and understand the inner workings of the code.
We use git to track source code, documentation, examples, and other files related to the project.
It is not necessary to learn git in order to contribute to SfePy but we strongly suggest you do so as soon as possible - it
is an extremely useful tool not just for writing code, but also for tracking revisions of articles, Ph.D. theses, books, . . .
it will also look well in your CV :-) It is also much easier for us to integrate changes that are in form of a github pull
request than in another form.
The first step is to obtain the latest development version of the code from the SfePy git repository:
For development, it is preferable to build the extension modules in place (see Compilation of C Extension Modules):
On Unix-like systems, you can simply type make in the top-level folder to build in-place.
After the initial compilation, or after making changes, do not forget to run the tests, see Testing Installation.
Here we list and describe the directories that are in the main sfepy directory.
New users/developers (after going through the Tutorial) should explore the sfepy/examples/ directory. For developers,
the principal directory is sfepy/, which has the following contents:
mesh/ some utilities to interface with tetgen and triangle mesh generators
homog- the homogenization engine and supporting modules - highly specialized code, one of the •
eniza- reasons of SfePy existence
tion/
linalg/ linear algebra functions not covered by NumPy and SciPy
mechan- modules for (continuum) mechanics: elastic constant conversions, tensor, units utilities, etc. •
ics/
opti- modules for shape optimization based on free-form deformation •
mize/
paral- modules supporting parallel assembling and solution of problems
lel/
postpro- Matplotlib and VTK based post-processing modules
cess/
solvers/ interface classes to various internal/external solvers (linear, nonlinear, eigenvalue, optimiza-
tion, time stepping)
terms/ implementation of the terms (weak formulation integrals), see Term Overview
The directories in the “field-specific” column are mostly interesting for specialists working in the respective fields.
The fem/ is the heart of the code, while the terms/ contains the particular integral forms usable to build equations -
new term writers should look there.
It is convenient to install IPython (see also Using IPython) to have the tab completion available. Moreover, all SfePy
classes can be easily examined by printing them:
We recommend going through the interactive example in the tutorial Interactive Example: Linear Elasticity in this way,
printing all the variables.
Another useful tool is the debug() function, that can be used as follows:
Try to use it in the examples with user defined functions to explore their parameters etc. It works best with IPython
installed, as then the tab completion is available also when debugging.
Read this section if you wish to contribute some work to the SfePy project - everyone is welcome to contribute. Con-
tributions can be made in a variety of forms, not just code. Reporting bugs and contributing to the documentation,
tutorials, and examples is in great need!
Below we describe
1. where to report problems or find existing issues and additional development suggestions
2. what to do to apply changes/fixes
3. what to do after you made your changes/fixes
Reporting problems
Reporting a bug is the first way in which to contribute to an open source project
Short version: go to the main SfePy site and follow the links given there.
When you encounter a problem, try searching that site first - an answer may already be posted in the SfePy mailing
list (to which we suggest you subscribe. . . ), or the problem might have been added to the SfePy issues. As is true in
any open source project, doing your homework by searching for existing known problems greatly reduces the burden
on the developers by eliminating duplicate issues. If you find your problem already exists in the issue tracker, feel free
to gather more information and append it to the issue. In case the problem is not there, create a new issue with proper
labels for the issue type and priority, and/or ask us using the mailing list.
Note: A google account (e.g., gmail account) is needed to join the mailing list. A github account is needed for working
with the source code repository and issues.
Note: When reporting a problem, try to provide as much information as possible concerning the version of SfePy, the
OS / Linux distribution, and the versions of Python, NumPy and SciPy, and other prerequisites. The versions found on
your system can be printed by running:
If you are a new user, please let us know what difficulties you have with this documentation. We greatly welcome a
variety of contributions not limited to code only.
Contributing changes
Note: To avoid duplicating work, it is highly advised that you contact the developers on the mailing list or create an
enhancement issue before starting work on a non-trivial feature.
Before making any changes, read the Notes on commits and patches.
The preferred way to contribute to SfePy is to fork the main repository on github, then submit a “pull request” (PR):
1. Create a github account if you do not already have one.
2. Fork the project repository: click on the “Fork” button near the top of the sfepy git repository page. This creates
a copy of the repository under your account on the github server.
3. Clone your fork to your computer:
4. If you have never used git before, introduce yourself to git and make (optionally) some handy aliases either in
.gitconfig in your home directory (global settings for all your git projects), or directly in .git/config in the
repository:
1 [user]
2 email = [email protected]
3 name = Name Surname
4
5 [color]
6 ui = auto
7 interactive = true
(continues on next page)
9 [alias]
10 ci = commit
11 di = diff --color-words
12 st = status
13 co = checkout
Then you can start to make your changes. Do not work in the master branch!
6. Modify some files and use git to track your local changes. The changed added/modified files can be listed using:
git status
git diff
gitk --all
in order to visualize of project history (all branches). There are other GUIs for this purpose, e.g. qgit. You may
need to install those tools, as they usually are not installed with git by default. Record a set of changes by:
We recommend git gui command in case you want to add and commit only some changes in a modified file.
Note: Do not be afraid to experiment - git works with your local copy of the repository, so it is not possible to
damage the master repository. It is always possible to re-clone a fresh copy, in case you do something that is
really bad.
7. The commit(s) now reflect changes, but only in your local git repository. To update your github repository with
your new commit(s), run:
8. Finally, when your feature is ready, and all tests pass, go to the github page of your sfepy repository fork, and
click “Pull request” to send your changes to the maintainers for review. It is recommended to check that your
contribution complies with the Notes on commits and patches.
In the above setup, your origin remote repository points to YourLogin/sfepy.git. If you wish to fetch/merge from
the main repository instead of your forked one, you will need to add another remote to use instead of origin. The main
repository is usually called “upstream”. To add it, type:
Warning The above will remove all your local commits in the master branch that are not in upstream/master,
and also reset all the changes in your non-committed modified files!
Optionally, the reset command can be run conveniently in gitk by right-clicking on a commit you want to reset
the current branch onto.
4. Optionally, rebase your feature branch onto the upstream master:
This is useful, for example, when the upstream master contains a change you need in your feature branch.
For additional information, see, for example, the gitwash git tutorial, or its incarnation NumPy gitwash.
Without using git, send the modified files to the SfePy mailing list or attach them using gist to the corresponding issue
at the Issues web page. Do not forget to describe the changes properly, and to follow the spirit of Notes on commits and
patches and the Coding style.
Coding style
All the code in SfePy should try to adhere to python style guidelines, see PEP-0008.
There are some additional recommendations:
• Prefer whole words to abbreviations in public APIs - there is completion after all. If some abbreviation is needed
(really too long name), try to make it as comprehensible as possible. Also check the code for similar names - try
to name things consistently with the existing code. Examples:
– yes: equation, transform_variables(), filename
– rather not: eq, transvar(), fname
• Functions have usually form <action>_<subject>() e.g.: save_data(), transform_variables(), do not
use data_save(), variable_transform() etc.
• Variables like V, c, A, b, x should be tolerated only locally when expressing mathematical ideas.
Really minor recommendations:
• Avoid single letter names, if you can:
– not even for loop variables - use e.g. ir, ic, . . . instead of i, j for rows and columns
– not even in generators, as they “leak” (this is fixed in Python 3.x)
These are recommendations only, we will not refuse code just on the ground that it uses slightly different formatting,
as long as it follows the PEP.
Note: some old parts of the code might not follow the PEP, yet. We fix them progressively as we update the code.
Docstring standard
We use sphinx with the numpydoc extension to generate this documentation. Refer to the sphinx site for the possible
markup constructs.
Basically (with a little tweak), we try to follow the NumPy/SciPy docstring standard as described in NumPy documen-
tation guide. See also the complete docstring example. It is exaggerated a bit to show all the possibilities. Use your
common sense here - the docstring should be sufficient for a new user to use the documented object. A good way to
remember the format is to type:
5 Parameters
6 ----------
7 arg1 : array
8 The coordinates of ...
9 arg2 : int
10 The dimension ...
11
12 Returns
(continues on next page)
4 Parameters
5 ----------
6 arg1 : array
7 The coordinates of ...
8 arg2 : int
9 The dimension ...
10
11 Returns
12 -------
13 out : array
14 The resulting array of shape ....
15 """
1 def function():
2 r"""
3 This is a function with :math:`\mbox{\LaTeX}` math:
4 :math:`\frac{1}{\pi}`.
5 """
to prevent Python from interpreting and consuming the backslashes in common escape sequences like ‘\n’, ‘\f’ etc.
cd doc
make html
firefox _build/html/index.html
Warning Implementing a new term usually involves C. As Cython is now supported by our build system, it should not
be that difficult. Python-only terms are possible as well.
Note There is an experimental way (newly from version 2021.1) of implementing multi-linear terms that is much easier
than what is described here, see Multi-linear Terms.
Notes on terminology
Volume refers to the whole domain (in space of dimension 𝑑), while surface to a subdomain of dimension 𝑑 − 1, for
example a part of the domain boundary. So in 3D problems volume = volume, surface = surface, while in 2D volume
= area, surface = curve.
Introduction
A term in SfePy usually corresponds to a single integral term in (weak) integral formulation of an equation. Both
volume and surface integrals are supported. There are three types of arguments a term can have:
• variables, i.e. the unknown, test or parameter variables declared by the variables keyword, see sec-problem-
description-file,
• materials, corresponding to material and other parameters (functions) that are known, declared by the materials
keyword,
• user data - anything, but user is responsible for passing them to the evaluation functions.
SfePy terms are subclasses of sfepy.terms.terms.Term. The purpose of a term is to implement a (vectorized)
function that evaluates the term contribution to residual/matrix and/or evaluates the term integral in elements of the
term region. Many such functions are currently implemented in C, but some terms are pure Python, vectorized using
NumPy.
Evaluation modes
Basic attributes
A term class should inherit from sfepy.terms.terms.Term base class. The simplest possible term with volume
integration and ‘weak’ evaluation mode needs to have the following attributes and methods:
• docstring (not really required per se, but we require it);
• name attribute - the name to be used in equations;
• arg_types attribute - the types of arguments the term accepts;
• integration attribute, optional - the kind of integral the term implements, one of ‘volume’ (the default, if not
given), ‘surface’, ‘surface_extra’ or ‘by_region’;
• function() static method - the assembling function;
• get_fargs() method - the method that takes term arguments and converts them to arguments for function().
Argument types
Integration kinds
function()
out, *args
where out is the already preallocated output array (change it in place!) and *args are any other arguments the function
requires. These function arguments have to be provided by the get_fargs() method. The function returns zero status on
success, nonzero on failure.
The out array has shape (n_el, 1, n_row, n_col), where n_el is the number of elements and n_row, n_col are matrix
dimensions of the value on a single element.
get_fargs()
here:
– mode is the actual evaluation mode, default is ‘eval’;
– term_mode is an optional term sub-mode influencing what the term should return (example:
dw_tl_he_neohook term has ‘strain’ and ‘stress’ evaluation sub-modes);
– diff_var is taken into account in the ‘weak’ evaluation mode. It is either None (residual mode) or a name
of variable with respect to differentiate to (matrix mode);
– **kwargs are any other arguments that the term supports.
The get_fargs() method returns arguments for function().
Additional attributes
These attributes are used mostly in connection with the tests/test_term_call_modes.py test for automatic testing of term
calls.
• arg_shapes attribute - the possible shapes of term arguments;
• geometries attribute - the list of reference element geometries that the term supports;
• mode attribute - the default evaluation mode.
Argument shapes
The argument shapes are specified using a dict of the following form:
The keys are the argument types listed in the arg_types attribute, for example:
The values are the shapes containing either integers, or ‘D’ (for space dimension) or ‘S’ (symmetric storage size corre-
sponding to the space dimension). For materials, the shape is a string ‘nr, nc’ or a single value, denoting a special-valued
term, or None denoting an optional material that is left out. For state and parameter variables, the shape is a single
value. For virtual variables, the shape is a tuple of a single shape value and a name of the corresponding state variable;
the name can be None.
When several alternatives are possible, a list of dicts can be used. For convenience, only the shapes of arguments that
change w.r.t. a previous dict need to be included, as the values of the other shapes are taken from the previous dict. For
example, the following corresponds to a case, where an optional material has either the shape (1, 1) in each point, or is
left out:
Geometries
The default that most terms use is a list of all the geometries:
Examples
Let us now discuss the implementation of a simple weak term dw_integrate defined as 𝑐𝑞, where 𝑐 is a weight
∫︀
𝒟
(material parameter) and 𝑞 is a virtual variable. This term is implemented as follows:
1 class IntegrateOperatorTerm(Term):
2 r"""
3 Integral of a test function weighted by a scalar function
4 :math:`c`.
5
6 :Definition:
7
8 .. math::
9 \int_{\cal{D}} q \mbox{ or } \int_{\cal{D}} c q
10
11 :Arguments:
12 - material : :math:`c` (optional)
13 - virtual : :math:`q`
14 """
15 name = 'dw_integrate'
16 arg_types = ('opt_material', 'virtual')
17 arg_shapes = [{'opt_material' : '1, 1', 'virtual' : (1, None)},
18 {'opt_material' : None}]
19 integration = 'by_region'
20
21 @staticmethod
22 def function(out, material, bf, geo):
23 bf_t = nm.tile(bf.transpose((0, 1, 3, 2)), (out.shape[0], 1, 1, 1))
24 bf_t = nm.ascontiguousarray(bf_t)
(continues on next page)
∫︀A more complex term that involves an ∫︀unknown variable and has two call modes, is dw_s_dot_mgrad_s, defined as
Ω
𝑞𝑦 · ∇𝑝 in the`’grad_state’` mode or Ω 𝑝𝑦 · ∇𝑞 in the ‘grad_virtual’ mode, where 𝑦 is a vector material parameter,
𝑞 is a virtual variable, and 𝑝 is a state variable:
1 class ScalarDotMGradScalarTerm(Term):
2 r"""
3 Volume dot product of a scalar gradient dotted with a material vector
4 with a scalar.
5
(continues on next page)
8 .. math::
9 \int_{\Omega} q \ul{y} \cdot \nabla p \mbox{ , }
10 \int_{\Omega} p \ul{y} \cdot \nabla q
11
12 :Arguments 1:
13 - material : :math:`\ul{y}`
14 - virtual : :math:`q`
15 - state : :math:`p`
16
17 :Arguments 2:
18 - material : :math:`\ul{y}`
19 - state : :math:`p`
20 - virtual : :math:`q`
21 """
22 name = 'dw_s_dot_mgrad_s'
23 arg_types = (('material', 'virtual', 'state'),
24 ('material', 'state', 'virtual'))
25 arg_shapes = [{'material' : 'D, 1',
26 'virtual/grad_state' : (1, None),
27 'state/grad_state' : 1,
28 'virtual/grad_virtual' : (1, None),
29 'state/grad_virtual' : 1}]
30 modes = ('grad_state', 'grad_virtual')
31
32 @staticmethod
33 def function(out, out_qp, geo, fmode):
34 status = geo.integrate(out, out_qp)
35 return status
36
42 if diff_var is None:
43 if self.mode == 'grad_state':
44 geo = vg1
45 bf_t = vg1.bf.transpose((0, 1, 3, 2))
46 val_qp = self.get(var2, 'grad')
47 out_qp = bf_t * dot_sequences(mat, val_qp, 'ATB')
48
49 else:
50 geo = vg2
51 val_qp = self.get(var1, 'val')
52 out_qp = dot_sequences(vg2.bfg, mat, 'ATB') * val_qp
53
54 fmode = 0
55
56 else:
57 if self.mode == 'grad_state':
(continues on next page)
62 else:
63 geo = vg2
64 out_qp = dot_sequences(vg2.bfg, mat, 'ATB') * vg1.bf
65
66 fmode = 1
67
Only interesting differences with respect to the previous example will by discussed:
• the argument types and shapes (lines 23-29) have to be specified for all the call modes (line 30)
• the term function (lines 32-35) just integrates the element contributions, as all the other calculations are done by
the get_fargs() function.
• the get_fargs() function (lines 37-68) contains:
– residual computation (lines 43-54) for both modes
– matrix computation (lines 57-66) for both modes
Concluding remarks
This is just a very basic introduction to the topic of new term implementation. Do not hesitate to ask the SfePy mailing
list, and look at the source code of the already implemented terms.
The examples below present the new way of implementing the terms shown in the original Examples, using sfepy.
terms.terms_multilinear.ETermBase.
Examples
• de_integrate defined as 𝑐𝑞, where 𝑐 is a weight (material parameter) and 𝑞 is a virtual variable:
∫︀
Ω
1 class EIntegrateOperatorTerm(ETermBase):
2 r"""
3 Volume and surface integral of a test function weighted by a scalar
4 function :math:`c`.
5
6 :Definition:
7
8 .. math::
9 \int_{\cal{D}} q \mbox{ or } \int_{\cal{D}} c q
10
11 :Arguments:
12 - material : :math:`c` (optional)
13 - virtual : :math:`q`
14 """
15 name = 'de_integrate'
16 arg_types = ('opt_material', 'virtual')
17 arg_shapes = [{'opt_material' : '1, 1', 'virtual' : (1, None)},
18 {'opt_material' : None}]
19
27 else:
28 fun = self.make_function(
29 '00,0', mat, virtual, diff_var=diff_var,
30 )
31
32 return fun
1 class EScalarDotMGradScalarTerm(ETermBase):
2 r"""
3 Volume dot product of a scalar gradient dotted with a material vector with
4 a scalar.
5
6 :Definition:
7
8 .. math::
9 \int_{\Omega} q \ul{y} \cdot \nabla p \mbox{ , }
10 \int_{\Omega} p \ul{y} \cdot \nabla q
11
12 :Arguments 1:
13 - material : :math:`\ul{y}`
14 - virtual : :math:`q`
(continues on next page)
17 :Arguments 2:
18 - material : :math:`\ul{y}`
19 - state : :math:`p`
20 - virtual : :math:`q`
21 """
22 name = 'de_s_dot_mgrad_s'
23 arg_types = (('material', 'virtual', 'state'),
24 ('material', 'state', 'virtual'))
25 arg_shapes = [{'material' : 'D, 1',
26 'virtual/grad_state' : (1, None),
27 'state/grad_state' : 1,
28 'virtual/grad_virtual' : (1, None),
29 'state/grad_virtual' : 1}]
30 modes = ('grad_state', 'grad_virtual')
31
Release Tasks
$ rm -rf doc/examples/
$ python3 script/gen_gallery.py
$ # copy site_cfg.py
$ python3 setup.py htmldocs
$ firefox doc/_build/html/index.html
or use:
$ cd doc/
$ make html
$ firefox _build/html/index.html
try also:
then remove the installed files so that they do not interfere with the local build
7. create final tarball
• update doc/release_notes.rst, with the help of:
• create tarball:
• log
• misc:
• make a pull request with the updated version in sfepy-feedstock/recipe/meta.yaml from a fork (e.g. https:
//github.com/rc/sfepy-feedstock) of https://github.com/conda-forge/sfepy-feedstock.
• publish development docs also as new release docs
• send announcement to
– [email protected], [email protected], [email protected], [email protected],
[email protected]
Main scripts
extractor.py script
Extract information from a SfePy multi-time-step results file (HDF5 format) and/or linearize results with stored higher
order DOFs.
For the linearization, the original input (problem description) file must be specified as the first argument. Use the
option –linearization below to override linearization parameters defined in the input file. The linearization forces
–dump option, i.e., output to VTK files.
Examples
extractor.main()
extractor.parse_linearization(linearization)
probe.py script
Generation mode
Generation options
Postprocessing mode
Postprocessing options
Notes
For extremely thin hexahedral elements the Newton’s iteration for finding the reference element coordinates might
converge to a spurious solution outside of the element. To obtain some values even in this case, try increasing the
–close-limit option value.
probe.generate_probes(filename_input, filename_results, options, conf=None, problem=None, probes=None,
labels=None, probe_hooks=None)
Generate probe figures and data files.
probe.integrate_along_line(x, y, is_radial=False)
Integrate numerically (trapezoidal rule) a function 𝑦 = 𝑦(𝑥).
If is_radial is True, multiply each 𝑦 by 4𝜋𝑥2 .
probe.main()
resview.py script
This is a script for quick VTK-based visualizations of finite element computations results.
Examples
• Customize the above output: plot0: field “p”, switch on edges, plot1: field “u”, surface with opacity 0.4, glyphs
scaled by factor 2e-2.
$ python resview.py output-tests/navier_stokes-navier_stokes.vtk -f p:e:p0 u:o.4:p1 u:g:f2e-2:p1
• As above, but glyphs are scaled by the factor determined automatically as 20% of the minimum bounding box
size.
$ python resview.py output-tests/navier_stokes-navier_stokes.vtk -f p:e:p0 u:o.4:p1 u:g:f10%:p1
• View data and take a screenshot.
$ python resview.py output-tests/diffusion-poisson.vtk -o image.png
• Take a screenshot without a window popping up.
$ python resview.py output-tests/diffusion-poisson.vtk -o image.png –off-screen
• Create animation from output-tests/diffusion-time_poisson.*.vtk.
$ python resview.py output-tests/diffusion-time_poisson.*.vtk -a mov.mp4
• Create animation from output-tests/test_hyperelastic.*.vtk, set frame rate to 3, plot displacements and
mooney_rivlin_stress.
separator = ':'
class resview.OptsToListAction(option_strings, dest, nargs=None, const=None, default=None, type=None,
choices=None, required=False, help=None, metavar=None)
separator = '='
class resview.StoreNumberAction(option_strings, dest, nargs=None, const=None, default=None, type=None,
choices=None, required=False, help=None, metavar=None)
resview.add_mat_id_to_grid(grid, cell_groups)
resview.main()
resview.make_cells_from_conn(conns, convert_to_vtk_type)
resview.parse_options(opts, separator=':')
resview.print_camera_position(plotter)
simple.py script
simple.print_solvers()
simple.print_terms()
simple_homog_mpi.py script
Solve a coupled two-scale problem in parallel. One computational node is solving a macroscopic equation while the
others are solving local microscopic problems and homogenized coefficients.
Run this script as:
simple_homog_mpi.main()
Utility scripts
build_helpers.py script
Notes
The original version of this file was adapted from NiPy project [1].
[1] http://nipy.sourceforge.net/
class build_helpers.Clean(dist)
Distutils Command class to clean, enhanced to clean also files generated during python setup.py build_ext –in-
place.
run()
A command’s raison d’etre: carry out the action it exists to perform, controlled by the options initialized
in ‘initialize_options()’, customized by other commands, the setup script, the command-line, and config
files, and finalized in ‘finalize_options()’. All terminal output and filesystem interaction should be done by
‘run()’.
This method must be implemented by all command classes.
class build_helpers.DoxygenDocs(dist)
finalize_options()
Set final values for all the options that this command supports. This is always called as late as possible, ie.
after any option assignments from the command-line or from other commands have been done. Thus, this
is the place to code option dependencies: if ‘foo’ depends on ‘bar’, then it is safe to set ‘foo’ from ‘bar’ as
long as ‘foo’ still has the same value it was assigned in ‘initialize_options()’.
This method must be implemented by all command classes.
initialize_options()
Set default values for all the options that this command supports. Note that these defaults may be overridden
by other commands, by the setup script, by config files, or by the command-line. Thus, this is not the place
to code dependencies between options; generally, ‘initialize_options()’ implementations are just a bunch
of “self.foo = None” assignments.
This method must be implemented by all command classes.
user_options = [('None', None, 'this command has no options')]
class build_helpers.SphinxHTMLDocs(dist)
build_helpers.have_good_cython()
optional [bool, optional] If False, raise error for absent package or wrong version; otherwise
warn
checker [callable, optional] If given, the callable with which to return a comparable thing from
a version string. The default is pkg_resources.parse_version.
version_getter [callable, optional:] If given, the callable that takes pkg_name as argument, and
returns the package version string - as in:
``version = version_getter(pkg_name)``
messages [dict, optional] If given, the dictionary providing (some of) output messages.
show_only [bool] If True, do not raise exceptions, only show the package name and version
information.
build_helpers.recursive_glob(top_dir, pattern)
Utility function working like glob.glob(), but working recursively and returning generator.
Parameters
topdir [str] The top-level directory.
pattern [str or list of str] The pattern or list of patterns to match.
test_install.py script
Simple script for testing various SfePy functionality, examples not covered by tests, and running the tests.
The script just runs the commands specified in its main() using the subprocess module, captures the output and compares
one or more key words to the expected ones.
The output of failed commands is saved to ‘test_install.log’ file.
test_install.check_output(cmd)
Run the specified command and capture its outputs.
Returns
out [tuple] The (stdout, stderr) output tuple.
test_install.main()
script/blockgen.py script
script/convert_mesh.py script
convert_mesh.main()
script/cylindergen.py script
script/dg_plot_1D.py script
Parameters
folder [str] folder where to look for files
filename [str] used in {name}.i.vtk, i = 0,1, . . . tns - 1
t0 [float] starting time
t1 [int] final time
tn [int] number of time steps
ic_fun [callable] initital condition
exact [callable] exact solution, for transient problems function of space ant time
compare [bool]
polar [bool]
dg_plot_1D.main(argv)
script/edit_identifiers.py script
edit_identifiers.edit(line)
edit_identifiers.main()
edit_identifiers.split_on(token, chars)
edit_identifiers.us2cw(x)
edit_identifiers.us2mc(x)
script/eval_ns_forms.py script
eval_ns_forms.create_scalar_base(name, n_ep)
eval_ns_forms.create_scalar_var_data(name, phi, g, u)
eval_ns_forms.create_u_operator(u, transpose=False)
eval_ns_forms.grad_vector_to_matrix(name, gv)
eval_ns_forms.main()
script/eval_tl_forms.py script
Operators present in the FE discretization of hyperelastic terms in the total Lagrangian formulation.
eval_tl_forms.main()
script/extract_edges.py script
Extract outline edges of a given mesh and save them into ‘<original path>/edge_<original mesh file name>.vtk’ or into
a user defined output file. The outline edge is an edge for which norm(nvec1 - nvec2) < eps, where nvec1 and nvec2
are the normal vectors of the incident facets.
extract_edges.extract_edges(mesh, eps=1e-16)
Extract outline edges of a given mesh. The outline edge is an edge for which norm(nvec_1 - nvec_2) < eps, where
nvec_1 and nvec_2 are the normal vectors of the incident facets.
Parameters
mesh [Mesh] The 3D or 2D mesh.
eps [float] The tolerance parameter of the outline edge searching algorithm.
Returns
mesh_out [tuple] The data of the outline mesh, Mesh.from_data() format, i.e. (coors, ngroups,
ed_conns, mat_ids, descs).
extract_edges.main()
extract_edges.merge_lines(mesh, eps=1e-18)
script/extract_surface.py script
Given a mesh file, this script extracts its surface and prints it to stdout in form of a list where each row is [element, face,
component]. A component corresponds to a contiguous surface region - for example, a cubical mesh with a spherical
hole has two surface components. Two surface faces sharing a single node belong to one component.
With ‘-m’ option, a mesh of the surface is created and saved in ‘<original path>/surf_<original mesh file name>.mesh’.
extract_surface.get_surface_faces(domain)
extract_surface.main()
extract_surface.surface_components(gr_s, surf_faces)
Determine surface components given surface mesh connectivity graph.
extract_surface.surface_graph(surf_faces, n_nod)
script/gen_gallery.py script
Generate the images and rst files for gallery of SfePy examples.
The following steps need to be made to regenerate the documentation with the updated example files:
1. remove doc/examples/*:
$ rm -rf doc/examples/*
gen_gallery.apply_view_options(views, default)
gen_gallery.ebase2fbase(ebase)
script/gen_iga_patch.py script
Generate a single IGA patch block in 2D or 3D of given degrees and continuity using igakit.
The grid has equally-spaced knot vectors.
gen_iga_patch.main()
script/gen_legendre_simplex_base.py script
Generate simplex legendre 2D basis coffecients and exponents matrices and save them to legendre2D_simplex_coefs.txt
and legendre2D_simplex_expos.txt
gen_legendre_simplex_base.main()
script/gen_lobatto1d_c.py script
gen_lobatto1d_c.gen_lobatto(max_order)
gen_lobatto1d_c.main()
script/gen_mesh_prev.py script
Examples
$ ./script/gen_mesh_prev.py meshes/2d/
gen_mesh_prev.gen_shot(vtk_filename, png_filename)
Generate PNG image of the FE mesh.
Parameters
vtk_filename [str] The input mesh filename (file in VTK format).
png_filename [str] The name of the output PNG file.
gen_mesh_prev.main()
script/gen_release_notes.py script
Generate release notes using git log starting from the given version.
gen_release_notes.main()
script/gen_serendipity_basis.py script
script/gen_solver_table.py script
gen_solver_table.main()
gen_solver_table.setup(app)
gen_solver_table.trim(docstring)
Trim and split (doc)string.
gen_solver_table.typeset(fd)
Utility function called by Sphinx.
gen_solver_table.typeset_solvers_table(fd, solver_table)
Generate solvers table ReST output.
script/gen_term_table.py script
gen_term_table.gen_term_table(app)
gen_term_table.get_examples(table)
gen_term_table.main()
gen_term_table.set_section(sec)
gen_term_table.setup(app)
gen_term_table.to_list(slist, sec)
gen_term_table.typeset(filename)
Utility function called by sphinx.
gen_term_table.typeset_examples(term_class, term_use)
gen_term_table.typeset_term_syntax(term_class)
script/plot_condition_numbers.py script
Plot conditions numbers w.r.t. polynomial approximation order of reference element matrices for various FE polynomial
spaces (bases).
plot_condition_numbers.main()
script/plot_logs.py script
plot_logs.main()
script/plot_mesh.py script
Plot mesh connectivities, facet orientations, global and local DOF ids etc.
To switch off plotting some mesh entities, set the corresponding color to None.
plot_mesh.main()
script/plot_quadratures.py script
Plot quadrature points for the given geometry and integration order.
plot_quadratures.main()
script/plot_times.py script
Plot time steps, times of time steps and time deltas in a HDF5 results file.
plot_times.main()
script/save_basis.py script
Save polynomial basis on reference elements or on a mesh for visualization into a given output directory.
save_basis.get_dofs(dofs, n_total)
save_basis.main()
script/show_authors.py script
show_authors.main()
script/show_mesh_info.py script
script/show_terms_use.py script
script/sync_module_docs.py script
Synchronize the documentation files in a given directory doc_dir with the actual state of the SfePy sources in top_dir.
Missing files are created, files with no corresponding source file are removed, other files are left untouched.
Notes
script/tile_periodic_mesh.py script
The program scales a periodic input mesh (a rectangle or box) in filename_in by a scale factor and generates a new
mesh by repeating the scaled original mesh in a regular grid (scale x scale [x scale]) if repeat option is None, or in a
grid nx x ny x nz for repeat ‘nx,ny,nz’, producing again a periodic rectangle or box mesh.
class tile_periodic_mesh.ParseRepeat(option_strings, dest, nargs=None, const=None, default=None,
type=None, choices=None, required=False, help=None,
metavar=None)
tile_periodic_mesh.main()
sfepy package
sfepy.config module
class sfepy.config.Config
compile_flags()
debug_flags()
is_release()
link_flags()
numpydoc_path()
python_include()
python_version()
refmap_memory_factor()
system()
tetgen_path()
sfepy.config.has_attr(obj, attr)
sfepy.version module
sfepy.version.get_basic_info(version='2022.2')
Return SfePy installation directory information. Append current git commit hash to version.
sfepy.applications package
sfepy.applications.application module
call_parametrized(**kwargs)
parametrize(parametric_hook)
Add parametric_hook, set __call__() to call_parametrized().
restore()
Remove parametric_hook, restore __call__() to call_basic().
setup_options()
sfepy.applications.evp_solver_app module
make_full(svecs)
static process_options(options)
Application options setup. Sets default values for missing non-compulsory options.
save_results(eigs, vecs, out=None, mesh_results_name=None, eig_results_name=None)
setup_options()
setup_output()
Setup various file names for the output directory given by self.problem.output_dir.
solve_eigen_problem()
sfepy.applications.pde_solver_app module
call(status=None)
load_dict(filename)
Utility function to load a dictionary data from a HDF5 file filename.
static process_options(options)
Application options setup. Sets default values for missing non-compulsory options.
save_dict(filename, data)
Utility function to save a dictionary data to a HDF5 file filename.
setup_options()
setup_output_info(problem, options)
Modifies both problem and options!
sfepy.applications.pde_solver_app.assign_standard_hooks(obj, get, conf )
Set standard hook function attributes from conf to obj using the get function.
sfepy.applications.pde_solver_app.save_only(conf, save_names, problem=None)
Save information available prior to setting equations and solving them.
sfepy.applications.pde_solver_app.solve_pde(conf, options=None, status=None, **app_options)
Solve a system of partial differential equations (PDEs).
This function is a convenience wrapper that creates and runs an instance of PDESolverApp.
Parameters
conf [str or ProblemConf instance] Either the name of the problem description file defining the
PDEs, or directly the ProblemConf instance.
options [options] The command-line options.
status [dict-like] The object for storing the solver return status.
app_options [kwargs] The keyword arguments that can override application-specific options.
sfepy.base package
sfepy.base.base module
sfepy.base.base.debug(frame=None, frames_back=1)
Start debugger on line where it is called, roughly equivalent to:
First, this function tries to start an IPython-enabled debugger using the IPython API.
When this fails, the plain old pdb is used instead.
With IPython, one can say in what frame the debugger can stop.
class sfepy.base.base.Container(objs=None, **kwargs)
append(obj)
as_dict()
Return stored objects in a dictionary with object names as keys.
extend(objs)
Extend the container items by the sequence objs.
get(ii, default=None, msg_if_none=None)
Get an item from Container - a wrapper around Container.__getitem__() with defaults and custom error
message.
Parameters
ii [int or str] The index or name of the item.
default [any, optional] The default value returned in case the item ii does not exist.
msg_if_none [str, optional] If not None, and if default is None and the item ii does not exist,
raise ValueError with this message.
get_names()
has_key(ii)
insert(ii, obj)
iteritems()
iterkeys()
itervalues()
print_names()
remove_name(name)
update(objs=None)
A dict-like update for Struct attributes.
class sfepy.base.base.IndexedStruct(**kwargs)
find(name, ret_indx=False)
get_names()
print_names()
Examples
get_output_function()
get_output_prefix()
property prefix
set_output(filename=None, quiet=False, combined=False, append=False)
Set the output mode.
If quiet is True, no messages are printed to screen. If simultaneously filename is not None, the messages
are logged into the specified file.
If quiet is False, more combinations are possible. If filename is None, output is to screen only, otherwise it
is to the specified file. Moreover, if combined is True, both the ways are used.
Parameters
filename [str or file object] Print messages into the specified file.
quiet [bool] Do not print anything to screen.
combined [bool] Print both on screen and into the specified file.
append [bool] Append to an existing file instead of overwriting it. Use with filename.
set_output_prefix(prefix)
class sfepy.base.base.Struct(**kwargs)
copy(deep=False, name=None)
Make a (deep) copy of self.
Parameters:
deep [bool] Make a deep copy.
name [str] Name of the copy, with default self.name + ‘_copy’.
get(key, default=None, msg_if_none=None)
A dict-like get() for Struct attributes.
set_default(key, default=None)
Behaves like dict.setdefault().
str_all()
str_class()
As __str__(), but for class attributes.
to_dict()
update(other, **kwargs)
A dict-like update for Struct attributes.
sfepy.base.base.as_float_or_complex(val)
Try to cast val to Python float, and if this fails, to Python complex type.
sfepy.base.base.assert_(condition, msg='assertion failed!')
First, this function tries to start an IPython-enabled debugger using the IPython API.
When this fails, the plain old pdb is used instead.
With IPython, one can say in what frame the debugger can stop.
sfepy.base.base.debug_on_error()
Start debugger at the line where an exception was raised.
sfepy.base.base.dict_extend(d1, d2)
sfepy.base.base.dict_from_keys_init(keys, seq_class=None)
sfepy.base.base.dict_to_array(adict)
Convert a dictionary of nD arrays of the same shapes with non-negative integer keys to a single (n+1)D array.
sfepy.base.base.dict_to_struct(*args, **kwargs)
Convert a dict instance to a Struct instance.
sfepy.base.base.edit_dict_strings(str_dict, old, new, recur=False)
Replace substrings old with new in string values of dictionary str_dict. Both old and new can be lists of the same
length - items in old are replaced by items in new with the same index.
Parameters
str_dict [dict] The dictionary with string values or tuples containing strings.
old [str or list of str] The old substring or list of substrings.
new [str or list of str] The new substring or list of substrings.
recur [bool] If True, edit tuple values recursively.
Returns
new_dict [dict] The dictionary with edited strings.
sfepy.base.base.edit_tuple_strings(str_tuple, old, new, recur=False)
Replace substrings old with new in items of tuple str_tuple. Non-string items are just copied to the new tuple.
Parameters
str_tuple [tuple] The tuple with string values.
old [str] The old substring.
new [str] The new substring.
recur [bool] If True, edit items that are tuples recursively.
Returns
new_tuple [tuple] The tuple with edited strings.
sfepy.base.base.find_subclasses(context, classes, omit_unnamed=False, name_attr='name')
Find subclasses of the given classes in the given context.
Examples
sfepy.base.base.get_arguments(omit=None)
Get a calling function’s arguments.
Returns:
args [dict] The calling function’s arguments.
sfepy.base.base.get_debug()
Utility function providing debug() function.
sfepy.base.base.get_default(arg, default, msg_if_none=None)
sfepy.base.base.get_subdict(adict, keys)
Get a sub-dictionary of adict with given keys.
sfepy.base.base.import_file(filename, package_name=None, can_reload=True)
Import a file as a module. The module is explicitly reloaded to prevent undesirable interactions.
sfepy.base.base.insert_as_static_method(cls, name, function)
sfepy.base.base.insert_method(instance, function)
sfepy.base.base.insert_static_method(cls, function)
sfepy.base.base.ipython_shell(frame=0)
sfepy.base.base.is_derived_class(cls, parent)
sfepy.base.base.is_integer(var)
sfepy.base.base.is_sequence(var)
sfepy.base.base.is_string(var)
sfepy.base.base.iter_dict_of_lists(dol, return_keys=False)
sfepy.base.base.pause(msg=None)
Prints the line number and waits for a keypress.
If you press: “q” . . . . . . . . . . . . . it will call sys.exit() any other key . . . it will continue execution of the program
This is useful for debugging.
sfepy.base.base.print_structs(objs)
Print Struct instances in a container, works recursively. Debugging utility function.
sfepy.base.base.python_shell(frame=0)
sfepy.base.base.remap_dict(d, map)
Utility function to remap state dict keys according to var_map.
sfepy.base.base.select_by_names(objs_all, names, replace=None, simple=True)
sfepy.base.base.set_defaults(dict_, defaults)
sfepy.base.base.shell(frame=0)
Embed an IPython (if available) or regular Python shell in the given frame.
sfepy.base.base.spause(msg=None)
Waits for a keypress.
If you press: “q” . . . . . . . . . . . . . it will call sys.exit() any other key . . . it will continue execution of the program
This is useful for debugging. This function is called from pause().
sfepy.base.base.structify(obj)
Convert a (nested) dict obj into a (nested) Struct.
sfepy.base.base.try_imports(imports, fail_msg=None)
Try import statements until one succeeds.
Parameters
sfepy.base.compat module
This module contains functions that have different names or behavior depending on NumPy and Scipy versions.
sfepy.base.compat.in1d(ar1, ar2, assume_unique=False, invert=False)
Test whether each element of a 1-D array is also present in a second array.
Returns a boolean array the same length as ar1 that is True where an element of ar1 is in ar2 and False otherwise.
We recommend using isin() instead of in1d for new code.
Parameters
ar1 [(M,) array_like] Input array.
ar2 [array_like] The values against which to test each value of ar1.
assume_unique [bool, optional] If True, the input arrays are both assumed to be unique, which
can speed up the calculation. Default is False.
invert [bool, optional] If True, the values in the returned array are inverted (that is, False
where an element of ar1 is in ar2 and True otherwise). Default is False. np.in1d(a, b,
invert=True) is equivalent to (but is faster than) np.invert(in1d(a, b)).
New in version 1.8.0.
Returns
in1d [(M,) ndarray, bool] The values ar1[in1d] are in ar2.
See also:
Notes
in1d can be considered as an element-wise function version of the python keyword in, for 1-D sequences.
in1d(a, b) is roughly equivalent to np.array([item in b for item in a]). However, this idea fails if
ar2 is a set, or similar (non-sequence) container: As ar2 is converted to an array, in those cases asarray(ar2)
is an object array rather than the expected array of contained values.
New in version 1.4.0.
Examples
Parameters
ar [array_like] Input array. Unless axis is specified, this will be flattened if it is not already 1-D.
return_index [bool, optional] If True, also return the indices of ar (along the specified axis, if
provided, or in the flattened array) that result in the unique array.
return_inverse [bool, optional] If True, also return the indices of the unique array (for the spec-
ified axis, if provided) that can be used to reconstruct ar.
return_counts [bool, optional] If True, also return the number of times each unique item appears
in ar.
New in version 1.9.0.
axis [int or None, optional] The axis to operate on. If None, ar will be flattened. If an integer,
the subarrays indexed by the given axis will be flattened and treated as the elements of a 1-D
array with the dimension of the given axis, see the notes for more details. Object arrays or
structured arrays that contain objects are not supported if the axis kwarg is used. The default
is None.
New in version 1.13.0.
Returns
unique [ndarray] The sorted unique values.
unique_indices [ndarray, optional] The indices of the first occurrences of the unique values in
the original array. Only provided if return_index is True.
unique_inverse [ndarray, optional] The indices to reconstruct the original array from the unique
array. Only provided if return_inverse is True.
unique_counts [ndarray, optional] The number of times each of the unique values comes up in
the original array. Only provided if return_counts is True.
New in version 1.9.0.
See also:
numpy.lib.arraysetops Module with a number of other functions for performing set operations on arrays.
repeat Repeat elements of an array.
Notes
When an axis is specified the subarrays indexed by the axis are sorted. This is done by making the specified
axis the first dimension of the array (move the axis to the first dimension to keep the order of the other axes) and
then flattening the subarrays in C order. The flattened subarrays are then viewed as a structured type with each
element given a label, with the effect that we end up with a 1-D array of structured types that can be treated in
the same way as any other 1-D array. The result is that the flattened subarrays are sorted in lexicographic order
starting with the first element.
Examples
Return the indices of the original array that give the unique values:
Reconstruct the input array from the unique values and inverse:
Reconstruct the input values from the unique values and counts:
sfepy.base.conf module
Notes
Short syntax: key is suffixed with ‘__<number>’ to prevent collisions with long syntax keys -> both cases can be used
in a single input.
class sfepy.base.conf.ProblemConf(define_dict, funmod=None, filename=None, required=None,
other=None, verbose=True, override=None, setup=True)
Problem configuration, corresponding to an input (problem description file). It validates the input using lists
of required and other keywords that have to/can appear in the input. Default keyword lists can be obtained by
sfepy.base.conf.get_standard_keywords().
ProblemConf instance is used to construct a Problem instance via Problem.from_conf(conf).
add_missing(conf )
Add missing values from another problem configuration.
Missing keys/values are added also to values that are dictionaries.
Parameters
conf [ProblemConf instance] The other configuration.
edit(key, newval)
The filename can either contain plain definitions, or it can contain the define() function, in which case it
will be called to return the input definitions.
The job of the define() function is to return a dictionary of parameters. How the dictionary is constructed
is not our business, but the usual way is to simply have a function define() along these lines in the input file:
def define():
options = {
'save_eig_vectors' : None,
'eigen_solver' : 'eigen1',
}
region_2 = {
'name' : 'Surface',
'select' : 'nodes of surface',
}
return locals()
Optionally, the define() function can accept additional arguments that should be defined using the de-
fine_args tuple or dictionary.
static from_file_and_options(filename, options, required=None, other=None, verbose=True,
define_args=None, setup=True)
Utility function, a wrapper around ProblemConf.from_file() with possible override taken from options.
static from_module(module, required=None, other=None, verbose=True, override=None, setup=True)
get_function(name)
Get a function object given its name.
It can be either in ProblemConf.funmod, or a ProblemConf attribute directly.
Parameters
name [str or function or None] The function name or directly the function.
Returns
fun [function or None] The required function, or None if name was None.
get_item_by_name(key, item_name)
Return item with name item_name in configuration group given by key.
get_raw(key=None)
transform_input()
transform_input_trivial()
Trivial input transformations.
update_conf(conf )
Update configuration by values in another problem configuration.
Values that are dictionaries are updated in-place by dict.update().
Parameters
conf [ProblemConf instance] The other configuration.
validate(required=None, other=None)
sfepy.base.conf.dict_from_options(options)
Return a dictionary that can be used to construct/override a ProblemConf instance based on options.
See --conf and --options options of the simple.py script.
sfepy.base.conf.dict_from_string(string, allow_tuple=False, free_word=False)
Parse string and return a dictionary that can be used to construct/override a ProblemConf instance.
sfepy.base.conf.get_standard_keywords()
sfepy.base.conf.transform_conditions(adict, prefix)
sfepy.base.conf.transform_dgebcs(adict)
sfepy.base.conf.transform_dgepbcs(adict)
sfepy.base.conf.transform_ebcs(adict)
sfepy.base.conf.transform_epbcs(adict, prefix='epbc')
sfepy.base.conf.transform_fields(adict)
sfepy.base.conf.transform_functions(adict)
sfepy.base.conf.transform_ics(adict)
sfepy.base.conf.transform_integrals(adict)
sfepy.base.conf.transform_lcbcs(adict)
sfepy.base.conf.transform_materials(adict)
sfepy.base.conf.transform_regions(adict)
sfepy.base.conf.transform_solvers(adict)
sfepy.base.conf.transform_to_i_struct_1(adict)
sfepy.base.conf.transform_to_struct_01(adict)
sfepy.base.conf.transform_to_struct_1(adict)
sfepy.base.conf.transform_to_struct_10(adict)
sfepy.base.conf.transform_variables(adict)
sfepy.base.getch module
getch()-like unbuffered character reading from stdin on both Windows and Unix
_Getch classes inspired by Danny Yoo, iskeydown() based on code by Zachary Pincus.
sfepy.base.goptions module
Notes
sfepy.base.ioutils module
class sfepy.base.ioutils.Cached(data)
The wrapper class that marks data, that should be checked during saving, whether it has been stored to the hdf5
file already and if so, a softlink to the already created instance is created instead of saving.
class sfepy.base.ioutils.DataMarker(data)
The Base class for classes for marking data to be handled in a special way during saving to a HDF5 file by
write_to_hdf5(). The usage is simple: just “decorate” the desired data element, e.g.:
unpack_data()
One can request unpacking of the wrappers during saving.
Returns
object The original object, if possible, or self.
unpack_data()
One can request unpacking of the wrappers during saving.
Returns
object The original object, if possible, or self.
write_data(fd, group, cache=None)
Create the softlink to the destination and handle the caching.
class sfepy.base.ioutils.HDF5BaseData
When storing values to HDF5, special classes can be used that wrap the stored data and modify the way the
storing is done. This class is the base of those.
unpack_data()
One can request unpacking of the wrappers during saving.
Returns
object The original object, if possible, or self.
class sfepy.base.ioutils.HDF5ContextManager(filename, *args, **kwargs)
class sfepy.base.ioutils.HDF5Data
Some data written to the HDF5 file can have a custom format. Descendants of this class should have the method
.write_data() or redefine the .write() method.
write(fd, group, name, cache=None)
Write a data structure to the HDF5 file.
Create the following structure in the HDF5 file: {type: self.get_type(), anything writed by self.write_data()}
Parameters
fd: tables.File The hdf5 file handle the data should be writed in.
group: tables.group.Group The group the data will be stored to
name: str Name of node that will be appended to group and will contain the data
cache: dict or None, optional Store for already cached objects with structs id(obj) : /path/to
Can be used for not storing the one object twice.
write_data(fd, group)
Write data to the HDF5 file. Redefine this function in sub-classes.
Parameters
fd: tables.File The hdf5 file handle the data should be writed to.
group: tables.group.Group The group the data should be stored to.
class sfepy.base.ioutils.InDir(filename)
Store the directory name a file is in, and prepend this name to other files.
Examples
class sfepy.base.ioutils.SoftLink(destination)
This object is written to the HDF5 file as a softlink to the given path.
write(fd, group, name, cache=None)
Create the softlink to the destination.
class sfepy.base.ioutils.Uncached(data)
The wrapper class that marks data, that should be always stored to the hdf5 file, even if the object has been already
stored at a different path in the file and so it would have been stored by a softlink otherwise (IGDomain, Mesh
and sparse matrices behave so).
sfepy.base.ioutils.dec(val, encoding='utf-8')
Decode given bytes using the specified encoding.
sfepy.base.ioutils.edit_filename(filename, prefix='', suffix='', new_ext=None)
Edit a file name by add a prefix, inserting a suffix in front of a file name extension or replacing the extension.
Parameters
filename [str] The file name.
prefix [str] The prefix to be added.
suffix [str] The suffix to be inserted.
new_ext [str, optional] If not None, it replaces the original file name extension.
Returns
new_filename [str] The new file name.
sfepy.base.ioutils.enc(string, encoding='utf-8')
Encode given string or bytes using the specified encoding.
sfepy.base.ioutils.ensure_path(filename)
Check if path to filename exists and if not, create the necessary intermediate directories.
sfepy.base.ioutils.get_or_create_hdf5_group(fd, path, from_group=None)
sfepy.base.ioutils.get_print_info(n_step, fill=None)
Returns the max. number of digits in range(n_step) and the corresponding format string.
Examples:
>>> get_print_info(11)
(2, '%2d')
>>> get_print_info(8)
(1, '%1d')
>>> get_print_info(100)
(2, '%2d')
>>> get_print_info(101)
(3, '%3d')
>>> get_print_info(101, fill='0')
(3, '%03d')
sfepy.base.ioutils.get_trunk(filename)
output_format: {‘csr’, ‘csc’, None}, optional The resulting matrix will be in CSR or CSC for-
mat if this parameter is not None (which is default), otherwise it will be in the format the
matrix was stored.
Returns
scipy.sparse.base.spmatrix Readed matrix
sfepy.base.ioutils.read_sparse_matrix_hdf5(filename, output_format=None)
sfepy.base.ioutils.read_token(fd)
Read a single token (sequence of non-whitespace characters) from the given file object.
Notes
name: str The name of the node that will be appended to the group and will contain the data.
data: object Data to be stored in the HDF5 file.
cache: dict or None The cache where the paths to stored objects (currently meshes and iga do-
mains) are stored, so subsequent attempts to store such objects create only softlinks to the
initially stored object. The id() of objects serve as the keys into the cache. Mark the object
with Cached() or Uncached() for (no) softlinking.
unpack_markers: If True, the input data is modified so that Cached and Uncached markers are
removed from all sub-elements of the data.
Returns
tables.group.Group The HDF5 group the data was stored to.
sfepy.base.log module
Parameters
data_names [list of lists of str] The data names grouped by subplots: [[name1, name2, . . . ],
[name3, name4, . . . ], . . . ], where name<n> are strings to display in (sub)plot legends.
get_log_name()
plot_data(igs)
plot_vlines(igs=None, **kwargs)
Plot vertical lines in axes given by igs at current x locations to mark some events.
terminate()
sfepy.base.log.get_logging_conf(conf, log_name='log')
Check for a log configuration (‘log’ attribute by default) in conf. Supply default values if necessary.
Parameters
conf [Struct] The configuration object.
log_name [str, optional] The name of the log configuration attribute in conf.
Returns
log [dict] The dictionary {‘plot’ : <figure_file>, ‘text’ : <text_log_file>}. One or both values
can be None.
sfepy.base.log.iter_names(data_names, igs=None)
sfepy.base.log_plotter module
make_axes()
output = Output
poll_draw()
process_command(command)
terminate()
sfepy.base.mem_usage module
sfepy.base.multiproc module
Multiprocessing functions.
sfepy.base.multiproc.get_multiproc(mpi=False)
sfepy.base.multiproc.get_num_workers()
Get the number of slave nodes.
sfepy.base.multiproc.is_remote_dict(d)
sfepy.base.multiproc_mpi module
Multiprocessing functions.
class sfepy.base.multiproc_mpi.MPIFileHandler(filename, mode=4, encoding=None, delay=0,
comm=<mpi4py.MPI.Intracomm object>)
MPI file class for logging process communication.
close()
Closes the stream.
class sfepy.base.multiproc_mpi.MPILogFile
write(*args, **kwargs)
keys()
update(other)
remote_get_in(key, slave)
remote_get_keys(slave)
remote_get_len(slave)
release()
class sfepy.base.multiproc_mpi.RemoteQueue(name)
Remote queue class - slave side.
get()
put(value)
get()
static get_gdict_key(name)
put(value)
remote_get(slave)
remote_put(value, slave)
sfepy.base.multiproc_mpi.cpu_count()
Get the number of MPI nodes.
sfepy.base.multiproc_mpi.enum(*sequential)
sfepy.base.multiproc_mpi.set_logging_level(log_level='info')
sfepy.base.multiproc_mpi.slave_get_task(name='')
Start the slave nodes.
sfepy.base.multiproc_mpi.slave_task_done(task='')
Stop the slave nodes.
sfepy.base.multiproc_mpi.tags
alias of sfepy.base.multiproc_mpi.Enum
sfepy.base.multiproc_mpi.wait_for_tag(wtag, num=1)
sfepy.base.multiproc_proc module
get()
put(value)
sfepy.base.multiproc_proc.is_remote_dict(d)
Return True if ‘d’ is instance.
sfepy.base.parse_conf module
sfepy.base.parse_conf.cvt_array_index(toks)
sfepy.base.parse_conf.cvt_cmplx(toks)
sfepy.base.parse_conf.cvt_int(toks)
sfepy.base.parse_conf.cvt_none(toks)
sfepy.base.parse_conf.cvt_real(toks)
sfepy.base.parse_conf.list_of(element, *elements)
Return lexical element that parses a list of items. The items can be a one or several lexical elements. For example,
result of list_of(real, integer) parses list of real or integer numbers.
sfepy.base.plotutils module
sfepy.base.plotutils.font_size(size)
sfepy.base.plotutils.iplot(*args, **kwargs)
sfepy.base.plotutils.set_axes_font_size(ax, size)
sfepy.base.reader module
class sfepy.base.reader.Reader(directory)
Reads and executes a Python file as a script with execfile(), storing its locals. Then sets the __dict__ of a new
instance of obj_class to the stored locals.
Example:
>>> class A:
>>> pass
It is equivalent to:
sfepy.base.resolve_deps module
sfepy.base.testing module
class sfepy.base.testing.NLSStatus(**kwargs)
Custom nonlinear solver status storing stopping condition of all time steps.
sfepy.base.testing.assert_equal(a, b, msg='assertion of equality failed!')
sfepy.base.testing.check_conditions(conditions)
sfepy.base.testing.eval_coor_expression(expression, coor)
sfepy.base.testing.report(*argc)
All tests should print via this function.
sfepy.base.testing.run_declaratice_example(ex_filename, output_dir, ext='.vtk', remove_prefix='')
Run a declarative example in ex_filename given relatively to sfepy.base_dir.
sfepy.base.timing module
reset()
start(reset=False)
stop()
sfepy.discrete package
sfepy.discrete.conditions module
The Dirichlet, periodic and linear combination boundary condition classes, as well as the initial condition class.
class sfepy.discrete.conditions.Condition(name, **kwargs)
Common boundary condition methods.
canonize_dof_names(dofs)
Canonize the DOF names using the full list of DOFs of a variable.
Assumes single condition instance.
iter_single()
Create a single condition instance for each item in self.dofs and yield it.
class sfepy.discrete.conditions.Conditions(objs=None, **kwargs)
Container for various conditions.
canonize_dof_names(dofs)
Canonize the DOF names using the full list of DOFs of a variable.
static from_conf(conf, regions)
group_by_variables(groups=None)
Group boundary conditions of each variable. Each condition is a group is a single condition.
Parameters
groups [dict, optional] If present, update the groups dictionary.
Returns
out [dict] The dictionary with variable names as keys and lists of single condition instances
as values.
sort()
Sort boundary conditions by their key.
zero_dofs()
Set all boundary condition values to zero, if applicable.
sfepy.discrete.equations module
collect_conn_info(conn_info)
collect_materials()
Collect materials present in the terms of the equation.
collect_variables()
Collect variables present in the terms of the equation.
Ensures that corresponding primary variables of test/parameter variables are always in the list, even if they
are not directly used in the terms.
evaluate(mode='eval', dw_mode='vector', term_mode=None, asm_obj=None)
Parameters
mode [one of ‘eval’, ‘el_eval’, ‘el_avg’, ‘qp’, ‘weak’] The evaluation mode.
static from_desc(name, desc, variables, regions, materials, integrals, user=None, eterm_options=None)
class sfepy.discrete.equations.Equations(equations)
add_equation(equation)
Add a new equation.
Parameters
equation [Equation instance] The new equation.
advance(ts)
apply_ebc(vec=None, force_values=None)
Apply essential (Dirichlet) boundary conditions to equations’ variables, or a given vector.
apply_ic(vec=None, force_values=None)
Apply initial conditions to equations’ variables, or a given vector.
collect_conn_info()
Collect connectivity information as defined by the equations.
collect_materials()
Collect materials present in the terms of all equations.
collect_variables()
Collect variables present in the terms of all equations.
create_matrix_graph(any_dof_conn=False, rdcs=None, cdcs=None, shape=None, active_only=True,
verbose=True)
Create tangent matrix graph, i.e. preallocate and initialize the sparse storage needed for the tangent matrix.
Order of DOF connectivities is not important.
Parameters
any_dof_conn [bool] By default, only volume DOF connectivities are used, with the ex-
ception of trace surface DOF connectivities. If True, any kind of DOF connectivities is
allowed.
rdcs, cdcs [arrays, optional] Additional row and column DOF connectivities, corresponding
to the variables used in the equations.
shape [tuple, optional] The required shape, if it is different from the shape determined by the
equations variables. This may be needed if additional row and column DOF connectivities
are passed in.
active_only [bool] If True, the matrix graph has reduced size and is created with the reduced
(active DOFs only) numbering.
verbose [bool] If False, reduce verbosity.
Returns
matrix [csr_matrix] The matrix graph in the form of a CSR matrix with preallocated struc-
ture and zero data.
create_reduced_vec()
create_subequations(var_names, known_var_names=None)
Create sub-equations containing only terms with the given virtual variables.
Parameters
var_names [list] The list of names of virtual variables.
known_var_names [list] The list of names of (already) known state variables.
Returns
subequations [Equations instance] The sub-equations.
create_vec()
get_domain()
get_variable(name)
get_variable_dependencies()
For each virtual variable get names of state/parameter variables that are present in terms with that virtual
variable.
The virtual variables define the actual equations and their dependencies define the variables needed to
evaluate the equations.
Returns
deps [dict] The dependencies as a dictionary with virtual variable names as keys and sets of
state/parameter variables as values.
get_variable_names()
Return the list of names of all variables used in equations.
init_state(vec=None)
init_time(ts)
invalidate_term_caches()
Invalidate evaluate caches of variables present in equations.
make_full_vec(svec, force_value=None)
Make a full DOF vector satisfying E(P)BCs from a reduced DOF vector.
print_terms()
Print names of equations and their terms.
reduce_vec(vec, follow_epbc=False)
Get the reduced DOF vector, with EBC and PBC DOFs removed.
Notes
If ‘follow_epbc’ is True, values of EPBC master dofs are not simply thrown away, but added to the corre-
sponding slave dofs, just like when assembling. For vectors with state (unknown) variables it should be set
to False, for assembled vectors it should be set to True.
reset_materials()
Clear material data so that next materials.time_update() is performed even for stationary materials.
set_data(data, step=0, ignore_unknown=False)
Set data (vectors of DOF values) of variables.
Parameters
data [dict] The dictionary of {variable_name : data vector}.
step [int, optional] The time history step, 0 (default) = current.
ignore_unknown [bool, optional] Ignore unknown variable names if data is a dict.
set_state(vec, reduced=False, force=False, preserve_caches=False)
setup_initial_conditions(ics, functions=None)
sfepy.discrete.evaluate module
make_full_vec(vec)
conf_equations = {
'A,v,u' : "dw_lin_elastic.i1.Y2( inclusion.D, v, u )",
}
Notes
mode [one of ‘eval’, ‘el_avg’, ‘qp’, ‘weak’] The evaluation mode - ‘weak’ means the finite el-
ement assembling, ‘qp’ requests the values in quadrature points, ‘el_avg’ element averages
and ‘eval’ means integration over each term region.
dw_mode [‘vector’ or ‘matrix’] The assembling mode for ‘weak’ evaluation mode.
term_mode [str] The term call mode - some terms support different call modes and depending
on the call mode different values are returned.
active_only [bool] If True, in ‘weak’ mode, the (tangent) matrices and residual vectors (right-
hand sides) contain only active DOFs.
verbose [bool] If False, reduce verbosity.
Returns
out [dict or result] The evaluation result. In ‘weak’ mode it is the vector or sparse matrix, de-
pending on dw_mode. Otherwise, it is a dict of results with equation names as keys or a
single result for a single equation.
sfepy.discrete.evaluate.eval_in_els_and_qp(expression, iels, coors, fields, materials, variables,
functions=None, mode='eval', term_mode=None,
extra_args=None, active_only=True, verbose=True,
kwargs=None)
Evaluate an expression in given elements and points.
Parameters
expression [str] The expression to evaluate.
fields [dict] The dictionary of fields used in variables.
materials [Materials instance] The materials used in the expression.
variables [Variables instance] The variables used in the expression.
functions [Functions instance, optional] The user functions for materials etc.
mode [one of ‘eval’, ‘el_avg’, ‘qp’] The evaluation mode - ‘qp’ requests the values in quadrature
points, ‘el_avg’ element averages and ‘eval’ means integration over each term region.
term_mode [str] The term call mode - some terms support different call modes and depending
on the call mode different values are returned.
extra_args [dict, optional] Extra arguments to be passed to terms in the expression.
active_only [bool] If True, in ‘weak’ mode, the (tangent) matrices and residual vectors (right-
hand sides) contain only active DOFs.
verbose [bool] If False, reduce verbosity.
kwargs [dict, optional] The variables (dictionary of (variable name) : (Variable instance)) to be
used in the expression.
Returns
out [array] The result of the evaluation.
sfepy.discrete.evaluate_variable module
sfepy.discrete.functions module
set_function(function, is_constant=False)
sfepy.discrete.functions.make_sfepy_function(fun_or_name=None)
Convenience decorator to quickly create sfepy.discrete.functions.Function objects.
Has two modes of use either without parameter:
@make_sfepy_function
def my_function(...):
...
or with name:
@make_sfepy_function("new_name_for_my_function")
def my_function(...):
...
Parameters
fun_or_name [string, optional] Name to be saved within Function instance, if None name of
decorated function is used.
Returns
new_fun [sfepy.discrete.functions.Function] With attribute name set to provided name or origi-
nal function name.
sfepy.discrete.integrals module
Classes for accessing quadrature points and weights for various reference element geometries.
class sfepy.discrete.integrals.Integral(name, order=1, coors=None, weights=None, bounds=None,
tp_fix=1.0, weight_fix=1.0, symmetric=False)
Wrapper class around quadratures.
get_qp(geometry)
Get quadrature point coordinates and corresponding weights for given geometry. For built-in quadratures,
the integration order is given by self.order.
Parameters
geometry [str] The geometry key describing the integration domain, see the keys of
sfepy.discrete.quadratures.quadrature_tables.
Returns
coors [array] The coordinates of quadrature points.
weights: array The quadrature weights.
integrate(function, order=1, geometry='1_2')
Integrate numerically a given scalar function.
Parameters
function [callable(coors)] The function of space coordinates to integrate.
order [int, optional] The integration order. For tensor product geometries, this is the 1D
(line) order.
geometry [str] The geometry key describing the integration domain. Default is
‘1_2’, i.e. a line integral in [0, 1]. For other values see the keys of
sfepy.discrete.quadratures.quadrature_tables.
Returns
val [float] The value of the integral.
class sfepy.discrete.integrals.Integrals(objs=None, **kwargs)
Container for instances of Integral.
static from_conf(conf )
get(name)
Return existing or new integral.
Parameters
name [str] The name can either be a non-negative integer, a string representation of a non-
negative integer (the integral order) or ‘a’ (automatic order) or a string beginning with ‘i’
(existing custom integral name).
sfepy.discrete.materials module
material_2 = {
'name' : 'm',
'values' : {'E' : 1.0},
}
Material parameters are passed to terms using the dot notation, i.e. ‘m.E’ in our example case.
static from_conf(conf, functions)
Construct Material instance from configuration.
get_constant_data(name)
Get constant data by name.
get_data(key, name)
name can be a dict - then a Struct instance with data as attributes named as the dict keys is returned.
get_keys(region_name=None)
Get all data keys.
Parameters
region_name [str] If not None, only keys with this region are returned.
iter_terms(equations, only_new=True)
Iterate terms for which the material data should be evaluated.
reduce_on_datas(reduce_fun, init=0.0)
For non-special values only!
reset()
Clear all data created by a call to time_update(), set self.mode to None.
set_all_data(datas)
Use the provided data, set mode to ‘user’.
set_data(key, qps, data)
Set the material data in quadrature points.
Parameters
key [tuple] The (region_name, integral_name) data key.
qps [Struct] Information about the quadrature points.
data [dict] The material data.
set_extra_args(**extra_args)
Extra arguments passed tu the material function.
set_function(function)
sfepy.discrete.parse_equations module
class sfepy.discrete.parse_equations.TermParse
sfepy.discrete.parse_equations.collect_term(term_descs, lc)
sfepy.discrete.parse_equations.create_bnf(term_descs)
term_descs .. list of TermParse objects (sign, term_name, term_arg_names), where sign can be real or complex
multiplier
sfepy.discrete.parse_equations.rhs(lc)
sfepy.discrete.parse_regions module
Notes
sfepy.discrete.parse_regions.print_leaf(level, op)
sfepy.discrete.parse_regions.print_stack(stack)
sfepy.discrete.parse_regions.replace(what, keep=False)
sfepy.discrete.parse_regions.replace_with_region(what, r_index)
sfepy.discrete.parse_regions.to_stack(stack)
sfepy.discrete.probes module
report()
Report the probe parameters.
class sfepy.discrete.probes.Probe(name, share_geometry=True, n_point=None, **kwargs)
Base class for all point probes. Enforces two points minimum.
cache = Struct:probe_shared_evaluate_cache
get_actual_cache(pars, cache, hash_chunk_size=100000)
Return the actual evaluate cache, which is a combination of the (mesh-based) evaluate cache and probe-
specific data, like the reference element coordinates. The reference element coordinates are reused, if the
sha1 hash of the probe parameter vector does not change.
get_evaluate_cache()
Return the evaluate cache for domain-related data given by self.share_geometry.
is_cyclic = False
probe(variable, mode='val', ret_points=False)
Probe the given variable.
Parameters
variable [Variable instance] The variable to be sampled along the probe.
mode [{‘val’, ‘grad’}, optional] The evaluation mode: the variable value (default) or the
variable value gradient.
ret_points [bool] If True, return also the probe points.
Returns
pars [array] The parametrization of the probe points.
points [array, optional] If ret_points is True, the coordinates of points corresponding to pars,
where the variable is evaluated.
vals [array] The probed values.
static refine_pars(pars, refine_flag, cyclic_val=None)
Refine the probe parametrization based on the refine_flag.
refine_points(variable, points, cells)
Mark intervals between points for a refinement, based on element sizes at those points. Assumes the points
to be ordered.
Returns
refine_flag [bool array] True at places corresponding to intervals between subsequent points
that need to be refined.
report()
Report the probe parameters.
reset_refinement()
Reset the probe refinement state.
set_n_point(n_point)
Set the number of probe points.
Parameters
n_point [int] The (fixed) number of probe points, when positive. When non-positive, the
number of points is adaptively increased starting from -n_point, until the neighboring point
distance is less than the diameter of the elements enclosing the points. When None, it is
set to -10.
set_options(close_limit=None, size_hint=None)
Set the probe options.
Parameters
close_limit [float] The maximum limit distance of a point from the closest element allowed
for extrapolation.
size_hint [float] Element size hint for the refinement of probe parametrization.
class sfepy.discrete.probes.RayProbe(p0, dirvec, p_fun, n_point, both_dirs, share_geometry=True)
Probe variables along a ray. The points are parametrized by a function of radial coordinates from a given point
in a given direction.
gen_points(sign)
Generate the probe points and their parametrization.
get_points(refine_flag=None)
Get the probe points.
Returns
pars [array_like] The independent coordinate of the probe.
points [array_like] The probe points, parametrized by pars.
refine_points(variable, points, cache)
No refinement for this probe.
report()
Report the probe parameters.
sfepy.discrete.probes.get_data_name(fd)
Try to read next data name in file fd.
Returns
name [str] The data name.
nc [int] The number of data columns.
sfepy.discrete.probes.read_header(fd)
Read the probe data header from file descriptor fd.
Returns
header [Struct instance] The probe data header.
sfepy.discrete.probes.read_results(filename, only_names=None)
Read probing results from a file.
Parameters
filename [str or file object] The probe results file name.
Returns
header [Struct instance] The probe data header.
results [dict] The dictionary of probing results. Keys are data names, values are the probed
values.
sfepy.discrete.probes.write_results(filename, probe, results)
Write probing results into a file.
Parameters
filename [str or file object] The output file name.
probe [Probe subclass instance] The probe used to obtain the results.
results [dict] The dictionary of probing results. Keys are data names, values are the probed
values.
sfepy.discrete.problem module
Notes
The Problem is by default created with active_only set to True. Then the (tangent) matrices and residual vectors
(right-hand sides) have reduced sizes and contain only the active DOFs, i.e., DOFs not constrained by EBCs or
EPBCs.
Setting active_only to False results in full-size vectors and matrices. Then the matrix size non-zeros structure
does not depend on the actual E(P)BCs applied. It must be False when using parallel PETSc solvers.
The active DOF connectivities contain all DOFs, with the E(P)BC-constrained ones stored as -1 - <DOF num-
ber>, so that the full connectivities can be reconstructed for the matrix graph creation. However, the negative
entries mean that the assembled matrices/residuals have zero values at positions corresponding to constrained
DOFs.
The resulting linear system then provides a solution increment, that has to be added to the initial guess used to
compute the residual, just like in the Newton iterations. The increment of the constrained DOFs is automatically
zero.
When solving with a direct solver, the diagonal entries of a matrix at positions corresponding to con-
strained DOFs has to be set to ones, so that the matrix is not singular, see sfepy.discrete.evaluate.
apply_ebc_to_matrix(), which is called automatically in sfepy.discrete.evaluate.Evaluator.
eval_tangent_matrix(). It is not called automatically in Problem.evaluate(). Note that setting the diag-
onal entries to one might not be necessary with iterative solvers, as the zero matrix rows match the zero residual
rows, i.e. if the reduced matrix would be regular, then the right-hand side (the residual) is orthogonal to the
kernel of the matrix.
advance(ts=None)
copy(name=None)
Make a copy of Problem.
create_evaluable(expression, try_equations=True, auto_init=False, preserve_caches=False,
copy_materials=True, integrals=None, ebcs=None, epbcs=None, lcbcs=None, ts=None,
functions=None, mode='eval', var_dict=None, strip_variables=True, extra_args=None,
active_only=True, eterm_options=None, verbose=True, **kwargs)
Create evaluable object (equations and corresponding variables) from the expression string. Convenience
function calling create_evaluable() with defaults provided by the Problem instance self.
The evaluable can be repeatedly evaluated by calling eval_equations(), e.g. for different values of
variables.
Parameters
expression [str] The expression to evaluate.
try_equations [bool] Try to get variables from self.equations. If this fails, variables can ei-
ther be provided in var_dict, as keyword arguments, or are created automatically according
to the expression.
auto_init [bool] Set values of all variables to all zeros.
preserve_caches [bool] If True, do not invalidate evaluate caches of variables.
copy_materials [bool] Work with a copy of self.equations.materials instead of reusing them.
Safe but can be slow.
integrals [Integrals instance, optional] The integrals to be used. Automatically created as
needed if not given.
ebcs [Conditions instance, optional] The essential (Dirichlet) boundary conditions for ‘weak’
mode. If not given, self.ebcs are used.
epbcs [Conditions instance, optional] The periodic boundary conditions for ‘weak’ mode. If
not given, self.epbcs are used.
lcbcs [Conditions instance, optional] The linear combination boundary conditions for ‘weak’
mode. If not given, self.lcbcs are used.
ts [TimeStepper instance, optional] The time stepper. If not given, self.ts is used.
functions [Functions instance, optional] The user functions for boundary conditions, mate-
rials etc. If not given, self.functions are used.
mode [one of ‘eval’, ‘el_avg’, ‘qp’, ‘weak’] The evaluation mode - ‘weak’ means the finite el-
ement assembling, ‘qp’ requests the values in quadrature points, ‘el_avg’ element averages
and ‘eval’ means integration over each term region.
var_dict [dict, optional] The variables (dictionary of (variable name) : (Variable instance))
to be used in the expression. Use this if the name of a variable conflicts with one of the
parameters of this method.
strip_variables [bool] If False, the variables in var_dict or kwargs not present in the expres-
sion are added to the actual variables as a context.
extra_args [dict, optional] Extra arguments to be passed to terms in the expression.
active_only [bool] If True, in ‘weak’ mode, the (tangent) matrices and residual vectors (right-
hand sides) contain only active DOFs.
eterm_options [dict, optional] The einsum-based terms evaluation options.
verbose [bool] If False, reduce verbosity.
**kwargs [keyword arguments] Additional variables can be passed as keyword arguments,
see var_dict.
Returns
equations [Equations instance] The equations that can be evaluated.
variables [Variables instance] The corresponding variables. Set their values and use
eval_equations().
Examples
vec is a vector of coefficients compatible with the field of ‘u’ - let’s use all ones.
create_materials(mat_names=None)
Create materials with names in mat_names. Their definitions have to be present in self.conf.materials.
Notes
This method does not change self.equations, so it should not have any side effects.
create_state()
create_subproblem(var_names, known_var_names)
Create a sub-problem with equations containing only terms with the given virtual variables.
Parameters
var_names [list] The list of names of virtual variables.
known_var_names [list] The list of names of (already) known state variables.
Returns
subpb [Problem instance] The sub-problem.
create_variables(var_names=None)
Create variables with names in var_names. Their definitions have to be present in self.conf.variables.
Notes
This method does not change self.equations, so it should not have any side effects.
eval_equations(names=None, preserve_caches=False, mode='eval', dw_mode='vector', term_mode=None,
active_only=True, verbose=True)
Evaluate (some of) the problem’s equations, convenience wrapper of eval_equations().
Parameters
names [str or sequence of str, optional] Evaluate only equations of the given name(s).
preserve_caches [bool] If True, do not invalidate evaluate caches of variables.
mode [one of ‘eval’, ‘el_avg’, ‘qp’, ‘weak’] The evaluation mode - ‘weak’ means the finite el-
ement assembling, ‘qp’ requests the values in quadrature points, ‘el_avg’ element averages
and ‘eval’ means integration over each term region.
dw_mode [‘vector’ or ‘matrix’] The assembling mode for ‘weak’ evaluation mode.
term_mode [str] The term call mode - some terms support different call modes and depend-
ing on the call mode different values are returned.
verbose [bool] If False, reduce verbosity.
Returns
out [dict or result] The evaluation result. In ‘weak’ mode it is the vector or sparse matrix,
depending on dw_mode. Otherwise, it is a dict of results with equation names as keys or a
single result for a single equation.
evaluate(expression, try_equations=True, auto_init=False, preserve_caches=False, copy_materials=True,
integrals=None, ebcs=None, epbcs=None, lcbcs=None, ts=None, functions=None, mode='eval',
dw_mode='vector', term_mode=None, var_dict=None, strip_variables=True, ret_variables=False,
active_only=True, eterm_options=None, verbose=True, extra_args=None, **kwargs)
Evaluate an expression, convenience wrapper of Problem.create_evaluable() and
eval_equations().
Parameters
dw_mode [‘vector’ or ‘matrix’] The assembling mode for ‘weak’ evaluation mode.
term_mode [str] The term call mode - some terms support different call modes and depend-
ing on the call mode different values are returned.
ret_variables [bool] If True, return the variables that were created to evaluate the expression.
other [arguments] See docstrings of Problem.create_evaluable().
Returns
out [array] The result of the evaluation.
variables [Variables instance] The variables that were created to evaluate the expression.
Only provided if ret_variables is True.
static from_conf(conf, init_fields=True, init_equations=True, init_solvers=True)
get_dim(get_sym=False)
Returns mesh dimension, symmetric tensor dimension (if get_sym is True).
get_ebc_indices()
Get indices of E(P)BC-constrained DOFs in the full global state vector.
get_evaluator(reuse=False)
Either create a new Evaluator instance (reuse == False), or return an existing instance, created in a preceding
call to Problem.init_solvers().
get_initial_state(vec=None)
Create a zero state and apply initial conditions.
get_integrals(names=None)
Get integrals, initialized from problem configuration if available.
Parameters
names [list, optional] If given, only the named integrals are returned.
Returns
integrals [Integrals instance] The requested integrals.
get_ls()
get_materials()
get_mesh_coors(actual=False)
get_nls()
get_nls_functions()
Returns functions to be used by a nonlinear solver to evaluate the nonlinear function value (the residual)
and its gradient (the tangent matrix) corresponding to the problem equations.
Returns
get_solver_conf(name)
get_timestepper()
get_tss()
status [dict-like, IndexedStruct, optional] The user-supplied object to hold the time-
stepping/nonlinear solver convergence statistics.
ls_conf [Struct, optional] The linear solver options.
nls_conf [Struct, optional] The nonlinear solver options.
force [bool] If True, re-create the solver instances even if they already exist in self.nls at-
tribute.
init_time(ts)
is_linear()
load_restart(filename, ts=None)
Load the current state and time step from a restart file.
Alternatively, a regular output file in the HDF5 format can be used in place of the restart file. In that case
the restart is only approximate, because higher order field DOFs (if any) were stripped out. Files with the
adaptive linearization are not supported. Use with caution!
Parameters
filename [str] The restart file name.
ts [TimeStepper instance, optional] The time stepper. If not given, a default one is created.
Otherwise, it is modified in place.
Returns
variables [Variables instance] The loaded variables.
refine_uniformly(level)
Refine the mesh uniformly level-times.
Notes
This operation resets almost everything (fields, equations, . . . ) - it is roughly equivalent to creating a new
Problem instance with the refined mesh.
remove_bcs()
Convenience function to remove boundary conditions.
reset()
save_regions(filename_trunk, region_names=None)
Save regions as meshes.
Parameters
filename_trunk [str] The output filename without suffix.
region_names [list, optional] If given, only the listed regions are saved.
save_regions_as_groups(filename_trunk, region_names=None)
Save regions in a single mesh but mark them by using different element/node group numbers.
See Domain.save_regions_as_groups() for more details.
Parameters
filename_trunk [str] The output filename without suffix.
region_names [list, optional] If given, only the listed regions are saved.
save_restart(filename, ts=None)
Save the current state and time step to a restart file.
Parameters
filename [str] The restart file name.
ts [TimeStepper instance, optional] The time stepper. If not given, a default one is created.
Notes
Parameters
file_per_var [bool or None] If True, data of each variable are stored in a separate file. If
None, it is set to the application option value.
linearization [Struct or None] The linearization configuration for higher order approxima-
tions. If its kind is ‘adaptive’, file_per_var is assumed True.
select_bcs(ebc_names=None, epbc_names=None, lcbc_names=None, create_matrix=False)
select_materials(material_names, only_conf=False)
select_variables(variable_names, only_conf=False)
set_default_state(vec=None)
Return variables with an initialized state.
A convenience function that obtains the problem equations’ variables, initializes the state ones with zeros
(default) or using vec and then returns the variables.
set_equations(conf_equations=None, user=None, keep_solvers=False, make_virtual=False)
Set equations of the problem using the equations problem description entry.
Fields and Regions have to be already set.
set_equations_instance(equations, keep_solvers=False)
Set equations of the problem to equations.
set_fields(conf_fields=None)
set_ics(ics=None)
Set the initial conditions to use.
set_linear(is_linear)
set_materials(conf_materials=None)
Set definition of materials.
set_mesh_coors(coors, update_fields=False, actual=False, clear_all=True, extra_dofs=False)
Set mesh coordinates.
Parameters
coors [array] The new coordinates.
update_fields [bool] If True, update also coordinates of fields.
actual [bool] If True, update the actual configuration coordinates, otherwise the undeformed
configuration ones.
set_output_dir(output_dir=None)
Set the directory for output files.
The directory is created if it does not exist.
set_regions(conf_regions=None, conf_materials=None, functions=None, allow_empty=False)
set_solver(solver, status=None)
Set a time-stepping or nonlinear solver to be used in Problem.solve() call.
Parameters
solver [NonlinearSolver or TimeSteppingSolver instance] The nonlinear or time-stepping
solver.
Notes
A copy of the solver is used, and the nonlinear solver functions are set to those returned by Problem.
get_nls_functions(), if not set already. If a nonlinear solver is set, a default StationarySolver instance
is created automatically as the time-stepping solver. Also sets self.ts attribute.
set_variables(conf_variables=None)
Set definition of variables.
setup_default_output(conf=None, options=None)
Provide default values to Problem.setup_output() from conf.options and options.
setup_hooks(options=None)
Setup various hooks (user-defined functions), as given in options.
Supported hooks:
• matrix_hook
– check/modify tangent matrix in each nonlinear solver iteration
• nls_iter_hook
– called prior to every iteration of nonlinear solver, if the solver supports that
– takes the Problem instance (self ) as the first argument
setup_output(output_filename_trunk=None, output_dir=None, output_format=None, file_format=None,
float_format=None, file_per_var=None, linearization=None)
Sets output options to given values, or uses the defaults for each argument that is None.
solve(state0=None, status=None, force_values=None, var_data=None, update_bcs=True,
update_materials=True, save_results=True, step_hook=None, post_process_hook=None,
post_process_hook_final=None, verbose=True)
Solve the problem equations by calling the top-level solver.
Before calling this function the top-level solver has to be set, see Problem.set_solver(). Also, the
boundary conditions and the initial conditions (for time-dependent problems) has to be set, see Problem.
set_bcs(), Problem.set_ics().
Parameters
state0 [array, optional] If given, the initial state - then the initial conditions stored in the Prob-
lem instance are ignored. By default, the initial state is created and the initial conditions
are applied automatically.
status [dict-like, optional] The user-supplied object to hold the solver convergence statistics.
force_values [dict of floats or float, optional] If given, the supplied values override the values
of the essential boundary conditions.
var_data [dict, optional] A dictionary of {variable_name : data vector} used to initialize
parameter variables.
update_bcs [bool, optional] If True, update the boundary conditions in each prestep_fun
call. See Problem.get_tss_functions().
update_materials [bool, optional] If True, update the values of material parameters in each
prestep_fun call. See Problem.get_tss_functions().
save_results [bool, optional] If True, save the results in each poststep_fun call. See
Problem.get_tss_functions().
step_hook [callable, optional] The optional user-defined function that is called in each post-
step_fun call before saving the results. See Problem.get_tss_functions().
post_process_hook [callable, optional] The optional user-defined function that is passed in
each poststep_fun to Problem.save_state(). See Problem.get_tss_functions().
post_process_hook_final [callable, optional] The optional user-defined function that is
called after the top-level solver returns.
Returns
variables [Variables] The variables with the final time step state.
time_update(ts=None, ebcs=None, epbcs=None, lcbcs=None, functions=None, create_matrix=False,
is_matrix=True)
try_presolve(mtx)
sfepy.discrete.problem.make_is_save(options)
Given problem options, return a callable that determines whether to save results of a time step.
sfepy.discrete.problem.prepare_matrix(problem, state)
Pre-assemble tangent system matrix.
sfepy.discrete.projections module
sfepy.discrete.quadratures module
quadrature_tables = {
'<geometry1>' : {
order1 : QuadraturePoints(args1),
order2 : QuadraturePoints(args2),
...
},
'<geometry2>' : {
order1 : QuadraturePoints(args1),
order2 : QuadraturePoints(args2),
...
},
...
}
Note The order for quadratures on tensor product domains (‘2_4’, ‘3_8’ geometries) in case of composite Gauss quadra-
tures (products of 1D quadratures) holds for each component separately, so the actual polynomial order may be much
higher (up to order * dimension).
`<family>_<order>_<dimension>`
Returns
order [int] If order is in quadrature tables it is this value. Otherwise it is the closest higher order.
If no higher order is available, a warning is printed and the highest available order is used.
sfepy.discrete.simplex_cubature module
Generate simplex quadrature points. Code taken and adapted from pytools/hedge by Andreas Kloeckner.
sfepy.discrete.simplex_cubature.factorial(n)
sfepy.discrete.simplex_cubature.generate_decreasing_nonnegative_tuples_summing_to(n, length,
min=0,
max=None)
sfepy.discrete.simplex_cubature.generate_permutations(original)
Generate all permutations of the list `original’.
Nicked from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252178
sfepy.discrete.simplex_cubature.generate_unique_permutations(original)
Generate all unique permutations of the list `original’.
sfepy.discrete.simplex_cubature.get_simplex_cubature(order, dimension)
Cubature on an M{n}-simplex.
cf. A. Grundmann and H.M. Moeller, Invariant integration formulas for the n-simplex by combinatorial methods,
SIAM J. Numer. Anal. 15 (1978), 282–290.
This cubature rule has both negative and positive weights. It is exact for polynomials up to order 2𝑠 + 1, where
𝑠 is given as order. The integration domain is the unit simplex
∑︁
𝑇𝑛 := {(𝑥1 , . . . , 𝑥𝑛 ) : 𝑥𝑖 ≥ −1, 𝑥𝑖 ≤ −1}
𝑖
sfepy.discrete.variables module
Notes
The reduced vector starts in r_vec at r_offset. Passing a force_value overrides the EBC values. Optionally,
vec argument can be provided to store the full vector (in place) starting at offset.
class sfepy.discrete.variables.FieldVariable(name, kind, field, order=None, primary_var_name=None,
special=None, flags=None, history=None, **kwargs)
A finite element field variable.
field .. field description of variable (borrowed)
apply_ebc(vec, offset=0, force_values=None)
Apply essential (Dirichlet) and periodic boundary conditions to vector vec, starting at offset.
apply_ic(vec, offset=0, force_values=None)
Apply initial conditions conditions to vector vec, starting at offset.
clear_evaluate_cache()
Clear current evaluate cache.
create_output(vec=None, key=None, extend=True, fill_value=None, linearization=None)
Convert the DOF vector to a dictionary of output data usable by Mesh.write().
Parameters
vec [array, optional] An alternative DOF vector to be used instead of the variable DOF vector.
key [str, optional] The key to be used in the output dictionary instead of the variable name.
extend [bool] Extend the DOF values to cover the whole domain.
fill_value [float or complex] The value used to fill the missing DOF values if extend is True.
linearization [Struct or None] The linearization configuration for higher order approxima-
tions.
equation_mapping(bcs, var_di, ts, functions, problem=None, warn=False)
Create the mapping of active DOFs from/to all DOFs.
Sets n_adof.
Returns
active_bcs [set] The set of boundary conditions active in the current time.
evaluate(mode='val', region=None, integral=None, integration=None, step=0, time_derivative=None,
is_trace=False, trace_region=None, dt=None, bf=None)
Evaluate various quantities related to the variable according to mode in quadrature points defined by inte-
gral.
The evaluated data are cached in the variable instance in evaluate_cache attribute.
Parameters
mode [one of ‘val’, ‘grad’, ‘div’, ‘cauchy_strain’] The evaluation mode.
region [Region instance, optional] The region where the evaluation occurs. If None, the
underlying field region is used.
integral [Integral instance, optional] The integral defining quadrature points in which the
evaluation occurs. If None, the first order volume integral is created. Must not be None for
surface integrations.
integration [‘volume’, ‘surface’, ‘surface_extra’, or ‘point’] The term integration type. If
None, it is derived from integral.
Notes
Notes
The primary and dual variables must have the same Region.
get_dof_info(active=False)
Notes
The reduced vector starts in r_vec at r_offset. Passing a force_value overrides the EBC values. Optionally,
vec argument can be provided to store the full vector (in place) starting at offset.
get_interp_coors(strategy='interpolation', interp_term=None)
Get the physical coordinates to interpolate into, based on the strategy used.
get_mapping(region, integral, integration, get_saved=False, return_key=False)
Get the reference element mapping of the underlying field.
See also:
sfepy.discrete.common.fields.Field.get_mapping
Notes
The full vector starts in vec at offset. If ‘follow_epbc’ is True, values of EPBC master DOFs are not simply
thrown away, but added to the corresponding slave DOFs, just like when assembling. For vectors with state
(unknown) variables it should be set to False, for assembled vectors it should be set to True.
get_state_in_region(region, reshape=True, step=0)
Get DOFs of the variable in the given region.
Parameters
region [Region] The selected region.
reshape [bool] If True, reshape the DOF vector to a 2D array with the individual components
as columns. Otherwise a 1D DOF array of the form [all DOFs in region node 0, all DOFs
in region node 1, . . . ] is returned.
step [int, default 0] The time step (0 means current, -1 previous, . . . ).
Returns
out [array] The selected DOFs.
has_same_mesh(other)
Returns
flag [int] The flag can be either ‘different’ (different meshes), ‘deformed’ (slightly deformed
same mesh), or ‘same’ (same).
invalidate_evaluate_cache(step=0)
Invalidate variable data in evaluate cache for time step given by step (0 is current, -1 previous, . . . ).
This should be done, for example, prior to every nonlinear solver iteration.
save_as_mesh(filename)
Save the field mesh and the variable values into a file for visualization. Only the vertex values are stored.
set_from_function(fun, step=0)
Set the variable data (the vector of DOF values) using a function of space coordinates.
Parameters
fun [callable] The function of coordinates returning DOF values of shape (n_coor,
n_components).
step [int, optional] The time history step, 0 (default) = current.
set_from_mesh_vertices(data)
Set the variable using values at the mesh vertices.
set_from_other(other, strategy='projection', close_limit=0.1)
Set the variable using another variable. Undefined values (e.g. outside the other mesh) are set to numpy.nan,
or extrapolated.
Parameters
strategy [‘projection’ or ‘interpolation’] The strategy to set the values: the L^2 orthogonal
projection (not implemented!), or a direct interpolation to the nodes (nodal elements only!)
Notes
If the other variable uses the same field mesh, the coefficients are set directly.
set_from_qp(data_qp, integral, step=0)
Set DOFs of variable using values in quadrature points corresponding to the given integral.
setup_initial_conditions(ics, di, functions, warn=False)
Setup of initial conditions.
time_update(ts, functions)
Store time step, set variable data for variables with the setter function.
class sfepy.discrete.variables.Variable(name, kind, order=None, primary_var_name=None,
special=None, flags=None, **kwargs)
advance(ts)
Advance in time the DOF state history. A copy of the DOF vector is made to prevent history modification.
static from_conf(key, conf, fields)
get_dual()
Get the dual variable.
Returns
var [Variable instance] The primary variable for non-state variables, or the dual variable for
state variables.
get_initial_condition()
get_primary()
Get the corresponding primary variable.
Returns
var [Variable instance] The primary variable, or self for state variables or if pri-
mary_var_name is None, or None if no other variables are defined.
get_primary_name()
init_data(step=0)
Initialize the dof vector data of time step step to zeros.
init_history()
Initialize data of variables with history.
is_complex()
is_kind(kind)
is_parameter()
is_real()
is_state()
is_state_or_parameter()
is_virtual()
static reset()
set_constant(val=0.0, step=0)
Set the variable dof vector data of time step step to a scalar val.
set_data(data=None, indx=None, step=0, preserve_caches=False)
Set data (vector of DOF values) of the variable.
Parameters
data [array] The vector of DOF values.
indx [int, optional] If given, data[indx] is used.
step [int, optional] The time history step, 0 (default) = current.
preserve_caches [bool] If True, do not invalidate evaluate caches of the variable.
time_update(ts, functions)
Implemented in subclasses.
class sfepy.discrete.variables.Variables(variables=None)
Container holding instances of Variable.
advance(ts)
apply_ebc(vec=None, force_values=None)
Apply essential (Dirichlet) and periodic boundary conditions to state all variables or the given vector vec.
apply_ic(vec=None, force_values=None)
Apply initial conditions to all state variables or the given vector vec.
check_vec_size(vec, reduced=False)
Check whether the shape of the DOF vector corresponds to the total number of DOFs of the state variables.
Parameters
vec [array] The vector of DOF values.
reduced [bool] If True, the size of the DOF vector should be reduced, i.e. without DOFs
fixed by boundary conditions.
create_output(vec=None, fill_value=None, var_info=None, extend=True, linearization=None)
Creates an output dictionary with state variables data, that can be passed as ‘out’ kwarg to Mesh.write().
Then the dictionary entries are formed by components of the state vector corresponding to unknown vari-
ables according to kind of linearization given by linearization.
create_reduced_vec()
create_vec()
get_dual_names()
Get names of pairs of dual variables.
Returns
duals [dict] The dual names as virtual name : state name pairs.
get_indx(var_name, reduced=False, allow_dual=False)
get_lcbc_operator()
get_matrix_shape()
get_reduced_state(follow_epbc=False, force=False)
Get the reduced DOF vector, with EBC and PBC DOFs removed.
get_state(reduced=False, follow_epbc=False, force=False)
get_state_parts(vec=None)
Return parts of a state vector corresponding to individual state variables.
Parameters
vec [array, optional] The state vector. If not given, then the data stored in the variables are
returned instead.
Returns
out [dict] The dictionary of the state parts.
get_vec_part(vec, var_name, reduced=False)
has_ebc(vec=None, force_values=None)
has_virtuals()
init_history()
init_state(vec=None)
invalidate_evaluate_caches(step=0)
iter_state(ordered=True)
link_duals()
Link state variables with corresponding virtual variables, and assign link to self to each variable instance.
Usually, when solving a PDE in the weak form, each state variable has a corresponding virtual variable.
make_full_vec(svec, force_value=None, vec=None)
Make a full DOF vector satisfying E(P)BCs from a reduced DOF vector.
Parameters
svec [array] The reduced DOF vector.
Notes
If ‘follow_epbc’ is True, values of EPBC master dofs are not simply thrown away, but added to the corre-
sponding slave dofs, just like when assembling. For vectors with state (unknown) variables it should be set
to False, for assembled vectors it should be set to True.
set_adof_conns(adof_conns)
Set all active DOF connectivities to self as well as relevant sub-dicts to the individual variables.
set_data(data, step=0, ignore_unknown=False, preserve_caches=False)
Set data (vectors of DOF values) of variables.
Parameters
data [array] The state vector or dictionary of {variable_name : data vector}.
step [int, optional] The time history step, 0 (default) = current.
ignore_unknown [bool, optional] Ignore unknown variable names if data is a dict.
preserve_caches [bool] If True, do not invalidate evaluate caches of variables.
set_full_state(vec, force=False, preserve_caches=False)
Set the full DOF vector (including EBC and PBC DOFs). If var_name is given, set only the DOF sub-vector
corresponding to the given variable. If force is True, setting variables with LCBC DOFs is allowed.
set_reduced_state(r_vec, preserve_caches=False)
Set the reduced DOF vector, with EBC and PBC DOFs removed.
Parameters
r_vec [array] The reduced DOF vector corresponding to the variables.
preserve_caches [bool] If True, do not invalidate evaluate caches of variables.
set_state(vec, reduced=False, force=False, preserve_caches=False)
setup_dof_info(make_virtual=False)
Setup global DOF information.
setup_dtype()
Setup data types of state variables - all have to be of the same data type, one of nm.float64 or
nm.complex128.
setup_initial_conditions(ics, functions)
Notes
If active_only is False, the DOF connectivities contain all DOFs, with the E(P)BC-constrained ones stored as -1
- <DOF number>, so that the full connectivities can be reconstructed for the matrix graph creation.
sfepy.discrete.variables.expand_basis(basis, dpn)
Expand basis for variables with several components (DOFs per node), in a way compatible with
create_adof_conn(), according to dpn (DOF-per-node count).
sfepy.discrete.common sub-package
Common lower-level code and parent classes for FEM and IGA.
sfepy.discrete.common.dof_info module
Classes holding information on global DOFs and mapping of all DOFs - equations (active DOFs).
Helper functions for the equation mapping.
class sfepy.discrete.common.dof_info.DofInfo(name)
Global DOF information, i.e. ordering of DOFs of the state (unknown) variables in the global state vector.
append_raw(name, n_dof )
Append raw DOFs.
Parameters
name [str] The name of variable the DOFs correspond to.
n_dof [int] The number of DOFs.
append_variable(var, active=False)
Append DOFs of the given variable.
Parameters
var [Variable instance] The variable to append.
active [bool, optional] When True, only active (non-constrained) DOFs are considered.
get_info(var_name)
Return information on DOFs of the given variable.
Parameters
var_name [str] The name of the variable.
get_n_dof_total()
Return the total number of DOFs of all state variables.
get_subset_info(var_names)
Return global DOF information for selected variables only. Silently ignores non-existing variable names.
Parameters
var_names [list] The names of the selected variables.
update(name, n_dof )
Set the number of DOFs of the given variable.
Parameters
name [str] The name of variable the DOFs correspond to.
n_dof [int] The number of DOFs.
class sfepy.discrete.common.dof_info.EquationMap(name, dof_names, var_di)
Map all DOFs to equations for active DOFs.
get_operator()
Get the matrix operator 𝑅 corresponding to the equation mapping, such that the restricted matrix 𝐴𝑟 can
be obtained from the full matrix 𝐴 by 𝐴𝑟 = 𝑅𝑇 𝐴𝑅. All the matrices are w.r.t. a single variables that uses
this mapping.
Returns
mtx [coo_matrix] The matrix 𝑅.
map_equations(bcs, field, ts, functions, problem=None, warn=False)
Create the mapping of active DOFs from/to all DOFs.
Parameters
bcs [Conditions instance] The Dirichlet or periodic boundary conditions (single condition
instances). The dof names in the conditions must already be canonized.
field [Field instance] The field of the variable holding the DOFs.
ts [TimeStepper instance] The time stepper.
functions [Functions instance] The registered functions.
problem [Problem instance, optional] The problem that can be passed to user functions as a
context.
warn [bool, optional] If True, warn about BC on non-existent nodes.
Returns
active_bcs [set] The set of boundary conditions active in the current time.
Notes
• Periodic bc: master and slave DOFs must belong to the same field (variables can differ, though).
sfepy.discrete.common.dof_info.expand_nodes_to_dofs(nods, n_dof_per_node)
Expand DOF node indices into DOFs given a constant number of DOFs per node.
sfepy.discrete.common.dof_info.expand_nodes_to_equations(nods, dof_names, all_dof_names)
Expand vector of node indices to equations (DOF indices) based on the DOF-per-node count.
DOF names must be already canonized.
Returns
eq [array] The equations/DOF indices in the node-by-node order.
sfepy.discrete.common.dof_info.group_chains(chain_list)
Group EPBC chains.
sfepy.discrete.common.dof_info.is_active_bc(bc, ts=None, functions=None)
Check whether the given boundary condition is active in the current time.
Returns
active [bool] True if the condition bc is active.
sfepy.discrete.common.dof_info.resolve_chains(master_slave, chains)
Resolve EPBC chains - e.g. in corner nodes.
sfepy.discrete.common.domain module
get_centroids(dim)
Return the coordinates of centroids of mesh entities with dimension dim.
has_faces()
reset_regions()
Reset the list of regions associated with the domain.
save_regions(filename, region_names=None)
Save regions as individual meshes.
Parameters
filename [str] The output filename.
region_names [list, optional] If given, only the listed regions are saved.
save_regions_as_groups(filename, region_names=None)
Save regions in a single mesh but mark them by using different element/node group numbers.
If regions overlap, the result is undetermined, with exception of the whole domain region, which is marked
by group id 0.
Region masks are also saved as scalar point data for output formats that support this.
Parameters
filename [str] The output filename.
region_names [list, optional] If given, only the listed regions are saved.
sfepy.discrete.common.domain.region_leaf(domain, regions, rdef, functions)
Create/setup a region instance according to rdef.
sfepy.discrete.common.domain.region_op(level, op_code, item1, item2)
sfepy.discrete.common.extmods._fmfield module
sfepy.discrete.common.extmods._geommech module
sfepy.discrete.common.extmods.assemble module
sfepy.discrete.common.extmods.assemble.assemble_matrix_complex()
sfepy.discrete.common.extmods.assemble.assemble_vector()
sfepy.discrete.common.extmods.assemble.assemble_vector_complex()
sfepy.discrete.common.extmods.cmesh module
Notes
The memory is allocated/freed in C - this class just wraps NumPy arrays around that data without copying.
cprint()
indices
n_incident
num
offset
offsets
class sfepy.discrete.common.extmods.cmesh.CMesh
cell_groups
cell_types
conns
coors
cprint()
create_new()
Create a new CMesh instance, with cells corresponding to the given entities of dimension dent.
Parameters
entities [array, optional] The selected topological entities of the mesh to be in the new mesh.
If not given, a copy of the mesh based on the cell-vertex connectivity is returned.
dent [int, optional] The topological dimension of the entities.
localize [bool] If True, strip the vertices not used in the the resulting sub-mesh cells and
renumber the connectivity.
Returns
cmesh [CMesh] The new mesh with the cell-vertex connectivity. Other connectivities have
to be created and local entities need to be set manually.
dim
edge_oris
entities
face_oris
facet_oris
free_connectivity()
from_data()
Fill CMesh data using Python data.
get_cell_conn()
get_centroids()
Return the coordinates of centroids of mesh entities with dimension dim.
get_complete()
Get entities of dimension dim that are completely given by entities of dimension dent listed in entities.
get_conn()
get_conn_as_graph()
Get d1 -> d2 connectivity as a sparse matrix graph (values = ones).
For safety, creates a copy of the connectivity arrays. The connectivity is created if necessary.
get_facet_normals()
Return the normals of facets for each mesh cell. The normals can be accessed using the cell-facet connec-
tivity.
If which is -1, two normals of each quadrilateral face are averaged. If it is 0 or 1, the corresponding normal
is used.
get_incident()
Get non-unique entities indices of dimension dim that are contained in entities of dimension dent listed in
entities. As each of entities can be in several entities of dimension dent, offsets array is returned optionally.
get_local_entities()
get_local_ids()
Get local ids of entities of dimension dent in non-unique entities incident of dimension dim (with given
offsets per entities) incident to entities, see mesh_get_incident().
The function searches entities in incident -> entities connectivity for each non-unique entity in incident.
get_orientations()
Get orientations of entities of dimension dim. Alternatively, co-dimension can be specified using codim
argument.
get_surface_facets()
Get facets (edges in 2D, faces in 3D) on the mesh surface.
get_volumes()
Return the volumes of mesh entities with dimension dim > 0.
key_to_index
n_coor
n_el
num
set_local_entities()
setup_connectivity()
setup_entities()
Set up mesh edge (2D and 3D) and face connectivities (3D only) as well as their orientations.
tdim
vertex_groups
sfepy.discrete.common.extmods.cmesh.cmem_statistics()
sfepy.discrete.common.extmods.cmesh.create_mesh_graph()
Create sparse (CSR) graph corresponding to given row and column connectivities.
Parameters
n_row [int] The number of row connectivity nodes.
n_col [int] The number of column connectivity nodes.
n_gr [int] The number of element groups.
rconns [list of arrays] The list of length n_gr of row connectivities.
cconns [list of arrays] The list of length n_gr of column connectivities.
Returns
nnz [int] The number of graph nonzeros.
prow [array] The array of CSR row pointers.
icol [array] The array of CSR column indices.
sfepy.discrete.common.extmods.cmesh.get_cmem_usage()
sfepy.discrete.common.extmods.cmesh.graph_components()
Determine connected compoments of a compressed sparse graph.
Returns
n_comp [int] The number of components.
flag [array] The flag marking for each node its component.
sfepy.discrete.common.extmods.cmesh.orient_elements()
Swap element nodes so that its volume is positive.
sfepy.discrete.common.extmods.crefcoors module
class sfepy.discrete.common.extmods.crefcoors.CBasisContext
sfepy.discrete.common.extmods.crefcoors.evaluate_in_rc()
Evaluate source field DOF values or gradients in the given reference element coordinates using the given inter-
polation.
1. Evaluate basis functions or gradients of basis functions in the reference coordinates. For gradients, tranform
the values to the material coordinates. 2. Interpolate source values using the basis functions/gradients.
Interpolation uses field approximation connectivity.
sfepy.discrete.common.extmods.crefcoors.find_ref_coors()
sfepy.discrete.common.extmods.crefcoors.find_ref_coors_convex()
sfepy.discrete.common.extmods.mappings module
alloc_extra_data()
bf
bfg
cprint()
describe()
Describe the element geometry - compute the reference element mapping.
det
dim
evaluate_bfbgm()
Evaluate volume base function gradients in surface quadrature points.
get_element_diameters()
Compute diameters of selected elements.
integral
integrate()
Integrate arr over the domain of the mapping into out.
mode
mtx_t
n_el
n_ep
n_qp
normal
ps
qp
shape
volume
sfepy.discrete.common.fields module
class sfepy.discrete.common.fields.Field(**kwargs)
Base class for fields.
clear_mappings(clear_all=False)
Clear current reference mappings.
create_eval_mesh()
Create a mesh for evaluating the field. The default implementation returns None, because this mesh is for
most fields the same as the one created by Field.create_mesh().
evaluate_at(coors, source_vals, mode='val', strategy='general', close_limit=0.1, get_cells_fun=None,
cache=None, ret_cells=False, ret_status=False, ret_ref_coors=False, verbose=False)
Evaluate source DOF values corresponding to the field in the given coordinates using the field interpolation.
Parameters
coors [array, shape (n_coor, dim)] The coordinates the source values should be interpo-
lated into.
source_vals [array, shape (n_nod, n_components)] The source DOF values correspond-
ing to the field.
mode [{‘val’, ‘grad’}, optional] The evaluation mode: the field value (default) or the field
value gradient.
strategy [{‘general’, ‘convex’}, optional] The strategy for finding the elements that contain
the coordinates. For convex meshes, the ‘convex’ strategy might be faster than the ‘general’
one.
close_limit [float, optional] The maximum limit distance of a point from the closest element
allowed for extrapolation.
get_cells_fun [callable, optional] If given, a function with signature
get_cells_fun(coors, cmesh, **kwargs) returning cells and offsets that po-
tentially contain points with the coordinates coors. Applicable only when strategy is
‘general’. When not given, get_potential_cells() is used.
cache [Struct, optional] To speed up a sequence of evaluations, the field mesh and other
data can be cached. Optionally, the cache can also contain the reference element coor-
dinates as cache.ref_coors, cache.cells and cache.status, if the evaluation occurs in the
same coordinates repeatedly. In that case the mesh related data are ignored. See Field.
get_evaluate_cache().
ret_ref_coors [bool, optional] If True, return also the found reference element coordinates.
ret_status [bool, optional] If True, return also the enclosing cell status for each point.
ret_cells [bool, optional] If True, return also the cell indices the coordinates are in.
verbose [bool] If False, reduce verbosity.
Returns
vals [array] The interpolated values with shape (n_coor, n_components) or gradients
with shape (n_coor, n_components, dim) according to the mode. If ret_status is
False, the values where the status is greater than one are set to numpy.nan.
ref_coors [array] The found reference element coordinates, if ret_ref_coors is True.
cells [array] The cell indices, if ret_ref_coors or ret_cells or ret_status are True.
status [array] The status, if ret_ref_coors or ret_status are True, with the following meaning:
0 is success, 1 is extrapolation within close_limit, 2 is extrapolation outside close_limit, 3 is
failure, 4 is failure due to non-convergence of the Newton iteration in tensor product cells.
If close_limit is 0, then for the ‘general’ strategy the status 5 indicates points outside of the
field domain that had no potential cells.
static from_args(name, dtype, shape, region, approx_order=1, space='H1', poly_space_base='lagrange')
Create a Field subclass instance corresponding to a given space.
Parameters
name [str] The field name.
dtype [numpy.dtype] The field data type: float64 or complex128.
shape [int/tuple/str] The field shape: 1 or (1,) or ‘scalar’, space dimension (2, or (2,) or 3 or
(3,)) or ‘vector’, or a tuple. The field shape determines the shape of the FE base functions
and is related to the number of components of variables and to the DOF per node count,
depending on the field kind.
region [Region] The region where the field is defined.
approx_order [int/str] The FE approximation order, e.g. 0, 1, 2, ‘1B’ (1 with bubble).
space [str] The function space name.
poly_space_base [str] The name of polynomial space base.
Notes
Notes
The nodal basis fields (lagrange) reimplement this function to set DOFs directly.
The hierarchical basis field (lobatto) do not support surface mappings, so also reimplement this function.
sfepy.discrete.common.fields.fields_from_conf(conf, regions)
sfepy.discrete.common.fields.parse_approx_order(approx_order)
Parse the uniform approximation order value (str or int).
sfepy.discrete.common.fields.parse_shape(shape, dim)
sfepy.discrete.common.fields.setup_extra_data(conn_info)
Setup extra data required for non-volume integration.
sfepy.discrete.common.global_interp module
Parameters
field [Field instance] The field defining the approximation.
coors [array] The physical coordinates.
strategy [{‘general’, ‘convex’}, optional] The strategy for finding the elements that contain the
coordinates. For convex meshes, the ‘convex’ strategy might be faster than the ‘general’ one.
close_limit [float, optional] The maximum limit distance of a point from the closest element
allowed for extrapolation.
get_cells_fun [callable, optional] If given, a function with signature get_cells_fun(coors,
cmesh, **kwargs) returning cells and offsets that potentially contain points with the
coordinates coors. Applicable only when strategy is ‘general’. When not given,
get_potential_cells() is used.
cache [Struct, optional] To speed up a sequence of evaluations, the field mesh and other data
can be cached. Optionally, the cache can also contain the reference element coordinates as
cache.ref_coors, cache.cells and cache.status, if the evaluation occurs in the same coordi-
nates repeatedly. In that case the mesh related data are ignored.
verbose [bool] If False, reduce verbosity.
Returns
ref_coors [array] The reference coordinates.
cells [array] The cell indices corresponding to the reference coordinates.
status [array] The status: 0 is success, 1 is extrapolation within close_limit, 2 is extrapolation
outside close_limit, 3 is failure, 4 is failure due to non-convergence of the Newton iteration
in tensor product cells. If close_limit is 0, then for the ‘general’ strategy the status 5 indicates
points outside of the field domain that had no potential cells.
sfepy.discrete.common.global_interp.get_ref_coors_convex(field, coors, close_limit=0.1, cache=None,
verbose=False)
Get reference element coordinates and elements corresponding to given physical coordinates.
Parameters
field [Field instance] The field defining the approximation.
coors [array] The physical coordinates.
close_limit [float, optional] The maximum limit distance of a point from the closest element
allowed for extrapolation.
cache [Struct, optional] To speed up a sequence of evaluations, the field mesh and other data
can be cached. Optionally, the cache can also contain the reference element coordinates as
cache.ref_coors, cache.cells and cache.status, if the evaluation occurs in the same coordi-
nates repeatedly. In that case the mesh related data are ignored.
verbose [bool] If False, reduce verbosity.
Returns
ref_coors [array] The reference coordinates.
cells [array] The cell indices corresponding to the reference coordinates.
status [array] The status: 0 is success, 1 is extrapolation within close_limit, 2 is extrapolation
outside close_limit, 3 is failure, 4 is failure due to non-convergence of the Newton iteration
in tensor product cells.
Notes
sfepy.discrete.common.mappings module
kind [‘v’ or ‘s’] The kind of the entities: ‘v’ - cells, ‘s’ - facets.
Returns
mapping [VolumeMapping or SurfaceMapping instance] The requested mapping.
class sfepy.discrete.common.mappings.PhysicalQPs(num=0)
Physical quadrature points in a region.
get_shape(rshape)
Get shape from raveled shape.
sfepy.discrete.common.mappings.get_jacobian(field, integral, region=None, integration='volume')
Get the jacobian of reference mapping corresponding to field.
Parameters
field [Field instance] The field defining the reference mapping.
integral [Integral instance] The integral defining quadrature points.
region [Region instance, optional] If given, use the given region instead of field region.
integration [one of (‘volume’, ‘surface’, ‘surface_extra’)] The integration type.
Returns
jac [array] The jacobian merged for all element groups.
See also:
get_mapping_data
Notes
Assumes the same element geometry in all element groups of the field!
sfepy.discrete.common.mappings.get_mapping_data(name, field, integral, region=None,
integration='volume')
General helper function for accessing reference mapping data.
Get data attribute name from reference mapping corresponding to field in region in quadrature points of the given
integral and integration type.
Parameters
name [str] The reference mapping attribute name.
field [Field instance] The field defining the reference mapping.
integral [Integral instance] The integral defining quadrature points.
region [Region instance, optional] If given, use the given region instead of field region.
integration [one of (‘volume’, ‘surface’, ‘surface_extra’)] The integration type.
Returns
data [array] The required data merged for all element groups.
Notes
Assumes the same element geometry in all element groups of the field!
sfepy.discrete.common.mappings.get_normals(field, integral, region)
Get the normals of element faces in region.
Parameters
field [Field instance] The field defining the reference mapping.
integral [Integral instance] The integral defining quadrature points.
region [Region instance] The given of the element faces.
Returns
normals [array] The normals merged for all element groups.
See also:
get_mapping_data
Notes
Assumes the same element geometry in all element groups of the field!
sfepy.discrete.common.mappings.get_physical_qps(region, integral, map_kind=None)
Get physical quadrature points corresponding to the given region and integral.
sfepy.discrete.common.poly_spaces module
base [array] The basis (shape (n_coor, 1, n_base)) or its first derivative (shape (n_coor, dim,
n_base)) or its second derivative (shape (n_coor, dim, dim, n_base)) evaluated in the given
points. An additional axis is pre-pended of length n_cell, if ori is given, or of length 1, if
force_axis is True.
Notes
If coors.ndim == 3, several point sets are assumed, with equal number of points in each of them. This is
the case, for example, of the values of the volume base functions on the element facets. The indexing (of
bf_b(g)) is then (ifa,iqp,:,n_ep), so that the facet can be set in C using FMF_SetCell.
keys = {(0, 1): 'simplex', (1, 2): 'simplex', (2, 3): 'simplex', (2, 4):
'tensor_product', (3, 4): 'simplex', (3, 8): 'tensor_product'}
static suggest_name(geometry, order, base='lagrange', force_bubble=False)
Suggest the polynomial space name given its constructor parameters.
sfepy.discrete.common.poly_spaces.transform_basis(transform, bf )
Transform a basis bf using transform array of matrices.
sfepy.discrete.common.region module
property edges
eval_op_cells(other, op)
eval_op_edges(other, op)
eval_op_faces(other, op)
eval_op_facets(other, op)
eval_op_vertices(other, op)
property faces
property facets
finalize(allow_empty=False)
Initialize the entities corresponding to the region kind and regenerate all already existing (accessed) entities
of lower topological dimension from the kind entities.
static from_cells(cells, domain, name='region', kind='cell', parent=None)
Create a new region containing given cells.
Parameters
cells [array] The array of cells.
domain [Domain instance] The domain containing the facets.
name [str, optional] The name of the region.
kind [str, optional] The kind of the region.
parent [str, optional] The name of the parent region.
Returns
obj [Region instance] The new region.
static from_facets(facets, domain, name='region', kind='facet', parent=None)
Create a new region containing given facets.
Parameters
facets [array] The array with indices to unique facets.
domain [Domain instance] The domain containing the facets.
name [str, optional] The name of the region.
kind [str, optional] The kind of the region.
parent [str, optional] The name of the parent region.
Returns
obj [Region instance] The new region.
static from_vertices(vertices, domain, name='region', kind='cell')
Create a new region containing given vertices.
Parameters
vertices [array] The array of vertices.
domain [Domain instance] The domain containing the vertices.
name [str, optional] The name of the region.
kind [str, optional] The kind of the region.
Returns
Notes
If the number of unique values in cells is smaller or equal to the number of cells in the region, all cells
has to be also the region cells (self is a superset of cells). The region cells are considered depending on
true_cells_only.
Otherwise, indices of all cells in self that are in cells are returned.
get_cells(true_cells_only=True)
Get cells of the region.
Raises ValueError if true_cells_only is True and the region kind does not allow cells. For true_cells_only
equal to False, cells incident to facets are returned if the region itself contains no cells. Obeys parent region,
if given.
get_charfun(by_cell=False, val_by_id=False)
Return the characteristic function of the region as a vector of values defined either in the mesh vertices
(by_cell == False) or cells. The values are either 1 (val_by_id == False) or sequential id + 1.
get_edge_graph()
Return the graph of region edges as a sparse matrix having uid(k) + 1 at (i, j) if vertex[i] is connected with
vertex[j] by the edge k.
Degenerate edges are ignored.
get_entities(dim)
Return mesh entities of dimension dim.
get_facet_indices()
Return an array (per group) of (iel, ifa) for each facet. A facet can be in 1 (surface) or 2 (inner) cells.
get_mirror_region(name)
get_n_cells(is_surface=False)
Get number of region cells.
Parameters
is_surface [bool] If True, number of edges or faces according to domain dimension is re-
turned instead.
Returns
n_cells [int] The number of cells.
has_cells()
light_copy(name, parse_def )
set_kind(kind)
set_kind_tdim()
sfepy.discrete.fem sub-package
sfepy.discrete.fem.domain module
Notes
Surface groups define surface facet connectivity that is needed for sfepy.discrete.fem.mappings.
SurfaceMapping.
fix_element_orientation()
Ensure element vertices ordering giving positive cell volumes.
get_conn(ret_gel=False)
Get the cell-vertex connectivity and, if ret_gel is True, also the corresponding reference geometry element.
get_diameter()
Return the diameter of the domain.
Notes
get_mesh_bounding_box()
Return the bounding box of the underlying mesh.
Returns
bbox [ndarray (2, dim)] The bounding box with min. values in the first row and max. values
in the second row.
get_mesh_coors(actual=False)
Return the coordinates of the underlying mesh vertices.
refine()
Uniformly refine the domain mesh.
Returns
domain [FEDomain instance] The new domain with the refined mesh.
Notes
Works only for meshes with single element type! Does not preserve node groups!
sfepy.discrete.fem.extmods.bases module
base1d
cprint()
e_coors_max
evaluate()
geo_ctx
iel
is_bubble
mbfg
mesh_conn
mesh_coors
sfepy.discrete.fem.extmods.lobatto_bases module
sfepy.discrete.fem.facets module
sfepy.discrete.fem.facets.build_orientation_map(n_fp)
The keys are binary masks of the lexicographical ordering of facet vertices. A bit i set to one means v[i] < v[i+1].
The values are [original_order, permutation], where permutation can be used to sort facet vertices lexicograph-
ically. Hence permuted_facet = facet[permutation].
sfepy.discrete.fem.facets.get_facet_dof_permutations(n_fp, order)
Prepare DOF permutation vector for each possible facet orientation.
sfepy.discrete.fem.facets.iter0(num)
sfepy.discrete.fem.facets.iter01(num)
sfepy.discrete.fem.facets.iter01x01y(num)
sfepy.discrete.fem.facets.iter01x10y(num)
sfepy.discrete.fem.facets.iter01y01x(num)
sfepy.discrete.fem.facets.iter01y10x(num)
sfepy.discrete.fem.facets.iter02(num)
sfepy.discrete.fem.facets.iter1(num)
sfepy.discrete.fem.facets.iter10(num)
sfepy.discrete.fem.facets.iter10x01y(num)
sfepy.discrete.fem.facets.iter10x10y(num)
sfepy.discrete.fem.facets.iter10y01x(num)
sfepy.discrete.fem.facets.iter10y10x(num)
sfepy.discrete.fem.facets.iter12(num)
sfepy.discrete.fem.facets.iter20(num)
sfepy.discrete.fem.facets.iter21(num)
sfepy.discrete.fem.facets.make_line_matrix(order)
sfepy.discrete.fem.facets.make_square_matrix(order)
sfepy.discrete.fem.facets.make_triangle_matrix(order)
sfepy.discrete.fem.fe_surface module
sfepy.discrete.fem.fields_base module
Notes
Notes
• interps and hence node_descs are per region (must have single geometry!)
Notes
create_mesh(extra_nodes=True)
Create a mesh from the field region, optionally including the field extra nodes.
create_output(dofs, var_name, dof_names=None, key=None, extend=True, fill_value=None,
linearization=None)
Convert the DOFs corresponding to the field to a dictionary of output data usable by Mesh.write().
Parameters
dofs [array, shape (n_nod, n_component)] The array of DOFs reshaped so that each column
corresponds to one component.
var_name [str] The variable name corresponding to dofs.
dof_names [tuple of str] The names of DOF components.
key [str, optional] The key to be used in the output dictionary instead of the variable name.
extend [bool] Extend the DOF values to cover the whole domain.
fill_value [float or complex] The value used to fill the missing DOF values if extend is True.
linearization [Struct or None] The linearization configuration for higher order approxima-
tions.
Returns
out [dict] The output dictionary.
extend_dofs(dofs, fill_value=None)
Extend DOFs to the whole domain using the fill_value, or the smallest value in dofs if fill_value is None.
get_base(key, derivative, integral, iels=None, from_geometry=False, base_only=True)
Notes
get_dofs_in_region(region, merge=True)
Return indices of DOFs that belong to the given region and group.
get_evaluate_cache(cache=None, share_geometry=False, verbose=False)
Get the evaluate cache for Variable.evaluate_at().
Parameters
cache [Struct instance, optional] Optionally, use the provided instance to store the cache data.
share_geometry [bool] Set to True to indicate that all the evaluations will work on the same
region. Certain data are then computed only for the first probe and cached.
verbose [bool] If False, reduce verbosity.
Returns
cache [Struct instance] The evaluate cache.
get_output_approx_order()
Get the approximation order used in the output file.
get_qp(key, integral)
Get quadrature points and weights corresponding to the given key and integral. The key is ‘v’ or ‘s#’, where
# is the number of face vertices.
get_true_order()
Get the true approximation order depending on the reference element geometry.
For example, for P1 (linear) approximation the true order is 1, while for Q1 (bilinear) approximation in 2D
the true order is 2.
get_vertices()
Return indices of vertices belonging to the field region.
interp_to_qp(dofs)
Interpolate DOFs into quadrature points.
The quadrature order is given by the field approximation order.
Parameters
setup_point_data(field, region)
mode [one of ‘eval’, ‘el_avg’, ‘qp’] The evaluation mode - ‘qp’ requests the values in quadrature
points, ‘el_avg’ element averages and ‘eval’ means integration over each term region.
term_mode [str] The term call mode - some terms support different call modes and depending
on the call mode different values are returned.
extra_args [dict, optional] Extra arguments to be passed to terms in the expression.
verbose [bool] If False, reduce verbosity.
kwargs [dict, optional] The variables (dictionary of (variable name) : (Variable instance)) to be
used in the expression.
min_level [int] The minimum required level of mesh refinement.
max_level [int] The maximum level of mesh refinement.
eps [float] The relative tolerance parameter of mesh adaptivity.
Returns
out [dict] The output dictionary.
sfepy.discrete.fem.fields_base.eval_nodal_coors(coors, mesh_coors, region, poly_space,
geom_poly_space, econn, only_extra=True)
Compute coordinates of nodes corresponding to poly_space, given mesh coordinates and geom_poly_space.
sfepy.discrete.fem.fields_base.get_eval_expression(expression, fields, materials, variables,
functions=None, mode='eval', term_mode=None,
extra_args=None, verbose=True, kwargs=None)
Get the function for evaluating an expression given a list of elements, and reference element coordinates.
sfepy.discrete.fem.fields_base.set_mesh_coors(domain, fields, coors, update_fields=False,
actual=False, clear_all=True, extra_dofs=False)
sfepy.discrete.fem.fields_hierarchic module
create_basis_context()
Create the context required for evaluating the field basis.
family_name = 'volume_H1_lobatto'
set_dofs(fun=0.0, region=None, dpn=None, warn=None)
Set the values of DOFs in a given region using a function of space coordinates or value fun.
sfepy.discrete.fem.fields_nodal module
Notes
get_surface_basis(region)
Get basis for projections to region’s facets.
Notes
Cannot be uses for all fields because IGA does not support surface mappings.
class sfepy.discrete.fem.fields_nodal.H1DiscontinuousField(name, dtype, shape, region,
approx_order=1)
average_to_vertices(dofs)
Average DOFs of the discontinuous field into the field region vertices.
extend_dofs(dofs, fill_value=None)
Extend DOFs to the whole domain using the fill_value, or the smallest value in dofs if fill_value is None.
family_name = 'volume_H1_lagrange_discontinuous'
remove_extra_dofs(dofs)
Remove DOFs defined in higher order nodes (order > 1).
class sfepy.discrete.fem.fields_nodal.H1NodalMixin(**kwargs)
create_basis_context()
Create the context required for evaluating the field basis.
set_dofs(fun=0.0, region=None, dpn=None, warn=None)
Set the values of DOFs in a given region using a function of space coordinates or value fun.
class sfepy.discrete.fem.fields_nodal.H1NodalSurfaceField(name, dtype, shape, region,
approx_order=1)
A field defined on a surface region.
family_name = 'surface_H1_lagrange'
interp_v_vals_to_n_vals(vec)
Interpolate a function defined by vertex DOF values using the FE surface geometry base (P1 or Q1) into
the extra nodes, i.e. define the extra DOF values.
class sfepy.discrete.fem.fields_nodal.H1NodalVolumeField(name, dtype, shape, region,
approx_order=1)
family_name = 'volume_H1_lagrange'
interp_v_vals_to_n_vals(vec)
Interpolate a function defined by vertex DOF values using the FE geometry base (P1 or Q1) into the extra
nodes, i.e. define the extra DOF values.
class sfepy.discrete.fem.fields_nodal.H1SNodalSurfaceField(name, dtype, shape, region,
approx_order=1)
family_name = 'surface_H1_serendipity'
class sfepy.discrete.fem.fields_nodal.H1SNodalVolumeField(name, dtype, shape, region,
approx_order=1)
create_basis_context()
Create the context required for evaluating the field basis.
family_name = 'volume_H1_serendipity'
sfepy.discrete.fem.fields_positive module
family_name = 'surface_H1_bernstein'
class sfepy.discrete.fem.fields_positive.H1BernsteinVolumeField(name, dtype, shape, region,
approx_order=1)
create_basis_context()
Create the context required for evaluating the field basis.
family_name = 'volume_H1_bernstein'
sfepy.discrete.fem.geometry_element module
Notes
• geometry_data: surface facets are assumed to be of the same kind for each geometry element - wedges or pyra-
mides are not supported.
• the orientation is a tuple: (root1, vertices of direction vectors, swap from, swap to, root2, . . . )
class sfepy.discrete.fem.geometry_element.GeometryElement(name)
The geometric entities of a finite element mesh.
create_surface_facet()
Create a GeometryElement instance corresponding to this instance surface facet.
get_conn_permutations()
Get all possible connectivity permutations corresponding to different spatial orientations of the geometry
element.
get_edges_per_face()
Return the indices into self.edges per face.
get_grid(n_nod)
Get a grid of n_nod interpolation points, including the geometry element vertices. The number of points
must correspond to a valid number of FE nodes for each geometry.
get_interpolation_name()
Get the name of corresponding linear interpolant.
get_surface_entities()
Return self.vertices in 1D, self.edges in 2D and self.faces in 3D.
sfepy.discrete.fem.geometry_element.create_geometry_elements(names=None)
Utility function to create GeometryElement instances.
Parameters
names [str, optional] The names of the entity, one of the keys in geometry_data dictionary. If
None, all keys of geometry_data are used.
Returns
gels [dict] The dictionary of geometry elements with names as keys.
sfepy.discrete.fem.geometry_element.setup_orientation(vecs_tuple)
sfepy.discrete.fem.history module
sfepy.discrete.fem.lcbc_operators module
Operators for enforcing linear combination boundary conditions in nodal FEM setting.
class sfepy.discrete.fem.lcbc_operators.EdgeDirectionOperator(name, regions, dof_names,
dof_map_fun, filename, variables,
ts=None, functions=None)
Transformation matrix operator for edges direction LCBCs.
The substitution (in 3D) is:
[𝑢1 , 𝑢2 , 𝑢3 ]𝑇 = [𝑑1 , 𝑑2 , 𝑑3 ]𝑇 𝑤,
where 𝑑 is an edge direction vector averaged into a node. The new DOF is 𝑤.
kind = 'edge_direction'
class sfepy.discrete.fem.lcbc_operators.IntegralMeanValueOperator(name, regions, dof_names,
dof_map_fun, variables,
ts=None, functions=None)
Transformation matrix operator for integral mean value LCBCs. All DOFs in a region are summed to form a
single new DOF.
kind = 'integral_mean_value'
class sfepy.discrete.fem.lcbc_operators.LCBCOperator(name, regions, dof_names, dof_map_fun,
variables, functions=None)
Base class for LCBC operators.
setup()
finalize()
Call this after all LCBCs of the variable have been added.
Initializes the global column indices and DOF counts.
make_global_operator(adi, new_only=False)
Assemble all LCBC operators into a single matrix.
Parameters
adi [DofInfo] The active DOF information.
new_only [bool] If True, the operator columns will contain only new DOFs.
Returns
mtx_lc [csr_matrix] The global LCBC operator in the form of a CSR matrix.
rhs_lc [array] The right-hand side for non-homogeneous LCBCs.
lcdi [DofInfo] The global active LCBC-constrained DOF information.
class sfepy.discrete.fem.lcbc_operators.MRLCBCOperator(name, regions, dof_names, dof_map_fun,
variables, functions=None)
Base class for model-reduction type LCBC operators.
These operators are applied to a single field, and replace its DOFs in a given region by new DOFs. In case some
field DOFs are to be preserved, those have to be “copied” explicitly, by setting the corresponding row of the
operator matrix to a single value one (see, for example, NoPenetrationOperator).
setup()
treat_pbcs(dofs, master)
Treat dofs with periodic BC.
class sfepy.discrete.fem.lcbc_operators.NoPenetrationOperator(name, regions, dof_names,
dof_map_fun, filename, variables,
ts=None, functions=None)
Transformation matrix operator for no-penetration LCBCs.
kind = 'no_penetration'
class sfepy.discrete.fem.lcbc_operators.NodalLCOperator(name, regions, dof_names, dof_map_fun,
constraints, variables, ts=None,
functions=None)
Transformation matrix operator for the general linear combination of DOFs in each node of a field in the given
region.
The DOFs can be fully constrained - then the operator corresponds to enforcing Dirichlet boundary conditions.
The linear combination is given by:
𝑛
∑︁
𝐴𝑖𝑗 𝑢𝑗 = 𝑏𝑖 , ∀𝑖 ,
𝑗=1
where 𝑢𝑗 , 𝑗 = 1, . . . , 𝑛 are the DOFs in the node and 𝑖 = 1, . . . , 𝑚, 𝑚 < 𝑛, are the linear constraint indices.
SymPy is used to solve the constraint linear system in each node for the dependent DOF(s).
kind = 'nodal_combination'
class sfepy.discrete.fem.lcbc_operators.NormalDirectionOperator(name, regions, dof_names,
dof_map_fun, filename,
variables, ts=None,
functions=None)
Transformation matrix operator for normal direction LCBCs.
The substitution (in 3D) is:
[𝑢1 , 𝑢2 , 𝑢3 ]𝑇 = [𝑛1 , 𝑛2 , 𝑛3 ]𝑇 𝑤
The new DOF is 𝑤.
get_vectors(nodes, region, field, filename=None)
kind = 'normal_direction'
class sfepy.discrete.fem.lcbc_operators.RigidOperator(name, regions, dof_names, dof_map_fun,
variables, ts=None, functions=None)
Transformation matrix operator for rigid LCBCs.
kind = 'rigid'
class sfepy.discrete.fem.lcbc_operators.ShiftedPeriodicOperator(name, regions, dof_names,
dof_map_fun, shift_fun,
variables, ts, functions)
Transformation matrix operator for shifted periodic boundary conditions.
This operator ties existing DOFs of two fields in two disjoint regions together. Unlike MRLCBCOperator sub-
classes, it does not create any new DOFs.
kind = 'shifted_periodic'
sfepy.discrete.fem.linearizer module
sfepy.discrete.fem.mappings module
sfepy.discrete.fem.mesh module
get_conn(desc, ret_cells=False)
Get the rectangular cell-vertex connectivity corresponding to desc. If ret_cells is True, the corresponding
cells are returned as well.
transform_coors(mtx_t, ref_coors=None)
Transform coordinates of the mesh by the given transformation matrix.
Parameters
mtx_t [array] The transformation matrix T (2D array). It is applied depending on its shape:
• (dim, dim): x = T * x
• (dim, dim + 1): x = T[:, :-1] * x + T[:, -1]
ref_coors [array, optional] Alternative coordinates to use for the transformation instead of
the mesh coordinates, with the same shape as self.coors.
write(filename=None, io=None, out=None, float_format=None, file_format=None, **kwargs)
Write mesh + optional results in out to a file.
Parameters
filename [str, optional] The file name. If None, the mesh name is used instead.
io [MeshIO instance or ‘auto’, optional] Passing ‘auto’ respects the extension of filename.
out [dict, optional] The output data attached to the mesh vertices and/or cells.
float_format [str, optional] The format string used to print floats in case of a text file format.
**kwargs [dict, optional] Additional arguments that can be passed to the MeshIO instance.
sfepy.discrete.fem.mesh.find_map(x1, x2, allow_double=False, join=True)
Find a mapping between common coordinates in x1 and x2, such that x1[cmap[:,0]] == x2[cmap[:,1]]
sfepy.discrete.fem.mesh.fix_double_nodes(coor, ngroups, conns)
Detect and attempt fixing double nodes in a mesh.
The double nodes are nodes having the same coordinates w.r.t. precision given by eps.
sfepy.discrete.fem.mesh.get_min_vertex_distance(coor, guess)
Can miss the minimum, but is enough for our purposes.
sfepy.discrete.fem.mesh.get_min_vertex_distance_naive(coor)
Notes
Assumes the same number and kind of element groups in both meshes!
sfepy.discrete.fem.mesh.set_accuracy(eps)
sfepy.discrete.fem.meshio module
format = 'ansys_cdb'
static guess(filename)
read(mesh, **kwargs)
read_bounding_box()
read_dimension(ret_fd=False)
format = 'comsol'
read(mesh, **kwargs)
data [list, array] For ElementNodeData with shape (n_cell, n_cell_dof) contains for each
time step. For other contains array of data from last time step.
time [list] Contains times.
time_n [list] Contains time step numbers.
scheme [Struct] Interpolation scheme used in data, only one interpolation scheme is al-
lowed.
scheme_name [str] Name of the interpolation scheme, repeated fo convenience.
mode [str] Represents of type of data. cell_nodes : for ElementNodeData; vertex or cell :
Note that for vertex and cell data reading multiple time steps does not work yet.
Notes
Notes
format = 'hdf5'
read(mesh=None, **kwargs)
read_bounding_box(ret_fd=False, ret_dim=False)
read_dimension(ret_fd=False)
read_last_step(filename=None)
The default implementation: just return 0 as the last step.
static read_mesh_from_hdf5(filename, group=None, mesh=None)
Read the mesh from a HDF5 file.
filename: str or tables.File The HDF5 file to read the mesh from.
group: tables.group.Group or str, optional The HDF5 file group to read the mesh from. If None, the
root group is used.
mesh: sfepy.dicrete.fem.Mesh or None If None, the new mesh is created and returned, otherwise content
of this argument is replaced by the read mesh.
Returns
sfepy.dicrete.fem.Mesh readed mesh
read_time_stepper(filename=None)
read_times(filename=None)
Read true time step data from individual time steps.
Returns
steps [array] The time steps.
times [array] The times of the time steps.
nts [array] The normalized times of the time steps, in [0, 1].
format = 'hdf5-xdmf'
write(filename, mesh, out=None, ts=None, cache=None, **kwargs)
format = 'hmascii'
read(mesh, **kwargs)
read_dimension()
format = 'mesh3d'
read(mesh, **kwargs)
read_dimension()
See the Mesh class’ docstring how the nodes, ngroups, conns, mat_ids and descs should look like. You just need
to read them from your specific format from disk.
To write a mesh to disk, just implement the write() method and use the information from the mesh instance (e.g.
nodes, conns, mat_ids and descs) to construct your specific format.
Optionally, subclasses can implement read_data() to read also computation results. This concerns mainly the
subclasses with implemented write() supporting the ‘out’ kwarg.
The default implementation od read_last_step() just returns 0. It should be reimplemented in subclasses capable
of storing several steps.
static any_from_filename(filename, prefix_dir=None, file_format=None, mode='r')
Create a MeshIO instance according to the kind of filename.
Parameters
filename [str, function or MeshIO subclass instance] The name of the mesh file. It can be
also a user-supplied function accepting two arguments: mesh, mode, where mesh is a Mesh
instance and mode is one of ‘read’,’write’, or a MeshIO subclass instance.
prefix_dir [str] The directory name to prepend to filename.
Returns
io [MeshIO subclass instance] The MeshIO subclass instance corresponding to the kind of
filename.
call_msg = 'called an abstract MeshIO instance!'
format = None
get_filename_trunk()
get_vector_format(dim)
read_last_step()
The default implementation: just return 0 as the last step.
read_times(filename=None)
Read true time step data from individual time steps.
Returns
steps [array] The time steps.
times [array] The times of the time steps.
nts [array] The normalized times of the time steps, in [0, 1].
Notes
cell_types = {('hexahedron', 3): '3_8', ('line', 1): '1_2', ('line', 2): '1_2',
('line', 3): '1_2', ('quad', 2): '2_4', ('quad', 3): '2_4', ('tetra', 3): '3_4',
('triangle', 2): '2_3', ('triangle', 3): '2_3'}
format = 'meshio'
read(mesh, omit_facets=False, **kwargs)
read_bounding_box(ret_dim=False)
format = 'gambit'
read(mesh, **kwargs)
read_dimension(ret_fd=False)
get_filename_trunk()
read_bounding_box(ret_fd=False, ret_dim=False)
read_dimension(ret_fd=False)
sfepy.discrete.fem.meshio.check_format_suffix(file_format, suffix)
Check compatibility of a mesh file format and a mesh file suffix.
sfepy.discrete.fem.meshio.convert_complex_output(out_in)
Convert complex values in the output dictionary out_in to pairs of real and imaginary parts.
sfepy.discrete.fem.meshio.mesh_from_groups(mesh, ids, coors, ngroups, tris, mat_tris, quads, mat_quads,
tetras, mat_tetras, hexas, mat_hexas, remap=None)
sfepy.discrete.fem.meshio.output_mesh_formats(mode='r')
sfepy.discrete.fem.meshio.split_conns_mat_ids(conns_in)
Split connectivities (columns except the last ones in conns_in) from cell groups (the last columns of conns_in).
sfepy.discrete.fem.meshio.update_supported_formats(formats)
sfepy.discrete.fem.meshio.var
alias of sfepy.discrete.fem.meshio.XYZMeshIO
sfepy.discrete.fem.periodic module
sfepy.discrete.fem.periodic.get_grid_plane(idim)
sfepy.discrete.fem.periodic.set_accuracy(eps)
sfepy.discrete.fem.poly_spaces module
Notes
Naive proof-of-concept implementation, does not use recurrent formulas or Duffy transformation to obtain tensor
product structure.
name = 'bernstein_simplex'
class sfepy.discrete.fem.poly_spaces.BernsteinTensorProductPolySpace(name, geometry, order)
Bernstein polynomial space.
Each row of the nodes attribute defines indices of 1D Bernstein basis functions that need to be multiplied together
to evaluate the corresponding shape function. This defines the ordering of basis functions on the reference
element.
name = 'bernstein_tensor_product'
class sfepy.discrete.fem.poly_spaces.FEPolySpace(name, geometry, order)
Base for FE polynomial space classes.
describe_nodes()
get_mtx_i()
class sfepy.discrete.fem.poly_spaces.LagrangeNodes(**kwargs)
Helper class for defining nodes of Lagrange elements.
static append_bubbles(nodes, nts, iseq, nt, order)
name = 'lagrange_simplex_bubble'
class sfepy.discrete.fem.poly_spaces.LagrangeSimplexPolySpace(name, geometry, order,
init_context=True)
Lagrange polynomial space on a simplex domain.
name = 'lagrange_simplex'
class sfepy.discrete.fem.poly_spaces.LagrangeTensorProductPolySpace(name, geometry, order,
init_context=True)
Lagrange polynomial space on a tensor product domain.
get_mtx_i()
name = 'lagrange_tensor_product'
class sfepy.discrete.fem.poly_spaces.LobattoTensorProductPolySpace(name, geometry, order)
Hierarchical polynomial space using Lobatto functions.
Each row of the nodes attribute defines indices of Lobatto functions that need to be multiplied together to evaluate
the corresponding shape function. This defines the ordering of basis functions on the reference element.
name = 'lobatto_tensor_product'
class sfepy.discrete.fem.poly_spaces.NodeDescription(node_types, nodes)
Describe FE nodes defined on different parts of a reference element.
has_extra_nodes()
Return True if the element has some edge, face or bubble nodes.
class sfepy.discrete.fem.poly_spaces.SerendipityTensorProductPolySpace(name, geometry, order)
Serendipity polynomial space using Lagrange functions.
Notes
all_bfs = {2: {1: [[x*(y - 1.0) - y + 1.0, x*(1.0 - y), x*y, -x*y + y], [[y - 1.0,
x - 1.0], [1.0 - y, -x], [y, x], [-y, 1.0 - x]]], 2: [[x*(x*(2.0 - 2.0*y) + y*(5.0
- 2.0*y) - 3.0) + y*(2.0*y - 3.0) + 1.0, x*(x*(2.0 - 2.0*y) + y*(2.0*y - 1.0) -
1.0), x*(2.0*x*y + y*(2.0*y - 3.0)), x*(2.0*x*y + y*(-2.0*y - 1.0)) + y*(2.0*y -
1.0), x*(x*(4*y - 4) - 4*y + 4), x*y*(4.0 - 4.0*y), x*(-4.0*x*y + 4.0*y), x*y*(4.0*y
- 4.0) + y*(4.0 - 4.0*y)], [[x*(4.0 - 4.0*y) + y*(5.0 - 2.0*y) - 3.0, x*(-2.0*x -
4.0*y + 5.0) + 4.0*y - 3.0], [x*(4.0 - 4.0*y) + y*(2.0*y - 1.0) - 1.0, x*(-2.0*x +
4.0*y - 1.0)], [4.0*x*y + y*(2.0*y - 3.0), x*(2.0*x + 4.0*y - 3.0)], [4.0*x*y +
y*(-2.0*y - 1.0), x*(2.0*x - 4.0*y - 1.0) + 4.0*y - 1.0], [x*(8*y - 8) - 4*y + 4,
x*(4*x - 4)], [y*(4.0 - 4.0*y), x*(4.0 - 8.0*y)], [-8.0*x*y + 4.0*y, x*(4.0 -
4.0*x)], [y*(4.0*y - 4.0), x*(8.0*y - 4.0) - 8.0*y + 4.0]]], 3: [[x*(x*(x*(4.5*y -
4.5) - 9.0*y + 9.0) + y*(y*(4.5*y - 9.0) + 10.0) - 5.5) + y*(y*(9.0 - 4.5*y) - 5.5)
+ 1.0, x*(x*(x*(4.5 - 4.5*y) + 4.5*y - 4.5) + y*(y*(9.0 - 4.5*y) - 5.5) + 1.0),
x*(x*(4.5*x*y - 4.5*y) + y*(y*(4.5*y - 4.5) + 1.0)), x*(x*(-4.5*x*y + 9.0*y) +
y*(y*(4.5 - 4.5*y) - 5.5)) + y*(y*(4.5*y - 4.5) + 1.0), x*(x*(x*(13.5 - 13.5*y) +
22.5*y - 22.5) - 9.0*y + 9.0), x*(x*(x*(13.5*y - 13.5) - 18.0*y + 18.0) + 4.5*y -
4.5), x*y*(y*(13.5*y - 22.5) + 9.0), x*y*(y*(18.0 - 13.5*y) - 4.5), x*(x*(-13.5*x*y
+ 18.0*y) - 4.5*y), x*(x*(13.5*x*y - 22.5*y) + 9.0*y), x*y*(y*(13.5*y - 18.0) + 4.5)
+ y*(y*(18.0 - 13.5*y) - 4.5), x*y*(y*(22.5 - 13.5*y) - 9.0) + y*(y*(13.5*y - 22.5)
+ 9.0)], [[x*(x*(13.5*y - 13.5) - 18.0*y + 18.0) + y*(y*(4.5*y - 9.0) + 10.0) - 5.5,
x*(x*(4.5*x - 9.0) + y*(13.5*y - 18.0) + 10.0) + y*(18.0 - 13.5*y) - 5.5],
[x*(x*(13.5 - 13.5*y) + 9.0*y - 9.0) + y*(y*(9.0 - 4.5*y) - 5.5) + 1.0, x*(x*(4.5 -
4.5*x) + y*(18.0 - 13.5*y) - 5.5)], [x*(13.5*x*y - 9.0*y) + y*(y*(4.5*y - 4.5) +
1.0), x*(x*(4.5*x - 4.5) + y*(13.5*y - 9.0) + 1.0)], [x*(-13.5*x*y + 18.0*y) +
y*(y*(4.5 - 4.5*y) - 5.5), x*(x*(9.0 - 4.5*x) + y*(9.0 - 13.5*y) - 5.5) + y*(13.5*y
- 9.0) + 1.0], [x*(x*(40.5 - 40.5*y) + 45.0*y - 45.0) - 9.0*y + 9.0, x*(x*(22.5 -
13.5*x) - 9.0)], [x*(x*(40.5*y - 40.5) - 36.0*y + 36.0) + 4.5*y - 4.5, x*(x*(13.5*x
- 18.0) + 4.5)], [y*(y*(13.5*y - 22.5) + 9.0), x*(y*(40.5*y - 45.0) + 9.0)],
[y*(y*(18.0 - 13.5*y) - 4.5), x*(y*(36.0 - 40.5*y) - 4.5)], [x*(-40.5*x*y + 36.0*y)
- 4.5*y, x*(x*(18.0 - 13.5*x) - 4.5)], [x*(40.5*x*y - 45.0*y) + 9.0*y, x*(x*(13.5*x
- 22.5) + 9.0)], [y*(y*(13.5*y - 18.0) + 4.5), x*(y*(40.5*y - 36.0) + 4.5) + y*(36.0
- 40.5*y) - 4.5], [y*(y*(22.5 - 13.5*y) - 9.0), x*(y*(45.0 - 40.5*y) - 9.0) +
y*(40.5*y - 45.0) + 9.0]]]}, 3: {1: [[x*(y*(1.0 - z) + z - 1.0) + y*(z - 1.0) - z
+ 1.0, x*(y*(z - 1.0) - z + 1.0), x*y*(1.0 - z), x*y*(z - 1.0) + y*(1.0 - z), x*(y*z
- z) - y*z + z, x*(-y*z + z), x*y*z, -x*y*z + y*z], [[y*(1.0 - z) + z - 1.0, x*(1.0
- z) + z - 1.0, x*(1.0 - y) + y - 1.0], [y*(z - 1.0) - z + 1.0, x*(z - 1.0), x*(y -
1.0)], [y*(1.0 - z), x*(1.0 - z), -x*y], [y*(z - 1.0), x*(z - 1.0) - z + 1.0, x*y -
y], [y*z - z, x*z - z, x*(y - 1.0) - y + 1.0], [-y*z + z, -x*z, x*(1.0 - y)], [y*z,
x*z, x*y], [-y*z, -x*z + z, -x*y + y]]], 2: [[x*(x*(y*(2.0*z - 2.0) - 2.0*z + 2.0)
+ y*(y*(2.0*z - 2.0) + z*(2.0*z - 7.0) + 5.0) + z*(5.0 - 2.0*z) - 3.0) + y*(y*(2.0 -
2.0*z) + z*(5.0 - 2.0*z) - 3.0) + z*(2.0*z - 3.0) + 1.0, x*(x*(y*(2.0*z - 2.0) -
2.0*z + 2.0) + y*(y*(2.0 - 2.0*z) + z*(3.0 - 2.0*z) - 1.0) + z*(2.0*z - 1.0) - 1.0),
x*(x*y*(2.0 - 2.0*z) + y*(y*(2.0 - 2.0*z) + z*(2.0*z + 1.0) - 3.0)), x*(x*y*(2.0 -
2.0*z) + y*(y*(2.0*z - 2.0) + z*(3.0 - 2.0*z) - 1.0)) + y*(y*(2.0 - 2.0*z) +
z*(2.0*z - 1.0) - 1.0), x*(x*(-2.0*y*z + 2.0*z) + y*(-2.0*y*z + z*(2.0*z + 3.0)) +
z*(-2.0*z - 1.0)) + y*(2.0*y*z + z*(-2.0*z - 1.0)) + z*(2.0*z - 1.0), x*(x*(-2.0*y*z
+ 2.0*z) + y*(2.0*y*z + z*(1.0 - 2.0*z)) + z*(2.0*z - 3.0)), x*(2.0*x*y*z +
y*(2.0*y*z + z*(2.0*z - 5.0))), x*(2.0*x*y*z + y*(-2.0*y*z + z*(1.0 - 2.0*z))) +
y*(2.0*y*z + z*(2.0*z - 3.0)), x*(x*(y*(4.0 - 4.0*z) + 4.0*z - 4.0) + y*(4.0*z -
4.0) - 4.0*z + 4.0), x*y*(y*(4.0*z - 4.0) - 4.0*z + 4.0), x*(x*y*(4.0*z - 4.0) +
y*(4.0 - 4.0*z)), x*y*(y*(4.0 - 4.0*z) + 4.0*z - 4.0) + y*(y*(4.0*z - 4.0) - 4.0*z +
4.0), x*(x*(4.0*y*z - 4.0*z) - 4.0*y*z + 4.0*z), x*y*(-4.0*y*z + 4.0*z),
x*(-4.0*x*y*z + 4.0*y*z), x*y*(4.0*y*z - 4.0*z) + y*(-4.0*y*z + 4.0*z), x*(y*z*(4.0
- 4.0*z) + z*(4.0*z - 4.0)) + y*z*(4.0*z - 4.0) + z*(4.0 - 4.0*z), x*(y*z*(4.0*z -
4.0) + z*(4.0 - 4.0*z)), x*y*z*(4.0 - 4.0*z), x*y*z*(4.0*z - 4.0) + y*z*(4.0 -
4.0*z)], [[x*(y*(4.0*z - 4.0) - 4.0*z + 4.0) + y*(y*(2.0*z - 2.0) + z*(2.0*z - 7.0)
758 + 5.0) + z*(5.0 - 2.0*z) - 3.0, x*(x*(2.0*z - 2.0) + y*(4.0*z -Chapter
4.0) +2.z*(2.0*z
Development
-
7.0) + 5.0) + y*(4.0 - 4.0*z) + z*(5.0 - 2.0*z) - 3.0, x*(x*(2.0*y - 2.0) + y*(2.0*y
+ 4.0*z - 7.0) - 4.0*z + 5.0) + y*(-2.0*y - 4.0*z + 5.0) + 4.0*z - 3.0],
[x*(y*(4.0*z - 4.0) - 4.0*z + 4.0) + y*(y*(2.0 - 2.0*z) + z*(3.0 - 2.0*z) - 1.0) +
SfePy Documentation, Release version: 2022.2
name = 'serendipity_tensor_product'
supported_orders = {1, 2, 3}
sfepy.discrete.fem.refine module
Notes
The error edges must be generated in the order of the connectivity of the previous (lower) level.
sfepy.discrete.fem.refine_hanging module
Notes
sfepy.discrete.fem._serendipity module
sfepy.discrete.fem.utils module
is_surface [bool] If True, the data are defined on a surface region. In that case the values are
averaged or summed into the cells containing the region surface faces (a cell can have several
faces of the surface), see average_surface.
average_surface [bool] If True, the data defined on a surface region are averaged, otherwise the
data are summed.
Returns
edata [array] The data extended to all domain elements.
sfepy.discrete.fem.utils.get_edge_paths(graph, mask)
Get all edge paths in a graph with non-masked vertices. The mask is updated.
sfepy.discrete.fem.utils.get_min_value(dofs)
Get a reasonable minimal value of DOFs suitable for extending over a whole domain.
sfepy.discrete.fem.utils.invert_remap(remap)
Return the inverse of remap, i.e. a mapping from a sub-range indices to a full range, see prepare_remap().
sfepy.discrete.fem.utils.prepare_remap(indices, n_full)
Prepare vector for remapping range [0, n_full] to its subset given by indices.
sfepy.discrete.fem.utils.prepare_translate(old_indices, new_indices)
Prepare vector for translating old_indices to new_indices.
Returns
translate [array] The translation vector. Then new_ar = translate[old_ar].
sfepy.discrete.fem.utils.refine_mesh(filename, level)
Uniformly refine level-times a mesh given by filename.
The refined mesh is saved to a file with name constructed from base name of filename and level-times appended
‘_r’ suffix.
Parameters
filename [str] The mesh file name.
level [int] The refinement level.
sfepy.discrete.dg sub-package
sfepy.discrete.dg.dg_1D_vizualizer module
Module for animating solutions in 1D. Can also save them but requieres ffmpeg package see save_animation method.
sfepy.discrete.dg.dg_1D_vizualizer.animate1D_dgsol(Y, X, T, ax=None, fig=None, ylims=None,
labs=None, plott=None, delay=None)
Animates solution of 1D problem into current figure. Keep reference to returned animation object otherwise it
is discarded
Parameters
Y : solution, array |T| x |X| x n, where n is dimension of the solution
X : space interval discetization
T : time interval discretization
ax : specify axes to plot to (Default value = None)
fig : specifiy figure to plot to (Default value = None)
Parameters
coors : coordinates of the mesh
t0 [float] starting time
t1 [float] final time
u : vectors of DOFs, for each order one, shape(u) = (order, nspace_steps, ntime_steps, 1)
ic : analytical initial condition, optional (Default value = lambda x: 0.0)
tn : number of time steps to plot, starting at 0, if None and dt is not None run animation through
all time steps, spaced dt within [t0, tn] (Default value = None)
dt : time step size, if None and tn is not None computed as (t1- t0) / tn otherwise set to 1 if
dt and tn are both None, t0 and t1 are ignored and solution is animated as if in time 0 . . .
ntime_steps (Default value = None)
exact : (Default value = lambda x)
t: 0 :
delay : (Default value = None)
polar : (Default value = False)
Returns
anim_dofs [animation object of DOFs,]
anim_recon [animation object of reconstructed solution]
sfepy.discrete.dg.dg_1D_vizualizer.head(l)
Maybe get head of the list.
Parameters
l [indexable]
Returns
head [first element in l or None is l is empty]
sfepy.discrete.dg.dg_1D_vizualizer.load_1D_vtks(fold, name)
Reads series of .vtk files and crunches them into form suitable for plot10_DG_sol.
Attempts to read modal cell data for variable mod_data. i.e.
?_modal{i}, where i is number of modal DOF
Resulting solution data have shape: (order, nspace_steps, ntime_steps, 1)
Parameters
fold : folder where to look for files
name : used in {name}.i.vtk, i = 0,1, ... tns - 1
Returns
coors [ndarray]
mod_data [ndarray] solution data
sfepy.discrete.dg.dg_1D_vizualizer.load_state_1D_vtk(name)
Load one VTK file containing state in time
Parameters
name [str]
Returns
coors [ndarray]
u [ndarray]
sfepy.discrete.dg.dg_1D_vizualizer.plot1D_legendre_dofs(coors, dofss, fun=None)
Plots values of DOFs as steps
Parameters
coors : coordinates of nodes of the mesh
dofss : iterable of different projections’ DOFs into legendre space
fun : analytical function to plot (Default value = None)
sfepy.discrete.dg.dg_1D_vizualizer.plotsXT(Y1, Y2, YE, extent, lab1=None, lab2=None, lab3=None)
Plots Y1 and Y2 to one axes and YE to the second axes, Y1 and Y2 are presumed to be two solutions and YE
their error
Parameters
Y1 : solution 1, shape = (space nodes, time nodes)
Y2 : solution 2, shape = (space nodes, time nodes)
YE : soulutio 1 - soulution 2||
extent : imshow extent
lab1 : (Default value = None)
lab2 : (Default value = None)
lab3 : (Default value = None)
sfepy.discrete.dg.dg_1D_vizualizer.reconstruct_legendre_dofs(coors, tn, u)
Creates solution and coordinates vector which when plotted as
plot(xx, ww)
represent solution reconstructed from DOFs in Legendre poly space at cell borders.
Works only as linear interpolation between cell boundary points
Parameters
coors : coors of nodes of the mesh
u : vectors of DOFs, for each order one, shape(u) = (order, nspace_steps, ntime_steps, 1)
tn : number of time steps to reconstruct, if None all steps are reconstructed
Returns
ww [ndarray] solution values vector, shape is (3 * nspace_steps - 1, ntime_steps, 1),
xx [ndarray] corresponding coordinates vector, shape is (3 * nspace_steps - 1, 1)
sfepy.discrete.dg.dg_1D_vizualizer.save_animation(anim, filename)
Saves animation as .mp4, requires ffmeg package
Parameters
anim : animation object
filename : name of the file, without the .mp4 ending
sfepy.discrete.dg.dg_1D_vizualizer.save_sol_snap(Y, X, T, t0=0.5, filename=None, name=None,
ylims=None, labs=None, plott=None)
Wrapper for sol_frame, saves the frame to file specified.
Parameters
name : name of the solution e.g. name of the solver used (Default value = None)
filename : name of the file, overrides automatic generation (Default value = None)
Y : solution, array |T| x |X| x n, where n is dimension of the solution
X : space interval discetization
T : time interval discretization
t0 : time to take snap at (Default value = .5)
ylims : limits for y axis, default are 10% offsets of Y extremes
labs : labels to use for parts of the solution (Default value = None)
plott : plot type - how to plot data: tested plot, step (Default value = None)
Returns
fig
sfepy.discrete.dg.dg_1D_vizualizer.setup_axis(X, Y, ax=None, fig=None, ylims=None)
Setup axis, including timer for animation or snaps
Parameters
X : space disctretization to get limits
Y : solution to get limits
ax : ax where to put everything, if None current axes are used (Default value = None)
fig : fig where to put everything, if None current figure is used (Default value = None)
ylims : custom ylims, if None y axis limits are calculated from Y (Default value = None)
Returns
ax
fig
time_text object to fill in text
sfepy.discrete.dg.dg_1D_vizualizer.setup_lines(ax, Yshape, labs, plott)
Sets up artist for animation or solution snaps
Parameters
ax : axes to use for artist
Yshape [tuple] shape of the solution array
labs [list] labels for the solution
plott [str (“steps” or “plot”)] type of plot to use
Returns
lines
sfepy.discrete.dg.dg_1D_vizualizer.sol_frame(Y, X, T, t0=0.5, ax=None, fig=None, ylims=None,
labs=None, plott=None)
Creates snap of solution at specified time frame t0, basically gets one frame from animate1D_dgsol, but colors
wont be the same :-(
Parameters
Y : solution, array |T| x |X| x n, where n is dimension of the solution
X : space interval discetization
T : time interval discretization
t0 : time to take snap at (Default value = .5)
ax : specify axes to plot to (Default value = None)
fig : specifiy figure to plot to (Default value = None)
ylims : limits for y axis, default are 10% offsets of Y extremes
labs : labels to use for parts of the solution (Default value = None)
plott : plot type - how to plot data: tested plot, step (Default value = None)
Returns
fig
sfepy.discrete.dg.fields module
Parameters
region [sfepy.discrete.common.region.Region] If None clear all.
clear_facet_qp_base()
Clears facet_qp_base cache
clear_facet_vols_cache(region=None)
Clears facet volume cache for given region or all regions.
Parameters
region [sfepy.discrete.common.region.Region] region to clear cache or None to clear all
clear_normals_cache(region=None)
Clears normals cache for given region or all regions.
Parameters
region [sfepy.discrete.common.region.Region] region to clear cache or None to clear all
create_mapping(region, integral, integration, return_mapping=True)
Creates and returns mapping
Parameters
region [sfepy.discrete.common.region.Region]
integral [Integral]
integration [str] ‘volume’ is only accepted option
return_mapping [default True] (Default value = True)
Returns
mapping [VolumeMapping]
create_output(dofs, var_name, dof_names=None, key=None, extend=True, fill_value=None,
linearization=None)
Converts the DOFs corresponding to the field to a dictionary of output data usable by Mesh.write().
For 1D puts DOFs into vairables u_modal{0} . . . u_modal{n}, where n = approx_order and marks them
for writing as cell data.
For 2+D puts dofs into name_cell_nodes and creates sturct with: mode = “cell_nodes”, data and iterpolation
scheme.
Also get node values and adds them to dictionary as cell_nodes
Parameters
dofs [ndarray, shape (n_nod, n_component)] The array of DOFs reshaped so that each col-
umn corresponds to one component.
var_name [str] The variable name corresponding to dofs.
dof_names [tuple of str] The names of DOF components. (Default value = None)
key [str, optional] The key to be used in the output dictionary instead of the variable name.
(Default value = None)
extend [bool, not used] Extend the DOF values to cover the whole domain. (Default value =
True)
fill_value [float or complex, not used] The value used to fill the missing DOF values if extend
is True. (Default value = None)
linearization [Struct or None, not used] The linearization configuration for higher order ap-
proximations. (Default value = None)
Returns
out [dict]
family_name = 'volume_DG_legendre_discontinuous'
get_bc_facet_idx(region)
Caches results in self.boundary_facet_local_idx
Parameters
region [sfepy.discrete.common.region.Region] surface region defining BCs
Returns
bc2bfi [ndarray] index of cells on boundary along with corresponding facets
get_bc_facet_values(fun, region, ret_coors=False, diff=0)
Returns values of fun in facet QPs of the region
Parameters
diff: derivative 0 or 1 supported
fun: Function value or values to set qps values to
region [sfepy.discrete.common.region.Region] boundary region
ret_coors: default False, Return physical coors of qps in shape (n_cell, n_qp, dim).
Returns
vals [ndarray] In shape (n_cell,) + (self.dim,) * diff + (n_qp,)
get_both_facet_base_vals(state, region, derivative=None)
Returns values of the basis function in quadrature points on facets broadcasted to all cells inner to the
element as well as outer ones along with weights for the qps broadcasted and transformed to elements.
Contains quick fix to flip facet QPs for right integration order.
Parameters
state [used to get EPBC info]
region [sfepy.discrete.common.region.Region for connectivity]
derivative [if u need derivative] (Default value = None)
Returns
outer_facet_base_vals:
inner_facet_base_vals:
shape (n_cell, n_el_nod, n_el_facet, n_qp) or (n_cell, n_el_nod, n_el_facet, dim, n_qp)
when derivative is True or 1
whs: shape (n_cell, n_el_facet, n_qp)
get_both_facet_state_vals(state, region, derivative=None, reduce_nod=True)
Computes values of the variable represented by dofs in quadrature points located at facets, returns both
values - inner and outer, along with weights.
Parameters
end for derivatine: (1, number of qps, (dim,) * derivative, n_el_facets, 1, n_el_nod)
Parameters
derivative: truthy or integer
base_only: do not return weights
Returns
facet_bf [ndarray] values of basis functions in facet qps
weights [ndarray, optionally] weights of qps
get_facet_neighbor_idx(region=None, eq_map=None)
Returns index of cell neighbours sharing facet, along with local index of the facet within neighbour, also
treats periodic boundary conditions i.e. plugs correct neighbours for cell on periodic boundary. Where
there are no neighbours specified puts -1 instead of neighbour and facet id
Cashes neighbour index in self.facet_neighbours
Parameters
region [sfepy.discrete.common.region.Region] Main region, must contain cells.
eq_map : eq_map from state variable containing information on EPBC and DG EPBC. (De-
fault value = None)
Returns
facet_neighbours [ndarray]
Shape is (n_cell, n_el_facet, 2),
first value is index of the neighbouring cell, the second is index of the facet in said nb. cell.
get_facet_qp()
Returns quadrature points on all facets of the reference element in array of shape (n_qp, 1 , n_el_facets,
dim)
Returns
qps [ndarray] quadrature points
weights [ndarray] Still needs to be transformed to actual facets!
get_facet_vols(region)
Caches results, use clear_facet_vols_cache to clear the cache
Parameters
region [sfepy.discrete.common.region.Region]
Returns
vols_out: ndarray volumes of the facets by cells shape (n_cell, n_el_facets, 1)
get_nodal_values(dofs, region, ref_nodes=None)
Computes nodal representation of the DOFs
dofs [array_like] dofs to transform to nodes
region : ignored
ref_nodes: reference node to use instead of default qps
Parameters
dofs [array_like]
region [Region]
ref_nodes [array_like] (Default value = None)
Returns
nodes [ndarray]
nodal_vals [ndarray]
static get_region_info(region)
Extracts information about region needed in various methods of DGField
Parameters
region [sfepy.discrete.common.region.Region]
Returns
dim, n_cell, n_el_facets
is_surface = False
set_cell_dofs(fun=0.0, region=None, dpn=None, warn=None)
Compute projection of fun onto the basis, in main region, alternatively set DOFs directly to provided value
or values
Parameters
fun [callable, scallar or array corresponding to dofs] (Default value = 0.0)
region [sfepy.discrete.common.region.Region] region to set DOFs on (Default value = None)
dpn [number of dofs per element] (Default value = None)
warn [not used] (Default value = None)
Returns
nods [ndarray]
vals [ndarray]
Parameters
region [sfepy.discrete.common.region.Region]
Returns
gel : base geometry element of the region
sfepy.discrete.dg.fields.get_raveler(n_el_nod, n_cell)
Returns function for raveling i.e. packing dof data from two dimensional array of shape (n_cell, n_el_nod, 1) to
(n_el_nod*n_cell, 1)
The raveler returns view into the input array.
Parameters
n_el_nod : param n_el_nod, n_cell: expected dimensions of dofs array
n_cell [int]
Returns
ravel [callable]
sfepy.discrete.dg.fields.get_unraveler(n_el_nod, n_cell)
Returns function for unraveling i.e. unpacking dof data from serialized array from shape (n_el_nod*n_cell, 1)
to (n_cell, n_el_nod, 1).
The unraveler returns non-writeable view into the input array.
Parameters
n_el_nod [int] expected dimensions of dofs array
n_cell [int]
Returns
unravel [callable]
sfepy.discrete.dg.poly_spaces module
with
(0) (1) (2)
𝑝𝑗 (𝑢, 𝑣, 𝑤) = 𝑢𝑃𝑗 · 𝑣 𝑃𝑗 · 𝑤𝑃𝑗 (u, v and w being the coordinates in the element’s parameter space),
then val-coef-matrix denotes the n x n matrix F and val-exp-matrix denotes the n x 3 matrix P where n is
number of basis functions as calculated by get_n_el_nod.
Expects matrices to be saved in atributes coefM and expoM!
Returns
interp_scheme_struct [Struct] Struct with name of the scheme, geometry desc and P and F
get_nth_fun(n)
Uses shifted Legendre polynomials formula on interval [0, 1].
Convenience function for testing
Parameters
n [int]
Returns
fun [callable] n-th function of the legendre basis
get_nth_fun_der(n, diff=1)
Returns diff derivative of nth function. Uses shifted legendre polynomials formula on interval [0, 1].
Useful for testing.
Parameters
n [int]
diff [int] (Default value = 1)
Returns
fun [callable] derivative of n-th function of the 1D legendre basis
gradjacobiP(coors, alpha, beta, diff=1)
diff derivative of the jacobi polynomials on interval [-1, 1] up to self.order + 1 at coors
Parameters
coors :
alpha [float]
beta [float]
diff [int] (Default value = 1)
Returns
values [ndarray] output shape is shape(coor) + (self.order + 1,)
gradlegendreP(coors, diff=1)
Parameters
diff [int] default 1
coors [array_like] coordinates, preferably in interval [-1, 1] for which this basis is intented
Returns
values [ndarray] values at coors of all the legendre polynomials up to self.order
jacobiP(coors, alpha, beta)
Values of the jacobi polynomials on interval [-1, 1] up to self.order + 1 at coors
Parameters
coors [array_like]
beta [float]
alpha [float]
Returns
values [ndarray] output shape is shape(coor) + (self.order + 1,)
legendreP(coors)
Parameters
coors [array_like] coordinates, preferably in interval [-1, 1] for which this basis is intented
Returns
values [ndarray] values at coors of all the legendre polynomials up to self.order
legendre_funs = [<function LegendrePolySpace.<lambda>>, <function
LegendrePolySpace.<lambda>>, <function LegendrePolySpace.<lambda>>, <function
LegendrePolySpace.<lambda>>, <function LegendrePolySpace.<lambda>>, <function
LegendrePolySpace.<lambda>>]
class sfepy.discrete.dg.poly_spaces.LegendreSimplexPolySpace(name, geometry, order,
extended=False)
name = 'legendre_simplex'
class sfepy.discrete.dg.poly_spaces.LegendreTensorProductPolySpace(name, geometry, order)
build_interpol_scheme()
Builds F and P matrices returned by self.get_interpol_scheme.
Note that this function returns coeficients according to gmsh parametrization of Quadrangle i.e. [-1, 1] x [-1,
1] and hence the form of basis function is not the same as exhibited by the LegendreTensorProductPolySpace
object which acts on parametrization [0, 1] x [0, 1].
Returns
F [ndarray] coefficient matrix
P [ndarray] exponent matrix
name = 'legendre_tensor_product'
sfepy.discrete.dg.poly_spaces.get_n_el_nod(order, dim, extended=False)
Number of nodes per element for discontinuous legendre basis, i.e. number of iterations yielded by iter_by_order
When extended is False
(𝑛 + 1) · (𝑛 + 2) · ... · (𝑛 + 𝑑)
𝑁𝑝 =
𝑑!
where n is the order and d the dimension. When extended is True
𝑁𝑝 = (𝑛 + 1)𝑑
Parameters
order [int] desired order of multidimensional basis
dim [int] dimension of the basis
extended [bool] iterate over extended tensor product basis (Default value = False)
Yields
idx [tuple] containing basis function indexes, used in _combine_polyvals and
_combine_polyvals_der
sfepy.discrete.dg.limiters module
sfepy.solvers.ts_dg_solvers module
solve_step0(nls, vec0)
p(1) = p𝑛 − ∆𝑡ℒ̄(p𝑛 ),
3 1 1
p(2) = p𝑛 + p(1) − ∆𝑡ℒ̄(p(1) ),
4 4 4
1 2 2
p(𝑛+1) = p𝑛 + p(2) − ∆𝑡ℒ̄(p(2) ).
3 3 3
Kind: ‘ts.tvd_runge_kutta_3’
For common configuration parameters, see Solver.
Specific configuration parameters:
name = 'ts.tvd_runge_kutta_3'
solve_step(ts, nls, vec_x0, status=None, prestep_fun=None, poststep_fun=None)
sfepy.discrete.iga sub-package
sfepy.discrete.iga.domain module
write_domain_to_hdf5(fd, group)
Save the domain to a hdf5 file.
fd: tables.File HDF5 file handle to write the mesh to.
group: tables.group.Group HDF5 data group (of file fd) to write the mesh to.
class sfepy.discrete.iga.domain.NurbsPatch(knots, degrees, cps, weights, cs, conn)
Single NURBS patch data.
elevate(times=0)
Elevate the patch degrees several times by one.
Returns
nurbs [NurbsPatch instance] Either self if times is zero, or a new instance.
evaluate(field, u=None, v=None, w=None)
Igakit-like interface for NURBS evaluation.
sfepy.discrete.iga.domain_generators module
Returns
nurbs [NurbsPatch instance] The NURBS data. The igakit NURBS object is stored as nurbs
attribute.
bmesh [Struct instance] The Bezier mesh data.
regions [dict] The patch surface regions.
sfepy.discrete.iga.extmods.igac module
class sfepy.discrete.iga.extmods.igac.CNURBSContext
R
bf
bfg
bufBN
cprint()
dR_dx
dR_dxi
e_coors_max
evaluate()
iel
sfepy.discrete.iga.extmods.igac.eval_bernstein_basis()
sfepy.discrete.iga.extmods.igac.eval_in_tp_coors()
Evaluate a field variable (if given) or the NURBS geometry in the given tensor-product reference coordinates.
The field variable is defined by its DOFs - the coefficients of the NURBS basis.
Parameters
variable [array] The DOF values of the variable with n_c components, shape (:, n_c).
indices [list of arrays] The indices of knot spans for each axis, defining the Bezier element num-
bers.
ref_coors [list of arrays] The reference coordinates in [0, 1] for each knot span for each axis,
defining the reference coordinates in the Bezier elements given by indices.
control_points [array] The NURBS control points.
weights [array] The NURBS weights.
degrees [sequence of ints or int] The basis degrees in each parametric dimension.
cs [list of lists of 2D arrays] The element extraction operators in each parametric dimension.
conn [array] The connectivity of the global NURBS basis.
Returns
out [array] The field variable values or NURBS geometry coordinates for the given reference
coordinates.
sfepy.discrete.iga.extmods.igac.eval_mapping_data_in_qp()
Evaluate data required for the isogeometric domain reference mapping in the given quadrature points. The
quadrature points are the same for all Bezier elements and should correspond to the Bernstein basis degree.
Parameters
qps [array] The quadrature points coordinates with components in [0, 1] reference element do-
main.
control_points [array] The NURBS control points.
weights [array] The NURBS weights.
degrees [sequence of ints or int] The basis degrees in each parametric dimension.
cs [list of lists of 2D arrays] The element extraction operators in each parametric dimension.
conn [array] The connectivity of the global NURBS basis.
cells [array, optional] If given, use only the given Bezier elements.
Returns
bfs [array] The NURBS shape functions in the physical quadrature points of all elements.
bfgs [array] The NURBS shape functions derivatives w.r.t. the physical coordinates in the phys-
ical quadrature points of all elements.
dets [array] The Jacobians of the mapping to the unit reference element in the physical quadra-
ture points of all elements.
sfepy.discrete.iga.extmods.igac.eval_variable_in_qp()
Evaluate a field variable in the given quadrature points. The quadrature points are the same for all Bezier elements
and should correspond to the Bernstein basis degree. The field variable is defined by its DOFs - the coefficients
of the NURBS basis.
Parameters
variable [array] The DOF values of the variable with n_c components, shape (:, n_c).
qps [array] The quadrature points coordinates with components in [0, 1] reference element do-
main.
control_points [array] The NURBS control points.
weights [array] The NURBS weights.
degrees [sequence of ints or int] The basis degrees in each parametric dimension.
cs [list of lists of 2D arrays] The element extraction operators in each parametric dimension.
conn [array] The connectivity of the global NURBS basis.
cells [array, optional] If given, use only the given Bezier elements.
Returns
coors [array] The physical coordinates of the quadrature points of all elements.
vals [array] The field variable values in the physical quadrature points.
dets [array] The Jacobians of the mapping to the unit reference element in the physical quadra-
ture points.
sfepy.discrete.iga.extmods.igac.is_nurbs()
Return True if some weights are not one.
sfepy.discrete.iga.fields module
Notes
The field has to cover the whole IGA domain. The field’s NURBS basis can have higher degree than the domain
NURBS basis.
create_basis_context()
Create the context required for evaluating the field basis.
create_eval_mesh()
Create a mesh with the original NURBS connectivity for evaluating the field. The mesh coordinates are
the NURBS control points.
create_mapping(region, integral, integration)
Create a new reference mapping.
create_mesh(extra_nodes=True)
Create a mesh corresponding to the field region. For IGA fields, this is directly the topological mesh. The
extra_nodes argument is ignored.
create_output(dofs, var_name, dof_names=None, key=None, **kwargs)
Convert the DOFs corresponding to the field to a dictionary of output data usable by Mesh.write().
Parameters
dofs [array, shape (n_nod, n_component)] The array of DOFs reshaped so that each column
corresponds to one component.
var_name [str] The variable name corresponding to dofs.
dof_names [tuple of str] The names of DOF components.
key [str, optional] The key to be used in the output dictionary instead of the variable name.
Returns
out [dict] The output dictionary.
family_name = 'volume_H1_iga'
get_data_shape(integral, integration='volume', region_name=None)
Get element data dimensions.
Parameters
integral [Integral instance] The integral describing used numerical quadrature.
integration [‘volume’] The term integration type. Only ‘volume’ type is implemented.
region_name [str] The name of the region of the integral.
Returns
data_shape [4 ints] The (n_el, n_qp, dim, n_en) for volume shape kind.
Notes
get_dofs_in_region(region, merge=True)
Return indices of DOFs that belong to the given region and group.
Notes
get_true_order()
is_higher_order()
Return True, if the field’s approximation order is greater than one.
setup_extra_data(geometry, info, is_trace)
sfepy.discrete.iga.fields.parse_approx_order(approx_order)
sfepy.discrete.iga.iga module
Notes
degrees [sequence of ints or int] The basis degrees in each parametric dimension.
Returns
conn [array] The connectivity of the global NURBS basis.
bconn [array] The connectivity of the Bezier basis.
sfepy.discrete.iga.iga.create_connectivity_1d(n_el, knots, degree)
Create connectivity arrays of 1D Bezier elements.
Parameters
n_el [int] The number of elements.
knots [array] The knot vector.
degree [int] The basis degree.
Returns
conn [array] The connectivity of the global NURBS basis.
bconn [array] The connectivity of the Bezier basis.
sfepy.discrete.iga.iga.eval_bernstein_basis(x, degree)
Evaluate the Bernstein polynomial basis of the given degree, and its derivatives, in a point x in [0, 1].
Parameters
x [float] The point in [0, 1].
degree [int] The basis degree.
Returns
funs [array] The degree + 1 values of the Bernstein polynomial basis.
ders [array] The degree + 1 values of the Bernstein polynomial basis derivatives.
sfepy.discrete.iga.iga.eval_mapping_data_in_qp(qps, control_points, weights, degrees, cs, conn,
cells=None)
Evaluate data required for the isogeometric domain reference mapping in the given quadrature points. The
quadrature points are the same for all Bezier elements and should correspond to the Bernstein basis degree.
Parameters
qps [array] The quadrature points coordinates with components in [0, 1] reference element do-
main.
control_points [array] The NURBS control points.
weights [array] The NURBS weights.
degrees [sequence of ints or int] The basis degrees in each parametric dimension.
cs [list of lists of 2D arrays] The element extraction operators in each parametric dimension.
conn [array] The connectivity of the global NURBS basis.
cells [array, optional] If given, use only the given Bezier elements.
Returns
bfs [array] The NURBS shape functions in the physical quadrature points of all elements.
bfgs [array] The NURBS shape functions derivatives w.r.t. the physical coordinates in the phys-
ical quadrature points of all elements.
dets [array] The Jacobians of the mapping to the unit reference element in the physical quadra-
ture points of all elements.
sfepy.discrete.iga.iga.eval_nurbs_basis_tp(qp, ie, control_points, weights, degrees, cs, conn)
Evaluate the tensor-product NURBS shape functions in a quadrature point for a given Bezier element.
Parameters
qp [array] The quadrature point coordinates with components in [0, 1] reference element do-
main.
ie [int] The Bezier element index.
control_points [array] The NURBS control points.
weights [array] The NURBS weights.
degrees [sequence of ints or int] The basis degrees in each parametric dimension.
cs [list of lists of 2D arrays] The element extraction operators in each parametric dimension.
conn [array] The connectivity of the global NURBS basis.
Returns
R [array] The NURBS shape functions.
dR_dx [array] The NURBS shape functions derivatives w.r.t. the physical coordinates.
det [array] The Jacobian of the mapping to the unit reference element.
sfepy.discrete.iga.iga.eval_variable_in_qp(variable, qps, control_points, weights, degrees, cs, conn,
cells=None)
Evaluate a field variable in the given quadrature points. The quadrature points are the same for all Bezier elements
and should correspond to the Bernstein basis degree. The field variable is defined by its DOFs - the coefficients
of the NURBS basis.
Parameters
variable [array] The DOF values of the variable with n_c components, shape (:, n_c).
qps [array] The quadrature points coordinates with components in [0, 1] reference element do-
main.
control_points [array] The NURBS control points.
weights [array] The NURBS weights.
degrees [sequence of ints or int] The basis degrees in each parametric dimension.
cs [list of lists of 2D arrays] The element extraction operators in each parametric dimension.
conn [array] The connectivity of the global NURBS basis.
cells [array, optional] If given, use only the given Bezier elements.
Returns
coors [array] The physical coordinates of the quadrature points of all elements.
vals [array] The field variable values in the physical quadrature points.
dets [array] The Jacobians of the mapping to the unit reference element in the physical quadra-
ture points.
sfepy.discrete.iga.iga.get_bezier_element_entities(degrees)
Get faces and edges of a Bezier mesh element in terms of indices into the element’s connectivity (reference
Bezier element entities).
Parameters
degrees [sequence of ints or int] Polynomial degrees in each parametric dimension.
Returns
faces [list of arrays] The indices for each face or None if not 3D.
edges [list of arrays] The indices for each edge or None if not at least 2D.
vertices [list of arrays] The indices for each vertex.
Notes
sfepy.discrete.iga.io module
Returns
tuple Data for restoring IGA domain.
Returns
tuple Data for restoring IGA domain.
sfepy.discrete.iga.mappings module
nurbs [NurbsPatch instance, optional] If given, the nurbs is used instead of domain.nurbs. The
nurbs has to be obtained by degree elevation of domain.nurbs.
get_geometry()
Return reference element geometry as a GeometryElement instance.
get_mapping(qp_coors, weights)
Get the mapping for given quadrature points and weights.
Returns
cmap [CMapping instance] The reference mapping.
Notes
sfepy.discrete.iga.plot_nurbs module
sfepy.discrete.iga.utils module
pars [sequence of array, optional] The values of parameters in each parametric dimension. If
not given, the values are set so that the resulting mesh has the same number of vertices as
the number of control points/basis functions of the NURBS object.
Returns
coors [array] The coordinates of mesh vertices.
conn [array] The vertex connectivity array.
desc [str] The cell kind.
sfepy.discrete.iga.utils.create_mesh_and_output(nurbs, pars=None, **kwargs)
Create a nD-linear tensor product FE mesh using create_linear_fe_mesh(), evaluate field variables given
as keyword arguments in the mesh vertices and create a dictionary of output data usable by Mesh.write().
Parameters
nurbs [igakit.nurbs.NURBS instance] The NURBS object.
pars [sequence of array, optional] The values of parameters in each parametric dimension. If
not given, the values are set so that the resulting mesh has the same number of vertices as
the number of control points/basis functions of the NURBS object.
**kwargs [kwargs] The field variables as keyword arguments. Their names serve as keys in the
output dictionary.
Returns
mesh [Mesh instance] The finite element mesh.
out [dict] The output dictionary.
sfepy.discrete.iga.utils.save_basis(nurbs, pars)
Save a NURBS object basis on a FE mesh corresponding to the given parametrization in VTK files.
Parameters
nurbs [igakit.nurbs.NURBS instance] The NURBS object.
pars [sequence of array, optional] The values of parameters in each parametric dimension.
sfepy.discrete.structural sub-package
sfepy.discrete.structural.fields module
sfepy.discrete.structural.mappings module
sfepy.homogenization package
sfepy.homogenization.band_gaps_app module
plot_dispersion(coefs)
static process_options(options)
Application options setup. Sets default values for missing non-compulsory options.
static process_options_pv(options)
Application options setup for phase velocity computation. Sets default values for missing non-compulsory
options.
setup_options()
sfepy.homogenization.coefficients module
class sfepy.homogenization.coefficients.Coefficients(**kwargs)
Class for storing (homogenized) material coefficients.
static from_file_hdf5(filename)
to_file_hdf5(filename)
sfepy.homogenization.coefficients.coef_arrays_to_dicts(idict, format='%s/%d')
sfepy.homogenization.coefs_base module
is_sym = False
static iter_sym(dim)
is_sym = False
static iter_sym(dim)
is_sym = True
static iter_sym(dim)
is_sym = True
static iter_sym(dim)
get_save_name(save_format='.h5', stamp='')
get_save_name_base()
class sfepy.homogenization.coefs_base.CorrSolution(**kwargs)
Class for holding solutions of corrector problems.
get_ts_val(step)
iter_solutions()
iter_time_steps()
init_solvers(problem)
Setup solvers. Use local options if these are defined, otherwise use the global ones.
For linear problems, assemble the matrix and try to presolve the linear system.
process_options()
Setup application-specific options.
Subclasses should implement this method as needed.
Returns
app_options [Struct instance] The application options.
class sfepy.homogenization.coefs_base.OnesDim(name, problem, kwargs)
setup_equations(equations, problem=None)
Set equations, update boundary conditions and materials.
class sfepy.homogenization.coefs_base.TSTimes(name, problem, kwargs)
Coefficient-like class, returns times of the time stepper.
class sfepy.homogenization.coefs_base.VolumeFractions(name, problem, kwargs)
Coefficient-like class, returns volume fractions of given regions within the whole domain.
sfepy.homogenization.coefs_base.create_ts_coef(cls)
Define a new class with modified call method which accepts time dependent data (correctors).
sfepy.homogenization.coefs_elastic module
sfepy.homogenization.coefs_perfusion module
get_variables(ir, data)
sfepy.homogenization.coefs_phononic module
get_coefs(freq)
Get frequency-dependent coefficients.
class sfepy.homogenization.coefs_phononic.AcousticMassTensor(name, problem, kwargs)
The acoustic mass tensor for a given frequency.
Returns
self [AcousticMassTensor instance] This class instance whose evaluate() method computes for
a given frequency the required tensor.
Notes
get_coefs(freq)
Get frequency-dependent coefficients.
to_file_txt = None
class sfepy.homogenization.coefs_phononic.AppliedLoadTensor(name, problem, kwargs)
The applied load tensor for a given frequency.
Returns
self [AppliedLoadTensor instance] This class instance whose evaluate() method computes for a
given frequency the required tensor.
Notes
to_file_txt = None
class sfepy.homogenization.coefs_phononic.BandGaps(name, problem, kwargs)
Band gaps detection.
Parameters
eigensolver [str] The name of the eigensolver for mass matrix eigenvalues.
eig_range [(int, int)] The eigenvalues range (squared frequency) to consider.
freq_margins [(float, float)] Margins in percents of initial frequency range given by eig_range
by which the range is increased.
fixed_freq_range [(float, float)] The frequency range to consider. Has precedence over
eig_range and freq_margins.
freq_step [float] The frequency step for tracing, in percent of the frequency range.
freq_eps [float] The frequency difference smaller than freq_eps is considered zero.
zero_eps [float] The tolerance for finding zeros of mass matrix eigenvalues.
detect_fun [callable] The function for detecting the band gaps. Default is
detect_band_gaps().
log_save_name [str] If not None, the band gaps log is to be saved under the given name.
raw_log_save_name [str] If not None, the raw band gaps log is to be saved under the given
name.
fix_eig_range(n_eigs)
process_options()
Setup application-specific options.
Subclasses should implement this method as needed.
Returns
app_options [Struct instance] The application options.
static save_log(filename, float_format, bg)
Save band gaps, valid flags and eigenfrequencies.
static to_file_txt(fd, float_format, bg)
process_options()
Setup application-specific options.
Subclasses should implement this method as needed.
Returns
app_options [Struct instance] The application options.
class sfepy.homogenization.coefs_phononic.DensityVolumeInfo(name, problem, kwargs)
Determine densities of regions specified in region_to_material, and compute average density based on region
volumes.
static to_file_txt(fd, float_format, dv_info)
prepare_matrices(problem)
A = K + B^T D^{-1} B
class sfepy.homogenization.coefs_phononic.SimpleEVP(name, problem, kwargs)
Simple eigenvalue problem.
post_process(eigs, mtx_s_phi, data, problem)
prepare_matrices(problem)
process_options()
Setup application-specific options.
Subclasses should implement this method as needed.
Returns
app_options [Struct instance] The application options.
save(eigs, mtx_phi, problem)
sfepy.homogenization.coefs_phononic.compute_cat_dim_dim(coef, iw_dir)
Christoffel acoustic tensor part of dielectric tensor dimension.
sfepy.homogenization.coefs_phononic.compute_cat_dim_sym(coef, iw_dir)
Christoffel acoustic tensor part of piezo-coupling tensor dimension.
sfepy.homogenization.coefs_phononic.compute_cat_sym_sym(coef, iw_dir)
Christoffel acoustic tensor (part) of elasticity tensor dimension.
sfepy.homogenization.coefs_phononic.compute_eigenmomenta(em_equation, var_name, problem,
eig_vectors, transform=None)
Compute the eigenmomenta corresponding to given eigenvectors.
sfepy.homogenization.coefs_phononic.cut_freq_range(freq_range, eigs, valid, freq_margins, eig_range,
fixed_freq_range, freq_eps)
Cut off masked resonance frequencies. Margins are preserved, like no resonances were cut.
Returns
freq_range [array] The new range of frequencies.
freq_range_margins [array] The range of frequencies with prepended/appended margins equal
to fixed_freq_range if it is not None.
sfepy.homogenization.coefs_phononic.describe_gaps(gaps)
Notes
Notes
Notes
sfepy.homogenization.convolutions module
where 𝑑(0) = 𝑒𝑛 (0) = 1, 𝑑 is the synchronous decay and 𝑒 its exponential approximation, 𝑒 = 𝑐𝑒0 𝑒𝑥𝑝(−𝑐𝑒1 𝑡).
diff_dt(use_exp=False)
The derivative of the kernel w.r.t. time.
get_exp()
Get the exponential synchronous decay kernel approximation.
get_full()
Get the original (full) kernel.
int_dt(use_exp=False)
The integral of the kernel in time.
sfepy.homogenization.convolutions.approximate_exponential(x, y)
Approximate 𝑦 = 𝑓 (𝑥) by 𝑦𝑎 = 𝑐1 𝑒𝑥𝑝(−𝑐2 𝑥).
Initial guess is given by assuming y has already the required exponential form.
sfepy.homogenization.convolutions.compute_mean_decay(coef )
Compute mean decay approximation of a non-scalar fading memory coefficient.
sfepy.homogenization.convolutions.eval_exponential(coefs, x)
sfepy.homogenization.convolutions.fit_exponential(x, y, return_coefs=False)
Evaluate 𝑦 = 𝑓 (𝑥) after approximating 𝑓 by an exponential.
sfepy.homogenization.engine module
call(ret_all=False, time_tag='')
setup_options(app_options=None)
class sfepy.homogenization.engine.HomogenizationWorker
class sfepy.homogenization.engine.HomogenizationWorkerMultiMPI(num_workers)
sfepy.homogenization.engine.get_dict_idxval(dict_array, idx)
sfepy.homogenization.homogen_app module
static process_options(options)
Application options setup. Sets default values for missing non-compulsory options.
setup_macro_data(data)
Setup macroscopic deformation gradient.
setup_options()
update_micro_states()
Update microstructures state according to the macroscopic data and corrector functions.
sfepy.homogenization.micmac module
sfepy.homogenization.micmac.get_correctors_from_file_hdf5(coefs_filename='coefs.h5',
dump_names=None)
sfepy.homogenization.recovery module
𝜂𝑘 𝜕𝑘𝑥 𝑝
or
(𝑦𝑘 + 𝜂𝑘 )𝜕𝑘𝑥 𝑝
̃︀𝑃 𝑝
𝜋
∑︁ ∫︁ 𝑡 ∫︁ 𝑡
d 𝑖𝑗 d d 𝑃
̃︀ (𝑡 − 𝑠) 𝑒𝑖𝑗 (𝑢(𝑠)) 𝑑𝑠 +
𝜋 ̃︀ (𝑡 − 𝑠) 𝑝(𝑠) 𝑑𝑠
𝜋
𝑖𝑗 0 d𝑡 d𝑠 0 d𝑡
∑︁
𝜔 𝑖𝑗 𝑒𝑖𝑗 (𝑢)
𝑖𝑗
Notes
∑︁ [︂∫︁ 𝑡 ]︂ ∫︁ 𝑡
d
𝜔 𝑖𝑗 (𝑡 − 𝑠) 𝑒𝑖𝑗 (𝑢(𝑠)) 𝑑𝑠 + ̃︀ 𝑃 (𝑡 − 𝑠) 𝑝(𝑠) 𝑑𝑠
𝜔
𝑖𝑗 0 d𝑠 0
∫︁ 𝑡
𝑓 (𝑡 − 𝑠)𝑝(𝑠)𝑑𝑠
0
Notes
• t is given by step
• f: fvars scalar field variables, defined in a micro domain, have shape [step][fmf dims]
• p: pvars scalar point variables, a scalar in a point of macro-domain, FMField style have shape [n_step][var
dims]
∫︁ 𝑡
𝑓 𝑖𝑗 (𝑡 − 𝑠)𝑝𝑖𝑗 (𝑠)𝑑𝑠
0
Notes
• t is given by step
• f: fvars field variables, defined in a micro domain, have shape [step][fmf dims]
• p: pvars sym. tensor point variables, a scalar in a point of macro-domain, FMField style, have shape [dim,
dim][var_name][n_step][var dims]
sfepy.homogenization.recovery.destroy_pool()
Notes
• note that
̃︀𝑃
𝜋
is in corrs_pressure -> from time correctors only ‘u’, ‘dp’ are needed.
sfepy.homogenization.recovery.recover_micro_hook_init(micro_filename, define_args,
output_dir=None)
sfepy.homogenization.utils module
sfepy.homogenization.utils.create_pis(problem, var_name)
Pi_i^{rs} = y_s delta_{ir}, ul{y} in Y coordinates.
sfepy.homogenization.utils.create_scalar_pis(problem, var_name)
Pi^k = y_k, ul{y} in Y coordinates.
sfepy.homogenization.utils.define_box_regions(dim, lbn, rtf=None, eps=0.001, kind='facet')
Define sides and corner regions for a box aligned with coordinate axes.
Parameters
dim [int] Space dimension
lbn [tuple] Left bottom near point coordinates if rtf is not None. If rtf is None, lbn are the
(positive) distances from the origin.
rtf [tuple] Right top far point coordinates.
eps [float] A parameter, that should be smaller than the smallest mesh node distance.
kind [bool, optional] The region kind.
Returns
regions [dict] The box regions.
sfepy.homogenization.utils.get_box_volume(dim, lbn, rtf=None)
Volume of a box aligned with coordinate axes.
Parameters:
dim [int] Space dimension
lbn [tuple] Left bottom near point coordinates if rtf is not None. If rtf is None, lbn are the (positive) distances
from the origin.
rtf [tuple] Right top far point coordinates.
Returns:
volume [float] The box volume.
sfepy.homogenization.utils.get_lattice_volume(axes)
Volume of a periodic cell in a rectangular 3D (or 2D) lattice.
Parameters
axes [array] The array with the periodic cell axes 𝑎1 , . . . , 𝑎3 as rows.
Returns
volume [float] The periodic cell volume 𝑉 = (𝑎1 × 𝑎2 ) · 𝑎3 . In 2D 𝑉 = |(𝑎1 × 𝑎2 )| with zeros
as the third components of vectors 𝑎1 , 𝑎2 .
sfepy.homogenization.utils.get_volume(problem, field_name, region_name, quad_order=1)
Get volume of a given region using integration defined by a given field. Both the region and the field have to be
defined in problem.
sfepy.homogenization.utils.iter_nonsym(dim)
sfepy.homogenization.utils.iter_sym(dim)
sfepy.homogenization.utils.rm_multi(s)
sfepy.linalg package
sfepy.linalg.check_derivatives module
sfepy.linalg.eigen module
sfepy.linalg.geometry module
sfepy.linalg.geometry.barycentric_coors(coors, s_coors)
Get barycentric (area in 2D, volume in 3D) coordinates of points with coordinates coors w.r.t. the simplex given
by s_coors.
Returns
bc [array] The barycentric coordinates. Then reference element coordinates xi = dot(bc.T,
ref_coors).
sfepy.linalg.geometry.flag_points_in_polygon2d(polygon, coors)
Test if points are in a 2D polygon.
Parameters
polygon [array, (:, 2)] The polygon coordinates.
coors: array, (:, 2) The coordinates of points.
Returns
flag [bool array] The flag that is True for points that are in the polygon.
Notes
Notes
All float comparisons are done using <= or >= operators, i.e. the points on the boundaries are taken into account.
sfepy.linalg.geometry.get_coors_in_tube(coors, centre, axis, radius_in, radius_out, length,
inside_radii=True)
Return indices of coordinates inside a tube given by centre, axis vector, inner and outer radii and length.
Parameters
inside_radii [bool, optional] If False, select points outside the radii, but within the tube length.
Notes
All float comparisons are done using <= or >= operators, i.e. the points on the boundaries are taken into account.
sfepy.linalg.geometry.get_face_areas(faces, coors)
Get areas of planar convex faces in 2D and 3D.
Parameters
faces [array, shape (n, m)] The indices of n faces with m vertices into coors.
coors [array] The coordinates of face vertices.
Returns
areas [array] The areas of the faces.
sfepy.linalg.geometry.get_perpendiculars(vec)
For a given vector, get a unit vector perpendicular to it in 2D, or get two mutually perpendicular unit vectors
perpendicular to it in 3D.
sfepy.linalg.geometry.get_simplex_circumcentres(coors, force_inside_eps=None)
Compute the circumcentres of n_s simplices in 1D, 2D and 3D.
Parameters
coors [array] The coordinates of the simplices with n_v vertices given in an array of shape (n_s,
n_v, dim), where dim is the space dimension and 2 <= n_v <= (dim + 1).
force_inside_eps [float, optional] If not None, move the circumcentres that are outside of their
simplices or closer to their boundary then force_inside_eps so that they are inside the sim-
plices at the distance given by force_inside_eps. It is ignored for edges.
Returns
centres [array] The circumcentre coordinates as an array of shape (n_s, dim).
sfepy.linalg.geometry.get_simplex_volumes(cells, coors)
Get volumes of simplices in nD.
Parameters
cells [array, shape (n, d)] The indices of n simplices with d vertices into coors.
coors [array] The coordinates of simplex vertices.
Returns
volumes [array] The volumes of the simplices.
sfepy.linalg.geometry.inverse_element_mapping(coors, e_coors, eval_base, ref_coors,
suppress_errors=False)
Given spatial element coordinates, find the inverse mapping for points with coordinats X = X(xi), i.e. xi = xi(X).
Returns
xi [array] The reference element coordinates.
sfepy.linalg.geometry.make_axis_rotation_matrix(direction, angle)
Create a rotation matrix 𝑅 corresponding to the rotation around a general axis 𝑑 by a specified angle 𝛼.
Parameters
direction [array] The rotation axis direction vector 𝑑.
Notes
The matrix follows the right hand rule: if the right hand thumb points along the axis vector 𝑑 the fingers show
the positive angle rotation direction.
Examples
Make transformation matrix for rotation of coordinate system by 90 degrees around ‘z’ axis.
Coordinates of vector [1, 0, 0]𝑇 w.r.t. the original system in the rotated system. (Or rotation of the vector by -90
degrees in the original system.)
Coordinates of vector [1, 0, 0]𝑇 w.r.t. the rotated system in the original system. (Or rotation of the vector by +90
degrees in the original system.)
sfepy.linalg.sparse module
row_sizes [sequence, optional] The required row sizes of the blocks. It can be either a sequence
of non-negative integers, or a sequence of slices with non-negative limits. In any case the
sizes have to be compatible with the true block sizes. This allows to extend the matrix shape
as needed and to specify sizes of all-zero blocks.
col_sizes [sequence, optional] The required column sizes of the blocks. See row_sizes.
Returns
mtx [coo_matrix] The sparse matrix (COO format) composed from the given blocks.
Examples
sfepy.linalg.sparse.infinity_norm(mtx)
Infinity norm of a sparse matrix (maximum absolute row sum).
Parameters
mtx [spmatrix or array] The sparse matrix.
Returns
norm [float] Infinity norm of the matrix.
See also:
Notes
sfepy.linalg.sympy_operators module
sfepy.linalg.sympy_operators.boundary(f, variables)
sfepy.linalg.sympy_operators.default_space_variables(variables)
sfepy.linalg.sympy_operators.div(field, variables=None)
sfepy.linalg.sympy_operators.grad(f, variables=None)
sfepy.linalg.sympy_operators.grad_v(f, variables=None)
sfepy.linalg.sympy_operators.laplace(f, variables=None)
sfepy.linalg.sympy_operators.set_dim(dim)
sfepy.linalg.utils module
class sfepy.linalg.utils.MatrixAction(**kwargs)
static from_array(arr)
to_array()
sfepy.linalg.utils.combine(seqs)
Same as cycle, but with general sequences.
Example:
In [19]: c = combine( [[‘a’, ‘x’], [‘b’, ‘c’], [‘dd’]] )
In [20]: list(c) Out[20]: [[‘a’, ‘b’, ‘dd’], [‘a’, ‘c’, ‘dd’], [‘x’, ‘b’, ‘dd’], [‘x’, ‘c’, ‘dd’]]
sfepy.linalg.utils.cycle(bounds)
Cycles through all combinations of bounds, returns a generator.
More specifically, let bounds=[a, b, c, . . . ], so cycle returns all combinations of lists [0<=i<a, 0<=j<b, 0<=k<c,
. . . ] for all i,j,k,. . .
Examples: In [9]: list(cycle([3, 2])) Out[9]: [[0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1]]
In [14]: list(cycle([3, 4])) [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1], [2, 2], [2, 3]]
sfepy.linalg.utils.dets_fast(a)
Fast determinant calculation of 3-dimensional array.
Parameters
a [array] The input array with shape (m, n, n).
Returns
out [array] The output array with shape (m,): out[i] = det(a[i, :, :]).
sfepy.linalg.utils.dot_sequences(mtx, vec, mode='AB')
Computes dot product for each pair of items in the two sequences.
Equivalent to
Parameters
mtx [array] The array of matrices with shape (n_item, m, n).
vec [array] The array of vectors with shape (n_item, a) or matrices with shape (n_item, a, b).
mode [one of ‘AB’, ‘ATB’, ‘ABT’, ‘ATBT’] The mode of the dot product - the corresponding
axes are dotted together:
‘AB’ : a = n ‘ATB’ : a = m ‘ABT’ : b = n (*) ‘ATBT’ : b = m (*)
(*) The ‘BT’ part is ignored for the vector second argument.
Returns
out [array] The resulting array.
Notes
Examples
[[ 0.78593989, 0.71852473]]])
>>> ar.shape
(2, 1, 2)
>>> ar2 = insert_strided_axis(ar, 1, 3)
>>> ar2
array([[[[ 0.18905119, 0.44552425]],
[[ 0.18905119, 0.44552425]],
[[ 0.18905119, 0.44552425]]],
[[[ 0.78593989, 0.71852473]],
[[ 0.78593989, 0.71852473]],
[[ 0.78593989, 0.71852473]]]])
>>> ar2.shape
(2, 3, 1, 2)
sfepy.linalg.utils.permutations(seq)
sfepy.linalg.utils.print_array_info(ar)
Print array shape and other basic information.
sfepy.linalg.utils.split_range(n_item, step)
sfepy.mechanics package
sfepy.mechanics.contact_bodies module
get_distance(points)
mask_points(points)
get_distance(points)
Get the penetration distance and normals of points w.r.t. the sphere surface.
Returns
d [array] The penetration distance.
normals [array] The normals from the points to the sphere centre.
mask_points(points, eps)
sfepy.mechanics.contact_bodies.plot_polygon(ax, polygon)
sfepy.mechanics.elastic_constants module
sfepy.mechanics.matcoefs module
Examples
• basic usage:
get(names)
Get the named elastic constants.
¯= 2𝜆𝜇
𝜆
𝜆 + 2𝜇
[1] I.S. Sokolnikoff: Mathematical Theory of Elasticity. New York, 1956.
[2] T.J.R. Hughes: The Finite Element Method, Linear Static and Dynamic Finite Element Analysis. New Jersey,
1987.
sfepy.mechanics.matcoefs.stiffness_from_lame(dim, lam, mu)
Compute stiffness tensor corresponding to Lamé parameters.
⎡ ⎤
𝜆 + 2𝜇 𝜆 0
𝐷(2𝐷) = ⎣ 𝜆 𝜆 + 2𝜇 0⎦
0 0 𝜇
⎡ ⎤
𝜆 + 2𝜇 𝜆 𝜆 0 0 0
⎢ 𝜆 𝜆 + 2𝜇 𝜆 0 0 0⎥
⎢ ⎥
⎢ 𝜆 𝜆 𝜆 + 2𝜇 0 0 0⎥
𝐷(3𝐷) = ⎢⎢ 0
⎥
⎢ 0 0 𝜇 0 0⎥⎥
⎣ 0 0 0 0 𝜇 0⎦
0 0 0 0 0 𝜇
̃︀ = − 2 𝜇
𝜆
3
𝐸 𝜇
𝑣𝑠2 = =
2𝜌(1 + 𝜈) 𝜌
Parameters
young [float or array] The Young’s modulus.
poisson [float or array] The Poisson’s ratio.
rho [float or array] The density.
Returns
vp [float or array] The P-wave speed.
vs [float or array] The S-wave speed.
sfepy.mechanics.matcoefs.youngpoisson_from_stiffness(stiffness, plane='strain')
Compute Young’s modulus and Poisson’s ratio from an isotropic stiffness tensor.
sfepy.mechanics.matcoefs.youngpoisson_from_wave_speeds(vp, vs, rho)
Compute the Young’s modulus 𝐸 and Poisson’s ratio 𝜈 from the P- and S-wave speeds in a homogeneous isotropic
material.
𝜌𝑣𝑠2 (3𝑣𝑝2 − 4𝑣𝑠2 )
𝐸=
(𝑣𝑝2 − 𝑣𝑠2 )
(𝑣𝑝2 /2 − 𝑣𝑠2 )
𝜈=
(𝑣𝑝2 − 𝑣𝑠2 )
Parameters
vp [float or array] The P-wave speed.
vs [float or array] The S-wave speed.
rho [float or array] The density.
Returns
young [float or array] The Young’s modulus.
poisson [float or array] The Poisson’s ratio.
sfepy.mechanics.membranes module
Notes
𝑇 = [𝑡1 , 𝑡2 , 𝑛], where 𝑡1 , 𝑡2 , are unit in-plane (column) vectors and 𝑛 is the unit normal vector, all mutually
orthonormal.
sfepy.mechanics.membranes.describe_deformation(el_disps, bfg)
Describe deformation of a thin incompressible 2D membrane in 3D space, composed of flat finite element faces.
The coordinate system of each element (face), i.e. the membrane mid-surface, should coincide with the x, y axes
of the x-y plane.
Parameters
el_disps [array] The displacements of element nodes, shape (n_el, n_ep, dim).
bfg [array] The in-plane base function gradients, shape (n_el, n_qp, dim-1, n_ep).
Returns
mtx_c ; array The in-plane right Cauchy-Green deformation tensor 𝐶𝑖𝑗 , 𝑖, 𝑗 = 1, 2.
c33 [array] The component 𝐶33 computed from the incompressibility condition.
mtx_b [array] The discrete Green strain variation operator.
sfepy.mechanics.membranes.describe_geometry(field, region, integral)
Describe membrane geometry in a given region.
Parameters
field [Field instance] The field defining the FE approximation.
region [Region instance] The surface region to describe.
integral [Integral instance] The integral defining the quadrature points.
Returns
mtx_t [array] The transposed transformation matrix 𝑇, see
create_transformation_matrix().
membrane_geo [CMapping instance] The mapping from transformed elements to a reference
elements.
sfepy.mechanics.membranes.get_green_strain_sym3d(mtx_c, c33)
Get the 3D Green strain tensor in symmetric storage.
Parameters
mtx_c ; array The in-plane right Cauchy-Green deformation tensor 𝐶𝑖𝑗 , 𝑖, 𝑗 = 1, 2, shape (n_el,
n_qp, dim-1, dim-1).
c33 [array] The component 𝐶33 computed from the incompressibility condition, shape (n_el,
n_qp).
Returns
mtx_e [array] The membrane Green strain 𝐸𝑖𝑗 = 12 (𝐶𝑖𝑗 ) − 𝛿𝑖𝑗 , symmetric storage: items (11,
22, 33, 12, 13, 23), shape (n_el, n_qp, sym, 1).
sfepy.mechanics.membranes.get_invariants(mtx_c, c33)
Get the first and second invariants of the right Cauchy-Green deformation tensor describing deformation of an
incompressible membrane.
Parameters
mtx_c ; array The in-plane right Cauchy-Green deformation tensor 𝐶𝑖𝑗 , 𝑖, 𝑗 = 1, 2, shape (n_el,
n_qp, dim-1, dim-1).
c33 [array] The component 𝐶33 computed from the incompressibility condition, shape (n_el,
n_qp).
Returns
i1 [array] The first invariant of 𝐶𝑖𝑗 .
i2 [array] The second invariant of 𝐶𝑖𝑗 .
sfepy.mechanics.membranes.get_tangent_stress_matrix(stress, bfg)
Get the tangent stress matrix of a thin incompressible 2D membrane in 3D space, given a stress.
Parameters
stress [array] The components 11, 22, 12 of the second Piola-Kirchhoff stress tensor, shape
(n_el, n_qp, 3, 1).
bfg [array] The in-plane base function gradients, shape (n_el, n_qp, dim-1, n_ep).
Returns
mtx [array] The tangent stress matrix, shape (n_el, n_qp, dim*n_ep, dim*n_ep).
sfepy.mechanics.membranes.transform_asm_matrices(out, mtx_t)
Transform matrix assembling contributions to global coordinate system, one node at a time.
Parameters
out [array] The array of matrices, transformed in-place.
mtx_t [array] The transposed transformation matrix 𝑇, see
create_transformation_matrix().
sfepy.mechanics.membranes.transform_asm_vectors(out, mtx_t)
Transform vector assembling contributions to global coordinate system, one node at a time.
Parameters
out [array] The array of vectors, transformed in-place.
mtx_t [array] The transposed transformation matrix 𝑇, see
create_transformation_matrix().
sfepy.mechanics.shell10x module
Notes
Notes
𝑇 = [𝑡1 , 𝑡2 , 𝑛], where 𝑡1 , 𝑡2 , are unit in-plane (column) vectors and 𝑛 is the unit normal vector, all mutually
orthonormal.
sfepy.mechanics.shell10x.get_dsg_strain(coors_loc, qp_coors)
Compute DSG strain components.
Returns
dsg [array] The strain matrix components corresponding to 𝑒13 , 𝑒23 , shape (n_el, n_qp, 2, 24).
Notes
Involves 𝑤, 𝛼, 𝛽 DOFs.
sfepy.mechanics.shell10x.get_mapping_data(ebs, rops, ps, coors_loc, qp_coors, qp_weights,
special_dx3=False)
Compute reference element mapping data for shell10x elements.
Notes
The code assumes that the quadrature points are w.r.t. (𝑡 = thickness of the shell) [0, 1] × [0, 1] × [−𝑡/2, 𝑡/2]
reference cell and the quadrature weights are multiplied by 𝑡.
sfepy.mechanics.shell10x.lock_drilling_rotations(mtx, ebs, coefs)
Lock the drilling rotations in the stiffness matrix.
sfepy.mechanics.shell10x.rotate_elastic_tensor(mtx_d, bfu, ebs)
Rotate the elastic tensor into the local coordinate system of each cell. The local coordinate system results from
interpolation of ebs with the bilinear basis.
sfepy.mechanics.shell10x.transform_asm_matrices(out, mtx_t, blocks)
Transform matrix assembling contributions to global coordinate system, one node at a time.
Parameters
out [array] The array of matrices, transformed in-place.
mtx_t [array] The array of transposed transformation matrices 𝑇, see
create_transformation_matrix().
sfepy.mechanics.tensors module
sfepy.mechanics.tensors.dim2sym(dim)
Given the space dimension, return the symmetric storage size.
sfepy.mechanics.tensors.get_deviator(tensor, sym_storage=True)
The deviatoric part (deviator) of a tensor.
sfepy.mechanics.tensors.get_full_indices(dim)
The indices for converting the symmetric storage to the full storage.
sfepy.mechanics.tensors.get_non_diagonal_indices(dim)
The non_diagonal indices for the full vector storage.
sfepy.mechanics.tensors.get_sym_indices(dim)
The indices for converting the full storage to the symmetric storage.
sfepy.mechanics.tensors.get_t4_from_t2s(t2s)
Get the full 4D tensor with major/minor symmetries from its 2D matrix representation.
Parameters
t2s [array] The symmetrically-stored tensor of shape (S, S), where S it the symmetric storage
size.
Returns
t4 [array] The full 4D tensor of shape (D, D, D, D), where D is the space dimension.
sfepy.mechanics.tensors.get_trace(tensor, sym_storage=True)
The trace of a tensor.
sfepy.mechanics.tensors.get_volumetric_tensor(tensor, sym_storage=True)
The volumetric part of a tensor.
sfepy.mechanics.tensors.get_von_mises_stress(stress, sym_storage=True)
Given a symmetric stress tensor, compute the von Mises stress (also known as Equivalent tensile stress).
Notes
√︂
2 + 𝜎2 + 𝜎2 )
(𝜎11 − 𝜎22 )2 + (𝜎22 − 𝜎33 )2 + (𝜎11 − 𝜎33 )2 + 6(𝜎12 13 23
𝜎𝑉 =
2
Notes
𝑣′ = 𝑀 · 𝑣
Parameters
data [array, shape (num, n_r) or (num, n_r, n_c)] The vectors (n_r is 3) or tensors (symmetric
storage, n_r is 6, n_c, if available, is 1 or 6) to be transformed.
coors [array] The Cartesian coordinates of the data. Not needed when mtx argument is given.
mode [one of [‘cylindrical’]] The requested coordinate system. Not needed when mtx argument
is given.
mtx [array] The array of transformation matrices 𝑀 for each data row.
Returns
new_data [array] The transformed data.
sfepy.mechanics.units module
Examples
>>> q1('m')
'1000.0 mPa'
>>> q1('')
'1.0 Pa'
>>> q1('k')
'0.001 kPa'
>>> q1('M')
'1e-06 MPa'
>>> q2('m')
'1000000.0 mPa'
>>> q2('')
'1000.0 Pa'
>>> q2('k')
'1.0 kPa'
>>> q2('M')
'0.001 MPa'
class sfepy.mechanics.units.Unit(name)
A unit of a physical quantity. The prefix and coefficient of the unit are determined from to its name.
Examples
>>> Unit.get_prefix(100.0)
('d', 10.0)
>>> Unit.get_prefix(100.0, omit=('d',))
('k', 0.10000000000000001)
pars_kinds [dict] The kinds of the parameters given as name : kind items, with kinds defined
in apply_unit_multipliers().
unit_multipliers [tuple] The time, length and mass unit multipliers.
Returns
new_pars [dict] The output parameters.
sfepy.mechanics.units.get_consistent_unit_set(length=None, time=None, mass=None,
temperature=None)
Given a set of basic units, return a consistent set of derived units for quantities listed in the units_of_quantities
dictionary.
sfepy.mechanics.extmods.ccontres module
sfepy.mechanics.extmods.ccontres.assemble_contact_residual_and_stiffness()
sfepy.mechanics.extmods.ccontres.evaluate_contact_constraints()
sfepy.mechanics.extmods.ccontres.get_AABB()
sfepy.mechanics.extmods.ccontres.get_longest_edge_and_gps()
sfepy.mechanics.extmods.ccontres.init_global_search()
The linked list initialization. The head array contains, at the position Ic, the index of the first point that belongs
to the cell Ic, the second point index is then next[head[Ic]], the third point index is next[next[head[Ic]]] etc. - the
next array points from the i-th point in each cell to the (i+1)-th point, until -1 is reached.
sfepy.mesh package
sfepy.mesh.bspline module
Returns
coors [array] The coordinates of control points.
get_knot_vector()
Return the knot vector.
Returns
knots [array] The knot vector.
insert_knot(new)
Insert a new knot into the knot vector.
Parameters
new [float] The new knot value.
make_knot_vector(knot_type='clamped', knot_data=None, knot_range=(0.0, 1.0))
Create a knot vector of the requested type.
Parameters
knot_type [str] The knot vector type: clamped/cyclic/userdef.
knot_data : The extra knot data.
set_approx_points(coors)
Set the coordinates of approximated points.
Parameters
coors [array] The coordinates of approximated points.
set_control_points(coors, cyclic_form=False)
Set the B-spline control points.
Parameters
coors [array] The coordinates of unique control points.
cyclic_form [bool] Are the control points in the cyclic form?
set_knot_vector(knots)
Set the knot vector.
Parameters
knots [array] The knot vector.
set_param(t)
Set the B-spline parametric vector.
Parameters
t [array] The parameter vector of the B-spline.
set_param_n(n=100, knot_range=(0.0, 1.0))
Generate the B-spline parametric vector using the number of steps.
Parameters
n [array] The number of steps in the B-spline parametric vector.
class sfepy.mesh.bspline.BSplineSurf(degree=(3, 3), is_cyclic=(False, False))
B-spline surface representation
Parameters
filename: str Name of the VTK file.
float_format: str Float formating.
write_surface_vtk(filename, float_format='%.6f')
Write the spline surface to VTK file.
Parameters
filename: str Name of the VTK file.
float_format: str Float formating.
sfepy.mesh.bspline.approximation_example()
The example of using BSplineSurf for approximation of the surface given by the set of points.
sfepy.mesh.bspline.get_2d_points(is3d=False)
Returns the set of points.
Parameters
is3d [bool] 3D coordinates?
sfepy.mesh.bspline.main(argv)
sfepy.mesh.bspline.simple_example()
The example of using B-spline class.
sfepy.mesh.bspline.to_ndarray(a)
sfepy.mesh.geom_tools module
class sfepy.mesh.geom_tools.geometry(dim=3)
The geometry is given by a sets of points (d0), lines (d1), surfaces (d2) and volumes (d3). A lines are constructed
from 2 points, a surface from any number of lines, a volume from any number of surfaces.
Physical volumes are contruted from any number of volumes.
The self.d0, self.d1, self.d2 and self.d3 are dictionaries holding a map
geometry element number -> instance of point,line,surface of volume
Examples
addphysicalvolume(n, volumelist)
volumelist=[v1,v2,v3,. . . ]
addpoint(n, p)
p=[x,y,z]
addpoints(ps, off=1)
ps=[p1, p2, . . . ]
addsurface(n, s, is_hole=False)
s=[l1,l2,l3,. . . ]
addsurfaces(ss, off=1)
s=[s1,s2,s3,. . . ]
addvolume(n, v)
v=[s1,s2,s3,. . . ]
addvolumes(vs, off=1)
v=[v1,v2,v3,. . . ]
static from_gmsh_file(filename)
Import geometry - Gmsh geometry format.
Parameters
filename [string] file name
Returns
geo [geometry] geometry description
getBCnum(snum)
leaveonlyphysicalsurfaces()
leaveonlyphysicalvolumes()
printinfo(verbose=False)
splitlines(ls, n)
to_poly_file(filename)
Export geometry to poly format (tetgen and triangle geometry format).
Parameters
geo [geometry] geometry description
filename [string] file name
class sfepy.mesh.geom_tools.geomobject
getn()
class sfepy.mesh.geom_tools.line(g, n, l)
getpoints()
class sfepy.mesh.geom_tools.physicalsurface(g, n, s)
getsurfaces()
class sfepy.mesh.geom_tools.physicalvolume(g, n, v)
getvolumes()
class sfepy.mesh.geom_tools.point(g, n, p)
getstr()
getxyz()
getcenterpoint()
getholepoints()
getinsidepoint()
getlines()
getpoints()
separate(s)
class sfepy.mesh.geom_tools.volume(g, n, v)
getinsidepoint()
getsurfaces()
sfepy.mesh.mesh_generators module
sfepy.mesh.mesh_tools module
sfepy.mesh.mesh_tools.elems_q2t(el)
sfepy.mesh.splinebox module
evaluate(cp_values=None, outside=True)
Evaluate the new position of the mesh coordinates.
Parameters
cp_values [array] The actual control point values. If None, use self.control_values.
outside [bool] If True, return also the coordinates outside the spline box.
Returns
new_coors [array] The new position of the mesh coordinates.
evaluate_derivative(cpoint, dirvec)
Evaluate derivative of the spline in a given control point and direction.
Parameters
cpoint [int, list] The position (index or grid indicies) of the spline control point.
dirvec [array] The directional vector.
Returns
diff [array] The derivative field.
static gen_cp_idxs(ncp)
get_box_matrix()
Returns:
mtx [2D array] The matrix containing the coefficients of b-spline basis functions.
get_control_points(init=False)
Get the spline control points coordinates.
Returns
cpt_coors [array] The coordinates of the spline control points.
init [bool] If True, return the initial state.
get_coors_shape()
Get the shape of the coordinates.
move_control_point(cpoint, val)
Change shape of spline parametrization.
Parameters
cpoint [int, list] The position (index or grid indicies) of the spline control point.
val [array] Displacement.
set_control_points(cpt_coors, add=False)
Set the spline control points position.
Parameters
cpt_coors [array] The coordinates of the spline control points.
add [bool] If True, coors += cpt_coors
write_control_net(filename, deform_by_values=True)
Write the SplineBox shape to the VTK file.
Parameters
filename [str] The VTK file name.
class sfepy.mesh.splinebox.SplineRegion2D(spl_bnd, coors, rho=1000.0)
B-spline geometry parametrization. The boundary of the SplineRegion2D is defined by BSpline curves.
static create_spb(spl_bnd, coors, rho=10)
Initialize SplineBox knots, control points, base functions, . . .
static define_control_points(cp_bnd_coors, ncp)
Find positions of “inner” control points depending on boundary splines.
find_ts(coors)
Function finds parameters (t, s) corresponding to given points (coors).
static points_in_poly(points, poly, tol=1e-06)
Find which points are located inside the polygon.
sfepy.parallel package
sfepy.parallel.evaluate module
Notes
sfepy.parallel.parallel module
[inner,
[own_inter1, own_inter2, ...],
[overlap_cells1, overlap_cells2, ...],
n_task_total, task_offset]
The overlapping cells are defined so that the system matrix corresponding to each task can be assembled inde-
pendently, see [1]. TODO: Some “corner” cells may be added even if not needed - filter them out by using the
PETSc DOFs range.
When debugging domain partitioning problems, it is advisable to set save_inter_regions to True to save the task
interfaces as meshes as well as vertex-based markers - to be used only with moderate problems and small numbers
of tasks.
[1] J. Sistek and F. Cirak. Parallel iterative solution of the incompressible Navier-Stokes equations with applica-
tion to rotating wings. Submitted for publication, 2015
sfepy.parallel.parallel.distribute_field_dofs(field, gfd, use_expand_dofs=False, comm=None,
verbose=False)
Distribute the owned cells and DOFs of the given field to all tasks.
The DOFs use the PETSc ordering and are in form of a connectivity, so that each task can easily identify them
with the DOFs of the original global ordering or local ordering.
sfepy.parallel.parallel.distribute_fields_dofs(fields, cell_tasks, is_overlap=True,
use_expand_dofs=False, save_inter_regions=False,
output_dir=None, comm=None, verbose=False)
Distribute the owned cells and DOFs of the given field to all tasks.
Uses interleaved PETSc numbering in each task, i.e., the PETSc DOFs of each tasks are consecutive and corre-
spond to the first field DOFs block followed by the second etc.
Expand DOFs to equations if use_expand_dofs is True.
sfepy.parallel.parallel.expand_dofs(dofs, n_components)
Expand DOFs to equation numbers.
sfepy.parallel.parallel.get_composite_sizes(lfds)
Get (local, total) sizes of a vector and local equation range for a composite matrix built from field blocks described
by lfds local field distributions information.
sfepy.parallel.parallel.get_inter_facets(domain, cell_tasks)
For each couple of neighboring task subdomains get the common boundary (interface) facets.
sfepy.parallel.parallel.get_local_ordering(field_i, petsc_dofs_conn, use_expand_dofs=False)
Get PETSc DOFs in the order of local DOFs of the localized field field_i.
Expand DOFs to equations if use_expand_dofs is True.
sfepy.parallel.parallel.get_sizes(petsc_dofs_range, n_dof, n_components)
Get (local, total) sizes of a vector and local equation range.
sfepy.parallel.parallel.init_petsc_args()
sfepy.parallel.plot_parallel_dofs module
sfepy.postprocess package
sfepy.postprocess.plot_cmesh module
Examples
>>> # 2D mesh.
>>> plot_cmesh(None, cmesh,
wireframe_opts = {'color' : 'k', 'linewidth' : 2},
entities_opts=[
{'color' : 'k', 'label_local' : 8, 'size' : 20},
{'color' : 'b', 'label_global' : 12, 'label_local' : 8, 'size' : 10},
{'color' : 'r', 'label_global' : 12, 'size' : 20},
])
sfepy.postprocess.plot_dofs module
Functions to visualize the mesh connectivity with global and local DOF numberings.
sfepy.postprocess.plot_dofs.plot_global_dofs(ax, coors, econn)
Plot global DOF numbers given in an extended connectivity.
The DOF numbers are plotted for each element, so on common facets they are plotted several times - this can be
used to check the consistency of the global DOF connectivity.
sfepy.postprocess.plot_dofs.plot_local_dofs(ax, coors, econn)
Plot local DOF numbers corresponding to an extended connectivity.
sfepy.postprocess.plot_dofs.plot_mesh(ax, coors, conn, edges, color='k', **plot_kwargs)
Plot a finite element mesh as a wireframe.
sfepy.postprocess.plot_dofs.plot_nodes(ax, coors, econn, ref_nodes, dofs)
Plot Lagrange reference element nodes corresponding to global DOF numbers given in an extended connectivity.
sfepy.postprocess.plot_dofs.plot_points(ax, coors, vals=None, point_size=20, show_colorbar=False)
Plot points with given coordinates, optionally colored using vals values.
sfepy.postprocess.plot_facets module
Functions to visualize the geometry elements and numbering and orientation of their facets (edges and faces).
The standard geometry elements can be plotted by running:
$ python sfepy/postprocess/plot_facets.py
sfepy.postprocess.plot_facets.plot_geometry(ax, gel)
Plot a geometry element as a wireframe.
sfepy.postprocess.plot_quadrature module
sfepy.postprocess.probes_vtk module
Classes for probing values of Variables, for example, along a line, using PyVTK library
class sfepy.postprocess.probes_vtk.Probe(data, mesh, **kwargs)
Probe class.
add_circle_probe(name, centre, normal, radius, n_point)
Create the ray (line) probe - VTK object.
Parameters
name [str] The probe name.
centre [array] The coordinates of the circle center point.
normal [array] The normal vector perpendicular to the circle plane.
radius [float] The radius of the circle.
n_point [int] The number of probe points.
add_line_probe(name, p0, p1, n_point)
Create the line probe - VTK object.
Parameters
name [str] The probe name.
p0 [array_like] The coordinates of the start point.
p1 [array_like] The coordinates of the end point.
n_point [int] The number of probe points.
add_points_probe(name, coors)
Create the point probe - VTK object.
Parameters
sfepy.postprocess.time_history module
sfepy.postprocess.time_history.average_vertex_var_in_cells(ths_in)
Average histories in the element nodes for each nodal variable originally requested in elements.
sfepy.postprocess.time_history.dump_to_vtk(filename, output_filename_trunk=None, step0=0,
steps=None, fields=None, linearization=None)
Dump a multi-time-step results file into a sequence of VTK files.
sfepy.postprocess.time_history.extract_time_history(filename, extract, verbose=True)
Extract time history of a variable from a multi-time-step results file.
Parameters
filename [str] The name of file to extract from.
extract [str] The description of what to extract in a string of comma-separated description items.
A description item consists of: name of the variable to extract, mode (‘e’ for elements, ‘n’
for nodes), ids of the nodes or elements (given by the mode). Example: ‘u n 10 15, p e 0’
means variable ‘u’ in nodes 10, 15 and variable ‘p’ in element 0.
verbose [bool] Verbosity control.
Returns
ths [dict] The time histories in a dict with variable names as keys. If a nodal variable is requested
in elements, its value is a dict of histories in the element nodes.
ts [TimeStepper instance] The time stepping information.
sfepy.postprocess.time_history.extract_times(filename)
Read true time step data from individual time steps.
Returns
steps [array] The time steps.
times [array] The times of the time steps.
nts [array] The normalized times of the time steps, in [0, 1].
dts [array] The true time deltas.
sfepy.postprocess.time_history.guess_time_units(times)
Given a vector of times in seconds, return suitable time units and new vector of times suitable for plotting.
Parameters
times [array] The vector of times in seconds.
Returns
new_times [array] The vector of times in units.
units [str] The time units.
sfepy.postprocess.time_history.save_time_history(ths, ts, filename_out)
Save time history and time-stepping information in a HDF5 file.
sfepy.postprocess.utils_vtk module
sfepy.postprocess.utils_vtk.get_vtk_from_file(filename)
Read VTK file.
Parameters
filename [str] Name of the VTK file.
Returns
vtkdata [VTK object] Mesh, scalar, vector and tensor data.
sfepy.postprocess.utils_vtk.get_vtk_from_mesh(mesh, data, prefix='')
sfepy.postprocess.utils_vtk.get_vtk_surface(vtkdata)
Get mesh surface.
Parameters
vtkdata [VTK object] Mesh, scalar, vector and tensor data.
Returns
surface [VTK object] Mesh, scalar, vector and tensor data.
sfepy.postprocess.utils_vtk.tetrahedralize_vtk_mesh(vtkdata)
3D cells are converted to tetrahedral meshes, 2D cells to triangles.
Parameters
vtkdata [VTK object] Mesh, scalar, vector and tensor data.
Returns
tetra [VTK object] Mesh, scalar, vector and tensor data.
sfepy.postprocess.utils_vtk.write_vtk_to_file(filename, vtkdata)
Write VTK file.
Parameters
filename [str] Name of the VTK file.
vtkdata [VTK object] Mesh, scalar, vector and tensor data.
sfepy.solvers package
sfepy.solvers.auto_fallback module
sfepy.solvers.eigen module
create_petsc_matrix(mtx, comm=None)
name = 'eig.slepc'
class sfepy.solvers.eigen.ScipyEigenvalueSolver(conf, **kwargs)
SciPy-based solver for both dense and sparse problems.
The problem is consirered sparse if n_eigs argument is not None.
Kind: ‘eig.scipy’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
method [{‘eig’, ‘eigh’, ‘eigs’, ‘eigsh’} (default: ‘eigs’)] The method for solving general or sym-
metric eigenvalue problems: for dense problems eig() or eigh() can be used, for sparse
problems eigs() or eigsh() should be used.
which [‘LM’ | ‘SM’ | ‘LR’ | ‘SR’ | ‘LI’ | ‘SI’ (default: ‘SM’)] Which eigenvectors and eigen-
values to find, see scipy.sparse.linalg.eigs() or scipy.sparse.linalg.eigsh().
For dense problmes, only ‘LM’ and ‘SM’ can be used
* [*] Additional parameters supported by the method.
name = 'eig.scipy'
class sfepy.solvers.eigen.ScipySGEigenvalueSolver(conf, **kwargs)
SciPy-based solver for dense symmetric problems.
Kind: ‘eig.sgscipy’
For common configuration parameters, see Solver.
Specific configuration parameters:
name = 'eig.sgscipy'
sfepy.solvers.eigen.eig(mtx_a, mtx_b=None, n_eigs=None, eigenvectors=True, return_time=None,
method='eig.scipy', **ckwargs)
Utility function that constructs an eigenvalue solver given by method, calls it and returns solution.
sfepy.solvers.eigen.init_slepc_args()
sfepy.solvers.eigen.standard_call(call)
Decorator handling argument preparation and timing for eigensolvers.
sfepy.solvers.ls module
name = 'ls.cm_pb'
sparse_submat(Ad, Ar, Ac, gr, gc, S)
A[gr,gc] = S
class sfepy.solvers.ls.PETScKrylovSolver(conf, comm=None, context=None, **kwargs)
PETSc Krylov subspace solver.
The solver supports parallel use with a given MPI communicator (see comm argument of PETScKrylovSolver.
__init__()) and allows passing in PETSc matrices and vectors. Returns a (global) PETSc solution vector
instead of a (local) numpy array, when given a PETSc right-hand side vector.
The solver and preconditioner types are set upon the solver object creation. Tolerances can be overridden when
called by passing a conf object.
Convergence is reached when rnorm < max(eps_r * rnorm_0, eps_a), where, in PETSc, rnorm is by default the
norm of preconditioned residual.
Kind: ‘ls.petsc’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
method [str (default: ‘cg’)] The actual solver to use.
setup_precond [callable] User-supplied function for the preconditioner initialization/setup. It
is called as setup_precond(mtx, context), where mtx is the matrix, context is a user-supplied
context, and should return an object with setUp(self, pc) and apply(self, pc, x, y) methods.
Has precedence over the precond/sub_precond parameters.
precond [str (default: ‘icc’)] The preconditioner.
sub_precond [str (default: ‘none’)] The preconditioner for matrix blocks (in parallel runs).
precond_side [{‘left’, ‘right’, ‘symmetric’, None}] The preconditioner side.
i_max [int (default: 100)] The maximum number of iterations.
eps_a [float (default: 1e-08)] The absolute tolerance for the residual.
eps_r [float (default: 1e-08)] The relative tolerance for the residual.
eps_d [float (default: 100000.0)] The divergence tolerance for the residual.
force_reuse [bool (default: False)] If True, skip the check whether the KSP solver object corre-
sponds to the mtx argument: it is always reused.
* [*] Additional parameters supported by the method. Can be used to pass all PETSc options
supported by petsc.Options().
create_ksp(options=None, comm=None)
create_petsc_matrix(mtx, comm=None)
name = 'ls.petsc'
set_field_split(field_ranges, comm=None)
Setup local PETSc ranges for fields to be used with ‘fieldsplit’ preconditioner.
This function must be called before solving the linear system.
class sfepy.solvers.ls.PyAMGKrylovSolver(conf, context=None, **kwargs)
Interface to PyAMG Krylov solvers.
Kind: ‘ls.pyamg_krylov’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
method [str (default: ‘cg’)] The actual solver to use.
setup_precond [callable (default: <function PyAMGKrylovSolver.<lambda> at
0x7f1c89b194c0>)] User-supplied function for the preconditioner initialization/setup.
It is called as setup_precond(mtx, context), where mtx is the matrix, context is a user-
supplied context, and should return one of {sparse matrix, dense matrix, LinearOperator}.
callback [callable] User-supplied function to call after each iteration. It is called as callback(xk),
where xk is the current solution vector, except the gmres method, where the argument is the
residual norm.
i_max [int (default: 100)] The maximum number of iterations.
eps_r [float (default: 1e-08)] The relative tolerance for the residual.
* [*] Additional parameters supported by the method.
name = 'ls.pyamg_krylov'
class sfepy.solvers.ls.PyAMGSolver(conf, **kwargs)
Interface to PyAMG solvers.
The method parameter can be one of: ‘smoothed_aggregation_solver’, ‘ruge_stuben_solver’. The accel param-
eter specifies the Krylov solver name, that is used as an accelerator for the multigrid solver.
Kind: ‘ls.pyamg’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
method [str (default: ‘smoothed_aggregation_solver’)] The actual solver to use.
accel [str] The accelerator.
callback [callable] User-supplied function to call after each iteration. It is called as callback(xk),
where xk is the current solution vector, except the gmres accelerator, where the argument is
the residual norm.
i_max [int (default: 100)] The maximum number of iterations.
eps_r [float (default: 1e-08)] The relative tolerance for the residual.
force_reuse [bool (default: False)] If True, skip the check whether the MG solver object corre-
sponds to the mtx argument: it is always reused.
* [*] Additional parameters supported by the method. Use the ‘method:’ prefix for arguments
of the method construction function (e.g. ‘method:max_levels’ : 5), and the ‘solve:’ prefix
for the subsequent solver call.
name = 'ls.pyamg'
class sfepy.solvers.ls.SchurMumps(conf, **kwargs)
Mumps Schur complement solver.
Kind: ‘ls.schur_mumps’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
use_presolve [bool (default: False)] If True, pre-factorize the matrix.
memory_relaxation [int (default: 20)] The percentage increase in the estimated working space.
schur_variables [list] The list of Schur variables.
name = 'ls.schur_mumps'
class sfepy.solvers.ls.ScipyDirect(conf, method=None, **kwargs)
Direct sparse solver from SciPy.
Kind: ‘ls.scipy_direct’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
method [{‘auto’, ‘umfpack’, ‘superlu’} (default: ‘auto’)] The actual solver to use.
use_presolve [bool (default: False)] If True, pre-factorize the matrix.
name = 'ls.scipy_direct'
presolve(mtx)
eps_a [float (default: 1e-08)] The absolute tolerance for the residual.
eps_r [float (default: 1e-08)] The relative tolerance for the residual.
* [*] Additional parameters supported by the method.
name = 'ls.scipy_iterative'
class sfepy.solvers.ls.ScipySuperLU(conf, **kwargs)
SuperLU - direct sparse solver from SciPy.
Kind: ‘ls.scipy_superlu’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
use_presolve [bool (default: False)] If True, pre-factorize the matrix.
name = 'ls.scipy_superlu'
class sfepy.solvers.ls.ScipyUmfpack(conf, **kwargs)
UMFPACK - direct sparse solver from SciPy.
Kind: ‘ls.scipy_umfpack’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
use_presolve [bool (default: False)] If True, pre-factorize the matrix.
name = 'ls.scipy_umfpack'
sfepy.solvers.ls.petsc_call(call)
Decorator handling argument preparation and timing for PETSc-based linear solvers.
sfepy.solvers.ls.solve(mtx, rhs, solver_class=None, solver_conf=None)
Solve the linear system with the matrix mtx and the right-hand side rhs.
Convenience wrapper around the linear solver classes below.
sfepy.solvers.ls.standard_call(call)
Decorator handling argument preparation and timing for linear solvers.
sfepy.solvers.ls_mumps module
get_schur(schur_list)
Get the Schur matrix and the condensed right-hand side vector.
Parameters
schur_list [array] The list of the Schur DOFs (indexing starts with 1).
Returns
schur_arr [array] The Schur matrix of order ‘schur_size’.
schur_rhs [array] The reduced right-hand side vector.
set_mtx_centralized(mtx)
Set the sparse matrix.
Parameters
mtx [scipy sparse martix] The sparse matrix in COO format.
set_rcd_centralized(ir, ic, data, n)
Set the matrix by row and column indicies and data vector. The matrix shape is determined by the maximal
values of row and column indicies. The indices start with 1.
Parameters
ir [array] The row idicies.
ic [array] The column idicies.
data [array] The matrix entries.
n [int] The matrix dimension.
set_rhs(rhs)
Set the right hand side of the linear system.
set_silent()
set_verbose()
sfepy.solvers.ls_mumps.coo_is_symmetric(mtx, tol=1e-06)
sfepy.solvers.ls_mumps.dec(val, encoding='utf-8')
Decode given bytes using the specified encoding.
sfepy.solvers.ls_mumps.load_library(libname)
Load shared library in a system dependent way.
sfepy.solvers.ls_mumps.load_mumps_libraries()
sfepy.solvers.ls_mumps.mumps_pcomplex
alias of sfepy.solvers.ls_mumps.LP_c_double
sfepy.solvers.ls_mumps.mumps_preal
alias of sfepy.solvers.ls_mumps.LP_c_double
class sfepy.solvers.ls_mumps.mumps_struc_c_4
a
Structure/Union member
a_elt
Structure/Union member
a_loc
Structure/Union member
cntl
Structure/Union member
colsca
Structure/Union member
comm_fortran
Structure/Union member
deficiency
Structure/Union member
eltptr
Structure/Union member
eltvar
Structure/Union member
icntl
Structure/Union member
info
Structure/Union member
infog
Structure/Union member
instance_number
Structure/Union member
irhs_ptr
Structure/Union member
irhs_sparse
Structure/Union member
irn
Structure/Union member
irn_loc
Structure/Union member
isol_loc
Structure/Union member
jcn
Structure/Union member
jcn_loc
Structure/Union member
job
Structure/Union member
listvar_schur
Structure/Union member
lredrhs
Structure/Union member
lrhs
Structure/Union member
lsol_loc
Structure/Union member
lwk_user
Structure/Union member
mapping
Structure/Union member
mblock
Structure/Union member
n
Structure/Union member
nblock
Structure/Union member
nelt
Structure/Union member
npcol
Structure/Union member
nprow
Structure/Union member
nrhs
Structure/Union member
nz
Structure/Union member
nz_alloc
Structure/Union member
nz_loc
Structure/Union member
nz_rhs
Structure/Union member
ooc_prefix
Structure/Union member
ooc_tmpdir
Structure/Union member
par
Structure/Union member
perm_in
Structure/Union member
pivnul_list
Structure/Union member
redrhs
Structure/Union member
rhs
Structure/Union member
rhs_sparse
Structure/Union member
rinfo
Structure/Union member
rinfog
Structure/Union member
rowsca
Structure/Union member
schur
Structure/Union member
schur_lld
Structure/Union member
schur_mloc
Structure/Union member
schur_nloc
Structure/Union member
size_schur
Structure/Union member
sol_loc
Structure/Union member
sym
Structure/Union member
sym_perm
Structure/Union member
uns_perm
Structure/Union member
version_number
Structure/Union member
wk_user
Structure/Union member
write_problem
Structure/Union member
class sfepy.solvers.ls_mumps.mumps_struc_c_5_0
a
Structure/Union member
a_elt
Structure/Union member
a_loc
Structure/Union member
cntl
Structure/Union member
colsca
Structure/Union member
colsca_from_mumps
Structure/Union member
comm_fortran
Structure/Union member
deficiency
Structure/Union member
dkeep
Structure/Union member
eltptr
Structure/Union member
eltvar
Structure/Union member
icntl
Structure/Union member
info
Structure/Union member
infog
Structure/Union member
instance_number
Structure/Union member
irhs_ptr
Structure/Union member
irhs_sparse
Structure/Union member
irn
Structure/Union member
irn_loc
Structure/Union member
isol_loc
Structure/Union member
jcn
Structure/Union member
jcn_loc
Structure/Union member
job
Structure/Union member
keep
Structure/Union member
keep8
Structure/Union member
listvar_schur
Structure/Union member
lredrhs
Structure/Union member
lrhs
Structure/Union member
lsol_loc
Structure/Union member
lwk_user
Structure/Union member
mapping
Structure/Union member
mblock
Structure/Union member
n
Structure/Union member
nblock
Structure/Union member
nelt
Structure/Union member
npcol
Structure/Union member
nprow
Structure/Union member
nrhs
Structure/Union member
nz
Structure/Union member
nz_alloc
Structure/Union member
nz_loc
Structure/Union member
nz_rhs
Structure/Union member
ooc_prefix
Structure/Union member
ooc_tmpdir
Structure/Union member
par
Structure/Union member
perm_in
Structure/Union member
pivnul_list
Structure/Union member
redrhs
Structure/Union member
rhs
Structure/Union member
rhs_sparse
Structure/Union member
rinfo
Structure/Union member
rinfog
Structure/Union member
rowsca
Structure/Union member
rowsca_from_mumps
Structure/Union member
schur
Structure/Union member
schur_lld
Structure/Union member
schur_mloc
Structure/Union member
schur_nloc
Structure/Union member
size_schur
Structure/Union member
sol_loc
Structure/Union member
sym
Structure/Union member
sym_perm
Structure/Union member
uns_perm
Structure/Union member
version_number
Structure/Union member
wk_user
Structure/Union member
write_problem
Structure/Union member
class sfepy.solvers.ls_mumps.mumps_struc_c_5_1
a
Structure/Union member
a_elt
Structure/Union member
a_loc
Structure/Union member
cntl
Structure/Union member
colsca
Structure/Union member
colsca_from_mumps
Structure/Union member
comm_fortran
Structure/Union member
deficiency
Structure/Union member
dkeep
Structure/Union member
eltptr
Structure/Union member
eltvar
Structure/Union member
icntl
Structure/Union member
info
Structure/Union member
infog
Structure/Union member
instance_number
Structure/Union member
irhs_ptr
Structure/Union member
irhs_sparse
Structure/Union member
irn
Structure/Union member
irn_loc
Structure/Union member
isol_loc
Structure/Union member
jcn
Structure/Union member
jcn_loc
Structure/Union member
job
Structure/Union member
keep
Structure/Union member
keep8
Structure/Union member
listvar_schur
Structure/Union member
lredrhs
Structure/Union member
lrhs
Structure/Union member
lsol_loc
Structure/Union member
lwk_user
Structure/Union member
mapping
Structure/Union member
mblock
Structure/Union member
n
Structure/Union member
nblock
Structure/Union member
nelt
Structure/Union member
nnz
Structure/Union member
nnz_loc
Structure/Union member
npcol
Structure/Union member
nprow
Structure/Union member
nrhs
Structure/Union member
nz
Structure/Union member
nz_alloc
Structure/Union member
nz_loc
Structure/Union member
nz_rhs
Structure/Union member
ooc_prefix
Structure/Union member
ooc_tmpdir
Structure/Union member
par
Structure/Union member
perm_in
Structure/Union member
pivnul_list
Structure/Union member
redrhs
Structure/Union member
rhs
Structure/Union member
rhs_sparse
Structure/Union member
rinfo
Structure/Union member
rinfog
Structure/Union member
rowsca
Structure/Union member
rowsca_from_mumps
Structure/Union member
save_dir
Structure/Union member
save_prefix
Structure/Union member
schur
Structure/Union member
schur_lld
Structure/Union member
schur_mloc
Structure/Union member
schur_nloc
Structure/Union member
size_schur
Structure/Union member
sol_loc
Structure/Union member
sym
Structure/Union member
sym_perm
Structure/Union member
uns_perm
Structure/Union member
version_number
Structure/Union member
wk_user
Structure/Union member
write_problem
Structure/Union member
class sfepy.solvers.ls_mumps.mumps_struc_c_5_2
a
Structure/Union member
a_elt
Structure/Union member
a_loc
Structure/Union member
cntl
Structure/Union member
colsca
Structure/Union member
colsca_from_mumps
Structure/Union member
comm_fortran
Structure/Union member
deficiency
Structure/Union member
dkeep
Structure/Union member
eltptr
Structure/Union member
eltvar
Structure/Union member
icntl
Structure/Union member
info
Structure/Union member
infog
Structure/Union member
instance_number
Structure/Union member
irhs_loc
Structure/Union member
irhs_ptr
Structure/Union member
irhs_sparse
Structure/Union member
irn
Structure/Union member
irn_loc
Structure/Union member
isol_loc
Structure/Union member
jcn
Structure/Union member
jcn_loc
Structure/Union member
job
Structure/Union member
keep
Structure/Union member
keep8
Structure/Union member
listvar_schur
Structure/Union member
lredrhs
Structure/Union member
lrhs
Structure/Union member
lrhs_loc
Structure/Union member
lsol_loc
Structure/Union member
lwk_user
Structure/Union member
mapping
Structure/Union member
mblock
Structure/Union member
metis_options
Structure/Union member
n
Structure/Union member
nblock
Structure/Union member
nelt
Structure/Union member
nloc_rhs
Structure/Union member
nnz
Structure/Union member
nnz_loc
Structure/Union member
npcol
Structure/Union member
nprow
Structure/Union member
nrhs
Structure/Union member
nz
Structure/Union member
nz_alloc
Structure/Union member
nz_loc
Structure/Union member
nz_rhs
Structure/Union member
ooc_prefix
Structure/Union member
ooc_tmpdir
Structure/Union member
par
Structure/Union member
perm_in
Structure/Union member
pivnul_list
Structure/Union member
redrhs
Structure/Union member
rhs
Structure/Union member
rhs_loc
Structure/Union member
rhs_sparse
Structure/Union member
rinfo
Structure/Union member
rinfog
Structure/Union member
rowsca
Structure/Union member
rowsca_from_mumps
Structure/Union member
save_dir
Structure/Union member
save_prefix
Structure/Union member
schur
Structure/Union member
schur_lld
Structure/Union member
schur_mloc
Structure/Union member
schur_nloc
Structure/Union member
size_schur
Structure/Union member
sol_loc
Structure/Union member
sym
Structure/Union member
sym_perm
Structure/Union member
uns_perm
Structure/Union member
version_number
Structure/Union member
wk_user
Structure/Union member
write_problem
Structure/Union member
class sfepy.solvers.ls_mumps.mumps_struc_c_x
aux
Structure/Union member
comm_fortran
Structure/Union member
icntl
Structure/Union member
job
Structure/Union member
par
Structure/Union member
sym
Structure/Union member
sfepy.solvers.ls_mumps_parallel module
sfepy.solvers.ls_mumps_parallel.mumps_parallel_solve()
sfepy.solvers.ls_mumps_parallel.tmpfile(fname)
sfepy.solvers.nls module
Nonlinear solvers.
class sfepy.solvers.nls.Newton(conf, **kwargs)
Solves a nonlinear system 𝑓 (𝑥) = 0 using the Newton method.
The solver uses a backtracking line-search on divergence.
Kind: ‘nls.newton’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
i_max [int (default: 1)] The maximum number of iterations.
eps_a [float (default: 1e-10)] The absolute tolerance for the residual, i.e. ||𝑓 (𝑥𝑖 )||.
eps_r [float (default: 1.0)] The relative tolerance for the residual, i.e. ||𝑓 (𝑥𝑖 )||/||𝑓 (𝑥0 )||.
eps_mode [‘and’ or ‘or’ (default: ‘and’)] The logical operator to use for combining the absolute
and relative tolerances.
macheps [float (default: 2.220446049250313e-16)] The float considered to be machine “zero”.
lin_red [float (default: 1.0)] The linear system solution error should be smaller than (eps_a *
lin_red), otherwise a warning is printed.
lin_precision [float or None] If not None, the linear system solution tolerances are set in each
nonlinear iteration relative to the current residual norm by the lin_precision factor. Ignored
for direct linear solvers.
step_red [0.0 < float <= 1.0 (default: 1.0)] Step reduction factor. Equivalent to the mixing
parameter 𝑎: (1 − 𝑎)𝑥 + 𝑎(𝑥 + 𝑑𝑥) = 𝑥 + 𝑎𝑑𝑥
ls_on [float (default: 0.99999)] Start the backtracking line-search by reducing the step, if
||𝑓 (𝑥𝑖 )||/||𝑓 (𝑥𝑖−1 )|| is larger than ls_on.
ls_red [0.0 < float < 1.0 (default: 0.1)] The step reduction factor in case of correct residual
assembling.
ls_red_warp [0.0 < float < 1.0 (default: 0.001)] The step reduction factor in case of failed resid-
ual assembling (e.g. the “warp violation” error caused by a negative volume element result-
ing from too large deformations).
ls_min [0.0 < float < 1.0 (default: 1e-05)] The minimum step reduction factor.
give_up_warp [bool (default: False)] If True, abort on the “warp violation” error.
check [0, 1 or 2 (default: 0)] If >= 1, check the tangent matrix using finite differences. If 2, plot
the resulting sparsity patterns.
delta [float (default: 1e-06)] If check >= 1, the finite difference matrix is taken as 𝐴𝑖𝑗 =
𝑓𝑖 (𝑥𝑗 +𝛿)−𝑓𝑖 (𝑥𝑗 −𝛿)
2𝛿 .
log [dict or None] If not None, log the convergence according to the configuration in the follow-
ing form: {'text' : 'log.txt', 'plot' : 'log.pdf'}. Each of the dict items
can be None.
is_linear [bool (default: False)] If True, the problem is considered to be linear.
__call__(vec_x0, conf=None, fun=None, fun_grad=None, lin_solver=None, iter_hook=None, status=None)
Nonlinear system solver call.
Solves a nonlinear system 𝑓 (𝑥) = 0 using the Newton method with backtracking line-search, starting with
an initial guess 𝑥0 .
Parameters
vec_x0 [array] The initial guess vector 𝑥0 .
conf [Struct instance, optional] The solver configuration parameters,
fun [function, optional] The function 𝑓 (𝑥) whose zero is sought - the residual.
fun_grad [function, optional] The gradient of 𝑓 (𝑥) - the tangent matrix.
lin_solver [LinearSolver instance, optional] The linear solver for each nonlinear iteration.
iter_hook [function, optional] User-supplied function to call before each iteration.
status [dict-like, optional] The user-supplied object to hold convergence statistics.
Notes
• The optional parameters except iter_hook and status need to be given either here or upon Newton
construction.
• Setting conf.is_linear == True means a pre-assembled and possibly pre-solved matrix. This is mostly
useful for linear time-dependent problems.
__init__(conf, **kwargs)
__module__ = 'sfepy.solvers.nls'
name = 'nls.newton'
class sfepy.solvers.nls.PETScNonlinearSolver(conf, pmtx=None, prhs=None, comm=None, **kwargs)
Interface to PETSc SNES (Scalable Nonlinear Equations Solvers).
The solver supports parallel use with a given MPI communicator (see comm argument of
PETScNonlinearSolver.__init__()). Returns a (global) PETSc solution vector instead of a (local)
numpy array, when given a PETSc initial guess vector.
For parallel use, the fun and fun_grad callbacks should be provided by PETScParallelEvaluator.
Kind: ‘nls.petsc’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
method [str (default: ‘newtonls’)] The SNES type.
i_max [int (default: 10)] The maximum number of iterations.
if_max [int (default: 100)] The maximum number of function evaluations.
eps_a [float (default: 1e-10)] The absolute tolerance for the residual, i.e. ||𝑓 (𝑥𝑖 )||.
eps_r [float (default: 1.0)] The relative tolerance for the residual, i.e. ||𝑓 (𝑥𝑖 )||/||𝑓 (𝑥0 )||.
eps_s [float (default: 0.0)] The convergence tolerance in terms of the norm of the change in the
solution between steps, i.e. $||delta x|| < epsilon_s ||x||$
__call__(vec_x0, conf=None, fun=None, fun_grad=None, lin_solver=None, iter_hook=None, status=None,
pmtx=None, prhs=None, comm=None)
Call self as a function.
__init__(conf, pmtx=None, prhs=None, comm=None, **kwargs)
__module__ = 'sfepy.solvers.nls'
name = 'nls.petsc'
class sfepy.solvers.nls.ScipyBroyden(conf, **kwargs)
Interface to Broyden and Anderson solvers from scipy.optimize.
Kind: ‘nls.scipy_broyden_like’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
__module__ = 'sfepy.solvers.nls'
name = 'nls.scipy_broyden_like'
set_method(conf )
sfepy.solvers.optimize module
eps_ofg [float (default: 1e-08)] The tolerance for the objective function gradient.
norm [numpy norm (default: inf)] The norm to be used.
ls [bool (default: True)] If True, use a line-search.
ls_method [{‘backtracking’, ‘full’} (default: ‘backtracking’)] The line-search method.
ls_on [float (default: 0.99999)] Start the backtracking line-search by reducing the step, if
||𝑓 (𝑥𝑖 )||/||𝑓 (𝑥𝑖−1 )|| is larger than ls_on.
ls0 [0.0 < float < 1.0 (default: 1.0)] The initial step.
ls_red [0.0 < float < 1.0 (default: 0.5)] The step reduction factor in case of correct residual
assembling.
ls_red_warp [0.0 < float < 1.0 (default: 0.1)] The step reduction factor in case of failed residual
assembling (e.g. the “warp violation” error caused by a negative volume element resulting
from too large deformations).
ls_min [0.0 < float < 1.0 (default: 1e-05)] The minimum step reduction factor.
check [0, 1 or 2 (default: 0)] If >= 1, check the tangent matrix using finite differences. If 2, plot
the resulting sparsity patterns.
delta [float (default: 1e-06)] If check >= 1, the finite difference matrix is taken as 𝐴𝑖𝑗 =
𝑓𝑖 (𝑥𝑗 +𝛿)−𝑓𝑖 (𝑥𝑗 −𝛿)
2𝛿 .
output [function] If given, use it instead of output() function.
yscales [list of str (default: [‘linear’, ‘log’, ‘log’, ‘linear’])] The list of four convergence log
subplot scales.
log [dict or None] If not None, log the convergence according to the configuration in the follow-
ing form: {'text' : 'log.txt', 'plot' : 'log.pdf'}. Each of the dict items
can be None.
name = 'opt.fmin_sd'
class sfepy.solvers.optimize.ScipyFMinSolver(conf, **kwargs)
Interface to SciPy optimization solvers scipy.optimize.fmin_*.
Kind: ‘nls.scipy_fmin_like’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
method [{‘fmin’, ‘fmin_bfgs’, ‘fmin_cg’, ‘fmin_cobyla’, ‘fmin_l_bfgs_b’, ‘fmin_ncg’,
‘fmin_powell’, ‘fmin_slsqp’, ‘fmin_tnc’} (default: ‘fmin’)] The actual optimization method
to use.
i_max [int (default: 10)] The maximum number of iterations.
* [*] Additional parameters supported by the method.
name = 'nls.scipy_fmin_like'
set_method(conf )
Returns
flag [int]
• -1 . . . continue
• 0 . . . small OF -> stop
• 1 . . . i_max reached -> stop
• 2 . . . small OFG -> stop
• 3 . . . small relative decrase of OF
sfepy.solvers.optimize.wrap_function(function, args)
sfepy.solvers.oseen module
Notes
get_maps()
Get the maps of names and indices of variables in state vector.
setup(problem)
Setup common problem-dependent data.
sfepy.solvers.oseen.are_close(a, b, rtol=0.2, atol=1e-08)
sfepy.solvers.qeigen module
sfepy.solvers.semismooth_newton module
𝐹 (𝑦) = 0
𝐴(𝑦) ≥ 0 , 𝐵(𝑦) ≥ 0 , ⟨𝐴(𝑦), 𝐵(𝑦)⟩ = 0
name = 'nls.semismooth_newton'
sfepy.solvers.solvers module
sfepy.solvers.solvers.make_get_conf(conf, kwargs)
sfepy.solvers.ts module
static from_conf(conf )
get_state()
iter_from(step)
normalize_time()
restore_step_time()
set_from_ts(ts, step=None)
set_state(step=0, **kwargs)
set_step(step=0, nt=0.0)
set_substep_time(sub_dt)
static from_conf(conf )
get_default_time_step()
get_state()
iter_from(step)
iter_from_current()
ts.step, ts.time is consistent with step, time returned here ts.nt is normalized time in [0, 1].
set_from_data(t0, t1, dt=None, n_step=None, step=None)
set_from_ts(ts, step=None)
set_n_digit_from_min_dt(dt)
set_step(step=0, nt=0.0)
set_time_step(dt, update_time=False)
sfepy.solvers.ts.get_print_info(n_step)
sfepy.solvers.ts_solvers module
get_matrices(nls, vec)
name = 'ts.generalized_alpha'
class sfepy.solvers.ts_solvers.NewmarkTS(conf, nls=None, context=None, **kwargs)
Solve elastodynamics problems by the Newmark method.
The method was introduced in [1]. Common settings [2]:
name = 'ts.newmark'
class sfepy.solvers.ts_solvers.SimpleTimeSteppingSolver(conf, nls=None, context=None, **kwargs)
Implicit time stepping solver with a fixed time step.
Kind: ‘ts.simple’
For common configuration parameters, see Solver.
Specific configuration parameters:
Parameters
t0 [float (default: 0.0)] The initial time.
t1 [float (default: 1.0)] The final time.
dt [float] The time step. Used if n_step is not given.
n_step [int (default: 10)] The number of time steps. Has precedence over dt.
quasistatic [bool (default: False)] If True, assume a quasistatic time-stepping. Then the non-
linear solver is invoked also for the initial time.
name = 'ts.simple'
output_step_info(ts)
solve_step0(nls, vec0)
name = 'ts.velocity_verlet'
sfepy.solvers.ts_solvers.adapt_time_step(ts, status, adt, context=None, verbose=False)
Adapt the time step of ts according to the exit status of the nonlinear solver.
The time step dt is reduced, if the nonlinear solver did not converge. If it converged in less then a specified number
of iterations for several time steps, the time step is increased. This is governed by the following parameters:
• red_factor : time step reduction factor
• red_max : maximum time step reduction factor
• inc_factor : time step increase factor
• inc_on_iter : increase time step if the nonlinear solver converged in less than this amount of iterations. . .
• inc_wait : . . . for this number of consecutive time steps
Parameters
ts [VariableTimeStepper instance] The time stepper.
status [IndexedStruct instance] The nonlinear solver exit status.
adt [Struct instance] The object with the adaptivity parameters of the time-stepping solver such
as red_factor (see above) as attributes.
context [object, optional] The context can be used in user-defined adaptivity functions. Not used
here.
Returns
is_break [bool] If True, the adaptivity loop should stop.
sfepy.solvers.ts_solvers.gen_multi_vec_packing(size, num)
sfepy.solvers.ts_solvers.get_min_dt(adt)
sfepy.solvers.ts_solvers.standard_ts_call(call)
Decorator handling argument preparation and timing for time-stepping solvers.
sfepy.terms package
sfepy.terms.terms module
class sfepy.terms.terms.ConnInfo(**kwargs)
get_region(can_trace=True)
get_region_name(can_trace=True)
advance(ts)
Advance to the next time step. Implemented in subclasses.
arg_shapes = {}
arg_types = ()
assemble_to(asm_obj, val, iels, mode='vector', diff_var=None)
Assemble the results of term evaluation.
For standard terms, assemble the values in val corresponding to elements/cells iels into a vector or a CSR
sparse matrix asm_obj, depending on mode.
For terms with a dynamic connectivity (e.g. contact terms), in ‘matrix’ mode, return the extra COO sparse
matrix instead. The extra matrix has to be added to the global matrix by the caller. By default, this is done
in Equations.evaluate().
assign_args(variables, materials, user=None)
Check term argument existence in variables, materials, user data and assign the arguments to terms. Also
check compatibility of field and term regions.
call_function(out, fargs)
call_get_fargs(args, kwargs)
check_args()
Common checking to all terms.
Check compatibility of field and term regions.
check_shapes(*args, **kwargs)
Check term argument shapes at run-time.
classify_args()
Classify types of the term arguments and find matching call signature.
A state variable can be in place of a parameter variable and vice versa.
eval_complex(shape, fargs, mode='eval', term_mode=None, diff_var=None, **kwargs)
Notes
This is a convenience wrapper of Variable.evaluate() that initializes the arguments using the term data.
get_arg_name(arg_type, full=False, join=None)
Get the name of the argument specified by arg_type.
Parameters
arg_type [str] The argument type string.
full [bool] If True, return the full name. For example, if the name of a variable argument is
‘u’ and its time derivative is requested, the full name is ‘du/dt’.
join [str, optional] Optionally, the material argument name tuple can be joined to a single
string using the join string.
Returns
name [str] The argument name.
get_args(arg_types=None, **kwargs)
Return arguments by type as specified in arg_types (or self.ats). Arguments in **kwargs can override the
ones assigned at the term construction - this is useful for passing user data.
get_args_by_name(arg_names)
Return arguments by name.
get_assembling_cells(shape=None)
Return the assembling cell indices into a DOF connectivity.
get_conn_info()
get_conn_key()
The key to be used in DOF connectivity information.
get_data_shape(variable)
Get data shape information from variable.
Notes
This is a convenience wrapper of FieldVariable.get_data_shape() that initializes the arguments using the
term data.
get_dof_conn_type()
get_geometry_types()
Returns
out [dict] The required geometry types for each variable argument.
get_kwargs(keys, **kwargs)
Extract arguments from **kwargs listed in keys (default is None).
get_mapping(variable, get_saved=False, return_key=False)
Get the reference mapping from a variable.
Notes
This is a convenience wrapper of Field.get_mapping() that initializes the arguments using the term data.
get_material_names()
get_materials(join=False)
get_parameter_names()
get_parameter_variables()
get_physical_qps()
Get physical quadrature points corresponding to the term region and integral.
get_qp_key()
Return a key identifying uniquely the term quadrature points.
get_region()
get_state_names()
If variables are given, return only true unknowns whose data are of the current time step (0).
get_state_variables(unknown_only=False)
get_str()
get_user_names()
get_variable_names()
get_variables(as_list=True)
get_vector(variable)
Get the vector stored in variable according to self.arg_steps and self.arg_derivatives. Supports only the
backward difference w.r.t. time.
get_virtual_name()
get_virtual_variable()
integration = 'volume'
name = ''
static new(name, integral, region, **kwargs)
set_arg_types()
set_integral(integral)
Set the term integral.
setup()
setup_args(**kwargs)
setup_formal_args()
setup_integration()
standalone_setup()
time_update(ts)
class sfepy.terms.terms.Terms(objs=None)
append(obj)
get_user_names()
get_variable_names()
insert(ii, obj)
setup()
update_expression()
sfepy.terms.terms.create_arg_parser()
sfepy.terms.terms.get_arg_kinds(arg_types)
Translate arg_types of a Term to a canonical form.
Parameters
arg_types [tuple of strings] The term argument types, as given in the arg_types attribute.
Returns
arg_kinds [list of strings] The argument kinds - one of ‘virtual_variable’, ‘state_variable’, ‘pa-
rameter_variable’, ‘opt_material’, ‘ts’, ‘user’.
sfepy.terms.terms.get_shape_kind(integration)
Get data shape kind for given integration type.
sfepy.terms.terms.split_complex_args(args)
Split complex arguments to real and imaginary parts.
Returns
newargs [dictionary] Dictionary with lists corresponding to args such that each argument of
numpy.complex128 data type is split to its real and imaginary part. The output depends on
the number of complex arguments in ‘args’:
• 0: list (key ‘r’) identical to input one
• 1: two lists with keys ‘r’, ‘i’ corresponding to real and imaginary parts
• 2: output dictionary contains four lists:
– ‘r’ - real(arg1), real(arg2)
– ‘i’ - imag(arg1), imag(arg2)
– ‘ri’ - real(arg1), imag(arg2)
– ‘ir’ - imag(arg1), real(arg2)
sfepy.terms.terms_adj_navier_stokes module
Arguments
• virtual : 𝑣
• state : 𝑤
• parameter : 𝑢
name = 'dw_adj_convect1'
class sfepy.terms.terms_adj_navier_stokes.AdjConvect2Term(name, arg_str, integral, region,
**kwargs)
The second adjoint term to nonlinear convective term dw_convect.
Definition
∫︁
((𝑢 · ∇)𝑣) · 𝑤
Ω
Call signature
Arguments
• virtual : 𝑣
• state : 𝑤
• parameter : 𝑢
name = 'dw_adj_convect2'
class sfepy.terms.terms_adj_navier_stokes.AdjDivGradTerm(name, arg_str, integral, region,
**kwargs)
Gateaux differential of Ψ(𝑢) = Ω 𝜈 ∇𝑣 : ∇𝑢 w.r.t. 𝑢 in the direction 𝑣 or adjoint term to dw_div_grad.
∫︀
Definition
𝑤𝛿𝑢 Ψ(𝑢) ∘ 𝑣
Call signature
Arguments
• material_1 : 𝑤 (weight)
• material_2 : 𝜈 (viscosity)
• virtual : 𝑣
• state : 𝑢
name = 'dw_adj_div_grad'
class sfepy.terms.terms_adj_navier_stokes.NSOFMinGradTerm(name, arg_str, integral, region,
**kwargs)
Call signature
name = 'd_of_ns_min_grad'
Arguments
• material : 𝑤 (weight)
• virtual : 𝑞
name = 'dw_of_ns_surf_min_d_press_diff'
class sfepy.terms.terms_adj_navier_stokes.NSOFSurfMinDPressTerm(name, arg_str, integral, region,
**kwargs)
Sensitivity of Ψ(𝑝).
Definition
(︂∫︁ ∫︁ )︂
𝛿Ψ(𝑝) = 𝛿 𝑝− 𝑏𝑝𝑟𝑒𝑠𝑠
Γ𝑖𝑛 Γ𝑜𝑢𝑡
Call signature
Arguments
• material_1 : 𝑤 (weight)
• material_2 : 𝑏𝑝𝑟𝑒𝑠𝑠 (given pressure)
• parameter : 𝑝
integration = 'surface'
name = 'ev_of_ns_surf_min_d_press'
class sfepy.terms.terms_adj_navier_stokes.SDConvectTerm(name, arg_str, integral, region, **kwargs)
Sensitivity (shape derivative) of convective term dw_convect.
Supports the following term modes: 1 (sensitivity) or 0 (original term value).
Definition
∫︁
𝜕𝑢𝑖 𝜕𝒱𝑗 𝜕𝑢𝑖
[𝑢𝑘 𝑤𝑖 (∇ · 𝒱) − 𝑢𝑘 𝑤𝑖 ]
Ω 𝜕𝑥𝑘 𝜕𝑥𝑘 𝜕𝑥𝑗
Call signature
Arguments
• parameter_u : 𝑢
• parameter_w : 𝑤
• parameter_mv : 𝒱
name = 'ev_sd_convect'
class sfepy.terms.terms_adj_navier_stokes.SDDivGradTerm(name, arg_str, integral, region, **kwargs)
Sensitivity (shape derivative) of diffusion term dw_div_grad.
Supports the following term modes: 1 (sensitivity) or 0 (original term value).
Definition
∫︁ ∫︁
ˆ
𝐼∇𝑣 : ∇𝑢 , ˆ
𝜈 𝐼∇𝑣 : ∇𝑢
Ω Ω
𝜕𝒱𝑙 𝜕𝒱𝑘
𝐼ˆ𝑖𝑗𝑘𝑙 = 𝛿𝑖𝑘 𝛿𝑗𝑙 ∇ · 𝒱 − 𝛿𝑖𝑘 𝛿𝑗𝑠 − 𝛿𝑖𝑠 𝛿𝑗𝑙
𝜕𝑥𝑠 𝜕𝑥𝑠
Call signature
Arguments
• material : 𝜈 (viscosity, optional)
• parameter_u : 𝑢
• parameter_w : 𝑤
• parameter_mv : 𝒱
name = 'ev_sd_div_grad'
class sfepy.terms.terms_adj_navier_stokes.SDDivTerm(name, arg_str, integral, region, **kwargs)
Sensitivity (shape derivative) of Stokes term dw_stokes in ‘div’ mode.
Supports the following term modes: 1 (sensitivity) or 0 (original term value).
Definition
∫︁
𝜕𝒱𝑘 𝜕𝑤𝑖
𝑝[(∇ · 𝑤)(∇ · 𝒱) − ]
Ω 𝜕𝑥𝑖 𝜕𝑥𝑘
Call signature
Arguments
• parameter_u : 𝑢
• parameter_p : 𝑝
• parameter_mv : 𝒱
name = 'ev_sd_div'
class sfepy.terms.terms_adj_navier_stokes.SDDotTerm(name, arg_str, integral, region, **kwargs)
Sensitivity (shape derivative) of dot product of scalars or vectors.
Definition
∫︁ ∫︁
𝑝𝑞(∇ · 𝒱) , (𝑢 · 𝑤)(∇ · 𝒱)
Ω Ω
Call signature
Arguments
• parameter_1 : 𝑝 or 𝑢
• parameter_2 : 𝑞 or 𝑤
• parameter_mv : 𝒱
name = 'ev_sd_dot'
class sfepy.terms.terms_adj_navier_stokes.SDGradDivStabilizationTerm(name, arg_str, integral,
region, **kwargs)
Sensitivity (shape derivative) of stabilization term dw_st_grad_div.
Definition
∫︁
𝜕𝑢𝑖 𝜕𝒱𝑘 𝜕𝑤𝑖 𝜕𝒱𝑘
𝛾 [(∇ · 𝑢)(∇ · 𝑤)(∇ · 𝒱) − (∇ · 𝑤) − (∇ · 𝑢) ]
Ω 𝜕𝑥𝑘 𝜕𝑥𝑖 𝜕𝑥𝑘 𝜕𝑥𝑖
Call signature
Arguments
• material : 𝛾
• parameter_u : 𝑢
• parameter_w : 𝑤
• parameter_mv : 𝒱
• mode : 1 (sensitivity) or 0 (original term value)
name = 'ev_sd_st_grad_div'
Call signature
Arguments
• material : 𝛿𝐾
• parameter_b : 𝑏
• parameter_u : 𝑢
• parameter_r : 𝑟
• parameter_mv : 𝒱
• mode : 1 (sensitivity) or 0 (original term value)
name = 'ev_sd_st_pspg_c'
class sfepy.terms.terms_adj_navier_stokes.SDPSPGPStabilizationTerm(name, arg_str, integral,
region, **kwargs)
Sensitivity (shape derivative) of stabilization term dw_st_pspg_p.
Definition
∑︁ ∫︁ 𝜕𝑟 𝜕𝑝
𝜏𝐾 [(∇𝑟 · ∇𝑝)(∇ · 𝒱) − (∇𝒱𝑘 · ∇𝑝) − (∇𝑟 · ∇𝒱𝑘 ) ]
𝑇𝐾 𝜕𝑥𝑘 𝜕𝑥𝑘
𝐾∈ℐℎ
Call signature
Arguments
• material : 𝜏𝐾
• parameter_r : 𝑟
• parameter_p : 𝑝
• parameter_mv : 𝒱
• mode : 1 (sensitivity) or 0 (original term value)
name = 'ev_sd_st_pspg_p'
class sfepy.terms.terms_adj_navier_stokes.SDSUPGCStabilizationTerm(name, arg_str, integral,
region, **kwargs)
Sensitivity (shape derivative) of stabilization term dw_st_supg_c.
Definition
∑︁ ∫︁ 𝜕𝑢𝑘 𝜕𝑤𝑘
𝛿𝐾 [(𝑏 · ∇𝑢𝑘 )(𝑏 · ∇𝑤𝑘 )(∇ · 𝒱) − (𝑏 · ∇𝒱𝑖 ) (𝑏 · ∇𝑤𝑘 ) − (𝑢 · ∇𝑢𝑘 )(𝑏 · ∇𝒱𝑖 ) ]
𝑇𝐾 𝜕𝑥𝑖 𝜕𝑥𝑖
𝐾∈ℐℎ
Call signature
Arguments
• material : 𝛿𝐾
• parameter_b : 𝑏
• parameter_u : 𝑢
• parameter_w : 𝑤
• parameter_mv : 𝒱
• mode : 1 (sensitivity) or 0 (original term value)
name = 'ev_sd_st_supg_c'
class sfepy.terms.terms_adj_navier_stokes.SUPGCAdjStabilizationTerm(name, arg_str, integral,
region, **kwargs)
Adjoint term to SUPG stabilization term dw_st_supg_c.
Definition
∑︁ ∫︁
𝛿𝐾 [((𝑣 · ∇)𝑢)((𝑢 · ∇)𝑤) + ((𝑢 · ∇)𝑢)((𝑣 · ∇)𝑤)]
𝐾∈ℐℎ 𝑇𝐾
Call signature
Arguments
• material : 𝛿𝐾
• virtual : 𝑣
• state : 𝑤
• parameter : 𝑢
name = 'dw_st_adj_supg_c'
class sfepy.terms.terms_adj_navier_stokes.SUPGPAdj1StabilizationTerm(name, arg_str, integral,
region, **kwargs)
The first adjoint term to SUPG stabilization term dw_st_supg_p.
Definition
∑︁ ∫︁
𝛿𝐾 ∇𝑝(𝑣 · ∇𝑤)
𝐾∈ℐℎ 𝑇𝐾
Call signature
Arguments
• material : 𝛿𝐾
• virtual : 𝑣
• state : 𝑤
• parameter : 𝑝
name = 'dw_st_adj1_supg_p'
class sfepy.terms.terms_adj_navier_stokes.SUPGPAdj2StabilizationTerm(name, arg_str, integral,
region, **kwargs)
The second adjoint term to SUPG stabilization term dw_st_supg_p as well as adjoint term to PSPG stabilization
term dw_st_pspg_c.
Definition
∑︁ ∫︁
𝜏𝐾 ∇𝑟(𝑣 · ∇𝑢)
𝐾∈ℐℎ 𝑇𝐾
Call signature
Arguments
• material : 𝜏𝐾
• virtual : 𝑣
• parameter : 𝑢
• state : 𝑟
name = 'dw_st_adj2_supg_p'
sfepy.terms.terms_adj_navier_stokes.grad_as_vector(grad)
sfepy.terms.terms_basic module
Definition
∫︁
𝑐
𝒟
Call signature
Arguments
• material : 𝑐 (can have up to two dimensions)
• parameter : 𝑦
integration = 'by_region'
name = 'ev_integrate_mat'
class sfepy.terms.terms_basic.IntegrateOperatorTerm(name, arg_str, integral, region, **kwargs)
Integral of a test function weighted by a scalar function 𝑐.
Definition
∫︁ ∫︁
𝑞 or 𝑐𝑞
𝒟 𝒟
Call signature
Arguments
• material : 𝑐 (optional)
• virtual : 𝑞
integration = 'by_region'
name = 'dw_integrate'
𝑐𝑦 , 𝑐𝑦 , 𝑐𝑦 · 𝑛 flux
𝒟 𝒟 Γ
Call signature
Arguments
• material : 𝑐 (optional)
• parameter : 𝑦 or 𝑦
integration = 'by_region'
name = 'ev_integrate'
class sfepy.terms.terms_basic.SumNodalValuesTerm(name, arg_str, integral, region, **kwargs)
Sum nodal values.
Call signature
ev_sum_vals (parameter)
Arguments
• parameter : 𝑝 or 𝑢
name = 'ev_sum_vals'
class sfepy.terms.terms_basic.SurfaceMomentTerm(name, arg_str, integral, region, **kwargs)
Surface integral of the outer product of the unit outward normal 𝑛 and the coordinate 𝑥 shifted by 𝑥0
Definition
∫︁
𝑛(𝑥 − 𝑥0 )
Γ
Call signature
Arguments
• material : 𝑥0 (special)
• parameter : any variable
integration = 'surface'
name = 'ev_surface_moment'
class sfepy.terms.terms_basic.VolumeSurfaceTerm(name, arg_str, integral, region, **kwargs)
Volume of a 𝐷-dimensional domain, using a surface integral. Uses approximation of the parameter variable.
Definition
∫︁
1/𝐷 𝑥·𝑛
Γ
Call signature
ev_volume_surface (parameter)
Arguments
• parameter : any variable
static function()
integration = 'surface'
name = 'ev_volume_surface'
class sfepy.terms.terms_basic.VolumeTerm(name, arg_str, integral, region, **kwargs)
Volume or surface of a domain. Uses approximation of the parameter variable.
Definition
∫︁
1
𝒟
Call signature
ev_volume (parameter)
Arguments
• parameter : any variable
integration = 'by_region'
name = 'ev_volume'
class sfepy.terms.terms_basic.ZeroTerm(name, arg_str, integral, region, **kwargs)
A do-nothing term useful for introducing additional variables into the equations.
Definition
0
Call signature
Arguments
• virtual : 𝑞 or 𝑣
• state : 𝑝 or 𝑢
name = 'dw_zero'
sfepy.terms.terms_biot module
Call signature
Arguments 1
• ts : TimeStepper instance
• material_0 : 𝛼𝑖𝑗 (0)
• material_1 : exp(−𝜆∆𝑡) (decay at 𝑡1 )
• virtual : 𝑣
• state : 𝑝
Arguments 2
• ts : TimeStepper instance
• material_0 : 𝛼𝑖𝑗 (0)
• material_1 : exp(−𝜆∆𝑡) (decay at 𝑡1 )
• state : 𝑢
• virtual : 𝑞
Arguments
• material : 𝛼𝑖𝑗
• parameter : 𝑝
integration = 'volume'
name = 'ev_biot_stress'
class sfepy.terms.terms_biot.BiotTHTerm(name, arg_str, integral, region, **kwargs)
Fading memory Biot term. Can use derivatives.
Definition
∫︀ [︁∫︀ 𝑡 ]︁
Ω 0
𝛼𝑖𝑗 (𝑡 − 𝜏 ) 𝑝(𝜏 )) d𝜏 𝑒𝑖𝑗 (𝑣) ,
∫︀ [︁∫︀ 𝑡 ]︁
Ω
𝛼
0 𝑖𝑗
(𝑡 − 𝜏 )𝑒 𝑘𝑙 (𝑢(𝜏 )) d𝜏 𝑞
Call signature
Arguments 1
• ts : TimeStepper instance
• material : 𝛼𝑖𝑗 (𝜏 )
• virtual : 𝑣
• state : 𝑝
Arguments 2
• ts : TimeStepper instance
• material : 𝛼𝑖𝑗 (𝜏 )
• state : 𝑢
• virtual : 𝑞
Arguments 1
• material : 𝛼𝑖𝑗
• virtual : 𝑣
• state : 𝑝
Arguments 2
• material : 𝛼𝑖𝑗
• state : 𝑢
• virtual : 𝑞
Arguments 3
• material : 𝛼𝑖𝑗
• parameter_v : 𝑢
• parameter_s : 𝑝
sfepy.terms.terms_compat module
Call signature
ev_cauchy_strain_s (parameter)
name = 'ev_cauchy_strain_s'
class sfepy.terms.terms_compat.DSumNodalValuesTerm(name, arg_str, integral, region, **kwargs)
Call signature
d_sum_vals (parameter)
name = 'd_sum_vals'
class sfepy.terms.terms_compat.DSurfaceFluxTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'd_surface_flux'
class sfepy.terms.terms_compat.DSurfaceMomentTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'd_surface_moment'
Call signature
d_volume_surface (parameter)
name = 'd_volume_surface'
class sfepy.terms.terms_compat.DotSurfaceProductTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'dw_surface_dot'
class sfepy.terms.terms_compat.DotVolumeProductTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'dw_volume_dot'
class sfepy.terms.terms_compat.IntegrateSurfaceMatTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'ev_surface_integrate_mat'
class sfepy.terms.terms_compat.IntegrateSurfaceOperatorTerm(name, arg_str, integral, region,
**kwargs)
Call signature
name = 'dw_surface_integrate'
class sfepy.terms.terms_compat.IntegrateSurfaceTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'ev_surface_integrate'
Call signature
name = 'ev_volume_integrate_mat'
class sfepy.terms.terms_compat.IntegrateVolumeOperatorTerm(name, arg_str, integral, region,
**kwargs)
Call signature
name = 'dw_volume_integrate'
class sfepy.terms.terms_compat.IntegrateVolumeTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'ev_volume_integrate'
class sfepy.terms.terms_compat.SDVolumeDotTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'ev_sd_volume_dot'
class sfepy.terms.terms_compat.SurfaceDivTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'ev_surface_div'
class sfepy.terms.terms_compat.SurfaceGradTerm(name, arg_str, integral, region, **kwargs)
Call signature
name = 'ev_surface_grad'
class sfepy.terms.terms_compat.SurfaceTerm(name, arg_str, integral, region, **kwargs)
Call signature
d_surface (parameter)
name = 'd_surface'
class sfepy.terms.terms_compat.VolumeXTerm(name, arg_str, integral, region, **kwargs)
Call signature
d_volume (parameter)
name = 'd_volume'
sfepy.terms.terms_constraints module
Arguments
• material : 𝑐
• virtual : 𝑣
• state : 𝑢
integration = 'surface'
name = 'dw_non_penetration_p'
class sfepy.terms.terms_constraints.NonPenetrationTerm(name, arg_str, integral, region, **kwargs)
Non-penetration condition in the weak sense.
Definition
∫︁ ∫︁
𝑐𝜆𝑛 · 𝑣 , ˆ ·𝑢
𝑐𝜆𝑛
Γ Γ
∫︁ ∫︁
𝜆𝑛 · 𝑣 , ˆ ·𝑢
𝜆𝑛
Γ Γ
Call signature
Arguments 1
• material : 𝑐 (optional)
• virtual : 𝑣
• state : 𝜆
Arguments 2
• material : 𝑐 (optional)
• state : 𝑢
ˆ
• virtual : 𝜆
integration = 'surface'
modes = ('grad', 'div')
name = 'dw_non_penetration'
sfepy.terms.terms_contact module
∫︁
𝜀𝑁 ⟨𝑔𝑁 (𝑢)⟩𝑛𝑣
Γ𝑐
Call signature
Arguments
• material : 𝜀𝑁
• virtual : 𝑣
• state : 𝑢
integration = 'surface'
name = 'dw_contact'
sfepy.terms.terms_dg module
Note
where
𝑝𝑖𝑛 + 𝑝𝑜𝑢𝑡 𝑝𝑖𝑛 − 𝑝𝑜𝑢𝑡
𝑓 * (𝑝𝑖𝑛 , 𝑝𝑜𝑢𝑡 ) = 𝑎 + (1 − 𝛼)𝑛𝐶 ,
2 2
𝛼 ∈ [0, 1]; 𝛼 = 0 for upwind scheme, 𝛼 = 1 for central scheme, and
the 𝑝𝑖𝑛 resp. 𝑝𝑜𝑢𝑡 is solution on the boundary of the element provided by element itself resp. its neighbor and 𝑎
is advection velocity.
Call signature
Arguments 1
• material : 𝑎
• virtual : 𝑞
• state : 𝑝
Arguments 3
• material : 𝑎
• virtual : 𝑞
• state : 𝑝
• opt_material : 𝛼
alpha = 0
integration = 'volume'
modes = ('weak',)
name = 'dw_dg_advect_laxfrie_flux'
symbolic = {'expression': 'div(a*p)*w', 'map': {'a': 'material', 'p': 'state',
'v': 'virtual'}}
class sfepy.terms.terms_dg.DGTerm(name, arg_str, integral, region, **kwargs)
Abstract base class for DG terms, provides alternative call_function and eval_real methods to accommodate
returning iels and vals.
call_function(out, fargs)
poly_space_base = 'legendre'
class sfepy.terms.terms_dg.DiffusionDGFluxTerm(name, arg_str, integral, region, **kwargs)
Basic DG diffusion flux term for scalar quantity.
Definition
∫︁ ∫︁
𝐷⟨∇𝑝⟩[𝑞] , 𝐷⟨∇𝑞⟩[𝑝]
𝜕𝑇𝐾 𝜕𝑇𝐾
where
∇𝜑𝑖𝑛 + ∇𝜑𝑜𝑢𝑡
⟨∇𝜑⟩ =
2
[𝜑] = 𝜑𝑖𝑛 − 𝜑𝑜𝑢𝑡
Math
The 𝑝𝑖𝑛 resp. 𝑝𝑜𝑢𝑡 is solution on the boundary of the element provided by element itself resp. its neighbour.
Call signature
Arguments 1
• material : 𝐷
• state : 𝑝
• virtual : 𝑞
Arguments 2
• material : 𝐷
• virtual : 𝑞
• state : 𝑝
integration = 'volume'
modes = ('avg_state', 'avg_virtual')
name = 'dw_dg_diffusion_flux'
class sfepy.terms.terms_dg.DiffusionInteriorPenaltyTerm(name, arg_str, integral, region, **kwargs)
Penalty term used to counteract discontinuity arising when modeling diffusion using Discontinuous Galerkin
schemes.
Definition
∫︁ 2
¯ 𝑤 𝑂𝑟𝑑 [𝑝][𝑞]
𝐷𝐶
𝜕𝑇𝐾 𝑑(𝜕𝑇𝐾 )
where
Math
the 𝑝𝑖𝑛 resp. 𝑝𝑜𝑢𝑡 is solution on the boundary of the element provided by element itself resp. its neighbour.
Call signature
Arguments
• material : 𝐷
• material : 𝐶𝑤
• state : 𝑝
• virtual : 𝑞
modes = ('weak',)
name = 'dw_dg_interior_penalty'
class sfepy.terms.terms_dg.NonlinearHyperbolicDGFluxTerm(name, arg_str, integral, region,
**kwargs)
Lax-Friedrichs flux term for nonlinear hyperpolic term of scalar quantity 𝑝 with the vector function
𝑓 given as a material parameter.
Definition
∫︁
𝑛 · 𝑓 * (𝑝𝑖𝑛 , 𝑝𝑜𝑢𝑡 )𝑞
𝜕𝑇𝐾
where
𝑓 (𝑝𝑖𝑛 ) + 𝑓 (𝑝𝑜𝑢𝑡 ) 𝑝𝑖𝑛 − 𝑝𝑜𝑢𝑡
𝑓 * (𝑝𝑖𝑛 , 𝑝𝑜𝑢𝑡 ) = + (1 − 𝛼)𝑛𝐶 ,
2 2
𝛼 ∈ [0, 1]; 𝛼 = 0 for upwind scheme, 𝛼 = 1 for central scheme, and
⃒ ⃒
⃒ 𝑑𝑓1 𝑑𝑓2 ⃒
𝐶 = max ⃒𝑛𝑥 ⃒ + 𝑛𝑦 + · · · ⃒⃒ =
𝑝∈[?,?] 𝑑𝑝 𝑑𝑝
⃒ ⃒
⃒ 𝑑𝑓 ⃒
max ⃒⃗𝑛 ·
⃒ (𝑝)⃒⃒
𝑝∈[?,?] 𝑑𝑝
the 𝑝𝑖𝑛 resp. 𝑝𝑜𝑢𝑡 is solution on the boundary of the element provided by element itself resp. its neighbor.
Call signature
Arguments 1
• material : 𝑓
𝑑𝑓
• material : 𝑑𝑝
• virtual : 𝑞
• state : 𝑝
Arguments 3
• material : 𝑓
𝑑𝑓
• material : 𝑑𝑝
• virtual : 𝑞
• state : 𝑝
• opt_material : 𝛼
alf = 0
arg_shapes = [{'opt_material': '.: 1', 'material_fun': '.: 1', 'material_fun_d':
'.: 1', 'virtual': (1, 'state'), 'state': 1}, {'opt_material': None}]
arg_types = ('opt_material', 'fun', 'fun_d', 'virtual', 'state')
integration = 'volume'
modes = ('weak',)
name = 'dw_dg_nonlinear_laxfrie_flux'
symbolic = {'expression': 'div(f(p))*w', 'map': {'f': 'function', 'p': 'state',
'v': 'virtual'}}
class sfepy.terms.terms_dg.NonlinearScalarDotGradTerm(name, arg_str, integral, region, **kwargs)
Product of virtual and divergence of vector function of state or volume dot product of vector function
of state and gradient of scalar virtual.
Definition
∫︁ ∫︁ ∫︁
𝑞 · ∇ · 𝑓 (𝑝) = 𝑞 · div𝑓 (𝑝) , 𝑓 (𝑝) · ∇𝑞
Ω Ω Ω
Call signature
Arguments 1
• function : 𝑓
• virtual : 𝑞
• state : 𝑝
Arguments 2
• function : 𝑓
• state : 𝑝
• virtual : 𝑞
name = 'dw_ns_dot_grad_s'
sfepy.terms.terms_diffusion module
Call signature
Arguments
• material : 𝑦
• virtual : 𝑞
• state : 𝑝
Arguments
• virtual : 𝑞
• state_v : 𝑢
• state_s : 𝑝
name = 'dw_convect_v_grad_s'
class sfepy.terms.terms_diffusion.DiffusionCoupling(name, arg_str, integral, region, **kwargs)
Diffusion copupling term with material parameter 𝐾𝑗 .
Definition
∫︁ ∫︁
𝑝𝐾𝑗 ∇𝑗 𝑞 , 𝑞𝐾𝑗 ∇𝑗 𝑝
Ω Ω
Call signature
Arguments
• material : 𝐾𝑗
• virtual : 𝑞
• state : 𝑝
Arguments
• material : 𝐾𝑗
• virtual : 𝑞
name = 'dw_diffusion_r'
class sfepy.terms.terms_diffusion.DiffusionTerm(name, arg_str, integral, region, **kwargs)
General diffusion term with permeability 𝐾𝑖𝑗 . Can be evaluated. Can use derivatives.
Definition
∫︁
𝐾𝑖𝑗 ∇𝑖 𝑞∇𝑗 𝑝
Ω
Call signature
Arguments
• material: 𝐾𝑖𝑗
• virtual/parameter_1: 𝑞
• state/parameter_2: 𝑝
Definition
∫︁
− 𝐾𝑖𝑗 ∇𝑗 𝑝
𝒟
Call signature
Arguments
• material : 𝐾𝑖𝑗
• parameter : 𝑝
integration = 'by_region'
name = 'ev_diffusion_velocity'
surface_integration = 'surface_extra'
class sfepy.terms.terms_diffusion.LaplaceTerm(name, arg_str, integral, region, **kwargs)
Laplace term with 𝑐 coefficient. Can be evaluated. Can use derivatives.
Definition
∫︁
𝑐∇𝑞 · ∇𝑝
Ω
Call signature
Arguments 1
• material: 𝑐
• virtual/parameter_1: 𝑞
• state/parameter_2: 𝑝
set_arg_types()
Arguments
• material: 𝐾𝑖𝑗
• parameter_q: 𝑞
• parameter_p: 𝑝
• parameter_mv: 𝒱
name = 'ev_sd_diffusion'
class sfepy.terms.terms_diffusion.SurfaceFluxOperatorTerm(name, arg_str, integral, region,
**kwargs)
Surface flux operator term.
Definition
∫︁
𝑞𝑛 · 𝐾 · ∇𝑝
Γ
Call signature
Arguments
• material : 𝐾
• virtual : 𝑞
• state : 𝑝
integration = 'surface_extra'
name = 'dw_surface_flux'
class sfepy.terms.terms_diffusion.SurfaceFluxTerm(name, arg_str, integral, region, **kwargs)
Surface flux term.
Supports ‘eval’, ‘el_eval’ and ‘el_avg’ evaluation modes.
Definition
∫︁
𝑛 · 𝐾𝑖𝑗 ∇𝑗 𝑝
Γ
Call signature
Arguments
• material: 𝐾
• parameter: 𝑝,
integration = 'surface_extra'
name = 'ev_surface_flux'
sfepy.terms.terms_dot module
Arguments
• material_1 : 𝛼
• material_2 : 𝑝outer
• virtual : 𝑞
• state : 𝑝
integration = 'surface'
mode = 'weak'
name = 'dw_bc_newton'
class sfepy.terms.terms_dot.DotProductTerm(name, arg_str, integral, region, **kwargs)
Volume and surface 𝐿2 () weighted dot product for both scalar and vector fields. If the region is a surface and
either virtual or state variable is a vector, the orientation of the normal vectors is outwards to the parent region
of the virtual variable. Can be evaluated. Can use derivatives.
Definition
∫︁ ∫︁
𝑞𝑝 , 𝑣·𝑢
𝒟
∫︁ ∫︁ 𝒟
𝑣 · 𝑛𝑝 , 𝑞𝑛 · 𝑢 ,
∫︁ ∫︁ Γ ∫︁Γ
𝑐𝑞𝑝 , 𝑐𝑣 · 𝑢 , 𝑣·𝑐·𝑢
𝒟 𝒟 𝒟
Call signature
Arguments
• material: 𝑐 or 𝑐 (optional)
• virtual/parameter_1: 𝑞 or 𝑣
• state/parameter_2: 𝑝 or 𝑢
integration = 'by_region'
modes = ('weak', 'eval')
name = 'dw_dot'
set_arg_types()
Call signature
Arguments
• ts : TimeStepper instance
• material_0 : 𝒢(0)
• material_1 : exp(−𝜆∆𝑡) (decay at 𝑡1 )
• virtual : 𝑞
• state : 𝑝
name = 'dw_volume_dot_w_scalar_eth'
class sfepy.terms.terms_dot.DotSProductVolumeOperatorWTHTerm(name, arg_str, integral, region,
**kwargs)
Fading memory volume 𝐿2 (Ω) weighted dot product for scalar fields. Can use derivatives.
Definition
∫︁ [︂∫︁ 𝑡 ]︂
𝒢(𝑡 − 𝜏 )𝑝(𝜏 ) d𝜏 𝑞
Ω 0
Call signature
Arguments
• ts : TimeStepper instance
• material : 𝒢(𝜏 )
• virtual : 𝑞
• state : 𝑝
name = 'dw_volume_dot_w_scalar_th'
class sfepy.terms.terms_dot.ScalarDotGradIScalarTerm(name, arg_str, integral, region, **kwargs)
Dot product of a scalar and the 𝑖-th component of gradient of a scalar. The index should be given as a ‘spe-
cial_constant’ material parameter.
Definition
∫︁
𝑍𝑖 = 𝑞∇𝑖 𝑝
Ω
Call signature
Arguments
• material : 𝑖
• virtual : 𝑞
• state : 𝑝
name = 'dw_s_dot_grad_i_s'
set_arg_types()
Arguments 1
• material : 𝑦
• virtual : 𝑞
• state : 𝑝
Arguments 2
• material : 𝑦
• state : 𝑝
• virtual : 𝑞
name = 'dw_s_dot_mgrad_s'
class sfepy.terms.terms_dot.VectorDotGradScalarTerm(name, arg_str, integral, region, **kwargs)
Volume dot product of a vector and a gradient of scalar. Can be evaluated.
Definition
∫︁ ∫︁
𝑣 · ∇𝑝 , 𝑢 · ∇𝑞
∫︁ Ω ∫︁ Ω
𝑐𝑣 · ∇𝑝 , 𝑐𝑢 · ∇𝑞
Ω
∫︁ ∫︁ Ω
𝑣 · (𝑐∇𝑝) , 𝑢 · (𝑐∇𝑞)
Ω Ω
Call signature
Arguments 1
• material: 𝑐 or 𝑐 (optional)
• virtual/parameter_v: 𝑣
• state/parameter_s: 𝑝
Arguments 2
• material : 𝑐 or 𝑐 (optional)
• state : 𝑢
• virtual : 𝑞
Call signature
Arguments 1
• material : 𝑐
• virtual/parameter_v: 𝑣
• state/parameter_s: 𝑝
Arguments 2
• material : 𝑐
• state : 𝑢
• virtual : 𝑞
sfepy.terms.terms_elastic module
∫︁
𝑒(𝑤)
𝒟
Call signature
ev_cauchy_strain (parameter)
Arguments
• parameter : 𝑤
integration = 'by_region'
name = 'ev_cauchy_strain'
surface_integration = 'surface_extra'
class sfepy.terms.terms_elastic.CauchyStressETHTerm(name, arg_str, integral, region, **kwargs)
Evaluate fading memory Cauchy stress tensor.
It is given in the usual vector form exploiting symmetry: in 3D it has 6 components with the indices ordered as
[11, 22, 33, 12, 13, 23], in 2D it has 3 components with the indices ordered as [11, 22, 12].
Assumes an exponential approximation of the convolution kernel resulting in much higher efficiency.
Supports ‘eval’, ‘el_avg’ and ‘qp’ evaluation modes.
Definition
∫︁ ∫︁ 𝑡
ℋ𝑖𝑗𝑘𝑙 (𝑡 − 𝜏 ) 𝑒𝑘𝑙 (𝑤(𝜏 )) d𝜏
Ω 0
Call signature
Arguments
• ts : TimeStepper instance
• material_0 : ℋ𝑖𝑗𝑘𝑙 (0)
• material_1 : exp(−𝜆∆𝑡) (decay at 𝑡1 )
• parameter : 𝑤
name = 'ev_cauchy_stress_eth'
class sfepy.terms.terms_elastic.CauchyStressTHTerm(name, arg_str, integral, region, **kwargs)
Evaluate fading memory Cauchy stress tensor.
It is given in the usual vector form exploiting symmetry: in 3D it has 6 components with the indices ordered as
[11, 22, 33, 12, 13, 23], in 2D it has 3 components with the indices ordered as [11, 22, 12].
Supports ‘eval’, ‘el_avg’ and ‘qp’ evaluation modes.
Definition
∫︁ ∫︁ 𝑡
ℋ𝑖𝑗𝑘𝑙 (𝑡 − 𝜏 ) 𝑒𝑘𝑙 (𝑤(𝜏 )) d𝜏
Ω 0
Call signature
Arguments
• ts : TimeStepper instance
• material : ℋ𝑖𝑗𝑘𝑙 (𝜏 )
• parameter : 𝑤
name = 'ev_cauchy_stress_th'
class sfepy.terms.terms_elastic.CauchyStressTerm(name, arg_str, integral, region, **kwargs)
Evaluate Cauchy stress tensor.
It is given in the usual vector form exploiting symmetry: in 3D it has 6 components with the indices ordered as
[11, 22, 33, 12, 13, 23], in 2D it has 3 components with the indices ordered as [11, 22, 12].
Supports ‘eval’, ‘el_avg’ and ‘qp’ evaluation modes.
Definition
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑘𝑙 (𝑤)
𝒟
Call signature
Arguments
• material : 𝐷𝑖𝑗𝑘𝑙
• parameter : 𝑤
integration = 'by_region'
name = 'ev_cauchy_stress'
surface_integration = 'surface_extra'
class sfepy.terms.terms_elastic.ElasticWaveCauchyTerm(name, arg_str, integral, region, **kwargs)
Elastic dispersion term involving the wave strain 𝑔𝑖𝑗 , 𝑔𝑖𝑗 (𝑢) = 12 (𝑢𝑖 𝜅𝑗 + 𝜅𝑖 𝑢𝑗 ), with the wave vector 𝜅 and the
elastic strain 𝑒𝑖𝑗 . 𝐷𝑖𝑗𝑘𝑙 is given in the usual matrix form exploiting symmetry: in 3D it is 6 × 6 with the indices
ordered as [11, 22, 33, 12, 13, 23], in 2D it is 3 × 3 with the indices ordered as [11, 22, 12].
Definition
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑔𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
∫︁Ω
𝐷𝑖𝑗𝑘𝑙 𝑔𝑖𝑗 (𝑢)𝑒𝑘𝑙 (𝑣)
Ω
Call signature
Arguments 1
• material_1 : 𝐷𝑖𝑗𝑘𝑙
• material_2 : 𝜅
• virtual : 𝑣
• state : 𝑢
Arguments 2
• material_1 : 𝐷𝑖𝑗𝑘𝑙
• material_2 : 𝜅
• state : 𝑢
• virtual : 𝑣
Arguments
• material_1 : 𝐷𝑖𝑗𝑘𝑙
• material_2 : 𝜅
• virtual : 𝑣
• state : 𝑢
name = 'dw_elastic_wave'
class sfepy.terms.terms_elastic.LinearElasticETHTerm(name, arg_str, integral, region, **kwargs)
This term has the same definition as dw_lin_elastic_th, but assumes an exponential approximation of the convo-
lution kernel resulting in much higher efficiency. Can use derivatives.
Definition
∫︁ [︂∫︁ 𝑡 ]︂
ℋ𝑖𝑗𝑘𝑙 (𝑡 − 𝜏 ) 𝑒𝑘𝑙 (𝑢(𝜏 )) d𝜏 𝑒𝑖𝑗 (𝑣)
Ω 0
Call signature
Arguments
• ts : TimeStepper instance
name = 'dw_lin_elastic_eth'
class sfepy.terms.terms_elastic.LinearElasticIsotropicTerm(name, arg_str, integral, region,
**kwargs)
Isotropic linear elasticity term.
Definition
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
Ω
with
𝐷𝑖𝑗𝑘𝑙 = 𝜇(𝛿𝑖𝑘 𝛿𝑗𝑙 + 𝛿𝑖𝑙 𝛿𝑗𝑘 ) + 𝜆 𝛿𝑖𝑗 𝛿𝑘𝑙
Call signature
Arguments
• material_1: 𝜆
• material_2: 𝜇
• virtual/parameter_1: 𝑣
• state/parameter_2: 𝑢
name = 'dw_lin_elastic_iso'
Call signature
Arguments
• ts : TimeStepper instance
• material : ℋ𝑖𝑗𝑘𝑙 (𝜏 )
• virtual : 𝑣
• state : 𝑢
name = 'dw_lin_elastic_th'
class sfepy.terms.terms_elastic.LinearElasticTerm(name, arg_str, integral, region, **kwargs)
General linear elasticity term, with 𝐷𝑖𝑗𝑘𝑙 given in the usual matrix form exploiting symmetry: in 3D it is 6 × 6
with the indices ordered as [11, 22, 33, 12, 13, 23], in 2D it is 3 × 3 with the indices ordered as [11, 22, 12]. Can
be evaluated. Can use derivatives.
Definition
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
Ω
Call signature
Arguments 1
• material : 𝐷𝑖𝑗𝑘𝑙
• virtual : 𝑣
• state : 𝑢
Arguments 2
• material : 𝐷𝑖𝑗𝑘𝑙
• parameter_1 : 𝑤
• parameter_2 : 𝑢
Arguments 1
• material : 𝜎𝑖𝑗
• virtual : 𝑣
Arguments 2
• material : 𝜎𝑖𝑗
• parameter : 𝑢
set_arg_types()
Arguments
• material_1 : 𝐷𝑖𝑗𝑘𝑙
• material_2 : 𝑑
• virtual : 𝑣
arg_shapes = {'material_1': 'S, S', 'material_2': 'D, 1', 'virtual': ('D', None)}
arg_types = ('material_1', 'material_2', 'virtual')
static function()
name = 'dw_lin_strain_fib'
class sfepy.terms.terms_elastic.NonsymElasticTerm(name, arg_str, integral, region, **kwargs)
Elasticity term with non-symmetric gradient. The indices of matrix 𝐷𝑖𝑗𝑘𝑙 are ordered as
[11, 12, 13, 21, 22, 23, 31, 32, 33] in 3D and as [11, 12, 21, 22] in 2D.
Definition
∫︁
𝐷∇𝑢 : ∇𝑣
Ω
Call signature
Arguments 1
• material : 𝐷
• virtual : 𝑣
• state : 𝑢
Arguments 2
• material : 𝐷
• parameter_1 : 𝑤
• parameter_2 : 𝑢
Arguments
• material : 𝐷𝑖𝑗𝑘𝑙
• parameter_w : 𝑤
• parameter_u : 𝑢
• parameter_mv : 𝒱
name = 'ev_sd_lin_elastic'
sfepy.terms.terms_electric module
Arguments
• material : 𝑐 (electric conductivity)
• virtual : 𝑠 (test function)
• parameter : 𝜑 (given electric potential)
name = 'dw_electric_source'
sfepy.terms.terms_fibres module
class sfepy.terms.terms_fibres.FibresActiveTLTerm(*args,{︁**kwargs) }︁
𝜖−𝜀
Hyperelastic active fibres term. Effective stress 𝑆𝑖𝑗 = 𝐴𝑓max exp −( 𝑠opt )2 𝑑𝑖 𝑑𝑗 , where 𝜖 = 𝐸𝑖𝑗 𝑑𝑖 𝑑𝑗 is the
Green strain 𝐸 projected to the fibre direction 𝑑.
Definition
∫︁
𝑆𝑖𝑗 (𝑢)𝛿𝐸𝑖𝑗 (𝑢; 𝑣)
Ω
Call signature
Arguments
• material_1 : 𝑓max
• material_2 : 𝜀opt
• material_3 : 𝑠
• material_4 : 𝑑
• material_5 : 𝐴
• virtual : 𝑣
• state : 𝑢
arg_shapes = {'material_1': '1, 1', 'material_2': '1, 1', 'material_3': '1, 1',
'material_4': 'D, 1', 'material_5': '1, 1', 'state': 'D', 'virtual': ('D',
'state')}
arg_types = ('material_1', 'material_2', 'material_3', 'material_4', 'material_5',
'virtual', 'state')
family_data_names = ['green_strain']
get_eval_shape(mat1, mat2, mat3, mat4, mat5, virtual, state, mode=None, term_mode=None,
diff_var=None, **kwargs)
get_fargs(mat1, mat2, mat3, mat4, mat5, virtual, state, mode=None, term_mode=None, diff_var=None,
**kwargs)
name = 'dw_tl_fib_a'
static stress_function(out, pars, green_strain, fibre_data=None)
sfepy.terms.terms_fibres.compute_fibre_strain(green_strain, omega)
Compute the Green strain projected to the fibre direction.
sfepy.terms.terms_fibres.create_omega(fdir)
Create the fibre direction tensor 𝜔𝑖𝑗 = 𝑑𝑖 𝑑𝑗 .
sfepy.terms.terms_hyperelastic_base module
ev_def_grad (parameter)
Arguments
• parameter : 𝑢
arg_types = ('parameter',)
static function(out, vec, vg, econn, term_mode, fmode)
name = 'ev_def_grad'
class sfepy.terms.terms_hyperelastic_base.HyperElasticBase(*args, **kwargs)
Base class for all hyperelastic terms in TL/UL formulation.
HyperElasticBase.__call__() computes element contributions given either stress (-> residual) or tangent modulus
(-> tangent sitffnes matrix), i.e. constitutive relation type (CRT) related data. The CRT data are computed in
subclasses implementing particular CRT (e.g. neo-Hookean material), in self.compute_crt_data().
Modes:
• 0: total formulation
• 1: updated formulation
Notes
class sfepy.terms.terms_hyperelastic_base.HyperElasticFamilyData(**kwargs)
Base class for hyperelastic family data.
The common (family) data are cached in the evaluate cache of state variable.
data_shapes = {'det_f': ('n_el', 'n_qp', 1, 1), 'green_strain': ('n_el', 'n_qp',
'sym', 1), 'in2_b': ('n_el', 'n_qp', 1, 1), 'in2_c': ('n_el', 'n_qp', 1, 1),
'inv_f': ('n_el', 'n_qp', 'dim', 'dim'), 'mtx_f': ('n_el', 'n_qp', 'dim', 'dim'),
'sym_b': ('n_el', 'n_qp', 'sym', 1), 'sym_c': ('n_el', 'n_qp', 'sym', 1),
'sym_inv_c': ('n_el', 'n_qp', 'sym', 1), 'tr_b': ('n_el', 'n_qp', 1, 1), 'tr_c':
('n_el', 'n_qp', 1, 1)}
init_data_struct(state_shape, name='family_data')
sfepy.terms.terms_hyperelastic_tl module
Arguments
• material : 𝐴
• virtual : 𝑣
• state : 𝑢
static tan_mod_function()
Arguments
• material : 𝐾
• virtual : 𝑣
• state : 𝑢
static tan_mod_function()
Arguments
• virtual : 𝑣
• state : 𝑢
• state_p : 𝑝
name = 'dw_tl_bulk_pressure'
static stress_function()
static tan_mod_u_function()
static weak_dp_function()
static weak_function()
Arguments
• material_1 : 𝑘
• material_2 : 𝑁𝑓
• virtual : 𝑞
• state : 𝑝
• parameter : 𝑢(𝑛−1)
name = 'dw_tl_diffusion'
class sfepy.terms.terms_hyperelastic_tl.GenYeohTLTerm(*args, **kwargs)
2
Hyperelastic generalized Yeoh term [1]. Effective stress 𝑆𝑖𝑗 = 2𝑝𝐾(𝐼1 − 3)𝑝−1 𝐽 − 3 (𝛿𝑖𝑗 − 31 𝐶𝑘𝑘 𝐶𝑖𝑗 −1 ).
Definition
∫︁
𝑆𝑖𝑗 (𝑢)𝛿𝐸𝑖𝑗 (𝑢; 𝑣)
Ω
Call signature
Arguments
• material : 𝑝, 𝐾
• virtual : 𝑣
• state : 𝑢
[1] Travis W. Hohenberger, Richard J. Windslow, Nicola M. Pugno, James J. C. Busfield. Aconstitutive Model
For Both Lowand High Strain Nonlinearities In Highly Filled Elastomers And Implementation With User-Defined
Material Subroutines In Abaqus. Rubber Chemistry And Technology, Vol. 92, No. 4, Pp. 653-686 (2019)
arg_shapes = {'material': '1, 2', 'state': 'D', 'virtual': ('D', 'state')}
family_data_names = ['det_f', 'tr_c', 'sym_inv_c']
geometries = ['3_4', '3_8']
name = 'dw_tl_he_genyeoh'
stress_function(out, mat, *fargs, **kwargs)
class sfepy.terms.terms_hyperelastic_tl.HyperElasticTLFamilyData(**kwargs)
Family data for TL formulation.
cache_name = 'tl_common'
data_names = ('mtx_f', 'det_f', 'sym_c', 'tr_c', 'in2_c', 'sym_inv_c',
'green_strain')
static family_function()
Arguments
• material : 𝜅
• virtual : 𝑣
• state : 𝑢
static tan_mod_function()
Arguments
• material : 𝜇
• virtual : 𝑣
• state : 𝑢
static tan_mod_function()
Definition
∫︁
𝑆𝑖𝑗 (𝑢)𝛿𝐸𝑖𝑗 (𝑢; 𝑣)
Ω
Call signature
Arguments
• material : 𝑝, 𝐾
• virtual : 𝑣
• state : 𝑢
[1] Ogden, R. W. Large deformation isotropic elasticity - on the correlation of theory and experiment for incom-
pressible rubberlike solids. Proceedings of the Royal Society A, Vol. 326, No. 1567, Pp. 565-584 (1972), DOI
10.1098/rspa.1972.0026.
[2] Steinmann, P., Hossain, M., Possart, G. Hyperelastic models for rubber-like materials: Consistent tangent
operators and suitability for Treloar’s data. Archive of Applied Mechanics, Vol. 82, No. 9, Pp. 1183-1217
(2012), DOI 10.1007/s00419-012-0610-z.
arg_shapes = {'material': '1, 2', 'state': 'D', 'virtual': ('D', 'state')}
family_data_names = ['det_f', 'sym_c', 'tr_c', 'sym_inv_c']
geometries = ['3_4', '3_8']
name = 'dw_tl_he_ogden'
stress_function(out, mat, *fargs, **kwargs)
Arguments
• material_1 : 𝑘
• material_2 : 𝑁𝑓
• parameter_1 : 𝑝
• parameter_2 : 𝑢(𝑛−1)
integration = 'surface_extra'
name = 'ev_tl_surface_flux'
class sfepy.terms.terms_hyperelastic_tl.SurfaceTractionTLTerm(*args, **kwargs)
Surface traction term in the total Lagrangian formulation, expressed using 𝜈, the outward unit normal vector
w.r.t. the undeformed surface, 𝐹 (𝑢), the deformation gradient, 𝐽 = det(𝐹 ), and 𝜎 a given traction, often equal
to a given pressure, i.e. 𝜎 = 𝜋𝐼.
Definition
∫︁
𝜈 · 𝐹 −1 · 𝜎 · 𝑣𝐽
Γ
Call signature
Arguments
• material : 𝜎
• virtual : 𝑣
• state : 𝑢
integration = 'surface_extra'
name = 'dw_tl_surface_traction'
class sfepy.terms.terms_hyperelastic_tl.VolumeSurfaceTLTerm(*args, **kwargs)
Volume of a 𝐷-dimensional domain, using a surface integral in the total Lagrangian formulation, expressed
using 𝜈, the outward unit normal vector w.r.t. the undeformed surface, 𝐹 (𝑢), the deformation gradient, and
𝐽 = det(𝐹 ). Uses the approximation of 𝑢 for the deformed surface coordinates 𝑥.
Definition
∫︁
1/𝐷 𝜈 · 𝐹 −1 · 𝑥𝐽
Γ
Call signature
ev_tl_volume_surface (parameter)
Arguments
• parameter : 𝑢
integration = 'surface_extra'
name = 'ev_tl_volume_surface'
class sfepy.terms.terms_hyperelastic_tl.VolumeTLTerm(*args, **kwargs)
Volume term (weak form) in the total Lagrangian formulation.
Definition
∫︀
Ω
𝑞𝐽(𝑢)
volume mode: vector for 𝐾 ← ℐℎ : 𝑇𝐾 ∫︀𝐽(𝑢)
∫︀
Call signature
Arguments
• virtual : 𝑞
• state : 𝑢
name = 'dw_tl_volume'
sfepy.terms.terms_hyperelastic_ul module
Arguments
• material : 𝐾
• virtual : 𝑣
• state : 𝑢
family_data_names = ['det_f']
name = 'dw_ul_bulk_penalty'
static stress_function()
static tan_mod_function()
Arguments
• virtual : 𝑣
• state : 𝑢
• state_p : 𝑝
static family_function()
name = 'dw_ul_bulk_pressure'
static stress_function()
static tan_mod_u_function()
static weak_dp_function()
static weak_function()
Arguments
• material : 𝛾
• virtual : 𝑞
• state : 𝑝
• parameter_u : (𝑢)
name = 'dw_ul_compressible'
class sfepy.terms.terms_hyperelastic_ul.HyperElasticULBase(*args, **kwargs)
Base class for all hyperelastic terms in UL formulation family.
The subclasses should have the following static method attributes: - stress_function() (the stress) -
tan_mod_function() (the tangent modulus)
get_family_data = HyperElasticULFamilyData
hyperelastic_mode = 1
static weak_function()
class sfepy.terms.terms_hyperelastic_ul.HyperElasticULFamilyData(**kwargs)
Family data for UL formulation.
cache_name = 'ul_common'
data_names = ('mtx_f', 'det_f', 'sym_b', 'tr_b', 'in2_b', 'green_strain')
static family_function()
Arguments
• material : 𝜅
• virtual : 𝑣
• state : 𝑢
static tan_mod_function()
Arguments
• material : 𝜇
• virtual : 𝑣
• state : 𝑢
static tan_mod_function()
Call signature
Arguments
• virtual : 𝑞
• state : 𝑢
name = 'dw_ul_volume'
sfepy.terms.terms_membrane module
Arguments
• material_a1 : 𝑎1
• material_a2 : 𝑎2
• material_h0 : ℎ0
• virtual : 𝑣
• state : 𝑢
Notes
integration = 'surface'
name = 'dw_tl_membrane'
static weak_function(out, a1, a2, h0, mtx_c, c33, mtx_b, mtx_t, bfg, geo, fmode)
sfepy.terms.terms_multilinear module
Arguments
• material : 𝐷𝑖𝑗𝑘𝑙
• parameter : 𝑤
name = 'de_cauchy_stress'
class sfepy.terms.terms_multilinear.EConvectTerm(*args, **kwargs)
Nonlinear convective term.
Definition
∫︁
((𝑢 · ∇)𝑢) · 𝑣
Ω
Call signature
Arguments
• virtual/parameter_1: 𝑣
• state/parameter_2: 𝑢
Arguments
• material: 𝐾𝑖𝑗
• virtual/parameter_1: 𝑞
• state/parameter_2: 𝑝
Arguments
• material: 𝜈 (viscosity, optional)
• virtual/parameter_1: 𝑣
• state/parameter_2: 𝑢
Arguments
• material: 𝑐 (optional)
• virtual/parameter: 𝑣
Arguments
• material: 𝑐 or 𝑐 (optional)
• virtual/parameter_1: 𝑞 or 𝑣
• state/parameter_2: 𝑝 or 𝑢
integration = 'by_region'
modes = ('weak', 'eval')
name = 'de_dot'
class sfepy.terms.terms_multilinear.EGradTerm(*args, **kwargs)
Weighted gradient term.
Definition
∫︁ ∫︁
∇𝑣 , 𝑐∇𝑣
Ω Ω
Call signature
Arguments
• material: 𝑐 (optional)
• virtual/parameter: 𝑣
name = 'de_grad'
class sfepy.terms.terms_multilinear.EIntegrateOperatorTerm(*args, **kwargs)
Volume and surface integral of a test function weighted by a scalar function 𝑐.
Definition
∫︁ ∫︁
𝑞 or 𝑐𝑞
𝒟 𝒟
Call signature
Arguments
• material : 𝑐 (optional)
• virtual : 𝑞
integration = 'by_region'
name = 'de_integrate'
class sfepy.terms.terms_multilinear.ELaplaceTerm(*args, **kwargs)
Laplace term with 𝑐 coefficient. Can be evaluated. Can use derivatives.
Definition
∫︁ ∫︁
∇𝑞 · ∇𝑝 , 𝑐∇𝑞 · ∇𝑝
Ω Ω
Call signature
Arguments
• material: 𝑐
• virtual/parameter_1: 𝑞
• state/parameter_2: 𝑝
Arguments
• virtual/parameter_1: 𝑣
• parameter/parameter_2: 𝑤
• state/parameter_3: 𝑢
Arguments
• material: 𝐷𝑖𝑗𝑘𝑙
• virtual/parameter_1: 𝑣
• state/parameter_2: 𝑢
Definition
∫︁ ∫︁
𝑣·𝑛, 𝑐𝑣 · 𝑛
Γ Γ
∫︁ ∫︁
𝑣 · (𝜎 𝑛) , 𝑣·𝑓
Γ Γ
Call signature
Arguments
• material: 𝑐, 𝑓 , 𝜎 or 𝜎
• virtual/parameter: 𝑣
integration = 'surface'
modes = ('weak', 'eval')
name = 'de_surface_ltr'
class sfepy.terms.terms_multilinear.ENonPenetrationPenaltyTerm(*args, **kwargs)
Non-penetration condition in the weak sense using a penalty.
Definition
∫︁
𝑐(𝑛 · 𝑣)(𝑛 · 𝑢)
Γ
Call signature
Arguments
• material : 𝑐
• virtual : 𝑣
• state : 𝑢
integration = 'surface'
name = 'de_non_penetration_p'
class sfepy.terms.terms_multilinear.ENonSymElasticTerm(*args, **kwargs)
Elasticity term with non-symmetric gradient. The indices of matrix 𝐷𝑖𝑗𝑘𝑙 are ordered as
[11, 12, 13, 21, 22, 23, 31, 32, 33] in 3D and as [11, 12, 21, 22] in 2D.
Definition
∫︁
𝐷∇𝑣 : ∇𝑢
Ω
Call signature
Arguments
• material: 𝐷
• virtual/parameter_1: 𝑣
• state/parameter_2: 𝑢
Arguments 1
• material : 𝑦
• virtual : 𝑞
• state : 𝑝
Arguments 2
• material : 𝑦
• state : 𝑝
• virtual : 𝑞
Arguments 1
• material: 𝑐 (optional)
• virtual/parameter_v: 𝑣
• state/parameter_s: 𝑝
Arguments 2
• material : 𝑐 (optional)
• state : 𝑢
• virtual : 𝑞
get_eval_shape(*args, **kwargs)
get_fargs(*args, **kwargs)
get_normals(arg)
get_operands(diff_var)
get_paths(expressions, operands)
layout_letters = 'cqgvd0'
make_function(texpr, *args, diff_var=None)
set_verbosity(verbosity=None)
verbosity = 0
class sfepy.terms.terms_multilinear.ExpressionArg(**kwargs)
get_bf(expr_cache)
add_constant(name, cname)
get_expressions(subscripts=None)
letters = 'defgh'
make_eye(size)
make_psg(dim)
make_pvg(dim)
print_shapes(subscripts, operands)
sfepy.terms.terms_multilinear.collect_modifiers(modifiers)
sfepy.terms.terms_multilinear.find_free_indices(indices)
sfepy.terms.terms_multilinear.get_loop_indices(subs, loop_index)
sfepy.terms.terms_multilinear.get_sizes(indices, operands)
sfepy.terms.terms_multilinear.parse_term_expression(texpr)
sfepy.terms.terms_multilinear.sym2nonsym(sym_obj, axes=[3])
sfepy.terms.terms_navier_stokes module
Arguments
• virtual : 𝑣
• state : 𝑢
name = 'dw_convect'
class sfepy.terms.terms_navier_stokes.DivGradTerm(name, arg_str, integral, region, **kwargs)
Diffusion term.
Definition
∫︁ ∫︁
𝜈 ∇𝑣 : ∇𝑢 , ∇𝑣 : ∇𝑢
Ω Ω
Call signature
Arguments
• material: 𝜈 (viscosity, optional)
• virtualparameter_1: 𝑣
• state/parameter_2: 𝑢
static function()
Definition
∫︁ ∫︁
∇ · 𝑣 or 𝑐∇ · 𝑣
Ω Ω
Call signature
Arguments
• material : 𝑐 (optional)
• virtual : 𝑣
name = 'dw_div'
class sfepy.terms.terms_navier_stokes.DivTerm(name, arg_str, integral, region, **kwargs)
Evaluate divergence of a vector field.
Supports ‘eval’, ‘el_avg’ and ‘qp’ evaluation modes.
Definition
∫︁ ∫︁
∇·𝑢, 𝑐∇ · 𝑢
𝒟 𝒟
Call signature
Arguments
• parameter : 𝑢
integration = 'by_region'
name = 'ev_div'
surface_integration = 'surface_extra'
Arguments
• material : 𝛾
• virtual : 𝑣
• state : 𝑢
name = 'dw_st_grad_div'
class sfepy.terms.terms_navier_stokes.GradTerm(name, arg_str, integral, region, **kwargs)
Evaluate gradient of a scalar or vector field.
Supports ‘eval’, ‘el_avg’ and ‘qp’ evaluation modes.
Definition
∫︁ ∫︁
∇𝑝 or ∇𝑢
𝒟
∫︁ ∫︁ 𝒟
𝑐∇𝑝 or 𝑐∇𝑢
𝒟 𝒟
Call signature
Arguments
• parameter : 𝑝 or 𝑢
integration = 'by_region'
name = 'ev_grad'
surface_integration = 'surface_extra'
class sfepy.terms.terms_navier_stokes.LinearConvect2Term(name, arg_str, integral, region,
**kwargs)
Linearized convective term with the convection velocity given as a material parameter.
Definition
∫︁
((𝑐 · ∇)𝑢) · 𝑣
Ω
((𝑐 · ∇)𝑢)|𝑞𝑝
Call signature
Arguments
• material : 𝑐
• virtual : 𝑣
• state : 𝑢
name = 'dw_lin_convect2'
class sfepy.terms.terms_navier_stokes.LinearConvectTerm(name, arg_str, integral, region, **kwargs)
Linearized convective term.
Definition
∫︁
((𝑤 · ∇)𝑢) · 𝑣
Ω
((𝑤 · ∇)𝑢)|𝑞𝑝
Call signature
Arguments
• virtual : 𝑣
• parameter : 𝑤
• state : 𝑢
name = 'dw_lin_convect'
class sfepy.terms.terms_navier_stokes.PSPGCStabilizationTerm(name, arg_str, integral, region,
**kwargs)
PSPG stabilization term, convective part ( 𝜏 is a local stabilization parameter).
Definition
∑︁ ∫︁
𝜏𝐾 ((𝑏 · ∇)𝑢) · ∇𝑞
𝐾∈ℐℎ 𝑇𝐾
Call signature
Arguments
• material : 𝜏𝐾
• virtual : 𝑞
• parameter : 𝑏
• state : 𝑢
arg_shapes = {'material': '1, 1', 'parameter': 'D', 'state': 'D', 'virtual': (1,
None)}
arg_types = ('material', 'virtual', 'parameter', 'state')
static function()
name = 'dw_st_pspg_c'
class sfepy.terms.terms_navier_stokes.PSPGPStabilizationTerm(name, arg_str, integral, region,
**kwargs)
PSPG stabilization term, pressure part ( 𝜏 is a local stabilization parameter), alias to Laplace term dw_laplace.
Definition
∑︁ ∫︁
𝜏𝐾 ∇𝑝 · ∇𝑞
𝐾∈ℐℎ 𝑇𝐾
Call signature
Arguments
• material : 𝜏𝐾
• virtual : 𝑞
• state : 𝑝
name = 'dw_st_pspg_p'
class sfepy.terms.terms_navier_stokes.SUPGCStabilizationTerm(name, arg_str, integral, region,
**kwargs)
SUPG stabilization term, convective part ( 𝛿 is a local stabilization parameter).
Definition
∑︁ ∫︁
𝛿𝐾 ((𝑏 · ∇)𝑢) · ((𝑏 · ∇)𝑣)
𝐾∈ℐℎ 𝑇𝐾
Call signature
Arguments
• material : 𝛿𝐾
• virtual : 𝑣
• parameter : 𝑏
• state : 𝑢
name = 'dw_st_supg_c'
class sfepy.terms.terms_navier_stokes.SUPGPStabilizationTerm(name, arg_str, integral, region,
**kwargs)
SUPG stabilization term, pressure part ( 𝛿 is a local stabilization parameter).
Definition
∑︁ ∫︁
𝛿𝐾 ∇𝑝 · ((𝑏 · ∇)𝑣)
𝐾∈ℐℎ 𝑇𝐾
Call signature
Arguments
• material : 𝛿𝐾
• virtual : 𝑣
• parameter : 𝑏
• state : 𝑝
name = 'dw_st_supg_p'
class sfepy.terms.terms_navier_stokes.StokesTerm(name, arg_str, integral, region, **kwargs)
Stokes problem coupling term. Corresponds to weak forms of gradient and divergence terms. Can be evaluated.
Definition
∫︁ ∫︁
𝑝∇·𝑣, 𝑞∇·𝑢
Ω
∫︁ ∫︁ Ω
or 𝑐𝑝∇·𝑣, 𝑐𝑞∇·𝑢
Ω Ω
Call signature
Arguments 1
• material: 𝑐 (optional)
• virtual/parameter_v: 𝑣
• state/parameter_s: 𝑝
Arguments 2
• material : 𝑐 (optional)
• state : 𝑢
• virtual : 𝑞
Arguments 1
• material : 𝜅
• virtual : 𝑣
• state : 𝑢
Arguments 2
• material : 𝜅
• state : 𝑢
• virtual : 𝑣
Arguments
• material : 𝜅
• virtual : 𝑣
• statee : 𝑢
name = 'dw_stokes_wave'
sfepy.terms.terms_piezo module
Arguments 1
• material: 𝑔𝑘𝑖𝑗
• virtual/parameter_v: 𝑣
• state/parameter_s: 𝑝
Arguments 2
• material : 𝑔𝑘𝑖𝑗
• state : 𝑢
• virtual : 𝑞
Arguments
• material : 𝑔𝑘𝑖𝑗
• parameter : 𝑢
name = 'ev_piezo_strain'
class sfepy.terms.terms_piezo.PiezoStressTerm(name, arg_str, integral, region, **kwargs)
Evaluate piezoelectric stress tensor.
It is given in the usual vector form exploiting symmetry: in 3D it has 6 components with the indices ordered as
[11, 22, 33, 12, 13, 23], in 2D it has 3 components with the indices ordered as [11, 22, 12].
Supports ‘eval’, ‘el_avg’ and ‘qp’ evaluation modes.
Definition
∫︁
𝑔𝑘𝑖𝑗 ∇𝑘 𝑝
Ω
Call signature
Arguments
• material : 𝑔𝑘𝑖𝑗
• parameter : 𝑝
name = 'ev_piezo_stress'
class sfepy.terms.terms_piezo.SDPiezoCouplingTerm(*args, **kwargs)
Sensitivity (shape derivative) of the piezoelectric coupling term.
Definition
∫︁
𝑔ˆ𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑢)∇𝑘 𝑝
Ω
𝜕𝒱𝑗 𝜕𝒱𝑘
𝑔ˆ𝑘𝑖𝑗 = 𝑔𝑘𝑖𝑗 (∇ · 𝒱) − 𝑔𝑘𝑖𝑙 − 𝑔𝑙𝑖𝑗
𝜕𝑥𝑙 𝜕𝑥𝑙
Call signature
Arguments
• material : 𝑔𝑘𝑖𝑗
• parameter_u : 𝑢
• parameter_p : 𝑝
• parameter_mv : 𝒱
name = 'ev_sd_piezo_coupling'
sfepy.terms.terms_point module
This term should be used with special care, as it bypasses the usual evaluation in quadrature points. It should
only be used with nodal FE basis. The number of rows of the load must be equal to the number of nodes in the
region and the number of columns equal to the field dimension.
Definition
𝑖
𝑓 𝑖 = 𝑓¯ ∀ FE node 𝑖 in a region
Call signature
Arguments
𝑖
• material : 𝑓¯
• virtual : 𝑣,
integration = 'point'
name = 'dw_point_load'
class sfepy.terms.terms_point.LinearPointSpringTerm(name, arg_str, integral, region, **kwargs)
Linear springs constraining movement of FE nodes in a region; to use as a relaxed Dirichlet boundary conditions.
Definition
𝑓 𝑖 = −𝑘𝑢𝑖 ∀ FE node 𝑖 in a region
Call signature
Arguments
• material : 𝑘
• virtual : 𝑣
• state : 𝑢
integration = 'point'
name = 'dw_point_lspring'
sfepy.terms.terms_sensitivity module
Arguments
• material: 𝐾𝑖𝑗
• virtual/parameter_1: 𝑞
• state/parameter_2: 𝑝
• parameter_mv: 𝒱
Definition
∫︁ ∫︁
ˆ
𝐼∇𝑣 : ∇𝑢 , ˆ
𝜈 𝐼∇𝑣 : ∇𝑢
Ω Ω
𝜕𝒱𝑙 𝜕𝒱𝑘
𝐼ˆ𝑖𝑗𝑘𝑙 = 𝛿𝑖𝑘 𝛿𝑗𝑙 ∇ · 𝒱 − 𝛿𝑖𝑘 𝛿𝑗𝑠 − 𝛿𝑖𝑠 𝛿𝑗𝑙
𝜕𝑥𝑠 𝜕𝑥𝑠
Call signature
Arguments
• material: 𝜈 (viscosity, optional)
• virtual/parameter_1: 𝑣
• state/parameter_2: 𝑢
• parameter_mv: 𝒱
Arguments
• material: 𝑐 or 𝑀 (optional)
• virtual/parameter_1: 𝑞 or 𝑣
• state/parameter_2: 𝑝 or 𝑢
• parameter_mv : 𝒱
Arguments 1
• material : 𝐷
• virtual/parameter_v : 𝑣
• state/parameter_s : 𝑢
• parameter_mv : 𝒱
∫︁
[︀(︀ )︀ ]︀
𝑣· 𝜎ˆ∇·𝒱 −𝜎
ˆ ∇𝒱 𝑛
Γ
ˆ =𝐼 ,𝜎
𝜎 ˆ = 𝑐 𝐼 or 𝜎
ˆ=𝜎
Call signature
Arguments
• material: 𝑐, 𝜎, 𝜎
• virtual/parameter: 𝑣
• parameter_mv: 𝒱
integration = 'surface'
modes = ('weak', 'eval')
name = 'de_sd_surface_ltr'
class sfepy.terms.terms_sensitivity.ESDPiezoCouplingTerm(*args, **kwargs)
Sensitivity (shape derivative) of the piezoelectric coupling term.
Definition
∫︁ ∫︁
𝑔ˆ𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑣)∇𝑘 𝑝 , 𝑔ˆ𝑘𝑖𝑗 𝑒𝑖𝑗 (𝑢)∇𝑘 𝑞
Ω Ω
𝜕𝒱𝑗 𝜕𝒱𝑘
𝑔ˆ𝑘𝑖𝑗 = 𝑔𝑘𝑖𝑗 (∇ · 𝒱) − 𝑔𝑘𝑖𝑙 − 𝑔𝑙𝑖𝑗
𝜕𝑥𝑙 𝜕𝑥𝑙
Call signature
Arguments 1
• material : 𝑔𝑘𝑖𝑗
• virtual/parameter_v : 𝑣
• state/parameter_s : 𝑝
• parameter_mv : 𝒱
Arguments 2
• material : 𝑔𝑘𝑖𝑗
• state : 𝑢
• virtual : 𝑞
• parameter_mv : 𝒱
Arguments 1
• virtual/parameter_v: 𝑣
• state/parameter_s: 𝑝
• parameter_mv: 𝒱
Arguments 2
• state : 𝑢
• virtual : 𝑞
• parameter_mv: 𝒱
sfepy.terms.terms_shells module
where
[︂ ]︂
H
Ĥ = and H = [e′1 e′2 e′3 ]
H
where 𝜁˜ = (𝑡/2)𝜁. The local nodal axes ẽ𝑖 are constructed in order to describe the behavior of warped (non-
planar) elements adequately.
The term employs three shell element enhancements:
• DSG method
• EAS method
• drilling rotations lock (parameter 𝜒 - a good value is about 10−7 )
For detailed theoretical information see the references.
High-Performance 4-Node Shell Element with Piezoelectric Coupling Mechanics of Advanced Materials and
Structures Vol. 13, Iss. 5, doi:10.1080/15376490600777657
High-performance four-node shell element with piezoelectric coupling for the analysis of smart laminated struc-
tures. Int. J. Numer. Meth. Engng., 70: 934–961. doi:10.1002/nme.1909
Definition
∫︁
𝐷𝑖𝑗𝑘𝑙 𝑒𝑖𝑗 (𝑣)𝑒𝑘𝑙 (𝑢)
Ω
Call signature
Arguments
• material_d : 𝐷
• material_drill : 𝜒
• virtual : 𝑣
• state : 𝑢
geometries = ['3_2_4']
get_fargs(mtx_d, drill, virtual, state, mode=None, term_mode=None, diff_var=None, **kwargs)
get_physical_qps()
Get physical quadrature points corresponding to the term region and integral.
integration = 'custom'
name = 'dw_shell10x'
poly_space_base = 'shell10x'
set_integral(integral)
Set the term integral.
sfepy.terms.terms_surface module
𝑓 (𝑑) = 0 for 𝑑 ≤ 0 ,
𝑓 (𝑑) = 𝑘𝑑 for 𝑑 > 0 .
• If 𝑓0 > 0:
2𝑟0
𝑓 (𝑑) = 0 for 𝑑 ≤ − ,
𝑘
𝑘2 2 2𝑟0
𝑓 (𝑑) = 𝑑 + 𝑘𝑑 + 𝑟0 for − <𝑑≤0,
4𝑟0 𝑘
𝑓 (𝑑) = 𝑘𝑑 + 𝑓0 for 𝑑 > 0 .
In this case the dependence 𝑓 (𝑑) is smooth, and a (small) force is applied even for (small) negative pene-
trations: − 2𝑟𝑘0 < 𝑑 ≤ 0.
Definition
∫︁
𝑣 · 𝑓 (𝑑(𝑢))𝑛
Γ
Call signature
Arguments
• material_f : [𝑘, 𝑓0 ]
• material_n : 𝑛 (special)
• material_a : 𝐴 (special)
• material_b : {𝐵 𝑖 }, 𝑖 = 1, . . . , 𝑁𝐵 (special)
• virtual : 𝑣
• state : 𝑢
integration = 'surface'
name = 'dw_contact_plane'
static smooth_f(d, k, f0, a, eps, diff )
𝑓 (𝑑) = 0 for 𝑑 ≤ 0 ,
𝑓 (𝑑) = 𝑘𝑑 for 𝑑 > 0 .
• If 𝑓0 > 0:
2𝑟0
𝑓 (𝑑) = 0 for 𝑑 ≤ − ,
𝑘
𝑘2 2 2𝑟0
𝑓 (𝑑) = 𝑑 + 𝑘𝑑 + 𝑟0 for − <𝑑≤0,
4𝑟0 𝑘
𝑓 (𝑑) = 𝑘𝑑 + 𝑓0 for 𝑑 > 0 .
In this case the dependence 𝑓 (𝑑) is smooth, and a (small) force is applied even for (small) negative pene-
trations: − 2𝑟𝑘0 < 𝑑 ≤ 0.
Definition
∫︁
𝑣 · 𝑓 (𝑑(𝑢))𝑛(𝑢)
Γ
Call signature
Arguments
• material_f : [𝑘, 𝑓0 ]
• material_c : 𝐶 (special)
• material_r : 𝑅 (special)
• virtual : 𝑣
• state : 𝑢
arg_shapes = {'material_c': '.: D', 'material_f': '1, 2', 'material_r': '.: 1',
'state': 'D', 'virtual': ('D', 'state')}
arg_types = ('material_f', 'material_c', 'material_r', 'virtual', 'state')
integration = 'surface'
name = 'dw_contact_sphere'
class sfepy.terms.terms_surface.LinearTractionTerm(name, arg_str, integral, region, **kwargs)
Linear traction forces, where, depending on dimension of ‘material’ argument, 𝜎 · 𝑛 is 𝑝¯𝐼 · 𝑛 for a given scalar
pressure, 𝑓 for a traction vector, and itself for a stress tensor.
The material parameter can have one of the following shapes: 1 or (1, 1), (D, 1), (S, 1) in all modes, or (D, D)
in the eval mode only. The symmetric tensor storage (S, 1) is as follows: in 3D S = 6 and the indices ordered as
[11, 22, 33, 12, 13, 23], in 2D S = 3 and the indices ordered as [11, 22, 12].
Definition
∫︁ ∫︁
𝑣 · 𝜎 · 𝑛, 𝑣 · 𝑛,
Γ Γ
Call signature
Arguments
• material : 𝜎
• virtual : 𝑣
integration = 'surface'
modes = ('weak', 'eval')
name = 'dw_surface_ltr'
set_arg_types()
Definition
∫︁ ∫︁
𝑣 · (𝜎 𝑛), 𝑣 · 𝑛,
Γ Γ
Call signature
Arguments
• material : 𝜎
• parameter : 𝑣
integration = 'surface'
name = 'ev_sd_surface_ltr'
set_arg_types()
Arguments
• parameter : 𝑝
• parameter_mv : 𝒱
integration = 'surface'
name = 'ev_sd_surface_integrate'
class sfepy.terms.terms_surface.SufaceNormalDotTerm(name, arg_str, integral, region, **kwargs)
“Scalar traction” term, (weak form).
Definition
∫︁
𝑞𝑐 · 𝑛
Γ
Call signature
Arguments
• material : 𝑐
• virtual : 𝑞
integration = 'surface'
modes = ('weak', 'eval')
name = 'dw_surface_ndot'
set_arg_types()
Arguments
• material : 𝑐
• virtual : 𝑞
• state_1 : 𝑝1
• state_2 : 𝑝2
integration = 'surface'
name = 'dw_jump'
sfepy.terms.terms_th module
sfepy.terms.terms_volume module
Arguments
• material : 𝑓 or 𝑓
• virtual : 𝑣 or 𝑞
arg_shapes = [{'material': 'D, 1', 'virtual': ('D', None)}, {'material': '1, 1',
'virtual': (1, None)}]
arg_types = ('material', 'virtual')
static function()
name = 'dw_volume_lvf'
sfepy.terms.utils module
sfepy.terms.utils.check_finiteness(data, info)
sfepy.terms.utils.get_range_indices(num)
Return indices and slices in given range.
Returns
indx [list of tuples] The list of (ii, slice(ii, ii + 1)) of the indices. The first item is the index itself,
the second item is a convenience slice to index components of material parameters.
sfepy.terms.extmods.terms module
sfepy.terms.extmods.terms.d_biot_div()
sfepy.terms.extmods.terms.d_diffusion()
sfepy.terms.extmods.terms.d_laplace()
sfepy.terms.extmods.terms.d_lin_elastic()
sfepy.terms.extmods.terms.d_of_nsMinGrad()
sfepy.terms.extmods.terms.d_of_nsSurfMinDPress()
sfepy.terms.extmods.terms.d_piezo_coupling()
sfepy.terms.extmods.terms.d_sd_convect()
sfepy.terms.extmods.terms.d_sd_diffusion()
sfepy.terms.extmods.terms.d_sd_div()
sfepy.terms.extmods.terms.d_sd_div_grad()
sfepy.terms.extmods.terms.d_sd_lin_elastic()
sfepy.terms.extmods.terms.d_sd_st_grad_div()
sfepy.terms.extmods.terms.d_sd_st_pspg_c()
sfepy.terms.extmods.terms.d_sd_st_pspg_p()
sfepy.terms.extmods.terms.d_sd_st_supg_c()
sfepy.terms.extmods.terms.d_sd_volume_dot()
sfepy.terms.extmods.terms.d_surface_flux()
sfepy.terms.extmods.terms.d_tl_surface_flux()
sfepy.terms.extmods.terms.d_tl_volume_surface()
sfepy.terms.extmods.terms.d_volume_surface()
sfepy.terms.extmods.terms.de_cauchy_strain()
sfepy.terms.extmods.terms.de_cauchy_stress()
sfepy.terms.extmods.terms.de_he_rtm()
sfepy.terms.extmods.terms.di_surface_moment()
sfepy.terms.extmods.terms.dq_cauchy_strain()
sfepy.terms.extmods.terms.dq_def_grad()
sfepy.terms.extmods.terms.dq_div_vector()
sfepy.terms.extmods.terms.dq_finite_strain_tl()
sfepy.terms.extmods.terms.dq_finite_strain_ul()
sfepy.terms.extmods.terms.dq_grad()
sfepy.terms.extmods.terms.dq_state_in_qp()
sfepy.terms.extmods.terms.dq_tl_finite_strain_surface()
sfepy.terms.extmods.terms.dq_tl_he_stress_bulk()
sfepy.terms.extmods.terms.dq_tl_he_stress_bulk_active()
sfepy.terms.extmods.terms.dq_tl_he_stress_mooney_rivlin()
sfepy.terms.extmods.terms.dq_tl_he_stress_neohook()
sfepy.terms.extmods.terms.dq_tl_he_tan_mod_bulk()
sfepy.terms.extmods.terms.dq_tl_he_tan_mod_bulk_active()
sfepy.terms.extmods.terms.dq_tl_he_tan_mod_mooney_rivlin()
sfepy.terms.extmods.terms.dq_tl_he_tan_mod_neohook()
sfepy.terms.extmods.terms.dq_tl_stress_bulk_pressure()
sfepy.terms.extmods.terms.dq_tl_tan_mod_bulk_pressure_u()
sfepy.terms.extmods.terms.dq_ul_he_stress_bulk()
sfepy.terms.extmods.terms.dq_ul_he_stress_mooney_rivlin()
sfepy.terms.extmods.terms.dq_ul_he_stress_neohook()
sfepy.terms.extmods.terms.dq_ul_he_tan_mod_bulk()
sfepy.terms.extmods.terms.dq_ul_he_tan_mod_mooney_rivlin()
sfepy.terms.extmods.terms.dq_ul_he_tan_mod_neohook()
sfepy.terms.extmods.terms.dq_ul_stress_bulk_pressure()
sfepy.terms.extmods.terms.dq_ul_tan_mod_bulk_pressure_u()
sfepy.terms.extmods.terms.dw_adj_convect1()
sfepy.terms.extmods.terms.dw_adj_convect2()
sfepy.terms.extmods.terms.dw_biot_div()
sfepy.terms.extmods.terms.dw_biot_grad()
sfepy.terms.extmods.terms.dw_convect_v_grad_s()
sfepy.terms.extmods.terms.dw_diffusion()
sfepy.terms.extmods.terms.dw_diffusion_r()
sfepy.terms.extmods.terms.dw_div()
sfepy.terms.extmods.terms.dw_electric_source()
sfepy.terms.extmods.terms.dw_grad()
sfepy.terms.extmods.terms.dw_he_rtm()
sfepy.terms.extmods.terms.dw_laplace()
sfepy.terms.extmods.terms.dw_lin_convect()
sfepy.terms.extmods.terms.dw_lin_elastic()
sfepy.terms.extmods.terms.dw_lin_prestress()
sfepy.terms.extmods.terms.dw_lin_strain_fib()
sfepy.terms.extmods.terms.dw_nonsym_elastic()
sfepy.terms.extmods.terms.dw_piezo_coupling()
sfepy.terms.extmods.terms.dw_st_adj1_supg_p()
sfepy.terms.extmods.terms.dw_st_adj2_supg_p()
sfepy.terms.extmods.terms.dw_st_adj_supg_c()
sfepy.terms.extmods.terms.dw_st_grad_div()
sfepy.terms.extmods.terms.dw_st_pspg_c()
sfepy.terms.extmods.terms.dw_st_supg_c()
sfepy.terms.extmods.terms.dw_st_supg_p()
sfepy.terms.extmods.terms.dw_surface_flux()
sfepy.terms.extmods.terms.dw_surface_ltr()
sfepy.terms.extmods.terms.dw_surface_s_v_dot_n()
sfepy.terms.extmods.terms.dw_surface_v_dot_n_s()
sfepy.terms.extmods.terms.dw_tl_diffusion()
sfepy.terms.extmods.terms.dw_tl_surface_traction()
sfepy.terms.extmods.terms.dw_tl_volume()
sfepy.terms.extmods.terms.dw_ul_volume()
sfepy.terms.extmods.terms.dw_v_dot_grad_s_sw()
sfepy.terms.extmods.terms.dw_v_dot_grad_s_vw()
sfepy.terms.extmods.terms.dw_volume_dot_scalar()
sfepy.terms.extmods.terms.dw_volume_dot_vector()
sfepy.terms.extmods.terms.dw_volume_lvf()
sfepy.terms.extmods.terms.errclear()
sfepy.terms.extmods.terms.he_eval_from_mtx()
sfepy.terms.extmods.terms.he_residuum_from_mtx()
sfepy.terms.extmods.terms.mulAB_integrate()
sfepy.terms.extmods.terms.sym2nonsym()
sfepy.terms.extmods.terms.term_ns_asm_convect()
sfepy.terms.extmods.terms.term_ns_asm_div_grad()
Tests
sfepy.tests.conftest module
sfepy.tests.conftest.output_dir(request, tmpdir_factory)
Output directory for tests.
sfepy.tests.conftest.pytest_addoption(parser)
sfepy.tests.conftest.pytest_configure(config)
sfepy.tests.test_assembling module
sfepy.tests.test_assembling.data()
sfepy.tests.test_assembling.test_assemble_matrix(data)
sfepy.tests.test_assembling.test_assemble_matrix_complex(data)
sfepy.tests.test_assembling.test_assemble_vector(data)
sfepy.tests.test_assembling.test_assemble_vector_complex(data)
sfepy.tests.test_base module
sfepy.tests.test_base.test_container_add()
sfepy.tests.test_base.test_parse_conf()
sfepy.tests.test_base.test_resolve_deps()
sfepy.tests.test_base.test_struct_add()
sfepy.tests.test_base.test_struct_i_add()
sfepy.tests.test_base.test_verbose_output()
sfepy.tests.test_cmesh module
sfepy.tests.test_cmesh.filename_meshes()
sfepy.tests.test_cmesh.test_cmesh_counts(filename_meshes)
sfepy.tests.test_cmesh.test_entity_volumes()
sfepy.tests.test_conditions module
sfepy.tests.test_conditions.data()
sfepy.tests.test_conditions.init_vec(variables)
sfepy.tests.test_conditions.test_ebcs(data)
sfepy.tests.test_conditions.test_epbcs(data)
sfepy.tests.test_conditions.test_ics(data)
sfepy.tests.test_conditions.test_save_ebc(data, output_dir)
sfepy.tests.test_declarative_examples module
sfepy.tests.test_declarative_examples.inedir(filename)
sfepy.tests.test_declarative_examples.test_examples(ex_filename, output_dir)
sfepy.tests.test_declarative_examples.test_examples_dg(ex_filename, output_dir)
sfepy.tests.test_dg_field module
class sfepy.tests.test_dg_field.TestDGField
test_create_output1D()
test_create_output2D()
test_get_bc_facet_values_1D()
test_get_bc_facet_values_2D()
test_get_bc_facet_values_2D_const()
test_get_facet_idx1D()
test_get_facet_idx2D()
test_get_facet_neighbor_idx_1d()
test_get_facet_neighbor_idx_2d()
test_set_dofs_1D()
test_set_dofs_2D()
sfepy.tests.test_dg_field.prepare_dgfield(approx_order, mesh)
sfepy.tests.test_dg_field.prepare_dgfield_1D(approx_order)
sfepy.tests.test_dg_field.prepare_field_2D(approx_order)
sfepy.tests.test_dg_terms_calls module
sfepy.tests.test_domain module
sfepy.tests.test_domain.domain()
sfepy.tests.test_domain.test_facets(domain)
sfepy.tests.test_domain.test_refine_2_3(output_dir)
sfepy.tests.test_domain.test_refine_2_4(output_dir)
sfepy.tests.test_domain.test_refine_3_4(output_dir)
sfepy.tests.test_domain.test_refine_3_8(output_dir)
sfepy.tests.test_domain.test_refine_hexa(output_dir)
sfepy.tests.test_domain.test_refine_tetra(domain, output_dir)
sfepy.tests.test_eigenvalue_solvers module
sfepy.tests.test_eigenvalue_solvers.data()
sfepy.tests.test_eigenvalue_solvers.mesh_hook(mesh, mode)
Generate the block mesh.
sfepy.tests.test_eigenvalue_solvers.test_eigenvalue_solvers(data)
sfepy.tests.test_elasticity_small_strain module
sfepy.tests.test_elasticity_small_strain.get_pars(dim, full=False)
sfepy.tests.test_elasticity_small_strain.solutions(output_dir)
sfepy.tests.test_elasticity_small_strain.test_converged(solutions)
sfepy.tests.test_elasticity_small_strain.test_linear_terms(solutions)
sfepy.tests.test_fem module
sfepy.tests.test_fem.gels()
sfepy.tests.test_fem.test_base_functions_delta(gels)
Test 𝛿 property of base functions evaluated in the reference element nodes.
sfepy.tests.test_fem.test_base_functions_values(gels)
Compare base function values and their gradients with correct data. Also test that sum of values over all element
nodes gives one.
sfepy.tests.test_functions module
sfepy.tests.test_functions.get_circle(coors, domain=None)
sfepy.tests.test_functions.problem()
sfepy.tests.test_functions.test_ebc_functions(problem, output_dir)
sfepy.tests.test_functions.test_material_functions(problem)
sfepy.tests.test_functions.test_region_functions(problem, output_dir)
sfepy.tests.test_high_level module
sfepy.tests.test_high_level.data()
sfepy.tests.test_high_level.test_solving(data, output_dir)
sfepy.tests.test_high_level.test_term_arithmetics(data)
sfepy.tests.test_high_level.test_term_evaluation(data)
sfepy.tests.test_high_level.test_variables(data)
sfepy.tests.test_homogenization_engine module
sfepy.tests.test_homogenization_engine.test_chunk_micro()
sfepy.tests.test_homogenization_engine.test_dependencies()
sfepy.tests.test_homogenization_perfusion module
sfepy.tests.test_homogenization_perfusion.test_solution(output_dir)
sfepy.tests.test_hyperelastic_tlul module
sfepy.tests.test_hyperelastic_tlul.test_solution(output_dir)
sfepy.tests.test_io module
sfepy.tests.test_io.test_recursive_dict_hdf5(output_dir)
sfepy.tests.test_io.test_sparse_matrix_hdf5(output_dir)
sfepy.tests.test_laplace_unit_disk module
sfepy.tests.test_laplace_unit_disk.data()
sfepy.tests.test_laplace_unit_disk.test_boundary_fluxes(data)
sfepy.tests.test_laplace_unit_square module
sfepy.tests.test_laplace_unit_square.data()
sfepy.tests.test_laplace_unit_square.test_boundary_fluxes(data, output_dir)
sfepy.tests.test_laplace_unit_square.test_solution(data)
sfepy.tests.test_lcbcs module
sfepy.tests.test_lcbcs.test_elasticity_rigid(mesh_filename, output_dir)
sfepy.tests.test_lcbcs.test_laplace_shifted_periodic(output_dir)
sfepy.tests.test_lcbcs.test_stokes_slip_bc(output_dir)
sfepy.tests.test_linalg module
sfepy.tests.test_linalg.test_assemble1d()
sfepy.tests.test_linalg.test_geometry()
sfepy.tests.test_linalg.test_tensors()
sfepy.tests.test_linalg.test_unique_rows()
sfepy.tests.test_linear_solvers module
class sfepy.tests.test_linear_solvers.DiagPC
Diagonal (Jacobi) preconditioner.
Equivalent to setting ‘precond’ : ‘jacobi’.
apply(pc, x, y)
setUp(pc)
sfepy.tests.test_linear_solvers.problem()
sfepy.tests.test_linear_solvers.setup_petsc_precond(mtx, problem)
sfepy.tests.test_linear_solvers.test_ls_reuse(problem)
sfepy.tests.test_linear_solvers.test_solvers(problem, output_dir)
sfepy.tests.test_linearization module
sfepy.tests.test_linearization.test_linearization(output_dir)
sfepy.tests.test_log module
sfepy.tests.test_log.log(log_filename)
sfepy.tests.test_log.log_filename(output_dir)
sfepy.tests.test_matcoefs module
sfepy.tests.test_matcoefs.test_conversion_functions()
sfepy.tests.test_matcoefs.test_elastic_constants()
sfepy.tests.test_matcoefs.test_stiffness_tensors()
sfepy.tests.test_matcoefs.test_wave_speeds()
sfepy.tests.test_mesh_expand module
sfepy.tests.test_mesh_expand.test_mesh_expand()
sfepy.tests.test_mesh_generators module
sfepy.tests.test_mesh_generators.test_gen_block_mesh(output_dir)
sfepy.tests.test_mesh_generators.test_gen_cylinder_mesh(output_dir)
sfepy.tests.test_mesh_generators.test_gen_extended_block_mesh(output_dir)
sfepy.tests.test_mesh_generators.test_gen_mesh_from_geom(output_dir)
sfepy.tests.test_mesh_generators.test_gen_mesh_from_voxels(output_dir)
sfepy.tests.test_mesh_generators.test_gen_tiled_mesh(output_dir)
sfepy.tests.test_mesh_interp module
sfepy.tests.test_mesh_interp.in_dir(adir)
sfepy.tests.test_mesh_interp.prepare_variable(filename, n_components)
sfepy.tests.test_mesh_interp.test_evaluate_at()
sfepy.tests.test_mesh_interp.test_field_gradient()
sfepy.tests.test_mesh_interp.test_interpolation(output_dir)
sfepy.tests.test_mesh_interp.test_interpolation_two_meshes(output_dir)
sfepy.tests.test_mesh_interp.test_invariance()
sfepy.tests.test_mesh_interp.test_invariance_qp()
sfepy.tests.test_mesh_smoothing module
sfepy.tests.test_mesh_smoothing.get_volume(el, nd)
sfepy.tests.test_mesh_smoothing.test_mesh_smoothing(output_dir)
sfepy.tests.test_meshio module
sfepy.tests.test_meshio.mesh_hook(mesh, mode)
Define a mesh programmatically.
sfepy.tests.test_meshio.test_compare_same_meshes()
Compare same meshes in various formats.
sfepy.tests.test_meshio.test_hdf5_meshio()
sfepy.tests.test_meshio.test_read_dimension()
sfepy.tests.test_meshio.test_read_meshes()
Try to read all listed meshes.
sfepy.tests.test_meshio.test_write_read_meshes(output_dir)
Try to write and then read all supported formats.
sfepy.tests.test_msm_laplace module
sfepy.tests.test_msm_laplace.problem()
sfepy.tests.test_msm_laplace.test_msm_laplace(problem, output_dir)
sfepy.tests.test_msm_symbolic module
sfepy.tests.test_msm_symbolic.problem()
sfepy.tests.test_msm_symbolic.test_msm_symbolic_diffusion(problem, output_dir)
sfepy.tests.test_msm_symbolic.test_msm_symbolic_laplace(problem, output_dir)
sfepy.tests.test_normals module
sfepy.tests.test_normals.test_normals()
Check orientations of surface normals on the reference elements.
sfepy.tests.test_parsing module
sfepy.tests.test_parsing.test_parse_equations()
sfepy.tests.test_parsing.test_parse_regions()
sfepy.tests.test_poly_spaces module
Test continuity of polynomial basis and its gradients along an edge on 𝑦 line (2D) or on a face in 𝑥-𝑦 plane (3D) between
two elements aligned with the coordinate system, stack one on top of the other. The evaluation occurs in several points
shifted by a very small amount from the boundary between the elements into the top and the bottom element.
For H1 space, the basis should be continuous. The components of its gradient parallel to the edge/face should be
continuous as well, while the perpendicular component should have the same absolute value, but different sign in the
top and the bottom element.
All connectivity permutations of the two elements are tested.
The serendipity basis implementation is a pure python proof-of-concept. Its order in continuity tests is limited to 2 on
3_8 elements to decrease the tests run time.
sfepy.tests.test_poly_spaces.gels()
sfepy.tests.test_poly_spaces.test_continuity(gels)
sfepy.tests.test_poly_spaces.test_gradients(gels)
sfepy.tests.test_poly_spaces.test_hessians(gels)
Test the second partial derivatives of basis functions using finite differences.
sfepy.tests.test_poly_spaces.test_partition_of_unity(gels)
sfepy.tests.test_projections module
sfepy.tests.test_projections.data()
sfepy.tests.test_projections.test_mass_matrix(data)
sfepy.tests.test_projections.test_project_tensors(data)
sfepy.tests.test_projections.test_projection_iga_fem()
sfepy.tests.test_projections.test_projection_tri_quad(data, output_dir)
sfepy.tests.test_quadratures module
sfepy.tests.test_ref_coors module
sfepy.tests.test_ref_coors.test_ref_coors_fem()
sfepy.tests.test_ref_coors.test_ref_coors_iga()
sfepy.tests.test_refine_hanging module
Test continuity along a boundary with hanging nodes due to a mesh refinement.
sfepy.tests.test_refine_hanging.eval_fun(ts, coors, mode, **kwargs)
sfepy.tests.test_refine_hanging.gels()
sfepy.tests.test_refine_hanging.test_continuity(gels, output_dir)
sfepy.tests.test_refine_hanging.test_preserve_coarse_entities(output_dir)
sfepy.tests.test_regions module
sfepy.tests.test_regions.data()
sfepy.tests.test_regions.get_cells(coors, domain=None)
sfepy.tests.test_regions.get_vertices(coors, domain=None)
sfepy.tests.test_regions.test_operators(data)
Test operators in region selectors.
sfepy.tests.test_regions.test_selectors(data)
Test basic region selectors.
sfepy.tests.test_semismooth_newton module
sfepy.tests.test_semismooth_newton.convert_to_csr(m_in)
sfepy.tests.test_semismooth_newton.define_matrices()
sfepy.tests.test_semismooth_newton.eval_matrix(mtx, **kwargs)
sfepy.tests.test_semismooth_newton.test_semismooth_newton()
sfepy.tests.test_sparse module
sfepy.tests.test_sparse.test_compose_sparse()
sfepy.tests.test_splinebox module
sfepy.tests.test_splinebox.test_spbox_2d()
Check position of a given vertex in the deformed mesh.
sfepy.tests.test_splinebox.test_spbox_3d()
Check volume change of the mesh which is deformed using the SplineBox functions.
sfepy.tests.test_splinebox.test_spbox_field()
‘Field’ vs. ‘coors’.
sfepy.tests.test_splinebox.test_spregion2d()
Check position of a given vertex in the deformed mesh.
sfepy.tests.test_splinebox.tetravolume(cells, vertices)
sfepy.tests.test_tensors module
sfepy.tests.test_tensors.get_ortho_d(phi1, phi2)
sfepy.tests.test_tensors.test_stress_transform()
sfepy.tests.test_tensors.test_tensors()
sfepy.tests.test_tensors.test_transform_data()
sfepy.tests.test_tensors.test_transform_data4()
sfepy.tests.test_term_call_modes module
sfepy.tests.test_term_call_modes.data()
sfepy.tests.test_term_call_modes.test_term_call_modes(data)
sfepy.tests.test_term_consistency module
sfepy.tests.test_term_consistency.problem()
sfepy.tests.test_term_consistency.test_consistency_d_dw(problem)
sfepy.tests.test_term_consistency.test_ev_div(problem)
sfepy.tests.test_term_consistency.test_ev_grad(problem)
sfepy.tests.test_term_consistency.test_eval_matrix(problem)
sfepy.tests.test_term_consistency.test_surface_evaluate(problem)
sfepy.tests.test_term_consistency.test_vector_matrix(problem)
sfepy.tests.test_term_sensitivity module
sfepy.tests.test_term_sensitivity.problem()
sfepy.tests.test_term_sensitivity.test_sensitivity(problem)
sfepy.tests.test_units module
sfepy.tests.test_units.test_consistent_sets()
sfepy.tests.test_units.test_units()
sfepy.tests.test_volume module
sfepy.tests.test_volume.test_volume(problem)
sfepy.tests.test_volume.test_volume_tl(problem)
1011
SfePy Documentation, Release version: 2022.2
1012 Bibliography
PYTHON MODULE INDEX
b s
blockgen, 635 save_basis, 642
build_helpers, 632 sfepy.applications.application, 644
sfepy.applications.evp_solver_app, 645
c sfepy.applications.pde_solver_app, 645
convert_mesh, 635 sfepy.base.base, 646
cylindergen, 635 sfepy.base.compat, 652
sfepy.base.conf, 655
d sfepy.base.getch, 658
dg_plot_1D, 635 sfepy.base.goptions, 658
sfepy.base.ioutils, 658
e sfepy.base.log, 663
edit_identifiers, 636 sfepy.base.log_plotter, 664
eval_ns_forms, 636 sfepy.base.mem_usage, 665
eval_tl_forms, 637 sfepy.base.multiproc, 665
extract_edges, 637 sfepy.base.multiproc_mpi, 666
extract_surface, 637 sfepy.base.multiproc_proc, 668
extractor, 628 sfepy.base.parse_conf, 669
sfepy.base.plotutils, 670
g sfepy.base.reader, 670
sfepy.base.resolve_deps, 671
gen_gallery, 638
sfepy.base.testing, 671
gen_iga_patch, 639
sfepy.base.timing, 672
gen_legendre_simplex_base, 639
sfepy.config, 644
gen_lobatto1d_c, 639
sfepy.discrete.common.dof_info, 712
gen_mesh_prev, 640
sfepy.discrete.common.domain, 714
gen_release_notes, 640
sfepy.discrete.common.extmods._fmfield, 715
gen_serendipity_basis, 640
sfepy.discrete.common.extmods._geommech, 715
gen_solver_table, 640
sfepy.discrete.common.extmods.assemble, 715
gen_term_table, 641
sfepy.discrete.common.extmods.cmesh, 716
p sfepy.discrete.common.extmods.crefcoors, 718
sfepy.discrete.common.extmods.mappings, 719
plot_condition_numbers, 641
sfepy.discrete.common.fields, 720
plot_logs, 642
sfepy.discrete.common.global_interp, 722
plot_mesh, 642
sfepy.discrete.common.mappings, 724
plot_quadratures, 642
sfepy.discrete.common.poly_spaces, 726
plot_times, 642
sfepy.discrete.common.region, 727
probe, 629
sfepy.discrete.conditions, 672
r sfepy.discrete.dg.dg_1D_vizualizer, 761
sfepy.discrete.dg.fields, 765
resview, 630 sfepy.discrete.dg.limiters, 775
sfepy.discrete.dg.poly_spaces, 772
1013
SfePy Documentation, Release version: 2022.2
1017
SfePy Documentation, Release version: 2022.2
1018 Index
SfePy Documentation, Release version: 2022.2
Index 1019
SfePy Documentation, Release version: 2022.2
arg_shapes (sfepy.terms.terms_constraints.NonPenetrationTerm
arg_shapes (sfepy.terms.terms_elastic.CauchyStressTHTerm
attribute), 911 attribute), 931
arg_shapes (sfepy.terms.terms_contact.ContactTerm at- arg_shapes (sfepy.terms.terms_elastic.ElasticWaveCauchyTerm
tribute), 912 attribute), 932
arg_shapes (sfepy.terms.terms_dg.AdvectionDGFluxTerm arg_shapes (sfepy.terms.terms_elastic.ElasticWaveTerm
attribute), 913 attribute), 933
arg_shapes (sfepy.terms.terms_dg.DiffusionDGFluxTerm arg_shapes (sfepy.terms.terms_elastic.LinearElasticETHTerm
attribute), 915 attribute), 934
arg_shapes (sfepy.terms.terms_dg.DiffusionInteriorPenaltyTerm
arg_shapes (sfepy.terms.terms_elastic.LinearElasticIsotropicTerm
attribute), 915 attribute), 934
arg_shapes (sfepy.terms.terms_dg.NonlinearHyperbolicDGFluxTerm
arg_shapes (sfepy.terms.terms_elastic.LinearElasticTerm
attribute), 916 attribute), 935
arg_shapes (sfepy.terms.terms_dg.NonlinearScalarDotGradTerm
arg_shapes (sfepy.terms.terms_elastic.LinearElasticTHTerm
attribute), 917 attribute), 935
arg_shapes (sfepy.terms.terms_diffusion.AdvectDivFreeTermarg_shapes (sfepy.terms.terms_elastic.LinearPrestressTerm
attribute), 918 attribute), 936
arg_shapes (sfepy.terms.terms_diffusion.ConvectVGradSTermarg_shapes (sfepy.terms.terms_elastic.LinearStrainFiberTerm
attribute), 918 attribute), 937
arg_shapes (sfepy.terms.terms_diffusion.DiffusionCouplingarg_shapes (sfepy.terms.terms_elastic.NonsymElasticTerm
attribute), 919 attribute), 937
arg_shapes (sfepy.terms.terms_diffusion.DiffusionRTerm arg_shapes (sfepy.terms.terms_elastic.SDLinearElasticTerm
attribute), 920 attribute), 938
arg_shapes (sfepy.terms.terms_diffusion.DiffusionTerm arg_shapes (sfepy.terms.terms_electric.ElectricSourceTerm
attribute), 920 attribute), 939
arg_shapes (sfepy.terms.terms_diffusion.DiffusionVelocityTerm
arg_shapes (sfepy.terms.terms_fibres.FibresActiveTLTerm
attribute), 921 attribute), 940
arg_shapes (sfepy.terms.terms_diffusion.LaplaceTerm arg_shapes (sfepy.terms.terms_hyperelastic_base.DeformationGradientTe
attribute), 921 attribute), 940
arg_shapes (sfepy.terms.terms_diffusion.SDDiffusionTerm arg_shapes (sfepy.terms.terms_hyperelastic_base.HyperElasticBase
attribute), 922 attribute), 941
arg_shapes (sfepy.terms.terms_diffusion.SurfaceFluxOperatorTerm
arg_shapes (sfepy.terms.terms_hyperelastic_tl.BulkPressureTLTerm
attribute), 923 attribute), 943
arg_shapes (sfepy.terms.terms_diffusion.SurfaceFluxTerm arg_shapes (sfepy.terms.terms_hyperelastic_tl.DiffusionTLTerm
attribute), 923 attribute), 944
arg_shapes (sfepy.terms.terms_dot.BCNewtonTerm at- arg_shapes (sfepy.terms.terms_hyperelastic_tl.GenYeohTLTerm
tribute), 924 attribute), 944
arg_shapes (sfepy.terms.terms_dot.DotSProductVolumeOperatorWETHTerm
arg_shapes (sfepy.terms.terms_hyperelastic_tl.OgdenTLTerm
attribute), 926 attribute), 947
arg_shapes (sfepy.terms.terms_dot.DotSProductVolumeOperatorWTHTerm
arg_shapes (sfepy.terms.terms_hyperelastic_tl.SurfaceFluxTLTerm
attribute), 926 attribute), 947
arg_shapes (sfepy.terms.terms_dot.ScalarDotGradIScalarTerm
arg_shapes (sfepy.terms.terms_hyperelastic_tl.SurfaceTractionTLTerm
attribute), 927 attribute), 948
arg_shapes (sfepy.terms.terms_dot.ScalarDotMGradScalarTerm
arg_shapes (sfepy.terms.terms_hyperelastic_tl.VolumeSurfaceTLTerm
attribute), 927 attribute), 949
arg_shapes (sfepy.terms.terms_dot.VectorDotGradScalarTermarg_shapes (sfepy.terms.terms_hyperelastic_tl.VolumeTLTerm
attribute), 928 attribute), 949
arg_shapes (sfepy.terms.terms_dot.VectorDotScalarTerm arg_shapes (sfepy.terms.terms_hyperelastic_ul.BulkPressureULTerm
attribute), 929 attribute), 950
arg_shapes (sfepy.terms.terms_elastic.CauchyStrainTerm arg_shapes (sfepy.terms.terms_hyperelastic_ul.CompressibilityULTerm
attribute), 930 attribute), 951
arg_shapes (sfepy.terms.terms_elastic.CauchyStressETHTermarg_shapes (sfepy.terms.terms_hyperelastic_ul.VolumeULTerm
attribute), 930 attribute), 953
arg_shapes (sfepy.terms.terms_elastic.CauchyStressTerm arg_shapes (sfepy.terms.terms_membrane.TLMembraneTerm
attribute), 931 attribute), 954
1020 Index
SfePy Documentation, Release version: 2022.2
arg_shapes (sfepy.terms.terms_multilinear.ECauchyStressTerm
arg_shapes (sfepy.terms.terms_navier_stokes.StokesWaveTerm
attribute), 955 attribute), 975
arg_shapes (sfepy.terms.terms_multilinear.EConvectTerm arg_shapes (sfepy.terms.terms_navier_stokes.SUPGCStabilizationTerm
attribute), 955 attribute), 972
arg_shapes (sfepy.terms.terms_multilinear.EDiffusionTermarg_shapes (sfepy.terms.terms_navier_stokes.SUPGPStabilizationTerm
attribute), 956 attribute), 973
arg_shapes (sfepy.terms.terms_multilinear.EDivGradTermarg_shapes (sfepy.terms.terms_piezo.PiezoCouplingTerm
attribute), 956 attribute), 975
arg_shapes (sfepy.terms.terms_multilinear.EDivTerm arg_shapes (sfepy.terms.terms_piezo.PiezoStrainTerm
attribute), 957 attribute), 976
arg_shapes (sfepy.terms.terms_multilinear.EDotTerm arg_shapes (sfepy.terms.terms_piezo.PiezoStressTerm
attribute), 957 attribute), 977
arg_shapes (sfepy.terms.terms_multilinear.EGradTerm arg_shapes (sfepy.terms.terms_piezo.SDPiezoCouplingTerm
attribute), 958 attribute), 977
arg_shapes (sfepy.terms.terms_multilinear.EIntegrateOperatorTerm
arg_shapes (sfepy.terms.terms_point.ConcentratedPointLoadTerm
attribute), 958 attribute), 978
arg_shapes (sfepy.terms.terms_multilinear.ELaplaceTerm arg_shapes (sfepy.terms.terms_point.LinearPointSpringTerm
attribute), 959 attribute), 978
arg_shapes (sfepy.terms.terms_multilinear.ELinearConvectTerm
arg_shapes (sfepy.terms.terms_sensitivity.ESDDiffusionTerm
attribute), 959 attribute), 979
arg_shapes (sfepy.terms.terms_multilinear.ELinearElasticTerm
arg_shapes (sfepy.terms.terms_sensitivity.ESDDivGradTerm
attribute), 960 attribute), 980
arg_shapes (sfepy.terms.terms_multilinear.ELinearTractionTerm
arg_shapes (sfepy.terms.terms_sensitivity.ESDDotTerm
attribute), 960 attribute), 980
arg_shapes (sfepy.terms.terms_multilinear.ENonPenetrationPenaltyTerm
arg_shapes (sfepy.terms.terms_sensitivity.ESDLinearElasticTerm
attribute), 961 attribute), 981
arg_shapes (sfepy.terms.terms_multilinear.ENonSymElasticTerm
arg_shapes (sfepy.terms.terms_sensitivity.ESDLinearTractionTerm
attribute), 961 attribute), 982
arg_shapes (sfepy.terms.terms_multilinear.EScalarDotMGradScalarTerm
arg_shapes (sfepy.terms.terms_sensitivity.ESDPiezoCouplingTerm
attribute), 962 attribute), 983
arg_shapes (sfepy.terms.terms_multilinear.EStokesTerm arg_shapes (sfepy.terms.terms_sensitivity.ESDStokesTerm
attribute), 963 attribute), 983
arg_shapes (sfepy.terms.terms_navier_stokes.ConvectTermarg_shapes (sfepy.terms.terms_shells.Shell10XTerm at-
attribute), 967 tribute), 985
arg_shapes (sfepy.terms.terms_navier_stokes.DivGradTerm arg_shapes (sfepy.terms.terms_surface.ContactPlaneTerm
attribute), 967 attribute), 986
arg_shapes (sfepy.terms.terms_navier_stokes.DivOperatorTerm
arg_shapes (sfepy.terms.terms_surface.ContactSphereTerm
attribute), 968 attribute), 987
arg_shapes (sfepy.terms.terms_navier_stokes.DivTerm arg_shapes (sfepy.terms.terms_surface.LinearTractionTerm
attribute), 968 attribute), 988
arg_shapes (sfepy.terms.terms_navier_stokes.GradDivStabilizationTerm
arg_shapes (sfepy.terms.terms_surface.SDLinearTractionTerm
attribute), 969 attribute), 989
arg_shapes (sfepy.terms.terms_navier_stokes.GradTerm arg_shapes (sfepy.terms.terms_surface.SDSufaceIntegrateTerm
attribute), 969 attribute), 989
arg_shapes (sfepy.terms.terms_navier_stokes.LinearConvect2Term
arg_shapes (sfepy.terms.terms_surface.SufaceNormalDotTerm
attribute), 970 attribute), 990
arg_shapes (sfepy.terms.terms_navier_stokes.LinearConvectTerm
arg_shapes (sfepy.terms.terms_surface.SurfaceJumpTerm
attribute), 971 attribute), 991
arg_shapes (sfepy.terms.terms_navier_stokes.PSPGCStabilizationTerm
arg_shapes (sfepy.terms.terms_volume.LinearVolumeForceTerm
attribute), 971 attribute), 991
arg_shapes (sfepy.terms.terms_navier_stokes.StokesTerm arg_shapes_dict (sfepy.terms.terms_dot.BCNewtonTerm
attribute), 973 attribute), 924
arg_shapes (sfepy.terms.terms_navier_stokes.StokesWaveDivTerm
arg_shapes_dict (sfepy.terms.terms_dot.DotProductTerm
attribute), 974 attribute), 925
Index 1021
SfePy Documentation, Release version: 2022.2
1022 Index
SfePy Documentation, Release version: 2022.2
Index 1023
SfePy Documentation, Release version: 2022.2
1024 Index
SfePy Documentation, Release version: 2022.2
Index 1025
SfePy Documentation, Release version: 2022.2
1026 Index
SfePy Documentation, Release version: 2022.2
Index 1027
SfePy Documentation, Release version: 2022.2
1028 Index
SfePy Documentation, Release version: 2022.2
Index 1029
SfePy Documentation, Release version: 2022.2
create_mapping() (sfepy.discrete.structural.fields.Shell10XField
create_petsc_system() (in module
method), 789 sfepy.parallel.parallel), 840
create_mass_matrix() (in module create_pis() (in module sfepy.homogenization.utils),
sfepy.discrete.projections), 701 807
create_materials() (sfepy.discrete.problem.Problem create_prealloc_data() (in module
method), 692 sfepy.parallel.parallel), 840
create_matrix_graph() create_problem() (in module extractor), 629
(sfepy.discrete.equations.Equations method), create_reduced_vec()
675 (sfepy.discrete.equations.Equations method),
create_mesh() (sfepy.discrete.fem.fields_base.FEField 675
method), 735 create_reduced_vec()
create_mesh() (sfepy.discrete.iga.fields.IGField (sfepy.discrete.variables.Variables method),
method), 781 709
create_mesh_and_output() (in module create_region() (sfepy.discrete.common.domain.Domain
sfepy.discrete.iga.utils), 789 method), 714
create_mesh_graph() (in module create_regions() (sfepy.discrete.common.domain.Domain
sfepy.discrete.common.extmods.cmesh), 718 method), 714
create_new() (sfepy.discrete.common.extmods.cmesh.CMesh create_rotation_ops() (in module
method), 716 sfepy.mechanics.shell10x), 822
create_nlst() (sfepy.solvers.ts_solvers.GeneralizedAlphaTS create_scalar() (in module eval_ns_forms), 636
method), 882 create_scalar_base() (in module eval_ns_forms),
create_nlst() (sfepy.solvers.ts_solvers.NewmarkTS 636
method), 882 create_scalar_base_grad() (in module
create_nlst() (sfepy.solvers.ts_solvers.VelocityVerletTS eval_ns_forms), 636
method), 884 create_scalar_pis() (in module
create_nlst1() (sfepy.solvers.ts_solvers.BatheTS sfepy.homogenization.utils), 807
method), 881 create_scalar_var_data() (in module
create_nlst2() (sfepy.solvers.ts_solvers.BatheTS eval_ns_forms), 636
method), 881 create_spb() (sfepy.mesh.splinebox.SplineBox static
create_omega() (in module sfepy.terms.terms_fibres), method), 838
940 create_spb() (sfepy.mesh.splinebox.SplineRegion2D
create_output() (in module static method), 839
sfepy.discrete.fem.linearizer), 745 create_state() (sfepy.discrete.problem.Problem
create_output() (sfepy.discrete.dg.fields.DGField method), 693
method), 766 create_strain_matrix() (in module
create_output() (sfepy.discrete.fem.fields_base.FEField sfepy.mechanics.shell10x), 822
method), 735 create_strain_transform() (in module
create_output() (sfepy.discrete.iga.fields.IGField sfepy.mechanics.shell10x), 822
method), 781 create_subequations()
create_output() (sfepy.discrete.structural.fields.Shell10XField (sfepy.discrete.equations.Equations method),
method), 789 675
create_output() (sfepy.discrete.variables.FieldVariable create_subproblem()
method), 704 (sfepy.discrete.problem.Problem method),
create_output() (sfepy.discrete.variables.Variables 693
method), 709 create_surface_facet()
create_parser() (in module gen_term_table), 641 (sfepy.discrete.fem.geometry_element.GeometryElement
create_petsc_matrix() (in module method), 741
sfepy.parallel.parallel), 840 create_surface_group()
create_petsc_matrix() (sfepy.discrete.fem.domain.FEDomain
(sfepy.solvers.eigen.SLEPcEigenvalueSolver method), 730
method), 849 create_task_dof_maps() (in module
create_petsc_matrix() sfepy.parallel.parallel), 840
(sfepy.solvers.ls.PETScKrylovSolver method), create_transformation_matrix() (in module
851 sfepy.mechanics.membranes), 820
1030 Index
SfePy Documentation, Release version: 2022.2
Index 1031
SfePy Documentation, Release version: 2022.2
data_names (sfepy.terms.terms_hyperelastic_ul.HyperElasticULFamilyData
sfepy.mechanics.membranes), 821
attribute), 952 describe_nodes() (sfepy.discrete.fem.poly_spaces.FEPolySpace
data_shapes (sfepy.terms.terms_hyperelastic_base.HyperElasticFamilyData
method), 755
attribute), 941 description (build_helpers.DoxygenDocs attribute),
DataMarker (class in sfepy.base.ioutils), 658 632
DataSoftLink (class in sfepy.base.ioutils), 659 description (build_helpers.SphinxHTMLDocs at-
de_cauchy_strain() (in module tribute), 633
sfepy.terms.extmods.terms), 993 description (build_helpers.SphinxPDFDocs attribute),
de_cauchy_stress() (in module 633
sfepy.terms.extmods.terms), 993 destroy_pool() (in module
de_he_rtm() (in module sfepy.terms.extmods.terms), sfepy.homogenization.recovery), 806
993 det (sfepy.discrete.common.extmods.mappings.CMapping
debug() (in module sfepy.base.base), 646, 649 attribute), 719
debug_flags() (sfepy.config.Config method), 644 detect_band_gaps() (in module
debug_on_error() (in module sfepy.base.base), 649 sfepy.homogenization.coefs_phononic), 799
dec() (in module sfepy.base.ioutils), 660 dets_fast() (in module sfepy.linalg.utils), 814
dec() (in module sfepy.solvers.ls_mumps), 855 dg_plot_1D
dechunk_reqs_coefs() module, 635
(sfepy.homogenization.engine.HomogenizationWorkerMulti
DGEssentialBC (class in sfepy.discrete.conditions), 672
static method), 803 DGField (class in sfepy.discrete.dg.fields), 765
default_space_variables() (in module DGFieldVariable (class in sfepy.discrete.variables),
sfepy.linalg.sympy_operators), 813 703
deficiency (sfepy.solvers.ls_mumps.mumps_struc_c_4 DGLimiter (class in sfepy.discrete.dg.limiters), 775
attribute), 856 DGMultiStageTSS (class in sfepy.solvers.ts_dg_solvers),
deficiency (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 776
attribute), 859 DGPeriodicBC (class in sfepy.discrete.conditions), 673
deficiency (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 DGTerm (class in sfepy.terms.terms_dg), 914
attribute), 862 di_surface_moment() (in module
deficiency (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 sfepy.terms.extmods.terms), 993
attribute), 865 DiagPC (class in sfepy.tests.test_linear_solvers), 1003
define_box_regions() (in module dict_extend() (in module sfepy.base.base), 649
sfepy.homogenization.utils), 807 dict_from_keys_init() (in module sfepy.base.base),
define_control_points() 649
(sfepy.mesh.splinebox.SplineRegion2D static dict_from_options() (in module sfepy.base.conf ),
method), 839 657
define_matrices() (in module dict_from_string() (in module sfepy.base.conf ), 657
sfepy.tests.test_semismooth_newton), 1008 dict_to_array() (in module sfepy.base.base), 649
define_volume_coef() dict_to_struct() (in module sfepy.base.base), 649
(sfepy.homogenization.engine.HomogenizationEngine
diff_dt() (sfepy.homogenization.convolutions.ConvolutionKernel
static method), 801 method), 800
DeformationGradientTerm (class in DiffusionCoupling (class in
sfepy.terms.terms_hyperelastic_base), 940 sfepy.terms.terms_diffusion), 919
delete_zero_faces() DiffusionDGFluxTerm (class in sfepy.terms.terms_dg),
(sfepy.discrete.common.region.Region method), 914
727 DiffusionInteriorPenaltyTerm (class in
DensityVolumeInfo (class in sfepy.terms.terms_dg), 915
sfepy.homogenization.coefs_phononic), 797 DiffusionRTerm (class in sfepy.terms.terms_diffusion),
describe() (sfepy.discrete.common.extmods.mappings.CMapping 919
method), 719 DiffusionTerm (class in sfepy.terms.terms_diffusion),
describe_deformation() (in module 920
sfepy.mechanics.membranes), 820 DiffusionTLTerm (class in
describe_gaps() (in module sfepy.terms.terms_hyperelastic_tl), 943
sfepy.homogenization.coefs_phononic), 799 DiffusionVelocityTerm (class in
describe_geometry() (in module sfepy.terms.terms_diffusion), 920
1032 Index
SfePy Documentation, Release version: 2022.2
Index 1033
SfePy Documentation, Release version: 2022.2
1034 Index
SfePy Documentation, Release version: 2022.2
edit_dict_strings() (in module sfepy.base.base), 649 enc() (in module sfepy.base.ioutils), 660
edit_filename() (in module sfepy.base.ioutils), 660 ENonPenetrationPenaltyTerm (class in
edit_identifiers sfepy.terms.terms_multilinear), 961
module, 636 ENonSymElasticTerm (class in
edit_tuple_strings() (in module sfepy.base.base), sfepy.terms.terms_multilinear), 961
649 ensure_path() (in module sfepy.base.ioutils), 660
EDivGradTerm (class in sfepy.terms.terms_multilinear), entities (sfepy.discrete.common.extmods.cmesh.CMesh
956 attribute), 716
EDivTerm (class in sfepy.terms.terms_multilinear), 956 enum() (in module sfepy.base.multiproc_mpi), 667
EDotTerm (class in sfepy.terms.terms_multilinear), 957 Equation (class in sfepy.discrete.equations), 674
EGradTerm (class in sfepy.terms.terms_multilinear), 957 equation_mapping() (sfepy.discrete.variables.FieldVariable
eig() (in module sfepy.solvers.eigen), 850 method), 704
Eigenmomenta (class in equation_mapping() (sfepy.discrete.variables.Variables
sfepy.homogenization.coefs_phononic), 797 method), 709
EigenvalueSolver (class in sfepy.solvers.solvers), 877 EquationMap (class in sfepy.discrete.common.dof_info),
EIntegrateOperatorTerm (class in 713
sfepy.terms.terms_multilinear), 958 Equations (class in sfepy.discrete.equations), 674
ELaplaceTerm (class in sfepy.terms.terms_multilinear), errclear() (in module sfepy.terms.extmods.terms), 996
958 EScalarDotMGradScalarTerm (class in
ElasticConstants (class in sfepy.mechanics.matcoefs), sfepy.terms.terms_multilinear), 962
817 ESDDiffusionTerm (class in
ElasticWaveCauchyTerm (class in sfepy.terms.terms_sensitivity), 979
sfepy.terms.terms_elastic), 932 ESDDivGradTerm (class in
ElasticWaveTerm (class in sfepy.terms.terms_elastic), sfepy.terms.terms_sensitivity), 979
933 ESDDotTerm (class in sfepy.terms.terms_sensitivity), 980
ElastodynamicsBaseTS (class in ESDLinearElasticTerm (class in
sfepy.solvers.ts_solvers), 881 sfepy.terms.terms_sensitivity), 981
ElectricSourceTerm (class in ESDLinearTractionTerm (class in
sfepy.terms.terms_electric), 939 sfepy.terms.terms_sensitivity), 981
elems_q2t() (in module sfepy.mesh.mesh_tools), 837 ESDPiezoCouplingTerm (class in
elevate() (sfepy.discrete.iga.domain.NurbsPatch sfepy.terms.terms_sensitivity), 982
method), 778 ESDStokesTerm (class in sfepy.terms.terms_sensitivity),
ELinearConvectTerm (class in 983
sfepy.terms.terms_multilinear), 959 EssentialBC (class in sfepy.discrete.conditions), 673
ELinearElasticTerm (class in EStokesTerm (class in sfepy.terms.terms_multilinear),
sfepy.terms.terms_multilinear), 959 962
ELinearTractionTerm (class in ETermBase (class in sfepy.terms.terms_multilinear), 963
sfepy.terms.terms_multilinear), 960 ETHTerm (class in sfepy.terms.terms_th), 991
eltptr (sfepy.solvers.ls_mumps.mumps_struc_c_4 EulerStepSolver (class in sfepy.solvers.ts_dg_solvers),
attribute), 856 776
eltptr (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 at- eval() (sfepy.mesh.bspline.BSpline method), 829
tribute), 859 eval() (sfepy.mesh.bspline.BSplineSurf method), 831
eltptr (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at- eval_base() (sfepy.discrete.common.poly_spaces.PolySpace
tribute), 862 method), 726
eltptr (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at- eval_basis() (sfepy.mesh.bspline.BSpline method),
tribute), 865 829
eltvar (sfepy.solvers.ls_mumps.mumps_struc_c_4 eval_bernstein_basis() (in module
attribute), 856 sfepy.discrete.iga.extmods.igac), 779
eltvar (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 at- eval_bernstein_basis() (in module
tribute), 859 sfepy.discrete.iga.iga), 784
eltvar (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at- eval_complex() (in module
tribute), 862 sfepy.discrete.evaluate_variable), 682
eltvar (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at- eval_complex() (sfepy.terms.terms.Term method), 885
tribute), 865 eval_complex() (sfepy.terms.terms_multilinear.ETermBase
Index 1035
SfePy Documentation, Release version: 2022.2
1036 Index
SfePy Documentation, Release version: 2022.2
Index 1037
SfePy Documentation, Release version: 2022.2
family_name (sfepy.discrete.fem.fields_nodal.H1SNodalSurfaceField
fit_exponential() (in module
attribute), 741 sfepy.homogenization.convolutions), 801
family_name (sfepy.discrete.fem.fields_nodal.H1SNodalVolumeField
fix_double_nodes() (in module
attribute), 741 sfepy.discrete.fem.mesh), 747
family_name (sfepy.discrete.fem.fields_positive.H1BernsteinSurfaceField
fix_eig_range() (sfepy.homogenization.coefs_phononic.BandGaps
attribute), 741 method), 797
family_name (sfepy.discrete.fem.fields_positive.H1BernsteinVolumeField
fix_element_orientation()
attribute), 741 (sfepy.discrete.fem.domain.FEDomain
family_name (sfepy.discrete.iga.fields.IGField at- method), 730
tribute), 781 fix_u_fun() (in module sfepy.tests.test_high_level),
family_name (sfepy.discrete.structural.fields.Shell10XField 1001
attribute), 790 flag_points_in_polygon2d() (in module
FEDomain (class in sfepy.discrete.fem.domain), 730 sfepy.linalg.geometry), 809
FEField (class in sfepy.discrete.fem.fields_base), 734 FMinSteepestDescent (class in sfepy.solvers.optimize),
FEMapping (class in sfepy.discrete.fem.mappings), 745 872
FEPolySpace (class in sfepy.discrete.fem.poly_spaces), font_size() (in module sfepy.base.plotutils), 670
755 format (sfepy.discrete.fem.meshio.ANSYSCDBMeshIO
FESurface (class in sfepy.discrete.fem.fe_surface), 734 attribute), 747
FibresActiveTLTerm (class in format (sfepy.discrete.fem.meshio.ComsolMeshIO
sfepy.terms.terms_fibres), 939 attribute), 748
Field (class in sfepy.discrete.common.fields), 720 format (sfepy.discrete.fem.meshio.GmshIO attribute),
FieldOptsToListAction (class in resview), 631 748
fields_from_conf() (in module format (sfepy.discrete.fem.meshio.HDF5MeshIO at-
sfepy.discrete.common.fields), 722 tribute), 750
FieldVariable (class in sfepy.discrete.variables), 704 format (sfepy.discrete.fem.meshio.HDF5XdmfMeshIO
filename_meshes() (in module sfepy.tests.test_cmesh), attribute), 751
998 format (sfepy.discrete.fem.meshio.HypermeshAsciiMeshIO
fill_state() (sfepy.discrete.variables.Variables attribute), 751
method), 709 format (sfepy.discrete.fem.meshio.Mesh3DMeshIO at-
finalize() (sfepy.discrete.common.region.Region tribute), 751
method), 728 format (sfepy.discrete.fem.meshio.MeshIO attribute),
finalize() (sfepy.discrete.fem.lcbc_operators.LCBCOperators 752
method), 743 format (sfepy.discrete.fem.meshio.MeshioLibIO at-
finalize_options() (build_helpers.NoOptionsDocs tribute), 753
method), 632 format (sfepy.discrete.fem.meshio.NEUMeshIO at-
find() (sfepy.base.base.OneTypeList method), 647 tribute), 753
find_facet_substitutions() (in module format (sfepy.discrete.fem.meshio.UserMeshIO at-
sfepy.discrete.fem.refine_hanging), 760 tribute), 753
find_free_indices() (in module format (sfepy.discrete.fem.meshio.XYZMeshIO at-
sfepy.terms.terms_multilinear), 966 tribute), 754
find_level_interface() (in module format_next() (in module gen_term_table), 641
sfepy.discrete.fem.refine_hanging), 760 format_next() (in module sfepy.solvers.solvers), 878
find_map() (in module sfepy.discrete.fem.mesh), 747 free_connectivity()
find_ref_coors() (in module (sfepy.discrete.common.extmods.cmesh.CMesh
sfepy.discrete.common.extmods.crefcoors), method), 716
718 from_args() (sfepy.discrete.common.fields.Field static
find_ref_coors_convex() (in module method), 721
sfepy.discrete.common.extmods.crefcoors), from_args() (sfepy.discrete.common.mappings.Mapping
719 static method), 724
find_subclasses() (in module sfepy.base.base), 650 from_array() (sfepy.linalg.utils.MatrixAction static
find_ts() (sfepy.mesh.splinebox.SplineRegion2D method), 813
method), 839 from_cells() (sfepy.discrete.common.region.Region
find_zero() (in module static method), 728
sfepy.homogenization.coefs_phononic), 799 from_conf() (sfepy.base.log.Log static method), 663
1038 Index
SfePy Documentation, Release version: 2022.2
Index 1039
SfePy Documentation, Release version: 2022.2
1040 Index
SfePy Documentation, Release version: 2022.2
function() (sfepy.terms.terms_navier_stokes.SUPGCStabilizationTerm
gen_lobatto1d_c
static method), 972 module, 639
function() (sfepy.terms.terms_navier_stokes.SUPGPStabilizationTerm
gen_mesh_from_geom() (in module
static method), 973 sfepy.mesh.mesh_generators), 836
function() (sfepy.terms.terms_piezo.PiezoStressTerm gen_mesh_from_string() (in module
static method), 977 sfepy.mesh.mesh_generators), 836
function() (sfepy.terms.terms_point.ConcentratedPointLoadTerm
gen_mesh_from_voxels() (in module
static method), 978 sfepy.mesh.mesh_generators), 836
function() (sfepy.terms.terms_point.LinearPointSpringTermgen_mesh_prev
static method), 979 module, 640
function() (sfepy.terms.terms_shells.Shell10XTerm gen_mesh_probe_png()
static method), 985 (sfepy.postprocess.probes_vtk.Probe method),
function() (sfepy.terms.terms_surface.ContactPlaneTerm 845
static method), 986 gen_misc_mesh() (in module
function() (sfepy.terms.terms_surface.ContactSphereTerm sfepy.mesh.mesh_generators), 836
static method), 987 gen_multi_vec_packing() (in module
function() (sfepy.terms.terms_surface.SDSufaceIntegrateTerm sfepy.solvers.ts_solvers), 884
static method), 989 gen_patch_block_domain() (in module
function() (sfepy.terms.terms_surface.SurfaceJumpTerm sfepy.discrete.iga.domain_generators), 778
static method), 991 gen_points() (sfepy.discrete.probes.RayProbe
function() (sfepy.terms.terms_volume.LinearVolumeForceTerm method), 689
static method), 992 gen_release_notes
function_silent() (sfepy.terms.terms_multilinear.ETermBasemodule, 640
static method), 964 gen_serendipity_basis
function_timer() (sfepy.terms.terms_multilinear.ETermBase module, 640
static method), 964 gen_shot() (in module gen_mesh_prev), 640
function_weak() (sfepy.terms.terms_contact.ContactTermgen_solver_table
static method), 912 module, 640
Functions (class in sfepy.discrete.functions), 682 gen_solver_table() (in module gen_solver_table),
640
G gen_term_table
gels() (in module sfepy.tests.test_fem), 1000 module, 641
gels() (in module sfepy.tests.test_poly_spaces), 1007 gen_term_table() (in module gen_term_table), 641
gels() (in module sfepy.tests.test_refine_hanging), 1008 gen_tiled_mesh() (in module
geme_mulAVSB3py() (in module sfepy.mesh.mesh_generators), 836
sfepy.discrete.common.extmods._geommech), GeneralizedAlphaTS (class in sfepy.solvers.ts_solvers),
715 881
gen_block_mesh() (in module generate_a_pyrex_source() (in module
sfepy.mesh.mesh_generators), 835 build_helpers), 633
gen_cp_idxs() (sfepy.mesh.splinebox.SplineBox static generate_decreasing_nonnegative_tuples_summing_to()
method), 838 (in module sfepy.discrete.simplex_cubature),
gen_cylinder_mesh() (in module 703
sfepy.mesh.mesh_generators), 835 generate_gallery() (in module gen_gallery), 638
gen_datas() (in module sfepy.tests.test_mesh_interp), generate_images() (in module gen_gallery), 638
1005 generate_permutations() (in module
gen_extended_block_mesh() (in module sfepy.discrete.simplex_cubature), 703
sfepy.mesh.mesh_generators), 835 generate_probes() (in module probe), 630
gen_gallery generate_rst_files() (in module gen_gallery), 638
module, 638 generate_thumbnails() (in module gen_gallery), 638
gen_iga_patch generate_unique_permutations() (in module
module, 639 sfepy.discrete.simplex_cubature), 703
gen_legendre_simplex_base GenYeohTLTerm (class in
module, 639 sfepy.terms.terms_hyperelastic_tl), 944
gen_lobatto() (in module gen_lobatto1d_c), 639 geo_ctx (sfepy.discrete.fem.extmods.bases.CLagrangeContext
Index 1041
SfePy Documentation, Release version: 2022.2
1042 Index
SfePy Documentation, Release version: 2022.2
Index 1043
SfePy Documentation, Release version: 2022.2
1044 Index
SfePy Documentation, Release version: 2022.2
get_eval_shape() (sfepy.terms.terms_diffusion.DiffusionTerm
get_eval_shape() (sfepy.terms.terms_multilinear.ETermBase
method), 920 method), 964
get_eval_shape() (sfepy.terms.terms_diffusion.DiffusionVelocityTerm
get_eval_shape() (sfepy.terms.terms_navier_stokes.DivGradTerm
method), 921 method), 967
get_eval_shape() (sfepy.terms.terms_diffusion.SDDiffusionTerm
get_eval_shape() (sfepy.terms.terms_navier_stokes.DivTerm
method), 922 method), 968
get_eval_shape() (sfepy.terms.terms_diffusion.SurfaceFluxTerm
get_eval_shape() (sfepy.terms.terms_navier_stokes.GradTerm
method), 923 method), 969
get_eval_shape() (sfepy.terms.terms_dot.DotProductTerm get_eval_shape() (sfepy.terms.terms_navier_stokes.StokesTerm
method), 925 method), 973
get_eval_shape() (sfepy.terms.terms_dot.VectorDotGradScalarTerm
get_eval_shape() (sfepy.terms.terms_piezo.PiezoCouplingTerm
method), 928 method), 975
get_eval_shape() (sfepy.terms.terms_dot.VectorDotScalarTerm
get_eval_shape() (sfepy.terms.terms_piezo.PiezoStrainTerm
method), 929 method), 976
get_eval_shape() (sfepy.terms.terms_elastic.CauchyStrainTerm
get_eval_shape() (sfepy.terms.terms_piezo.PiezoStressTerm
method), 930 method), 977
get_eval_shape() (sfepy.terms.terms_elastic.CauchyStressETHTerm
get_eval_shape() (sfepy.terms.terms_surface.LinearTractionTerm
method), 930 method), 988
get_eval_shape() (sfepy.terms.terms_elastic.CauchyStressTerm
get_eval_shape() (sfepy.terms.terms_surface.SDLinearTractionTerm
method), 932 method), 989
get_eval_shape() (sfepy.terms.terms_elastic.CauchyStressTHTerm
get_eval_shape() (sfepy.terms.terms_surface.SDSufaceIntegrateTerm
method), 931 method), 989
get_eval_shape() (sfepy.terms.terms_elastic.LinearElasticIsotropicTerm
get_eval_shape() (sfepy.terms.terms_surface.SufaceNormalDotTerm
method), 934 method), 990
get_eval_shape() (sfepy.terms.terms_elastic.LinearElasticTerm
get_evaluate_cache()
method), 936 (sfepy.discrete.fem.fields_base.FEField
get_eval_shape() (sfepy.terms.terms_elastic.LinearPrestressTerm method), 736
method), 936 get_evaluate_cache() (sfepy.discrete.probes.Probe
get_eval_shape() (sfepy.terms.terms_elastic.NonsymElasticTerm method), 688
method), 938 get_evaluator() (sfepy.discrete.problem.Problem
get_eval_shape() (sfepy.terms.terms_elastic.SDLinearElasticTerm method), 694
method), 938 get_examples() (in module gen_term_table), 641
get_eval_shape() (sfepy.terms.terms_fibres.FibresActiveTLTerm
get_exp() (sfepy.homogenization.convolutions.ConvolutionKernel
method), 940 method), 800
get_eval_shape() (sfepy.terms.terms_hyperelastic_base.DeformationGradientTerm
get_expression_arg_names() (in module
method), 941 sfepy.discrete.equations), 679
get_eval_shape() (sfepy.terms.terms_hyperelastic_base.HyperElasticBase
get_expressions() (sfepy.terms.terms_multilinear.ExpressionBuilder
method), 941 method), 965
get_eval_shape() (sfepy.terms.terms_hyperelastic_tl.BulkPressureTLTerm
get_face_areas() (in module sfepy.linalg.geometry),
method), 943 810
get_eval_shape() (sfepy.terms.terms_hyperelastic_tl.DiffusionTLTerm
get_facet_axes() (in module sfepy.discrete.iga.iga),
method), 944 786
get_eval_shape() (sfepy.terms.terms_hyperelastic_tl.SurfaceFluxTLTerm
get_facet_base() (sfepy.discrete.dg.fields.DGField
method), 948 method), 769
get_eval_shape() (sfepy.terms.terms_hyperelastic_tl.VolumeSurfaceTLTerm
get_facet_dof_permutations() (in module
method), 949 sfepy.discrete.fem.facets), 733
get_eval_shape() (sfepy.terms.terms_hyperelastic_tl.VolumeTLTerm
get_facet_indices()
method), 949 (sfepy.discrete.common.region.Region method),
get_eval_shape() (sfepy.terms.terms_hyperelastic_ul.BulkPressureULTerm
729
method), 951 get_facet_neighbor_idx()
get_eval_shape() (sfepy.terms.terms_hyperelastic_ul.VolumeULTerm (sfepy.discrete.dg.fields.DGField method),
method), 953 769
get_eval_shape() (sfepy.terms.terms_membrane.TLMembraneTerm
get_facet_normals()
method), 954 (sfepy.discrete.common.extmods.cmesh.CMesh
Index 1045
SfePy Documentation, Release version: 2022.2
1046 Index
SfePy Documentation, Release version: 2022.2
Index 1047
SfePy Documentation, Release version: 2022.2
1048 Index
SfePy Documentation, Release version: 2022.2
Index 1049
SfePy Documentation, Release version: 2022.2
(sfepy.homogenization.homogen_app.HomogenizationApp
get_or_create_hdf5_group() (in module
method), 803 sfepy.base.ioutils), 660
get_min_dt() (in module sfepy.solvers.ts_solvers), 884 get_orientations() (sfepy.discrete.common.extmods.cmesh.CMesh
get_min_value() (in module sfepy.discrete.fem.utils), method), 717
761 get_ortho_d() (in module sfepy.tests.test_tensors),
get_min_vertex_distance() (in module 1009
sfepy.discrete.fem.mesh), 747 get_output() (sfepy.homogenization.coefs_base.CorrMiniApp
get_min_vertex_distance_naive() (in module method), 793
sfepy.discrete.fem.mesh), 747 get_output_approx_order()
get_mirror_region() (sfepy.discrete.fem.fields_base.FEField
(sfepy.discrete.common.region.Region method), method), 736
729 get_output_function() (sfepy.base.base.Output
get_mpdict_value() (in module method), 647
sfepy.base.multiproc_proc), 668 get_output_name() (sfepy.discrete.problem.Problem
get_mtx_i() (sfepy.discrete.fem.poly_spaces.FEPolySpace method), 695
method), 755 get_output_prefix() (sfepy.base.base.Output
get_mtx_i() (sfepy.discrete.fem.poly_spaces.LagrangeTensorProductPolySpace
method), 648
method), 756 get_output_shape() (in module
get_multiproc() (in module sfepy.base.multiproc), 665 sfepy.terms.terms_multilinear), 966
get_n_cells() (sfepy.discrete.common.region.Region get_output_suffix() (in module
method), 729 sfepy.homogenization.recovery), 806
get_n_dof_total() (sfepy.discrete.common.dof_info.DofInfo
get_p_edge() (in module sfepy.tests.test_functions),
method), 713 1001
get_n_el_nod() (in module get_parameter_names() (sfepy.terms.terms.Term
sfepy.discrete.dg.poly_spaces), 774 method), 887
get_names() (sfepy.base.base.Container method), 647 get_parameter_variables() (sfepy.terms.terms.Term
get_names() (sfepy.base.base.OneTypeList method), method), 887
647 get_parents() (in module
get_nls() (sfepy.discrete.problem.Problem method), sfepy.discrete.common.region), 730
694 get_pars() (in module
get_nls_functions() sfepy.tests.test_elasticity_small_strain), 1000
(sfepy.discrete.problem.Problem method), get_pars() (in module sfepy.tests.test_functions), 1001
694 get_pars() (in module
get_nodal_values() (sfepy.discrete.dg.fields.DGField sfepy.tests.test_term_consistency), 1010
method), 770 get_patch_box_regions() (in module
get_non_diagonal_indices() (in module sfepy.discrete.iga.iga), 786
sfepy.mechanics.tensors), 824 get_paths() (sfepy.terms.terms_multilinear.ETermBase
get_nonsym_grad_op() (in module method), 964
sfepy.terms.terms_sensitivity), 984 get_perpendiculars() (in module
get_normals() (in module sfepy.linalg.geometry), 810
sfepy.discrete.common.mappings), 726 get_physical_qps() (in module
get_normals() (sfepy.terms.terms_multilinear.ETermBase sfepy.discrete.common.mappings), 726
method), 964 get_physical_qps() (sfepy.discrete.fem.mappings.FEMapping
get_nth_fun() (sfepy.discrete.dg.poly_spaces.LegendrePolySpace method), 745
method), 772 get_physical_qps() (sfepy.discrete.iga.mappings.IGMapping
get_nth_fun_der() (sfepy.discrete.dg.poly_spaces.LegendrePolySpace
method), 788
method), 773 get_physical_qps() (sfepy.discrete.structural.mappings.Shell10XMappin
get_num_workers() (in module sfepy.base.multiproc), method), 790
665 get_physical_qps() (sfepy.terms.terms.Term method),
get_nums() (in module sfepy.base.resolve_deps), 671 887
get_operands() (sfepy.terms.terms_multilinear.ETermBaseget_physical_qps() (sfepy.terms.terms_shells.Shell10XTerm
method), 964 method), 985
get_operator() (sfepy.discrete.common.dof_info.EquationMap
get_points() (sfepy.discrete.probes.CircleProbe
method), 713 method), 687
1050 Index
SfePy Documentation, Release version: 2022.2
Index 1051
SfePy Documentation, Release version: 2022.2
1052 Index
SfePy Documentation, Release version: 2022.2
Index 1053
SfePy Documentation, Release version: 2022.2
1054 Index
SfePy Documentation, Release version: 2022.2
Index 1055
SfePy Documentation, Release version: 2022.2
integration (sfepy.terms.terms_elastic.CauchyStressTerminvalidate_evaluate_cache()
attribute), 932 (sfepy.discrete.variables.FieldVariable
integration (sfepy.terms.terms_hyperelastic_tl.SurfaceFluxTLTerm method), 707
attribute), 948 invalidate_evaluate_caches()
integration (sfepy.terms.terms_hyperelastic_tl.SurfaceTractionTLTerm
(sfepy.discrete.variables.Variables method),
attribute), 948 710
integration (sfepy.terms.terms_hyperelastic_tl.VolumeSurfaceTLTerm
invalidate_term_caches()
attribute), 949 (sfepy.discrete.equations.Equations method),
integration (sfepy.terms.terms_membrane.TLMembraneTerm 677
attribute), 954 inverse_element_mapping() (in module
integration (sfepy.terms.terms_multilinear.EDotTerm sfepy.linalg.geometry), 810
attribute), 957 invert_dict() (in module sfepy.base.base), 650
integration (sfepy.terms.terms_multilinear.EIntegrateOperatorTerm
invert_remap() (in module sfepy.discrete.fem.utils),
attribute), 958 761
integration (sfepy.terms.terms_multilinear.ELinearTractionTerm
iplot() (in module sfepy.base.plotutils), 670
attribute), 960 ipython_shell() (in module sfepy.base.base), 650
integration (sfepy.terms.terms_multilinear.ENonPenetrationPenaltyTerm
irhs_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_2
attribute), 961 attribute), 866
integration (sfepy.terms.terms_navier_stokes.DivTerm irhs_ptr (sfepy.solvers.ls_mumps.mumps_struc_c_4 at-
attribute), 968 tribute), 856
integration (sfepy.terms.terms_navier_stokes.GradTerm irhs_ptr (sfepy.solvers.ls_mumps.mumps_struc_c_5_0
attribute), 970 attribute), 859
integration (sfepy.terms.terms_point.ConcentratedPointLoadTerm
irhs_ptr (sfepy.solvers.ls_mumps.mumps_struc_c_5_1
attribute), 978 attribute), 862
integration (sfepy.terms.terms_point.LinearPointSpringTerm
irhs_ptr (sfepy.solvers.ls_mumps.mumps_struc_c_5_2
attribute), 979 attribute), 866
integration (sfepy.terms.terms_sensitivity.ESDLinearTractionTerm
irhs_sparse (sfepy.solvers.ls_mumps.mumps_struc_c_4
attribute), 982 attribute), 856
integration (sfepy.terms.terms_shells.Shell10XTerm irhs_sparse (sfepy.solvers.ls_mumps.mumps_struc_c_5_0
attribute), 985 attribute), 859
integration (sfepy.terms.terms_surface.ContactPlaneTermirhs_sparse (sfepy.solvers.ls_mumps.mumps_struc_c_5_1
attribute), 987 attribute), 862
integration (sfepy.terms.terms_surface.ContactSphereTermirhs_sparse (sfepy.solvers.ls_mumps.mumps_struc_c_5_2
attribute), 988 attribute), 866
integration (sfepy.terms.terms_surface.LinearTractionTerm
irn (sfepy.solvers.ls_mumps.mumps_struc_c_4 at-
attribute), 988 tribute), 856
integration (sfepy.terms.terms_surface.SDLinearTractionTerm
irn (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 at-
attribute), 989 tribute), 859
integration (sfepy.terms.terms_surface.SDSufaceIntegrateTerm
irn (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at-
attribute), 990 tribute), 862
integration (sfepy.terms.terms_surface.SufaceNormalDotTerm
irn (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at-
attribute), 990 tribute), 866
integration (sfepy.terms.terms_surface.SurfaceJumpTermirn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_4 at-
attribute), 991 tribute), 856
interp_conv_mat() (in module irn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_0
sfepy.homogenization.utils), 808 attribute), 859
interp_to_qp() (sfepy.discrete.fem.fields_base.FEField irn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_1
method), 736 attribute), 862
interp_v_vals_to_n_vals() irn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_2
(sfepy.discrete.fem.fields_nodal.H1NodalSurfaceField attribute), 866
method), 740 is_active_bc() (in module
interp_v_vals_to_n_vals() sfepy.discrete.common.dof_info), 714
(sfepy.discrete.fem.fields_nodal.H1NodalVolumeField
is_bubble (sfepy.discrete.fem.extmods.bases.CLagrangeContext
method), 740 attribute), 731
1056 Index
SfePy Documentation, Release version: 2022.2
Index 1057
SfePy Documentation, Release version: 2022.2
J kind (sfepy.discrete.fem.lcbc_operators.EdgeDirectionOperator
jacobiP() (sfepy.discrete.dg.poly_spaces.LegendrePolySpace attribute), 743
method), 773 kind (sfepy.discrete.fem.lcbc_operators.IntegralMeanValueOperator
jcn (sfepy.solvers.ls_mumps.mumps_struc_c_4 at- attribute), 743
tribute), 856 kind (sfepy.discrete.fem.lcbc_operators.NodalLCOperator
jcn (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 at- attribute), 744
tribute), 859 kind (sfepy.discrete.fem.lcbc_operators.NoPenetrationOperator
jcn (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at- attribute), 744
tribute), 863 kind (sfepy.discrete.fem.lcbc_operators.NormalDirectionOperator
jcn (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at- attribute), 744
tribute), 866 kind (sfepy.discrete.fem.lcbc_operators.RigidOperator
jcn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_4 at- attribute), 744
tribute), 856 kind (sfepy.discrete.fem.lcbc_operators.ShiftedPeriodicOperator
jcn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 attribute), 744
attribute), 859
jcn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 L
attribute), 863 label_dofs() (in module
jcn_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 sfepy.parallel.plot_parallel_dofs), 842
attribute), 866 label_global_entities() (in module
job (sfepy.solvers.ls_mumps.mumps_struc_c_4 at- sfepy.postprocess.plot_cmesh), 842
tribute), 856 label_local_entities() (in module
job (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 at- sfepy.postprocess.plot_cmesh), 842
tribute), 859 label_points() (in module
job (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at- sfepy.postprocess.plot_quadrature), 844
tribute), 863 LagrangeNodes (class in
job (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at- sfepy.discrete.fem.poly_spaces), 755
tribute), 866 LagrangePolySpace (class in
job (sfepy.solvers.ls_mumps.mumps_struc_c_x at- sfepy.discrete.fem.poly_spaces), 756
tribute), 869 LagrangeSimplexBPolySpace (class in
sfepy.discrete.fem.poly_spaces),
join_subscripts() (sfepy.terms.terms_multilinear.ExpressionBuilder 756
static method), 965 LagrangeSimplexPolySpace (class in
join_tokens() (in module sfepy.discrete.fem.poly_spaces), 756
sfepy.discrete.parse_regions), 686 LagrangeTensorProductPolySpace (class in
sfepy.discrete.fem.poly_spaces), 756
K lame_from_stiffness() (in module
keep (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 sfepy.mechanics.matcoefs), 818
attribute), 859 lame_from_youngpoisson() (in module
keep (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 sfepy.mechanics.matcoefs), 818
attribute), 863 laplace() (in module sfepy.linalg.sympy_operators),
keep (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 813
attribute), 866 LaplaceTerm (class in sfepy.terms.terms_diffusion), 921
keep8 (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 at- layout_letters (sfepy.terms.terms_multilinear.ETermBase
tribute), 860 attribute), 964
keep8 (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at- LCBCOperator (class in
tribute), 863 sfepy.discrete.fem.lcbc_operators), 743
keep8 (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at- LCBCOperators (class in
tribute), 866 sfepy.discrete.fem.lcbc_operators), 743
key_to_index (sfepy.discrete.common.extmods.cmesh.CMesh leaveonlyphysicalsurfaces()
attribute), 717 (sfepy.mesh.geom_tools.geometry method),
keys (sfepy.discrete.common.poly_spaces.PolySpace at- 833
tribute), 727 leaveonlyphysicalvolumes()
keys() (sfepy.base.goptions.ValidatedDict method), 658 (sfepy.mesh.geom_tools.geometry method),
keys() (sfepy.base.multiproc_mpi.RemoteDict method), 833
666
1058 Index
SfePy Documentation, Release version: 2022.2
Index 1059
SfePy Documentation, Release version: 2022.2
1060 Index
SfePy Documentation, Release version: 2022.2
Index 1061
SfePy Documentation, Release version: 2022.2
1062 Index
SfePy Documentation, Release version: 2022.2
Index 1063
SfePy Documentation, Release version: 2022.2
1064 Index
SfePy Documentation, Release version: 2022.2
Index 1065
SfePy Documentation, Release version: 2022.2
1066 Index
SfePy Documentation, Release version: 2022.2
Index 1067
SfePy Documentation, Release version: 2022.2
1068 Index
SfePy Documentation, Release version: 2022.2
name (sfepy.terms.terms_navier_stokes.PSPGCStabilizationTerm
name (sfepy.terms.terms_surface.SurfaceJumpTerm at-
attribute), 971 tribute), 991
name (sfepy.terms.terms_navier_stokes.PSPGPStabilizationTerm
name (sfepy.terms.terms_volume.LinearVolumeForceTerm
attribute), 972 attribute), 992
name (sfepy.terms.terms_navier_stokes.StokesTerm nblock (sfepy.solvers.ls_mumps.mumps_struc_c_4
attribute), 974 attribute), 857
name (sfepy.terms.terms_navier_stokes.StokesWaveDivTerm nblock (sfepy.solvers.ls_mumps.mumps_struc_c_5_0 at-
attribute), 974 tribute), 860
name (sfepy.terms.terms_navier_stokes.StokesWaveTerm nblock (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at-
attribute), 975 tribute), 863
name (sfepy.terms.terms_navier_stokes.SUPGCStabilizationTerm
nblock (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at-
attribute), 972 tribute), 867
name (sfepy.terms.terms_navier_stokes.SUPGPStabilizationTerm
nelt (sfepy.solvers.ls_mumps.mumps_struc_c_4 at-
attribute), 973 tribute), 857
name (sfepy.terms.terms_piezo.PiezoCouplingTerm nelt (sfepy.solvers.ls_mumps.mumps_struc_c_5_0
attribute), 976 attribute), 860
name (sfepy.terms.terms_piezo.PiezoStrainTerm at- nelt (sfepy.solvers.ls_mumps.mumps_struc_c_5_1
tribute), 976 attribute), 863
name (sfepy.terms.terms_piezo.PiezoStressTerm at- nelt (sfepy.solvers.ls_mumps.mumps_struc_c_5_2
tribute), 977 attribute), 867
name (sfepy.terms.terms_piezo.SDPiezoCouplingTerm at- NeoHookeanTLTerm (class in
tribute), 977 sfepy.terms.terms_hyperelastic_tl), 946
name (sfepy.terms.terms_point.ConcentratedPointLoadTerm NeoHookeanULTerm (class in
attribute), 978 sfepy.terms.terms_hyperelastic_ul), 952
name (sfepy.terms.terms_point.LinearPointSpringTerm NEUMeshIO (class in sfepy.discrete.fem.meshio), 753
attribute), 979 new() (sfepy.terms.terms.Term static method), 888
name (sfepy.terms.terms_sensitivity.ESDDiffusionTerm new_ulf_iteration()
attribute), 979 (sfepy.discrete.evaluate.Evaluator static
name (sfepy.terms.terms_sensitivity.ESDDivGradTerm at- method), 679
tribute), 980 new_vtk_polyline() (sfepy.postprocess.probes_vtk.Probe
name (sfepy.terms.terms_sensitivity.ESDDotTerm at- method), 845
tribute), 981 NewmarkTS (class in sfepy.solvers.ts_solvers), 882
name (sfepy.terms.terms_sensitivity.ESDLinearElasticTerm Newton (class in sfepy.solvers.nls), 869
attribute), 981 nloc_rhs (sfepy.solvers.ls_mumps.mumps_struc_c_5_2
name (sfepy.terms.terms_sensitivity.ESDLinearTractionTerm attribute), 867
attribute), 982 NLSStatus (class in sfepy.base.testing), 671
name (sfepy.terms.terms_sensitivity.ESDPiezoCouplingTermnnz (sfepy.solvers.ls_mumps.mumps_struc_c_5_1 at-
attribute), 983 tribute), 863
name (sfepy.terms.terms_sensitivity.ESDStokesTerm at- nnz (sfepy.solvers.ls_mumps.mumps_struc_c_5_2 at-
tribute), 984 tribute), 867
name (sfepy.terms.terms_shells.Shell10XTerm attribute), nnz_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_1
985 attribute), 863
name (sfepy.terms.terms_surface.ContactPlaneTerm at- nnz_loc (sfepy.solvers.ls_mumps.mumps_struc_c_5_2
tribute), 987 attribute), 867
name (sfepy.terms.terms_surface.ContactSphereTerm at- NodalLCOperator (class in
tribute), 988 sfepy.discrete.fem.lcbc_operators), 744
name (sfepy.terms.terms_surface.LinearTractionTerm at- NodeDescription (class in
tribute), 988 sfepy.discrete.fem.poly_spaces), 756
name (sfepy.terms.terms_surface.SDLinearTractionTerm NonlinearHyperbolicDGFluxTerm (class in
attribute), 989 sfepy.terms.terms_dg), 916
name (sfepy.terms.terms_surface.SDSufaceIntegrateTerm NonlinearScalarDotGradTerm (class in
attribute), 990 sfepy.terms.terms_dg), 917
name (sfepy.terms.terms_surface.SufaceNormalDotTerm NonlinearSolver (class in sfepy.solvers.solvers), 877
attribute), 990 NonPenetrationPenaltyTerm (class in
Index 1069
SfePy Documentation, Release version: 2022.2
1070 Index
SfePy Documentation, Release version: 2022.2
Index 1071
SfePy Documentation, Release version: 2022.2
1072 Index
SfePy Documentation, Release version: 2022.2
presolve() (sfepy.homogenization.coefs_base.PressureEigenvalueProblem
1010
method), 794 problem() (in module sfepy.tests.test_volume), 1010
presolve() (sfepy.solvers.ls.MUMPSSolver method), ProblemConf (class in sfepy.base.conf ), 655
850 process_command() (sfepy.base.log_plotter.LogPlotter
presolve() (sfepy.solvers.ls.ScipyDirect method), 853 method), 664
presolve() (sfepy.solvers.solvers.LinearSolver method), process_conf() (sfepy.solvers.solvers.Solver class
877 method), 877
PressureEigenvalueProblem (class in process_options() (sfepy.applications.evp_solver_app.EVPSolverApp
sfepy.homogenization.coefs_base), 794 static method), 645
PressureRHSVector (class in process_options() (sfepy.applications.pde_solver_app.PDESolverApp
sfepy.homogenization.coefs_elastic), 795 static method), 645
print_array_info() (in module sfepy.linalg.utils), 816 process_options() (sfepy.homogenization.band_gaps_app.AcousticBand
print_camera_position() (in module resview), 631 static method), 790
print_leaf() (in module sfepy.discrete.parse_regions), process_options() (sfepy.homogenization.coefs_base.MiniAppBase
686 method), 794
print_matrix_diff() (in module sfepy.base.plotutils), process_options() (sfepy.homogenization.coefs_phononic.BandGaps
670 method), 797
print_mem_usage() (in module process_options() (sfepy.homogenization.coefs_phononic.ChristoffelAco
sfepy.base.mem_usage), 665 method), 797
print_names() (sfepy.base.base.Container method), process_options() (sfepy.homogenization.coefs_phononic.Eigenmoment
647 method), 798
print_names() (sfepy.base.base.OneTypeList method), process_options() (sfepy.homogenization.coefs_phononic.PhaseVelocity
647 method), 798
print_op() (in module sfepy.discrete.parse_regions), process_options() (sfepy.homogenization.coefs_phononic.PolarizationA
686 method), 798
print_shapes() (sfepy.terms.terms_multilinear.ExpressionBuilder
process_options() (sfepy.homogenization.coefs_phononic.SimpleEVP
method), 966 method), 798
print_solvers() (in module simple), 631 process_options() (sfepy.homogenization.engine.HomogenizationEngine
print_stack() (in module static method), 801
sfepy.discrete.parse_regions), 686 process_options() (sfepy.homogenization.homogen_app.Homogenization
print_structs() (in module sfepy.base.base), 651 static method), 803
print_terms() (in module simple), 631 process_options_pv()
print_terms() (sfepy.discrete.equations.Equations (sfepy.homogenization.band_gaps_app.AcousticBandGapsApp
method), 677 static method), 790
printinfo() (sfepy.mesh.geom_tools.geometry process_reqs_coefs()
method), 833 (sfepy.homogenization.engine.HomogenizationWorkerMulti
probe static method), 803
module, 629 project_by_component() (in module
Probe (class in sfepy.discrete.probes), 688 sfepy.discrete.projections), 701
Probe (class in sfepy.postprocess.probes_vtk), 844 project_to_facets() (in module
probe() (sfepy.discrete.probes.Probe method), 688 sfepy.discrete.projections), 701
ProbeFromFile (class in sfepy.postprocess.probes_vtk), ps (sfepy.discrete.common.extmods.mappings.CMapping
845 attribute), 719
Problem (class in sfepy.discrete.problem), 690 PSPGCStabilizationTerm (class in
problem() (in module sfepy.tests.test_functions), 1001 sfepy.terms.terms_navier_stokes), 971
problem() (in module sfepy.tests.test_linear_solvers), PSPGPStabilizationTerm (class in
1003 sfepy.terms.terms_navier_stokes), 971
problem() (in module sfepy.tests.test_msm_laplace), put() (sfepy.base.multiproc_mpi.RemoteQueue method),
1006 667
problem() (in module sfepy.tests.test_msm_symbolic), put() (sfepy.base.multiproc_mpi.RemoteQueueMaster
1006 method), 667
problem() (in module sfepy.tests.test_term_consistency), put() (sfepy.base.multiproc_proc.MyQueue method),
1010 668
problem() (in module sfepy.tests.test_term_sensitivity), pv_plot() (in module resview), 631
Index 1073
SfePy Documentation, Release version: 2022.2
1074 Index
SfePy Documentation, Release version: 2022.2
Index 1075
SfePy Documentation, Release version: 2022.2
1076 Index
SfePy Documentation, Release version: 2022.2
Index 1077
SfePy Documentation, Release version: 2022.2
1078 Index
SfePy Documentation, Release version: 2022.2
Index 1079
SfePy Documentation, Release version: 2022.2
1080 Index
SfePy Documentation, Release version: 2022.2
Index 1081
SfePy Documentation, Release version: 2022.2
1082 Index
SfePy Documentation, Release version: 2022.2
Index 1083
SfePy Documentation, Release version: 2022.2
1084 Index
SfePy Documentation, Release version: 2022.2
Index 1085
SfePy Documentation, Release version: 2022.2
1086 Index
SfePy Documentation, Release version: 2022.2
Index 1087
SfePy Documentation, Release version: 2022.2
1088 Index
SfePy Documentation, Release version: 2022.2
Index 1089
SfePy Documentation, Release version: 2022.2
1090 Index
SfePy Documentation, Release version: 2022.2
Index 1091
SfePy Documentation, Release version: 2022.2
1092 Index
SfePy Documentation, Release version: 2022.2
Index 1093
SfePy Documentation, Release version: 2022.2
1094 Index
SfePy Documentation, Release version: 2022.2
Y
youngpoisson_from_stiffness() (in module
sfepy.mechanics.matcoefs), 819
youngpoisson_from_wave_speeds() (in module
sfepy.mechanics.matcoefs), 819
Z
zero_dofs() (sfepy.discrete.conditions.Conditions
method), 672
zero_dofs() (sfepy.discrete.conditions.EssentialBC
method), 673
ZeroTerm (class in sfepy.terms.terms_basic), 903
Index 1095