Exemple #1
0
    def test_it(self):
        actuation_type = 'robin'
        bound_cond_type = 'robin'
        param = [2., 1.5, -3., -1., -.5]
        adjoint_param = ef.get_adjoint_rad_evp_param(param)
        a2, a1, a0, alpha, beta = param

        l = 1.
        spatial_disc = 10
        dz = sim.Domain(bounds=(0, l), num=spatial_disc)

        T = 1.
        temporal_disc = 1e2
        dt = sim.Domain(bounds=(0, T), num=temporal_disc)
        n = 10

        eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies(param, l, n)

        init_eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, param, dz.bounds) for om in eig_freq])
        init_adjoint_eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, adjoint_param, 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(n)]
        eig_funcs = np.array([f_tuple[0] for f_tuple in adjoint_and_eig_funcs])
        adjoint_eig_funcs = np.array([f_tuple[1] for f_tuple in adjoint_and_eig_funcs])

        # register eigenfunctions
        register_base("eig_funcs", eig_funcs, overwrite=True)
        register_base("adjoint_eig_funcs", adjoint_eig_funcs, overwrite=True)

        # derive initial field variable x(z,0) and weights
        start_state = cr.Function(lambda z: 0., domain=(0, l))
        initial_weights = cr.project_on_base(start_state, adjoint_eig_funcs)

        # init trajectory
        u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type)

        # determine (A,B) with weak-formulation (pyinduct)
        rad_pde = ut.get_parabolic_robin_weak_form("eig_funcs", "adjoint_eig_funcs", u, param, dz.bounds)
        cf = sim.parse_weak_formulation(rad_pde)
        ss_weak = cf.convert_to_state_space()

        # determine (A,B) with modal-transfomation
        A = np.diag(np.real_if_close(eig_val))
        B = a2*np.array([adjoint_eig_funcs[i](l) for i in xrange(len(eig_freq))])
        ss_modal = sim.StateSpace("eig_funcs", A, B)

        # check if ss_modal.(A,B) is close to ss_weak.(A,B)
        self.assertTrue(np.allclose(np.sort(np.linalg.eigvals(ss_weak.A)), np.sort(np.linalg.eigvals(ss_modal.A)),
                                    rtol=1e-05, atol=0.))
        self.assertTrue(np.allclose(np.array([i[0] for i in ss_weak.B]), ss_modal.B))

        # display results
        if show_plots:
            t, q = sim.simulate_state_space(ss_modal, u, initial_weights, dt)
            eval_d = ut.evaluate_approximation("eig_funcs", q, t, dz, spat_order=1)
            win1 = vis.PgAnimatedPlot([eval_d], title="Test")
            win2 = vis.PgSurfacePlot(eval_d[0])
            app.exec_()
Exemple #2
0
    def test_it(self):
        actuation_type = 'dirichlet'
        bound_cond_type = 'dirichlet'
        param = [1., -2., -1., None, None]
        adjoint_param = ef.get_adjoint_rad_evp_param(param)
        a2, a1, a0, _, _ = param

        l = 1.
        spatial_disc = 10
        dz = sim.Domain(bounds=(0, l), num=spatial_disc)

        T = 1.
        temporal_disc = 1e2
        dt = sim.Domain(bounds=(0, T), num=temporal_disc)

        omega = np.array([(i+1)*np.pi/l for i in xrange(spatial_disc)])
        eig_values = a0 - a2*omega**2 - a1**2/4./a2
        norm_fak = np.ones(omega.shape)*np.sqrt(2)
        eig_funcs = np.array([ef.SecondOrderDirichletEigenfunction(omega[i], param, dz.bounds, norm_fak[i])
                              for i in range(spatial_disc)])
        register_base("eig_funcs", eig_funcs, overwrite=True)
        adjoint_eig_funcs = np.array([ef.SecondOrderDirichletEigenfunction(omega[i],
                                                                           adjoint_param,
                                                                           dz.bounds,
                                                                           norm_fak[i]) for i in range(spatial_disc)])
        register_base("adjoint_eig_funcs", adjoint_eig_funcs, overwrite=True)

        # derive initial field variable x(z,0) and weights
        start_state = cr.Function(lambda z: 0., domain=(0, l))
        initial_weights = cr.project_on_base(start_state, adjoint_eig_funcs)

        # init trajectory
        u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type)

        # determine (A,B) with weak-formulation (pyinduct)

        # derive sate-space system
        rad_pde = ut.get_parabolic_dirichlet_weak_form("eig_funcs", "adjoint_eig_funcs", u, param, dz.bounds)
        cf = sim.parse_weak_formulation(rad_pde)
        ss_weak = cf.convert_to_state_space()

        # determine (A,B) with modal-transfomation
        A = np.diag(eig_values)
        B = -a2*np.array([adjoint_eig_funcs[i].derive()(l) for i in xrange(spatial_disc)])
        ss_modal = sim.StateSpace("eig_funcs", A, B)

        # TODO: resolve the big tolerance (rtol=3e-01) between ss_modal.A and ss_weak.A
        # check if ss_modal.(A,B) is close to ss_weak.(A,B)
        self.assertTrue(np.allclose(np.sort(np.linalg.eigvals(ss_weak.A)), np.sort(np.linalg.eigvals(ss_modal.A)),
                                    rtol=3e-1, atol=0.))
        self.assertTrue(np.allclose(np.array([i[0] for i in ss_weak.B]), ss_modal.B))

        # display results
        if show_plots:
            t, q = sim.simulate_state_space(ss_modal, u, initial_weights, dt)
            eval_d = ut.evaluate_approximation("eig_funcs", q, t, dz, spat_order=1)
            win2 = vis.PgSurfacePlot(eval_d)
            app.exec_()
    def test_it(self):

        # 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
        # a1_t = a1; a0_t = a0; alpha_t = alpha; beta_t = beta
        self.param_t = [a2, a1_t, a0_t, alpha_t, beta_t]

        # 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

        # system/simulation parameters
        self.l = 1; self.spatial_domain = (0, self.l); self.spatial_disc = 30
        self.n = 10

        # create (not normalized) eigenfunctions
        self.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.spatial_domain) for om in self.eig_freq])
        init_adjoint_eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, adjoint_param, self.spatial_domain) for om in self.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)]
        self.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])

        # eigenvalues and -frequencies test
        eig_freq_i, eig_val_i = ef.compute_rad_robin_eigenfrequencies(self.param_i, self.l, self.n)
        self.assertTrue(all(np.isclose(self.eig_val, eig_val_i)))
        calc_eig_freq = np.sqrt((a0_i-eig_val_i)/a2)
        self.assertTrue(all(np.isclose(calc_eig_freq, eig_freq_i)))

        # intermediate (_i) eigenfunction test
        eig_funcs_i = np.array([ef.SecondOrderRobinEigenfunction(eig_freq_i[i],
                                                                 self.param_i,
                                                                 self.spatial_domain,
                                                                 self.eig_funcs[i](0) )
                                for i in range(self.n)])
        self.assertTrue(all(np.isclose([func(0) for func in eig_funcs_i],
                                       [func(0) for func in self.eig_funcs])))
        test_vec = np.linspace(0, self.l, 100)
        for i in range(self.n):
            self.assertTrue(all(np.isclose(self.eig_funcs[i](test_vec),
                                           eig_funcs_i[i](test_vec)*np.exp(-a1/2/a2*test_vec))))
