Esempio n. 1
0
def get_initial_constraints(options, initial_variables, ref_variables, model, xi_dict):

    cstr_list = ocp_constraint.OcpConstraintList()

    # list all initial equalities ==> put SX expressions in dict
    if 'e' in list(model.variables_dict['xd'].keys()):
        init_energy_eq = make_initial_energy_equality(initial_variables, ref_variables)
        init_energy_cstr = cstr_op.Constraint(expr=init_energy_eq,
                                    name='initial_energy',
                                    cstr_type='eq')
        cstr_list.append(init_energy_cstr)

    _, initial_conditions, param_initial_conditions, _, _, _ = get_operation_conditions(options)

    if param_initial_conditions:
        init_param_eq = make_param_initial_conditions(initial_variables, ref_variables, xi_dict, model, options)
        init_param_cstr = cstr_op.Constraint(expr=init_param_eq,
                                    name='param_initial_conditions',
                                    cstr_type='eq')
        cstr_list.append(init_param_cstr)

    if initial_conditions:
        init_eq = make_initial_conditions(initial_variables, ref_variables, xi_dict, model, options)
        init_cstr = cstr_op.Constraint(expr=init_eq,
                                    name='initial_conditions',
                                    cstr_type='eq')
        cstr_list.append(init_cstr)

    return cstr_list
Esempio n. 2
0
def generate_rotational_dynamics(variables, f_nodes, parameters, outputs,
                                 architecture):
    kite_nodes = architecture.kite_nodes
    parent_map = architecture.parent_map

    j_inertia = parameters['theta0', 'geometry', 'j']

    xd = variables['SI']['xd']
    xddot = variables['SI']['xddot']

    cstr_list = mdl_constraint.MdlConstraintList()

    for kite in kite_nodes:
        parent = parent_map[kite]
        moment = f_nodes['m' + str(kite) + str(parent)]

        rlocal = cas.reshape(xd['r' + str(kite) + str(parent)], (3, 3))
        drlocal = cas.reshape(xddot['dr' + str(kite) + str(parent)], (3, 3))

        omega = xd['omega' + str(kite) + str(parent)]
        omega_skew = vect_op.skew(omega)
        domega = xddot['domega' + str(kite) + str(parent)]

        tether_moment = outputs['tether_moments']['n{}{}'.format(kite, parent)]

        # moment = J dot(omega) + omega x (J omega) + [tether moment which is zero if holonomic constraints do not depend on omega]
        J_dot_omega = cas.mtimes(j_inertia, domega)
        omega_cross_J_omega = vect_op.cross(omega,
                                            cas.mtimes(j_inertia, omega))
        omega_derivative = moment - (J_dot_omega + omega_cross_J_omega +
                                     tether_moment)
        rotational_2nd_law = omega_derivative / vect_op.norm(
            cas.diag(j_inertia))

        rotation_dynamics_cstr = cstr_op.Constraint(expr=rotational_2nd_law,
                                                    name='rotation_dynamics' +
                                                    str(kite),
                                                    cstr_type='eq')
        cstr_list.append(rotation_dynamics_cstr)

        # Rdot = R omega_skew -> R ( kappa/2 (I - R.T R) + omega_skew )
        baumgarte = parameters['theta0', 'kappa_r']
        orthonormality = baumgarte / 2. * (cas.DM_eye(3) -
                                           cas.mtimes(rlocal.T, rlocal))
        ref_frame_deriv_matrix = drlocal - (cas.mtimes(
            rlocal, orthonormality + omega_skew))
        ref_frame_derivative = cas.reshape(ref_frame_deriv_matrix, (9, 1))

        ortho_cstr = cstr_op.Constraint(expr=ref_frame_derivative,
                                        name='ref_frame_deriv' + str(kite),
                                        cstr_type='eq')
        cstr_list.append(ortho_cstr)

    return cstr_list, outputs
Esempio n. 3
0
def get_force_cstr(options, variables, atmos, wind, architecture, parameters):

    cstr_list = mdl_constraint.MdlConstraintList()

    for kite in architecture.kite_nodes:
        parent = architecture.parent_map[kite]

        kite_dcm = get_kite_dcm(options, variables, wind, kite, architecture)

        vec_u = tools.get_local_air_velocity_in_earth_frame(options, variables, atmos, wind, kite, kite_dcm,
                                                             architecture, parameters)

        force_found_frame = 'earth'
        force_found_vector = get_force_from_u_sym_in_earth_frame(vec_u, options, variables, kite, atmos, wind, architecture, parameters)

        forces_dict = tools.get_framed_forces(vec_u, kite_dcm, variables, kite, architecture)
        force_framed_variable = forces_dict[force_found_frame]

        f_scale = tools.get_f_scale(parameters, options)

        resi_f_kite = (force_framed_variable - force_found_vector) / f_scale

        f_kite_cstr = cstr_op.Constraint(expr=resi_f_kite,
                                        name='f_aero' + str(kite) + str(parent),
                                        cstr_type='eq')
        cstr_list.append(f_kite_cstr)

    return cstr_list
