FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman...

105
FEniCS, part III M. M. Sussman [email protected] Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1 / 67

Transcript of FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman...

Page 1: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

FEniCS, part III

M. M. [email protected]

Office Hours: 11:10AM-12:10PM, Thack 622

May 12 – June 19, 2014

1 / 67

Page 2: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Topics

Geometry

Elements

Nonlinear problems

Transient problems

Eigenvalue problems

2 / 67

Page 3: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

How do I generate complicated meshes?

I UnitIntervalMesh, UnitSquareMesh and UnitCubeMeshI RectangleMesh, BoxMeshI If have a simple figure, can map unit square into itI Use MeshEditorI Can read XML or OFF fileI Use a few CGAL functionsI Can use dolfin-convert

3 / 67

Page 4: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Mesh mapping

If you have a differentiable function f : I2 → R2, you can map anexisting mesh:

from dolfin import *import numpy

Theta = pi/2a, b = 1, 5.0nr = 10 # divisions in r directionnt = 20 # divisions in theta directionmesh = RectangleMesh(a, 0, b, 1, nr, nt, "crossed")

# First make a denser mesh towards r=ax = mesh.coordinates()[:,0]y = mesh.coordinates()[:,1]s = 1.3

def denser(x,y):return [a + (b-a)*((x-a)/(b-a))**s, y]

x_bar, y_bar = denser(x, y)xy_bar_coor = numpy.array([x_bar, y_bar]).transpose()mesh.coordinates()[:] = xy_bar_coorplot(mesh, title="stretched mesh", interactive=True)

4 / 67

Page 5: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Mesh mapping cont’d

def cylinder(r, s):return [r*numpy.cos(Theta*s),r*numpy.sin(Theta*s)]

x_hat, y_hat = cylinder(x_bar, y_bar)xy_hat_coor = numpy.array([x_hat, y_hat]).transpose()mesh.coordinates()[:] = xy_hat_coorplot(mesh, title="hollow cylinder")interactive()

5 / 67

Page 6: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Modified mesh

6 / 67

Page 7: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

MeshEditor

From the book: no one should ever do this kind of thing by hand

mesh = Mesh();editor = MeshEditor();editor.open(mesh, 2, 2)editor.init_vertices(4)editor.init_cells(2)editor.add_vertex(0, 0.0, 0.0)editor.add_vertex(1, 1.0, 0.0)editor.add_vertex(2, 1.0, 1.0)editor.add_vertex(3, 0.0, 1.0)editor.add_cell(0, 0, 1, 2)editor.add_cell(1, 0, 2, 3)editor.close()

7 / 67

Page 8: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

XML filesThis format is useful for saving and communicating meshes, not forgenerating them.

<?xml version="1.0" encoding="UTF-8"?><dolfin smlns:dolfin="http"//fenicsproject.org">

<mesh celltype="triangle" dim="2"><vertices size="9"><vertex index="0" x="0" y="0"/><vertex index="1" x="0.5" y="0"/><vertex index="2" x="1" y="0"/><vertex index="3" x="0" y="0.5"/><vertex index="4" x="0.5" y="0.5"/><vertex index="5" x="1" y="0.5"/><vertex index="6" x="0" y="1"/><vertex index="7" x="0.5" y="1"/><vertex index="8" x="1" y="1"/>

</vertices><cells size="8"><triangle index="0" v0="0" v1="1" v2="4"/><triangle index="1" v0="0" v1="3" v2="4"/><triangle index="2" v0="1" v1="2" v2="5"/><triangle index="3" v0="1" v1="4" v2="5"/><triangle index="4" v0="3" v1="4" v2="7"/><triangle index="5" v0="3" v1="6" v2="7"/><triangle index="6" v0="4" v1="5" v2="8"/><triangle index="7" v0="4" v1="7" v2="8"/>

</cells></mesh>

</dolfin>8 / 67

Page 9: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

CGAL functions

I Computational Geometry Algorithms LibraryI Open-source projectI Python bindingsI Probably can use more than Dolfin provides.

I Best built-in optionI CircleMeshI EllipseMeshI SphereMeshI EllipsoidMeshI PolyhedralMeshGeneratorI Add and subtract, overlap figures

9 / 67

Page 10: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example9.py 2D example

from dolfin import *

# Define 2D geometrydomain = Rectangle(0., 0., 5., 5.) - \

Rectangle(2., 1.25, 3., 1.75) - Circle(1, 4, .25) - Circle(4, 4, .25)domain.set_subdomain(1, Rectangle(1., 1., 4., 3.))domain.set_subdomain(2, Rectangle(2., 2., 3., 4.))

# Generate and plot meshmesh2d = Mesh(domain, 45)plot(mesh2d, "2D mesh")

# Convert subdomains to mesh function for plottingmf = MeshFunction("size_t", mesh2d, 2, mesh2d.domains())plot(mf, "Subdomains")

interactive()

10 / 67

Page 11: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Output

11 / 67

Page 12: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Read .OFF files

I .OFF files are written by some programsI PolyhedralMeshGenerator to read OFF filesI Awkward to generate by hand

12 / 67

Page 13: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Real meshes: use dolfin-convert

Suffix File format.xml DOLFIN XML format.ele / .node Triangle file format.mesh Medit format, generated by TetGen with -g.msh / .gmsh Gmsh∗ version 2.0.grid Diffpack tetrahedral grid format.inp Abaqus tetrahedral grid format.e / .exo Sandia Exodus II file format.ncdf ncdump’ed Exodus II.vrt / .cell Star-CD tetrahedral grid format

∗Installed on your VM

13 / 67

Page 14: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Mesh refinement

