def setUp(self): self.u = CorrectInput() # setup temp and spat domain spat_domain = sim.Domain((0, 1), num=3) nodes, ini_funcs = sf.cure_interval(sf.LagrangeFirstOrder, spat_domain.bounds, node_count=3) register_base("init_funcs", ini_funcs, overwrite=True) # enter string with mass equations for testing int1 = ph.IntegralTerm( ph.Product(ph.TemporalDerivedFieldVariable("init_funcs", 2), ph.TestFunction("init_funcs")), spat_domain.bounds) s1 = ph.ScalarTerm( ph.Product( ph.TemporalDerivedFieldVariable("init_funcs", 2, location=0), ph.TestFunction("init_funcs", location=0))) int2 = ph.IntegralTerm( ph.Product(ph.SpatialDerivedFieldVariable("init_funcs", 1), ph.TestFunction("init_funcs", order=1)), spat_domain.bounds) s2 = ph.ScalarTerm( ph.Product(ph.Input(self.u), ph.TestFunction("init_funcs", location=1)), -1) string_pde = sim.WeakFormulation([int1, s1, int2, s2]) self.cf = sim.parse_weak_formulation(string_pde) self.ic = np.zeros((3, 2))
def setUp(self): self.u = CorrectInput() # setup temp and spat domain spat_domain = sim.Domain((0, 1), num=3) nodes, ini_funcs = sf.cure_interval(sf.LagrangeFirstOrder, spat_domain.bounds, node_count=3) register_base("init_funcs", ini_funcs, overwrite=True) # enter string with mass equations for testing int1 = ph.IntegralTerm( ph.Product(ph.TemporalDerivedFieldVariable("init_funcs", 2), ph.TestFunction("init_funcs")), spat_domain.bounds) s1 = ph.ScalarTerm( ph.Product(ph.TemporalDerivedFieldVariable("init_funcs", 2, location=0), ph.TestFunction("init_funcs", location=0))) int2 = ph.IntegralTerm( ph.Product(ph.SpatialDerivedFieldVariable("init_funcs", 1), ph.TestFunction("init_funcs", order=1)), spat_domain.bounds) s2 = ph.ScalarTerm( ph.Product(ph.Input(self.u), ph.TestFunction("init_funcs", location=1)), -1) string_pde = sim.WeakFormulation([int1, s1, int2, s2]) self.cf = sim.parse_weak_formulation(string_pde) self.ic = np.zeros((3, 2))
def _build_bases(self, n_modal, orig_params, tar_params, spatial_domain): """ Compute approximation bases for original and target system """ # eigenvalues and -vectors of the original system orig_eig_values, orig_eig_vectors = \ pi.SecondOrderDirichletEigenfunction.cure_interval(spatial_domain, param=orig_params, n=n_modal) norm_orig_eig_vectors = pi.normalize_base(orig_eig_vectors) pi.register_base(self.orig_base_lbl, norm_orig_eig_vectors) # eigenvectors of the target system (slightly different) target_eig_freq = pi.SecondOrderDirichletEigenfunction.eigval_tf_eigfreq( tar_params, eig_val=orig_eig_values) orig_scale = np.array( [vec(0) for vec in norm_orig_eig_vectors.derive(1)]) tar_scale = orig_scale / target_eig_freq _, tar_eig_vectors = pi.SecondOrderDirichletEigenfunction.cure_interval( spatial_domain, param=tar_params, eig_val=orig_eig_values, scale=tar_scale) pi.register_base(self.tar_base_lbl, tar_eig_vectors) if self.verbose: pi.visualize_functions(orig_eig_vectors) pi.visualize_functions(norm_orig_eig_vectors) pi.visualize_functions(tar_eig_vectors)
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_()
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_fem(self): """ use best documented fem case to test all steps in simulation process """ # enter string with mass equations nodes, ini_funcs = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeSecondOrder, self.dz.bounds, node_count=10) register_base("init_funcs", ini_funcs, overwrite=True) int1 = ph.IntegralTerm( ph.Product(ph.TemporalDerivedFieldVariable("init_funcs", 2), ph.TestFunction("init_funcs")), self.dz.bounds, scale=self.params.sigma*self.params.tau**2) s1 = ph.ScalarTerm( ph.Product(ph.TemporalDerivedFieldVariable("init_funcs", 2, location=0), ph.TestFunction("init_funcs", location=0)), scale=self.params.m) int2 = ph.IntegralTerm( ph.Product(ph.SpatialDerivedFieldVariable("init_funcs", 1), ph.TestFunction("init_funcs", order=1)), self.dz.bounds, scale=self.params.sigma) s2 = ph.ScalarTerm( ph.Product(ph.Input(self.u), ph.TestFunction("init_funcs", location=1)), -self.params.sigma) # derive sate-space system string_pde = sim.WeakFormulation([int1, s1, int2, s2], name="fem_test") self.cf = sim.parse_weak_formulation(string_pde) ss = self.cf.convert_to_state_space() # generate initial conditions for weights q0 = np.array([cr.project_on_base(self.ic[idx], ini_funcs) for idx in range(2)]).flatten() # simulate t, q = sim.simulate_state_space(ss, self.cf.input_function, q0, self.dt) # calculate result data eval_data = [] for der_idx in range(2): eval_data.append( ut.evaluate_approximation("init_funcs", q[:, der_idx * ini_funcs.size:(der_idx + 1) * ini_funcs.size], t, self.dz)) eval_data[-1].name = "{0}{1}".format(self.cf.name, "_"+"".join(["d" for x in range(der_idx)]) + "t" if der_idx > 0 else "") # display results if show_plots: win = vis.PgAnimatedPlot(eval_data[:2], title="fem approx and derivative") win2 = vis.PgSurfacePlot(eval_data[0]) app.exec_() # test for correct transition self.assertTrue(np.isclose(eval_data[0].output_data[-1, 0], self.y_end, atol=1e-3)) # TODO dump in pyinduct/tests/ressources file_path = os.sep.join(["resources", "test_data.res"]) if not os.path.isdir("resources"): os.makedirs("resources") with open(file_path, "w") as f: f.write(dumps(eval_data))
def setUp(self): self.u = np.sin self.input = ph.Input(self.u) # control input nodes, self.ini_funcs = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeFirstOrder, (0, 1), node_count=3) register_base("ini_funcs", self.ini_funcs, overwrite=True) self.phi = ph.TestFunction("ini_funcs") # eigenfunction or something else self.dphi = ph.TestFunction("ini_funcs", order=1) # eigenfunction or something else self.dphi_at1 = ph.TestFunction("ini_funcs", order=1, location=1) # eigenfunction or something else self.field_var = ph.FieldVariable("ini_funcs") self.field_var_at1 = ph.FieldVariable("ini_funcs", location=1)
def setUp(self): self.input = ph.Input(np.sin) self.phi = np.array([cr.Function(lambda x: 2*x)]) register_base("phi", self.phi, overwrite=True) self.test_func = ph.TestFunction("phi") nodes, self.ini_funcs = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeFirstOrder, (0, 1), node_count=2) register_base("ini_funcs", self.ini_funcs, overwrite=True) self.xdt = ph.TemporalDerivedFieldVariable("ini_funcs", order=1) self.xdz_at1 = ph.SpatialDerivedFieldVariable("ini_funcs", order=1, location=1) self.prod = ph.Product(self.input, self.xdt)
def setUp(self): self.node_cnt = 5 self.time_step = 1e-1 self.dates = np.arange(0, 10, self.time_step) self.spat_int = (0, 1) self.nodes = np.linspace(self.spat_int[0], self.spat_int[1], self.node_cnt) # create initial functions self.nodes, self.funcs = sh.cure_interval(sh.LagrangeFirstOrder, self.spat_int, node_count=self.node_cnt) register_base("approx_funcs", self.funcs, overwrite=True) # create a slow rising, nearly horizontal line self.weights = np.array(list(range(self.node_cnt*self.dates.size))).reshape((self.dates.size, len(self.nodes)))
def setUp(self): interval = (0, 10) node_cnt = 11 self.nodes, self.initial_functions = shapefunctions.cure_interval(shapefunctions.LagrangeFirstOrder, interval, node_count=node_cnt) register_base("ini_funcs", self.initial_functions, overwrite=True) # "real" functions self.z_values = np.linspace(interval[0], interval[1], 100*node_cnt) # because we are smarter self.funcs = [core.Function(lambda x: 2), core.Function(lambda x: 2*x), core.Function(lambda x: x**2), core.Function(lambda x: np.sin(x)) ] self.real_values = [func(self.z_values) for func in self.funcs]
def setUp(self): self.input = ph.Input(np.sin) self.phi = np.array([cr.Function(lambda x: 2 * x)]) register_base("phi", self.phi, overwrite=True) self.test_func = ph.TestFunction("phi") nodes, self.ini_funcs = cure_interval(LagrangeFirstOrder, (0, 1), node_count=2) register_base("ini_funcs", self.ini_funcs, overwrite=True) self.xdt = ph.TemporalDerivedFieldVariable("ini_funcs", order=1) self.xdz_at1 = ph.SpatialDerivedFieldVariable("ini_funcs", order=1, location=1) self.prod = ph.Product(self.input, self.xdt)
def setUp(self): self.u = np.sin self.input = ph.Input(self.u) # control input nodes, self.ini_funcs = cure_interval(LagrangeFirstOrder, (0, 1), node_count=3) register_base("ini_funcs", self.ini_funcs, overwrite=True) self.phi = ph.TestFunction( "ini_funcs") # eigenfunction or something else self.dphi = ph.TestFunction("ini_funcs", order=1) # eigenfunction or something else self.dphi_at1 = ph.TestFunction( "ini_funcs", order=1, location=1) # eigenfunction or something else self.field_var = ph.FieldVariable("ini_funcs") self.field_var_at1 = ph.FieldVariable("ini_funcs", location=1)
def setUp(self): interval = (0, 1) nodes, funcs = sf.cure_interval(sf.LagrangeFirstOrder, interval, 3) register_base("funcs", funcs, overwrite=True) x = ph.FieldVariable("funcs") x_dt = ph.TemporalDerivedFieldVariable("funcs", 1) x_dz = ph.SpatialDerivedFieldVariable("funcs", 1) register_base("scal_func", cr.Function(np.exp), overwrite=True) exp = ph.ScalarFunction("scal_func") alpha = 2 self.term1 = ph.IntegralTerm(x_dt, interval, 1 + alpha) self.term2 = ph.IntegralTerm(x_dz, interval, 2) self.term3 = ph.IntegralTerm(ph.Product(x, exp), interval) self.weight_label = "funcs" self.weights = np.hstack([1, 1, 1, 2, 2, 2])
def setUp(self): self.node_cnt = 5 self.time_step = 1e-1 self.dates = np.arange(0, 10, self.time_step) self.spat_int = (0, 1) self.nodes = np.linspace(self.spat_int[0], self.spat_int[1], self.node_cnt) # create initial functions self.nodes, self.funcs = sh.cure_interval(sh.LagrangeFirstOrder, self.spat_int, node_count=self.node_cnt) register_base("approx_funcs", self.funcs, overwrite=True) # create a slow rising, nearly horizontal line self.weights = np.array(list(range( self.node_cnt * self.dates.size))).reshape( (self.dates.size, len(self.nodes)))
def setUp(self): interval = (0, 1) nodes, funcs = sf.cure_interval(sf.LagrangeFirstOrder, interval, 3) register_base("funcs", funcs, overwrite=True) x_at1 = ph.FieldVariable("funcs", location=1) x_dt_at1 = ph.TemporalDerivedFieldVariable("funcs", 1, location=1) x_dz_at0 = ph.SpatialDerivedFieldVariable("funcs", 1, location=0) exp_func = cr.Function(np.exp) register_base("exp_func", exp_func, overwrite=True) exp_at1 = ph.ScalarFunction("exp_func", location=1) alpha = 2 self.term1 = ph.ScalarTerm(x_dt_at1, 1 + alpha) self.term2 = ph.ScalarTerm(x_dz_at0, 2) self.term3 = ph.ScalarTerm(ph.Product(x_at1, exp_at1)) self.weight_label = "funcs" self.weights = np.array([1, 1, 1, 2, 2, 2])
def shape_generator(self, cls, der_order): """ verify the correct connection with visual feedback """ dz = pi.Domain((0, 1), step=.001) dt = pi.Domain((0, 0), num=1) nodes, funcs = pi.cure_interval(cls, dz.bounds, node_count=11) pi.register_base("test", funcs, overwrite=True) # approx_func = pi.Function(np.cos, domain=dz.bounds, # derivative_handles=[lambda z: -np.sin(z), lambda z: -np.cos(z)]) approx_func = pi.Function(lambda z: np.sin(3*z), domain=dz.bounds, derivative_handles=[lambda z: 3*np.cos(3*z), lambda z: -9*np.sin(3*z)]) weights = approx_func(nodes) hull = pi.evaluate_approximation("test", np.atleast_2d(weights), temp_domain=dt, spat_domain=dz, spat_order=der_order) if show_plots: # plot shapefunctions c_map = pi.visualization.create_colormap(len(funcs)) pw = pg.plot(title="{}-Test".format(cls.__name__)) pw.addLegend() pw.showGrid(x=True, y=True, alpha=0.5) [pw.addItem(pg.PlotDataItem(np.array(dz), weights[idx]*func.derive(der_order)(dz), pen=pg.mkPen(color=c_map[idx]), name="{}.{}".format(cls.__name__, idx))) for idx, func in enumerate(funcs)] # plot hull curve pw.addItem(pg.PlotDataItem(np.array(hull.input_data[1]), hull.output_data[0, :], pen=pg.mkPen(width=2), name="hull-curve")) # plot original function pw.addItem(pg.PlotDataItem(np.array(dz), approx_func.derive(der_order)(dz), pen=pg.mkPen(color="m", width=2, style=pg.QtCore.Qt.DashLine), name="original")) pg.QtCore.QCoreApplication.instance().exec_() return np.sum(np.abs(hull.output_data[0, :] - approx_func.derive(der_order)(dz)))
def __init__(self, params, n_modal, spat_dom): a2 = params[0] z_start, z_end = spat_dom.bounds self.base_lbl = "eigen_vectors" # eigenvalues and -vectors of the system system eig_values, eig_vectors = \ pi.SecondOrderDirichletEigenfunction.cure_interval(spat_dom, param=params, n=n_modal) # pi.visualize_functions(orig_eig_vectors) norm_eig_vectors = pi.normalize_base(eig_vectors) # pi.visualize_functions(normalized_eig_vectors) pi.register_base(self.base_lbl, norm_eig_vectors) self.a_mat = np.diag(np.real_if_close(eig_values)) b_mat = -a2 * np.array( [eig_vect.derive()(z_end) for eig_vect in norm_eig_vectors]) self.b_mat = np.reshape(b_mat, (b_mat.size, 1))
def setUp(self): # enter string with mass equations self.u = cr.Function(lambda x: 0) interval = (0, 1) nodes, ini_funcs = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeFirstOrder, interval, node_count=3) register_base("init_funcs", ini_funcs, overwrite=True) int1 = ph.IntegralTerm( ph.Product(ph.TemporalDerivedFieldVariable("init_funcs", 2), ph.TestFunction("init_funcs")), interval) s1 = ph.ScalarTerm( ph.Product(ph.TemporalDerivedFieldVariable("init_funcs", 2, location=0), ph.TestFunction("init_funcs", location=0))) int2 = ph.IntegralTerm( ph.Product(ph.SpatialDerivedFieldVariable("init_funcs", 1), ph.TestFunction("init_funcs", order=1)), interval) s2 = ph.ScalarTerm( ph.Product(ph.Input(self.u), ph.TestFunction("init_funcs", location=1)), -1) string_pde = sim.WeakFormulation([int1, s1, int2, s2]) self.cf = sim.parse_weak_formulation(string_pde)
def setUp(self): # real function self.z_values = np.linspace(0, 1, 1000) self.real_func = core.Function(lambda x: x) self.real_func_handle = np.vectorize(self.real_func) # approximation by lag1st self.nodes, self.src_test_funcs = shapefunctions.cure_interval(shapefunctions.LagrangeFirstOrder, (0, 1), node_count=2) register_base("test_funcs", self.src_test_funcs, overwrite=True) self.src_weights = core.project_on_base(self.real_func, self.src_test_funcs) self.assertTrue(np.allclose(self.src_weights, [0, 1])) # just to be sure self.src_approx_handle = core.back_project_from_base(self.src_weights, self.src_test_funcs) # approximation by sin(w*x) def trig_factory(freq): def func(x): return np.sin(freq*x) return func self.trig_test_funcs = np.array([core.Function(trig_factory(w), domain=(0, 1)) for w in range(1, 3)])
def setUp(self): self.input = ph.Input(np.sin) phi = cr.Function(np.sin) psi = cr.Function(np.cos) self.t_funcs = np.array([phi, psi]) register_base("funcs", self.t_funcs, overwrite=True) self.test_funcs = ph.TestFunction("funcs") self.s_funcs = np.array([cr.Function(self.scale)])[[0, 0]] register_base("scale_funcs", self.s_funcs, overwrite=True) self.scale_funcs = ph.ScalarFunction("scale_funcs") nodes, self.ini_funcs = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeFirstOrder, (0, 1), node_count=2) register_base("prod_ini_funcs", self.ini_funcs, overwrite=True) self.field_var = ph.FieldVariable("prod_ini_funcs") self.field_var_dz = ph.SpatialDerivedFieldVariable("prod_ini_funcs", 1)
def setUp(self): self.input = ph.Input(np.sin) phi = cr.Function(np.sin) psi = cr.Function(np.cos) self.t_funcs = np.array([phi, psi]) register_base("funcs", self.t_funcs, overwrite=True) self.test_funcs = ph.TestFunction("funcs") self.s_funcs = np.array([cr.Function(self.scale)])[[0, 0]] register_base("scale_funcs", self.s_funcs, overwrite=True) self.scale_funcs = ph.ScalarFunction("scale_funcs") nodes, self.ini_funcs = cure_interval(LagrangeFirstOrder, (0, 1), node_count=2) register_base("prod_ini_funcs", self.ini_funcs, overwrite=True) self.field_var = ph.FieldVariable("prod_ini_funcs") self.field_var_dz = ph.SpatialDerivedFieldVariable("prod_ini_funcs", 1)
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_()
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
def setUp(self): self.psi = cr.Function(np.sin) register_base("funcs", self.psi, overwrite=True) self.funcs = ph.TestFunction("funcs")
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_()
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
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_modal(self): order = 8 def char_eq(w): return w * (np.sin(w) + self.params.m * w * np.cos(w)) def phi_k_factory(freq, derivative_order=0): def eig_func(z): return np.cos( freq * z) - self.params.m * freq * np.sin(freq * z) def eig_func_dz(z): return -freq * (np.sin(freq * z) + self.params.m * freq * np.cos(freq * z)) def eig_func_ddz(z): return freq**2 * (-np.cos(freq * z) + self.params.m * freq * np.sin(freq * z)) if derivative_order == 0: return eig_func elif derivative_order == 1: return eig_func_dz elif derivative_order == 2: return eig_func_ddz else: raise ValueError # create eigenfunctions eig_frequencies = ut.find_roots(char_eq, n_roots=order, grid=np.arange(0, 1e3, 2), rtol=-2) print("eigenfrequencies:") print(eig_frequencies) # create eigen function vectors class SWMFunctionVector(cr.ComposedFunctionVector): """ String With Mass Function Vector, necessary due to manipulated scalar product """ @property def func(self): return self.members["funcs"][0] @property def scalar(self): return self.members["scalars"][0] eig_vectors = [] for n in range(order): eig_vectors.append( SWMFunctionVector( cr.Function(phi_k_factory(eig_frequencies[n]), derivative_handles=[ phi_k_factory(eig_frequencies[n], der_order) for der_order in range(1, 3) ], domain=self.dz.bounds, nonzero=self.dz.bounds), phi_k_factory(eig_frequencies[n])(0))) # normalize eigen vectors norm_eig_vectors = [cr.normalize_function(vec) for vec in eig_vectors] norm_eig_funcs = np.array([vec.func for vec in norm_eig_vectors]) register_base("norm_eig_funcs", norm_eig_funcs, overwrite=True) norm_eig_funcs[0](1) # debug print eigenfunctions if 0: func_vals = [] for vec in eig_vectors: func_vals.append(np.vectorize(vec.func)(self.dz)) norm_func_vals = [] for func in norm_eig_funcs: norm_func_vals.append(np.vectorize(func)(self.dz)) clrs = ["r", "g", "b", "c", "m", "y", "k", "w"] for n in range(1, order + 1, len(clrs)): pw_phin_k = pg.plot(title="phin_k for k in [{0}, {1}]".format( n, min(n + len(clrs), order))) for k in range(len(clrs)): if k + n > order: break pw_phin_k.plot(x=np.array(self.dz), y=norm_func_vals[n + k - 1], pen=clrs[k]) app.exec_() # create terms of weak formulation terms = [ ph.IntegralTerm(ph.Product( ph.FieldVariable("norm_eig_funcs", order=(2, 0)), ph.TestFunction("norm_eig_funcs")), self.dz.bounds, scale=-1), ph.ScalarTerm(ph.Product( ph.FieldVariable("norm_eig_funcs", order=(2, 0), location=0), ph.TestFunction("norm_eig_funcs", location=0)), scale=-1), ph.ScalarTerm( ph.Product(ph.Input(self.u), ph.TestFunction("norm_eig_funcs", location=1))), ph.ScalarTerm(ph.Product( ph.FieldVariable("norm_eig_funcs", location=1), ph.TestFunction("norm_eig_funcs", order=1, location=1)), scale=-1), ph.ScalarTerm( ph.Product( ph.FieldVariable("norm_eig_funcs", location=0), ph.TestFunction("norm_eig_funcs", order=1, location=0))), ph.IntegralTerm( ph.Product(ph.FieldVariable("norm_eig_funcs"), ph.TestFunction("norm_eig_funcs", order=2)), self.dz.bounds) ] modal_pde = sim.WeakFormulation(terms, name="swm_lib-modal") eval_data = sim.simulate_system(modal_pde, self.ic, self.dt, self.dz, der_orders=(2, 0)) # display results if show_plots: win = vis.PgAnimatedPlot(eval_data[0:2], title="modal approx and derivative") win2 = vis.PgSurfacePlot(eval_data[0]) app.exec_() # test for correct transition self.assertTrue( np.isclose(eval_data[0].output_data[-1, 0], self.y_end, atol=1e-3))
def test_modal(self): order = 8 def char_eq(w): return w * (np.sin(w) + self.params.m * w * np.cos(w)) def phi_k_factory(freq, derivative_order=0): def eig_func(z): return np.cos(freq * z) - self.params.m * freq * np.sin(freq * z) def eig_func_dz(z): return -freq * (np.sin(freq * z) + self.params.m * freq * np.cos(freq * z)) def eig_func_ddz(z): return freq ** 2 * (-np.cos(freq * z) + self.params.m * freq * np.sin(freq * z)) if derivative_order == 0: return eig_func elif derivative_order == 1: return eig_func_dz elif derivative_order == 2: return eig_func_ddz else: raise ValueError # create eigenfunctions eig_frequencies = ut.find_roots(char_eq, n_roots=order, grid=np.arange(0, 1e3, 2), rtol=-2) print("eigenfrequencies:") print eig_frequencies # create eigen function vectors class SWMFunctionVector(cr.ComposedFunctionVector): """ String With Mass Function Vector, necessary due to manipulated scalar product """ @property def func(self): return self.members["funcs"][0] @property def scalar(self): return self.members["scalars"][0] eig_vectors = [] for n in range(order): eig_vectors.append(SWMFunctionVector(cr.Function(phi_k_factory(eig_frequencies[n]), derivative_handles=[ phi_k_factory(eig_frequencies[n], der_order) for der_order in range(1, 3)], domain=self.dz.bounds, nonzero=self.dz.bounds), phi_k_factory(eig_frequencies[n])(0))) # normalize eigen vectors norm_eig_vectors = [cr.normalize_function(vec) for vec in eig_vectors] norm_eig_funcs = np.array([vec.func for vec in norm_eig_vectors]) register_base("norm_eig_funcs", norm_eig_funcs, overwrite=True) norm_eig_funcs[0](1) # debug print eigenfunctions if 0: func_vals = [] for vec in eig_vectors: func_vals.append(np.vectorize(vec.func)(self.dz)) norm_func_vals = [] for func in norm_eig_funcs: norm_func_vals.append(np.vectorize(func)(self.dz)) clrs = ["r", "g", "b", "c", "m", "y", "k", "w"] for n in range(1, order + 1, len(clrs)): pw_phin_k = pg.plot(title="phin_k for k in [{0}, {1}]".format(n, min(n + len(clrs), order))) for k in range(len(clrs)): if k + n > order: break pw_phin_k.plot(x=np.array(self.dz), y=norm_func_vals[n + k - 1], pen=clrs[k]) app.exec_() # create terms of weak formulation terms = [ph.IntegralTerm(ph.Product(ph.FieldVariable("norm_eig_funcs", order=(2, 0)), ph.TestFunction("norm_eig_funcs")), self.dz.bounds, scale=-1), ph.ScalarTerm(ph.Product( ph.FieldVariable("norm_eig_funcs", order=(2, 0), location=0), ph.TestFunction("norm_eig_funcs", location=0)), scale=-1), ph.ScalarTerm(ph.Product(ph.Input(self.u), ph.TestFunction("norm_eig_funcs", location=1))), ph.ScalarTerm( ph.Product(ph.FieldVariable("norm_eig_funcs", location=1), ph.TestFunction("norm_eig_funcs", order=1, location=1)), scale=-1), ph.ScalarTerm(ph.Product(ph.FieldVariable("norm_eig_funcs", location=0), ph.TestFunction("norm_eig_funcs", order=1, location=0))), ph.IntegralTerm(ph.Product(ph.FieldVariable("norm_eig_funcs"), ph.TestFunction("norm_eig_funcs", order=2)), self.dz.bounds)] modal_pde = sim.WeakFormulation(terms, name="swm_lib-modal") eval_data = sim.simulate_system(modal_pde, self.ic, self.dt, self.dz, der_orders=(2, 0)) # display results if show_plots: win = vis.PgAnimatedPlot(eval_data[0:2], title="modal approx and derivative") win2 = vis.PgSurfacePlot(eval_data[0]) app.exec_() # test for correct transition self.assertTrue(np.isclose(eval_data[0].output_data[-1, 0], self.y_end, atol=1e-3))
def setUp(self): # scalars self.scalars = ph.Scalars(np.vstack(list(range(3)))) # inputs self.u = np.sin self.input = ph.Input(self.u) self.input_squared = ph.Input(self.u, exponent=2) nodes, self.ini_funcs = sf.cure_interval(sf.LagrangeFirstOrder, (0, 1), node_count=3) # TestFunctions register_base("ini_funcs", self.ini_funcs, overwrite=True) self.phi = ph.TestFunction("ini_funcs") self.phi_at0 = ph.TestFunction("ini_funcs", location=0) self.phi_at1 = ph.TestFunction("ini_funcs", location=1) self.dphi = ph.TestFunction("ini_funcs", order=1) self.dphi_at1 = ph.TestFunction("ini_funcs", order=1, location=1) # FieldVars self.field_var = ph.FieldVariable("ini_funcs") self.field_var_squared = ph.FieldVariable("ini_funcs", exponent=2) self.odd_weight_field_var = ph.FieldVariable( "ini_funcs", weight_label="special_weights") self.field_var_at1 = ph.FieldVariable("ini_funcs", location=1) self.field_var_at1_squared = ph.FieldVariable("ini_funcs", location=1, exponent=2) self.field_var_dz = ph.SpatialDerivedFieldVariable("ini_funcs", 1) self.field_var_dz_at1 = ph.SpatialDerivedFieldVariable("ini_funcs", 1, location=1) self.field_var_ddt = ph.TemporalDerivedFieldVariable("ini_funcs", 2) self.field_var_ddt_at0 = ph.TemporalDerivedFieldVariable("ini_funcs", 2, location=0) self.field_var_ddt_at1 = ph.TemporalDerivedFieldVariable("ini_funcs", 2, location=1) # create all possible kinds of input variables self.input_term1 = ph.ScalarTerm(ph.Product(self.phi_at1, self.input)) self.input_term1_swapped = ph.ScalarTerm( ph.Product(self.input, self.phi_at1)) self.input_term1_squared = ph.ScalarTerm( ph.Product(self.input_squared, self.phi_at1)) self.input_term2 = ph.ScalarTerm(ph.Product(self.dphi_at1, self.input)) self.func_term = ph.ScalarTerm(self.phi_at1) # same goes for field variables self.field_term_at1 = ph.ScalarTerm(self.field_var_at1) self.field_term_at1_squared = ph.ScalarTerm(self.field_var_at1_squared) self.field_term_dz_at1 = ph.ScalarTerm(self.field_var_dz_at1) self.field_term_ddt_at1 = ph.ScalarTerm(self.field_var_ddt_at1) self.field_int = ph.IntegralTerm(self.field_var, (0, 1)) self.field_squared_int = ph.IntegralTerm(self.field_var_squared, (0, 1)) self.field_dz_int = ph.IntegralTerm(self.field_var_dz, (0, 1)) self.field_ddt_int = ph.IntegralTerm(self.field_var_ddt, (0, 1)) self.prod_term_fs_at1 = ph.ScalarTerm( ph.Product(self.field_var_at1, self.scalars)) self.prod_int_fs = ph.IntegralTerm( ph.Product(self.field_var, self.scalars), (0, 1)) self.prod_int_f_f = ph.IntegralTerm( ph.Product(self.field_var, self.phi), (0, 1)) self.prod_int_f_squared_f = ph.IntegralTerm( ph.Product(self.field_var_squared, self.phi), (0, 1)) self.prod_int_f_f_swapped = ph.IntegralTerm( ph.Product(self.phi, self.field_var), (0, 1)) self.prod_int_f_at1_f = ph.IntegralTerm( ph.Product(self.field_var_at1, self.phi), (0, 1)) self.prod_int_f_at1_squared_f = ph.IntegralTerm( ph.Product(self.field_var_at1_squared, self.phi), (0, 1)) self.prod_int_f_f_at1 = ph.IntegralTerm( ph.Product(self.field_var, self.phi_at1), (0, 1)) self.prod_int_f_squared_f_at1 = ph.IntegralTerm( ph.Product(self.field_var_squared, self.phi_at1), (0, 1)) self.prod_term_f_at1_f_at1 = ph.ScalarTerm( ph.Product(self.field_var_at1, self.phi_at1)) self.prod_term_f_at1_squared_f_at1 = ph.ScalarTerm( ph.Product(self.field_var_at1_squared, self.phi_at1)) self.prod_int_fddt_f = ph.IntegralTerm( ph.Product(self.field_var_ddt, self.phi), (0, 1)) self.prod_term_fddt_at0_f_at0 = ph.ScalarTerm( ph.Product(self.field_var_ddt_at0, self.phi_at0)) self.prod_term_f_at1_dphi_at1 = ph.ScalarTerm( ph.Product(self.field_var_at1, self.dphi_at1)) self.temp_int = ph.IntegralTerm( ph.Product(self.field_var_ddt, self.phi), (0, 1)) self.spat_int = ph.IntegralTerm( ph.Product(self.field_var_dz, self.dphi), (0, 1)) self.spat_int_asymmetric = ph.IntegralTerm( ph.Product(self.field_var_dz, self.phi), (0, 1)) self.alternating_weights_term = ph.IntegralTerm( self.odd_weight_field_var, (0, 1))
def setUp(self): nodes, ini_funcs = cure_interval(LagrangeFirstOrder, (0, 1), node_count=2) register_base("test_funcs", ini_funcs, overwrite=True)
def test_it(self): # original system parameters a2 = 1 a1 = 0 # attention: only a2 = 1., a1 =0 supported in this test case a0 = 0 param = [a2, a1, a0, None, None] # target system parameters (controller parameters) a1_t = 0 a0_t = 0 # attention: only a2 = 1., a1 =0 and a0 =0 supported in this test case param_t = [a2, a1_t, a0_t, None, None] # system/simulation parameters actuation_type = 'dirichlet' bound_cond_type = 'dirichlet' 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 # eigenvalues /-functions original system eig_freq = np.array([(i + 1) * np.pi / l for i in range(n)]) eig_values = a0 - a2 * eig_freq**2 - a1**2 / 4. / a2 norm_fac = np.ones(eig_freq.shape) * np.sqrt(2) eig_funcs = np.asarray([ ef.SecondOrderDirichletEigenfunction(eig_freq[i], param, dz.bounds, norm_fac[i]) for i in range(n) ]) register_base("eig_funcs", eig_funcs, overwrite=True) # eigenfunctions target system eig_freq_t = np.sqrt(-eig_values.astype(complex)) norm_fac_t = norm_fac * eig_freq / eig_freq_t eig_funcs_t = np.asarray([ ef.SecondOrderDirichletEigenfunction(eig_freq_t[i], param_t, dz.bounds, norm_fac_t[i]) for i in range(n) ]) 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, l)) initial_weights = cr.project_on_base(start_state, eig_funcs) # init trajectory / input of target system traj = tr.RadTrajectory(l, T, param_t, bound_cond_type, actuation_type) # init controller x_at_1 = ph.FieldVariable("eig_funcs", location=1) xt_at_1 = ph.FieldVariable("eig_funcs_t", weight_label="eig_funcs", location=1) controller = ct.Controller( ct.ControlLaw( [ph.ScalarTerm(x_at_1, 1), ph.ScalarTerm(xt_at_1, -1)])) # input with feedback control_law = sim.SimulationInputSum([traj, controller]) # determine (A,B) with modal-transfomation A = np.diag(eig_values) B = -a2 * np.array([eig_funcs[i].derive()(l) for i in range(n)]) ss = sim.StateSpace("eig_funcs", A, B, input_handle=control_law) # simulate t, q = sim.simulate_state_space(ss, 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), 0.5) # display results if show_plots: eval_d = sim.evaluate_approximation("eig_funcs", q, t, dz) 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_()
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 shape_generator(self, cls, der_order): """ verify the correct connection with visual feedback """ dz = pi.Domain((0, 1), step=.001) dt = pi.Domain((0, 0), num=1) nodes, funcs = pi.cure_interval(cls, dz.bounds, node_count=11) pi.register_base("test", funcs, overwrite=True) # approx_func = pi.Function(np.cos, domain=dz.bounds, # derivative_handles=[lambda z: -np.sin(z), lambda z: -np.cos(z)]) approx_func = pi.Function(lambda z: np.sin(3 * z), domain=dz.bounds, derivative_handles=[ lambda z: 3 * np.cos(3 * z), lambda z: -9 * np.sin(3 * z) ]) weights = approx_func(nodes) hull = pi.evaluate_approximation("test", np.atleast_2d(weights), temp_domain=dt, spat_domain=dz, spat_order=der_order) if show_plots: # plot shapefunctions c_map = pi.visualization.create_colormap(len(funcs)) pw = pg.plot(title="{}-Test".format(cls.__name__)) pw.addLegend() pw.showGrid(x=True, y=True, alpha=0.5) [ pw.addItem( pg.PlotDataItem(np.array(dz), weights[idx] * func.derive(der_order)(dz), pen=pg.mkPen(color=c_map[idx]), name="{}.{}".format(cls.__name__, idx))) for idx, func in enumerate(funcs) ] # plot hull curve pw.addItem( pg.PlotDataItem(np.array(hull.input_data[1]), hull.output_data[0, :], pen=pg.mkPen(width=2), name="hull-curve")) # plot original function pw.addItem( pg.PlotDataItem(np.array(dz), approx_func.derive(der_order)(dz), pen=pg.mkPen(color="m", width=2, style=pg.QtCore.Qt.DashLine), name="original")) pg.QtCore.QCoreApplication.instance().exec_() return np.sum( np.abs(hull.output_data[0, :] - approx_func.derive(der_order)(dz)))
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_()
def test_it(self): # original system parameters a2 = 1 a1 = 0 # attention: only a2 = 1., a1 =0 supported in this test case a0 = 0 param = [a2, a1, a0, None, None] # target system parameters (controller parameters) a1_t = 0 a0_t = 0 # attention: only a2 = 1., a1 =0 and a0 =0 supported in this test case param_t = [a2, a1_t, a0_t, None, None] # system/simulation parameters actuation_type = 'dirichlet' bound_cond_type = 'dirichlet' 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 # eigenvalues /-functions original system eig_freq = np.array([(i + 1) * np.pi / l for i in range(n)]) eig_values = a0 - a2 * eig_freq ** 2 - a1 ** 2 / 4. / a2 norm_fac = np.ones(eig_freq.shape) * np.sqrt(2) eig_funcs = np.asarray([ef.SecondOrderDirichletEigenfunction(eig_freq[i], param, dz.bounds, norm_fac[i]) for i in range(n)]) register_base("eig_funcs", eig_funcs, overwrite=True) # eigenfunctions target system eig_freq_t = np.sqrt(-eig_values.astype(complex)) norm_fac_t = norm_fac * eig_freq / eig_freq_t eig_funcs_t = np.asarray([ef.SecondOrderDirichletEigenfunction(eig_freq_t[i], param_t, dz.bounds, norm_fac_t[i]) for i in range(n)]) 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, l)) initial_weights = cr.project_on_base(start_state, eig_funcs) # init trajectory / input of target system traj = tr.RadTrajectory(l, T, param_t, bound_cond_type, actuation_type) # init controller x_at_1 = ph.FieldVariable("eig_funcs", location=1) xt_at_1 = ph.FieldVariable("eig_funcs_t", weight_label="eig_funcs", location=1) controller = ct.Controller(ct.ControlLaw([ph.ScalarTerm(x_at_1, 1), ph.ScalarTerm(xt_at_1, -1)])) # input with feedback control_law = sim.SimulationInputSum([traj, controller]) # determine (A,B) with modal-transfomation A = np.diag(eig_values) B = -a2 * np.array([eig_funcs[i].derive()(l) for i in range(n)]) ss = sim.StateSpace("eig_funcs", A, B, input_handle=control_law) # simulate t, q = sim.simulate_state_space(ss, 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), 0.5) # display results if show_plots: eval_d = sim.evaluate_approximation("eig_funcs", q, t, dz) win2 = vis.PgSurfacePlot(eval_d) app.exec_()
def test_fem(self): """ use best documented fem case to test all steps in simulation process """ # enter string with mass equations # nodes, ini_funcs = sf.cure_interval(sf.LagrangeFirstOrder, nodes, ini_funcs = sf.cure_interval(sf.LagrangeSecondOrder, self.dz.bounds, node_count=11) register_base("init_funcs", ini_funcs, overwrite=True) int1 = ph.IntegralTerm(ph.Product( ph.TemporalDerivedFieldVariable("init_funcs", 2), ph.TestFunction("init_funcs")), self.dz.bounds, scale=self.params.sigma * self.params.tau**2) s1 = ph.ScalarTerm(ph.Product( ph.TemporalDerivedFieldVariable("init_funcs", 2, location=0), ph.TestFunction("init_funcs", location=0)), scale=self.params.m) int2 = ph.IntegralTerm(ph.Product( ph.SpatialDerivedFieldVariable("init_funcs", 1), ph.TestFunction("init_funcs", order=1)), self.dz.bounds, scale=self.params.sigma) s2 = ph.ScalarTerm( ph.Product(ph.Input(self.u), ph.TestFunction("init_funcs", location=1)), -self.params.sigma) # derive sate-space system string_pde = sim.WeakFormulation([int1, s1, int2, s2], name="fem_test") self.cf = sim.parse_weak_formulation(string_pde) ss = self.cf.convert_to_state_space() # generate initial conditions for weights q0 = np.array([ cr.project_on_base(self.ic[idx], ini_funcs) for idx in range(2) ]).flatten() # simulate t, q = sim.simulate_state_space(ss, q0, self.dt) # calculate result data eval_data = [] for der_idx in range(2): eval_data.append( sim.evaluate_approximation( "init_funcs", q[:, der_idx * ini_funcs.size:(der_idx + 1) * ini_funcs.size], t, self.dz)) eval_data[-1].name = "{0}{1}".format( self.cf.name, "_" + "".join(["d" for x in range(der_idx)]) + "t" if der_idx > 0 else "") # display results if show_plots: win = vis.PgAnimatedPlot(eval_data[:2], title="fem approx and derivative") win2 = vis.PgSurfacePlot(eval_data[0]) app.exec_() # test for correct transition self.assertTrue( np.isclose(eval_data[0].output_data[-1, 0], self.y_end, atol=1e-3)) # save some test data for later use root_dir = os.getcwd() if root_dir.split(os.sep)[-1] == "tests": res_dir = os.sep.join([os.getcwd(), "resources"]) else: res_dir = os.sep.join([os.getcwd(), "tests", "resources"]) if not os.path.isdir(res_dir): os.makedirs(res_dir) file_path = os.sep.join([res_dir, "test_data.res"]) with open(file_path, "w+b") as f: dump(eval_data, f)
def _build_system(self): # initial and test functions nodes = pi.Domain(self.bounds, num=self.approx_cnt) full_fem_base = pi.LagrangeFirstOrder.cure_interval(nodes) act_fem_base = pi.Base(full_fem_base[-1]) not_act_fem_base = pi.Base(full_fem_base[1:-1]) pi.register_base("act_base", act_fem_base) pi.register_base("sim_base", not_act_fem_base) pi.register_base(self.base_lbl, full_fem_base) a2, a1, a0, _, _ = self.params # weak form x = pi.FieldVariable("sim_base") x_dt = x.derive(temp_order=1) x_dz = x.derive(spat_order=1) phi = pi.TestFunction("sim_base") phi_dz = phi.derive(1) act_phi = pi.ScalarFunction("act_base") act_phi_dz = act_phi.derive(1) u = pi.ConstantTrajectory(0) # dummy input weak_form = pi.WeakFormulation( [ # ... of the homogeneous part of the system pi.IntegralTerm(pi.Product(x_dt, phi), limits=self.bounds), pi.IntegralTerm( pi.Product(x_dz, phi_dz), limits=self.bounds, scale=a2), pi.IntegralTerm( pi.Product(x_dz, phi), limits=self.bounds, scale=-a1), pi.IntegralTerm( pi.Product(x, phi), limits=self.bounds, scale=-a0), # ... of the inhomogeneous part of the system pi.IntegralTerm(pi.Product(pi.Product(act_phi, phi), pi.Input(u, order=1)), limits=self.bounds), pi.IntegralTerm(pi.Product(pi.Product(act_phi_dz, phi_dz), pi.Input(u)), limits=self.bounds, scale=a2), pi.IntegralTerm(pi.Product(pi.Product(act_phi_dz, phi), pi.Input(u)), limits=self.bounds, scale=-a1), pi.IntegralTerm(pi.Product(pi.Product(act_phi, phi), pi.Input(u)), limits=self.bounds, scale=-a0) ], name="main_system") # system matrices \dot x = A x + b0 u + b1 \dot u cf = pi.parse_weak_formulation(weak_form) ss = pi.create_state_space(cf) a_mat = ss.A[1] b0 = ss.B[0][1] self.b1 = ss.B[1][1] # Idea: \bar x = \tilde A x + b1 u self.a_tilde = np.diag(np.ones(a_mat.shape[0]), 0) self.a_tilde_inv = np.linalg.inv(self.a_tilde) # Yields: \dot \bar x = \bar A \bar x + \bar b u self.a_bar = (self.a_tilde @ a_mat) @ self.a_tilde_inv self.b_bar = self.a_tilde @ (a_mat @ self.b1) + b0
def test_it(self): param = [2., -1.5, -3., 2., .5] a2, a1, a0, alpha, beta = param l = 1. spatial_disc = 10 dz = sim.Domain(bounds=(0, l), num=spatial_disc) T = 1. temporal_disc = 2e2 dt = sim.Domain(bounds=(0, T), num=temporal_disc) # create test functions nodes_1, ini_funcs_1 = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeFirstOrder, dz.bounds, node_count=spatial_disc) register_base("init_funcs_1", ini_funcs_1, overwrite=True) nodes_2, ini_funcs_2 = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeSecondOrder, dz.bounds, node_count=spatial_disc) register_base("init_funcs_2", ini_funcs_2, overwrite=True) def test_dd(): # trajectory bound_cond_type = 'dirichlet' actuation_type = 'dirichlet' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # derive state-space system rad_pde = ut.get_parabolic_dirichlet_weak_form("init_funcs_2", "init_funcs_2", u, param, dz.bounds) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, cf.input_function, np.zeros(ini_funcs_2.shape), dt) return t, q def test_rd(): # trajectory bound_cond_type = 'robin' actuation_type = 'dirichlet' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # integral terms int1 = ph.IntegralTerm(ph.Product(ph.TemporalDerivedFieldVariable("init_funcs_2", order=1), ph.TestFunction("init_funcs_2", order=0)), dz.bounds) int2 = ph.IntegralTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_2", order=0), ph.TestFunction("init_funcs_2", order=2)), dz.bounds, -a2) int3 = ph.IntegralTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_2", order=1), ph.TestFunction("init_funcs_2", order=0)), dz.bounds, -a1) int4 = ph.IntegralTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_2", order=0), ph.TestFunction("init_funcs_2", order=0)), dz.bounds, -a0) # scalar terms from int 2 s1 = ph.ScalarTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_2", order=1, location=l), ph.TestFunction("init_funcs_2", order=0, location=l)), -a2) s2 = ph.ScalarTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_2", order=0, location=0), ph.TestFunction("init_funcs_2", order=0, location=0)), a2*alpha) s3 = ph.ScalarTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_2", order=0, location=0), ph.TestFunction("init_funcs_2", order=1, location=0)), -a2) s4 = ph.ScalarTerm(ph.Product(ph.Input(u), ph.TestFunction("init_funcs_2", order=1, location=l)), a2) # derive state-space system rad_pde = sim.WeakFormulation([int1, int2, int3, int4, s1, s2, s3, s4]) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, cf.input_function, np.zeros(ini_funcs_2.shape), dt) return t, q def test_dr(): # trajectory bound_cond_type = 'dirichlet' actuation_type = 'robin' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # integral terms int1 = ph.IntegralTerm(ph.Product(ph.TemporalDerivedFieldVariable("init_funcs_1", order=1), ph.TestFunction("init_funcs_1", order=0)), dz.bounds) int2 = ph.IntegralTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_1", order=1), ph.TestFunction("init_funcs_1", order=1)), dz.bounds, a2) int3 = ph.IntegralTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_1", order=0), ph.TestFunction("init_funcs_1", order=1)), dz.bounds, a1) int4 = ph.IntegralTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_1", order=0), ph.TestFunction("init_funcs_1", order=0)), dz.bounds, -a0) # scalar terms from int 2 s1 = ph.ScalarTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_1", order=0, location=l), ph.TestFunction("init_funcs_1", order=0, location=l)), -a1) s2 = ph.ScalarTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_1", order=0, location=l), ph.TestFunction("init_funcs_1", order=0, location=l)), a2*beta) s3 = ph.ScalarTerm(ph.Product(ph.SpatialDerivedFieldVariable("init_funcs_1", order=1, location=0), ph.TestFunction("init_funcs_1", order=0, location=0)), a2) s4 = ph.ScalarTerm(ph.Product(ph.Input(u), ph.TestFunction("init_funcs_1", order=0, location=l)), -a2) # derive state-space system rad_pde = sim.WeakFormulation([int1, int2, int3, int4, s1, s2, s3, s4]) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, cf.input_function, np.zeros(ini_funcs_1.shape), dt) # check if (x'(0,t_end) - 1.) < 0.1 self.assertLess(np.abs(ini_funcs_1[0].derive(1)(sys.float_info.min) * (q[-1, 0] - q[-1, 1])) - 1, 0.1) return t, q def test_rr(): # trajectory bound_cond_type = 'robin' actuation_type = 'robin' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # derive state-space system rad_pde = ut.get_parabolic_robin_weak_form("init_funcs_1", "init_funcs_1", u, param, dz.bounds) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, cf.input_function, np.zeros(ini_funcs_1.shape), dt) # check if (x(0,t_end) - 1.) < 0.1 self.assertLess(np.abs(ini_funcs_1[0].derive(0)(0) * q[-1, 0]) - 1, 0.1) return t, q t, q = test_dr() _, _ = test_rr() # TODO: fit LagrangeSecondOrder to test_dd and test_rd # t, q = test_dd() # t, q = test_rd() # display results if show_plots: eval_d = ut.evaluate_approximation("init_funcs_1", q, t, dz, spat_order=1) win1 = vis.PgAnimatedPlot([eval_d], title="Test") win2 = vis.PgSurfacePlot(eval_d) app.exec_()
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_()
def setUp(self): # scalars self.scalars = ph.Scalars(np.vstack(range(3))) # inputs self.u = np.sin self.input = ph.Input(self.u) # control input # TestFunctions nodes, self.ini_funcs = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeFirstOrder, (0, 1), node_count=3) register_base("ini_funcs", self.ini_funcs, overwrite=True) self.phi = ph.TestFunction("ini_funcs") # eigenfunction or something else self.phi_at0 = ph.TestFunction("ini_funcs", location=0) # eigenfunction or something else self.phi_at1 = ph.TestFunction("ini_funcs", location=1) # eigenfunction or something else self.dphi = ph.TestFunction("ini_funcs", order=1) # eigenfunction or something else self.dphi_at1 = ph.TestFunction("ini_funcs", order=1, location=1) # eigenfunction or something else # FieldVars self.field_var = ph.FieldVariable("ini_funcs") self.odd_weight_field_var = ph.FieldVariable("ini_funcs", weight_label="special_weights") self.field_var_at1 = ph.FieldVariable("ini_funcs", location=1) self.field_var_dz = ph.SpatialDerivedFieldVariable("ini_funcs", 1) self.field_var_dz_at1 = ph.SpatialDerivedFieldVariable("ini_funcs", 1, location=1) self.field_var_ddt = ph.TemporalDerivedFieldVariable("ini_funcs", 2) self.field_var_ddt_at0 = ph.TemporalDerivedFieldVariable("ini_funcs", 2, location=0) self.field_var_ddt_at1 = ph.TemporalDerivedFieldVariable("ini_funcs", 2, location=1) # create all possible kinds of input variables self.input_term1 = ph.ScalarTerm(ph.Product(self.phi_at1, self.input)) self.input_term1_swapped = ph.ScalarTerm(ph.Product(self.input, self.phi_at1)) self.input_term2 = ph.ScalarTerm(ph.Product(self.dphi_at1, self.input)) self.func_term = ph.ScalarTerm(self.phi_at1) self.field_term_at1 = ph.ScalarTerm(self.field_var_at1) self.field_term_dz_at1 = ph.ScalarTerm(self.field_var_dz_at1) self.field_term_ddt_at1 = ph.ScalarTerm(self.field_var_ddt_at1) self.field_int = ph.IntegralTerm(self.field_var, (0, 1)) self.field_dz_int = ph.IntegralTerm(self.field_var_dz, (0, 1)) self.field_ddt_int = ph.IntegralTerm(self.field_var_ddt, (0, 1)) self.prod_term_fs_at1 = ph.ScalarTerm( ph.Product(self.field_var_at1, self.scalars)) self.prod_int_fs = ph.IntegralTerm(ph.Product(self.field_var, self.scalars), (0, 1)) self.prod_int_f_f = ph.IntegralTerm(ph.Product(self.field_var, self.phi), (0, 1)) self.prod_int_f_f_swapped = ph.IntegralTerm(ph.Product(self.phi, self.field_var), (0, 1)) self.prod_int_f_at1_f = ph.IntegralTerm( ph.Product(self.field_var_at1, self.phi), (0, 1)) self.prod_int_f_f_at1 = ph.IntegralTerm( ph.Product(self.field_var, self.phi_at1), (0, 1)) self.prod_term_f_at1_f_at1 = ph.ScalarTerm( ph.Product(self.field_var_at1, self.phi_at1)) self.prod_int_fddt_f = ph.IntegralTerm( ph.Product(self.field_var_ddt, self.phi), (0, 1)) self.prod_term_fddt_at0_f_at0 = ph.ScalarTerm( ph.Product(self.field_var_ddt_at0, self.phi_at0)) self.prod_term_f_at1_dphi_at1 = ph.ScalarTerm( ph.Product(self.field_var_at1, self.dphi_at1)) self.temp_int = ph.IntegralTerm(ph.Product(self.field_var_ddt, self.phi), (0, 1)) self.spat_int = ph.IntegralTerm(ph.Product(self.field_var_dz, self.dphi), (0, 1)) self.spat_int_asymmetric = ph.IntegralTerm( ph.Product(self.field_var_dz, self.phi), (0, 1)) self.alternating_weights_term = ph.IntegralTerm(self.odd_weight_field_var, (0, 1))
def test_it(self): param = [2., -1.5, -3., 2., .5] a2, a1, a0, alpha, beta = param l = 1. spatial_disc = 11 dz = sim.Domain(bounds=(0, l), num=spatial_disc) T = 1. temporal_disc = 2e2 dt = sim.Domain(bounds=(0, T), num=temporal_disc) # create test functions nodes_1, ini_funcs_1 = sf.cure_interval(sf.LagrangeFirstOrder, dz.bounds, node_count=spatial_disc) register_base("init_funcs_1", ini_funcs_1, overwrite=True) nodes_2, ini_funcs_2 = sf.cure_interval(sf.LagrangeSecondOrder, dz.bounds, node_count=spatial_disc) register_base("init_funcs_2", ini_funcs_2, overwrite=True) def test_dd(): # trajectory bound_cond_type = 'dirichlet' actuation_type = 'dirichlet' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # derive state-space system rad_pde = ut.get_parabolic_dirichlet_weak_form( "init_funcs_2", "init_funcs_2", u, param, dz.bounds) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, np.zeros(ini_funcs_2.shape), dt) return t, q def test_rd(): # trajectory bound_cond_type = 'robin' actuation_type = 'dirichlet' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # integral terms int1 = ph.IntegralTerm( ph.Product( ph.TemporalDerivedFieldVariable("init_funcs_2", order=1), ph.TestFunction("init_funcs_2", order=0)), dz.bounds) int2 = ph.IntegralTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_2", order=0), ph.TestFunction("init_funcs_2", order=2)), dz.bounds, -a2) int3 = ph.IntegralTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_2", order=1), ph.TestFunction("init_funcs_2", order=0)), dz.bounds, -a1) int4 = ph.IntegralTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_2", order=0), ph.TestFunction("init_funcs_2", order=0)), dz.bounds, -a0) # scalar terms from int 2 s1 = ph.ScalarTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_2", order=1, location=l), ph.TestFunction("init_funcs_2", order=0, location=l)), -a2) s2 = ph.ScalarTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_2", order=0, location=0), ph.TestFunction("init_funcs_2", order=0, location=0)), a2 * alpha) s3 = ph.ScalarTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_2", order=0, location=0), ph.TestFunction("init_funcs_2", order=1, location=0)), -a2) s4 = ph.ScalarTerm( ph.Product( ph.Input(u), ph.TestFunction("init_funcs_2", order=1, location=l)), a2) # derive state-space system rad_pde = sim.WeakFormulation( [int1, int2, int3, int4, s1, s2, s3, s4]) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, np.zeros(ini_funcs_2.shape), dt) return t, q def test_dr(): # trajectory bound_cond_type = 'dirichlet' actuation_type = 'robin' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # integral terms int1 = ph.IntegralTerm( ph.Product( ph.TemporalDerivedFieldVariable("init_funcs_1", order=1), ph.TestFunction("init_funcs_1", order=0)), dz.bounds) int2 = ph.IntegralTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_1", order=1), ph.TestFunction("init_funcs_1", order=1)), dz.bounds, a2) int3 = ph.IntegralTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_1", order=0), ph.TestFunction("init_funcs_1", order=1)), dz.bounds, a1) int4 = ph.IntegralTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_1", order=0), ph.TestFunction("init_funcs_1", order=0)), dz.bounds, -a0) # scalar terms from int 2 s1 = ph.ScalarTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_1", order=0, location=l), ph.TestFunction("init_funcs_1", order=0, location=l)), -a1) s2 = ph.ScalarTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_1", order=0, location=l), ph.TestFunction("init_funcs_1", order=0, location=l)), a2 * beta) s3 = ph.ScalarTerm( ph.Product( ph.SpatialDerivedFieldVariable("init_funcs_1", order=1, location=0), ph.TestFunction("init_funcs_1", order=0, location=0)), a2) s4 = ph.ScalarTerm( ph.Product( ph.Input(u), ph.TestFunction("init_funcs_1", order=0, location=l)), -a2) # derive state-space system rad_pde = sim.WeakFormulation( [int1, int2, int3, int4, s1, s2, s3, s4]) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, np.zeros(ini_funcs_1.shape), dt) # check if (x'(0,t_end) - 1.) < 0.1 self.assertLess( np.abs(ini_funcs_1[0].derive(1)(sys.float_info.min) * (q[-1, 0] - q[-1, 1])) - 1, 0.1) return t, q def test_rr(): # trajectory bound_cond_type = 'robin' actuation_type = 'robin' u = tr.RadTrajectory(l, T, param, bound_cond_type, actuation_type) # derive state-space system rad_pde = ut.get_parabolic_robin_weak_form("init_funcs_1", "init_funcs_1", u, param, dz.bounds) cf = sim.parse_weak_formulation(rad_pde) ss = cf.convert_to_state_space() # simulate system t, q = sim.simulate_state_space(ss, np.zeros(ini_funcs_1.shape), dt) # check if (x(0,t_end) - 1.) < 0.1 self.assertLess( np.abs(ini_funcs_1[0].derive(0)(0) * q[-1, 0]) - 1, 0.1) return t, q t, q = test_dr() _, _ = test_rr() # TODO: fit LagrangeSecondOrder to test_dd and test_rd # t, q = test_dd() # t, q = test_rd() # display results if show_plots: eval_d = sim.evaluate_approximation("init_funcs_1", q, t, dz, spat_order=1) win1 = vis.PgAnimatedPlot([eval_d], title="Test") win2 = vis.PgSurfacePlot(eval_d) app.exec_()
adjoint_eig_funcs_t = np.array([f_tuple[1] for f_tuple in adjoint_and_eig_funcs_t]) # transformed original eigenfunctions eig_funcs = np.array([ef.TransformedSecondOrderEigenfunction(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, l, 1e4)) for i in range(n)]) # create testfunctions nodes, fem_funcs = sh.cure_interval(sh.LagrangeFirstOrder, spatial_domain.bounds, node_count=len(spatial_domain)) # register functions register_base("eig_funcs_t", eig_funcs_t, overwrite=True) register_base("adjoint_eig_funcs_t", adjoint_eig_funcs_t, overwrite=True) register_base("eig_funcs", eig_funcs, overwrite=True) register_base("fem_funcs", fem_funcs, overwrite=True) # init trajectory traj = tr.RadTrajectory(l, T, param_ti, bound_cond_type, actuation_type) # original () and target (_t) field variable fem_field_variable = ph.FieldVariable("fem_funcs", location=l) field_variable_t = ph.FieldVariable("eig_funcs_t", weight_label="eig_funcs", location=l) d_field_variable_t = ph.SpatialDerivedFieldVariable("eig_funcs_t", 1, weight_label="eig_funcs", location=l) field_variable = ph.FieldVariable("eig_funcs", location=l) d_field_variable = ph.SpatialDerivedFieldVariable("eig_funcs", 1, location=l) # intermediate (_i) and target intermediate (_ti) transformations by z=l
def setUp(self): nodes, ini_funcs = pyinduct.shapefunctions.cure_interval(pyinduct.shapefunctions.LagrangeFirstOrder, (0, 1), node_count=2) register_base("test_funcs", ini_funcs, overwrite=True)
[f_tuple[1] for f_tuple in adjoint_and_eig_funcs_t]) # transformed original eigenfunctions eig_funcs = np.array([ ef.TransformedSecondOrderEigenfunction( 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, l, 1e4)) for i in range(n) ]) # create testfunctions nodes, fem_funcs = sh.cure_interval(sh.LagrangeFirstOrder, spatial_domain.bounds, node_count=len(spatial_domain)) # register functions register_base("eig_funcs_t", eig_funcs_t, overwrite=True) register_base("adjoint_eig_funcs_t", adjoint_eig_funcs_t, overwrite=True) register_base("eig_funcs", eig_funcs, overwrite=True) register_base("fem_funcs", fem_funcs, overwrite=True) # init trajectory traj = tr.RadTrajectory(l, T, param_ti, bound_cond_type, actuation_type) # original () and target (_t) field variable fem_field_variable = ph.FieldVariable("fem_funcs", location=l) field_variable_t = ph.FieldVariable("eig_funcs_t", weight_label="eig_funcs", location=l) d_field_variable_t = ph.SpatialDerivedFieldVariable("eig_funcs_t", 1, weight_label="eig_funcs",
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_()