Esempio n. 4
0
def get_terminal_constraints(options, terminal_variables, ref_variables, model, xi_dict):

    cstr_list = ocp_constraint.OcpConstraintList()

    _, _, _, param_terminal_conditions, terminal_inequalities, integral_constraints = get_operation_conditions(options)

    if param_terminal_conditions:
        terminal_param_eq = make_param_terminal_conditions(terminal_variables, ref_variables, xi_dict, model, options)
        terminal_param_cstr = cstr_op.Constraint(expr=terminal_param_eq,
                                    name='param_terminal_conditions',
                                    cstr_type='eq')
        cstr_list.append(terminal_param_cstr)

    if terminal_inequalities:
        terminal_ineq = make_terminal_position_inequality(terminal_variables, model, options)
        terminal_ineq_cstr = cstr_op.Constraint(expr=terminal_ineq,
                                    name='terminal_inequalities',
                                    cstr_type='ineq')
        cstr_list.append(terminal_ineq_cstr)

    return cstr_list
Esempio n. 5
0
def get_periodic_constraints(options, initial_model_variables, terminal_model_variables):
    cstr_list = ocp_constraint.OcpConstraintList()

    periodic, _, _, _, _, _ = get_operation_conditions(options)

    # list all periodic equalities ==> put SX expressions in dict
    if periodic:
        periodic_eq = make_periodicity_equality(initial_model_variables, terminal_model_variables, options)
        cstr = cstr_op.Constraint(expr=periodic_eq,
                                  name='state_periodicity',
                                  cstr_type='eq')
        cstr_list.append(cstr)

    return cstr_list
Esempio n. 6
0
    def get_continuity_constraint(self, ms_xf, V, kdx):
        """Append multiple shooting continuity constraint to list of constraints

        @param g_list current list of constraints
        @param g_bounds corresponding list of constraint bounds
        @param ms_xf integrator output
        @param V nlp decision variables
        @param kdx interval index
        """

        # add continuity equation to nlp
        g_continuity = V['xd', kdx + 1] - ms_xf[:, kdx]

        cont_cstr = cstr_op.Constraint(expr=g_continuity,
                                       name='ms_continuity_' + str(kdx),
                                       cstr_type='eq')
        return cont_cstr
Esempio n. 7
0
    def get_continuity_constraint(self, V, kdx):

        # get an expression for the state at the end of the finite element
        xf_k = 0
        for ddx in range(self.__d + 1):
            if ddx == 0:
                xf_k += self.__coeff_continuity[ddx] * V['xd', kdx]
            else:
                xf_k += self.__coeff_continuity[ddx] * V['coll_var', kdx,
                                                         ddx - 1, 'xd']

        # pin the end of the control interval to the start of the new control interval
        g_continuity = V['xd', kdx + 1] - xf_k

        cstr = cstr_op.Constraint(expr=g_continuity,
                                  name='continuity' + str(kdx),
                                  cstr_type='eq')

        return cstr
Esempio n. 8
0
def p_el_sign(options, variables_si, outputs, parameters, architecture):

    n_k = options['aero']['vortex']['n_k']
    d = options['aero']['vortex']['d']
    sign = variables_si['u']['sign']
    vortex_wake_nodes = options['induction']['vortex_wake_nodes']

    cstr_list = cstr_op.ConstraintList()

    rings = vortex_wake_nodes - 1

    for ring in range(rings):
        wake_node = ring
        for ndx in range(n_k):
            for ddx in range(d):

                local_name = 'p_el_sign_' + str(ring) + '_' + str(
                    ndx) + '_' + str(ddx)
                ndx_shed = n_k - 1 - wake_node
                ddx_shed = d - 1

                already_shed = False
                if (ndx > ndx_shed):
                    already_shed = True
                elif ((ndx == ndx_shed) and (ddx == ddx_shed)):
                    already_shed = True

                if already_shed:
                    sign_eq = sign - 1.
                else:
                    sign_eq = sign + 1

                print(sign_eq)

                sign_eq = cstr_op.Constraint(expr=sign_eq,
                                             name=local_name,
                                             cstr_type='eq')
                cstr_list.append(sign_eq)

    return cstr_list