I mesh = refine(mesh): uniform refinementI mesh = refine(mesh, marker_function: selective

refinementI marker_function is a boolean CellFunctionI Depends on good error estimator

I Chapters 28 and 29 include discussion of adaptive meshrefinement

I The goal-oriented adaptive solution in Chapter 29 isimplemented in AdaptiveLinearVariationalSolver.

14 / 67

Page 15: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

AdaptiveLinearVariationalSolver example# directory: dolfin-demos/documented/auto-adaptive-poisson/python/# file: demo_auto-adaptive_poisson.pyfrom dolfin import *

# Create mesh and define function spacemesh = UnitSquareMesh(8, 8)V = FunctionSpace(mesh, "Lagrange", 1)

# Define boundary conditionu0 = Function(V)bc = DirichletBC(V, u0, "x[0] < DOLFIN_EPS || x[0] > 1.0 - DOLFIN_EPS")

# Define variational problemu = TrialFunction(V)v = TestFunction(V)f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)",

degree=1)g = Expression("sin(5*x[0])", degree=1)a = inner(grad(u), grad(v))*dx()L = f*v*dx() + g*v*ds()

# Define function for the solutionu = Function(V)

# Define goal functional (quantity of interest)M = u*dx()

# Define error tolerancetol = 1.e-5

15 / 67

Page 16: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

AdaptiveLinearVariationalSolver examplecont’d

# Solve equation a = L with respect to u and the given boundary# conditions, such that the estimated error (measured in M) is less# than tolproblem = LinearVariationalProblem(a, L, u, bc)solver = AdaptiveLinearVariationalSolver(problem, M)solver.parameters["error_control"]["dual_variational_solver"]\

["linear_solver"] = "cg"solver.solve(tol)

solver.summary()

# Plot solution(s)plot(u.root_node(), title="Solution on initial mesh")plot(u.leaf_node(), title="Solution on final mesh")interactive()

16 / 67

Page 17: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

AdaptiveLinearVariationalSolver output

Level | functional_value error_estimate tolerance num_cells num_dofs-------------------------------------------------0 | 0.121629 0.001179 1e-05 128 811 | 0.125724 0.000881366 1e-05 162 982 | 0.125833 0.000852912 1e-05 209 1263 | 0.126245 0.000456543 1e-05 267 1564 | 0.125464 0.000308555 1e-05 343 1975 | 0.124939 0.000247634 1e-05 511 2836 | 0.1253 0.000216778 1e-05 713 3947 | 0.125635 0.000143245 1e-05 966 5268 | 0.125408 9.46871e-05 1e-05 1218 6569 | 0.125237 7.26173e-05 1e-05 1819 96210 | 0.125174 5.40451e-05 1e-05 2648 139311 | 0.125304 3.39704e-05 1e-05 3694 192812 | 0.125285 2.22991e-05 1e-05 4759 247213 | 0.125234 1.83246e-05 1e-05 7114 366014 | 0.125204 1.38494e-05 1e-05 10308 528015 | 0.125243 8.78483e-06 1e-05 14402 7358

17 / 67

Page 18: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Topics

Geometry

Elements

Nonlinear problems

Transient problems

Eigenvalue problems

18 / 67

Page 19: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Elements available

Name Symbol Dimension DegreeArgyris ARG 2 5Arnold-Winther AW 2Brezzi-Douglas-Marini BDM 2,3 1-6Crouzeix-Raviart CR 2,3 1Discontinuous Lagrange DG 2,3 1-6Hermite HER 2,3Lagrange CG 2,3 1-6Mordal-Tai-Winther MTW 2Morley MOR 2Nédélec 1st kind H(curl) N1curl 2,3 6Nédélec 2nd kind H(curl) N2curl 2,3 6Raviart-Thomas RT 2,3 6

19 / 67

Page 20: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Lagrange (CG) elements

First order on triangles Fourth order on triangles

First order on tetrahedra

20 / 67

Page 21: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Discontinuous Lagrange (DG) elements

Constant on triangles Linear on triangles

Constant on tetrahedra

21 / 67

Page 22: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Raviert-Thomas (RT) elements

These elements are H(div)-conforming.First order on triangles Third order on triangles

Second order on tetrahedra

22 / 67

Page 23: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Brezzi-Douglas-Marini (BDM) elementsThese elements are H(div)-conforming.

First order on tetrahedra Third order on tetrahedra

Second order on triangles

23 / 67

Page 24: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Nédélec First Kind elements

These elements are H(curl)-conforming.First order on triangles Third order on triangles

First order on tetrahedra

24 / 67

Page 25: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Nédélec Second Kind elements

These elements are H(curl)-conforming.First order on triangles First order on tetrahedra

25 / 67

Page 26: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Topics

Geometry

Elements

Nonlinear problems

Transient problems

Eigenvalue problems

26 / 67

Page 27: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

A nonlinear problem

Suppose Ω = [0,1] is the unit interval, and consider the equation

−∇ · (q(u)∇u) = fu = 0 for x = 0u = 1 for x = 1

q(u) = (1 + u)m

The exact solution is u =(

(2m+1 − 1)x + 1)1/(m+1)

− 1

27 / 67

Page 28: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Variational formulation

F (u; v) =

∫Ω

q(u)∇u · ∇v dx = 0 ∀v ∈ V

where

V = v ∈ H1(Ω) : v = 0 on x = 0, v = 1 on x = 1

andV = v ∈ H1(Ω) : v = 0 on x = 0, v = 0 on x = 1

28 / 67

Page 29: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Picard iteration (successive substitution)

Given an initial guess u0, recursively define iterates uk+1 as solutionsof the linear variational problem

a(u, v) =

∫Ω

q(uk )∇u · ∇v dx

with the same boundary conditions as before.

29 / 67

Page 30: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration

from dolfin import *import numpy as npimport scipy.linalg as la

# Create mesh and define function spacemesh = UnitIntervalMesh(10)V = FunctionSpace(mesh, ’Lagrange’, 1)

# Define boundary conditionsfuzz = 1E-14def left_boundary(x, on_boundary):

return on_boundary and abs(x[0]) < fuzz

def right_boundary(x, on_boundary):return on_boundary and abs(x[0]-1) < fuzz

Gamma_0 = DirichletBC(V, Constant(0.0), left_boundary)Gamma_1 = DirichletBC(V, Constant(1.0), right_boundary)bcs = [Gamma_0, Gamma_1]

# Choice of nonlinear coefficientm = 2