bound_cond_type = 'robin'
l = 1
T = 1
spatial_domain = sim.Domain(bounds=(0, l), num=n_fem)
temporal_domain = sim.Domain(bounds=(0, T), num=1e2)
n = n_modal
show_plots = False

# original system parameters
a2 = .5
a1 = 1
a0 = 2
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
Exemple #5
0
    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_()
Exemple #6
0
    def test_it(self):
        # system/simulation parameters
        actuation_type = 'robin'
        bound_cond_type = 'robin'

        self.l = 1.
        spatial_disc = 10
        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 = 10

        # original system parameters
        a2 = 1.5
        a1_z = cr.Function(lambda z: 1, derivative_handles=[lambda z: 0])
        a0_z = lambda z: 3
        alpha = -2
        beta = -3
        self.param = [a2, a1_z, a0_z, alpha, beta]

        # 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]
        adjoint_param_t = ef.get_adjoint_rad_evp_param(self.param_t)

        # original intermediate ("_i") and traget intermediate ("_ti") system parameters
        _, _, a0_i, alpha_i, beta_i = ef.transform2intermediate(self.param, d_end=self.l)
        self.param_i = a2, 0, a0_i, alpha_i, beta_i
        _, _, a0_ti, alpha_ti, beta_ti = ef.transform2intermediate(self.param_t)
        self.param_ti = a2, 0, a0_ti, alpha_ti, beta_ti

        # create (not normalized) target (_t) eigenfunctions
        eig_freq_t, self.eig_val_t = ef.compute_rad_robin_eigenfrequencies(self.param_t, self.l, self.n)
        init_eig_funcs_t = np.array([ef.SecondOrderRobinEigenfunction(om, self.param_t, self.dz.bounds)
                                     for om in eig_freq_t])
        init_adjoint_eig_funcs_t = np.array([ef.SecondOrderRobinEigenfunction(om, adjoint_param_t, self.dz.bounds)
                                             for om in eig_freq_t])

        # normalize eigenfunctions and adjoint eigenfunctions
        adjoint_and_eig_funcs_t = [cr.normalize_function(init_eig_funcs_t[i], init_adjoint_eig_funcs_t[i])
                                   for i in range(self.n)]
        eig_funcs_t = np.array([f_tuple[0] for f_tuple in adjoint_and_eig_funcs_t])
        self.adjoint_eig_funcs_t = np.array([f_tuple[1] for f_tuple in adjoint_and_eig_funcs_t])

        # # transformed original eigenfunctions
        self.eig_funcs = np.array([ef.TransformedSecondOrderEigenfunction(self.eig_val_t[i],
                                                                          [eig_funcs_t[i](0), alpha * eig_funcs_t[i](0),
                                                                           0, 0],
                                                                          [a2, a1_z, a0_z],
                                                                          np.linspace(0, self.l, 1e4))
                                   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 functions
        register_base("eig_funcs_t", eig_funcs_t, overwrite=True)
        register_base("adjoint_eig_funcs_t", self.adjoint_eig_funcs_t, overwrite=True)
        register_base("eig_funcs", self.eig_funcs, 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_t = ph.FieldVariable("eig_funcs_t", weight_label="eig_funcs", location=self.l)
        d_field_variable_t = ph.SpatialDerivedFieldVariable("eig_funcs_t", 1, weight_label="eig_funcs", location=self.l)
        field_variable = ph.FieldVariable("eig_funcs", location=self.l)
        d_field_variable = ph.SpatialDerivedFieldVariable("eig_funcs", 1, location=self.l)
        # intermediate (_i) and target intermediate (_ti) transformations by z=l

        #  x_i  = x   * transform_i_at_l
        self.transform_i_at_l = np.exp(integrate.quad(lambda z: a1_z(z) / 2 / a2, 0, self.l)[0])

        # x  = x_i   * inv_transform_i_at_l
        self.inv_transform_i_at_l = np.exp(-integrate.quad(lambda z: a1_z(z) / 2 / a2, 0, self.l)[0])

        # x_ti = x_t * transform_ti_at_l
        self.transform_ti_at_l = np.exp(a1_t / 2 / a2 * 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.transform_i_at_l)]
        self.x_i_at_l = [ph.ScalarTerm(field_variable, self.transform_i_at_l)]
        self.xd_i_at_l = [ph.ScalarTerm(d_field_variable, self.transform_i_at_l),
                          ph.ScalarTerm(field_variable, self.transform_i_at_l * a1_z(self.l) / 2 / a2)]
        self.x_ti_at_l = [ph.ScalarTerm(field_variable_t, self.transform_ti_at_l)]
        self.xd_ti_at_l = [ph.ScalarTerm(d_field_variable_t, self.transform_ti_at_l),
                           ph.ScalarTerm(field_variable_t, self.transform_ti_at_l * a1_t / 2 / a2)]

        # discontinuous operator (Kx)(t) = int_kernel_zz(l)*x(l,t)
        self.int_kernel_zz = alpha_ti - alpha_i + integrate.quad(lambda z: (a0_i(z) - a0_ti) / 2 / a2, 0, self.l)[0]

        controller = ut.get_parabolic_robin_backstepping_controller(state=self.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,
                                                                    original_beta=beta_i,
                                                                    target_beta=beta_ti,
                                                                    trajectory=self.traj,
                                                                    scale=self.inv_transform_i_at_l)

        rad_pde = ut.get_parabolic_robin_weak_form("fem_funcs", "fem_funcs", controller, self.param, self.dz.bounds)
        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)
        eval_d = sim.evaluate_approximation("fem_funcs", q, t, self.dz)
        x_0t = eval_d.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-4)

        # display results
        if show_plots:
            win1 = vis.PgAnimatedPlot([eval_d], title="Test")
            win2 = vis.PgSurfacePlot(eval_d)
            app.exec_()
