示例#1
0
文件: control.py 项目: rihe/pyinduct
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
示例#2
0
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