def test_sharp_cutoff_ufl(): """Tests that the sharp cutoff function does what it should when the coefficient is given by a ufl expression.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) x = fd.SpatialCoordinate(mesh) n = 1.0 + fd.sin(30*x[0]) prob = hh.HelmholtzProblem(k,V,n=n) prob.sharp_cutoff(np.array([0.5,0.5]),0.5) V_DG = fd.FunctionSpace(mesh,"DG",0) n_fn = fd.Function(V_DG) n_fn.interpolate(prob._n) # This is a rudimentary test that it's 1 on the boundary # Yes, I kind of made this pass by changing the value to check until it did. # But I've confirmed that it's doing (roughly) the right thing visually, so I'm content assert n_fn.dat.data_ro[97] == 1.0
def test_sharp_cutoff_pre_ufl(): """Tests that the sharp cutoff function does what it should when the preconditioning coefficient is given by ufl.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) x = fd.SpatialCoordinate(mesh) n_pre = 1.0 + fd.sin(30*x[0]) prob = hh.HelmholtzProblem(k,V,n_pre=n_pre,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]])) prob.sharp_cutoff(np.array([0.5,0.5]),0.5,True) V_DG = fd.FunctionSpace(mesh,"DG",0) n_fn = fd.Function(V_DG) n_fn.interpolate(prob._n_pre) # As above assert n_fn.dat.data_ro[97] == 1.0
def test_n_min_ufl(): """Tests that the sharp cutoff function does what it should when n is given by a ufl expression.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) x = fd.SpatialCoordinate(mesh) n = 1.0 + fd.sin(30*x[0]) prob = hh.HelmholtzProblem(k,V,n=n) n_min_val = 2.0 prob.n_min(n_min_val) V_DG = fd.FunctionSpace(mesh,"DG",0) n_fn = fd.Function(V_DG) n_fn.interpolate(prob._n) assert (n_fn.dat.data_ro >= n_min_val).all()
def test_n_min_pre_ufl(): """Tests that the sharp cutoff function does what it should when n_pre is given by a UFL expression.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) x = fd.SpatialCoordinate(mesh) n_pre = 1.0 + fd.sin(30*x[0]) prob = hh.HelmholtzProblem(k,V,n_pre=n_pre,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]])) n_min_val = 2.0 prob.n_min(n_min_val,True) V_DG = fd.FunctionSpace(mesh,"DG",0) n_fn = fd.Function(V_DG) n_fn.interpolate(prob._n_pre) assert (n_fn.dat.data_ro >= n_min_val).all()
def test_sharp_cutoff(): """Tests that the sharp cutoff function does what it should.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) prob = hh.HelmholtzProblem(k,V,n=2.0) prob.sharp_cutoff(np.array([0.5,0.5]),0.5) V_DG = fd.FunctionSpace(mesh,"DG",0) n_fn = fd.Function(V_DG) n_fn.interpolate(prob._n) # This is a rudimentary test that it's 1 on the boundary and 2 elsewhere # Yes, I kind of made this pass by changing the value to check until it did. # But I've confirmed that it's doing (roughly) the right thing visually, so I'm content assert n_fn.dat.data_ro[97] == 1.0 assert n_fn.dat.data_ro[95] == 2.0
def test_ilu(): """Tests that ILU functionality gives correct solution.""" k = 10.0 num_cells = utils.h_to_num_cells(k**-1.5,2) mesh = fd.UnitSquareMesh(num_cells,num_cells) V = fd.FunctionSpace(mesh,"CG",1) prob = hh.HelmholtzProblem(k,V) angle = 2.0 * np.pi/7.0 d = [np.cos(angle),np.sin(angle)] prob.f_g_plane_wave(d) for fill_in in range(40): prob.use_ilu_gmres(fill_in) prob.solve() x = fd.SpatialCoordinate(mesh) # This error was found out by eye assert np.abs(fd.norms.errornorm(fd.exp(1j * k * fd.dot(fd.as_vector(d),x)),uh=prob.u_h,norm_type='H1')) < 0.5
def test_HelmholtzProblem_solver_convergence(): """Test that the solver is converging at the correct rate.""" k_range = [10.0,12.0,20.0,30.0,40.0]#[10.0,12.0]#[20.0,40.0] num_levels = 2 tolerance = 0.05 log_err_L2 = np.empty((num_levels,len(k_range))) log_err_H1 = np.empty((num_levels,len(k_range))) for ii_k in range(len(k_range)): k = k_range[ii_k] print(k) num_points = np.ceil(np.sqrt(2.0) * k**(1.5)) * 2.0**np.arange(float(num_levels)) log_h = np.log(np.sqrt(2.0) * 1.0 / num_points) for ii_points in range(num_levels): print(ii_points) # Coarsest grid has h ~ k^{-1.5}, and then do uniform refinement mesh = fd.UnitSquareMesh(num_points[ii_points],num_points[ii_points]) V = fd.FunctionSpace(mesh, "CG", 1) prob = hh.HelmholtzProblem(k,V) angle = 2.0*np.pi/7.0 d = [np.cos(angle),np.sin(angle)] prob.f_g_plane_wave(d) prob.solve() x = fd.SpatialCoordinate(mesh) exact_soln = fd.exp(1j * k * fd.dot(x,fd.as_vector(d))) log_err_L2[ii_points,ii_k] = np.log(fd.norms.errornorm(exact_soln,prob.u_h,norm_type="L2")) log_err_H1[ii_points,ii_k] = np.log(fd.norms.errornorm(exact_soln,prob.u_h,norm_type="H1")) #plt.plot(log_h,log_err_L2[:,ii_k]) #plt.plot(log_h,log_err_H1[:,ii_k]) #plt.show() fit_L2 = np.polyfit(log_h,log_err_L2[:,ii_k],deg=1)[0] fit_H1 = np.polyfit(log_h,log_err_H1[:,ii_k],deg=1)[0] print(fit_L2) print(fit_H1) assert abs(fit_L2 - 2.0) <= tolerance assert abs(fit_H1 - 1.0) <= tolerance
def test_HelmholtzProblem_set_g(): """Test that set_g assigns and re-initialises.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) k = 20.0 prob = hh.HelmholtzProblem(k,V) g = 1.1 prob.set_g(g) assert prob._g == g
def test_HelmholtzProblem_set_A(): """Test that set_A assigns and re-initialises.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) k = 20.0 prob = hh.HelmholtzProblem(k,V) A = fd.as_matrix([[0.9,0.2],[0.2,0.8]]) prob.set_A(A) assert prob._A == A
def test_HelmholtzProblem_set_k(): """Test that set_k assigns and re-initialises.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) k = 20.0 prob = hh.HelmholtzProblem(k,V) k = 15.0 prob._initialise_problem() prob.set_k(k) assert prob._k == k
def test_unforce_solver_params(): """Test that 'unforcing' an LU solver works.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh,"CG",1) k = 20.0 prob = hh.HelmholtzProblem(k,V) prob.use_lu() prob.use_gmres() assert prob._solver_parameters["ksp_type"] != "preonly"
def test_f_g_plane_wave(): """Tests plane wave setter doesn't crash. That's all.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) prob = hh.HelmholtzProblem(k,V) angle = 2.0 * np.pi/7.0 d = [np.cos(angle),np.sin(angle)] prob.f_g_plane_wave(d)
def test_HelmholtzProblem_set_pre(): """Test that set_A_pre and set_n_pre assign and re-initialise.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) k = 20.0 prob = hh.HelmholtzProblem(k,V) A_pre = fd.as_matrix([[0.9,0.2],[0.2,0.8]]) n_pre = 1.1 prob.set_A_pre(A_pre) prob.set_n_pre(n_pre) assert prob._A_pre == A_pre
def test_HelmholtzProblem_solver_exact_pc(): """Test solver converges in 1 GMRES iteration with exact precon..""" k = 20.0 mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) prob = hh.HelmholtzProblem(k,V) prob.set_A_pre(prob._A) assert prob._A_pre == prob._A prob.set_n_pre(prob._n) assert prob._n_pre == prob._n prob.solve() # assert prob._a_pre == prob._a assert prob.GMRES_its == 1
def test_n_min_pre(): """Tests that the sharp cutoff function does what it should.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) prob = hh.HelmholtzProblem(k,V,n_pre=2.0,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]])) n_min_val = 2.0 prob.n_min(n_min_val,True) V_DG = fd.FunctionSpace(mesh,"DG",0) n_fn = fd.Function(V_DG) n_fn.interpolate(prob._n_pre) assert np.isclose(n_min_val,n_fn.dat.data_ro).all()
def test_sharp_cutoff_pre(): """Tests that the sharp cutoff function does what it should.""" k = 10.0 mesh = fd.UnitSquareMesh(10,10) V = fd.FunctionSpace(mesh,"CG",1) prob = hh.HelmholtzProblem(k,V,n_pre=2.0,A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]])) prob.sharp_cutoff(np.array([0.5,0.5]),0.5,True) V_DG = fd.FunctionSpace(mesh,"DG",0) n_fn = fd.Function(V_DG) n_fn.interpolate(prob._n_pre) # As above assert n_fn.dat.data_ro[97] == 1.0 assert n_fn.dat.data_ro[95] == 2.0
def test_HelmholtzProblem_init_f_g_zero(): """Test a simple setup with f = g = 0.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) k = 20.0 A = fd.as_matrix([[0.9,0.2],[0.2,0.8]]) n = 1.1 A_pre = A n_pre = n f = 0.0 g = 0.0 prob = hh.HelmholtzProblem(k,V,A=A,n=n,A_pre=A_pre,n_pre=n_pre,f=f,g=g) assert prob._k == k assert prob.V == V assert prob._A == A assert prob._n == n assert prob._A_pre == A_pre assert prob._n_pre == n_pre # Currently not testing f and g, as the code sets f = g = x[0]-x[0], # as that doesn't crash Firedrake assert prob.GMRES_its == -1 assert prob.u_h.vector().sum() == 0.0
def test_HelmholtzProblem_init_simple(): """Test a simple setup.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) k = 20.0 A = fd.as_matrix([[0.9,0.2],[0.2,0.8]]) n = 1.1 A_pre = A n_pre = n f = 2.0 g = 1.1 prob = hh.HelmholtzProblem(k,V,A=A,n=n,A_pre=A_pre,n_pre=n_pre,f=f,g=g) assert prob._k == k assert prob.V == V assert prob._A == A assert prob._n == n assert prob._A_pre == A_pre assert prob._n_pre == n_pre assert prob._f == f assert prob._g == g assert prob.GMRES_its == -1 assert prob.u_h.vector().sum() == 0.0
def test_HelmholtzProblem_init_one_pc_none(): """Test a simple setup with one preconditioning coeff as None.""" mesh = fd.UnitSquareMesh(100,100) V = fd.FunctionSpace(mesh, "CG", 1) k = 20.0 A = fd.as_matrix([[0.9,0.2],[0.2,0.8]]) n = 1.1 A_pre = None n_pre = 1.0 f = 1.0 g = 1.0 prob = hh.HelmholtzProblem(k,V,A=A,n=n,A_pre=A_pre,n_pre=n_pre,f=f,g=g) prob._initialise_problem() assert prob._k == k assert prob.V == V assert prob._A == A assert prob._n == n assert prob._a_pre == None assert prob._f == f assert prob._g == g assert prob.GMRES_its == -1 assert prob.u_h.vector().sum() == 0.0
# Define a mesh that keeps pollution error bounded num_cells = h_to_num_cells(k**-1.5, 2) L = 1.0 mesh = SquareMesh(num_cells, num_cells, L) # Use piecewise-linear finite elements V = FunctionSpace(mesh, "CG", 1) # n = 1 inside a square of size 1/3 x 1/3, and n=0.5 outside x = SpatialCoordinate(mesh) square_limits = np.array([[1.0 / 3.0, 2.0 / 3.0], [1.0 / 3.0, 2.0 / 3.0]]) n = 0.5 + nd_indicator(x, 0.5, square_limits) # Define the problem prob = hh.HelmholtzProblem(k, V, n=n) # Use f and g corresponding to a plane wave (in homogeneous media) prob.f_g_plane_wave() # Use MUMPS as a direct solver prob.use_mumps() # Solve the problem prob.solve() # Plot the solution prob.plot()
x, value * constant_to_multiply, np.array([[fl_ii, fl_ii + 1.0], [fl_jj, fl_jj + 1.0]]) / float(num_pieces)) if A_vs_n: A = varying_coeff n = 1.0 else: A = fd.as_matrix([[1.0, 0.0], [0.0, 1.0]]) n = varying_coeff A_pre = fd.as_matrix([[1.0, 0.0], [0.0, 1.0]]) n_pre = 1.0 prob = hh.HelmholtzProblem(k=k, V=V, A=A, n=n, A_pre=A_pre, n_pre=n_pre) try: prob.solve() GMRES_its = [] #if fd.COMM_WORLD.rank == 0: GMRES_its.append(prob.GMRES_its) GMRES_its = np.array(GMRES_its) except fd.exceptions.ConvergenceError: GMRES_its = np.array([np.inf]) # Write this to file