Esempio n. 9
0
def get_dynamics(options, atmos, wind, architecture, system_variables,
                 system_gc, parameters, outputs):

    parent_map = architecture.parent_map
    number_of_nodes = architecture.number_of_nodes

    # generalized coordinates, velocities and accelerations
    generalized_coordinates = {}
    generalized_coordinates['scaled'] = generate_generalized_coordinates(
        system_variables['scaled'], system_gc)
    generalized_coordinates['SI'] = generate_generalized_coordinates(
        system_variables['SI'], system_gc)

    # -------------------------------
    # mass distribution in the system
    # -------------------------------
    node_masses_si, outputs = mass_comp.generate_m_nodes(
        options, system_variables['SI'], outputs, parameters, architecture)

    # --------------------------------
    # lagrangian
    # --------------------------------

    outputs = energy_comp.energy_outputs(options, parameters, outputs,
                                         node_masses_si,
                                         system_variables['SI'], architecture)
    e_kinetic = sum(outputs['e_kinetic'][nodes]
                    for nodes in list(outputs['e_kinetic'].keys()))
    e_potential = sum(outputs['e_potential'][nodes]
                      for nodes in list(outputs['e_potential'].keys()))

    holonomic_constraints, outputs, g, gdot, gddot = holonomic_comp.generate_holonomic_constraints(
        architecture, outputs, system_variables, parameters, options)

    # lagrangian function
    lag = e_kinetic - e_potential - holonomic_constraints

    # --------------------------------
    # generalized forces in the system
    # --------------------------------

    f_nodes, outputs = forces_comp.generate_f_nodes(options, atmos, wind,
                                                    system_variables['SI'],
                                                    parameters, outputs,
                                                    architecture)
    outputs = forces_comp.generate_tether_moments(options,
                                                  system_variables['SI'],
                                                  system_variables['scaled'],
                                                  holonomic_constraints,
                                                  outputs, architecture)

    cstr_list = mdl_constraint.MdlConstraintList()

    # --------------------------------
    # translational dynamics
    # --------------------------------

    # lhs of lagrange equations
    dlagr_dqdot = cas.jacobian(
        lag, generalized_coordinates['scaled']['xgcdot'].cat).T
    dlagr_dqdot_dt = tools.time_derivative(dlagr_dqdot, system_variables,
                                           architecture)

    dlagr_dq = cas.jacobian(lag,
                            generalized_coordinates['scaled']['xgc'].cat).T

    lagrangian_lhs_translation = dlagr_dqdot_dt - dlagr_dq

    lagrangian_lhs_constraints = holonomic_comp.get_constraint_lhs(
        g, gdot, gddot, parameters)

    # lagrangian momentum correction
    if options['tether']['use_wound_tether']:
        lagrangian_momentum_correction = 0.
    else:
        lagrangian_momentum_correction = momentum_correction(
            options, generalized_coordinates, system_variables, node_masses_si,
            outputs, architecture)

    # rhs of lagrange equations
    lagrangian_rhs_translation = cas.vertcat(
        *[f_nodes['f' + str(n) + str(parent_map[n])] for n in range(1, number_of_nodes)]) + \
                                 lagrangian_momentum_correction
    lagrangian_rhs_constraints = np.zeros(g.shape)

    # scaling
    holonomic_scaling = holonomic_comp.generate_holonomic_scaling(
        options, architecture, system_variables['SI'], parameters)
    node_masses_scaling = mass_comp.generate_m_nodes_scaling(
        options, system_variables['SI'], outputs, parameters, architecture)
    forces_scaling = node_masses_scaling * options['scaling']['other'][
        'g'] * options['model_bounds']['acceleration']['acc_max']

    dynamics_translation = (lagrangian_lhs_translation -
                            lagrangian_rhs_translation) / forces_scaling
    dynamics_translation_cstr = cstr_op.Constraint(expr=dynamics_translation,
                                                   cstr_type='eq',
                                                   name='dynamics_translation')
    cstr_list.append(dynamics_translation_cstr)

    dynamics_constraints = (lagrangian_lhs_constraints -
                            lagrangian_rhs_constraints) / holonomic_scaling
    dynamics_constraint_cstr = cstr_op.Constraint(expr=dynamics_constraints,
                                                  cstr_type='eq',
                                                  name='dynamics_constraint')
    cstr_list.append(dynamics_constraint_cstr)

    # --------------------------------
    # rotational dynamics
    # --------------------------------

    kite_has_6dof = (int(options['kite_dof']) == 6)
    if kite_has_6dof:
        rotation_dynamics_cstr, outputs = generate_rotational_dynamics(
            system_variables, f_nodes, parameters, outputs, architecture)
        cstr_list.append(rotation_dynamics_cstr)

    # --------------------------------
    # trivial kinematics
    # --------------------------------

    for name in system_variables['SI']['xddot'].keys():

        name_in_xd = name in system_variables['SI']['xd'].keys()
        name_in_u = name in system_variables['SI']['u'].keys()

        if name_in_xd:
            trivial_dyn = cas.vertcat(*[
                system_variables['scaled']['xddot', name] -
                system_variables['scaled']['xd', name]
            ])
        elif name_in_u:
            trivial_dyn = cas.vertcat(*[
                system_variables['scaled']['xddot', name] -
                system_variables['scaled']['u', name]
            ])

        if name_in_xd or name_in_u:
            trivial_dyn_cstr = cstr_op.Constraint(expr=trivial_dyn,
                                                  cstr_type='eq',
                                                  name='trivial_' + name)
            cstr_list.append(trivial_dyn_cstr)

    return cstr_list, outputs