Exemple #7
0
    def setUp(self):
        # 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
        # a1_t = a1; a0_t = a0; alpha_t = alpha; beta_t = beta
        self.param_t = [a2, a1_t, a0_t, alpha_t, beta_t]

        # original intermediate ("_i") and target 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

        # system/simulation parameters
        actuation_type = 'robin'
        bound_cond_type = 'robin'
        self.l = 1.
        spatial_disc = 10
        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 = 10

        # 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 from target system ("_t")
        eig_freq_t = np.sqrt(-a1_t ** 2 / 4 / a2 ** 2 + (a0_t - self.eig_val) / a2)
        eig_funcs_t = np.array([ef.SecondOrderRobinEigenfunction(eig_freq_t[i],
                                                                 self.param_t, self.dz.bounds).scale(eig_funcs[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_base("eig_funcs", eig_funcs, overwrite=True)
        register_base("adjoint_eig_funcs", self.adjoint_eig_funcs, overwrite=True)
        register_base("eig_funcs_t", eig_funcs_t, 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 = ph.FieldVariable("eig_funcs", location=self.l)
        d_field_variable = ph.SpatialDerivedFieldVariable("eig_funcs", 1, location=self.l)
        field_variable_t = ph.FieldVariable("eig_funcs_t", weight_label="eig_funcs", location=self.l)
        d_field_variable_t = ph.SpatialDerivedFieldVariable("eig_funcs_t", 1, weight_label="eig_funcs", location=self.l)

        # intermediate (_i) and target intermediate (_ti) transformations by z=l
        self.transform_i = lambda z: np.exp(a1 / 2 / a2 * z)  # x_i  = x   * transform_i
        self.transform_ti = lambda z: np.exp(a1_t / 2 / a2 * z)  # x_ti = x_t * transform_ti

        # 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.transform_i(self.l))]
        self.x_i_at_l = [ph.ScalarTerm(field_variable, self.transform_i(self.l))]
        self.xd_i_at_l = [ph.ScalarTerm(d_field_variable, self.transform_i(self.l)),
                          ph.ScalarTerm(field_variable, self.transform_i(self.l) * a1 / 2 / a2)]
        self.x_ti_at_l = [ph.ScalarTerm(field_variable_t, self.transform_ti(self.l))]
        self.xd_ti_at_l = [ph.ScalarTerm(d_field_variable_t, self.transform_ti(self.l)),
                           ph.ScalarTerm(field_variable_t, self.transform_ti(self.l) * a1_t / 2 / a2)]

        # 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
Exemple #8
0
    def test_it(self):
        actuation_type = 'robin'
        bound_cond_type = 'robin'
        param = [2., 1.5, -3., -1., -.5]
        adjoint_param = ef.get_adjoint_rad_evp_param(param)
        a2, a1, a0, alpha, beta = param

        l = 1.
        spatial_disc = 10
        dz = sim.Domain(bounds=(0, l), num=spatial_disc)

        T = 1.
        temporal_disc = 1e2
        dt = sim.Domain(bounds=(0, T), num=temporal_disc)
        n = 10

        eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies(param, l, n)

        init_eig_funcs = np.array([
            ef.SecondOrderRobinEigenfunction(om, param, dz.bounds)
            for om in eig_freq
        ])
        init_adjoint_eig_funcs = np.array([
            ef.SecondOrderRobinEigenfunction(om, adjoint_param, 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(n)
        ]
        eig_funcs = np.array([f_tuple[0] for f_tuple in adjoint_and_eig_funcs])
        adjoint_eig_funcs = np.array(
            [f_tuple[1] for f_tuple in adjoint_and_eig_funcs])

        # register eigenfunctions
        register_base("eig_funcs", eig_funcs, overwrite=True)
        register_base("adjoint_eig_funcs", adjoint_eig_funcs, overwrite=True)

        # derive initial field variable x(z,0) and weights
        start_state = cr.Function(lambda z: 0., domain=(0, l))
        initial_weights = cr.project_on_base(start_state, adjoint_eig_funcs)

        # init trajectory
        u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type)

        # determine (A,B) with weak-formulation (pyinduct)
        rad_pde = ut.get_parabolic_robin_weak_form("eig_funcs",
                                                   "adjoint_eig_funcs", u,
                                                   param, dz.bounds)
        cf = sim.parse_weak_formulation(rad_pde)
        ss_weak = cf.convert_to_state_space()

        # determine (A,B) with modal-transfomation
        A = np.diag(np.real_if_close(eig_val))
        B = a2 * np.array(
            [adjoint_eig_funcs[i](l) for i in range(len(eig_freq))])
        ss_modal = sim.StateSpace("eig_funcs", A, B, input_handle=u)

        # check if ss_modal.(A,B) is close to ss_weak.(A,B)
        self.assertTrue(
            np.allclose(np.sort(np.linalg.eigvals(ss_weak.A[1])),
                        np.sort(np.linalg.eigvals(ss_modal.A[1])),
                        rtol=1e-05,
                        atol=0.))
        self.assertTrue(
            np.allclose(np.array([i[0] for i in ss_weak.B[1]]), ss_modal.B[1]))

        # display results
        if show_plots:
            t, q = sim.simulate_state_space(ss_modal, initial_weights, dt)
            eval_d = sim.evaluate_approximation("eig_funcs",
                                                q,
                                                t,
                                                dz,
                                                spat_order=1)
            win1 = vis.PgAnimatedPlot([eval_d], title="Test")
            win2 = vis.PgSurfacePlot(eval_d)
            app.exec_()
    def test_it(self):

        # 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
        # a1_t = a1; a0_t = a0; alpha_t = alpha; beta_t = beta
        self.param_t = [a2, a1_t, a0_t, alpha_t, beta_t]

        # 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

        # system/simulation parameters
        self.l = 1
        self.spatial_domain = (0, self.l)
        self.spatial_disc = 30
        self.n = 10

        # create (not normalized) eigenfunctions
        self.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.spatial_domain)
            for om in self.eig_freq
        ])
        init_adjoint_eig_funcs = np.array([
            ef.SecondOrderRobinEigenfunction(om, adjoint_param,
                                             self.spatial_domain)
            for om in self.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)
        ]
        self.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])

        # eigenvalues and -frequencies test
        eig_freq_i, eig_val_i = ef.compute_rad_robin_eigenfrequencies(
            self.param_i, self.l, self.n)
        self.assertTrue(all(np.isclose(self.eig_val, eig_val_i)))
        calc_eig_freq = np.sqrt((a0_i - eig_val_i) / a2)
        self.assertTrue(all(np.isclose(calc_eig_freq, eig_freq_i)))

        # intermediate (_i) eigenfunction test
        eig_funcs_i = np.array([
            ef.SecondOrderRobinEigenfunction(eig_freq_i[i], self.param_i,
                                             self.spatial_domain,
                                             self.eig_funcs[i](0))
            for i in range(self.n)
        ])
        self.assertTrue(
            all(
                np.isclose([func(0) for func in eig_funcs_i],
                           [func(0) for func in self.eig_funcs])))
        test_vec = np.linspace(0, self.l, 100)
        for i in range(self.n):
            self.assertTrue(
                all(
                    np.isclose(
                        self.eig_funcs[i](test_vec), eig_funcs_i[i](test_vec) *
                        np.exp(-a1 / 2 / a2 * test_vec))))
Exemple #10
0
    def test_it(self):
        # system/simulation parameters
        actuation_type = 'robin'
        bound_cond_type = 'robin'

        self.l = 1.
        spatial_disc = 10
        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 = 10

        # original system parameters
        a2 = 1.5
        a1_z = cr.Function(lambda z: 1, derivative_handles=[lambda z: 0])
        a0_z = lambda z: 3
        alpha = -2
        beta = -3
        self.param = [a2, a1_z, a0_z, alpha, beta]

        # 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]
        adjoint_param_t = ef.get_adjoint_rad_evp_param(self.param_t)

        # original intermediate ("_i") and traget intermediate ("_ti") system parameters
        _, _, a0_i, alpha_i, beta_i = ef.transform2intermediate(self.param,
                                                                d_end=self.l)
        self.param_i = a2, 0, a0_i, alpha_i, beta_i
        _, _, a0_ti, alpha_ti, beta_ti = ef.transform2intermediate(
            self.param_t)
        self.param_ti = a2, 0, a0_ti, alpha_ti, beta_ti

        # create (not normalized) target (_t) eigenfunctions
        eig_freq_t, self.eig_val_t = ef.compute_rad_robin_eigenfrequencies(
            self.param_t, self.l, self.n)
        init_eig_funcs_t = np.array([
            ef.SecondOrderRobinEigenfunction(om, self.param_t, self.dz.bounds)
            for om in eig_freq_t
        ])
        init_adjoint_eig_funcs_t = np.array([
            ef.SecondOrderRobinEigenfunction(om, adjoint_param_t,
                                             self.dz.bounds)
            for om in eig_freq_t
        ])

        # normalize eigenfunctions and adjoint eigenfunctions
        adjoint_and_eig_funcs_t = [
            cr.normalize_function(init_eig_funcs_t[i],
                                  init_adjoint_eig_funcs_t[i])
            for i in range(self.n)
        ]
        eig_funcs_t = np.array(
            [f_tuple[0] for f_tuple in adjoint_and_eig_funcs_t])
        self.adjoint_eig_funcs_t = np.array(
            [f_tuple[1] for f_tuple in adjoint_and_eig_funcs_t])

        # # transformed original eigenfunctions
        self.eig_funcs = np.array([
            ef.TransformedSecondOrderEigenfunction(
                self.eig_val_t[i],
                [eig_funcs_t[i](0), alpha * eig_funcs_t[i](0), 0, 0],
                [a2, a1_z, a0_z], np.linspace(0, self.l, 1e4))
            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 functions
        register_base("eig_funcs_t", eig_funcs_t, overwrite=True)
        register_base("adjoint_eig_funcs_t",
                      self.adjoint_eig_funcs_t,
                      overwrite=True)
        register_base("eig_funcs", self.eig_funcs, 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_t = ph.FieldVariable("eig_funcs_t",
                                            weight_label="eig_funcs",
                                            location=self.l)
        d_field_variable_t = ph.SpatialDerivedFieldVariable(
            "eig_funcs_t", 1, weight_label="eig_funcs", location=self.l)
        field_variable = ph.FieldVariable("eig_funcs", location=self.l)
        d_field_variable = ph.SpatialDerivedFieldVariable("eig_funcs",
                                                          1,
                                                          location=self.l)
        # intermediate (_i) and target intermediate (_ti) transformations by z=l

        #  x_i  = x   * transform_i_at_l
        self.transform_i_at_l = np.exp(
            integrate.quad(lambda z: a1_z(z) / 2 / a2, 0, self.l)[0])

        # x  = x_i   * inv_transform_i_at_l
        self.inv_transform_i_at_l = np.exp(
            -integrate.quad(lambda z: a1_z(z) / 2 / a2, 0, self.l)[0])

        # x_ti = x_t * transform_ti_at_l
        self.transform_ti_at_l = np.exp(a1_t / 2 / a2 * 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.transform_i_at_l)
        ]
        self.x_i_at_l = [ph.ScalarTerm(field_variable, self.transform_i_at_l)]
        self.xd_i_at_l = [
            ph.ScalarTerm(d_field_variable, self.transform_i_at_l),
            ph.ScalarTerm(field_variable,
                          self.transform_i_at_l * a1_z(self.l) / 2 / a2)
        ]
        self.x_ti_at_l = [
            ph.ScalarTerm(field_variable_t, self.transform_ti_at_l)
        ]
        self.xd_ti_at_l = [
            ph.ScalarTerm(d_field_variable_t, self.transform_ti_at_l),
            ph.ScalarTerm(field_variable_t,
                          self.transform_ti_at_l * a1_t / 2 / a2)
        ]

        # discontinuous operator (Kx)(t) = int_kernel_zz(l)*x(l,t)
        self.int_kernel_zz = alpha_ti - alpha_i + integrate.quad(
            lambda z: (a0_i(z) - a0_ti) / 2 / a2, 0, self.l)[0]

        controller = ut.get_parabolic_robin_backstepping_controller(
            state=self.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,
            original_beta=beta_i,
            target_beta=beta_ti,
            trajectory=self.traj,
            scale=self.inv_transform_i_at_l)

        rad_pde = ut.get_parabolic_robin_weak_form("fem_funcs", "fem_funcs",
                                                   controller, self.param,
                                                   self.dz.bounds)
        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)
        eval_d = sim.evaluate_approximation("fem_funcs", q, t, self.dz)
        x_0t = eval_d.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-4)

        # display results
        if show_plots:
            win1 = vis.PgAnimatedPlot([eval_d], title="Test")
            win2 = vis.PgSurfacePlot(eval_d)
            app.exec_()
Exemple #11
0
    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_()
Exemple #12
0
    def setUp(self):
        # 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
        # a1_t = a1; a0_t = a0; alpha_t = alpha; beta_t = beta
        self.param_t = [a2, a1_t, a0_t, alpha_t, beta_t]

        # original intermediate ("_i") and target 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

        # system/simulation parameters
        actuation_type = 'robin'
        bound_cond_type = 'robin'
        self.l = 1.
        spatial_disc = 10
        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 = 10

        # 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 from target system ("_t")
        eig_freq_t = np.sqrt(-a1_t**2 / 4 / a2**2 + (a0_t - self.eig_val) / a2)
        eig_funcs_t = np.array([
            ef.SecondOrderRobinEigenfunction(eig_freq_t[i], self.param_t,
                                             self.dz.bounds).scale(
                                                 eig_funcs[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_base("eig_funcs", eig_funcs, overwrite=True)
        register_base("adjoint_eig_funcs",
                      self.adjoint_eig_funcs,
                      overwrite=True)
        register_base("eig_funcs_t", eig_funcs_t, 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 = ph.FieldVariable("eig_funcs", location=self.l)
        d_field_variable = ph.SpatialDerivedFieldVariable("eig_funcs",
                                                          1,
                                                          location=self.l)
        field_variable_t = ph.FieldVariable("eig_funcs_t",
                                            weight_label="eig_funcs",
                                            location=self.l)
        d_field_variable_t = ph.SpatialDerivedFieldVariable(
            "eig_funcs_t", 1, weight_label="eig_funcs", location=self.l)

        # intermediate (_i) and target intermediate (_ti) transformations by z=l
        self.transform_i = lambda z: np.exp(a1 / 2 / a2 * z
                                            )  # x_i  = x   * transform_i
        self.transform_ti = lambda z: np.exp(a1_t / 2 / a2 * z
                                             )  # x_ti = x_t * transform_ti

        # 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.transform_i(self.l))
        ]
        self.x_i_at_l = [
            ph.ScalarTerm(field_variable, self.transform_i(self.l))
        ]
        self.xd_i_at_l = [
            ph.ScalarTerm(d_field_variable, self.transform_i(self.l)),
            ph.ScalarTerm(field_variable,
                          self.transform_i(self.l) * a1 / 2 / a2)
        ]
        self.x_ti_at_l = [
            ph.ScalarTerm(field_variable_t, self.transform_ti(self.l))
        ]
        self.xd_ti_at_l = [
            ph.ScalarTerm(d_field_variable_t, self.transform_ti(self.l)),
            ph.ScalarTerm(field_variable_t,
                          self.transform_ti(self.l) * a1_t / 2 / a2)
        ]

        # 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
Exemple #13
0
    def test_it(self):
        # original system parameters
        a2 = 1.5
        a1 = 2.5
        a0 = 28
        alpha = -2
        beta = -3
        param = [a2, a1, a0, alpha, beta]
        adjoint_param = ef.get_adjoint_rad_evp_param(param)

        # target system parameters (controller parameters)
        a1_t = -5
        a0_t = -25
        alpha_t = 3
        beta_t = 2
        # a1_t = a1; a0_t = a0; alpha_t = alpha; beta_t = beta
        param_t = [a2, a1_t, a0_t, alpha_t, beta_t]

        # original intermediate ("_i") and traget intermediate ("_ti") system parameters
        _, _, a0_i, alpha_i, beta_i = ef.transform2intermediate(param)
        _, _, a0_ti, alpha_ti, beta_ti = ef.transform2intermediate(param_t)

        # system/simulation parameters
        actuation_type = 'robin'
        bound_cond_type = 'robin'
        self.l = 1.
        spatial_disc = 10
        dz = sim.Domain(bounds=(0, self.l), num=spatial_disc)

        T = 1.
        temporal_disc = 1e2
        dt = sim.Domain(bounds=(0, T), num=temporal_disc)
        n = 10

        # create (not normalized) eigenfunctions
        eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies(
            param, self.l, n)
        init_eig_funcs = np.array([
            ef.SecondOrderRobinEigenfunction(om, param, dz.bounds)
            for om in eig_freq
        ])
        init_adjoint_eig_funcs = np.array([
            ef.SecondOrderRobinEigenfunction(om, adjoint_param, 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(n)
        ]
        eig_funcs = np.array([f_tuple[0] for f_tuple in adjoint_and_eig_funcs])
        adjoint_eig_funcs = np.array(
            [f_tuple[1] for f_tuple in adjoint_and_eig_funcs])

        # eigenfunctions from target system ("_t")
        eig_freq_t = np.sqrt(-a1_t**2 / 4 / a2**2 + (a0_t - eig_val) / a2)
        eig_funcs_t = np.array([
            ef.SecondOrderRobinEigenfunction(eig_freq_t[i], param_t,
                                             dz.bounds).scale(eig_funcs[i](0))
            for i in range(n)
        ])

        # register eigenfunctions
        register_base("eig_funcs", eig_funcs, overwrite=True)
        register_base("adjoint_eig_funcs", adjoint_eig_funcs, overwrite=True)
        register_base("eig_funcs_t", eig_funcs_t, overwrite=True)

        # derive initial field variable x(z,0) and weights
        start_state = cr.Function(lambda z: 0., domain=(0, self.l))
        initial_weights = cr.project_on_base(start_state, adjoint_eig_funcs)

        # controller initialization
        x_at_l = ph.FieldVariable("eig_funcs", location=self.l)
        xd_at_l = ph.SpatialDerivedFieldVariable("eig_funcs",
                                                 1,
                                                 location=self.l)
        x_t_at_l = ph.FieldVariable("eig_funcs_t",
                                    weight_label="eig_funcs",
                                    location=self.l)
        xd_t_at_l = ph.SpatialDerivedFieldVariable("eig_funcs_t",
                                                   1,
                                                   weight_label="eig_funcs",
                                                   location=self.l)
        combined_transform = lambda z: np.exp((a1_t - a1) / 2 / a2 * z)
        int_kernel_zz = lambda z: alpha_ti - alpha_i + (a0_i - a0_ti
                                                        ) / 2 / a2 * z
        controller = ct.Controller(
            ct.ControlLaw([
                ph.ScalarTerm(x_at_l,
                              (beta_i - beta_ti - int_kernel_zz(self.l))),
                ph.ScalarTerm(x_t_at_l, -beta_ti * combined_transform(self.l)),
                ph.ScalarTerm(x_at_l, beta_ti),
                ph.ScalarTerm(xd_t_at_l, -combined_transform(self.l)),
                ph.ScalarTerm(x_t_at_l,
                              -a1_t / 2 / a2 * combined_transform(self.l)),
                ph.ScalarTerm(xd_at_l, 1),
                ph.ScalarTerm(x_at_l, a1 / 2 / a2 + int_kernel_zz(self.l))
            ]))

        # init trajectory
        traj = tr.RadTrajectory(self.l, T, param_t, bound_cond_type,
                                actuation_type)
        traj.scale = combined_transform(self.l)

        # input with feedback
        control_law = sim.SimulationInputSum([traj, controller])
        # control_law = sim.simInputSum([traj])

        # determine (A,B) with modal-transformation
        A = np.diag(np.real(eig_val))
        B = a2 * np.array(
            [adjoint_eig_funcs[i](self.l) for i in range(len(eig_freq))])
        ss_modal = sim.StateSpace("eig_funcs", A, B, input_handle=control_law)

        # simulate
        t, q = sim.simulate_state_space(ss_modal, initial_weights, dt)

        eval_d = sim.evaluate_approximation("eig_funcs", q, t, dz)
        x_0t = eval_d.output_data[:, 0]
        yc, tc = tr.gevrey_tanh(T, 1)
        x_0t_desired = np.interp(t, tc, yc[0, :])
        self.assertLess(np.average((x_0t - x_0t_desired)**2), 1e-4)

        # display results
        if show_plots:
            win1 = vis.PgAnimatedPlot([eval_d], title="Test")
            win2 = vis.PgSurfacePlot(eval_d)
            app.exec_()
Exemple #14
0
    def test_it(self):
        actuation_type = 'dirichlet'
        bound_cond_type = 'dirichlet'
        param = [1., -2., -1., None, None]
        adjoint_param = ef.get_adjoint_rad_evp_param(param)
        a2, a1, a0, _, _ = param

        l = 1.
        spatial_disc = 10
        dz = sim.Domain(bounds=(0, l), num=spatial_disc)

        T = 1.
        temporal_disc = 1e2
        dt = sim.Domain(bounds=(0, T), num=temporal_disc)

        omega = np.array([(i + 1) * np.pi / l for i in range(spatial_disc)])
        eig_values = a0 - a2 * omega**2 - a1**2 / 4. / a2
        norm_fak = np.ones(omega.shape) * np.sqrt(2)
        eig_funcs = np.array([
            ef.SecondOrderDirichletEigenfunction(omega[i], param, dz.bounds,
                                                 norm_fak[i])
            for i in range(spatial_disc)
        ])
        register_base("eig_funcs", eig_funcs, overwrite=True)
        adjoint_eig_funcs = np.array([
            ef.SecondOrderDirichletEigenfunction(omega[i], adjoint_param,
                                                 dz.bounds, norm_fak[i])
            for i in range(spatial_disc)
        ])
        register_base("adjoint_eig_funcs", adjoint_eig_funcs, overwrite=True)

        # derive initial field variable x(z,0) and weights
        start_state = cr.Function(lambda z: 0., domain=(0, l))
        initial_weights = cr.project_on_base(start_state, adjoint_eig_funcs)

        # init trajectory
        u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type)

        # determine (A,B) with weak-formulation (pyinduct)

        # derive sate-space system
        rad_pde = ut.get_parabolic_dirichlet_weak_form("eig_funcs",
                                                       "adjoint_eig_funcs", u,
                                                       param, dz.bounds)
        cf = sim.parse_weak_formulation(rad_pde)
        ss_weak = cf.convert_to_state_space()

        # determine (A,B) with modal-transfomation
        A = np.diag(eig_values)
        B = -a2 * np.array(
            [adjoint_eig_funcs[i].derive()(l) for i in range(spatial_disc)])
        ss_modal = sim.StateSpace("eig_funcs", A, B, input_handle=u)

        # TODO: resolve the big tolerance (rtol=3e-01) between ss_modal.A and ss_weak.A
        # check if ss_modal.(A,B) is close to ss_weak.(A,B)
        self.assertTrue(
            np.allclose(np.sort(np.linalg.eigvals(ss_weak.A[1])),
                        np.sort(np.linalg.eigvals(ss_modal.A[1])),
                        rtol=3e-1,
                        atol=0.))
        self.assertTrue(
            np.allclose(np.array([i[0] for i in ss_weak.B[1]]), ss_modal.B[1]))

        # display results
        if show_plots:
            t, q = sim.simulate_state_space(ss_modal, initial_weights, dt)
            eval_d = sim.evaluate_approximation("eig_funcs",
                                                q,
                                                t,
                                                dz,
                                                spat_order=1)
            win2 = vis.PgSurfacePlot(eval_d)
            app.exec_()
bound_cond_type = 'robin'
l = 1
T = 1
spatial_domain = sim.Domain(bounds=(0, l), num=n_fem)
temporal_domain = sim.Domain(bounds=(0, T), num=1e2)
n = n_modal
show_plots = False

# original system parameters
a2 = .5
a1 = 1
a0 = 2
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
Exemple #16
0
    def test_it(self):
        # original system parameters
        a2 = 1.5;
        a1 = 2.5;
        a0 = 28;
        alpha = -2;
        beta = -3
        param = [a2, a1, a0, alpha, beta]
        adjoint_param = ef.get_adjoint_rad_evp_param(param)

        # target system parameters (controller parameters)
        a1_t = -5;
        a0_t = -25;
        alpha_t = 3;
        beta_t = 2
        # a1_t = a1; a0_t = a0; alpha_t = alpha; beta_t = beta
        param_t = [a2, a1_t, a0_t, alpha_t, beta_t]

        # original intermediate ("_i") and traget intermediate ("_ti") system parameters
        _, _, a0_i, alpha_i, beta_i = ef.transform2intermediate(param)
        _, _, a0_ti, alpha_ti, beta_ti = ef.transform2intermediate(param_t)

        # system/simulation parameters
        actuation_type = 'robin'
        bound_cond_type = 'robin'
        self.l = 1.
        spatial_disc = 10
        dz = sim.Domain(bounds=(0, self.l), num=spatial_disc)

        T = 1.
        temporal_disc = 1e2
        dt = sim.Domain(bounds=(0, T), num=temporal_disc)
        n = 10

        # create (not normalized) eigenfunctions
        eig_freq, eig_val = ef.compute_rad_robin_eigenfrequencies(param, self.l, n)
        init_eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, param, dz.bounds) for om in eig_freq])
        init_adjoint_eig_funcs = np.array([ef.SecondOrderRobinEigenfunction(om, adjoint_param, 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(n)]
        eig_funcs = np.array([f_tuple[0] for f_tuple in adjoint_and_eig_funcs])
        adjoint_eig_funcs = np.array([f_tuple[1] for f_tuple in adjoint_and_eig_funcs])

        # eigenfunctions from target system ("_t")
        eig_freq_t = np.sqrt(-a1_t ** 2 / 4 / a2 ** 2 + (a0_t - eig_val) / a2)
        eig_funcs_t = np.array([ef.SecondOrderRobinEigenfunction(eig_freq_t[i],
                                                                 param_t, dz.bounds).scale(eig_funcs[i](0))
                                for i in range(n)])

        # register eigenfunctions
        register_base("eig_funcs", eig_funcs, overwrite=True)
        register_base("adjoint_eig_funcs", adjoint_eig_funcs, overwrite=True)
        register_base("eig_funcs_t", eig_funcs_t, overwrite=True)

        # derive initial field variable x(z,0) and weights
        start_state = cr.Function(lambda z: 0., domain=(0, self.l))
        initial_weights = cr.project_on_base(start_state, adjoint_eig_funcs)

        # controller initialization
        x_at_l = ph.FieldVariable("eig_funcs", location=self.l)
        xd_at_l = ph.SpatialDerivedFieldVariable("eig_funcs", 1, location=self.l)
        x_t_at_l = ph.FieldVariable("eig_funcs_t", weight_label="eig_funcs", location=self.l)
        xd_t_at_l = ph.SpatialDerivedFieldVariable("eig_funcs_t", 1, weight_label="eig_funcs", location=self.l)
        combined_transform = lambda z: np.exp((a1_t - a1) / 2 / a2 * z)
        int_kernel_zz = lambda z: alpha_ti - alpha_i + (a0_i - a0_ti) / 2 / a2 * z
        controller = ct.Controller(
            ct.ControlLaw([ph.ScalarTerm(x_at_l, (beta_i - beta_ti - int_kernel_zz(self.l))),
                           ph.ScalarTerm(x_t_at_l, -beta_ti * combined_transform(self.l)),
                           ph.ScalarTerm(x_at_l, beta_ti),
                           ph.ScalarTerm(xd_t_at_l, -combined_transform(self.l)),
                           ph.ScalarTerm(x_t_at_l, -a1_t / 2 / a2 * combined_transform(self.l)),
                           ph.ScalarTerm(xd_at_l, 1),
                           ph.ScalarTerm(x_at_l, a1 / 2 / a2 + int_kernel_zz(self.l))
                           ]))

        # init trajectory
        traj = tr.RadTrajectory(self.l, T, param_t, bound_cond_type, actuation_type)
        traj.scale = combined_transform(self.l)

        # input with feedback
        control_law = sim.SimulationInputSum([traj, controller])
        # control_law = sim.simInputSum([traj])

        # determine (A,B) with modal-transformation
        A = np.diag(np.real(eig_val))
        B = a2 * np.array([adjoint_eig_funcs[i](self.l) for i in range(len(eig_freq))])
        ss_modal = sim.StateSpace("eig_funcs", A, B, input_handle=control_law)

        # simulate
        t, q = sim.simulate_state_space(ss_modal, initial_weights, dt)

        eval_d = sim.evaluate_approximation("eig_funcs", q, t, dz)
        x_0t = eval_d.output_data[:, 0]
        yc, tc = tr.gevrey_tanh(T, 1)
        x_0t_desired = np.interp(t, tc, yc[0, :])
        self.assertLess(np.average((x_0t - x_0t_desired) ** 2), 1e-4)

        # display results
        if show_plots:
            win1 = vis.PgAnimatedPlot([eval_d], title="Test")
            win2 = vis.PgSurfacePlot(eval_d)
            app.exec_()
# original system parameters
a2 = .5
a1_z = cr.Function(lambda z: 0.1 * np.exp(4 * z),
                   derivative_handles=[lambda z: 0.4 * np.exp(4 * z)])
a0_z = lambda z: 1 + 10 * z + 2 * np.sin(4 * np.pi / l * z)
alpha = -1
beta = -1
param = [a2, a1_z, a0_z, alpha, beta]

# target system parameters (controller parameters)
a1_t = -0
a0_t = -6
alpha_t = 3
beta_t = 3
param_t = [a2, a1_t, a0_t, alpha_t, beta_t]
adjoint_param_t = ef.get_adjoint_rad_evp_param(param_t)

# original intermediate ("_i") and target intermediate ("_ti") system parameters
_, _, a0_i, alpha_i, beta_i = ef.transform2intermediate(param, d_end=l)
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

# create (not normalized) target (_t) eigenfunctions
eig_freq_t, eig_val_t = ef.compute_rad_robin_eigenfrequencies(param_t, l, n)
init_eig_funcs_t = np.array([ef.SecondOrderRobinEigenfunction(om, param_t, spatial_domain.bounds) for om in eig_freq_t])
init_adjoint_eig_funcs_t = np.array(
    [ef.SecondOrderRobinEigenfunction(om, adjoint_param_t, spatial_domain.bounds) for om in eig_freq_t])

# normalize eigenfunctions and adjoint eigenfunctions
adjoint_and_eig_funcs_t = [cr.normalize_function(init_eig_funcs_t[i], init_adjoint_eig_funcs_t[i]) for i in range(n)]
# original system parameters
a2 = .5
a1_z = cr.Function(lambda z: 0.1 * np.exp(4 * z),
                   derivative_handles=[lambda z: 0.4 * np.exp(4 * z)])
a0_z = lambda z: 1 + 10 * z + 2 * np.sin(4 * np.pi / l * z)
alpha = -1
beta = -1
param = [a2, a1_z, a0_z, alpha, beta]

# target system parameters (controller parameters)
a1_t = -0
a0_t = -6
alpha_t = 3
beta_t = 3
param_t = [a2, a1_t, a0_t, alpha_t, beta_t]
adjoint_param_t = ef.get_adjoint_rad_evp_param(param_t)

# original intermediate ("_i") and target intermediate ("_ti") system parameters
_, _, a0_i, alpha_i, beta_i = ef.transform2intermediate(param, d_end=l)
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

# create (not normalized) target (_t) eigenfunctions
eig_freq_t, eig_val_t = ef.compute_rad_robin_eigenfrequencies(param_t, l, n)
init_eig_funcs_t = np.array([
    ef.SecondOrderRobinEigenfunction(om, param_t, spatial_domain.bounds)
    for om in eig_freq_t
])
init_adjoint_eig_funcs_t = np.array([
    ef.SecondOrderRobinEigenfunction(om, adjoint_param_t,