Skip to content

Commit

Permalink
Add new solvers to the sparse solver in ProblemBase
Browse files Browse the repository at this point in the history
Update doc (install procedure)
Update conda recipe (remove architecture specificities and solvers in dependencies)
  • Loading branch information
pruliere committed Oct 20, 2023
1 parent 2c04e88 commit 1e85887
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 35 deletions.
8 changes: 3 additions & 5 deletions conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@ source:
git_url: https://github.com/3MAH/fedoo.git

build:
number: 0
noarch: python
script: pip install .

requirements:
host:
- python # [build_platform != target_platform]
- cross-python_{{ target_platform }} # [build_platform != target_platform]
- python
- pip
run:
- python>=3.8
- numpy>=1.22.4
- scipy
- pypardiso # [x86 or x86_64]
- scikit-umfpack # [(not x86) and (not x86_64)]
- vtk>=9.2
- pyvista>=0.39
- simcoon
Expand Down
39 changes: 31 additions & 8 deletions docs/Install.rst
Original file line number Diff line number Diff line change
@@ -1,29 +1,52 @@
Installation
=================================

Installation using conda with recommanded dependencices (including simcoon):
Minimal installation with pip:

.. code-block:: none
$ conda install -c conda-forge -c set3mah fedoo
$ pip install fedoo
Installation using pip including recommanded dependencies (except simcoon):
Installation using conda:

.. code-block:: none
$ pip install fedoo[all]
$ conda install -c conda-forge -c set3mah fedoo
The only required dependencies that are automatically installed with fedoo are:

* `Numpy<https://numpy.org/`_

* `Scipy<https://scipy.org/`_ mainly for sparse matrices.

Minimal installation with pip:
In addition, the conda package also includes some recommanded dependencies:

.. code-block:: none
* `Simcoon<https://simcoon.readthedocs.io/en/latest/`_: brings a lot of features (finite strain, non-linear constitutive laws, ...).

$ pip install fedoo
* `PyVista<https://docs.pyvista.org/version/stable/>`_ for results visulisation and
mesh utils.

It is highly recommanded to also install a fast direct sparse matrix solver
to improve performance :

* `Pypardiso<https://pypi.org/project/pypardiso/`_ for intel processors (binding to the pardiso solver)

* `Scikit-umfpack<https://scikit-umfpack.github.io/scikit-umfpack/>`_


It is also possible to install fedoo with all recommanded dependencies (except simcoon)
in one line. However this installation needs to be done carefully because of potentiel
version compatibility problems.

.. code-block:: none
$ pip install fedoo[all]
A lot of features (finite strain, non-linear constitutive laws, ...) requires the installation of simcoon.
Simcoon is available on conda only To install simcoon:
Simcoon is available on conda only and can be installed with:

.. code-block:: none
Expand Down
2 changes: 2 additions & 0 deletions example/homogenization/periodic_homogenization.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
# # from simcoon import simmit as sim
# # print(sim.L_iso_props(L_eff)) #to check material properties

assert 0

import matplotlib.pyplot as plt

from matplotlib import cm, colors
Expand Down
78 changes: 57 additions & 21 deletions fedoo/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
try:
from pypardiso import spsolve
USE_PYPARDISO = True
except:
except:
USE_PYPARDISO = False
try:
from scikits import umfpack
except:
print('WARNING: no fast direct sparse solver has been found. Consider installing pypardiso or scikit-umfpack to improve computation performance')


#=============================================================
Expand Down Expand Up @@ -230,6 +234,8 @@ def __init__(self, name = "", space = None):
space = ModelingSpace.get_active()
self.__space = space

self.set_solver() #initialize solver properties

self.make_active()


Expand Down Expand Up @@ -274,38 +280,68 @@ def get_active():
return ProblemBase.active


