def solve_equation(): mesh = UnitSquareMesh(32, 32) V = FunctionSpace(mesh, "Lagrange", 1) def boundary(x, on_boundary): return on_boundary u0 = Expression("cos(10 * x[0])", degree=2) bc = DirichletBC(V, u0, boundary) u = TrialFunction(V) v = TestFunction(V) f = Expression("(x[0] - 0.5)*(x[0] - 0.5)", degree=2) a = inner(grad(u), grad(v)) * dx L = f * v * dx u = Function(V) solve(a == L, u, bc) # Plot solution at current time step fig = plt.figure() plot(u, fig=fig) plt.show() print("The norm of u is {}".format(u.vector().norm("l2")))
def compute_interpolation_error(mesh_resolution=20): # Define domain and mesh a, b = 0, 1 mesh = IntervalMesh(mesh_resolution, a, b) # Define finite element function space p_order = 1 V = FunctionSpace(mesh, "CG", p_order) # Extract vertices of the mesh x = V.tabulate_dof_coordinates() # Note: Not the same as x = mesh.coordinates() (apparently has been re-ordered) # Express the analytical function u = Expression("1 + x[0] * sin(10 * x[0])", degree=5) # Interpolate u onto V and extract the values in the mesh nodes Iu = interpolate(u, V) Iua = Iu.vector().array() # Evaluate u at the mesh vertices Eua = np.empty(len(x)) for i in range(len(x)): Eua[i] = 1 + x[i] * math.sin(10 * x[i]) # Compute max interpolation error in the nodes e = Eua - Iua e_abs = np.absolute(e) error = np.amax(e_abs) return error
def compute_projection_error(mesh_resolution=20, p_order=1): # Define domain and mesh a, b = 0, 1 mesh = IntervalMesh(mesh_resolution, a, b) # Define finite element function space V = FunctionSpace(mesh, "CG", p_order) # Extract vertices of the mesh x = V.dofmap().tabulate_all_coordinates(mesh) indices = np.argsort(x) # Express the analytical function u = Expression("1 + 4 * x[0] * x[0] - 5 * x[0] * x[0] * x[0]", degree=5) # Project u onto V and extract the values in the mesh nodes Pu = project(u, V) Pua = Pu.vector().array() # Create a function in the finite element function space V Eu = Function(V) Eua = Eu.vector().array() # Evaluate function in the mesh nodes for j in indices: Eua[j] = 1 + 4 * x[j] * x[j] - 5 * x[j] * x[j] * x[j] # Compute sum of projection error in the nodes e = Eua - Pua error = 0 for i in range(len(e)): error += abs(e[i]) return error
def compute_projection_error(mesh_resolution=20, p_order=1): # Define domain and mesh a, b = 0, 1 mesh = IntervalMesh(mesh_resolution, a, b) # Define finite element function space V = FunctionSpace(mesh, "CG", p_order) # Extract vertices of the mesh x = V.tabulate_dof_coordinates() # Note: Not the same as x = mesh.coordinates() (apparently has been re-ordered) # Express the analytical function u = Expression("1 + 4 * x[0] * x[0] - 5 * x[0] * x[0] * x[0]", degree=5) # Project u onto V and extract the values in the mesh nodes Pu = project(u, V) Pua = Pu.vector().array() # Create a function in the finite element function space V Eu = Function(V) Eua = Eu.vector().array() # Evaluate function in the mesh nodes for i in range(len(x)): Eua[i] = 1 + 4 * x[i]**2 - 5 * x[i]**3 # Compute sum of projection error in the nodes e = Eua - Pua error = 0 for i in range(len(e)): error += abs(e[i]) return error
def compare_errors(p_order=1): # Express the analytical function u = Expression("1 + sin(10*x[0])", degree=5) mesh_resolutions = [10, 50, 100, 200] projection_errors = [] interpolation_errors = [] for mesh_resolution in mesh_resolutions: # Define mesh mesh = UnitIntervalMesh(mesh_resolution) # Define finite element function space V = FunctionSpace(mesh, "CG", p_order) # Compute projection up = project(u, V) # Compute interpolation ui = interpolate(u, V) # Compute errors projection_errors.append(compute_error(u, up)) interpolation_errors.append(compute_error(u, ui)) print(projection_errors) print(interpolation_errors)
def simple_test(): # Declare mesh and FEM functions mesh = UnitSquareMesh(10, 10) V = FunctionSpace(mesh, "CG", 1) f = Expression("1.0 + sin(10 * x[0]) * cos(7 * x[1])", degree=3) v = TestFunction(V) u = Function(V) # FEM solution # Weak form of L2 projection r = (u - f) * v * dx # Solving the linear system generated by the L2 projection solve(r == 0, u) # Plot the FEM solution fig = plt.figure() plot(u, fig=fig) plt.show() print(u.vector().norm('linf'))
def solve_navier_stokes_equation(interior_circle=True, num_mesh_refinements=0): """ Solve the Navier-Stokes equation on a hard-coded mesh with hard-coded initial and boundary conditions """ mesh, om, im, nm, ymax, sub_domains = setup_geometry( interior_circle, num_mesh_refinements) dsi = Measure("ds", domain=mesh, subdomain_data=sub_domains) # Setup FEM function spaces # Function space for the velocity V = VectorFunctionSpace(mesh, "CG", 1) # Function space for the pressure Q = FunctionSpace(mesh, "CG", 1) # Mixed function space for velocity and pressure W = V * Q # Setup FEM functions v, q = TestFunctions(W) w = Function(W) (u, p) = (as_vector((w[0], w[1])), w[2]) u0 = Function(V) # Inlet velocity uin = Expression(("4*(x[1]*(YMAX-x[1]))/(YMAX*YMAX)", "0."), YMAX=ymax, degree=1) # Viscosity and stabilization parameters nu = 1e-6 h = CellSize(mesh) d = 0.2 * h**(3.0 / 2.0) # Time parameters time_step = 0.1 t_start, t_end = 0.0, 10.0 # Penalty parameter gamma = 10 / h # Time stepping t = t_start step = 0 while t < t_end: # Time discretization (Crank–Nicolson method) um = 0.5 * u + 0.5 * u0 # Navier-Stokes equations in weak residual form (stabilized FEM) # Basic residual r = (inner((u - u0) / time_step + grad(p) + grad(um) * um, v) + nu * inner(grad(um), grad(v)) + div(um) * q) * dx # Weak boundary conditions r += gamma * (om * p * q + im * inner(u - uin, v) + nm * inner(u, v)) * ds # Stabilization r += d * (inner(grad(p) + grad(um) * um, grad(q) + grad(um) * v) + inner(div(um), div(v))) * dx # Solve the Navier-Stokes equation (one time step) solve(r == 0, w) if step % 5 == 0: # Plot norm of velocity at current time step nov = project(sqrt(inner(u, u)), Q) fig = plt.figure() plot(nov, fig=fig) plt.show() # Compute drag force on circle n = FacetNormal(mesh) drag_force_measure = p * n[0] * dsi(1) # Drag (only pressure) drag_force = assemble(drag_force_measure) print("Drag force = " + str(drag_force)) # Shift to next time step t += time_step step += 1 u0 = project(u, V)
def setup_geometry(interior_circle=True, num_mesh_refinements=0): # Generate mesh xmin, xmax = 0.0, 4.0 ymin, ymax = 0.0, 1.0 mesh_resolution = 30 geometry1 = Rectangle(Point(xmin, ymin), Point(xmax, ymax)) center = Point(0.5, 0.5) r = 0.1 side_length = 0.1 if interior_circle: geometry2 = Circle(center, r) else: l2 = side_length / 2 geometry2 = Rectangle(Point(center[0] - l2, center[1] - l2), Point(center[0] + l2, center[1] + l2)) mesh = generate_mesh(geometry1 - geometry2, mesh_resolution) # Refine mesh around the interior boundary for i in range(0, num_mesh_refinements): cell_markers = MeshFunction("bool", mesh, mesh.topology().dim()) for c in cells(mesh): p = c.midpoint() cell_markers[c] = (abs(p[0] - .5) < .5 and abs(p[1] - .5) < .3 and c.diameter() > .1) or c.diameter() > .2 mesh = refine(mesh, cell_markers) # Mark regions for boundary conditions eps = 1e-5 # Part of the boundary with zero pressure om = Expression("x[0] > XMAX - eps ? 1. : 0.", XMAX=xmax, eps=eps, degree=1) # Part of the boundary with prescribed velocity im = Expression("x[0] < XMIN + eps ? 1. : 0.", XMIN=xmin, eps=eps, degree=1) # Part of the boundary with zero velocity nm = Expression("x[0] > XMIN + eps && x[0] < XMAX - eps ? 1. : 0.", XMIN=xmin, XMAX=xmax, eps=eps, degree=1) # Define interior boundary class InteriorBoundary(SubDomain): def inside(self, x, on_boundary): # Compute squared distance to interior object midpoint d2 = (x[0] - center[0])**2 + (x[1] - center[1])**2 return on_boundary and d2 < (2 * r)**2 # Create mesh function over the cell facets sub_domains = MeshFunction("size_t", mesh, mesh.topology().dim() - 1) # Mark all facets as sub domain 0 sub_domains.set_all(0) # Mark interior boundary facets as sub domain 1 interior_boundary = InteriorBoundary() interior_boundary.mark(sub_domains, 1) return mesh, om, im, nm, ymax, sub_domains
def solve_wave_equation(a, symmetric=True): """ Solve the wave equation on a hard-coded mesh with a hard-coded initial and boundary conditions :param a: Wave propagation factor :param symmetric: Whether or not the problem is symmetric """ mesh, boundary = setup_geometry() # Exact solution if symmetric: ue = Expression( "(1-pow(a*t-x[0],2))*exp(-pow(a*t-x[0],2)) + (1-pow(a*t+x[0],2))*exp(-pow(a*t+x[0],2))", a=a, t=0, domain=mesh, degree=2) ve = Expression( "2*a*(a*t-x[0])*(pow(a*t-x[0],2)-2)*exp(-pow(a*t-x[0],2))" "+ 2*a*(a*t+x[0])*(pow(a*t+x[0],2)-2)*exp(-pow(a*t+x[0],2))", a=a, t=0, domain=mesh, degree=2) else: ue = Expression("(1-pow(a*t+x[0],2))*exp(-pow(a*t+x[0],2))", a=a, t=0, domain=mesh, degree=2) ve = Expression( "2*a*(a*t+x[0])*(pow(a*t+x[0],2)-2)*exp(-pow(a*t+x[0],2))", a=a, t=0, domain=mesh, degree=2) # Polynomial degree r = 1 # Setup FEM function spaces Q = FunctionSpace(mesh, "CG", r) W = VectorFunctionSpace(mesh, "CG", r, dim=2) # Create boundary conditions bcu = DirichletBC(W.sub(0), ue, boundary) bcv = DirichletBC(W.sub(1), ve, boundary) bcs = [bcu, bcv] # Setup FEM functions p, q = TestFunctions(W) w = Function(W) u, v = w[0], w[1] # Time parameters time_step = 0.05 t_start, t_end = 0.0, 5.0 # Time stepping t = t_start u0 = ue v0 = ve step = 0 while t < t_end: # Weak form of the wave equation um = 0.5 * (u + u0) vm = 0.5 * (v + v0) a1 = (u - u0) / time_step * p * dx - vm * p * dx a2 = (v - v0) / time_step * q * dx + a**2 * inner(grad(um), grad(q)) * dx # Solve the wave equation (one time step) solve(a1 + a2 == 0, w, bcs) # Advance time in exact solution t += time_step ue.t = t ve.t = t if step % 10 == 0: # Plot solution at current time step fig = plt.figure() plot(u, fig=fig) plt.show() # Compute max error at vertices vertex_values_ue = ue.compute_vertex_values(mesh) vertex_values_w = w.compute_vertex_values(mesh) vertex_values_u = np.split(vertex_values_w, 2)[0] error_max = np.max(np.abs(vertex_values_ue - vertex_values_u)) # Print error print(error_max) # Shift to next time step u0 = project(u, Q) v0 = project(v, Q) step += 1
def solve_heat_equation(k, time_stepping_method): """ Solve the heat equation on a hard-coded mesh with a hard-coded initial and boundary conditions :param k: Thermal conductivity :param time_stepping_method: Time stepping method. Can be one of ["forward_euler", "backward_euler", "trapezoidal"] """ mesh, boundary = setup_geometry() # Exact solution (Gauss curve) ue = Expression("exp(-(x[0]*x[0]+x[1]*x[1])/(4*a*t))/(4*pi*a*t)", a=k, t=1e-7, domain=mesh, degree=1) # Polynomial degree r = 1 # Setup FEM function space V = FunctionSpace(mesh, "CG", r) # Create boundary condition bc = DirichletBC(V, ue, boundary) # Setup FEM functions v = TestFunction(V) u = Function(V) # Time parameters time_step = 0.001 t_start, t_end = 0.0, 20.0 # Time stepping t = t_start if time_stepping_method == "forward_euler": theta = 0.0 if time_stepping_method == "backward_euler": theta = 1.0 if time_stepping_method == "trapezoidal": theta = 0.5 u0 = ue step = 0 while t < t_end: # Intermediate value for u (depending on the chosen time stepping method) um = (1.0 - theta) * u0 + theta * u # Weak form of the heat equation a = (u - u0) / time_step * v * dx + k * inner(grad(um), grad(v)) * dx # Solve the heat equation (one time step) solve(a == 0, u, bc) # Advance time in exact solution t += time_step ue.t = t if step % 100 == 0: # Compute error in L2 norm error_L2 = errornorm(ue, u, 'L2') # or equivalently # sqrt(assemble((ue - u) * (ue - u) * dx)) # Compute norm of exact solution nue = norm(ue) # Print relative error print("Relative error = {}".format(error_L2 / nue)) # Shift to next time step u0 = project(u, V) step += 1
def solve_heat_equation(k): """ Solve the heat equation on a hard-coded mesh with a hard-coded initial and boundary conditions :param k: Thermal conductivity """ mesh, boundary = setup_geometry() # Exact solution (Gauss curve) ue = Expression("exp(-(x[0]*x[0]+x[1]*x[1])/(4*a*t))/(4*pi*a*t)", a=k, t=1e-7, domain=mesh, degree=2) # Polynomial degree r = 1 # Setup FEM function space V = FunctionSpace(mesh, "CG", r) # Create boundary condition bc = DirichletBC(V, ue, boundary) # Setup FEM functions v = TestFunction(V) u = Function(V) # Time parameters time_step = 0.5 t_start, t_end = 0.0, 20.0 # Time stepping t = t_start u0 = ue step = 0 while t < t_end: # Weak form of the heat equation a = (u - u0) / time_step * v * dx + k * inner(grad(u), grad(v)) * dx # Solve the heat equation (one time step) solve(a == 0, u, bc) # Advance time in exact solution t += time_step ue.t = t if step % 5 == 0: # Plot solution at current time step fig = plt.figure() plot(u, fig=fig) plt.show() # Compute error in L2 norm error_L2 = errornorm(ue, u, 'L2') # or equivalently # sqrt(assemble((ue - u) * (ue - u) * dx)) # Print error print(error_L2) # Shift to next time step u0 = project(u, V) step += 1
from dolfin import IntervalMesh from dolfin.fem.interpolation import interpolate from dolfin.functions import FunctionSpace, TestFunction, Function, Expression # Define domain and mesh a, b = 0, 1 mesh_resolution = 20 mesh = IntervalMesh(mesh_resolution, a, b) # Define finite element function space p_order = 1 V = FunctionSpace(mesh, "CG", p_order) # Interpolate function u = Expression("1 + 4.0 * x[0] * x[0] - 5.0 * x[0] * x[0] * x[0]", degree=5) Iu = interpolate(u, V) Iua = Iu.vector().array() print(Iua.max())