Obstacle problem#

\[\renewcommand{\div}{\operatorname{div}} \newcommand{\bsig}{\boldsymbol{\sigma}}\]

Implementation#

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Obstacle problem solved with fenics_optim.

@author: Jeremy Bleyer, Ecole des Ponts ParisTech,
Laboratoire Navier (ENPC, Univ Gustave Eiffel, CNRS, UMR 8205)
@email: jeremy.bleyer@enpc.fr
"""
from ufl import dot, grad
from dolfin import (
    UnitSquareMesh,
    FunctionSpace,
    Function,
    DirichletBC,
    Constant,
    Expression,
    dx,
    plot,
)
from fenics_optim import MosekProblem, QuadraticTerm
import numpy as np
import matplotlib.pyplot as plt

N = 100
mesh = UnitSquareMesh(N, N, "crossed")
V = FunctionSpace(mesh, "CG", 1)

bc = DirichletBC(V, Constant(0), "on_boundary")

load = Constant(-5)
hmean = -0.1
ampl = 0.01
k1, k2 = 2, 8
obstacle = Function(V)
obstacle.interpolate(
    Expression(
        "h+a*sin(2*pi*k1*x[0])*cos(2*pi*k1*x[1])*sin(2*pi*k2*x[0])*cos(2*pi*k2*x[1])",
        h=hmean,
        a=ampl,
        k1=k1,
        k2=k2,
        degree=2,
    )
)

prob = MosekProblem("Obstacle problem")
u = prob.add_var(V, bc=bc, lx=obstacle)
prob.add_obj_func(-dot(load, u) * dx)


F = QuadraticTerm(grad(u), degree=0)
prob.add_convex_term(F)

prob.parameters["presolve"] = True
prob.optimize()

x = np.linspace(0, 1, 200)
y = 0.5
U = [u(xi, y) for xi in x]
plt.figure(1)
plt.plot(
    x,
    hmean
    + ampl
    * np.sin(2 * np.pi * k1 * x)
    * np.sin(2 * np.pi * k2 * x)
    * np.cos(2 * np.pi * k1 * y)
    * np.cos(2 * np.pi * k2 * y),
    linewidth=2,
    label="obstacle",
)
plt.plot(x, U, linewidth=1.0, label="membrane")
plt.legend()
plt.xlabel("$x$ coordinate")
plt.ylabel("Displacement")
plt.show()

plot(u)
plt.show()
../_images/contact_area.png