Skip to content

Commit

Permalink
Docs (#6)
Browse files Browse the repository at this point in the history
* Add docs

* Add readthedocs

* Update readthedocs

* Update readthedocs

* Empty commit to trigger doc rebuild

* Update ci to build docs

* Use https for modules

* Update readthedocs

* workaround for RTD not setting CONDA_PREFIX

* Update README

* Add installation instructions

* Update some docstrings

* Clean up pybind signatures in sphinx

* Update docstring

* Update usage

* Update usage

* Fix README

* Add docstring

* Update docstrings

* Update conf.py

* Update docs

* Update docs

* Update installation

* Change the name of setParameter[Solver] to just setParameters in the python interface
  • Loading branch information
RaulPPelaez authored Apr 30, 2024
1 parent e98d0db commit 8b66ac1
Show file tree
Hide file tree
Showing 21 changed files with 673 additions and 39 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,13 @@ jobs:
python -c "import libMobility"
python -c "from libMobility import DPStokes, PSE, NBody, SelfMobility"
- name: Install docs dependencies
run: |
pip install -r docs/requirements.txt
shell: bash -el {0}

- name: Build Sphinx Documentation
run: |
cd docs
make html
shell: bash -el {0}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ cpp/example
.\#*
temp
*_init_*
*.o
*.o
build
docs/source/generated
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "third_party/uammd"]
path = third_party/uammd
url = git@github.com:/raulppelaez/uammd
url = https://github.com/raulppelaez/uammd
[submodule "third_party/LanczosAlgorithm"]
path = third_party/LanczosAlgorithm
url = git@github.com:Raulppelaez/LanczosAlgorithm
url = https://github.com/Raulppelaez/LanczosAlgorithm
21 changes: 21 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: "2"

submodules:
include: all
recursive: true

build:
os: "ubuntu-22.04"
tools:
python: "mambaforge-22.9"
jobs:
post_create_environment:
- pip install -r docs/requirements.txt
- cmake -DCMAKE_INSTALL_PREFIX=$(which pip | rev | cut -d/ -f3- | rev) . && make -j4 all install

conda:
environment: environment.yml


sphinx:
configuration: docs/source/conf.py
30 changes: 13 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ This repository contains several GPU solvers that can compute the action of the

In particular, given a group of forces, $\boldsymbol{F}$ , acting on a group of positions, $\boldsymbol{X}$, the libMobility solvers can compute:

$$d\boldsymbol{X} = \boldsymbol{\mathcal{M}}\boldsymbol{F} + \text{prefactor}\sqrt{2T\boldsymbol{\mathcal{M}}}d\boldsymbol{W}$$
$$d\boldsymbol{X} = \boldsymbol{\mathcal{M}}\boldsymbol{F}dt + \text{prefactor}\sqrt{2T\boldsymbol{\mathcal{M}}}d\boldsymbol{W}$$

<!--- Donev: The default value for prefactor is 1. Default value should be 0, and in that case the calculation of sqrtW should be omitted and zero returned for efficiency. --->

Where dX are the linear displacements, prefactor is an user provided prefactor and dW is a collection of i.i.d Weinner processes. T is the temperature (really $k_B T$). Finally $\boldsymbol{\mathcal{M}}$ represents the mobility tensor.
Each solver in libMobility allows to compute either the deterministic term, the stochastic term, or both at the same time.
Expand All @@ -18,7 +17,7 @@ Some of the solvers have different functionalities than the others. For instance

## How this repository is organized