Esempio n. 10
0
def get_tether_cstr(options, variables_si, architecture, parameters, outputs):

    # homotopy parameters
    p_dec = parameters.prefix['phi']

    # initialize dictionary
    tether_drag_forces = {}
    for node in range(1, architecture.number_of_nodes):
        parent = architecture.parent_map[node]
        tether_drag_forces['f' + str(node) + str(parent)] = cas.SX.zeros(
            (3, 1))

    for node in range(1, architecture.number_of_nodes):
        parent = architecture.parent_map[node]

        multi_upper = outputs['tether_aero']['multi_upper' + str(node)]
        multi_lower = outputs['tether_aero']['multi_lower' + str(node)]
        single_upper = outputs['tether_aero']['single_upper' + str(node)]
        single_lower = outputs['tether_aero']['single_lower' + str(node)]
        split_upper = outputs['tether_aero']['split_upper' + str(node)]
        split_lower = outputs['tether_aero']['split_lower' + str(node)]
        kite_only_upper = outputs['tether_aero']['kite_only_upper' + str(node)]
        kite_only_lower = outputs['tether_aero']['kite_only_lower' + str(node)]

        tether_model = options['tether']['tether_drag']['model_type']

        if tether_model == 'multi':
            drag_node = p_dec['tau'] * split_upper + (
                1. - p_dec['tau']) * multi_upper
            drag_parent = p_dec['tau'] * split_lower + (
                1. - p_dec['tau']) * multi_lower

        elif tether_model == 'single':
            drag_node = p_dec['tau'] * split_upper + (
                1. - p_dec['tau']) * single_upper
            drag_parent = p_dec['tau'] * split_lower + (
                1. - p_dec['tau']) * single_lower

        elif tether_model == 'split':
            drag_node = split_upper
            drag_parent = split_lower

        elif tether_model == 'kite_only':
            drag_node = kite_only_upper
            drag_parent = kite_only_lower

        elif tether_model == 'not_in_use':
            drag_parent = cas.DM.zeros((3, 1))
            drag_node = cas.DM.zeros((3, 1))

        else:
            raise ValueError('tether drag model not supported.')

        # attribute portion of segment drag to parent
        if node > 1:
            grandparent = architecture.parent_map[parent]
            tether_drag_forces['f' + str(parent) +
                               str(grandparent)] += drag_parent

        # attribute portion of segment drag to node
        tether_drag_forces['f' + str(node) + str(parent)] += drag_node

    cstr_list = mdl_constraint.MdlConstraintList()
    for node in range(1, architecture.number_of_nodes):

        parent = architecture.parent_map[node]
        f_tether_var = get_force_var(variables_si, node, architecture)
        f_tether_val = tether_drag_forces['f' + str(node) + str(parent)]
        local_resi_unscaled = (f_tether_var - f_tether_val)

        scale = options['scaling']['xl']['f_tether']
        local_resi = local_resi_unscaled / scale

        f_cstr = cstr_op.Constraint(expr=local_resi,
                                    name='f_tether' + str(node) + str(parent),
                                    cstr_type='eq')
        cstr_list.append(f_cstr)

    return cstr_list