def q(u):return (1+u)**m

30 / 67

Page 31: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

# Define variational problem for Picard iterationu = TrialFunction(V)v = TestFunction(V)u_k = interpolate(Constant(0.0), V) # previous (known) ua = inner(q(u_k)*nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dx

# Picard iterationsu = Function(V) # new unknown functioneps = 1.0 # error measure ||u-u_k||rho = 0 # convergence ratetol = 1.0E-6 # toleranceiter = 0 # iteration countermaxiter = 25 # max no of iterations allowedfor iter in range(maxiter):

solve(a == L, u, bcs)diff = u.vector().array() - u_k.vector().array()oldeps = epseps = la.norm(diff, ord=np.Inf) / la.norm(u.vector().array(), ord=np.Inf)rho = eps/oldepsprint ’iter=%d: norm=%g, rho=%g’ % (iter, eps, rho)if eps < tol * (1.0-rho):

breaku_k.assign(u) # update for next iteration

31 / 67

Page 32: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

# Define variational problem for Picard iterationu = TrialFunction(V)v = TestFunction(V)u_k = interpolate(Constant(0.0), V) # previous (known) ua = inner(q(u_k)*nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dx

# Picard iterationsu = Function(V) # new unknown functioneps = 1.0 # error measure ||u-u_k||rho = 0 # convergence ratetol = 1.0E-6 # toleranceiter = 0 # iteration countermaxiter = 25 # max no of iterations allowedfor iter in range(maxiter):

solve(a == L, u, bcs)diff = u.vector().array() - u_k.vector().array()oldeps = epseps = la.norm(diff, ord=np.Inf) / la.norm(u.vector().array(), ord=np.Inf)rho = eps/oldepsprint ’iter=%d: norm=%g, rho=%g’ % (iter, eps, rho)if eps < tol * (1.0-rho):

breaku_k.assign(u) # update for next iteration

31 / 67

Page 33: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

# Define variational problem for Picard iterationu = TrialFunction(V)v = TestFunction(V)u_k = interpolate(Constant(0.0), V) # previous (known) ua = inner(q(u_k)*nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dx

# Picard iterationsu = Function(V) # new unknown functioneps = 1.0 # error measure ||u-u_k||rho = 0 # convergence ratetol = 1.0E-6 # toleranceiter = 0 # iteration countermaxiter = 25 # max no of iterations allowedfor iter in range(maxiter):

solve(a == L, u, bcs)diff = u.vector().array() - u_k.vector().array()oldeps = epseps = la.norm(diff, ord=np.Inf) / la.norm(u.vector().array(), ord=np.Inf)rho = eps/oldepsprint ’iter=%d: norm=%g, rho=%g’ % (iter, eps, rho)if eps < tol * (1.0-rho):

breaku_k.assign(u) # update for next iteration

31 / 67

Page 34: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

# Define variational problem for Picard iterationu = TrialFunction(V)v = TestFunction(V)u_k = interpolate(Constant(0.0), V) # previous (known) ua = inner(q(u_k)*nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dx

# Picard iterationsu = Function(V) # new unknown functioneps = 1.0 # error measure ||u-u_k||rho = 0 # convergence ratetol = 1.0E-6 # toleranceiter = 0 # iteration countermaxiter = 25 # max no of iterations allowedfor iter in range(maxiter):

solve(a == L, u, bcs)diff = u.vector().array() - u_k.vector().array()oldeps = epseps = la.norm(diff, ord=np.Inf) / la.norm(u.vector().array(), ord=np.Inf)rho = eps/oldepsprint ’iter=%d: norm=%g, rho=%g’ % (iter, eps, rho)if eps < tol * (1.0-rho):

breaku_k.assign(u) # update for next iteration

31 / 67

Page 35: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

# Define variational problem for Picard iterationu = TrialFunction(V)v = TestFunction(V)u_k = interpolate(Constant(0.0), V) # previous (known) ua = inner(q(u_k)*nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dx

# Picard iterationsu = Function(V) # new unknown functioneps = 1.0 # error measure ||u-u_k||rho = 0 # convergence ratetol = 1.0E-6 # toleranceiter = 0 # iteration countermaxiter = 25 # max no of iterations allowedfor iter in range(maxiter):

solve(a == L, u, bcs)diff = u.vector().array() - u_k.vector().array()oldeps = epseps = la.norm(diff, ord=np.Inf) / la.norm(u.vector().array(), ord=np.Inf)rho = eps/oldepsprint ’iter=%d: norm=%g, rho=%g’ % (iter, eps, rho)if eps < tol * (1.0-rho):

breaku_k.assign(u) # update for next iteration

31 / 67

Page 36: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

# Define variational problem for Picard iterationu = TrialFunction(V)v = TestFunction(V)u_k = interpolate(Constant(0.0), V) # previous (known) ua = inner(q(u_k)*nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dx

# Picard iterationsu = Function(V) # new unknown functioneps = 1.0 # error measure ||u-u_k||rho = 0 # convergence ratetol = 1.0E-6 # toleranceiter = 0 # iteration countermaxiter = 25 # max no of iterations allowedfor iter in range(maxiter):

solve(a == L, u, bcs)diff = u.vector().array() - u_k.vector().array()oldeps = epseps = la.norm(diff, ord=np.Inf) / la.norm(u.vector().array(), ord=np.Inf)rho = eps/oldepsprint ’iter=%d: norm=%g, rho=%g’ % (iter, eps, rho)if eps < tol * (1.0-rho):

breaku_k.assign(u) # update for next iteration

31 / 67

Page 37: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

assign ??

I “Assigns” one function to anotherI Presumably efficientI It means u_k.vector()[:]=u.vector()

32 / 67

Page 38: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

convergence = ’convergence after %d Picard iterations’ % iterif iter >= maxiter-1:

convergence = ’no ’ + convergenceprint convergence

# Find max erroru_exact = Expression(’pow((pow(2, m+1)-1)*x[0] + 1, 1.0/(m+1)) - 1’, m=m)u_e = interpolate(u_exact, V)diff = la.norm((u_e.vector().array() - u.vector().array()), ord=np.Inf)print ’Max error:’, diff

