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 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_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 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 local_mass_matrix(): # Define mesh mesh = UnitIntervalMesh(1) # Define function space V = FunctionSpace(mesh, "Lagrange", 1) # Define trial and test functions u = TrialFunction(V) v = TestFunction(V) # Define bilinear form a = (dot(grad(u), grad(v)) + u * v) * dx # Assemble matrix A = assemble(a) print(A.array()) # Bilinear form for just the mass matrix part a2 = u * v * dx # Assemble mass matrix A2 = assemble(a2) print(6 * A2.array())
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 plot_basis_function(): # Declare mesh and FEM functions mesh = UnitSquareMesh(10, 10) V = FunctionSpace(mesh, "CG", 1) phi = Function(V) phi.vector()[:] = 0.0 phi.vector()[10] = 1.0 # Plot the basis function fig = plt.figure() plot(phi, fig=fig) plt.show() val = assemble(phi * phi * dx) print(val)
def compute_error(u1, u2): # Reference mesh mesh_resolution_ref = 500 mesh_ref = UnitIntervalMesh(mesh_resolution_ref) # Reference function space V_ref = FunctionSpace(mesh_ref, "CG", 1) # Evaluate the input functions on the reference mesh Iu1 = interpolate(u1, V_ref) Iu2 = interpolate(u2, V_ref) # Compute the error e = Iu1 - Iu2 error = sqrt(assemble(e * e * dx)) return error
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 global_stiffness_matrix(): # Define mesh mesh = UnitIntervalMesh(10) # Define function space V = FunctionSpace(mesh, "Lagrange", 1) # Define trial and test functions u = TrialFunction(V) v = TestFunction(V) # Define bilinear form a = dot(grad(u), grad(v)) * dx # Assemble matrix A = assemble(a) h = 1 / 10 print(h * A.array())
def automated_fenics_assembly(): mesh = UnitSquareMesh(5, 5) mesh.init() A, b = myassemble(mesh) f = Constant(1) V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx L = f * v * dx A1, b1 = assemble_system(a, L) B = A - A1.array() print("The norm of B is {}".format(np.linalg.norm(B))) print("A = ") print(A) print("A1 = ") print(A1.array())
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
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_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_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
point_in_subdomain(v.point()) == num for v in vertices(f_mesh)): facet_function[f_mesh] = num set = True if not set: facet_function[f_mesh] = 1 # wall plot(facet_function) f_mesh = HDF5File(mpi_comm_world(), 'meshes/' + meshName + '.hdf5', 'w') f_mesh.write(mesh, 'mesh') f_mesh.write(facet_function, 'facet_function') f_mesh.close() # compute volume of mesh V = FunctionSpace(mesh, 'Lagrange', 1) one = interpolate(Expression('1.'), V) volume = assemble(one * dx) # compute real areas of boudary parts for obj in itertools.chain(inflows, outflows): dS = Measure("ds", subdomain_id=obj['number'], subdomain_data=facet_function) obj['S'] = assemble(one * dS) # compute reference coefs for inf in inflows: inf['reference_coef'] = inf['reference_radius'] * inf[ 'reference_radius'] / (inf['radius'] * inf['radius'])
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())