The directory **solvers** contains a subfolder for each module. Each module exists on a different git repository (and included here as a submodule). Besides the submodule repo, the folder for each solver contains a wrapper to the afforementioned repository that allows to use it under a common interface.
The directory **solvers** contains a subfolder for each module. The folder for each solver the implementation of the libMobility interface for that solver.
The directory **python** contains the file libMobility.py, which can be imported giving access to all the compiled modules.
The directory **cpp** contains an example usage of the C++ interface to the modules.
The directory **include** contains the C++ base class and utilities used to construct the modules.
Expand All @@ -31,18 +30,17 @@ Each solver provides the following set of functions (called the same in C++ and
* **setParameters[SolverName]([extra parameters])**: Some modules might need special parameters, in these instances this function must also be called. Check the README for each module and its mobility.h file.
* **setPositions(positions)**: Sets the positions to compute the mobility of.
* **Mdot(forces, result)**: Computes the deterministic hydrodynamic displacements, i.e applies the mobility operator.
* **sqrtMdotW(result, prefactor = 1)**: Computes the stochastic displacements and multiplies them by the provided prefactor.
!--- Donev: If prefactor=0 do nothing --->
* **hydrodynamicVelocities(forces = null, torques = null, result, prefactor = 1)**: Equivalent to calling Mdot followed by sqrtMdotW (some algorithms might benefit from doing these operations together, e.g., solvers based on fluctuating hydrodynamics).
!--- Donev: default value of prefactor should be 0. This function is confusing with regards to the torques. NOTE: I only later saw torques were removed from mobility.h... I assume what you mean here is that stochastic increments are only computed for linear velocity, and if torques are provided only the deterministic term is provided? If you mean that M in the case of torques is the combined force-torque mobility, then forces and torques should be in one vector called "applied". There has to be consistency between result and input and cleared up. I have a strong feeling I wrote this comment already but not sure you ever saw it or never looked at my last round of comments. --->
* **sqrtMdotW(result, prefactor = 1)**: Computes the stochastic displacements and multiplies them by the provided prefactor. The computation will be skipped if prefactor is 0.

* **hydrodynamicVelocities(forces = null, result, prefactor = 1)**: Equivalent to calling Mdot followed by sqrtMdotW (some algorithms might benefit from doing these operations together, e.g., solvers based on fluctuating hydrodynamics).

* **clean()**: Cleans any memory allocated by the module. The initialization function must be called again in order to use the module again.
The many examples in this repository offer more insight about the interface and how to use them. See cpp/example.cpp or python/example.py. See solvers/NBody for an example of a module implementation. Even though the algorithm behind it is quite convoluted, the files in this directory are short and simple, since they are only a thin wrapper to the actual algorithm, located under BatchedNBodyRPY there.
The many examples in this repository offer more insight about the interface and how to use them. See cpp/example.cpp or python/example.py.
An equal sign denotes defaults.

### Data format
Positions, forces, torques and the results provided by the functions are packed in a 3*numberParticles contiguos array containing ```[x_1, y_1, z_1, x_2,...z_N]``` .
Positions, forces, and the results provided by the functions are packed in a 3*numberParticles contiguous array containing ```[x_1, y_1, z_1, x_2,...z_N]```.

!--- Donev: This is not clear if both forces and torques are provided as input. What is the format of result? 6*N or 2*3*N? --->

### Parameters
The valid parameters accepted by the interface are:
Expand All @@ -56,15 +54,15 @@ An equal sign denotes default values.

### Configuration parameters
At contruction, solvers must be provided with the following information:
* **periodicityX**, **periodicityY**, **periodicityZ**: The periodicity, can any of "periodic", "open", "single_wall", "two_walls", "unspecified".
* **periodicityX**, **periodicityY**, **periodicityZ**: The periodicity, can be any of "periodic", "open", "single_wall", "two_walls", "unspecified".

The solvers constructor will check the provided configuration and throw an error if something invalid is requested of it (for instance, the PSE solver will complain if open boundaries are chosen).


## How to use this repo
Some solvers might be included as a git submodule (So that each solver has its own, separated, repository). Be sure to clone this repository recursively (using ```git clone --recurse```).
Be sure to clone this repository recursively (using ```git clone --recurse```).

After compilation (see below) you will have all the tools mentioned above available for each solver. Note that it is not required to compile all modules, only the ones you need (so you do not need to worry about dependencies of unused solvers).
After compilation (see below) you will have all the tools mentioned above available for each solver.

## Compilation

Expand Down Expand Up @@ -115,7 +113,7 @@ will provide more in depth information about the solver.

In order to use a module called SolverName, the header solvers/SolverName/mobility.h must be included.
If the module has been compiled correctly the definitions required for the functions in mobility.h will be available at solvers/SolverName/mobility.so.
An example is available in cpp/example.cpp and the accompanying Makefile.
An example is available in cpp/example.cpp.
## Adding a new solver

Solvers must be added following the ```libmobility::Mobility``` directives (see include/MobilityInterface). This C++ base class joins every solver under a common interface. When the C++ interface is prepared, the python bindings can be added automagically by using ```pythonify.h``` (a tool under MobilityInterface).
Expand All @@ -124,8 +122,6 @@ Solvers are exposed to Python and C++ via a single class that inherits from ```l

A new solver must add a directory under the "solvers", which must be the name that both the python and C++ classes.

Under the directory proper to this new module, the repository containing the solver can be added as a submodule.

Besides the folder containing the repository, inside the solver directory a series of files (and only these files) must exist (additional files might be placed under an "extra" directory inside the solver directory). These files are:
* **mobility.h**: Must include ```MobilityInterface.h``` and define a single class, named as the directory for the solver, that inherits the ```libmobility::Mobility``` base class. For instance, in solvers/NBody/mobility.h we have:
```c++
Expand All @@ -134,7 +130,7 @@ Besides the folder containing the repository, inside the solver directory a seri
...
```
Every pure virtual function in ```libmobility::Mobility``` must be overriden and defined. See more about the mobility interface in include/MobilityInterface.
mobility.h can include and make use of any existent utilities/files from the solvers repository.
* **python_wrapper.cpp**: This file must provide the python bindings for the class in mobility.h. If this class follows the ```libmobility::Mobility``` correctly, this file can in general be quite simple, having only a single line using the ```MOBILITY_PYTHONIFY``` utility in include/MobilityInterface/pythonify.h. See solvers/NBody/python_wrapper.cpp for an example.
In the case of a module being python only (or in general not providing a correct child of ```libmobility::Mobility```), python_wrapper.cpp might be ommited, but a file called [solver].py must exist instead, providing a python class that is compatible with ```libmobility::Mobility``` (so that the user can write ```from solver import *``` and get a class, called "solver" that adheres to the libmobility requirements).
* **CMakeLists.txt**: This must contain rules to create the shared library for the particular solver and its python wrapper. The solver library should be called "lib[Solver].so", while the python library should be called "[Solver].[Python_SOABI].so" with the correct extension suffix. See one of the available CMakeLists.txt for an example.
Expand Down
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
59 changes: 59 additions & 0 deletions docs/_static/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@import 'theme.css';

.rst-content dl:not(.docutils) dt:first-child {
margin-top: 0;
}

.rst-content dl:not(.docutils) dl dt {
margin-bottom: 4px;
border: none;
border-left: solid 3px #ccc;
background: #f0f0f0;
color: #555;
}

.rst-content dl table,
.rst-content dl ul,
.rst-content dl ol,
.rst-content dl p {
margin-bottom: 8px !important;
}

.rst-content dl:not(.docutils) dt {
display: table;
margin: 6px 0;
font-size: 90%;
line-height: normal;
background: #e7f2fa;
color: #2980B9;
border-top: solid 3px #6ab0de;
padding: 6px;
position: relative;
}

html.writer-html5 .rst-content dl.field-list {
display: initial;
}

html.writer-html5 .rst-content dl.field-list>dd,
html.writer-html5 .rst-content dl.field-list>dt {
margin-bottom: 4px;
padding-left: 6px;
}

p {
line-height: 20px;
font-size: 14px;
}

html.writer-html5 .rst-content dl.field-list>dt:after {
content: initial;
}

dt.field-even {
text-transform: uppercase;
}

dt.field-odd {
text-transform: uppercase;
}
35 changes: 35 additions & 0 deletions docs/make.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd
5 changes: 5 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
sphinx==7.2.6
sphinx-rtd-theme==1.3.0
sphinxcontrib-autoprogram==0.1.8
sphinxcontrib-napoleon==0.7
gitpython
10 changes: 10 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
API Reference
=============

.. autosummary::
:toctree: generated
:recursive:

libMobility


85 changes: 85 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Configuration file for the Sphinx documentation builder.
project = "libMobility"
author = "RaulPPelaez"

import git
import sys
import os


def get_latest_git_tag(repo_path="."):
repo = git.Repo(repo_path)
tags = sorted(repo.tags, key=lambda t: t.commit.committed_datetime)
return tags[-1].name if tags else None


current_tag = get_latest_git_tag("../../")
sys.path.append(os.path.abspath("./extensions"))
if current_tag is None:
current_tag = "master"
release = current_tag
version = current_tag

# -- General configuration
extensions = [
"sphinx.ext.duration",
"sphinx.ext.doctest",
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.intersphinx",
"sphinx.ext.napoleon",
"sphinx.ext.viewcode",
"sphinxcontrib.autoprogram",
"customsig",
]
napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = True
napoleon_use_admonition_for_notes = True
napoleon_use_admonition_for_references = True
napoleon_use_ivar = True
napoleon_use_param = True
napoleon_use_rtype = True
napoleon_preprocess_types = True
napoleon_type_aliases = None
napoleon_attr_annotations = True
autosummary_ignore_module_all = False

intersphinx_mapping = {
"python": ("https://docs.python.org/3/", None),
"torch": ("https://pytorch.org/docs/stable/", None),
"sphinx": ("https://www.sphinx-doc.org/en/master/", None),
"pybind11": ("https://pybind11.readthedocs.io/en/stable/", None),
}
intersphinx_disabled_domains = ["std"]

templates_path = ["_templates"]

# -- Options for HTML output

html_theme = "sphinx_rtd_theme"

# -- Options for EPUB output
epub_show_urls = "footnote"

autoclass_content = "both"
autodoc_typehints = "none"
autodoc_inherit_docstrings = False
sphinx_autodoc_typehints = True
html_show_sourcelink = True
autodoc_default_options = {
"members": True,
"member-order": "bysource",
"exclude-members": "__weakref__",
"undoc-members": False,
"show-inheritance": True,
"inherited-members": False,
}
# Exclude all torchmdnet.datasets.*.rst files in source/generated/
html_static_path = ["../_static"]
html_css_files = [
"style.css",
]
Loading

0 comments on commit 8b66ac1

Please sign in to comment.