33 / 67

Page 39: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: Picard iteration, cont’d

convergence = ’convergence after %d Picard iterations’ % iterif iter >= maxiter-1:

convergence = ’no ’ + convergenceprint convergence

# Find max erroru_exact = Expression(’pow((pow(2, m+1)-1)*x[0] + 1, 1.0/(m+1)) - 1’, m=m)u_e = interpolate(u_exact, V)diff = la.norm((u_e.vector().array() - u.vector().array()), ord=np.Inf)print ’Max error:’, diff

33 / 67

Page 40: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example10.py: results

iter=0: norm=1, rho=1iter=1: norm=0.171129, rho=0.171129iter=2: norm=0.0149607, rho=0.0874237iter=3: norm=0.00620223, rho=0.414567iter=4: norm=0.000799731, rho=0.128943iter=5: norm=0.000240982, rho=0.301329)iter=6: norm=3.99044e-05, rho=0.165591iter=7: norm=8.81351e-06, rho=0.220866iter=8: norm=1.85317e-06, rho=0.210265iter=9: norm=3.30119e-07, rho=0.178137convergence after 9 Picard iterations

34 / 67

Page 41: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Newton instead of Picard iteration

I System of nonlinear equations must hold ∀v ∈ Vh

a(u, v)− L(v) =

∫Ω

q(u)∇u · ∇v dx −∫

Ω

fv dx = 0

I Approximate by a system of nonlinear equations

Fi (u) = a(u, φi )− L(φi ) = 0

I Given an inital guess, u0, solve the nonlinear system

(J δuk )i = (J(uk − uk−1))i = a(uk−1, φi )− L(φi )

I δuk satisfies homogeneous Dirichlet conditionsI J is Jacobian matrixI FEniCS needs this expressed in weak form

35 / 67

Page 42: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Newton iteration as weak formWriting a vector U = (u1,u2, . . . )

T , Newton iteration is applied to thenonlinear system

Fi (∑`

U`φ`) =

∫Ω

q(∑`

U`φ`)∑`

U`∇φ` · ∇φi dx −∫

Ω

fφi dx = 0

Given a starting vector U0, define subsequent iterates as

J(Uk ) δUk+1 = −Fi (Uk )

Uk+1 = Uk + δUk+1

The Jacobian matrix is

Jij =∂Fi

∂Uj=∫

Ω

q|∑` U`φ`

∇φj · ∇φi dx +

∫Ω

dqdu

∣∣∣∣∑` U`φ`

φj (∑`

U`∇φ`) · ∇φi dx

36 / 67