Esempio n. 11
0
def get_strength_constraint(options, V, Outputs, model):

    n_k = options['n_k']
    d = options['collocation']['d']

    comparison_labels = options['induction']['comparison_labels']
    wake_nodes = options['induction']['vortex_wake_nodes']
    rings = wake_nodes - 1
    kite_nodes = model.architecture.kite_nodes

    strength_scale = tools.get_strength_scale(options)

    Xdot = struct_op.construct_Xdot_struct(options, model.variables_dict)(0.)

    cstr_list = cstr_op.ConstraintList()

    any_vor = any(label[:3] == 'vor' for label in comparison_labels)
    if any_vor:

        for kite in kite_nodes:
            for ring in range(rings):
                wake_node = ring

                for ndx in range(n_k):
                    for ddx in range(d):

                        local_name = 'vortex_strength_' + str(kite) + '_' + str(ring) + '_' + str(ndx) + '_' + str(ddx)

                        variables = struct_op.get_variables_at_time(options, V, Xdot, model.variables, ndx, ddx)
                        wg_local = tools.get_ring_strength(variables, kite, ring)

                        ndx_shed = n_k - 1 - wake_node
                        ddx_shed = d - 1

                        # working out:
                        # n_k = 3
                        # if ndx = 0 and ddx = 0 -> shed: wn >= n_k
                        #     wn: 0 sheds at ndx = 2, ddx = -1 : unshed,    period = 0
                        #     wn: 1 sheds at ndx = 1, ddx = -1 : unshed,    period = 0
                        #     wn: 2 sheds at ndx = 0, ddx = -1 : unshed,    period = 0
                        #     wn: 3 sheds at ndx = -1, ddx = -1 : SHED      period = 1
                        #     wn: 4 sheds at ndx = -2,                      period = 1
                        #     wn: 5 sheds at ndx = -3                       period = 1
                        #     wn: 6 sheds at ndx = -4                       period = 2
                        # if ndx = 1 and ddx = 0 -> shed: wn >= n_k - ndx
                        #     wn: 0 sheds at ndx = 2, ddx = -1 : unshed,
                        #     wn: 1 sheds at ndx = 1, ddx = -1 : unshed,
                        #     wn: 2 sheds at ndx = 0, ddx = -1 : SHED,
                        #     wn: 3 sheds at ndx = -1, ddx = -1 : SHED
                        # if ndx = 0 and ddx = -1 -> shed:
                        #     wn: 0 sheds at ndx = 2, ddx = -1 : unshed,
                        #     wn: 1 sheds at ndx = 1, ddx = -1 : unshed,
                        #     wn: 2 sheds at ndx = 0, ddx = -1 : SHED,
                        #     wn: 3 sheds at ndx = -1, ddx = -1 : SHED

                        already_shed = False
                        if (ndx > ndx_shed):
                            already_shed = True
                        elif ((ndx == ndx_shed) and (ddx == ddx_shed)):
                            already_shed = True

                        if already_shed:

                            # working out:
                            # n_k = 3
                            # period_0 -> wn 0, wn 1, wn 2 -> floor(ndx_shed / n_k)
                            # period_1 -> wn 3, wn 4, wn 5

                            period_number = int(np.floor(float(ndx_shed)/float(n_k)))
                            ndx_shed_w_periodicity = ndx_shed - period_number * n_k

                            gamma_val = Outputs['coll_outputs', ndx_shed_w_periodicity, ddx_shed, 'aerodynamics', 'circulation' + str(kite)]
                            wg_ref = 1. * gamma_val / strength_scale
                        else:
                            wg_ref = 0.

                        local_resi = (wg_local - wg_ref)

                        local_cstr = cstr_op.Constraint(expr = local_resi,
                                                        name = local_name,
                                                        cstr_type='eq')
                        cstr_list.append(local_cstr)

    return cstr_list
