Optimal Control with Nonlinear PDE Constraints¶
Problem Formulation¶
In this demo, we take a look at the case of nonlinear PDE constraints for optimization problems. As a model problem, we consider
As this problem has a nonlinear PDE as state constraint, we have to modify the config file slightly. In particular, in the Section StateSystem we have to write
is_linear = False
Note, that is_linear = False
works for any problem, as linear equations are just a special case
of nonlinear ones, and the corresponding nonlinear solver converges in a single iteration for these.
However, in the opposite case, FEniCS will raise an error, so that an actually nonlinear
equation cannot be solved using is_linear = True
. Also, we briefly recall from
Documentation of the Config Files for Optimal Control Problems, that the default behavior is is_linear = False
,
so that this is not an issue.
Implementation¶
The complete python code can be found in the file demo_nonlinear_pdes.py
,
and the corresponding config can be found in config.ini
.
Initialization¶
Thanks to the high level interface for implementing weak formulations, this problem is tackled almost as easily as the one in Distributed Control of a Poisson Problem. In particular, the entire initialization, up to the definition of the weak form of the PDE constraint, is identical, and we have
from fenics import *
import cashocs
config = cashocs.load_config('config.ini')
mesh, subdomains, boundaries, dx, ds, dS = cashocs.regular_mesh(25)
V = FunctionSpace(mesh, 'CG', 1)
y = Function(V)
p = Function(V)
u = Function(V)
For the definition of the state constraints, we use essentially the same syntax as we would use for the problem in FEniCS, i.e., we write
c = Constant(1e2)
e = inner(grad(y), grad(p))*dx + c*pow(y, 3)*p*dx - u*p*dx
Note
In particular, the only difference between the CASHOCS implementation of this weak form
and the FEniCS one is that, as before, we use fenics.Function
objects for both the state and
adjoint variables, whereas we would use fenics.Function
objects for the state, and
fenics.TestFunction
for the adjoint variable, which would actually play the role of the
test function. Other than that, the syntax is, again, identical to the one of
FEniCS.
Finally, the boundary conditions are defined as before
bcs = cashocs.create_dirichlet_bcs(V, Constant(0), boundaries, [1, 2, 3, 4])
Solution of the optimization problem¶
To define and solve the optimization problem, we now proceed exactly as in Distributed Control of a Poisson Problem, and use
y_d = Expression('sin(2*pi*x[0])*sin(2*pi*x[1])', degree=1)
alpha = 1e-6
J = Constant(0.5)*(y - y_d)*(y - y_d)*dx + Constant(0.5*alpha)*u*u*dx
ocp = cashocs.OptimalControlProblem(e, bcs, J, y, u, p, config)
ocp.solve()
The results looks like this