def test_mesh1(): m = Mesh(-1, 1, 5, 2) pts, p = m.get_mesh_data() assert (abs(pts - array([-1, -0.6, -0.2, 0.2, 0.6, 1])) < eps).all() assert (abs(p - array([2, 2, 2, 2, 2])) < eps).all() m = Mesh(-1, 1, 4, 1) pts, p = m.get_mesh_data() assert (abs(pts - array([-1, -0.5, 0, 0.5, 1])) < eps).all() assert (abs(p - array([1, 1, 1, 1])) < eps).all()
def test_mesh3(): m = Mesh([0, 1, 3, 4], [2, 2, 2]) pts, p = m.get_mesh_data() assert (abs(pts - array([0, 1, 3, 4])) < eps).all() assert (abs(p - array([2, 2, 2])) < eps).all() m = Mesh([-1, -0.5, 0, 0.5, 1], [2, 2, 2, 2]) pts, p = m.get_mesh_data() assert (abs(pts - array([-1, -0.5, 0, 0.5, 1])) < eps).all() assert (abs(p - array([2, 2, 2, 2])) < eps).all()
def radial_dirac_equation_adapt(params, error_tol=1e-8): if params["mesh_uniform"]: pts = create_uniform_mesh(params["a"], params["b"], n_elem=params["el_num"]) else: pts = create_log_mesh(params["a"], params["b"], par=params["mesh_par1"], n_elem=params["el_num"]) orders = [params["el_order"]] * (len(pts) - 1) mesh = Mesh(pts, orders) conv_graph = [] l = params["l"] Z = params["Z"] N_eig = params["eig_num"] #exact_energies=[-1.*Z**2/(2*n**2) for n in range(1+l,N_eig+1+l)] #old_energies = None try: for i in range(10000): print "-" * 80 print "adaptivity iteration:", i mesh.set_bc_right_dirichlet(0, 0) pts, orders = mesh.get_mesh_data() print "Current mesh:" print pts print orders #stop N_dof, energies, eigs = solve_dirac(mesh, l=l, Z=Z, eqn_type=eqn_type, eig_num=N_eig) for n in range(1, 51): print "%d %10.5f" % (n, energies[n - 1]) break conv_graph.append((N_dof, energies)) # This doesn't work well: if old_energies is not None: err = max(abs(old_energies - energies)) print "Maximum error in energies:", err if err < error_tol: break #err = max(abs(energies - exact_energies)) #print "Maximum error in energies:", err #if err < error_tol: # break old_energies = energies # exact_energies = array(exact_energies) # print energies - exact_energies mesh = adapt_mesh(mesh, eigs, l=l, Z=Z, adapt_type=params["adapt_type"]) finally: plot_conv(conv_graph, exact=exact_energies, l=l)
def refine_mesh(mesh, els2refine): new_pts = [] pts, orders = mesh.get_mesh_data() new_pts.append(pts[0]) for id in range(len(orders)): if id in els2refine: new_pts.append((pts[id] + pts[id + 1]) / 2.) new_pts.append(pts[id + 1]) # assumes uniform order: orders = [orders[0]] * (len(new_pts) - 1) return Mesh(new_pts, orders)
def main(): params_hydrogen_p_L = dict(l=0, Z=1, a=0, b=100, el_num=4, el_order=1, eig_num=3, mesh_uniform=False, mesh_par1=20, adapt_type="p") #radial_dirac_equation_adapt(params_hydrogen_uniform_p_L, error_tol=1e-5) #pts = create_uniform_mesh(0, 50, 40) pts = create_log_mesh(0, 150, 10000, 40) orders = [20] * (len(pts) - 1) mesh = Mesh(pts, orders, eq_num=2) N_dof, energies, eigs = solve_dirac(mesh, kappa=1, Z=47, eig_num=50) for i, E in enumerate(energies): print i + 1, E
def radial_schroedinger_equation_adapt(params, error_tol=1e-8): if params["mesh_uniform"]: pts = create_uniform_mesh(params["a"], params["b"], n_elem=params["el_num"]) else: pts = create_log_mesh(params["a"], params["b"], par=params["mesh_par1"], n_elem=params["el_num"]) orders = [params["el_order"]] * (len(pts) - 1) mesh = Mesh(pts, orders) conv_graph = [] l = params["l"] Z = params["Z"] N_eig = params["eig_num"] exact_energies = [ -1. * Z**2 / (2 * n**2) for n in range(1 + l, N_eig + 1 + l) ] old_energies = None eqn_type = params["eqn_type"] try: for i in range(10000): print "-" * 80 print "adaptivity iteration:", i if eqn_type == "rR": mesh.set_bc_left_dirichlet(0, 0) mesh.set_bc_right_dirichlet(0, 0) # Use zero dirichlet for eqn_type="R" as well, just to make sure # that we agree with sle1d mesh.set_bc_right_dirichlet(0, 0) pts, orders = mesh.get_mesh_data() print "Current mesh:" print pts print orders #stop N_dof, energies, eigs = solve_schroedinger(mesh, l=l, Z=Z, eqn_type=eqn_type, eig_num=N_eig) for n in range(1, N_eig + 1): print "%d %10.5f" % (n, energies[n - 1]) conv_graph.append((N_dof, energies)) # This doesn't work well: if old_energies is not None: err = max(abs(old_energies - energies)) print "Maximum error in energies:", err if err < error_tol: break #err = max(abs(energies - exact_energies)) #print "Maximum error in energies:", err #if err < error_tol: # break old_energies = energies # exact_energies = array(exact_energies) # print energies - exact_energies mesh = adapt_mesh(mesh, eigs, l=l, Z=Z, adapt_type=params["adapt_type"]) finally: pass #plot_conv(conv_graph, exact=exact_energies, l=l) return [e for e in energies if e < 0]
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")