def error_function(u_e, u, norm="L2"): """ Compute the error between estimated solution u and exact solution u_e in the specified norm. """ # Get function space V = u.function_space() if norm == "L2": # L2 norm # Explicit computation of L2 norm # E = ((u_e - u) ** 2) * F.dx # error = np.sqrt(np.abs(F.assemble(E))) # Implicit interpolation of u_e to higher-order elements. # u will also be interpolated to the space Ve before integration error = F.errornorm(u_e, u, norm_type="L2", degree_rise=3) elif norm == "H10": # H^1_0 seminorm error = F.errornorm(u_e, u, norm_type="H10", degree_rise=3) elif norm == "max": # max/infinity norm u_e_ = F.interpolate(u_e, V) error = np.abs(np.array(u_e_.vector()) - np.array(u.vector())).max() return error
def problem(f, nx=8, ny=8, degrees=[1,2]): """ Plot u along x=const or y=const for Lagrange elements, of given degrees, on a nx times ny mesh. f is a SymPy expression. """ f = sym.printing.ccode(f) f = fe.Expression(f) mesh = fe.RectangleMesh( fe.Point(-1, 0), fe.Point(1, 2), 2, 2) for degree in degrees: if degree == 0: # The P0 element is specified like this in FEniCS V = fe.FunctionSpace(mesh, 'DG', 0) else: # The Lagrange Pd family of elements, d=1,2,3,... V = fe.FunctionSpace(mesh, 'P', degree) u = fe.project(f, V) u_error = fe.errornorm(f, u, 'L2') print '||u-f||=%g' % u_error, degree comparison_plot2D( u, f, n=50, value=0.4, variation='x', plottitle='Approximation by P%d elements' % degree, filename='approx_fenics_by_P%d' % degree, tol=1E-3)
def problem(f, nx=8, ny=8, degrees=[1, 2]): """ Plot u along x=const or y=const for Lagrange elements, of given degrees, on a nx times ny mesh. f is a SymPy expression. """ f = sym.printing.ccode(f) f = fe.Expression(f, degree=2) mesh = fe.RectangleMesh(fe.Point(-1, 0), fe.Point(1, 2), 2, 2) for degree in degrees: if degree == 0: # The P0 element is specified like this in FEniCS V = fe.FunctionSpace(mesh, 'DG', 0) else: # The Lagrange Pd family of elements, d=1,2,3,... V = fe.FunctionSpace(mesh, 'P', degree) u = fe.project(f, V) u_error = fe.errornorm(f, u, 'L2') print('||u-f||=%g' % u_error, degree) comparison_plot2D(u, f, n=50, value=0.4, variation='x', plottitle='Approximation by P%d elements' % degree, filename='approx_fenics_by_P%d' % degree, tol=1E-3)
def solve_poisson_eps(h, eps, plot=False): eps = fe.Constant(eps) n = int(1 / h) # Create mesh and define function space mesh = fe.UnitIntervalMesh(n) V = fe.FunctionSpace(mesh, 'P', 1) # Define boundary condition u_D = fe.Constant(0.0) # Find exact solution: u_exact = fe.Expression( "(1./2 - x[0]) * (2 * x[0] + eps/(2*pi) * sin(2*pi*x[0]/eps)) " "+ eps*eps/(2*pi*2*pi) * (1 - cos(2*pi*x[0]/eps)) + x[0]*x[0]", eps=eps, degree=4) def boundary(x, on_boundary): return on_boundary bc = fe.DirichletBC(V, u_D, boundary) # Define variational problem u = fe.TrialFunction(V) v = fe.TestFunction(V) f = fe.Constant(1) A = fe.Expression('1./(2+cos(2*pi*x[0]/eps))', eps=eps, degree=2) a = A * fe.dot(fe.grad(u), fe.grad(v)) * fe.dx L = f * v * fe.dx # Compute solution u = fe.Function(V) fe.solve(a == L, u, bc) if plot: # Plot solution fe.plot(u) fe.plot(u_exact, mesh=mesh) # Hold plot fe.interactive() # # Save solution to file in VTK format # vtkfile = fe.File('poisson/solution.pvd') # vtkfile << u # Compute error err_norm = fe.errornorm(u_exact, u, 'L2') return err_norm
def compute_error(self): if self.mode != 'test': return error_L2 = fe.errornorm(self.boundary_fun, self.u_n, 'L2') error_LI = np.abs(\ fe.interpolate(\ self.boundary_fun,self.function_space).vector().get_local() -\ self.u_n.vector().get_local()\ ).max() print('L2 error at t = {:.3f}: {:.2e}'.format(\ self.current_time, error_L2)) print('LI error at t = {:.3f}: {:.2e}'.format(\ self.current_time, error_LI)) self.error_list.append(error_L2)
u = fex.Function(V) fex.solve(a == L, u, bc) print(u) # Plot solution and mesh plt.subplot(2, 1, 1) fex.plot(u) #define the boundary conditions plt.subplot(2, 1, 2) fex.plot(mesh) plt.savefig('possion_fex2.png') #define the boundary conditions # Save solution to file in VTK format vtkfile = fex.File('poisson/solution.pvd') vtkfile << u # Compute error in L2 norm error_L2 = fex.errornorm(u_D, u, 'L2') # Compute maximum error at vertices vertex_values_u_D = u_D.compute_vertex_values(mesh) vertex_values_u = u.compute_vertex_values(mesh) import numpy as np error_max = np.max(np.abs(vertex_values_u_D - vertex_values_u)) # Print errors print('error_L2 =', error_L2) print('error_max =', error_max) # Hold plot #plt.show()
def staggered_solve(self): self.U = fe.VectorFunctionSpace(self.mesh, 'CG', 1) self.W = fe.FunctionSpace(self.mesh, 'CG', 1) self.WW = fe.FunctionSpace(self.mesh, 'DG', 0) self.EE = fe.TensorFunctionSpace(self.mesh, 'DG', 0) self.MM = fe.VectorFunctionSpace(self.mesh, 'CG', 1) self.eta = fe.TestFunction(self.U) self.zeta = fe.TestFunction(self.W) q = fe.TestFunction(self.WW) del_x = fe.TrialFunction(self.U) del_d = fe.TrialFunction(self.W) p = fe.TrialFunction(self.WW) self.x_new = fe.Function(self.U, name="u") self.d_new = fe.Function(self.W, name="d") self.d_pre = fe.Function(self.W) self.x_pre = fe.Function(self.U) x_old = fe.Function(self.U) d_old = fe.Function(self.W) self.H_old = fe.Function(self.WW) self.map_plot = fe.Function(self.MM, name="m") e = fe.Function(self.EE, name="e") self.create_custom_xdmf_files() self.file_results = fe.XDMFFile('data/xdmf/{}/u.xdmf'.format( self.case_name)) self.file_results.parameters["functions_share_mesh"] = True vtkfile_e = fe.File('data/pvd/simulation/{}/e.pvd'.format( self.case_name)) vtkfile_u = fe.File('data/pvd/simulation/{}/u.pvd'.format( self.case_name)) vtkfile_d = fe.File('data/pvd/simulation/{}/d.pvd'.format( self.case_name)) for i, (disp, rp) in enumerate( zip(self.displacements, self.relaxation_parameters)): print('\n') print( '=================================================================================' ) print('>> Step {}, disp boundary condition = {} [mm]'.format( i, disp)) print( '=================================================================================' ) self.i = i self.update_weak_form_due_to_Model_C_bug() if self.update_weak_form: self.set_bcs_staggered() print("Update weak form...") self.build_weak_form_staggered() print("Taking derivatives of weak form...") J_u = fe.derivative(self.G_u, self.x_new, del_x) J_d = fe.derivative(self.G_d, self.d_new, del_d) print("Define nonlinear problems...") p_u = fe.NonlinearVariationalProblem(self.G_u, self.x_new, self.BC_u, J_u) p_d = fe.NonlinearVariationalProblem(self.G_d, self.d_new, self.BC_d, J_d) print("Define solvers...") solver_u = fe.NonlinearVariationalSolver(p_u) solver_d = fe.NonlinearVariationalSolver(p_d) self.update_weak_form = False print("Update history weak form") a = p * q * fe.dx L = history(self.H_old, self.update_history(), self.psi_cr) * q * fe.dx if self.map_flag: self.interpolate_map() # delta_x = self.x - self.x_hat # self.map_plot.assign(fe.project(delta_x, self.MM)) self.presLoad.t = disp newton_prm = solver_u.parameters['newton_solver'] newton_prm['maximum_iterations'] = 100 # newton_prm['absolute_tolerance'] = 1e-8 newton_prm['relaxation_parameter'] = rp newton_prm = solver_d.parameters['newton_solver'] newton_prm['maximum_iterations'] = 100 # newton_prm['absolute_tolerance'] = 1e-8 newton_prm['relaxation_parameter'] = rp vtkfile_e_staggered = fe.File( 'data/pvd/simulation/{}/step{}/e.pvd'.format( self.case_name, i)) vtkfile_u_staggered = fe.File( 'data/pvd/simulation/{}/step{}/u.pvd'.format( self.case_name, i)) vtkfile_d_staggered = fe.File( 'data/pvd/simulation/{}/step{}/d.pvd'.format( self.case_name, i)) iteration = 0 err = 1. while err > self.staggered_tol: iteration += 1 solver_d.solve() solver_u.solve() if self.solution_scheme == 'explicit': break # # Remarks(Tianju): self.x_new.vector() does not behave as expected: producing nan values # The following lines of codes cause issues # We use an error measure similar in https://doi.org/10.1007/s10704-019-00372-y # np_x_new = np.asarray(self.x_new.vector()) # np_d_new = np.asarray(self.d_new.vector()) # np_x_old = np.asarray(x_old.vector()) # np_d_old = np.asarray(d_old.vector()) # err_x = np.linalg.norm(np_x_new - np_x_old) / np.sqrt(len(np_x_new)) # err_d = np.linalg.norm(np_d_new - np_d_old) / np.sqrt(len(np_d_new)) # err = max(err_x, err_d) # # Remarks(Tianju): dolfin (2019.1.0) errornorm function has severe bugs not behave as expected # The bug seems to be fixed in later versions # The following sometimes produces nonzero results in dolfin (2019.1.0) # print(fe.errornorm(self.d_new, self.d_new, norm_type='l2')) err_x = fe.errornorm(self.x_new, x_old, norm_type='l2') err_d = fe.errornorm(self.d_new, d_old, norm_type='l2') err = max(err_x, err_d) x_old.assign(self.x_new) d_old.assign(self.d_new) e.assign( fe.project(strain(self.mfem_grad(self.x_new)), self.EE)) print( '---------------------------------------------------------------------------------' ) print( '>> iteration. {}, err_u = {:.5}, err_d = {:.5}, error = {:.5}' .format(iteration, err_x, err_d, err)) print( '---------------------------------------------------------------------------------' ) # vtkfile_e_staggered << e # vtkfile_u_staggered << self.x_new # vtkfile_d_staggered << self.d_new if err < self.staggered_tol or iteration >= self.staggered_maxiter: print( '=================================================================================' ) print('\n') break print("L2 projection to update the history function...") fe.solve(a == L, self.H_old, []) # self.d_pre.assign(self.d_new) # self.H_old.assign(fe.project(history(self.H_old, self.update_history(), self.psi_cr), self.WW)) if self.map_flag and not self.finish_flag: self.update_map() if self.compute_and_save_intermediate_results: print("Save files...") self.file_results.write(e, i) self.file_results.write(self.x_new, i) self.file_results.write(self.d_new, i) self.file_results.write(self.map_plot, i) vtkfile_e << e vtkfile_u << self.x_new vtkfile_d << self.d_new # Assume boundary is not affected by the map. # There's no need to use the mfem_grad wrapper so that fe.grad is used for speed-up print("Define forces...") sigma = cauchy_stress_plus(strain(fe.grad(self.x_new)), self.psi) sigma_minus = cauchy_stress_minus(strain(fe.grad(self.x_new)), self.psi_minus) sigma_plus = cauchy_stress_plus(strain(fe.grad(self.x_new)), self.psi_plus) sigma_degraded = g_d(self.d_new) * sigma_plus + sigma_minus print("Compute forces...") if self.case_name == 'pure_shear': f_full = float(fe.assemble(sigma[0, 1] * self.ds(1))) f_degraded = float( fe.assemble(sigma_degraded[0, 1] * self.ds(1))) else: f_full = float(fe.assemble(sigma[1, 1] * self.ds(1))) f_degraded = float( fe.assemble(sigma_degraded[1, 1] * self.ds(1))) print("Force full is {}".format(f_full)) print("Force degraded is {}".format(f_degraded)) self.delta_u_recorded.append(disp) self.force_full.append(f_full) self.force_degraded.append(f_degraded) # if force_upper < 0.5 and i > 10: # break if self.display_intermediate_results and i % 10 == 0: self.show_force_displacement() self.save_data_in_loop() if self.display_intermediate_results: plt.ioff() plt.show()
x = ufl.SpatialCoordinate(mesh) w = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) f_analytic = 1 / (1 + alpha * 4 * ufl.pi ** 4) * w u_analytic = 1 / (2 * ufl.pi ** 2) * f_analytic f_opt = from_numpy(res.x, fn.Function(W)) u = fn.Function(V) v = fn.TestFunction(V) F = (ufl.inner(ufl.grad(u), ufl.grad(v)) - f_opt * v) * ufl.dx bc = fn.DirichletBC(V, 0.0, "on_boundary") fn.solve(F == 0, u, bc) print(f"norm of f_opt is {fn.norm(f_opt)}") # interpolatation of UFL forms does not work in FEniCS, hence projection CG3 = fn.FunctionSpace(mesh, "CG", 3) control_error = fn.errornorm(fn.project(f_analytic, CG3), f_opt) state_error = fn.errornorm(fn.project(u_analytic, CG3), u) print("h(min): %e." % mesh.hmin()) print("Error in state: %e." % state_error) print("Error in control: %e." % control_error) # Write solutions to XDMFFile, can be visualized with paraview # First time step is approximated solution, second timestep is analytic # solution out_f = fn.XDMFFile("output/f_jax_scipy.xdmf") out_f.write_checkpoint(f_opt, "f", 0.0, fn.XDMFFile.Encoding.HDF5, True) out_f.write_checkpoint( fn.project(f_analytic, W), "f", 1.0, fn.XDMFFile.Encoding.HDF5, True )
u = fs.TrialFunction(V) v = fs.TestFunction(V) f = fs.Constant(-6.0) a = fs.dot(fs.grad(u), fs.grad(v)) * fs.dx L = f * v * fs.dx # compute solution u = fs.Function(V) fs.solve(a == L, u, bc) # plot solution and mesh fs.plot(u) fs.plot(mesh) # save solution to file in VTK format vtkfile = fs.File('solution.pvd') vtkfile << u # compute error in L2 norm error_L2 = fs.errornorm(u_D, u, 'L2') # #compute maximum error at vertices vertex_values_u_D = u_D.compute_vertex_values(mesh) vertex_values_u = u.compute_vertex_values(mesh) error_max = np.max(np.abs(vertex_values_u_D - vertex_values_u)) # print errors print('error_L2 =', error_L2) print('error_max = ', error_max) plt.savefig('newtest', Format='png')
def staggered_solve(self): self.U = fe.VectorFunctionSpace(self.mesh, 'CG', 1) self.W = fe.FunctionSpace(self.mesh, 'CG', 1) self.WW = fe.FunctionSpace(self.mesh, 'DG', 0) self.eta = fe.TestFunction(self.U) self.zeta = fe.TestFunction(self.W) del_x = fe.TrialFunction(self.U) del_d = fe.TrialFunction(self.W) self.x_new = fe.Function(self.U) self.d_new = fe.Function(self.W) x_old = fe.Function(self.U) d_old = fe.Function(self.W) self.H_old = fe.Function(self.WW) self.build_weak_form_staggered() J_u = fe.derivative(self.G_u, self.x_new, del_x) J_d = fe.derivative(self.G_d, self.d_new, del_d) self.set_bcs_staggered() p_u = fe.NonlinearVariationalProblem(self.G_u, self.x_new, self.BC_u, J_u) p_d = fe.NonlinearVariationalProblem(self.G_d, self.d_new, self.BC_d, J_d) solver_u = fe.NonlinearVariationalSolver(p_u) solver_d = fe.NonlinearVariationalSolver(p_d) vtkfile_u = fe.File('data/pvd/{}/u.pvd'.format(self.case_name)) vtkfile_d = fe.File('data/pvd/{}/d.pvd'.format(self.case_name)) for i, (disp, rp) in enumerate( zip(self.displacements, self.relaxation_parameters)): print('\n') print( '=================================================================================' ) print('>> Step {}, disp boundary condition = {} [mm]'.format( i, disp)) print( '=================================================================================' ) self.H_old.assign( fe.project( history(self.H_old, self.psi(strain(fe.grad(self.x_new))), self.psi_cr), self.WW)) self.presLoad.t = disp newton_prm = solver_u.parameters['newton_solver'] newton_prm['maximum_iterations'] = 100 newton_prm['absolute_tolerance'] = 1e-4 newton_prm['relaxation_parameter'] = rp iteration = 0 err = 1. while err > self.staggered_tol: iteration += 1 solver_d.solve() solver_u.solve() err_u = fe.errornorm(self.x_new, x_old, norm_type='l2', mesh=None) err_d = fe.errornorm(self.d_new, d_old, norm_type='l2', mesh=None) err = max(err_u, err_d) x_old.assign(self.x_new) d_old.assign(self.d_new) print( '---------------------------------------------------------------------------------' ) print('>> iteration. {}, error = {:.5}'.format(iteration, err)) print( '---------------------------------------------------------------------------------' ) if err < self.staggered_tol or iteration >= self.staggered_maxiter: print( '=================================================================================' ) print('\n') self.x_new.rename("u", "u") self.d_new.rename("d", "d") vtkfile_u << self.x_new vtkfile_d << self.d_new break force_upper = float(fe.assemble(self.sigma[1, 1] * self.ds(1))) print("Force upper {}".format(force_upper)) self.delta_u_recorded.append(disp) self.sigma_recorded.append(force_upper)
# Define variational problem u = TrialFunction(V) v = TestFunction(V) f = Constant(-6.0) a = dot(grad(u), grad(v)) * dx L = f * v * dx # Compute solution u = Function(V) solve(a == L, u, bc) # since u is created as a Function object, it can be evaluated at any new point - although # this is an expensive operation! # Compute error in L2 norm error_L2 = errornorm(u_D, u, 'L2') # Compute maximum error at vertices vertex_values_u_D = u_D.compute_vertex_values(mesh) vertex_values_u = u.compute_vertex_values(mesh) # plot solution plt.figure() plt.contourf(vertex_values_u.reshape(*(grid_shape + 1)), cmap='viridis') plt.show() error_max = np.max(np.abs(vertex_values_u_D - vertex_values_u)) # Print errors print('error_L2 =', error_L2) print('error_max =', error_max)
bc = fe.DirichletBC(V, u_D, boundary) #define variational problem u = fe.TrialFunction(V) v = fe.TestFunction(V) f = fe.Constant(-6.0) a = (fe.dot(fe.grad(u), fe.grad(v))) * fe.dx L = f * v * fe.dx #compute the solution u = fe.Function(V) fe.solve(a == L, u, bc) #plot solution and mesh fe.plot(u) fe.plot(mesh) #save the solution into a vtk file vtkfile = fe.File("poisson/solution.pvd") vtkfile << u #compute the error error_l2 = fe.errornorm(u_D, u, "L2") print("The overall L2 error is given by: " + str(error_l2) + "\n") #maximum error at vertices vertex_values_u_D = u_D.compute_vertex_values(mesh) vertex_values_u = u.compute_vertex_values(mesh) max_vertex_error = np.max(np.abs(vertex_values_u_D - vertex_values_u)) print("Maximum vertex error given by: " + str(max_vertex_error) + "\n")