Page 43: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Newton iteration cont’dWriting qk = q(

∑` Uk

` φ`) and uk =∑` Uk

` φ`, The Newton updatesystem becomes

...

. . .∫

Ωqk∇φj · ∇φi dx +

∫Ω

(dqdu

)kφj∇uk · ∇φi dx . . .

...

...δUj

...

=

...∫

Ωqk∇uk · ∇φi dx −

∫Ω

fφi dx...

This is the system that would arise if you wanted to solve

J (δu, v) =

∫Ω

q(uk )∇δu · ∇v dx +

∫Ω

(dqdu

)k

δu∇uk · ∇v dx

L(v) =

∫Ω

qk∇uk · ∇v dx −∫

Ω

fφi dx

37 / 67

Page 44: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Exercise 17 (8 points)

Show by direct calculation that the same bilinear operator J arisesfrom computing the Jacobian of the original nonlinear forma(u, v) =

∫Ω

q(u)∇u · ∇v directly. (8 points) (See FEniCS book,Section 1.2.4.)

38 / 67

Page 45: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

The diagram commutes!

J (δu, v) = L(v)

a(u, v) = L(v) a(uh, vh) = L(vh)

J (δuh, vh) = L(vh)h

h

-

-

? ?

Newton Newton

39 / 67

Page 46: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solutionfrom dolfin import *import numpy as npimport scipy.linalg as la

# Create mesh and define function spacemesh = UnitIntervalMesh(20)V = FunctionSpace(mesh, ’Lagrange’, 1)

# Define boundary conditions for initial guessfuzz = 1E-14def left_boundary(x, on_boundary):

return on_boundary and abs(x[0]) < fuzz

def right_boundary(x, on_boundary):return on_boundary and abs(x[0]-1) < fuzz

Gamma_0 = DirichletBC(V, Constant(0.0), left_boundary)Gamma_1 = DirichletBC(V, Constant(1.0), right_boundary)bcs = [Gamma_0, Gamma_1]

# Define variational problem for initial guess (q(u)=1, i.e., m=0)u = TrialFunction(V)v = TestFunction(V)a = inner(nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dxA, b = assemble_system(a, L, bcs)u_k = Function(V)solve(A, u_k.vector(), b, ’lu’)

40 / 67

Page 47: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solutionfrom dolfin import *import numpy as npimport scipy.linalg as la

# Create mesh and define function spacemesh = UnitIntervalMesh(20)V = FunctionSpace(mesh, ’Lagrange’, 1)

# Define boundary conditions for initial guessfuzz = 1E-14def left_boundary(x, on_boundary):

return on_boundary and abs(x[0]) < fuzz

def right_boundary(x, on_boundary):return on_boundary and abs(x[0]-1) < fuzz

Gamma_0 = DirichletBC(V, Constant(0.0), left_boundary)Gamma_1 = DirichletBC(V, Constant(1.0), right_boundary)bcs = [Gamma_0, Gamma_1]

# Define variational problem for initial guess (q(u)=1, i.e., m=0)u = TrialFunction(V)v = TestFunction(V)a = inner(nabla_grad(u), nabla_grad(v))*dxf = Constant(0.0)L = f*v*dxA, b = assemble_system(a, L, bcs)u_k = Function(V)solve(A, u_k.vector(), b, ’lu’)

40 / 67

Page 48: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solution cont’d

# Note that all Dirichlet conditions must be zero for# the correction function in a Newton-type methodGamma_0_du = DirichletBC(V, Constant(0.0), left_boundary)Gamma_1_du = DirichletBC(V, Constant(0.0), right_boundary)bcs_du = [Gamma_0_du, Gamma_1_du]

# Choice of nonlinear coefficientm = 2

def q(u):return (1+u)**m

def Dq(u):return m*(1+u)**(m-1)

# Define variational problem for the matrix and vector# in a Newton iterationdu = TrialFunction(V) # u = u_k + omega*duJ = inner(q(u_k)*nabla_grad(du), nabla_grad(v))*dx + \

inner(Dq(u_k)*du*nabla_grad(u_k), nabla_grad(v))*dxL = -inner(q(u_k)*nabla_grad(u_k), nabla_grad(v))*dx

41 / 67

Page 49: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solution cont’d

# Note that all Dirichlet conditions must be zero for# the correction function in a Newton-type methodGamma_0_du = DirichletBC(V, Constant(0.0), left_boundary)Gamma_1_du = DirichletBC(V, Constant(0.0), right_boundary)bcs_du = [Gamma_0_du, Gamma_1_du]

# Choice of nonlinear coefficientm = 2

def q(u):return (1+u)**m

def Dq(u):return m*(1+u)**(m-1)

# Define variational problem for the matrix and vector# in a Newton iterationdu = TrialFunction(V) # u = u_k + omega*duJ = inner(q(u_k)*nabla_grad(du), nabla_grad(v))*dx + \

inner(Dq(u_k)*du*nabla_grad(u_k), nabla_grad(v))*dxL = -inner(q(u_k)*nabla_grad(u_k), nabla_grad(v))*dx

41 / 67

Page 50: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solution cont’d

# Note that all Dirichlet conditions must be zero for# the correction function in a Newton-type methodGamma_0_du = DirichletBC(V, Constant(0.0), left_boundary)Gamma_1_du = DirichletBC(V, Constant(0.0), right_boundary)bcs_du = [Gamma_0_du, Gamma_1_du]

# Choice of nonlinear coefficientm = 2

def q(u):return (1+u)**m

def Dq(u):return m*(1+u)**(m-1)

# Define variational problem for the matrix and vector# in a Newton iterationdu = TrialFunction(V) # u = u_k + omega*duJ = inner(q(u_k)*nabla_grad(du), nabla_grad(v))*dx + \

inner(Dq(u_k)*du*nabla_grad(u_k), nabla_grad(v))*dxL = -inner(q(u_k)*nabla_grad(u_k), nabla_grad(v))*dx

41 / 67

Page 51: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solution cont’d

# Newton iteration at the algebraic leveldu = Function(V)u = Function(V) # u = u_k + omega*duomega = 1.0 # relaxation parametererr = 1.0tol = 1.0E-5iter = 0maxiter = 25# u_k has correct nonhomogeneous boundary conditionsu.assign(u_k)

for iter in range(maxiter):print iter, "iteration",AJ, b = assemble_system(J, L, bcs_du)solve(AJ, du.vector(), b)u.vector()[:] += omega*du.vector()

# or, better for parallel computing#u.assign(u_k) # u = u_k#u.vector().axpy(omega, du.vector())

olderr = errerr = la.norm(du.vector().array(), ord=np.Inf) / \

la.norm(u.vector().array(), ord=np.Inf)rho = err/olderrprint "Norm=%g, rho=%g"% (err, rho)if err < tol * (1.0 - rho):

breaku_k.assign(u)

42 / 67

Page 52: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solution cont’d

# Newton iteration at the algebraic leveldu = Function(V)u = Function(V) # u = u_k + omega*duomega = 1.0 # relaxation parametererr = 1.0tol = 1.0E-5iter = 0maxiter = 25# u_k has correct nonhomogeneous boundary conditionsu.assign(u_k)for iter in range(maxiter):

print iter, "iteration",AJ, b = assemble_system(J, L, bcs_du)solve(AJ, du.vector(), b)u.vector()[:] += omega*du.vector()

# or, better for parallel computing#u.assign(u_k) # u = u_k#u.vector().axpy(omega, du.vector())

olderr = errerr = la.norm(du.vector().array(), ord=np.Inf) / \

la.norm(u.vector().array(), ord=np.Inf)rho = err/olderrprint "Norm=%g, rho=%g"% (err, rho)if err < tol * (1.0 - rho):

breaku_k.assign(u)

42 / 67

Page 53: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solution cont’d

# Newton iteration at the algebraic leveldu = Function(V)u = Function(V) # u = u_k + omega*duomega = 1.0 # relaxation parametererr = 1.0tol = 1.0E-5iter = 0maxiter = 25# u_k has correct nonhomogeneous boundary conditionsu.assign(u_k)for iter in range(maxiter):

print iter, "iteration",AJ, b = assemble_system(J, L, bcs_du)solve(AJ, du.vector(), b)u.vector()[:] += omega*du.vector()# or, better for parallel computing#u.assign(u_k) # u = u_k#u.vector().axpy(omega, du.vector())olderr = errerr = la.norm(du.vector().array(), ord=np.Inf) / \

la.norm(u.vector().array(), ord=np.Inf)rho = err/olderrprint "Norm=%g, rho=%g"% (err, rho)if err < tol * (1.0 - rho):

breaku_k.assign(u)

42 / 67

Page 54: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example11.py: Newton solution cont’d

convergence = ’convergence after %d Newton iterations’ % iterif iter >= maxiter:

convergence = ’no ’ + convergence

# Find max erroru_exact = Expression(’pow((pow(2, m+1)-1)*x[0] + 1, 1.0/(m+1)) - 1’, m=m)u_e = interpolate(u_exact, V)diff = la.norm((u_e.vector().array() - u.vector().array()), ord=np.Inf)print ’Max error:’, diff

43 / 67

Page 55: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Automatic Jacobian computation is available!

I Deriving Jacobians automatically!I Replace the following code in example11.py:

J = inner(q(u_k)*nabla_grad(du), nabla_grad(v))*dx + \inner(Dq(u_k)*du*nabla_grad(u_k), nabla_grad(v))*dx

L = -inner(q(u_k)*nabla_grad(u_k), nabla_grad(v))*dx

I With the following code (example12.py)L = inner(q(u_k)*nabla_grad(u_k), nabla_grad(v))*dxJ = derivative(L, u_k, du)L = -L

44 / 67

Page 56: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

More on the derivative

dolfin.derivative = derivative(form, u, du=None)I Compute derivative of form with respect to uI Resulting form has second variable (du)I v is in same space as uI “A tuple of Coefficients may be provided in place of a single

Coefficient, in which case the new Argument argument is basedon a MixedElement created from this tuple.”

45 / 67

Page 57: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Some results

I Manual Jacobian (example11.py)0 iteration Norm=0.181001, rho=0.1810011 iteration Norm=0.0197372, rho=0.1090442 iteration Norm=0.000269528, rho=0.01365593 iteration Norm=4.98281e-08, rho=0.000184872Max error: 1.72084568817e-15

I Automatic Jacobian (example12.py)0 iteration Norm=0.181001, rho=0.1810011 iteration Norm=0.0197372, rho=0.1090442 iteration Norm=0.000269528, rho=0.01365593 iteration Norm=4.98281e-08, rho=0.000184872Max error: 1.72084568817e-15

I Same convergence historiesI Quadratic convergence

46 / 67

Page 58: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Some results

I Manual Jacobian (example11.py)0 iteration Norm=0.181001, rho=0.1810011 iteration Norm=0.0197372, rho=0.1090442 iteration Norm=0.000269528, rho=0.01365593 iteration Norm=4.98281e-08, rho=0.000184872Max error: 1.72084568817e-15

I Automatic Jacobian (example12.py)0 iteration Norm=0.181001, rho=0.1810011 iteration Norm=0.0197372, rho=0.1090442 iteration Norm=0.000269528, rho=0.01365593 iteration Norm=4.98281e-08, rho=0.000184872Max error: 1.72084568817e-15

I Same convergence historiesI Quadratic convergence

46 / 67

Page 59: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

What does the solution look like?

47 / 67

Page 60: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Nonlinear solve can be automated!

1. Define weak form as usual2. Turn it into a vector function using action

3. Compute Jacobian using derivative

4. Define the problem using NonlinearVariationalProblem

5. Create a solver using NonlinearVariationalSolver

6. Set solver parameters if desired7. solver.solve()

48 / 67

Page 61: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)

# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 62: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 63: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 64: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 65: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 66: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 67: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by default

uinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 68: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 69: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: automated nonlinear solve

# Define variational problemv = TestFunction(V)u = TrialFunction(V)F = inner(q(u)*nabla_grad(u), nabla_grad(v))*dxu_ = Function(V)# Make functional into a vector functionF = action(F, u_ )

# Automatic differentiationJ = derivative(F, u_ )

# set initial guess# u_ is zero by defaultuinit = interpolate(Expression("2.*x[0]*x[0]"),V)u_.assign(uinit)

# Compute solutionproblem = NonlinearVariationalProblem(F, u_ , bcs, J)solver = NonlinearVariationalSolver(problem)

solver.solve()

49 / 67

Page 70: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Controlling the nonlinear solution

I Very sensitive to initial guessI Often hard to convergeI Linear solve inside Newton loopI What linear method to use?I What preconditioner to use?

50 / 67

Page 71: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 72: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 73: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 74: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 75: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 76: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 77: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 78: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example13.py: Parameters

solver = NonlinearVariationalSolver(problem)

prm = solver.parametersinfo(prm, True)prm["nonlinear_solver"]="newton" # default. could be "snes"prm["newton_solver"]["absolute_tolerance"] = 1E-8prm["newton_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["maximum_iterations"] = 25prm["newton_solver"]["relaxation_parameter"] = 1.0prm["newton_solver"]["linear_solver"] = "gmres"prm["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1E-9prm["newton_solver"]["krylov_solver"]["relative_tolerance"] = 1E-7prm["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000prm["newton_solver"]["krylov_solver"]["monitor_convergence"] = Trueprm["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = Falseprm["newton_solver"]["krylov_solver"]["gmres"]["restart"] = 40prm["newton_solver"]["preconditioner"] = "jacobi" # default is "ilu"prm["newton_solver"]["krylov_solver"]["preconditioner"]["structure"]\

= "same_nonzero_pattern"prm["newton_solver"]["krylov_solver"]["preconditioner"]["ilu"]["fill_level"] =0

set_log_level(PROGRESS)

51 / 67

Page 79: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Go deeper: use PETSc

I PETSc offers enormous control via command lineI petsc4py can be usedI May have to use a compiled language for full control

52 / 67

Page 80: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Recommendations

I Start: automatic differentiation, no initial guess, and automatednonlinear solve

I Fails? pick better initial guessI Diverging?prm["newton_solver"]["relaxation_parameter"]smaller

I Still Fails? set_log_level(PROGRESS) or DEBUGI Newton iteration fails? SNES.I Linear sub-solve fails?

I Out of memory in LU? Use Krylov solver (GMRES)I Begin sub-solve from previous solution instead of zeroI Construct better preconditioner matrixI Larger relative and/or absolute toleranceI Different linear solver

I Simplify: same problems in 1D?

53 / 67

Page 81: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Topics

Geometry

Elements

Nonlinear problems

Transient problems

Eigenvalue problems

54 / 67

Page 82: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Transient simulations

Transient simulations follow a similar outline1. Set up the mesh, function spaces, etc.2. Set up initial condition3. Assemble constant matrices and vectors4. Enter timestepping loop

4.1 Assemble changing matrices and vectors4.2 Solve for the new time step values

55 / 67

Page 83: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Method of lines: implicit Euler timestepping

I Transient heat equation

∂u∂t

= ∇ · ∇u + f

I Discretize in t, continuous in space

uk+1 − uk

∆t= ∇ · ∇uk+1 + f k+1

I Re-writeuk+1 −∆t∇ · ∇uk+1 = uk + f k+1