def set_solver(self, solver: str, tol: float = 1e-5, precond: bool = True):
def set_solver(self, solver: str='direct', precond: bool=True, **kargs): #tol: float = 1e-5, precond: bool = True):
"""Define the solver for the linear system resolution.
Parameters
---------------
solver: str
Type of solver.
The possible choice are :
* 'direct': direct solver based on the function scipy.sparse.linalg.spsolve
* 'cg': conjugate gradient based on the function scipy.sparse.linalg.cg
tol: float
Convergence tolerance for conjugate gradient method (default = 1e-5).
This parameters is not used for direct solver.
precond: bool
use precond = False to desactivate the diagonal matrix preconditionning
in the conjugate gradient method (default precond=True).
* 'direct': direct solver. If pypardiso is installed, the pypardiso solver is used.
If not, the function scipy.sparse.linalg.spsolve is used instead.
If sckikit-umfpack is installed, scipy will use the umfpack solver which is significantly
more efficient than the base scipy solver.
* 'cg', 'bicg', 'bicgstab','minres','gmres', 'lgmres' or 'gcrotmk' using the corresponding
iterative method from scipy.sparse.linalg. For instance, 'cg' is the conjugate gradient based on
the function scipy.sparse.linalg.cg
* 'pardiso': force the use of the pypardiso solver
* 'direct_scipy': force the use of the direct scipy solver (umfpack if installed)
* function:
A user spsolve function that should have the signature res = solver(A,B,**kargs)
where A is a scipy sparse matrix and B a 1d numpy array. kargs may contains
optional parameters.
precond: bool, default = True
use precond = False to desactivate the diagonal matrix preconditionning.
Only used for iterative method.
"""
self.__solver = [solver.lower(), tol, precond]
return_info = False
if isinstance(solver, str):
if solver == 'direct':
if USE_PYPARDISO:
solver_func = spsolve
else:
solver_func = sparse.linalg.spsolve
elif solver in ['cg', 'bicg', 'bicgstab','minres','gmres', 'lgmres', 'gcrotmk']: #use scipy solver
solver_func = eval('sparse.linalg.'+solver)
return_info = True
elif solver == 'pardiso':
if USE_PYPARDISO:
solver_func = spsolve
else:
raise NameError('pypardiso not installed. Use "pip install pypardiso".')
elif solver == 'direct_scipy':
solver_func = sparse.linalg.spsolve
else:
raise NameError('Choosen solver not available')
else: #assume solver is a function
solver_func = solver

self.__solver = [solver, solver_func, kargs, return_info, precond]


def _solve(self, A, B):
if self.__solver[0] == 'direct':
if USE_PYPARDISO == True:
return spsolve(A,B)
kargs = self.__solver[2]
if self.__solver[3]: #return_info = True
if self.__solver[4] and 'M' not in kargs: #precond
Mprecond = sparse.diags(1/A.diagonal(), 0)
res, info = self.__solver[1](A,B, M=Mprecond, **kargs)
else:
return sparse.linalg.spsolve(A,B)
elif self.__solver[0] == 'cg':
if self.__solver[2] == True: Mprecond = sparse.diags(1/A.diagonal(), 0)
else: Mprecond = None
res, info = sparse.linalg.cg(A,B, tol=self.__solver[1], M=Mprecond)
if info > 0: print('Warning: CG convergence to tolerance not achieved')
res, info = self.__solver[1](A,B, **kargs)
if info > 0: print(f'Warning: {self.__solver[0]} solver convergence to tolerance not achieved')
return res
else:
return self.__solver[1](A,B, **kargs)


@staticmethod
Expand All @@ -316,7 +352,7 @@ def get_all():
@property
def solver(self):
"""Return the current solver used for the problem."""
return self.__solver[0]
return self.__solver[1]



Expand Down
2 changes: 1 addition & 1 deletion fedoo/mesh/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@

from .importmesh import import_file, import_vtk, import_msh

from .functions import extrude, extract_surface
from .functions import extrude, extract_surface, change_elm_type

0 comments on commit 1e85887

Please sign in to comment.