def test_trivial(self): l = 5.0 k = 5 b_desired = 0 k1, k2, b = ut.split_domain(k, b_desired, l, mode="coprime")[0:3] A = ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n") self.assertAlmostEqual(b, 0) self.assertTrue(all(np.isclose(A, np.linalg.inv(A)).all(1))) b_desired = l k1, k2, b = ut.split_domain(k, b_desired, l, mode="coprime")[0:3] B = ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n") self.assertAlmostEqual(b, l) self.assertTrue(all(np.isclose(B, np.diag(np.ones(B.shape[0]))).all(1))) A = ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")
def test_trivial(self): l = 5. k = 5 b_desired = 0 k1, k2, b = ut.split_domain(k, b_desired, l, mode='coprime')[0:3] A = ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n") self.assertAlmostEqual(b, 0) self.assertTrue(all(np.isclose(A, np.linalg.inv(A)).all(1))) b_desired = l k1, k2, b = ut.split_domain(k, b_desired, l, mode='coprime')[0:3] B = ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n") self.assertAlmostEqual(b, l) self.assertTrue(all( np.isclose(B, np.diag(np.ones(B.shape[0]))).all(1))) A = ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")
def test_segmentation_fault(self): if show_plots: plt.figure() fun_end = list() for k in [5, 7, 9, 11, 13, 15, 17, 19]: param = [2.0, 1.5, -3.0, -1.0, -0.5] l = 5.0 spatial_domain = (0, l) n = 1 b_desired = 2 k1, k2, b = ut.split_domain(k, b_desired, l, mode="coprime")[0:3] M = np.linalg.inv(ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies(param, l, n) eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, param, spatial_domain) for om in eig_freq]) shifted_eig_funcs = np.array( [ef.FiniteTransformFunction(func, M, b, l, nested_lambda=self.nested_lambda) for func in eig_funcs] ) z = np.linspace(0, l, 1e3) y = shifted_eig_funcs[0](z) self.assertLess(max(np.diff(y)), 0.1) plt.plot(z, y, label=str(k) + " " + str(b)) plt.plot(z, eig_funcs[0](z)) plt.legend() plt.show()
def test_const(self): param = [2., 1.5, -3., -1., -.5] l = 5. spatial_domain = (0, l) n = 1 k = 5 b_desired = 2 k1, k2, b = ut.split_domain(k, b_desired, l, mode='coprime')[0:3] M = np.linalg.inv( ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies( param, l, n, show_plot=show_plots) eig_funcs = np.array([ ef.SecondOrderRobinEigenfunction(om, param, spatial_domain) for om in eig_freq ]) shifted_eig_funcs = np.array([ ef.FiniteTransformFunction(func, M, b, l, nested_lambda=self.nested_lambda) for func in eig_funcs ]) z = np.linspace(0, l, 1e3) if show_plots: for i in range(n): plt.figure() plt.plot(z, shifted_eig_funcs[i](z)) plt.plot(z, eig_funcs[i](z)) plt.show()
def test_segmentation_fault(self): if show_plots: plt.figure() fun_end = list() for k in [5, 7, 9, 11, 13, 15, 17, 19]: param = [2., 1.5, -3., -1., -.5] l = 5. spatial_domain = (0, l) n = 1 b_desired = 2 k1, k2, b = ut.split_domain(k, b_desired, l, mode='coprime')[0:3] M = np.linalg.inv( ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies( param, l, n) eig_funcs = np.array([ ef.SecondOrderRobinEigenfunction(om, param, spatial_domain) for om in eig_freq ]) shifted_eig_funcs = np.array([ ef.FiniteTransformFunction( func, M, b, l, nested_lambda=self.nested_lambda) for func in eig_funcs ]) z = np.linspace(0, l, 1e3) y = shifted_eig_funcs[0](z) self.assertLess(max(np.diff(y)), 0.1) plt.plot(z, y, label=str(k) + " " + str(b)) plt.plot(z, eig_funcs[0](z)) plt.legend() plt.show()
def test_temporal_derive(self): b_desired = 0.4 k = 5 # = k1 + k2 k1, k2, b = ut.split_domain(k, b_desired, self.l, mode='coprime')[0:3] # q E = tr.coefficient_recursion(self.y, self.beta * self.y, self.param) q = tr.temporal_derived_power_series(self.l - b, E, int(self.n_y / 2) - 1, self.n_y) # u B = tr.coefficient_recursion(self.y, self.alpha * self.y, self.param) xq = tr.temporal_derived_power_series(self.l, B, int(self.n_y / 2) - 1, self.n_y, spatial_der_order=0) d_xq = tr.temporal_derived_power_series(self.l, B, int(self.n_y / 2) - 1, self.n_y, spatial_der_order=1) u = d_xq + self.beta * xq # x(0,t) C = tr.coefficient_recursion(q, self.beta * q, self.param) D = tr.coefficient_recursion(np.zeros(u.shape), u, self.param) x_0t = tr.power_series(0, self.t, C) if show_plots: pw = pg.plot(title="control_input") pw.plot(self.t, x_0t) app.exec_()
def test_paper_example(self): l = 5.0 k = 5 b_desired = 2 k1, k2, b = ut.split_domain(k, b_desired, l, mode="coprime")[0:3] M = np.linalg.inv(ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) func = lambda z: np.cos(z) shifted_func = ef.FiniteTransformFunction(func, M, b, l, nested_lambda=self.nested_lambda) z = np.linspace(0, l, 1e3) if show_plots: for i in [0]: plt.figure() plt.plot(z, shifted_func(z)) plt.plot(z, func(z)) plt.show()
def test_paper_example(self): l = 5. k = 5 b_desired = 2 k1, k2, b = ut.split_domain(k, b_desired, l, mode='coprime')[0:3] M = np.linalg.inv( ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) func = lambda z: np.cos(z) shifted_func = ef.FiniteTransformFunction( func, M, b, l, nested_lambda=self.nested_lambda) z = np.linspace(0, l, 1e3) if show_plots: for i in [0]: plt.figure() plt.plot(z, shifted_func(z)) plt.plot(z, func(z)) plt.show()
def test_const(self): param = [2., 1.5, -3., -1., -.5] l = 5.; spatial_domain = (0, l) n = 1 k = 5 b_desired = 2 k1, k2, b = ut.split_domain(k, b_desired, l, mode='coprime')[0:3] M = np.linalg.inv(ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies(param, l, n, show_plot=show_plots) eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, param, spatial_domain) for om in eig_freq]) shifted_eig_funcs = np.array([ef.FiniteTransformFunction(func, M, b, l, nested_lambda=self.nested_lambda) for func in eig_funcs]) z = np.linspace(0, l, 1e3) if show_plots: for i in range(n): plt.figure() plt.plot(z, shifted_eig_funcs[i](z)) plt.plot(z, eig_funcs[i](z)) plt.show()
def test_temporal_derive(self): b_desired = 0.4 k = 5 # = k1 + k2 k1, k2, b = ut.split_domain(k, b_desired, self.l, mode='coprime')[0:3] # q E = tr.coefficient_recursion(self.y, self.beta*self.y, self.param) q = tr.temporal_derived_power_series(self.l-b, E, int(self.n_y/2)-1, self.n_y) # u B = tr.coefficient_recursion(self.y, self.alpha*self.y, self.param) xq = tr.temporal_derived_power_series(self.l, B, int(self.n_y/2)-1, self.n_y, spatial_der_order=0) d_xq = tr.temporal_derived_power_series(self.l, B, int(self.n_y/2)-1, self.n_y, spatial_der_order=1) u = d_xq + self.beta*xq # x(0,t) C = tr.coefficient_recursion(q, self.beta*q, self.param) D = tr.coefficient_recursion(np.zeros(u.shape), u, self.param) x_0t = tr.power_series(0, self.t, C) if show_plots: pw = pg.plot(title="control_input") pw.plot(self.t, x_0t) app.exec_()
alpha = -0.5 beta = -1 param = [a2, a1, a0, alpha, beta] adjoint_param = ef.get_adjoint_rad_evp_param(param) # target system parameters (controller parameters) a1_t = -1 a0_t = param_a0_t alpha_t = 3 beta_t = 2 param_t = [a2, a1_t, a0_t, alpha_t, beta_t] # actuation_type by b which is close to b_desired on a k times subdivided spatial domain b_desired = 0.4 k = 5 # = k1 + k2 k1, k2, b = ut.split_domain(k, b_desired, l, mode='coprime')[0:3] M = np.linalg.inv(ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) # original intermediate ("_i") and target intermediate ("_ti") system parameters _, _, a0_i, alpha_i, beta_i = ef.transform2intermediate(param) param_i = a2, 0, a0_i, alpha_i, beta_i _, _, a0_ti, alpha_ti, beta_ti = ef.transform2intermediate(param_t) param_ti = a2, 0, a0_ti, alpha_ti, beta_ti # COMPUTE DESIRED FIELDVARIABLE # THE NAMING OF THE POWER SERIES COEFFICIENTS IS BASED ON THE PUBLICATION: # - WANG; WOITTENNEK:BACKSTEPPING-METHODE FUER PARABOLISCHE SYSTEM MIT PUNKTFOERMIGEM INNEREN EINGRIFF # compute input u_i of the boundary-controlled intermediate (_i) system with n_y/2 temporal derivatives n_y = 80 y, t_x = tr.gevrey_tanh(T, n_y, 1.1, 2) B = tr.coefficient_recursion(y, alpha_i * y, param_i)
def test_fem(self): # system/simulation parameters actuation_type = 'robin' bound_cond_type = 'robin' self.l = 1. spatial_disc = 30 self.dz = sim.Domain(bounds=(0, self.l), num=spatial_disc) self.T = 1. temporal_disc = 1e2 self.dt = sim.Domain(bounds=(0, self.T), num=temporal_disc) self.n = 12 # original system parameters a2 = 1.5 a1 = 2.5 a0 = 28 alpha = -2 beta = -3 self.param = [a2, a1, a0, alpha, beta] adjoint_param = ef.get_adjoint_rad_evp_param(self.param) # target system parameters (controller parameters) a1_t = -5 a0_t = -25 alpha_t = 3 beta_t = 2 self.param_t = [a2, a1_t, a0_t, alpha_t, beta_t] # actuation_type by b which is close to b_desired on a k times subdivided spatial domain b_desired = self.l / 2 k = 51 # = k1 + k2 k1, k2, self.b = ut.split_domain(k, b_desired, self.l, mode='coprime')[0:3] M = np.linalg.inv(ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) # original intermediate ("_i") and traget intermediate ("_ti") system parameters _, _, a0_i, self.alpha_i, self.beta_i = ef.transform2intermediate(self.param) self.param_i = a2, 0, a0_i, self.alpha_i, self.beta_i _, _, a0_ti, self.alpha_ti, self.beta_ti = ef.transform2intermediate(self.param_t) self.param_ti = a2, 0, a0_ti, self.alpha_ti, self.beta_ti # create (not normalized) eigenfunctions eig_freq, self.eig_val = ef.compute_rad_robin_eigenfrequencies(self.param, self.l, self.n) init_eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, self.param, self.dz.bounds) for om in eig_freq]) init_adjoint_eig_funcs = np.array( [ef.SecondOrderRobinEigenfunction(om, adjoint_param, self.dz.bounds) for om in eig_freq]) # normalize eigenfunctions and adjoint eigenfunctions adjoint_and_eig_funcs = [cr.normalize_function(init_eig_funcs[i], init_adjoint_eig_funcs[i]) for i in range(self.n)] eig_funcs = np.array([f_tuple[0] for f_tuple in adjoint_and_eig_funcs]) self.adjoint_eig_funcs = np.array([f_tuple[1] for f_tuple in adjoint_and_eig_funcs]) # eigenfunctions of the in-domain intermediate (_id) and the intermediate (_i) system eig_freq_i, eig_val_i = ef.compute_rad_robin_eigenfrequencies(self.param_i, self.l, self.n) self.assertTrue(all(np.isclose(eig_val_i, self.eig_val))) eig_funcs_id = np.array([ef.SecondOrderRobinEigenfunction(eig_freq_i[i], self.param_i, self.dz.bounds, eig_funcs[i](0)) for i in range(self.n)]) eig_funcs_i = np.array([ef.SecondOrderRobinEigenfunction(eig_freq_i[i], self.param_i, self.dz.bounds, eig_funcs[i](0) * eig_funcs_id[i](self.l) / eig_funcs_id[i](self.b)) for i in range(self.n)]) # eigenfunctions from target system ("_ti") eig_freq_ti = np.sqrt((a0_ti - self.eig_val) / a2) eig_funcs_ti = np.array([ef.SecondOrderRobinEigenfunction(eig_freq_ti[i], self.param_ti, self.dz.bounds, eig_funcs_i[i](0)) for i in range(self.n)]) # create testfunctions nodes, self.fem_funcs = sf.cure_interval(sf.LagrangeFirstOrder, self.dz.bounds, node_count=self.n) # register eigenfunctions # register_functions("eig_funcs", eig_funcs, overwrite=True) register_base("adjoint_eig_funcs", self.adjoint_eig_funcs, overwrite=True) register_base("eig_funcs", eig_funcs, overwrite=True) register_base("eig_funcs_i", eig_funcs_i, overwrite=True) register_base("eig_funcs_ti", eig_funcs_ti, overwrite=True) register_base("fem_funcs", self.fem_funcs, overwrite=True) # init trajectory self.traj = tr.RadTrajectory(self.l, self.T, self.param_ti, bound_cond_type, actuation_type) # original () and target (_t) field variable fem_field_variable = ph.FieldVariable("fem_funcs", location=self.l) field_variable_i = ph.FieldVariable("eig_funcs_i", weight_label="eig_funcs", location=self.l) d_field_variable_i = ph.SpatialDerivedFieldVariable("eig_funcs_i", 1, weight_label="eig_funcs", location=self.l) field_variable_ti = ph.FieldVariable("eig_funcs_ti", weight_label="eig_funcs", location=self.l) d_field_variable_ti = ph.SpatialDerivedFieldVariable("eig_funcs_ti", 1, weight_label="eig_funcs", location=self.l) # intermediate (_i) and target intermediate (_ti) field variable (list of scalar terms = sum of scalar terms) self.x_fem_i_at_l = [ph.ScalarTerm(fem_field_variable)] self.x_i_at_l = [ph.ScalarTerm(field_variable_i)] self.xd_i_at_l = [ph.ScalarTerm(d_field_variable_i)] self.x_ti_at_l = [ph.ScalarTerm(field_variable_ti)] self.xd_ti_at_l = [ph.ScalarTerm(d_field_variable_ti)] # shift transformation shifted_fem_funcs_i = np.array( [ef.FiniteTransformFunction(func, M, self.b, self.l, scale_func=lambda z: np.exp(a1 / 2 / a2 * z)) for func in self.fem_funcs]) shifted_eig_funcs_id = np.array([ef.FiniteTransformFunction(func, M, self.b, self.l) for func in eig_funcs_id]) register_base("sh_fem_funcs_i", shifted_fem_funcs_i, overwrite=True) register_base("sh_eig_funcs_id", shifted_eig_funcs_id, overwrite=True) sh_fem_field_variable_i = ph.FieldVariable("sh_fem_funcs_i", weight_label="fem_funcs", location=self.l) sh_field_variable_id = ph.FieldVariable("sh_eig_funcs_id", weight_label="eig_funcs", location=self.l) self.sh_x_fem_i_at_l = [ph.ScalarTerm(sh_fem_field_variable_i), ph.ScalarTerm(field_variable_i), ph.ScalarTerm(sh_field_variable_id, -1)] # discontinuous operator (Kx)(t) = int_kernel_zz(l)*x(l,t) self.int_kernel_zz = lambda z: self.alpha_ti - self.alpha_i + (a0_i - a0_ti) / 2 / a2 * z a2, a1, _, _, _ = self.param controller = ut.get_parabolic_robin_backstepping_controller(state=self.sh_x_fem_i_at_l, approx_state=self.x_i_at_l, d_approx_state=self.xd_i_at_l, approx_target_state=self.x_ti_at_l, d_approx_target_state=self.xd_ti_at_l, integral_kernel_zz=self.int_kernel_zz(self.l), original_beta=self.beta_i, target_beta=self.beta_ti, trajectory=self.traj, scale=np.exp(-a1 / 2 / a2 * self.b)) # determine (A,B) with modal-transfomation rad_pde = ut.get_parabolic_robin_weak_form("fem_funcs", "fem_funcs", controller, self.param, self.dz.bounds, self.b) cf = sim.parse_weak_formulation(rad_pde) ss_weak = cf.convert_to_state_space() # simulate t, q = sim.simulate_state_space(ss_weak, np.zeros((len(self.fem_funcs))), self.dt) # weights of the intermediate system mat = cr.calculate_base_transformation_matrix(self.fem_funcs, eig_funcs) q_i = np.zeros((q.shape[0], len(eig_funcs_i))) for i in range(q.shape[0]): q_i[i, :] = np.dot(q[i, :], np.transpose(mat)) eval_i = sim.evaluate_approximation("eig_funcs_i", q_i, t, self.dz) x_0t = eval_i.output_data[:, 0] yc, tc = tr.gevrey_tanh(self.T, 1) x_0t_desired = np.interp(t, tc, yc[0, :]) self.assertLess(np.average((x_0t - x_0t_desired) ** 2), 1e-2) # display results if show_plots: eval_d = sim.evaluate_approximation("fem_funcs", q, t, self.dz) win1 = vis.PgSurfacePlot(eval_i) win2 = vis.PgSurfacePlot(eval_d) app.exec_()
def test_fem(self): # system/simulation parameters actuation_type = 'robin' bound_cond_type = 'robin' self.l = 1. spatial_disc = 30 self.dz = sim.Domain(bounds=(0, self.l), num=spatial_disc) self.T = 1. temporal_disc = 1e2 self.dt = sim.Domain(bounds=(0, self.T), num=temporal_disc) self.n = 12 # original system parameters a2 = 1.5 a1 = 2.5 a0 = 28 alpha = -2 beta = -3 self.param = [a2, a1, a0, alpha, beta] adjoint_param = ef.get_adjoint_rad_evp_param(self.param) # target system parameters (controller parameters) a1_t = -5 a0_t = -25 alpha_t = 3 beta_t = 2 self.param_t = [a2, a1_t, a0_t, alpha_t, beta_t] # actuation_type by b which is close to b_desired on a k times subdivided spatial domain b_desired = self.l / 2 k = 51 # = k1 + k2 k1, k2, self.b = ut.split_domain(k, b_desired, self.l, mode='coprime')[0:3] M = np.linalg.inv( ut.get_inn_domain_transformation_matrix(k1, k2, mode="2n")) # original intermediate ("_i") and traget intermediate ("_ti") system parameters _, _, a0_i, self.alpha_i, self.beta_i = ef.transform2intermediate( self.param) self.param_i = a2, 0, a0_i, self.alpha_i, self.beta_i _, _, a0_ti, self.alpha_ti, self.beta_ti = ef.transform2intermediate( self.param_t) self.param_ti = a2, 0, a0_ti, self.alpha_ti, self.beta_ti # create (not normalized) eigenfunctions eig_freq, self.eig_val = ef.compute_rad_robin_eigenfrequencies( self.param, self.l, self.n) init_eig_funcs = np.array([ ef.SecondOrderRobinEigenfunction(om, self.param, self.dz.bounds) for om in eig_freq ]) init_adjoint_eig_funcs = np.array([ ef.SecondOrderRobinEigenfunction(om, adjoint_param, self.dz.bounds) for om in eig_freq ]) # normalize eigenfunctions and adjoint eigenfunctions adjoint_and_eig_funcs = [ cr.normalize_function(init_eig_funcs[i], init_adjoint_eig_funcs[i]) for i in range(self.n) ] eig_funcs = np.array([f_tuple[0] for f_tuple in adjoint_and_eig_funcs]) self.adjoint_eig_funcs = np.array( [f_tuple[1] for f_tuple in adjoint_and_eig_funcs]) # eigenfunctions of the in-domain intermediate (_id) and the intermediate (_i) system eig_freq_i, eig_val_i = ef.compute_rad_robin_eigenfrequencies( self.param_i, self.l, self.n) self.assertTrue(all(np.isclose(eig_val_i, self.eig_val))) eig_funcs_id = np.array([ ef.SecondOrderRobinEigenfunction(eig_freq_i[i], self.param_i, self.dz.bounds, eig_funcs[i](0)) for i in range(self.n) ]) eig_funcs_i = np.array([ ef.SecondOrderRobinEigenfunction( eig_freq_i[i], self.param_i, self.dz.bounds, eig_funcs[i](0) * eig_funcs_id[i](self.l) / eig_funcs_id[i](self.b)) for i in range(self.n) ]) # eigenfunctions from target system ("_ti") eig_freq_ti = np.sqrt((a0_ti - self.eig_val) / a2) eig_funcs_ti = np.array([ ef.SecondOrderRobinEigenfunction(eig_freq_ti[i], self.param_ti, self.dz.bounds, eig_funcs_i[i](0)) for i in range(self.n) ]) # create testfunctions nodes, self.fem_funcs = sf.cure_interval(sf.LagrangeFirstOrder, self.dz.bounds, node_count=self.n) # register eigenfunctions # register_functions("eig_funcs", eig_funcs, overwrite=True) register_base("adjoint_eig_funcs", self.adjoint_eig_funcs, overwrite=True) register_base("eig_funcs", eig_funcs, overwrite=True) register_base("eig_funcs_i", eig_funcs_i, overwrite=True) register_base("eig_funcs_ti", eig_funcs_ti, overwrite=True) register_base("fem_funcs", self.fem_funcs, overwrite=True) # init trajectory self.traj = tr.RadTrajectory(self.l, self.T, self.param_ti, bound_cond_type, actuation_type) # original () and target (_t) field variable fem_field_variable = ph.FieldVariable("fem_funcs", location=self.l) field_variable_i = ph.FieldVariable("eig_funcs_i", weight_label="eig_funcs", location=self.l) d_field_variable_i = ph.SpatialDerivedFieldVariable( "eig_funcs_i", 1, weight_label="eig_funcs", location=self.l) field_variable_ti = ph.FieldVariable("eig_funcs_ti", weight_label="eig_funcs", location=self.l) d_field_variable_ti = ph.SpatialDerivedFieldVariable( "eig_funcs_ti", 1, weight_label="eig_funcs", location=self.l) # intermediate (_i) and target intermediate (_ti) field variable (list of scalar terms = sum of scalar terms) self.x_fem_i_at_l = [ph.ScalarTerm(fem_field_variable)] self.x_i_at_l = [ph.ScalarTerm(field_variable_i)] self.xd_i_at_l = [ph.ScalarTerm(d_field_variable_i)] self.x_ti_at_l = [ph.ScalarTerm(field_variable_ti)] self.xd_ti_at_l = [ph.ScalarTerm(d_field_variable_ti)] # shift transformation shifted_fem_funcs_i = np.array([ ef.FiniteTransformFunction( func, M, self.b, self.l, scale_func=lambda z: np.exp(a1 / 2 / a2 * z)) for func in self.fem_funcs ]) shifted_eig_funcs_id = np.array([ ef.FiniteTransformFunction(func, M, self.b, self.l) for func in eig_funcs_id ]) register_base("sh_fem_funcs_i", shifted_fem_funcs_i, overwrite=True) register_base("sh_eig_funcs_id", shifted_eig_funcs_id, overwrite=True) sh_fem_field_variable_i = ph.FieldVariable("sh_fem_funcs_i", weight_label="fem_funcs", location=self.l) sh_field_variable_id = ph.FieldVariable("sh_eig_funcs_id", weight_label="eig_funcs", location=self.l) self.sh_x_fem_i_at_l = [ ph.ScalarTerm(sh_fem_field_variable_i), ph.ScalarTerm(field_variable_i), ph.ScalarTerm(sh_field_variable_id, -1) ] # discontinuous operator (Kx)(t) = int_kernel_zz(l)*x(l,t) self.int_kernel_zz = lambda z: self.alpha_ti - self.alpha_i + ( a0_i - a0_ti) / 2 / a2 * z a2, a1, _, _, _ = self.param controller = ut.get_parabolic_robin_backstepping_controller( state=self.sh_x_fem_i_at_l, approx_state=self.x_i_at_l, d_approx_state=self.xd_i_at_l, approx_target_state=self.x_ti_at_l, d_approx_target_state=self.xd_ti_at_l, integral_kernel_zz=self.int_kernel_zz(self.l), original_beta=self.beta_i, target_beta=self.beta_ti, trajectory=self.traj, scale=np.exp(-a1 / 2 / a2 * self.b)) # determine (A,B) with modal-transfomation rad_pde = ut.get_parabolic_robin_weak_form("fem_funcs", "fem_funcs", controller, self.param, self.dz.bounds, self.b) cf = sim.parse_weak_formulation(rad_pde) ss_weak = cf.convert_to_state_space() # simulate t, q = sim.simulate_state_space(ss_weak, np.zeros( (len(self.fem_funcs))), self.dt) # weights of the intermediate system mat = cr.calculate_base_transformation_matrix(self.fem_funcs, eig_funcs) q_i = np.zeros((q.shape[0], len(eig_funcs_i))) for i in range(q.shape[0]): q_i[i, :] = np.dot(q[i, :], np.transpose(mat)) eval_i = sim.evaluate_approximation("eig_funcs_i", q_i, t, self.dz) x_0t = eval_i.output_data[:, 0] yc, tc = tr.gevrey_tanh(self.T, 1) x_0t_desired = np.interp(t, tc, yc[0, :]) self.assertLess(np.average((x_0t - x_0t_desired)**2), 1e-2) # display results if show_plots: eval_d = sim.evaluate_approximation("fem_funcs", q, t, self.dz) win1 = vis.PgSurfacePlot(eval_i) win2 = vis.PgSurfacePlot(eval_d) app.exec_()