def flip_vectors(mesh, eigs, mesh_ref, eigs_ref, test_it=False): x_c = 1e-3 for i in range(len(eigs)): s = FESolution(mesh, eigs[i]) s_ref = FESolution(mesh_ref, eigs_ref[i]) if s.value(x_c) < 0: #print " Multiplying %d-th coarse eigenvector by (-1)" % i eigs[i] = -eigs[i] if s_ref.value(x_c) < 0: #print " Multiplying %d-th ref. eigenvector by (-1)" % i eigs_ref[i] = -eigs_ref[i] if test_it: # Test it: s = FESolution(mesh, eigs[i]).to_discrete_function() s_ref = FESolution(mesh_ref, eigs_ref[i]).to_discrete_function() same_norm = (s - s_ref).l2_norm() flipped_norm = (s + s_ref).l2_norm() print same_norm, flipped_norm if same_norm > flipped_norm: c = min(same_norm, flipped_norm) / max(same_norm, flipped_norm) print "Warning: the flip is wrong, c=", c # If "c" is almost one, then the vectors can't really be # aligned anyway: assert c > 0.9
def project_onto(self, mesh, proj_type="Fekete"): """ Projects 'self' onto the 'mesh' using the 'proj_type' projection. proj_type == "Fekete"/"L2"/"H1" """ if mesh == self._mesh: return self if proj_type == "Fekete": return Function(self, mesh) elif proj_type in ["L2", "H1"]: from hermes1d.h1d_wrapper.h1d_wrapper import \ (assemble_projection_matrix_rhs, Mesh, FESolution) from hermes1d.hermes_common.matrix import CSCMatrix, AVector pts, orders = mesh.get_mesh_data() m = Mesh(pts, orders) n_dof = m.assign_dofs() A = CSCMatrix(n_dof) rhs = AVector(n_dof) assemble_projection_matrix_rhs(m, A, rhs, self, projection_type=proj_type) coeffs = solve(A.to_scipy_csc().todense(), rhs.to_numpy()) return FESolution(m, coeffs).to_discrete_function() else: raise ValueError("Unknown projection type")
def test_l2_h1_proj_run(): """ Test that the projections run. It doesn't test if it's correct. """ pts = arange(0, 2 * pi, 1) orders = [3] * (len(pts) - 1) m = Mesh(pts, orders) n_dof = m.assign_dofs() A = CSCMatrix(n_dof) rhs = AVector(n_dof) assemble_projection_matrix_rhs(m, A, rhs, f_sin, projection_type="L2") x = solve(A.to_scipy_csc().todense(), rhs.to_numpy()) sol_l2 = FESolution(m, x).to_discrete_function() A = CSCMatrix(n_dof) assemble_projection_matrix_rhs(m, A, rhs, f_sin, projection_type="H1") x = solve(A.to_scipy_csc().todense(), rhs.to_numpy()) sol_h1 = FESolution(m, x).to_discrete_function() sol_l2.plot(False) sol_h1.plot(False)
def test_l2_h1_proj3(): """ Tests conversion to FE basis. """ pts = arange(0, 2 * pi, 0.1) orders = [2] * (len(pts) - 1) m = Mesh(pts, orders) f = Function(lambda x: sin(x), Mesh1D(pts, orders)) n_dof = m.assign_dofs() A = CSCMatrix(n_dof) rhs = AVector(n_dof) assemble_projection_matrix_rhs(m, A, rhs, f, projection_type="L2") x = solve(A.to_scipy_csc().todense(), rhs.to_numpy()) sol_l2 = FESolution(m, x).to_discrete_function() A = CSCMatrix(n_dof) assemble_projection_matrix_rhs(m, A, rhs, f, projection_type="H1") x = solve(A.to_scipy_csc().todense(), rhs.to_numpy()) sol_h1 = FESolution(m, x).to_discrete_function() assert sol_l2 == f assert sol_h1 == f
def calculate_FE_coeffs(self): if self._fe_sol is None: from hermes1d.h1d_wrapper.h1d_wrapper import \ (assemble_projection_matrix_rhs, Mesh, FESolution) from hermes_common._hermes_common import CooMatrix pts, orders = self._mesh.get_mesh_data() m = Mesh(pts, orders) n_dof = m.assign_dofs() A = CooMatrix(n_dof) rhs = empty(n_dof) assemble_projection_matrix_rhs(m, A, rhs, self, projection_type="L2") coeffs = solve(A.to_scipy_coo().todense(), rhs) self._fe_sol = FESolution(m, coeffs)
def test_l2_h1_proj2(): """ Tests the correctness of the projections. """ pts = arange(0, 2 * pi, 3) orders = [4] * (len(pts) - 1) m = Mesh(pts, orders) pts = array(list(arange(0, pts[-1], 0.1)) + [pts[-1]]) orders = [6] * (len(pts) - 1) f_exact = Function(lambda x: sin(x), Mesh1D(pts, orders)) n_dof = m.assign_dofs() A = CSCMatrix(n_dof) rhs = AVector(n_dof) assemble_projection_matrix_rhs(m, A, rhs, f_sin, projection_type="L2") x = solve(A.to_scipy_csc().todense(), rhs.to_numpy()) sol_l2 = FESolution(m, x).to_discrete_function() A = CSCMatrix(n_dof) assemble_projection_matrix_rhs(m, A, rhs, f_sin, projection_type="H1") x = solve(A.to_scipy_csc().todense(), rhs.to_numpy()) sol_h1 = FESolution(m, x).to_discrete_function() assert (sol_l2 - f_exact).l2_norm() < 0.002 assert (sol_h1 - f_exact).l2_norm() < 0.002
def refine_mesh_romanowski(mesh, solutions): """ Uses Romanowski refinement for all solutions in 'solutions'. Solutions are given as vectors coming from the matrix solver. """ els2refine = [] errors = [] for sol in solutions: s = FESolution(mesh, sol) id, error = find_element_romanowski(s.get_element_coeffs()) els2refine.append(id) errors.append(error) els2refine = list(set(els2refine)) print "Will refine the elements:", els2refine mesh = refine_mesh(mesh, els2refine) return mesh
def adapt_mesh(mesh, eigs, l=0, Z=1, adapt_type="hp", eqn_type="R"): """ Adapts the mesh using the adaptivity type 'adapt_type'. Returns a new instance of the H1D mesh. adapt_type .... one of: h, hp, p, uniform-p, romanowski """ if adapt_type == "romanowski": m = refine_mesh_romanowski(mesh, eigs) pts, orders = m.get_mesh_data() return Mesh(pts, orders) elif adapt_type == "uniform-p": pts, orders = mesh.get_mesh_data() orders = array(orders) + 1 return Mesh(pts, orders) elif adapt_type in ["h", "p", "hp"]: NORM = 1 # 1 ... H1; 0 ... L2; THRESHOLD = 0.7 mesh_ref = mesh.reference_refinement() print "Fine mesh created (%d DOF)." % mesh_ref.get_n_dof() N_dof, energies, eigs_ref = solve_schroedinger(mesh_ref, l=l, Z=Z, eqn_type=eqn_type, eig_num=len(eigs)) flip_vectors(mesh, eigs, mesh_ref, eigs_ref) print " Done." sols = [] sols_ref = [] print "Normalizing solutions..." for i in range(len(eigs)): e = (eigs[i]).copy() coarse_h1_norm = FESolution(mesh, e).h1_norm() e /= coarse_h1_norm sols.append(e) e = (eigs_ref[i]).copy() reference_h1_norm = FESolution(mesh_ref, e).h1_norm() e /= reference_h1_norm sols_ref.append(e) #print "H1 norms:" #print "coarse (%d):" % i, coarse_h1_norm #print "reference (%d):" % i, reference_h1_norm print " Done." meshes = [] mesh_orig = mesh.copy() mesh_orig.assign_dofs() errors = [] for sol, sol_ref in zip(sols, sols_ref): mesh = mesh_orig.copy() mesh.assign_dofs() mesh_ref = mesh.reference_refinement() mesh_ref.assign_dofs() mesh.copy_vector_to_mesh(sol, 0) mesh_ref.copy_vector_to_mesh(sol_ref, 0) err_est_total, err_est_array = calc_error_estimate( NORM, mesh, mesh_ref) ref_sol_norm = calc_solution_norm(NORM, mesh_ref) err_est_rel = err_est_total / ref_sol_norm print "Relative error (est) = %g %%\n" % (100. * err_est_rel) errors.append(err_est_rel) # TODO: adapt using all the vectors: # 0 ... hp, 1 ... h, 2 ... p if adapt_type == "hp": ADAPT_TYPE = 0 elif adapt_type == "h": ADAPT_TYPE = 1 elif adapt_type == "p": ADAPT_TYPE = 2 else: raise ValueError("Unkown adapt_type") adapt(NORM, ADAPT_TYPE, THRESHOLD, err_est_array, mesh, mesh_ref) meshes.append(mesh) pts, orders = mesh_orig.get_mesh_data() mesh = Mesh1D(pts, orders) for m in meshes: pts, orders = m.get_mesh_data() m = Mesh1D(pts, orders) mesh = mesh.union(m) pts, orders = mesh.get_mesh_data() mesh = Mesh(pts, orders) return mesh else: raise ValueError("Unknown adapt_type")