Poisson in a hundred ways¶
First touch¶
Login by SSH to tyche
and type: How to login
Open a terminal window by hitting
CTRL+ALT+T
. Usessh
to connect to a remote system:ssh -X -C tycheNote
-X
enableX11
forwarding (allows processes on the remote machine opening windows of graphical applications on the local machine)
-C
enables compression which is mainly beneficial for access from a remote network
tyche
stands here for machinetyche.mathematik.tu-chemnitz.de
; username on the local machine is used by default to login to the remote machine; the machine is not accessible from outside the univerity, so one would login through a jump hostluigivercotti@local_machine:~$ ssh -X -C user@login.tu-chemnitz.de user@login:~$ ssh -X -C tyche user@tyche:~$Alternatively one can use VPN.
For experts: Kerberos + public key + jump host
The most comfortable solution for password-less logins outside of the university:
add
Host login Hostname login.tu-chemnitz.de User <user> ForwardAgent yes ForwardX11 yes ForwardX11Trusted yes GSSAPIAuthentication yes GSSAPIDelegateCredentials yes Host tyche Hostname tyche.mathematik.tu-chemnitz.de User <user> ForwardAgent yes ForwardX11 yes ForwardX11Trusted yes ProxyCommand ssh login -W %h:%pto
~/.ssh/config
,upload public key to
login
andtyche
byssh-copy-id login ssh-copy-id tychewhich allows to get Kerberos ticket by
kinit <user>@TU-CHEMNITZ.DEand during its validity password-less login from anywhere
ssh tyche
source /LOCAL/opt/fenics-2017.2.0/fenics.conf
to prepare environment for using FEniCS. Now fire up interactive Python 3 interpreter:
python3
You should see something like:
Python 3.6.5 (default, Apr 1 2018, 05:46:30)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Now type:
>>> from dolfin import *
>>> import matplotlib.pyplot as plt
>>>
>>> mesh = UnitSquareMesh(13, 8)
>>> plot(mesh)
[<matplotlib.lines.Line2D object at 0x7fe0003d65c0>, <matplotlib.lines.Line2D object at 0x7fe0003d6748>]
>>> plt.show()
Hint
Click on >>>
in the right top corner
of the code snippet to make the code copyable.
A graphical plot of the mesh should appear. If any of the
steps above failed, you’re not correctly set up to use FEniCS.
If everything went fine, close the plot window and hit ^D
to
quit the interpreter.
Run and modify Poisson demo¶
Task 1
Get the Poisson demo from FEniCS install dir and run it:
mkdir -p work/fenics/poisson
cd work/fenics/poisson
cp /LOCAL/opt/fenics-2017.2.0/share/dolfin/demo/documented/poisson/python/demo_poisson.py .
python3 demo_poisson.py
You should see some console output and a plot of the solution.
Now login to tyche
from another terminal window and open
the demo file using your favourite editor (if you don’t have any
you can use gedit
, nano
, …):
cd work/fenics/poisson
<editor> demo_poisson.py
Task 2
Now add keyword argument
warp='mode'
to the plot
function
call by applying the following diff:
# Plot solution
import matplotlib.pyplot as plt
-plot(u)
+plot(u, mode='warp')
plt.show()
and run the demo again by python3 demo_poisson.py
.
Open Poisson demo documentation on the FEniCS website. Notice that the doc page is generated from the demo file. Go quickly through the docpage while paying attention to
- definition of weak formulation through forms
a
andL
, - usage of
Constant
andExpression
classes.
Task 3
Modify the code to solve the following problem instead:
with
Semilinear Poisson equation¶
Task 4
Derive weak formulation for the following semilinear Poisson problem:
with
Notice that the weak formulation has the form
Find \(u\in H^1(\Omega)\) such that
with certain \(F\) depending on \(u\) in nonlinear fashion but being linear in test functions \(v\). One can find the solution iteratively by the Newton method:
Choose \(u_0\in H^1(\Omega)\),
For \(k=1,2,\ldots\) do
Find \(\delta u\in H^1(\Omega)\) such that
(3)¶\[\frac{\partial F}{\partial u}(u_k; v, \delta u) = -F(u_k; v) \qquad \text{for all } v\in H^1(\Omega),\]Set \(u_{k+1} = u_k + \delta u\).
Check certain convergence criterion and eventually stop iterating.
Here Jacobian \(\frac{\partial F}{\partial u}(u; v, \delta u)\) is Gâteaux derivative of \(F\). It is generally nonlinear in \(u\), but linear in \(v\) and \(\delta u\). Hence with fixed \(u_k\in H^1(\Omega)\) the left-hand side and the right-hand side of (3) are a bilinear and linear form respectively and (3) is just ordinary linear problem.
Task 5
Modify the previous code to adapt it to problem (1), (2). Define \(F\) by filing the gaps in the following code:
u = Function(V)
v = TestFunction(V)
f = Expression(...)
g = Expression(...)
F = ...
If in doubts, peek into Nonlinear Poisson demo documentation.
Look into documentation of solve
function, read section Solving nonlinear variational problems.
Now you should be able to call the solve
function to obtain the solution.
Nonlinear Dirichlet problem¶
Task 6
Modify the code to solve the following Dirichlet problem:
with
Hint
Supply instance of SubDomain
class to DirichletBC
.
How do you tell SubDomain
to define \(\partial\Omega\)? What do you fill in?
class Boundary(SubDomain):
def inside(self, x, on_boundary):
return ...
on_boundary
argument evaluates to True
on boundary
facets, False
otherwise.
Variational formulation¶
For \(u\in H^1(\Omega)\) consider functional
Convince yourself that minimization of \(F\) over \(H^1(\Omega)\) is equivalent to problem (1).
Task 7
By filling the following code:
u = Function(V)
f = Expression(...)
g = Expression(...)
E = ...
define \(E(u)\) for data (2). Remember that functionals (zero-forms) do not have any test and trial functions.
Obtain \(F(u;v):=\frac{\partial E}{\partial u}(u; v)\)
using derivative
:
F = derivative(E, u)
and run the solver like in Task 5. Check you get the same solution.
Yet another nonlinearity¶
Consider quasilinear equation in divergence form
with data
Reference solution¶
Show/Hide Code
from dolfin import *
import matplotlib.pyplot as plt
def solve_task3(V):
"""Return solution of Task 3 on space V"""
# Define Dirichlet boundary (x = 0 or x = 1)
def boundary(x, on_boundary):
return on_boundary and x[0] > 1.0 - DOLFIN_EPS
# Define boundary condition
uD = Expression("x[1]", degree=1)
bc = DirichletBC(V, uD, boundary)
# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Expression("x[0]", degree=1)
g = Expression("sin(5*x[0])*exp(x[1])", degree=3)
a = inner(grad(u), grad(v))*dx + 6*u*v*dx
L = f*v*dx + g*v*ds
# Compute solution
u = Function(V)
solve(a == L, u, bc)
return u
def solve_task5(V):
"""Return solution of Task 5 on space V"""
# Define variational problem
u = Function(V)
v = TestFunction(V)
f = Expression("x[0]", degree=1)
g = Expression("sin(5*x[0])*exp(x[1])", degree=3)
F = inner(grad(u), grad(v))*dx + (u**3 + u)*v*dx - f*v*dx - g*v*ds
# Compute solution
solve(F == 0, u)
return u
def solve_task6(V):
"""Return solution of Task 6 on space V"""
# Define Dirichlet boundary
class Boundary(SubDomain):
def inside(self, x, on_boundary):
return on_boundary
# Define boundary condition
boundary = Boundary()
uD = Expression("x[1]", degree=1)
bc = DirichletBC(V, uD, boundary)
# Define variational problem
u = Function(V)
v = TestFunction(V)
c = Expression("0.1 + 0.5*(x[0]*x[0] + x[1]*x[1])", degree=2)
f = Expression("100*x[0]", degree=1)
F = c*inner(grad(u), grad(v))*dx + (10*u**3 + u)*v*dx - f*v*dx
# Compute solution
solve(F == 0, u, bc)
return u
def solve_task7(V):
"""Return solution of Task 7 on space V"""
# Define variational problem
u = Function(V)
f = Expression("x[0]", degree=1)
g = Expression("sin(5*x[0])*exp(x[1])", degree=3)
E = ( grad(u)**2/2 + u**4/4 + u**2/2 - f*u )*dx - g*u*ds
F = derivative(E, u)
# Compute solution
solve(F == 0, u)
return u
def solve_task8(V):
"""Return solution of Task 8 on space V"""
# Define variational problem
u = Function(V)
v = TestFunction(V)
f = Expression("0.5*(x[0] + x[1])", degree=1)
A = as_matrix((
(0.1 + u**2, 0),
( 0, 1 + u**2),
))
F = inner(A*grad(u), grad(v))*dx + u*v*dx - f*v*dx
# Compute solution
solve(F == 0, u)
return u
if __name__ == '__main__':
# Create mesh and define function space
mesh = UnitSquareMesh(32, 32)
V = FunctionSpace(mesh, "Lagrange", 1)
# Solve all problems
u3 = solve_task3(V)
u5 = solve_task5(V)
u6 = solve_task6(V)
u7 = solve_task7(V)
u8 = solve_task8(V)
# Compare solution which should be same
err = ( grad(u7 - u5)**2 + (u7 - u5)**2 )*dx
err = assemble(err)
print("||u7 - u5||_H1 =", err)
# Plot all solutions into separate figures
plt.figure()
plot(u3, title='u3', mode="warp")
plt.figure()
plot(u5, title='u5', mode="warp")
plt.figure()
plot(u6, title='u6', mode="warp")
plt.figure()
plot(u7, title='u7', mode="warp")
plt.figure()
plot(u8, title='u8', mode="warp")
# Display all plots
plt.show()