def _parse_control_law(law): """ parses the given control law by approximating given terms :param law: list of equation terms :return: evaluation handle """ # check terms for term in law.terms: if not isinstance(term, EquationTerm): raise TypeError("only EquationTerm(s) accepted.") cfs = sim.CanonicalForms(law.name) for term in law.terms: placeholders = dict( [ ("field_variables", term.arg.get_arg_by_class(FieldVariable)), ("scalars", term.arg.get_arg_by_class(Scalars)), ] ) if placeholders["field_variables"]: field_var = placeholders["field_variables"][0] temp_order = field_var.order[0] func_lbl = field_var.data["func_lbl"] weight_lbl = field_var.data["weight_lbl"] init_funcs = get_base(func_lbl, field_var.order[1]) factors = np.atleast_2d( [integrate_function(func, domain_intersection(term.limits, func.nonzero))[0] for func in init_funcs] ) if placeholders["scalars"]: scales = placeholders["scalars"][0] res = np.prod(np.array([factors, scales]), axis=0) else: res = factors cfs.add_to(weight_lbl, ("E", temp_order), res * term.scale) elif placeholders["scalars"]: # TODO make sure that all have the same target form! scalars = placeholders["scalars"] if len(scalars) > 1: # TODO if one of 'em is just a scalar and no array an error occurs res = np.prod(np.array([scalars[0].data, scalars[1].data]), axis=0) else: res = scalars[0].data cfs.add_to(scalars[0].target_form, get_scalar_target(scalars), res * term.scale) else: raise NotImplementedError return cfs
def parse_weak_formulation(weak_form): """ creates an ode system for the weights x_i based on the weak formulation. :return: simulation.ODESystem """ if not isinstance(weak_form, WeakFormulation): raise TypeError("only able to parse WeakFormulation") cf = CanonicalForm(weak_form.name) # handle each term for term in weak_form.terms: # extract Placeholders placeholders = dict(scalars=term.arg.get_arg_by_class(Scalars), functions=term.arg.get_arg_by_class(TestFunction), field_variables=term.arg.get_arg_by_class(FieldVariable), inputs=term.arg.get_arg_by_class(Input)) # field variable terms, sort into E_n, E_n-1, ..., E_0 if placeholders["field_variables"]: if len(placeholders["field_variables"]) != 1: raise NotImplementedError field_var = placeholders["field_variables"][0] temp_order = field_var.order[0] init_funcs = get_base(field_var.data["func_lbl"], field_var.order[1]) if placeholders["inputs"]: # TODO think about this case, is it relevant? raise NotImplementedError # is the integrand a product? if placeholders["functions"]: if len(placeholders["functions"]) != 1: raise NotImplementedError func = placeholders["functions"][0] test_funcs = get_base(func.data["func_lbl"], func.order[1]) result = calculate_scalar_product_matrix(dot_product_l2, test_funcs, init_funcs) else: # pull constant term out and compute integral a = Scalars(np.atleast_2d([integrate_function(func, func.nonzero)[0] for func in init_funcs])) if placeholders["scalars"]: b = placeholders["scalars"][0] else: b = Scalars(np.ones_like(a.data.T)) result = _compute_product_of_scalars([a, b]) cf.weights = field_var.data["weight_lbl"] cf.add_to(("E", temp_order), result*term.scale) continue # TestFunction Terms, those will end up in f if placeholders["functions"]: if not 1 <= len(placeholders["functions"]) <= 2: raise NotImplementedError func = placeholders["functions"][0] test_funcs = get_base(func.data["func_lbl"], func.order[1]) if len(placeholders["functions"]) == 2: # TODO this computation is nonesense. Result must be a vektor conataining int of (tf1*tf2) raise NotImplementedError func2 = placeholders["functions"][1] test_funcs2 = get_base(func2.data["func_lbl"], func2.order[2]) result = calculate_scalar_product_matrix(dot_product_l2, test_funcs, test_funcs2) cf.add_to(("f", 0), result*term.scale) continue if placeholders["scalars"]: a = placeholders["scalars"][0] b = Scalars(np.vstack([integrate_function(func, func.nonzero)[0] for func in test_funcs])) result = _compute_product_of_scalars([a, b]) cf.add_to(get_scalar_target(placeholders["scalars"]), result*term.scale) continue if placeholders["inputs"]: if len(placeholders["inputs"]) != 1: raise NotImplementedError input_var = placeholders["inputs"][0] input_func = input_var.data input_order = input_var.order result = np.array([integrate_function(func, func.nonzero)[0] for func in init_funcs]) cf.add_to(("g", 0), result*term.scale) cf.input_function = input_func continue # pure scalar terms, sort into corresponding matrices if placeholders["scalars"]: result = _compute_product_of_scalars(placeholders["scalars"]) target = get_scalar_target(placeholders["scalars"]) if placeholders["inputs"]: input_var = placeholders["inputs"][0] input_func = input_var.data input_order = input_var.order[0] # this would mean that the input term should appear in a matrix like E1 or E2 if target[0] == "E": raise NotImplementedError cf.add_to(("g", 0), result*term.scale) # TODO think of a more modular concept for input handling cf.input_function = input_func continue cf.add_to(target, result*term.scale) continue return cf