diff --git a/.style.yapf b/.style.yapf index 2897013..6e0fe0c 100644 --- a/.style.yapf +++ b/.style.yapf @@ -1,3 +1,4 @@ [style] based_on_style = pep8 -blank_line_before_nested_class_or_def = true \ No newline at end of file +blank_line_before_nested_class_or_def = true +blank_line_before_module_docstring = true \ No newline at end of file diff --git a/README.md b/README.md index 1d97bdf..067963b 100644 --- a/README.md +++ b/README.md @@ -1,263 +1,265 @@ Tamaas --- A high-performance library for periodic rough surface contact ======================================================================== +[![JOSS](https://joss.theoj.org/papers/10.21105/joss.02121/status.svg)](https://doi.org/10.21105/joss.02121) +[![Documentation Status](https://readthedocs.org/projects/tamaas/badge/?version=latest)](https://tamaas.readthedocs.io/en/latest/?badge=latest) +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gl/tamaas%2Ftutorials/HEAD) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3479236.svg)](https://doi.org/10.5281/zenodo.3479236) + Tamaas is a C++/Python library that implements a number of numerical methods based on integral equations to efficiently solve contact problems with rough surfaces. The word تماس (tamaas) means "contact" in Arabic and Farsi. ## Quick Start -If you have a Linux system, you can simply run `pip(3) install tamaas`. Note +If you have a Linux system, you can simply run `pip3 install tamaas`. Note however that there due to compatibility reasons, this version of Tamaas is not built with parallel/multi-threading capabilities. So if you want parallelism, or encounter an issue with the [PyPI package](https://pypi.org/project/tamaas/), please compile from source. You can also use one of our [interactive tutorial notebooks](https://tamaas.readthedocs.io/en/latest/overview.html#tutorials) to get started. ## Dependencies Here is a list of dependencies to compile Tamaas: - a C++ compiler with full C++14 and OpenMP support - [SCons](https://scons.org/) (python build system) - [FFTW3](http://www.fftw.org/) - [boost](https://www.boost.org/) (preprocessor) - [thrust](https://github.com/thrust/thrust) (1.9.2+) - [python 3+](https://www.python.org/) with [numpy](https://numpy.org/) - [pybind11](https://github.com/pybind/pybind11) Optional dependencies are: - an MPI implementation - [FFTW3](http://www.fftw.org/) with MPI/pthreads/OpenMP support - [scipy](https://scipy.org) (for nonlinear solvers) - [uvw](https://pypi.org/project/uvw/), [netCDF4](https://unidata.github.io/netcdf4-python/netCDF4/index.html#section1), [h5py](https://www.h5py.org/) (for various dumpers) - [googletest](https://github.com/google/googletest) and [pytest](https://docs.pytest.org/en/latest/) (for tests) - [Doxygen](http://doxygen.nl/) and [Sphinx](https://www.sphinx-doc.org/en/stable/) (for documentation) Note that a Debian distribution should have the right packages for all these dependencies (they package the right version of thrust extracted from CUDA in `stretch-backports non-free` and `buster non-free`). ## Compiling Here are the instructions to compile Tamaas. Note that we provide a [Docker image](#using-docker-image) and a [PyPI package](https://pypi.org/project/tamaas/) that do not require compiling. ### Installing Dependencies On Debian-based systems, mandatory dependencies can be installed with the following command: apt install \ g++ \ libboost-dev \ libthrust-dev \ libfftw3-dev \ pybind11-dev \ python3-dev \ python3-numpy \ scons Additionally, to build and run tests, one needs to install: apt install \ libgtest-dev \ python3-pytest For documentation: apt install \ doxygen \ python3-sphinx \ python3-breathe \ python3-sphinx-rtd-theme ### Build System The build system uses SCons. In order to compile Tamaas with the default options (i.e. optimized release build with python bindings + OpenMP): scons After compiling a first time (or running `scons -h` if you want to avoid compiling), you can edit the compilation options in the file `build-setup.conf`, or alternatively supply the options directly in the command line: scons option=value [...] To get a list of *all* build options and their possible values, you can run `scons -h`. You can run `scons -H` to see the SCons-specific options (among them `-j n` executes the build with `n` threads and `-c` cleans the build). Note that the build is aware of the `CXX` and `CXXFLAGS` environment variables. ## Installing Before you can import tamaas in python, you need to install the python package in some way. ### Using pip You have two choices to install tamaas: - An out-of-repository installation to a given prefix (e.g. `/usr/local`, or a python virtual environment) - A development installation to `~/.local` which links to the build directory The former is simply achieved with: scons prefix=/your/prefix install # Equivalent to (if you build in release) install build-release/src/libTamaas.so* /your/prefix/lib pip3 install --prefix /your/prefix build-release/python The compiled parts of the python module should automatically know where to find the Tamaas shared library, so no need to tinker with `LD_LIBRARY_PATH`. The second installation choice is equally simple: scons dev # Equivalent to pip3 install --user -e build-release/python You can check that everything is working fine with: python3 -c 'import tamaas; print(tamaas)' ### Using environment variables (not recommended) You can source (e.g. in your `~/.bashrc` file) the file `build-release/tamaas_environment.sh` to modify the `PYTHONPATH` and `LD_LIBRARY_PATH` environment variables. This is however not recommended because these variables may conflict in a python virtual environment (i.e. if you use `virtualenv` with tamaas). ### Using Docker image Tamaas provides a `Dockerfile` you can use to compile and deploy Tamaas in a tested environment. Simply run `docker build -t tamaas .` in the root folder of the repository. Check the documentation to see which build options can be adjusted. ## Tests To run tests, make sure to have [pytest](https://docs.pytest.org/en/latest/) installed and run `scons test` if you have compiled Tamaas with tests activated (`scons build_tests=True`). ## Documentation The latest documentation is available on [ReadTheDocs](https://tamaas.readthedocs.io/en/latest/)! It contains detailed guides on the different components of Tamaas as well as a combined C++ and Python API documentation. You can also build the documentation locally: activate the `build_doc` option and run `scons doc`. Make sure you have [sphinx-rtd-theme](https://pypi.org/project/sphinx-rtd-theme/) and [breathe](https://pypi.org/project/breathe/) installed. The compiled indexes for the doxygen C++ API and Sphinx documentation can be found in -`doc/build/{doxygen,sphinx}/html/index.html`. Beware however that manually -compiling documentation leads to a lot of warnings. +`doc/build/{doxygen,sphinx}/html/index.html`. ## Examples -Example simulations can be found in the `examples/` directory. There is no -guarantee that the examples in `examples/legacy/` all work however. +Example simulations can be found in the `examples/` directory. These simulations +can be run in MPI. - `rough_contact.py` shows a typical normal rough contact simulation - `adhesion.py` shows how you can derive some classes from Tamaas in python, here to implement a custom adhesion potential - `plasticity.py` computes an elastoplastic Hertz simulation and dumps the result in `examples/paraview/` in VTK format - `stresses.py` shows how you can compute stresses from a boundary traction distribution -- the scripts in `pipe_tools` allow to execute elastic contact simulations - without the need to code a custom script (see documentation for more details) ## Command-line Interface The Tamaas python module exposes a `tamaas` command with three subcommands: - `tamaas surface` generates rough surfaces - `tamaas contact` solves elastic contact - `tamaas plot` plots contact pressure and displacement See `tamaas --help` for command line arguments. ## Contributing Contributions to Tamaas are welcome! Please follow the guidelines below. ### Report an issue If you have an account on [gitlab](https://gitlab.com), you can [submit an issue](https://gitlab.com/tamaas/tamaas/-/issues/new). The full list of issues is available [here](https://gitlab.com/tamaas/tamaas/-/issues). ### Submit a patch / merge-request Follow [this guide](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html#new-merge-request-from-a-fork) to create a merge request on GitLab. Please target the repository's `master` branch. ## Citing Tamaas is the result of a science research project. To give proper credit to Tamaas and the researchers who have developed the numerical methods that it implements, please cite Tamaas as: Frérot , L., Anciaux, G., Rey, V., Pham-Ba, S., & Molinari, J.-F. Tamaas: a library for elastic-plastic contact of periodic rough surfaces. Journal of Open Source Software, 5(51), 2121 (2020). [doi:10.21105/joss.02121](https://doi.org/10.21105/joss.02121) The paper above details relevant references for the different features of Tamaas. In particular, if you use the elastic-plastic contact capabilities of Tamaas, please cite: Frérot, L., Bonnet, M., Molinari, J.-F. & Anciaux, G. A Fourier-accelerated volume integral method for elastoplastic contact. Computer Methods in Applied Mechanics and Engineering 351, 951–976 (2019) [doi:10.1016/j.cma.2019.04.006](https://doi.org/10.1016/j.cma.2019.04.006). If you use the adhesive contact capabilities of Tamaas, please cite: Rey, V., Anciaux, G. & Molinari, J.-F. Normal adhesive contact on rough surfaces: efficient algorithm for FFT-based BEM resolution. Comput Mech 1–13 (2017) [doi:10.1007/s00466-017-1392-5](https://doi.org/10.1007/s00466-017-1392-5). For an (almost) exhaustive list of publications, insert the following code snippet at the end of your python scripts: ```python from tamaas.utils import publications publications() ``` ## Changelog The changelog can be consulted [here](https://gitlab.com/tamaas/tamaas/-/blob/master/CHANGELOG.md). ## Funding Tamaas' development was funded by the [Swiss National Science Foundation](https://www.snf.ch), grants [162569 ("Contact mechanics of rough surfaces")](https://p3.snf.ch/Project-162569) and [191720 ("Tribology of Polymers: from Atomistic to Continuum Scales")](https://p3.snf.ch/project-191720). ## License Tamaas is distributed under the terms of the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl.html). diff --git a/python/setup.py.in b/python/setup.py.in index ce0aa1b..bcb8030 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -1,112 +1,113 @@ # -*- mode:python; coding: utf-8 -*- import setuptools import shutil import sysconfig import os long_description = """ # Tamaas - A high-performance library for periodic rough surface contact [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3479236.svg)](https://doi.org/10.5281/zenodo.3479236) [![status](https://joss.theoj.org/papers/86903c51f3c66964eef7776d8aeaf17d/status.svg)](https://joss.theoj.org/papers/86903c51f3c66964eef7776d8aeaf17d) [![Documentation Status](https://readthedocs.org/projects/tamaas/badge/?version=latest)](https://tamaas.readthedocs.io/en/latest/?badge=latest) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gl/tamaas%2Ftutorials/HEAD) Tamaas (from تماس meaning “contact” in Arabic and Farsi) is a high-performance rough-surface periodic contact code based on boundary and volume integral equations. The clever mathematical formulation of the underlying numerical methods allows the use of the fast-Fourier Transform, a great help in achieving peak performance: Tamaas is consistently two orders of magnitude faster (and lighter) than traditional FEM! Tamaas is aimed at researchers and practitioners wishing to compute realistic contact solutions for the study of interface phenomena. ## Disclaimer This package is intended for ease of installation for Linux platforms, but comes with NO WARRANTY of compatibility (although it is manylinux2010_x86_64 compliant). If you experience any issue, please install Tamaas from [source](https://gitlab.com/tamaas/tamaas). We provide a Docker image for non-Linux systems. Note that the version of Tamaas provided by this package is not parallel. This version of Tamaas is statically linked to [FFTW3](http://fftw.org/) developed by Matteo Frigo and Steven G. Johnson, released under the terms of the GPL public license ([source code](https://github.com/FFTW/fftw3)). Tamaas is the result of a science research project. To give proper credit to Tamaas and the researchers who have developed the numerical methods that it implements, please cite the [JOSS paper](https://joss.theoj.org/papers/86903c51f3c66964eef7776d8aeaf17d) and the appropriate references therein. ## Dependencies Essentials: - Numpy Optional: - Scipy (for non-linear solvers) - UVW (for dumpers) - h5py (for dumpers) - netCDF4 (for dumpers) To install with all dependencies, run ``pip install tamaas[all]``. ## Documentation Documentation can be found on [tamaas.readthedocs.io](https://tamaas.readthedocs.io/en/latest/). ## Changelog The changelog can be consulted [here](https://gitlab.com/tamaas/tamaas/-/blob/master/CHANGELOG.md). """ try: shutil.copyfile('../../README.md', 'README.md') except FileNotFoundError: pass setuptools.setup( name="tamaas", version="@version@", - packages=setuptools.find_packages(), include_package_data=True, author=', '.join(@authors@), author_email="@email@", description='@description@', long_description=long_description, long_description_content_type="text/markdown", url="https://gitlab.com/tamaas", project_urls={ "Bug Tracker": "https://gitlab.com/tamaas/tamaas/-/issues", "Documentation": "https://tamaas.readthedocs.io/en/latest/", "Source Code": "https://gitlab.com/tamaas/tamaas", + "Changes": + "https://gitlab.com/tamaas/tamaas/-/blob/master/CHANGELOG.md", }, platforms=['Linux'], install_requires=['numpy'], entry_points={ "console_scripts": ['tamaas = tamaas.__main__:main'], }, extras_require={ "all": ['uvw', 'h5py', 'netCDF4', 'scipy', 'mpi4py'], "dumpers": ['uvw', 'h5py', 'netCDF4'], "solvers": ['scipy'], "mpi": ['mpi4py'], }, classifiers=[ "Intended Audience :: Science/Research", "License :: OSI Approved :: GNU Affero General Public License v3", "Programming Language :: C++", "Programming Language :: Python :: 3", "Topic :: Scientific/Engineering", "Intended Audience :: Science/Research", "Operating System :: POSIX :: Linux", - ] + ], ) diff --git a/python/tamaas/utils.py b/python/tamaas/utils.py index 3a174d3..0315b58 100644 --- a/python/tamaas/utils.py +++ b/python/tamaas/utils.py @@ -1,305 +1,294 @@ # -*- mode: python; coding: utf-8 -*- # vim: set ft=python: # # Copyright (©) 2016-2022 EPFL (École Polytechnique Fédérale de Lausanne), # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . """Convenience utilities.""" import inspect from collections import namedtuple from contextlib import contextmanager from typing import Iterable, Union from functools import partial from operator import contains import numpy as np from . import ( ContactSolver, Model, SurfaceGenerator1D, SurfaceGenerator2D, dtype, set_log_level, get_log_level, LogLevel, Logger, ) - __all__ = [ "log_context", "publications", "load_path", "seeded_surfaces", "hertz_surface", ] class NoConvergenceError(RuntimeError): """Convergence not reached exception.""" @contextmanager def log_context(log_level: LogLevel): """Context manager to easily control Tamaas' logging level.""" current = get_log_level() set_log_level(log_level) try: yield finally: set_log_level(current) def publications(format_str="{pub.citation}\n\t{pub.doi}"): """Print publications associated with objects in use.""" Publication = namedtuple("Publication", ["citation", "doi"]) joss = Publication( citation=( "Frérot, L., Anciaux, G., Rey, V., Pham-Ba, S. & Molinari, J.-F." " Tamaas: a library for elastic-plastic contact of periodic rough" - " surfaces. Journal of Open Source Software 5, 2121 (2020)." - ), + " surfaces. Journal of Open Source Software 5, 2121 (2020)."), doi="10.21105/joss.02121", ) + zenodo = Puclication( + citation=( + "Frérot, Lucas, Anciaux, Guillaume, Rey, Valentine, Pham-Ba, Son, " + "& Molinari, Jean-François. (2022). Tamaas, a high-performance " + "library for periodic rough surface contact (2.4.0). Zenodo."), + doi="10.5281/zenodo.3479236", + ) + _publications = { k: v for keys, v in [ ( ( "SurfaceGeneratorRandomPhase1D", "SurfaceGeneratorRandomPhase2D", ), [ Publication( citation=( "Wu, J.-J. Simulation of rough surfaces with FFT." - " Tribology International 33, 47–58 (2000)." - ), + " Tribology International 33, 47–58 (2000)."), doi="10.1016/S0301-679X(00)00016-5", ), ], ), ( ("SurfaceGeneratorFilter1D", "SurfaceGeneratorFilter2D"), [ Publication( citation=( "Hu, Y. Z. & Tonder, K. Simulation of 3-D random" " rough surface by 2-D digital filter and fourier" " analysis. International Journal of Machine Tools" - " and Manufacture 32, 83–90 (1992)." - ), + " and Manufacture 32, 83–90 (1992)."), doi="10.1016/0890-6955(92)90064-N", ), ], ), ( - ("PolonskyKeerRey",), + ("PolonskyKeerRey", ), [ Publication( citation=( "Polonsky, I. A. & Keer, L. M. A numerical method" " for solving rough contact problems based on the" " multi-level multi-summation and conjugate" - " gradient techniques. Wear 231, 206–219 (1999)." - ), + " gradient techniques. Wear 231, 206–219 (1999)."), doi="10.1016/S0043-1648(99)00113-1", ), Publication( citation=( "Rey, V., Anciaux, G. & Molinari, J.-F. Normal" " adhesive contact on rough surfaces: efficient" " algorithm for FFT-based BEM resolution. Comput" - " Mech 1–13 (2017)." - ), + " Mech 1–13 (2017)."), doi="10.1007/s00466-017-1392-5", ), ], ), ( ("DFSANESolver", "DFSANECXXSolver"), [ Publication( citation=( "La Cruz, W., Martínez, J. & Raydan, M. Spectral" " residual method without gradient information for" " solving large-scale nonlinear systems of" - " equations. Math. Comp. 75, 1429–1448 (2006)." - ), + " equations. Math. Comp. 75, 1429–1448 (2006)."), doi="10.1090/S0025-5718-06-01840-0", ), ], ), ( - ("Residual",), + ("Residual", ), [ Publication( - citation=( - "Frérot, L., Bonnet, M., Molinari, J.-F. &" - " Anciaux, G. A Fourier-accelerated volume" - " integral method for elastoplastic contact." - " Computer Methods in Applied Mechanics and" - " Engineering 351, 951–976 (2019)." - ), + citation=("Frérot, L., Bonnet, M., Molinari, J.-F. &" + " Anciaux, G. A Fourier-accelerated volume" + " integral method for elastoplastic contact." + " Computer Methods in Applied Mechanics and" + " Engineering 351, 951–976 (2019)."), doi="10.1016/j.cma.2019.04.006", ), ], ), ( - ("EPICSolver",), + ("EPICSolver", ), [ Publication( - citation=( - "Frérot, L., Bonnet, M., Molinari, J.-F. &" - " Anciaux, G. A Fourier-accelerated volume" - " integral method for elastoplastic contact." - " Computer Methods in Applied Mechanics and" - " Engineering 351, 951–976 (2019)." - ), + citation=("Frérot, L., Bonnet, M., Molinari, J.-F. &" + " Anciaux, G. A Fourier-accelerated volume" + " integral method for elastoplastic contact." + " Computer Methods in Applied Mechanics and" + " Engineering 351, 951–976 (2019)."), doi="10.1016/j.cma.2019.04.006", ), Publication( citation=( "Jacq, C., Nélias, D., Lormand, G. & Girodin, D." " Development of a Three-Dimensional" " Semi-Analytical Elastic-Plastic Contact Code." - " Journal of Tribology 124, 653 (2002)." - ), + " Journal of Tribology 124, 653 (2002)."), doi="10.1115/1.1467920", ), ], ), ( - ("Condat",), + ("Condat", ), [ Publication( citation=( "Condat, L. A Primal–Dual Splitting Method for" " Convex Optimization Involving Lipschitzian," " Proximable and Linear Composite Terms. J Optim" - " Theory Appl 158, 460–479 (2012)." - ), + " Theory Appl 158, 460–479 (2012)."), doi="10.1007/s10957-012-0245-9", ), ], ), ( - ( - "KatoSaturated", - ), + ("KatoSaturated", ), [ Publication( citation=( "Stanley, H. M. & Kato, T. An FFT-Based Method for" " Rough Surface Contact. J. Tribol 119, 481–485" - " (1997)." - ), + " (1997)."), doi="10.1115/1.2833523", ), Publication( citation=( "Almqvist, A., Sahlin, F., Larsson, R. &" " Glavatskih, S. On the dry elasto-plastic contact" " of nominally flat surfaces. Tribology" - " International 40, 574–579 (2007)." - ), + " International 40, 574–579 (2007)."), doi="10.1016/j.triboint.2005.11.008", ), ], ), - ] - for k in keys + ] for k in keys } caller_globals = inspect.stack()[1][0].f_globals citable = filter( partial(contains, _publications.keys()), map(lambda x: type(x).__name__, caller_globals.values()), ) - citable = [joss] + list({pub for k in citable for pub in _publications[k]}) + citable = [joss, zenodo] \ + + list({pub for k in citable for pub in _publications[k]}) msg = "Please cite the following publications:\n\n" msg += "\n".join(format_str.format(pub=pub) for pub in citable) Logger().get(LogLevel.info) << msg return citable def load_path( solver: ContactSolver, loads: Iterable[Union[float, np.ndarray]], verbose: bool = False, callback=None, ) -> Iterable[Model]: """ Generate model objects solutions for a sequence of applied loads. :param solver: a contact solver object :param loads: an iterable sequence of loads :param verbose: print info output of solver :param callback: a callback executed after the yield """ log_level = LogLevel.info if verbose else LogLevel.warning with log_context(log_level): for load in loads: if solver.solve(load) > solver.tolerance: raise NoConvergenceError("Solver error exceeded tolerance") yield solver.model if callback is not None: callback() def seeded_surfaces( generator: Union[SurfaceGenerator1D, SurfaceGenerator2D], seeds: Iterable[int], ) -> Iterable[np.ndarray]: """ Generate rough surfaces with a prescribed seed sequence. :param generator: surface generator object :param seeds: random seed sequence """ for seed in seeds: generator.random_seed = seed yield generator.buildSurface() -def hertz_surface( - system_size: Iterable[float], shape: Iterable[int], radius: float -) -> np.ndarray: +def hertz_surface(system_size: Iterable[float], shape: Iterable[int], + radius: float) -> np.ndarray: """ Construct a parabolic surface. :param system_size: size of the domain in each direction :param shape: number of points in each direction :param radius: radius of surface """ coords = map( lambda L, N: np.linspace(0, L, N, endpoint=False, dtype=dtype), system_size, shape, ) coords = np.meshgrid(*coords, "ij", sparse=True) surface = (-1 / (2 * radius)) * sum( - (x - L / 2) ** 2 for x, L in zip(coords, system_size) - ) + (x - L / 2)**2 for x, L in zip(coords, system_size)) return surface