Esempio n. 12
0
def get_force_cstr(options, variables, atmos, wind, architecture, parameters):

    surface_control = options['surface_control']

    f_scale = tools.get_f_scale(parameters, options)
    m_scale = tools.get_m_scale(parameters, options)

    cstr_list = mdl_constraint.MdlConstraintList()

    for kite in architecture.kite_nodes:

        parent = architecture.parent_map[kite]

        kite_dcm = cas.reshape(variables['xd']['r' + str(kite) + str(parent)],
                               (3, 3))

        vec_u_earth = tools.get_local_air_velocity_in_earth_frame(
            options, variables, atmos, wind, kite, kite_dcm, architecture,
            parameters)

        if int(surface_control) == 0:
            delta = variables['u']['delta' + str(kite) + str(parent)]
        elif int(surface_control) == 1:
            delta = variables['xd']['delta' + str(kite) + str(parent)]

        omega = variables['xd']['omega' + str(kite) + str(parent)]
        q = variables['xd']['q' + str(kite) + str(parent)]
        rho = atmos.get_density(q[2])
        force_info, moment_info = get_force_and_moment(options, parameters,
                                                       vec_u_earth, kite_dcm,
                                                       omega, delta, rho)

        f_found_frame = force_info['frame']
        f_found_vector = force_info['vector']

        m_found_frame = moment_info['frame']
        m_found_vector = moment_info['vector']

        forces_dict = tools.get_framed_forces(vec_u_earth, kite_dcm, variables,
                                              kite, architecture)
        f_var_frame = tools.force_variable_frame()
        f_var = forces_dict[f_var_frame]
        f_val = frames.from_named_frame_to_named_frame(from_name=f_found_frame,
                                                       to_name=f_var_frame,
                                                       vec_u=vec_u_earth,
                                                       kite_dcm=kite_dcm,
                                                       vector=f_found_vector)

        moments_dict = tools.get_framed_moments(vec_u_earth, kite_dcm,
                                                variables, kite, architecture)
        m_var_frame = tools.moment_variable_frame()
        m_var = moments_dict[m_var_frame]
        m_val = frames.from_named_frame_to_named_frame(from_name=m_found_frame,
                                                       to_name=m_var_frame,
                                                       vec_u=vec_u_earth,
                                                       kite_dcm=kite_dcm,
                                                       vector=m_found_vector)

        resi_f_kite = (f_var - f_val) / f_scale
        resi_m_kite = (m_var - m_val) / m_scale

        f_kite_cstr = cstr_op.Constraint(expr=resi_f_kite,
                                         name='f_aero' + str(kite) +
                                         str(parent),
                                         cstr_type='eq')
        cstr_list.append(f_kite_cstr)

        m_kite_cstr = cstr_op.Constraint(expr=resi_m_kite,
                                         name='m_aero' + str(kite) +
                                         str(parent),
                                         cstr_type='eq')
        cstr_list.append(m_kite_cstr)

    return cstr_list
Esempio n. 13
0
def get_fixing_constraint(options, V, Outputs, model):

    n_k = options['n_k']

    comparison_labels = options['induction']['comparison_labels']
    wake_nodes = options['induction']['vortex_wake_nodes']
    kite_nodes = model.architecture.kite_nodes
    wingtips = ['ext', 'int']

    Xdot = struct_op.construct_Xdot_struct(options, model.variables_dict)(0.)

    cstr_list = cstr_op.ConstraintList()

    any_vor = any(label[:3] == 'vor' for label in comparison_labels)
    if any_vor:

        for kite in kite_nodes:
            for tip in wingtips:
                for wake_node in range(wake_nodes):
                    local_name = 'wake_fixing_' + str(kite) + '_' + str(tip) + '_' + str(wake_node)

                    if wake_node < n_k:

                        # working out:
                        # n_k = 3
                        # wn:0, n_k-1=2
                        # wn:1, n_k-2=1
                        # wn:2=n_k-1, n_k-3=0
                        # ... switch to periodic fixing

                        reverse_index = n_k - 1 - wake_node
                        variables_at_shed = struct_op.get_variables_at_time(options, V, Xdot, model.variables,
                                                                            reverse_index, -1)

                        wx_local = tools.get_wake_node_position_si(options, variables_at_shed, kite, tip, wake_node)
                        wingtip_pos = Outputs[
                            'coll_outputs', reverse_index, -1, 'aerodynamics', 'wingtip_' + tip + str(kite)]

                        local_resi = wx_local - wingtip_pos

                        local_cstr = cstr_op.Constraint(expr = local_resi,
                                                        name = local_name,
                                                        cstr_type='eq')
                        cstr_list.append(local_cstr)

                    else:

                        # working out:
                        # n_k = 3
                        # wn:0, n_k-1=2
                        # wn:1, n_k-2=1
                        # wn:2=n_k-1, n_k-3=0
                        # ... switch to periodic fixing
                        # wn:3 at ndx = 0 must be equal to -> wn:0 at ndx = -1, ddx = -1
                        # wn:4 at ndx = 0 must be equal to -> wn:1 at ndx = -1, ddx = -1

                        variables_at_initial = struct_op.get_variables_at_time(options, V, Xdot, model.variables, 0)
                        variables_at_final = struct_op.get_variables_at_time(options, V, Xdot, model.variables, -1, -1)

                        upstream_node = wake_node - n_k
                        wx_local = tools.get_wake_node_position_si(options, variables_at_initial, kite, tip, wake_node)
                        wx_upstream = tools.get_wake_node_position_si(options, variables_at_final, kite, tip, upstream_node)

                        local_resi = wx_local - wx_upstream
                        local_cstr = cstr_op.Constraint(expr = local_resi,
                                                        name = local_name,
                                                        cstr_type='eq')
                        cstr_list.append(local_cstr)

    return cstr_list