I Weak form

(uk+1, v) + ∆t(∇uk+1,∇v) = (uk , v) + (f k+1, v)

56 / 67

Page 84: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example14.py: Transient heat equationfrom dolfin import *import numpy

# Create mesh and define function spacemesh = UnitSquareMesh(20,10)V = FunctionSpace(mesh, "Lagrange", 2)

# Define boundary conditionsalpha = 3; beta = 1.2u0 = Expression("1 + x[0]*x[0] + alpha*x[1]*x[1] + beta*t",

alpha=alpha, beta=beta, t=0)

class Boundary(SubDomain): # define the Dirichlet boundarydef inside(self, x, on_boundary):

return on_boundary

boundary = Boundary()bc = DirichletBC(V, u0, boundary)

# Initial conditionu_k = interpolate(u0, V)dt = 0.3 # time step

# Define variational problemu = TrialFunction(V)v = TestFunction(V)f = Constant(beta - 2 - 2*alpha)a = u*v*dx + dt*inner(nabla_grad(u), nabla_grad(v))*dxL = (u_k + dt*f)*v*dx

57 / 67

Page 85: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example14.py: cont’d

A = assemble(a) # assemble only once, before the time steppingb = None # trick: first time through loop below, assemble creates b

# Timestep loopu = Function(V) # the unknown at a new time levelT = 1.9 # total simulation timet = dt

while t <= T:print "time =", t ,b = assemble(L, tensor=b)u0.t = tbc.apply(A, b)solve(A, u.vector(), b) # trick

# Verifyu_e = interpolate(u0, V)diff = numpy.abs(u_e.vector().array() - u.vector().array())print "Max error: %-10.3e" % diff.max()

t += dtu_k.assign(u)

58 / 67

Page 86: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example14.py: cont’d

A = assemble(a) # assemble only once, before the time steppingb = None # trick: first time through loop below, assemble creates b

# Timestep loopu = Function(V) # the unknown at a new time levelT = 1.9 # total simulation timet = dtwhile t <= T:

print "time =", t ,b = assemble(L, tensor=b)u0.t = tbc.apply(A, b)solve(A, u.vector(), b) # trick

# Verifyu_e = interpolate(u0, V)diff = numpy.abs(u_e.vector().array() - u.vector().array())print "Max error: %-10.3e" % diff.max()

t += dtu_k.assign(u)

58 / 67

Page 87: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example14.py: cont’d

A = assemble(a) # assemble only once, before the time steppingb = None # trick: first time through loop below, assemble creates b

# Timestep loopu = Function(V) # the unknown at a new time levelT = 1.9 # total simulation timet = dtwhile t <= T:

print "time =", t ,b = assemble(L, tensor=b)u0.t = tbc.apply(A, b)solve(A, u.vector(), b) # trick

# Verifyu_e = interpolate(u0, V)diff = numpy.abs(u_e.vector().array() - u.vector().array())print "Max error: %-10.3e" % diff.max()

t += dtu_k.assign(u)

58 / 67

Page 88: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example14.py: cont’d

A = assemble(a) # assemble only once, before the time steppingb = None # trick: first time through loop below, assemble creates b

# Timestep loopu = Function(V) # the unknown at a new time levelT = 1.9 # total simulation timet = dtwhile t <= T:

print "time =", t ,b = assemble(L, tensor=b)u0.t = tbc.apply(A, b)solve(A, u.vector(), b) # trick

# Verifyu_e = interpolate(u0, V)diff = numpy.abs(u_e.vector().array() - u.vector().array())print "Max error: %-10.3e" % diff.max()

t += dtu_k.assign(u)

58 / 67

Page 89: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example14.py: cont’d

A = assemble(a) # assemble only once, before the time steppingb = None # trick: first time through loop below, assemble creates b

# Timestep loopu = Function(V) # the unknown at a new time levelT = 1.9 # total simulation timet = dtwhile t <= T:

print "time =", t ,b = assemble(L, tensor=b)u0.t = tbc.apply(A, b)solve(A, u.vector(), b) # trick

# Verifyu_e = interpolate(u0, V)diff = numpy.abs(u_e.vector().array() - u.vector().array())print "Max error: %-10.3e" % diff.max()

t += dtu_k.assign(u)

58 / 67

Page 90: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example14.py: cont’d

A = assemble(a) # assemble only once, before the time steppingb = None # trick: first time through loop below, assemble creates b

# Timestep loopu = Function(V) # the unknown at a new time levelT = 1.9 # total simulation timet = dtwhile t <= T:

print "time =", t ,b = assemble(L, tensor=b)u0.t = tbc.apply(A, b)solve(A, u.vector(), b) # trick

# Verifyu_e = interpolate(u0, V)diff = numpy.abs(u_e.vector().array() - u.vector().array())print "Max error: %-10.3e" % diff.max()

t += dtu_k.assign(u)

58 / 67

Page 91: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Exercise 18 (15 points)

1. example14.py implements the backward or implicit Eulermethod. In this exercise, you are to modify that program toimplement the Crank-Nicolson method.

uk+1 − uk

∆t= ∆

(uk+1 + uk

2

)+

f k+1 + f k

2

2. This method is second order in time, so it is exact for quadraticfunctions of t . Modify the exact solution so it includes a t2 termand demonstrate numerically that the error on each timestep iszero or roundoff.

59 / 67

Page 92: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Efficiency

I You should assemble the constant matrices onceI Right side vectors need to be assembled each stepI Much of the work can be compressed into matrix-vector products

60 / 67

Page 93: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Saving matrices

I Weak form

(uk+1, v) + ∆t(∇uk+1,∇v) = (uk , v) + (f k+1, v)

I Assembles to

(M + ∆tK )Uk+1 = MUk + MF k

Mij = (φi , φj ) Kij = (∇φi ,∇φj ) u =∑

i

Uiφi f ≈∑

i

Fiφi

I It is usually cheaper in 3D to save M than to assemble the rightside each timestep.

I In 2D problems, it depends on the details.

61 / 67

Page 94: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Exercise 19 (5 points)

