Skip to content

Commit

Permalink
Merge pull request #246 from mfem/install.md
Browse files Browse the repository at this point in the history
Install.md
  • Loading branch information
sshiraiwa authored Aug 7, 2024
2 parents e1466a6 + b630210 commit 3e68b55
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 160 deletions.
178 changes: 178 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Installation Guide

## Basic install

Most users will be fine using the binary bundled in the default `pip` install:

```shell
pip install mfem
```
The above installation will download and install a *serial* version of `MFEM`.

## Building from source
PyMFEM has many options for installation, when building from source, including:
- Serial and parallel (MPI) wrappers
- Using pre-built local dependencies
- Installing additional dependencies such as
- `hypre`
- `gslib`
- `libceed`
- `metis`

Most of the options for PyMFEM can be used directly when installing via `python setup.py install`, e.g.
```shell
git clone git@github:mfem/PyMFEM.git
cd PyMFEM
python setup.py install --user
```
For example, parallel (MPI) support is built with the `--with-parallel` flag:
```shell
python setup.py install --with-parallel
```

Note: this option turns on building `metis` and `Hypre`

## Commonly used flags

| Flag | Description |
|------|-------------|
| `--with-parallel` | Install both serial and parallel versions of `MFEM` and the wrapper<br>(note: this option turns on building `metis` and `hypre`) |
| `--mfem-branch=<reference>` | Download/install MFEM using a specific reference (`git` `branch`, `hash`, or `tag`) |
| `--user` | Install in user's site-package |

In order to see the full list of options, use

```shell
python setup.py install --help
```

## Advanced options

### Suitesparse
`--with-suitesparse` : build MFEM with `suitesparse`. `suitesparse` needs to be installed separately.
Point to the location of `suitesparse` using the flag `--suitesparse-prefix=<location>`

Note: this option turns on building `metis` in serial