Esempio n. 14
0
def get_winch_cstr(options, atmos, wind, variables_si, parameters, outputs,
                   architecture):

    cstr_list = mdl_constraint.MdlConstraintList()

    t_em = cas.DM(0.)

    if options['generator']['type'] != None and options['generator'][
            'type'] != 'experimental':
        if not options['tether']['use_wound_tether']:
            raise ValueError(
                'Invalid user_options: use_wound_tether = False, when you use a generator model with ODEs it have to be True'
            )
        if options['ground_station']['in_lag_dyn']:
            raise ValueError(
                'Invalid user_options: in_lag_dyn = True, when you use a generator model with ODEs it have to be False or when you dont want to use the default winch'
            )

        t_em = t_em_ode(options, variables_si, outputs, parameters,
                        architecture)

    if not options['ground_station']['in_lag_dyn']:

        radius_winch = parameters['theta0', 'ground_station',
                                  'r_gen']  #not optinal
        j_gen = parameters['theta0', 'ground_station', 'j_gen']
        j_winch = parameters['theta0', 'ground_station', 'j_winch']
        f_winch = parameters['theta0', 'ground_station', 'f_winch']
        l_t_full = variables_si['theta']['l_t_full']
        phi = (l_t_full - variables_si['xd']['l_t']) / radius_winch
        omega = -variables_si['xd']['dl_t'] / radius_winch
        domega = -variables_si['xddot']['ddl_t'] / radius_winch
        t_tether = -variables_si['xa']['lambda10'] * variables_si['xd'][
            'l_t'] * radius_winch
        t_frict = -f_winch * omega
        t_inertia = j_winch * domega
        t_inertia += variables_si['theta'][
            'diam_t']**2 / 4 * np.pi * parameters['theta0', 'tether',
                                                  'rho'] * radius_winch**3 * (
                                                      omega * omega +
                                                      domega * phi)  #

        rhs = t_tether + t_em + t_frict
        lhs = t_inertia

        omega = variables_si['xd']['dl_t'] / radius_winch
        domega = variables_si['xddot']['ddl_t'] / radius_winch
        phi = (l_t_full - variables_si['xd']['l_t']) / radius_winch

        rhs = (j_gen + j_winch) * variables_si['xddot']['ddl_t'] / radius_winch
        rhs += variables_si['theta']['diam_t']**2 / 4 * np.pi * parameters[
            'theta0', 'tether',
            'rho'] * radius_winch**3 * (-omega * omega + domega * phi)
        lhs = variables_si['xa']['lambda10'] * variables_si['xd'][
            'l_t'] * radius_winch - t_em

        if options['generator']['gear_train']['used']:
            j_gen = parameters['theta0', 'ground_station', 'j_gen']
            j_winch = parameters['theta0', 'ground_station',
                                 'j_winch']  #normaly rigid body
            f_gen = parameters['theta0', 'ground_station', 'f_gen']

            k = variables_si['theta']['k_gear']

            t_win = j_winch * variables_si['xddot'][
                'ddl_t'] / radius_winch + options['scaling']['theta'][
                    'diam_t']**2 / 4 * np.pi * parameters[
                        'theta0', 'tether', 'rho'] * radius_winch**3 * (
                            -omega * omega + domega * phi)  #
            j_gen *= k**2
            t_tether = -variables_si['xa']['lambda10'] * variables_si['xd'][
                'l_t'] * radius_winch

            t_gen = j_gen * variables_si['xddot']['ddl_t'] / radius_winch
            lhs = -t_gen - t_win
            rhs = t_tether + k * t_em  #+ omega*(f_winch + f_gen*k**2)

        if options['generator']['gear_train']['used']:

            k = variables_si['theta']['k_gear']
            #            dk  = variables_si['xddot']['dk_gear']

            #           dk_ineq         = dk

            #          dk_ineq_cstr    = cstr_op.Constraint(expr=dk_ineq, name='dk_ineq', cstr_type='eq')
            #         cstr_list.append(dk_ineq_cstr)
            #
            len_zstl = 0.1
            delta_r = 0.05
            rho_zstl = 2700
            j_zstl = np.pi * len_zstl * rho_zstl * (
                -3 * k * radius_winch**2 * delta_r**2 +
                2 * k**2 * delta_r**3 * radius_winch +
                2 * delta_r * radius_winch**3 - 1 / 2 * k**3 * delta_r**4)

            j_gen_zstl = k**3 * j_gen + j_zstl

            t_tether = variables_si['xa']['lambda10'] * variables_si['xd'][
                'l_t'] * radius_winch

            t_angular_momentum = (j_gen_zstl + k * j_winch) * domega
            t_angular_momentum_tether = k * variables_si['theta'][
                'diam_t']**2 / 4 * np.pi * parameters['theta0', 'tether',
                                                      'rho']
            t_angular_momentum_tether *= radius_winch**3 * (-omega * omega +
                                                            domega * phi)

            rhs = t_angular_momentum + t_angular_momentum_tether
            rhs += omega * (f_winch * k**3)
            lhs = t_tether * k - k**2 * t_em

        if options['generator']['type'] == 'pmsm':
            generator = generator_ode(options, variables_si, outputs,
                                      parameters, architecture)
            cstr_list.append(generator)


