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 solve(self, spaceV): u = TrialFunction(spaceV) v = TestFunction(spaceV) solution = Function(spaceV) a = self.kappa.expression * np.inner(nabla_grad(u), nabla_grad(v)) * dx L = self.rhs_f * v * dx bc = DirichletBC(spaceV, self.bcExpression, self.bcBoundary) solve(a == L, solution, bc) return solution
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 compute_projection_error_solve(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 = Function(V) v = TestFunction(V) r = inner(Pu - u, v)*dx solve(r == 0, Pu) 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 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 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