Overview
ADCME is suitable for conducting inverse modeling in scientific computing. The purpose of the package is to: (1) provide differentiable programming framework for scientific computing based on TensorFlow automatic differentiation (AD) backend; (2) adapt syntax to facilitate implementing scientific computing, particularly for numerical PDE discretization schemes; (3) supply missing functionalities in the backend (TensorFlow) that are important for engineering, such as sparse linear algebra, constrained optimization, etc. Applications include
full wavelength inversion
reduced order modeling in solid mechanics
learning hidden geophysical dynamics
physics based machine learning
parameter estimation in stochastic processes
The package inherents the scalability and efficiency from the well-optimized backend TensorFlow. Meanwhile, it provides access to incooperate existing C/C++ codes via the custom operators. For example, some functionalities for sparse matrices are implemented in this way and serve as extendable "plugins" for ADCME.
Read more about the methodology and philosophy about ADCME: slides.
Getting Started
To install ADCME, simply type the following commands in Julia REPL
julia> using Pkg; Pkg.add("ADCME")
To enable GPU support for custom operators (if you do not need to compile custom operators, you do not need this step), make sure nvcc
command is available on your machine, then
using ADCME
enable_gpu()
We consider a simple inverse modeling problem: consider the following partial differential equation
where
Assume that we have observed $u(0.5)=1$, we want to estimate $b$. The true value in this case should be $b=1$. We can discretize the system using finite difference method, and the resultant linear system will be
where
The idea for implementing the inverse modeling method in ADCME is that we make the unknown $b$ a Variable
and then solve the forward problem pretending $b$ is known. The following code snippet shows the implementation
using LinearAlgebra
using ADCME
n = 101 # number of grid nodes in [0,1]
h = 1/(n-1)
x = LinRange(0,1,n)[2:end-1]
b = Variable(10.0) # we use Variable keyword to mark the unknowns
A = diagm(0=>2/h^2*ones(n-2), -1=>-1/h^2*ones(n-3), 1=>-1/h^2*ones(n-3))
B = b*A + I # I stands for the identity matrix
f = @. 4*(2 + x - x^2)
u = B\f # solve the equation using built-in linear solver
ue = u[div(n+1,2)] # extract values at x=0.5
loss = (ue-1.0)^2
# Optimization
sess = Session(); init(sess)
BFGS!(sess, loss)
println("Estimated b = ", run(sess, b))
The expected output is
Estimated b = 0.9995582304494237