#            sign = variables_si['u']['sign']
#            sign_eq = sign**2 - 4*sign + 3
#            sign_ineq = -variables_si['u']['v_sq']/(sign)
#            sign_eq = cstr_op.Constraint(expr=sign_eq, name='sign_eq', cstr_type='eq')
#            cstr_list.append(sign_eq)
#            sign_ineq = cstr_op.Constraint(expr=sign_ineq, name='sign_ineq', cstr_type='ineq')
#            cstr_list.append(sign_ineq)
#sign = p_el_sign(options, variables_si, outputs, parameters, architecture)
#cstr_list.append(sign)

        torque = lhs - rhs

        print("torque")
        print(torque)
        winch_cstr = cstr_op.Constraint(expr=torque,
                                        name='winch',
                                        cstr_type='eq')
        cstr_list.append(winch_cstr)

    return cstr_list
Esempio n. 15
0
def generator_ode(options, variables_si, outputs, parameters, architecture):

    cstr_list = mdl_constraint.MdlConstraintList()

    if options['generator']['type'] == 'pmsm':
        if options['generator']['dv_sd']:
            #    v_sd = variables_si['u']['v_sd']
            v_sd_ode = variables_si['xddot']['dv_sd'] - variables_si['u'][
                'dv_sd']
            v_sd_ode = cstr_op.Constraint(expr=v_sd_ode,
                                          name='v_sd_ode',
                                          cstr_type='eq')
            cstr_list.append(v_sd_ode)
            v_sd = variables_si['xd']['v_sd']
            i_sd = variables_si['xd']['i_sd']
            di_sd = variables_si['xddot']['di_sd']

    #    v_sq = variables_si['u']['v_sq']
        v_sq_ode = variables_si['xddot']['dv_sq'] - variables_si['u']['dv_sq']
        v_sq_ode = cstr_op.Constraint(expr=v_sq_ode,
                                      name='v_sq_ode',
                                      cstr_type='eq')
        cstr_list.append(v_sq_ode)
        v_sq = variables_si['xd']['v_sq']
        i_sq = variables_si['xd']['i_sq']
        di_sq = variables_si['xddot']['di_sq']
        ld = parameters['theta0', 'generator', 'l_d']
        lq = parameters['theta0', 'generator', 'l_q']
        rs = parameters['theta0', 'generator', 'r_s']
        phi_f = parameters['theta0', 'generator', 'phi_f']
        p_p = parameters['theta0', 'generator', 'p_p']

        omega = -variables_si['xd']['dl_t'] / parameters['theta0',
                                                         'ground_station',
                                                         'r_gen']
        i_sq_ode = -v_sq + rs * i_sq + phi_f * omega * p_p + lq * di_sq

        if options['generator']['dv_sd']:
            i_sq_ode += omega * p_p * i_sd * ld
            i_sd_ode = -v_sd + rs * i_sd - omega * p_p * i_sq * lq + ld * di_sd

        if options['generator']['gear_train']['used']:
            k = variables_si['theta']['k_gear']

            r_gen = parameters['theta0', 'ground_station', 'r_gen']
            omega = k * variables_si['xd']['dl_t'] / r_gen
            i_sq_ode = -v_sq + rs * i_sq - phi_f * omega * p_p + lq * di_sq

            if options['generator']['dv_sd']:
                i_sq_ode += -omega * p_p * i_sd * ld
                i_sd_ode = -v_sd + rs * i_sd + omega * p_p * i_sq * lq + ld * di_sd

        print("i_sq_ode")
        print(i_sq_ode)

        i_sq_cstr = cstr_op.Constraint(expr=i_sq_ode,
                                       name='gen1',
                                       cstr_type='eq')
        cstr_list.append(i_sq_cstr)

        if options['generator']['dv_sd']:
            print('i_sd_ode')
            print(i_sd_ode)
            i_sd_cstr = cstr_op.Constraint(expr=i_sd_ode,
                                           name='gen0',
                                           cstr_type='eq')
            cstr_list.append(i_sd_cstr)
    return cstr_list