Code Monkey home page Code Monkey logo

dymos's Introduction

Dymos: Open Source Optimization of Dynamic Multidisciplinary Systems

Build Status Coverage Status

Dymos is a framework for the simulation and optimization of dynamical systems within the OpenMDAO Multidisciplinary Analysis and Optimization environment. Dymos leverages implicit and explicit simulation techniques to simulate generic dynamic systems of arbitary complexity.

The software has two primary objectives:

  • Provide a generic ODE integration interface that allows for the analysis of dynamical systems.
  • Allow the user to solve optimal control problems involving dynamical multidisciplinary systems.

Installation

pip install git+https://github.com/OpenMDAO/dymos.git

Documentation

Online documentation is available at https://openmdao.github.io/dymos/

Defining Ordinary Differential Equations

The first step in simulating or optimizing a dynamical system is to define the ordinary differential equations to be integrated. The user first builds an OpenMDAO model which has outputs that provide the rates of the state variables. This model can be an OpenMDAO model of arbitrary complexity, including nested groups and components, layers of nonlinear solvers, etc.

Next we can wrap our system with decorators that provide information regarding the states to be integrated, which sources in the model provide their rates, and where any externally provided parameters should be connected. When used in an optimal control context, these external parameters may serve as controls.

import numpy as np
from openmdao.api import ExplicitComponent

from dymos import declare_time, declare_state, declare_parameter

@declare_time(units='s')
@declare_state('x', rate_source='xdot', units='m')
@declare_state('y', rate_source='ydot', units='m')
@declare_state('v', rate_source='vdot', targets=['v'], units='m/s')
@declare_parameter('theta', targets=['theta'])
@declare_parameter('g', units='m/s**2', targets=['g'])
class BrachistochroneEOM(ExplicitComponent):

    def initialize(self):
        self.metadata.declare('num_nodes', types=int)

    def setup(self):
        nn = self.metadata['num_nodes']

        # Inputs
        self.add_input('v',
                       val=np.zeros(nn),
                       desc='velocity',
                       units='m/s')

        self.add_input('g',
                       val=9.80665*np.ones(nn),
                       desc='gravitational acceleration',
                       units='m/s/s')

        self.add_input('theta',
                       val=np.zeros(nn),
                       desc='angle of wire',
                       units='rad')

        self.add_output('xdot',
                        val=np.zeros(nn),
                        desc='velocity component in x',
                        units='m/s')

        self.add_output('ydot',
                        val=np.zeros(nn),
                        desc='velocity component in y',
                        units='m/s')

        self.add_output('vdot',
                        val=np.zeros(nn),
                        desc='acceleration magnitude',
                        units='m/s**2')

        self.add_output('check',
                        val=np.zeros(nn),
                        desc='A check on the solution: v/sin(theta) = constant',
                        units='m/s')

        # Setup partials
        arange = np.arange(self.metadata['num_nodes'])

        self.declare_partials(of='vdot', wrt='g', rows=arange, cols=arange, val=1.0)
        self.declare_partials(of='vdot', wrt='theta', rows=arange, cols=arange, val=1.0)

        self.declare_partials(of='xdot', wrt='v', rows=arange, cols=arange, val=1.0)
        self.declare_partials(of='xdot', wrt='theta', rows=arange, cols=arange, val=1.0)

        self.declare_partials(of='ydot', wrt='v', rows=arange, cols=arange, val=1.0)
        self.declare_partials(of='ydot', wrt='theta', rows=arange, cols=arange, val=1.0)

        self.declare_partials(of='check', wrt='v', rows=arange, cols=arange, val=1.0)
        self.declare_partials(of='check', wrt='theta', rows=arange, cols=arange, val=1.0)

    def compute(self, inputs, outputs):
        theta = inputs['theta']
        cos_theta = np.cos(theta)
        sin_theta = np.sin(theta)
        g = inputs['g']
        v = inputs['v']

        outputs['vdot'] = g*cos_theta
        outputs['xdot'] = v*sin_theta
        outputs['ydot'] = -v*cos_theta
        outputs['check'] = v/sin_theta

    def compute_partials(self, inputs, jacobian):
        theta = inputs['theta']
        cos_theta = np.cos(theta)
        sin_theta = np.sin(theta)
        g = inputs['g']
        v = inputs['v']

        jacobian['vdot', 'g'] = cos_theta
        jacobian['vdot', 'theta'] = -g*sin_theta

        jacobian['xdot', 'v'] = sin_theta
        jacobian['xdot', 'theta'] = v*cos_theta

        jacobian['ydot', 'v'] = -cos_theta
        jacobian['ydot', 'theta'] = v*sin_theta

        jacobian['check', 'v'] = 1/sin_theta
        jacobian['check', 'theta'] = -v*cos_theta/sin_theta**2

Integrating Ordinary Differential Equations

Dymos's RungeKutta and solver-based pseudspectral transcriptions provide the ability to numerically integrate the ODE system it is given. Used in an optimal control context, these provide a shooting method in which each iteration provides a physically viable trajectory.

Pseudospectral Methods

dymos currently supports the Radau Pseudospectral Method and high-order Gauss-Lobatto transcriptions. These implicit techniques rely on the optimizer to impose "defect" constraints which enforce the physical accuracy of the resulting trajectories. To verify the physical accuracy of the solutions, Dymos can explicitly integrate them using variable-step methods.

Solving Optimal Control Problems

dymos uses the concept of phases to support optimal control of dynamical systems. Users connect one or more phases to construct trajectories. Each phase can have its own:

  • Optimal Control Transcription (Gauss-Lobatto, Radau Pseudospectral, or RungeKutta)
  • Equations of motion
  • Boundary and path constraints

dymos Phases and Trajectories are ultimately just OpenMDAO Groups that can exist in a problem along with numerous other models, allowing for the simultaneous optimization of systems and dynamics.

dymos's People

Contributors

ehariton avatar hwangjt avatar justinsgray avatar kenneth-t-moore avatar naylor-b avatar robfalck avatar swryan avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.