Modify example14.py to construct and store the matrix M andreplace the assembly of the right side vector b with multiplication myM. Be sure that your program still results in roundoff-sized errors.

62 / 67

Page 95: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Automated timestepping

I ODE integrators are availableI PETSc has themI Perhaps FEniCS will take advantage in the futureI You could call PETSc functions directlyI petsc4py or C++

63 / 67

Page 96: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

Topics

Geometry

Elements

Nonlinear problems

Transient problems

Eigenvalue problems

64 / 67

Page 97: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example15.py: Use SLEPc for eigenpairs

# Define basis and bilinear form (Laplace matrix)u = TrialFunction(V)v = TestFunction(V)a = dot(grad(u), grad(v))*dx

# Assemble stiffness formA = PETScMatrix()assemble(a, tensor=A)

# Create eigensolvereigensolver = SLEPcEigenSolver(A)

# Compute all eigenvalues of A x = \lambda xprint "Computing eigenvalues. This can take a minute."eigensolver.solve()

# Extract largest (first) eigenpairr, c, rx, cx = eigensolver.get_eigenpair(0)

65 / 67

Page 98: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example15.py: Use SLEPc for eigenpairs

# Define basis and bilinear form (Laplace matrix)u = TrialFunction(V)v = TestFunction(V)a = dot(grad(u), grad(v))*dx

# Assemble stiffness formA = PETScMatrix()assemble(a, tensor=A)

# Create eigensolvereigensolver = SLEPcEigenSolver(A)

# Compute all eigenvalues of A x = \lambda xprint "Computing eigenvalues. This can take a minute."eigensolver.solve()

# Extract largest (first) eigenpairr, c, rx, cx = eigensolver.get_eigenpair(0)

65 / 67

Page 99: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example15.py: Use SLEPc for eigenpairs

# Define basis and bilinear form (Laplace matrix)u = TrialFunction(V)v = TestFunction(V)a = dot(grad(u), grad(v))*dx

# Assemble stiffness formA = PETScMatrix()assemble(a, tensor=A)

# Create eigensolvereigensolver = SLEPcEigenSolver(A)

# Compute all eigenvalues of A x = \lambda xprint "Computing eigenvalues. This can take a minute."eigensolver.solve()

# Extract largest (first) eigenpairr, c, rx, cx = eigensolver.get_eigenpair(0)

65 / 67

Page 100: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example15.py: Use SLEPc for eigenpairs

# Define basis and bilinear form (Laplace matrix)u = TrialFunction(V)v = TestFunction(V)a = dot(grad(u), grad(v))*dx

# Assemble stiffness formA = PETScMatrix()assemble(a, tensor=A)

# Create eigensolvereigensolver = SLEPcEigenSolver(A)

# Compute all eigenvalues of A x = \lambda xprint "Computing eigenvalues. This can take a minute."eigensolver.solve()

# Extract largest (first) eigenpairr, c, rx, cx = eigensolver.get_eigenpair(0)

65 / 67

Page 101: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example15.py: Use SLEPc for eigenpairs

# Define basis and bilinear form (Laplace matrix)u = TrialFunction(V)v = TestFunction(V)a = dot(grad(u), grad(v))*dx

# Assemble stiffness formA = PETScMatrix()assemble(a, tensor=A)

# Create eigensolvereigensolver = SLEPcEigenSolver(A)

# Compute all eigenvalues of A x = \lambda xprint "Computing eigenvalues. This can take a minute."eigensolver.solve()

# Extract largest (first) eigenpairr, c, rx, cx = eigensolver.get_eigenpair(0)

65 / 67

Page 102: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

SLEPc parametersI prm = eigensolver.parametersinfo(prm, True)

I pydoc dolfin.SLEPcEigenSolver

I “spectrum”: “largest magnitude”, “smallestmagnitude”, “largest real”, “smallest real”,“largest imaginary”, “smallest imaginary”“target real”, “target imaginary”

I “solver”I “tolerance” (default 1.e-15)I “maximum_iterations” (positive integer)I “problem_type”: “hermitian”, “non_hermitian”,“gen_hermitian”, “gen_non_hermitian”,“pos_gen_non_hermitian”

I Generalized problem: Ax = λBxI “spectral_transform”: “shift-and-invert”I “spectral_shift” (real number)

66 / 67

Page 103: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

SLEPc parametersI prm = eigensolver.parametersinfo(prm, True)

I pydoc dolfin.SLEPcEigenSolverI “spectrum”: “largest magnitude”, “smallestmagnitude”, “largest real”, “smallest real”,“largest imaginary”, “smallest imaginary”“target real”, “target imaginary”

I “solver”I “tolerance” (default 1.e-15)I “maximum_iterations” (positive integer)I “problem_type”: “hermitian”, “non_hermitian”,“gen_hermitian”, “gen_non_hermitian”,“pos_gen_non_hermitian”

I Generalized problem: Ax = λBxI “spectral_transform”: “shift-and-invert”I “spectral_shift” (real number)

66 / 67

Page 104: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

SLEPc parametersI prm = eigensolver.parametersinfo(prm, True)

I pydoc dolfin.SLEPcEigenSolverI “spectrum”: “largest magnitude”, “smallestmagnitude”, “largest real”, “smallest real”,“largest imaginary”, “smallest imaginary”“target real”, “target imaginary”

I “solver”I “tolerance” (default 1.e-15)I “maximum_iterations” (positive integer)I “problem_type”: “hermitian”, “non_hermitian”,“gen_hermitian”, “gen_non_hermitian”,“pos_gen_non_hermitian”

I Generalized problem: Ax = λBxI “spectral_transform”: “shift-and-invert”I “spectral_shift” (real number)

66 / 67

Page 105: FEniCS, part IIIsussmanm/3040Summer14/fenicsIII.pdf · FEniCS, part III M. M. Sussman sussmanm@math.pitt.edu Office Hours: 11:10AM-12:10PM, Thack 622 May 12 – June 19, 2014 1/67

example15.py output

Mesh

Eigenvectors 1 and 200

67 / 67