### CUDA
`--with-cuda` : build MFEM with CUDA. Hypre cuda build is also supported using
`--with-cuda-hypre`. `--cuda-arch` can be used to specify cuda compute capablility.
(See table in https://en.wikipedia.org/wiki/CUDA#Supported_GPUs)

CUDA needs to be installed separately and nvcc must be found in PATH ([Example](https://github.com/mfem/PyMFEM/blob/e1466a6a/.github/workflows/build-and-test-callable.yml#L111-L122)).

(examples)
```shell
python setup.py install --with-cuda

python setup.py install --with-cuda --with-cuda-hypre

python setup.py install --with-cuda --with-cuda-hypre --cuda-arch=80 (A100)

python setup.py install --with-cuda --with-cuda-hypre --cuda-arch=75 (Turing)
```

### gslib
`--with-gslib` : build MFEM with [GSlib](https://github.com/Nek5000/gslib)

Note: this option downloads and builds GSlib

### libCEED
`--with-libceed` : build MFEM with [libCEED](https://github.com/CEED/libCEED)

Note: this option downloads and builds libCEED

### Specifying compilers
| Flag | Description |
|------|--------|
| `--CC` | c compiler |
| `--CXX` | c++ compiler |
| `--MPICC` | mpic compiler |
| `--MPICXX` | mpic++ compiler |

(example)
Using Intel compiler
```shell
python setup.py install --with-parallel --CC=icc, --CXX=icpc, --MPICC=mpiicc, --MPICXX=mpiicpc
```

### Building MFEM with specific version
By default, setup.py build MFEM with specific SHA (which is usually the released latest version).
In order to use the latest MFEM in Github. One can specify the branch name or SHA using mfem-branch
option.

`--mfem-branch = <branch name or SHA>`

(example)
```shell
python setup.py install --mfem-branch=master
```

### Using MFEM build externally.
These options are used to link PyMFEM wrapper with existing MFEM library. We need `--mfem-source`
and `--mfem-prefix`

| Flag | Description |
|----------------------------|-------------------------------------------------------------------|
| `--mfem-source <location>` | The location of MFEM source used to build MFEM |
| `--mfem-prefix <location>` | The location of the MFEM library. `libmfem.so` needs to be found in `<location>/lib` |
| `--mfems-prefix <location>`| (optional) Specify serial MFEM location separately |
| `--mfemp-prefix <location>`| (optional) Specify parallel MFEM location separately |


### Blas and Lapack
--with-lapack : build MFEM with lapack

`<location>` is used for CMAKE call to buid MFEM
`--blas-libraries=<location>`
`--lapack-libraries=<location>`

### Options for development and testing
| Flag | Description |
|------|--------|
| `--swig` | run swig only |
| `--skip-swig` | build without running swig` |
| `--skip-ext` | skip building external libraries.|
| `--ext-only` | build exteranl libraries and exit.|

During the development, often we update depenencies (such as MFEM) and edit `*.i` file.


First clean everything.

```shell
python setup.py clean --all
```

Then, build externals alone
```shell
python setup.py install --with-parallel --ext-only --mfem-branch=master
```

Then, genrate swig wrappers.
```shell
python setup.py install --with-parallel --swig --mfem-branch=master
```

If you are not happy with the wrapper (`*.cxx` and `*.py`), you edit `*.i` and redo
the same. When you are happy, build the wrapper. `--swig` does not clean the
existing wrapper. So, it will only update wrapper for updated `*.i`

When building a wrapper, you can use `--skip-ext` option. By default, it will re-run
swig to generate entire wrapper codes.
```shell
python setup.py install --with-parallel --skip-ext --mfem-branch=master
```

If you are sure, you could use `--skip-swig` option, so that it compiles the wrapper
codes without re-generating it.
```shell
python setup.py install --with-parallel --skip-ext --skip-swig --mfem-branch=master
```

### Other options
`--unverifiedSSL` :
This addresses error relating SSL certificate. Typical error message is
`<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:xxx)>`


65 changes: 35 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ By default, "pip install mfem" downloads and builds the serial version of MFEM a
Additionally, the installer supports building MFEM with specific options together with other external libraries, including MPI version.

## Install
```bash
```shell
pip install mfem # binary install is available only on linux platforms (Py36-310)
pip install mfem --no-binary mfem # install serial MFEM + wrapper from source

Expand All @@ -24,12 +24,12 @@ and build parallel version of MFEM library (linked with Metis and Hypre)
and installs under <prefix>/mfem. See also, docs/install.txt

### Using pip
```bash
$ pip install mfem --install-option="--with-parallel"
```shell
pip install mfem --install-option="--with-parallel"
```

### Build from local source file
```python
```shell
# Download source and build
$ pip download mfem --no-binary mfem (expand tar.gz file and move to the downloaded directory)
or clone this repository
Expand Down Expand Up @@ -59,75 +59,80 @@ $ python setup.py install --help
```

## Usage
Here is an example to solve div(alpha grad(u)) = f in a square and to plot the result
with matplotlib (modified from ex1.cpp). Use the badge above to open this in Binder.
This example (modified from `ex1.cpp`) solves the Poisson equation,
$$\nabla \cdot (\alpha \nabla u) = f$$
in a square and plots the result using matplotlib.
Use the badge above to open this in Binder.

```python
import mfem.ser as mfem

# create sample mesh for square shape
# Create a square mesh
mesh = mfem.Mesh(10, 10, "TRIANGLE")

# create finite element function space
# Define the finite element function space
fec = mfem.H1_FECollection(1, mesh.Dimension()) # H1 order=1
fespace = mfem.FiniteElementSpace(mesh, fec)

#
# Define the essential dofs
ess_tdof_list = mfem.intArray()
ess_bdr = mfem.intArray([1]*mesh.bdr_attributes.Size())
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list)

# constant coefficient (diffusion coefficient and RHS)
# Define constants for alpha (diffusion coefficient) and f (RHS)
alpha = mfem.ConstantCoefficient(1.0)
rhs = mfem.ConstantCoefficient(1.0)

# Note:
# Diffusion coefficient can be variable. To use numba-JIT compiled
# functio. Use the following, where x is numpy-like array.
# @mfem.jit.scalar
# def alpha(x):
# return x+1.0
#
"""
Note
-----
In order to represent a variable diffusion coefficient, you
must use a numba-JIT compiled function. For example:
# define Bilinear and Linear operator
>>> @mfem.jit.scalar
>>> def alpha(x):
>>> return x+1.0
"""

# Define the bilinear and linear operators
a = mfem.BilinearForm(fespace)
a.AddDomainIntegrator(mfem.DiffusionIntegrator(alpha))
a.Assemble()
b = mfem.LinearForm(fespace)
b.AddDomainIntegrator(mfem.DomainLFIntegrator(rhs))
b.Assemble()

# create gridfunction, which is where the solution vector is stored
x = mfem.GridFunction(fespace);
# Initialize a gridfunction to store the solution vector
x = mfem.GridFunction(fespace)
x.Assign(0.0)

# form linear equation (AX=B)
# Form the linear system of equations (AX=B)
A = mfem.OperatorPtr()
B = mfem.Vector()
X = mfem.Vector()
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B)
print("Size of linear system: " + str(A.Height()))

# solve it using PCG solver and store the solution to x
# Solve the linear system using PCG and store the solution in x
AA = mfem.OperatorHandle2SparseMatrix(A)
M = mfem.GSSmoother(AA)
mfem.PCG(AA, M, B, X, 1, 200, 1e-12, 0.0)
a.RecoverFEMSolution(X, b, x)

# extract vertices and solution as numpy array
# Extract vertices and solution as numpy arrays
verts = mesh.GetVertexArray()
sol = x.GetDataArray()

# plot solution using Matplotlib

# Plot the solution using matplotlib
import matplotlib.pyplot as plt
import matplotlib.tri as tri

triang = tri.Triangulation(verts[:,0], verts[:,1])

fig1, ax1 = plt.subplots()
ax1.set_aspect('equal')
tpc = ax1.tripcolor(triang, sol, shading='gouraud')
fig1.colorbar(tpc)
fig, ax = plt.subplots()
ax.set_aspect('equal')
tpc = ax.tripcolor(triang, sol, shading='gouraud')
fig.colorbar(tpc)
plt.show()
```
![](https://raw.githubusercontent.com/mfem/PyMFEM/master/docs/example_image.png)
Expand Down
Loading

0 comments on commit 3e68b55

Please sign in to comment.