def test_christoffel_inv_gradients(self): degree = 2 ab = jacobi_recurrence(degree + 1, 0, 0, True) basis_fun = partial(evaluate_orthonormal_polynomial_1d, nmax=degree, ab=ab) basis_fun_and_jac = partial(evaluate_orthonormal_polynomial_deriv_1d, nmax=degree, ab=ab, deriv_order=1) sample = np.random.uniform(-1, 1, (1, 1)) #sample = np.atleast_2d(-0.99) fun = partial(christoffel_function_inv_1d, basis_fun) jac = partial(christoffel_function_inv_jac_1d, basis_fun_and_jac) #xx = np.linspace(-1, 1, 101); plt.plot(xx, fun(xx[None, :])); #plt.plot(sample[0], fun(sample), 'o'); plt.show() err = check_gradients(fun, jac, sample) assert err.max() > .5 and err.min() < 1e-7 basis_fun_jac_hess = partial(evaluate_orthonormal_polynomial_deriv_1d, nmax=degree, ab=ab, deriv_order=2) hess = partial(christoffel_function_inv_hess_1d, basis_fun_jac_hess, normalize=False) err = check_gradients(jac, hess, sample) assert err.max() > .5 and err.min() < 1e-7
def test_smooth_conditioal_value_at_risk_gradient(self): smoother_type, eps, alpha = 0, 1e-1, 0.7 samples = np.linspace(-1, 1, 11) t = 0.1 x0 = np.concatenate([samples, [t]])[:, np.newaxis] errors = check_gradients( partial(smooth_conditional_value_at_risk, smoother_type, eps, alpha), partial(smooth_conditional_value_at_risk_gradient, smoother_type, eps, alpha), x0) assert errors.min() < 1e-6 weights = np.random.uniform(1, 2, samples.shape[0]) weights /= weights.sum() errors = check_gradients( partial(smooth_conditional_value_at_risk, smoother_type, eps, alpha, weights=weights), partial(smooth_conditional_value_at_risk_gradient, smoother_type, eps, alpha, weights=weights), x0) assert errors.min() < 1e-6
def help_check_smooth_max_function_gradients(self, smoother_type, eps): x = np.array([0.01]) errors = check_gradients( partial(smooth_max_function, smoother_type, eps), partial(smooth_max_function_first_derivative, smoother_type, eps), x[:, np.newaxis]) errors = check_gradients( partial(smooth_max_function_first_derivative, smoother_type, eps), partial(smooth_max_function_second_derivative, smoother_type, eps), x[:, np.newaxis]) assert errors.min() < 1e-6
def test_objective_derivatives(self): smoother_type, eps = 'quintic', 5e-1 nsamples, degree = 10, 1 samples, values, fun, jac, probabilities, ncoef, x0 = \ self.setup_linear_regression_problem(nsamples, degree, eps) x0 -= eps / 3 eta = np.arange(nsamples // 2, nsamples) problem = FSDOptProblem(values, fun, jac, None, eta, probabilities, smoother_type, eps, ncoef) # assert smooth function is shifted correctly assert problem.smooth_fun(np.array([[0.]])) == 1.0 err = check_gradients(problem.objective_fun, problem.objective_jac, x0, rel=False) # fd difference error should exhibit V-cycle. These values # test this for this specific problem assert err.min() < 1e-6 and err.max() > 0.1 err = check_hessian(problem.objective_jac, problem.objective_hessp, x0, rel=False) # fd hessian error should decay linearly (assuming first order fd) # because hessian is constant (indendent of x) assert err[0] < 1e-14 and err[10] > 1e-9 # fd difference error should exhibit V-cycle. These values # test this for this specific problem err = check_gradients(problem.constraint_fun, problem.constraint_jac, x0, rel=False) assert err.min() < 1e-7 and err.max() > 0.1 lmult = np.random.normal(0, 1, (eta.shape[0])) def constr_jac(x): jl = problem.constraint_jac(x).T.dot(lmult) return jl def constr_hessp(x, v): hl = problem.constraint_hess(x, lmult).dot(v) return hl err = check_hessian(constr_jac, constr_hessp, x0) assert err.min() < 1e-5 and err.max() > 0.1
def help_check_smooth_conditional_value_at_risk_composition_gradient( self, smoother_type, eps, alpha, nsamples, nvars): samples = np.arange(nsamples*nvars).reshape(nvars, nsamples) t = 0.1 x0 = np.array([2, 3, t])[:, np.newaxis] def fun(x): return (np.sum((x*samples)**2, axis=0).T)[:, np.newaxis] def jac(x): return 2*(x*samples**2).T errors = check_gradients(fun, jac, x0[:2], disp=False) assert (errors.min() < 1e-6) errors = check_gradients( partial(smooth_conditional_value_at_risk_composition, smoother_type, eps, alpha, fun, jac), True, x0) assert errors.min() < 1e-7
def test_least_squares(self): """for tutorial purposes. Perhaps move to a tutorial""" np.random.seed(1) tol = 1e-14 nsamples, degree, sparsity = 20, 7, 2 samples = np.random.uniform(0, 1, (1, nsamples)) basis_matrix = samples.T**np.arange(degree + 1)[np.newaxis, :] true_coef = np.zeros((basis_matrix.shape[1], 1)) true_coef[np.random.permutation(true_coef.shape[0])[:sparsity]] = 1. vals = basis_matrix.dot(true_coef) def objective(x, return_jac=True): residual = basis_matrix.dot(x) - vals obj = 0.5 * residual.T.dot(residual)[0, 0] jac = basis_matrix.T.dot(residual).T if return_jac: return obj, jac return obj def hessian(x): return basis_matrix.T.dot(basis_matrix) lstsq_coef = np.linalg.lstsq(basis_matrix, vals, rcond=0)[0] init_guess = np.random.normal(0, 0.1, (true_coef.shape[0], 1)) #init_guess = lstsq_coef+np.random.normal(0,1e-3,(true_coef.shape[0])) errors = check_gradients(objective, True, init_guess, disp=True) print(errors.min()) assert errors.min() < 2e-7 method = 'trust-constr' func = partial(objective, return_jac=True) jac = True hess = hessian options = { 'gtol': tol, 'verbose': 0, 'disp': True, 'xtol': tol, 'maxiter': 10000 } constraints = [] from pyapprox.optimization import \ PyapproxFunctionAsScipyMinimizeObjective fun = PyapproxFunctionAsScipyMinimizeObjective(func) res = minimize(fun, init_guess[:, 0], method=method, jac=jac, hess=hess, options=options, constraints=constraints) #print(lstsq_coef) #print(res.x,true_coef) assert np.allclose(res.x[:, np.newaxis], true_coef, atol=1e-4)
def test_smooth_max_function_gradients(self): smoother_type, eps = 0, 1e-1 #x = np.linspace(-1,1,101) #plt.plot(x,smooth_max_function(smoother_type,eps,x));plt.show() #plt.plot(x,smooth_max_function_first_derivative(smoother_type,eps,x));plt.show() x = np.array([0.01]) errors = check_gradients( partial(smooth_max_function, smoother_type, eps), partial(smooth_max_function_first_derivative, smoother_type, eps), x[:, np.newaxis]) assert errors.min() < 1e-6
def help_check_smooth_conditional_value_at_risk(self, smoother_type, eps, alpha): samples = np.linspace(-1, 1, 11) t = value_at_risk(samples, alpha)[0] x0 = np.hstack((samples, t))[:, None] errors = check_gradients( lambda xx: smooth_conditional_value_at_risk( smoother_type, eps, alpha, xx), lambda xx: smooth_conditional_value_at_risk_gradient( smoother_type, eps, alpha, xx), x0) assert errors.min() < 1e-6 weights = np.random.uniform(1, 2, samples.shape[0]) weights /= weights.sum() errors = check_gradients( lambda xx: smooth_conditional_value_at_risk( smoother_type, eps, alpha, xx, weights), lambda xx: smooth_conditional_value_at_risk_gradient( smoother_type, eps, alpha, xx, weights), x0) assert errors.min() < 1e-6
def test_smooth_conditional_value_at_risk_composition_gradient(self): smoother_type, eps, alpha = 0, 1e-1, 0.7 nsamples, nvars = 4, 2 samples = np.arange(nsamples * nvars).reshape(nvars, nsamples) t = 0.1 x0 = np.array([2, 3, t])[:, np.newaxis] fun = lambda x: (np.sum((x * samples)**2, axis=0).T)[:, np.newaxis] jac = lambda x: 2 * (x * samples**2).T errors = check_gradients(fun, jac, x0[:2], disp=False) assert (errors.min() < 1e-6) #import pyapprox as pya #f = lambda x: smooth_conditional_value_at_risk_composition(smoother_type,eps,alpha,fun,jac,x)[0] #print(pya.approx_jacobian(f,x0)) #print(smooth_conditional_value_at_risk_composition(smoother_type,eps,alpha,fun,jac,x0)[1]) errors = check_gradients( partial(smooth_conditional_value_at_risk_composition, smoother_type, eps, alpha, fun, jac), True, x0) assert errors.min() < 1e-7
def test_christoffel_leja_objective_gradients(self): #leja_sequence = np.array([[-1, 1]]) leja_sequence = np.array([[-1, 0, 1]]) degree = leja_sequence.shape[1] - 1 ab = jacobi_recurrence(degree + 2, 0, 0, True) basis_fun = partial(evaluate_orthonormal_polynomial_1d, nmax=degree + 1, ab=ab) tmp = basis_fun(leja_sequence[0, :]) nterms = degree + 1 basis_mat = tmp[:, :nterms] new_basis = tmp[:, nterms:] coef = compute_coefficients_of_christoffel_leja_interpolant_1d( basis_mat, new_basis) fun = partial(christoffel_leja_objective_fun_1d, basis_fun, coef) #xx = np.linspace(-1, 1, 101); plt.plot(xx, fun(xx[None, :])); #plt.plot(leja_sequence[0, :], fun(leja_sequence), 'o'); plt.show() basis_fun_and_jac = partial(evaluate_orthonormal_polynomial_deriv_1d, nmax=degree + 1, ab=ab, deriv_order=1) jac = partial(christoffel_leja_objective_jac_1d, basis_fun_and_jac, coef) sample = sample = np.random.uniform(-1, 1, (1, 1)) err = check_gradients(fun, jac, sample) assert err.max() > 0.5 and err.min() < 1e-7 basis_fun_jac_hess = partial(evaluate_orthonormal_polynomial_deriv_1d, nmax=degree + 1, ab=ab, deriv_order=2) hess = partial(christoffel_leja_objective_hess_1d, basis_fun_jac_hess, coef) err = check_gradients(jac, hess, sample) assert err.max() > .5 and err.min() < 1e-7
def test_smooth_l1_norm_gradients(self): #x = np.linspace(-1,1,101) #t = np.ones_like(x) #r = 1e1 #plt.plot(x,kouri_smooth_absolute_value(t,r,x)) #plt.show() t = np.ones(5);r=1 init_guess = np.random.normal(0,1,(t.shape[0])) func = partial(kouri_smooth_l1_norm,t,r) jac = partial(kouri_smooth_l1_norm_gradient,t,r) errors = check_gradients(func,jac,init_guess,disp=False) assert errors.min()<3e-7 fd_hess = approx_jacobian(jac,init_guess) assert np.allclose(fd_hess,kouri_smooth_l1_norm_hessian(t,r,init_guess))
def check_nn_loss_gradients(self, activation_fun): nvars = 3 nqoi = 2 opts = { 'activation_func': activation_fun, 'layers': [nvars, 3, nqoi], 'loss_func': 'squared_loss', 'lag_mult': 0.5 } # No hidden layers works # opts = {'activation_func':'sigmoid', 'layers':[nvars, nqoi], # 'loss_func':'squared_loss'} network = NeuralNetwork(opts) # train_samples = np.linspace(0, 1, 11)[None, :] train_samples = np.random.uniform(0, 1, (nvars, nvars * 11)) train_values = np.hstack([ np.sum(train_samples**(ii + 2), axis=0)[:, None] for ii in range(nqoi) ]) obj = partial(network.objective_function, train_samples, train_values) jac = partial(network.objective_jacobian, train_samples, train_values) parameters = np.random.normal(0, 1, (network.nparams)) disp = True # disp = False def fun(x): return np.sum(obj(x)) zz = parameters[:, None] errors = check_gradients(fun, jac, zz, plot=False, disp=disp, rel=True, direction=None, jacp=None) # make sure gradient changes by six orders of magnitude assert np.log10(errors.max()) - np.log10(errors.min()) > 6
def check_nn_input_gradients(self, activation_fun): nvars = 3 nqoi = 2 opts = { 'activation_func': activation_fun, 'layers': [nvars, 3, nqoi], 'loss_func': 'squared_loss' } # No hidden layers works # opts = {'activation_func':'sigmoid', 'layers':[nvars, nqoi], # 'loss_func':'squared_loss'} network = NeuralNetwork(opts) # train_samples = np.linspace(0, 1, 11)[None, :] train_samples = np.random.uniform(0, 1, (nvars, nvars * 11)) train_values = np.hstack([ np.sum(train_samples**(ii + 2), axis=0)[:, None] for ii in range(nqoi) ]) obj = partial(network.objective_function, train_samples, train_values) jac = partial(network.objective_jacobian, train_samples, train_values) parameters = np.random.normal(0, 1, (network.nparams)) disp = True # disp = False jac = partial(network.gradient_wrt_inputs, parameters, store=True) x0 = train_samples[:, :1] def fun(x): return network.forward_propagate(x, parameters).T errors = check_gradients(fun, jac, x0, plot=False, disp=disp, rel=True, direction=None, jacp=None) # print(np.log10(errors.max())-np.log10(errors.min())) assert np.log10(errors.max()) - np.log10(errors.min()) > 5.7 # 6
def test_smooth_l1_norm_gradients(self): #x = np.linspace(-1,1,101) #t = np.ones_like(x) #r = 1e1 #plt.plot(x,kouri_smooth_absolute_value(t,r,x)) #plt.show() from pyapprox.optimization import \ ScipyMinimizeObjectiveAsPyapproxFunction,\ ScipyMinimizeObjectiveJacAsPyapproxJac t = np.ones(5) r = 1 init_guess = np.random.normal(0, 1, (t.shape[0], 1)) func = ScipyMinimizeObjectiveAsPyapproxFunction( partial(kouri_smooth_l1_norm, t, r)) jac = partial(kouri_smooth_l1_norm_gradient, t, r) pya_jac = ScipyMinimizeObjectiveJacAsPyapproxJac(jac) errors = check_gradients(func, pya_jac, init_guess, disp=False) assert errors.min() < 3e-7 fd_hess = approx_jacobian(jac, init_guess[:, 0]) assert np.allclose(fd_hess, kouri_smooth_l1_norm_hessian(t, r, init_guess))
def test_pdf_weighted_leja_objective_gradients(self): #leja_sequence = np.array([[-1, 1]]) leja_sequence = np.array([[-1, 0, 1]]) degree = leja_sequence.shape[1] - 1 ab = jacobi_recurrence(degree + 2, 0, 0, True) basis_fun = partial(evaluate_orthonormal_polynomial_1d, nmax=degree + 1, ab=ab) def pdf(x): return beta_pdf(1, 1, (x + 1) / 2) / 2 def pdf_jac(x): return beta_pdf_derivative(1, 1, (x + 1) / 2) / 4 tmp = basis_fun(leja_sequence[0, :]) nterms = degree + 1 basis_mat = tmp[:, :nterms] new_basis = tmp[:, nterms:] coef = compute_coefficients_of_pdf_weighted_leja_interpolant_1d( pdf(leja_sequence[0, :]), basis_mat, new_basis) fun = partial(pdf_weighted_leja_objective_fun_1d, pdf, basis_fun, coef) #xx = np.linspace(-1, 1, 101); plt.plot(xx, fun(xx[None, :])); #plt.plot(leja_sequence[0, :], fun(leja_sequence), 'o'); plt.show() basis_fun_and_jac = partial(evaluate_orthonormal_polynomial_deriv_1d, nmax=degree + 1, ab=ab, deriv_order=1) jac = partial(pdf_weighted_leja_objective_jac_1d, pdf, pdf_jac, basis_fun_and_jac, coef) sample = sample = np.random.uniform(-1, 1, (1, 1)) err = check_gradients(fun, jac, sample) assert err.max() > 0.4 and err.min() < 1e-7
def test_advection_diffusion_base_class_adjoint(self): nvars, corr_len = 2, 0.1 benchmark = setup_advection_diffusion_benchmark(nvars=nvars, corr_len=corr_len, max_eval_concurrency=1) model = benchmark.fun #random_samples = np.zeros((nvars,1)) random_samples = -np.sqrt(3) * np.ones((nvars, 1)) config_samples = 3 * np.ones((3, 1)) samples = np.vstack([random_samples, config_samples]) bmodel = model.base_model qoi = bmodel(samples) assert np.all(np.isfinite(qoi)) sol = bmodel.solve(samples) grad = qoi_functional_grad_misc(sol, bmodel) kappa = bmodel.kappa J = dl_qoi_functional_misc(sol) control = dla.Control(kappa) Jhat = dla.ReducedFunctional(J, control) h = dla.Function(kappa.function_space()) h.vector()[:] = np.random.normal(0, 1, kappa.function_space().dim()) conv_rate = dla.taylor_test(Jhat, kappa, h) assert np.allclose(conv_rate, 2.0, atol=1e-3) # Check that gradient with respect to kappa is calculated correctly # this requires passing in entire kappa vector and not just variables # used to compute the KLE. from pyapprox.optimization import check_gradients from pyapprox.models.wrappers import SingleFidelityWrapper from functools import partial init_condition, boundary_conditions, function_space, beta, \ forcing, kappa = bmodel.initialize_random_expressions( random_samples[:, 0]) def fun(np_kappa): dt = 0.1 fn_kappa = dla.Function(function_space) fn_kappa.vector()[:] = np_kappa[:, 0] bmodel.kappa = fn_kappa sol = run_model( function_space, fn_kappa, forcing, init_condition, dt, bmodel.final_time, boundary_conditions, velocity=beta, second_order_timestepping=bmodel.second_order_timestepping, intermediate_times=bmodel.options.get('intermediate_times', None)) vals = np.atleast_1d(bmodel.qoi_functional(sol)) if vals.ndim == 1: vals = vals[:, np.newaxis] grad = bmodel.qoi_functional_grad(sol, bmodel) return vals, grad kappa = bmodel.get_diffusivity(random_samples[:, 0]) x0 = dla.project(kappa, function_space).vector()[:].copy()[:, None] check_gradients(fun, True, x0) # Test that gradient with respect to kle coefficients is correct from pyapprox.karhunen_loeve_expansion import \ compute_kle_gradient_from_mesh_gradient vals, jac = bmodel(samples, jac=True) # Extract mean field and KLE basis from expression # TODO add ability to compute gradient of kle to # nobile_diffusivity_fenics_class kle = bmodel.get_diffusivity(np.zeros(random_samples.shape[0])) mean_field_fn = dla.Function(function_space) mean_field_fn = dla.interpolate(kle, function_space) mean_field = mean_field_fn.vector()[:].copy() - np.exp(1) mesh_coords = function_space.tabulate_dof_coordinates()[:, 0] I = np.argsort(mesh_coords) basis_matrix = np.empty((mean_field.shape[0], random_samples.shape[0])) exact_basis_matrix = np.array([ mesh_coords * 0 + 1, np.sin((2) / 2 * np.pi * mesh_coords / bmodel.options['corr_len']) ]).T for ii in range(random_samples.shape[0]): zz = np.zeros(random_samples.shape[0]) zz[ii] = 1.0 kle = bmodel.get_diffusivity(zz) field_fn = dla.Function(function_space) field_fn = dla.interpolate(kle, function_space) # 1e-15 used to avoid taking log of zero basis_matrix[:, ii] = np.log(field_fn.vector()[:].copy() - mean_field + 1e-15) - 1 assert np.allclose( mean_field + np.exp(1 + basis_matrix.dot(random_samples[:, 0])), x0[:, 0]) # nobile diffusivity uses different definitions of KLE # k = np.exp(1+basis_matrix.dot(coef))+mean_field # than that assumed in compute_kle_gradient_from_mesh_gradient # k = np.exp(basis_matrix.dot(coef)+mean_field) # So to # keep current interface set mean field to zero and then correct # returned gradient grad = compute_kle_gradient_from_mesh_gradient(jac, basis_matrix, mean_field * 0, True, random_samples[:, 0]) grad *= np.exp(1) from pyapprox.optimization import approx_jacobian fun = SingleFidelityWrapper(bmodel, config_samples[:, 0]) fd_grad = approx_jacobian(fun, random_samples) # print(grad, fd_grad) assert np.allclose(grad, fd_grad)
def test_adjoint(self): np_kappa = 2 nx, ny, degree = 11, 11, 2 mesh = dla.RectangleMesh(dl.Point(0, 0), dl.Point(1, 1), nx, ny) function_space = dl.FunctionSpace(mesh, "Lagrange", degree) def constant_diffusion(kappa, u): return kappa boundary_conditions = \ get_dirichlet_boundary_conditions_from_expression( get_advec_exact_solution(mesh, degree), 0, 1, 0, 1) class NonlinearDiffusivity(object): def __init__(self, kappa): self.kappa = kappa def __call__(self, u): return (self.kappa+u**2) dl_kappa = dla.Constant(np_kappa) options = {'time_step': 0.05, 'final_time': 1., 'forcing': dla.Constant(1), 'boundary_conditions': boundary_conditions, 'init_condition': get_advec_exact_solution(mesh, degree), 'nonlinear_diffusion': NonlinearDiffusivity(dl_kappa), 'second_order_timestepping': True, 'nlsparam': dict()} def dl_qoi_functional(sol): return dla.assemble(sol*dl.dx) def dl_fun(np_kappa): kappa = dla.Constant(np_kappa) options_copy = options.copy() options_copy['forcing'] = dla.Constant(1.0) # using class avoids pickling options_copy['nonlinear_diffusion'] = NonlinearDiffusivity(kappa) sol = run_model(function_space, **options_copy) return sol, kappa def fun(np_kappa): np_kappa = np_kappa[0, 0] sol, kappa = dl_fun(np_kappa) J = dl_qoi_functional(sol) control = dla.Control(kappa) dJd_kappa = dla.compute_gradient(J, [control])[0] return np.atleast_1d(float(J)), np.atleast_2d(float(dJd_kappa)) sol, kappa = dl_fun(np_kappa) J = dl_qoi_functional(sol) control = dla.Control(kappa) Jhat = dla.ReducedFunctional(J, control) # h = dla.Constant(np.random.normal(0, 1, 1)) # conv_rate = dla.taylor_test(Jhat, kappa, h) # assert np.allclose(conv_rate, 2.0, atol=1e-2) from pyapprox.optimization import check_gradients x0 = np.atleast_2d(np_kappa) errors = check_gradients(fun, True, x0) assert errors.min() < 1e-7 and errors.max() > 1e-1
def test_halfar_model(self): nlsparams = get_default_snes_nlsparams() # nlsparams = get_default_newton_nlsparams() def dl_qoi_functional(sol): return dla.assemble(sol*dl.dx) def qoi_functional(sol): return np.atleast_1d(float(dl_qoi_functional(sol))) def qoi_functional_grad(sol, model): J = dl_qoi_functional(sol) control = dla.Control(model.shallow_ice_diffusivity.Gamma) dJd_gamma = dla.compute_gradient(J, [control])[0] # apply chain rule. we want gradient of qoi as a function of x # but fenics compute gradient with respect to g(x)=(1+x)*Gamma # dq/dx = dq/dg*dg/dx dJd_gamma *= model.shallow_ice_diffusivity.Gamma # h = dla.Constant(1e-5) # h must be similar magnitude to Gamma #Jhat = dla.ReducedFunctional(J, control) # conv_rate = dla.taylor_test( # Jhat, model.shallow_ice_diffusivity.Gamma, h) return np.atleast_2d(float(dJd_gamma)) if not has_dla: qoi_functional_grad = None secpera = 31556926 # seconds per anum init_time = 200*secpera final_time, degree, nphys_dim = 300*secpera, 1, 1 # 600*secpera, 1, 1 model = HalfarShallowIceModel( nphys_dim, init_time, final_time, degree, qoi_functional, second_order_timestepping=True, nlsparams=nlsparams, qoi_functional_grad=qoi_functional_grad) # for nphys_dim=1 [8, 8] will produce error of 2.7 e-5 # but stagnates for a while at around 1e-4 for values # 5, 6, 7 random_sample = np.array([[0]]).T config_sample = np.array([[4]*nphys_dim + [4]]).T sample = np.vstack((random_sample, config_sample)) sol = model.solve(sample) exact_solution = get_halfar_shallow_ice_exact_solution( model.Gamma, model.mesh, model.degree, model.nphys_dim) exact_solution.t = final_time error = dl.errornorm(exact_solution, sol, mesh=model.mesh) print('Abs. Error', error) rel_error = error/dl.sqrt( dla.assemble(exact_solution**2*dl.dx(degree=5))) print('Rel. Error', rel_error) assert rel_error < 1e-3 if not has_dla: return # TODO: complete test qoi grad but first add taylor_test val, grad = model(sample, True) print(val, grad) from pyapprox.optimization import check_gradients from pyapprox.models.wrappers import SingleFidelityWrapper fun = SingleFidelityWrapper( partial(model, jac=True), config_sample[:, 0]) x0 = np.atleast_2d(model.Gamma) errors = check_gradients(fun, True, x0, direction=np.atleast_2d(1)) assert errors.min() < 3e-5 and errors.max() > 1e-1