项目作者: IvanYashchuk

项目描述 :
Easy interoperability with Automatic Differentiation libraries through NumPy interface to FEniCS adjoint
高级语言: Python
项目地址: git://github.com/IvanYashchuk/numpy-fenics-adjoint.git
创建时间: 2020-06-07T09:26:26Z
项目社区:https://github.com/IvanYashchuk/numpy-fenics-adjoint

开源协议:MIT License

下载


This project is archived

The development of this package was moved to another repository. Please check out Finite Element Chain Rules. In addition to supporting FEniCS it also supports Firedrake.

numpy-fenics-adjoint · Build Coverage Status

Easy interoperability with Automatic Differentiation libraries through NumPy interface to FEniCS.

Overview

This package provides a high-level interface for evaluating derivatives of FEniCS models.
It is intended to be used as the backend for extending Automatic Differentiation libraries to support FEniCS solvers.

Automatic tangent linear and adjoint solvers for FEniCS problems are derived with dolfin-adjoint/pyadjoint.
These solvers make it possible to use forward and reverse modes Automatic Differentiation with FEniCS.

This package is used for building bridges between FEniCS and JAX in jax-fenics-adjoint. Stay tuned for the PyMC3 (Theano), Julia’s ChainRule.jl, PyTorch integrations.

Current limitations:

  • Composition of forward and reverse modes for higher-order derivatives are not implemented yet.
  • Differentiation wrt Dirichlet boundary conditions and mesh coordinates is not implemented yet.

Example

Here is the demonstration of solving the Poisson’s PDE
on the 2D square domain and calculating the result of multiplying a vector with the solution Jacobian matrix (du/df) using the reverse (adjoint) mode Automatic Differentiation.

  1. import numpy as np
  2. import fenics
  3. import fenics_adjoint
  4. import ufl
  5. from functools import partial
  6. from fenics_numpy import evaluate_primal, evaluate_vjp
  7. from fenics_numpy import fenics_to_numpy, numpy_to_fenics
  8. # Create mesh for the unit square domain
  9. n = 10
  10. mesh = fenics_adjoint.UnitSquareMesh(n, n)
  11. # Define discrete function spaces and functions
  12. V = fenics.FunctionSpace(mesh, "CG", 1)
  13. W = fenics.FunctionSpace(mesh, "DG", 0)
  14. # Define FEniCS template representation of NumPy input
  15. templates = (fenics_adjoint.Function(W),)
  16. # This function takes FEniCS types as arguments and returns a FEniCS Function (solution)
  17. def fenics_solve(f):
  18. # This function inside should be traceable by fenics_adjoint
  19. u = fenics_adjoint.Function(V, name="PDE Solution")
  20. v = fenics.TestFunction(V)
  21. inner, grad, dx = ufl.inner, ufl.grad, ufl.dx
  22. F = (inner(grad(u), grad(v)) - f * v) * dx
  23. bcs = [fenics_adjoint.DirichletBC(V, 0.0, "on_boundary")]
  24. fenics_adjoint.solve(F == 0, u, bcs)
  25. return u
  26. # Let's build a decorator which transforms NumPy input to FEniCS types input
  27. # and returns NumPy representation of FEniCS output
  28. numpy_fenics_solve = partial(evaluate_primal, fenics_solve, templates)
  29. # Let's create a vector of ones with size equal to the number of cells in the mesh
  30. f = np.ones(W.dim())
  31. u = numpy_fenics_solve(f)[0] # u is a NumPy array now
  32. u_fenics = numpy_to_fenics(u, fenics.Function(V)) # we need to explicitly provide template function for conversion
  33. # Now let's evaluate the vector-Jacobian product
  34. numpy_output, fenics_output, fenics_inputs, tape = numpy_fenics_solve(f)
  35. g = np.ones_like(numpy_output)
  36. # `vjp_out` is the result of (implicitly) multiplying the vector `g` with the solution Jacobian du/df
  37. vjp_out = evaluate_vjp(g, fenics_output, fenics_inputs, tape)

Check the tests/ folder for the additional usage examples.

Installation

First install FEniCS.
Then install dolfin-adjoint with:

  1. python -m pip install git+https://github.com/dolfin-adjoint/pyadjoint.git@master

Then install numpy-fenics-adjoint with:

  1. python -m pip install git+https://github.com/IvanYashchuk/numpy-fenics-adjoint@master

Reporting bugs

If you found a bug, create an issue.

Contributing

Pull requests are welcome from everyone.

Fork, then clone the repository:

  1. git clone https://github.com/IvanYashchuk/numpy-fenics-adjoint.git

Make your change. Add tests for your change. Make the tests pass:

  1. pytest tests/

Check the formatting with black and flake8. Push to your fork and submit a pull request.