Modeling and Simulation with Compose and Activate

This book provides a tutorial in the use of Compose and Activate, software packages that provide system modeling and simulation facilities. Advanced system modeling software provide multiple ways of creating models: models can be programmed in specialized languages, graphically constructed as block-diagrams and state machines, or expressed mathematically in equation-based languages. Compose and Activate are introduced in this text in two parts. The first part introduces the multi-language environment of Compose and its use for modeling, simulation and optimization. The second describes the graphical system modeling and optimization with Activate, an open-system environment providing signal-based modeling as well as physical system component-based modeling. Throughout both parts are applied examples from mechanical, biological, and electrical systems, as well as control and signal processing systems. This book will be an invaluable addition with many examples both for those just interested in OML and those doing industrial scale modeling, simulation, and design. All examples are worked using the free basic editions of Activate and Compose that are available.

105 downloads 5K Views 25MB Size

Recommend Stories

Empty story

Idea Transcript


Stephen L. Campbell · Ramine Nikoukhah

Modeling and Simulation with Compose and Activate

Modeling and Simulation with Compose and Activate

Stephen L. Campbell Ramine Nikoukhah •

Modeling and Simulation with Compose and Activate

123

Stephen L. Campbell Department of Mathematics North Carolina State University Raleigh, NC, USA

Ramine Nikoukhah Altair Engineering France Antony, France

ISBN 978-3-030-04884-6 ISBN 978-3-030-04885-3 https://doi.org/10.1007/978-3-030-04885-3

(eBook)

Library of Congress Control Number: 2018962375 Mathematics Subject Classification (2010): 34A01, 34A04, 34A38, 34H05, 68U07, 68U20, 37M05, 65Y15 © Springer Nature Switzerland AG 2018 This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication does not imply, even in the absence of a specific statement, that such names are exempt from the relevant protective laws and regulations and therefore free for general use. The publisher, the authors and the editors are safe to assume that the advice and information in this book are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or the editors give a warranty, express or implied, with respect to the material contained herein or for any errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional claims in published maps and institutional affiliations. This Springer imprint is published by the registered company Springer Nature Switzerland AG The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland

This book is dedicated to our wives and children. They make the whole journey worthwhile; Homa Nikoukhah and daughters Tina and Dana, Gail Campbell and sons Matt and Eric.

Preface

System modeling and simulation is a fundamental aspect of most areas of science and engineering. This has led to the development of software packages aimed at helping speed up the process of modeling, simulation, optimization, analysis, and assessment of systems. More advanced system modeling software provide multiple ways of creating models: Models can be programmed in specialized languages, and they can be graphically constructed as block diagrams and state machines, or expressed mathematically in equation-based languages. This book is about two new software packages, called Altair Compose™ and Altair Activate™, providing all these modeling facilities. Compose is a multi-language environment for scientific computation with special emphasis on modeling, simulation, optimization, and assessment. This book will focus on the newly developed open matrix language (OML). OML is part of the MATLAB-like family of languages such as MATLAB®, Scilab, and Octave. OML is compatible with Octave and provides bridges to Python and Tcl/Tk. An open-source version of OML has been released in 2018, available from www. openmatrix.org. Activate is an open-system graphical modeling and simulation environment providing signal-based modeling as well as physical system component-based modeling, where the latter supports Modelica and Spice libraries. OML is the underlying scripting language in Activate for defining model parameters, programmatically constructing models and performing pre- and post-processing. Basic editions of Compose and Activate are available for free from Altair at https://www.altair.com/mbd2019/. Basic Compose OML includes a number of toolboxes, such as the Control Toolbox. Basic Activate includes many libraries as well. All the examples in this book have been modeled and simulated with the basic editions. Compose and Activate run under the Windows operating system. There is also a Linux version of Compose with OML. A Linux version of Activate is in development and should be available in 2019. The professional versions integrate with numerous 1D and 3D simulation tools and are available from Altair as well. vii

viii

Preface

This book provides a tutorial in the use of Compose and Activate. Part I introduces Compose and OML and its use for modeling, simulation, and optimization of dynamical systems. Part II describes graphical system modeling and optimization with Activate. The support of equation-based modeling language Modelica in Activate is also presented and illustrated through a number of examples. Throughout the book, numerous examples of varying complexity are carefully developed and worked out. The examples are drawn from several application areas including mechanical systems, biological systems, electrical systems, and control and signal processing systems. A number of people have supported us in many ways. We would especially like to acknowledge Michael Hoffmann and James Dagg for their support and contributions to the development of Compose and Activate, and especially James Scapa for making it all happen. Raleigh, NC, USA Antony, France October 2018

Stephen L. Campbell Ramine Nikoukhah

Contents

Part I

Altair Compose and OML

1

General Information . . . . . . . . . . . . . . . 1.1 What Is OML? . . . . . . . . . . . . . . . 1.2 Compose OML . . . . . . . . . . . . . . . 1.3 OML in Modeling and Simulation .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

3 3 5 8

2

Introduction to OML . . . . . . . . . . . . . . . . . . . . . . . 2.1 OML Objects . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Matrix Construction and Manipulation . 2.1.2 Strings . . . . . . . . . . . . . . . . . . . . . . . . 2.1.3 Boolean Matrices . . . . . . . . . . . . . . . . 2.1.4 Polynomial Matrices . . . . . . . . . . . . . . 2.1.5 Structures and Cells . . . . . . . . . . . . . . 2.1.6 Functions . . . . . . . . . . . . . . . . . . . . . . 2.2 OML Programming . . . . . . . . . . . . . . . . . . . . . 2.2.1 Branching . . . . . . . . . . . . . . . . . . . . . 2.2.2 Iterations . . . . . . . . . . . . . . . . . . . . . . 2.2.3 OML Functions . . . . . . . . . . . . . . . . . 2.2.4 User Defined C/C++ Functions . . . . . . 2.3 Input and Output Functions . . . . . . . . . . . . . . . 2.3.1 Display of Variables . . . . . . . . . . . . . . 2.3.2 User Input During Computation . . . . . 2.3.3 Formatted Input and Output . . . . . . . . 2.4 OML Graphics . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 Basic Graphing . . . . . . . . . . . . . . . . . 2.4.2 Interpolation . . . . . . . . . . . . . . . . . . . . 2.4.3 Graphic Tour . . . . . . . . . . . . . . . . . . . 2.4.4 Subplots . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

9 10 11 21 23 24 26 27 29 31 33 36 40 43 43 44 44 46 46 48 50 59

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

ix

x

Contents

3

Modeling and Simulation in OML . . . . . . . . 3.1 Types of Models . . . . . . . . . . . . . . . . . . 3.1.1 Ordinary Differential Equations . 3.1.2 Boundary Value Problems . . . . 3.1.3 Difference Equations . . . . . . . . . 3.1.4 Differential Algebraic Equations 3.1.5 Hybrid Systems . . . . . . . . . . . . 3.2 OML Simulation Functions . . . . . . . . . . 3.2.1 Implicit Differential Equations . . 3.2.2 Linear Systems . . . . . . . . . . . . . 3.2.3 Root Finding . . . . . . . . . . . . . . 3.2.4 Boundary Value Problems . . . . 3.2.5 Difference Equations . . . . . . . . . 3.2.6 Hybrid Systems . . . . . . . . . . . . 3.3 Control Toolbox . . . . . . . . . . . . . . . . . .

4

Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Comments on Optimization and Solving Nonlinear Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Nonlinear Equation Solving . . . . . . . . . . . 4.2 General Optimization . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Genetic Algorithms . . . . . . . . . . . . . . . . . 4.3 Solving Nonlinear Equations . . . . . . . . . . . . . . . . . 4.4 Parameter Fitting . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.1 Linear Programs . . . . . . . . . . . . . . . . . . . .

5

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

61 62 62 63 64 65 67 68 74 74 75 75 76 78 78

.........

97

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

98 99 100 103 105 107 108

Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 Boundary Value Problems by Shooting . . . . . . . . . . . . . 5.2 Parameter Fitting and Implicit Models . . . . . . . . . . . . . . 5.2.1 Mathematical Model . . . . . . . . . . . . . . . . . . . . . 5.2.2 OML Implementation . . . . . . . . . . . . . . . . . . . . 5.3 Open-Loop Control of a Pendulum . . . . . . . . . . . . . . . . 5.3.1 Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.2 Control Problem Formulation: Tracking . . . . . . . 5.3.3 Control Problem Formulation: Minimizing Time 5.3.4 Optimization Problem . . . . . . . . . . . . . . . . . . . . 5.3.5 Implementation in OML . . . . . . . . . . . . . . . . . . 5.4 PDEs and Time-Delay Systems Using MOL . . . . . . . . . 5.4.1 Solving PDEs Using MOL . . . . . . . . . . . . . . . . 5.4.2 Systems with Delays . . . . . . . . . . . . . . . . . . . . 5.5 Plane Boarding Strategies . . . . . . . . . . . . . . . . . . . . . . . 5.6 Introduction to Block Diagrams . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

111 111 118 119 119 126 126 127 130 132 134 137 138 144 148 151

. . . . . . .

. . . . . . .

. . . . . . .

Contents

Part II

xi

Altair Activate

6

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 Modeling and Simulation in Activate . . . . . . . . . . . . 6.1.1 Running Activate . . . . . . . . . . . . . . . . . . . . 6.1.2 Constructing a First Model . . . . . . . . . . . . . 6.1.3 Support of Vectors and Matrices in Activate 6.1.4 Time Delay Blocks . . . . . . . . . . . . . . . . . . . 6.1.5 Activation Signals . . . . . . . . . . . . . . . . . . . 6.2 Virtual Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Modeling a Traffic Light as a State Machine 6.3 Synchronism and Special Blocks . . . . . . . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

157 159 159 159 164 170 171 177 177 183

7

Expression Blocks . . . . . . . . . . . . . . . . . . . . . . 7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 7.2 Activate MathExpression Block . . . . . . . . . 7.2.1 MathExpressions Block . . . . . . . . 7.2.2 Example: Bouc-Wen Model . . . . 7.3 Activate MatrixExpression Block . . . . . . . . 7.3.1 The Matrix Expression Language 7.3.2 Examples . . . . . . . . . . . . . . . . . . 7.4 Activate OmlExpression Block . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

187 187 188 189 190 191 192 193 204

8

Beyond Single Run Simulations 8.1 End Block . . . . . . . . . . . . 8.1.1 Stop Option . . . . 8.1.2 Restart Option . 8.1.3 Examples . . . . . . . 8.2 BobyqaOpt Block . . . . . . . . 8.2.1 Examples . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

205 205 205 206 208 213 214

9

Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1 Predator Prey Model . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Thermostat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 Generic Extended Kalman Filter Model . . . . . . . . . . . . 9.4 Signal Processing Application . . . . . . . . . . . . . . . . . . . 9.5 Neuroscience Application . . . . . . . . . . . . . . . . . . . . . . 9.6 Active Cruise Controller . . . . . . . . . . . . . . . . . . . . . . . 9.6.1 Model Construction . . . . . . . . . . . . . . . . . . . . 9.6.2 Implementation of the Adaptive Cruise Control 9.7 Swing-Up Pendulum Problem . . . . . . . . . . . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

219 219 223 226 234 236 238 239 241 247

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

xii

Contents

10 Formalism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1 From Graphical Model to Simulation Structure . . . . . 10.1.1 Scoping Rule . . . . . . . . . . . . . . . . . . . . . . . 10.1.2 Basic Blocks and Atomic Units . . . . . . . . . . 10.1.3 Masking . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Activation Signals . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1 Block Activation . . . . . . . . . . . . . . . . . . . . 10.2.2 Activation Generation . . . . . . . . . . . . . . . . . 10.2.3 Activation Inheritance . . . . . . . . . . . . . . . . . 10.2.4 Always Active Blocks . . . . . . . . . . . . . . . . 10.2.5 Initially Active Blocks . . . . . . . . . . . . . . . . 10.2.6 Conditional Blocks . . . . . . . . . . . . . . . . . . . 10.2.7 EventPortZero Block . . . . . . . . . . . . . . . . . . 10.3 Synchronous Versus Asynchronous Events . . . . . . . . 10.3.1 SampleClock Block Versus EventClock Block 10.3.2 Zero-Crossing Events . . . . . . . . . . . . . . . . . 10.4 Periodic Activations . . . . . . . . . . . . . . . . . . . . . . . . 10.5 Repeat Activations . . . . . . . . . . . . . . . . . . . . . . . . . 10.5.1 Example: Simple Counter . . . . . . . . . . . . . . 10.5.2 Example: Random Permutation . . . . . . . . . . 10.5.3 Example: Golden-Section Search . . . . . . . . . 10.6 Atomic Super Block . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

251 251 251 252 254 254 255 258 258 260 261 262 265 266 267 267 269 269 270 271 273 274

11 Hybrid Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Hybrid System Modeling . . . . . . . . . . . . . . . . . . . . 11.2.1 Activating and Deactivating a Super Block . 11.2.2 Dynamics Common to all Discrete States . . 11.2.3 Use of SetSignal and GetSignal Blocks . . . . . 11.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.1 Integrator with Saturation Indicator . . . . . . . 11.3.2 Auto-Tuning PID Controller . . . . . . . . . . . . 11.3.3 Clutch Mechanism . . . . . . . . . . . . . . . . . . . 11.3.4 Simple Two Dimensional Car Model . . . . . . 11.4 Systematic Approach to Constructing State Machines 11.4.1 Exclusive and Concurrent States . . . . . . . . . 11.4.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.3 Two Dimensional Car or Bike Model . . . . . 11.4.4 Racing Cars . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

277 277 282 284 285 286 286 286 290 293 294 306 308 310 325 326

12 Activate-OML Interactions and Batch Simulation . . . . . . . . . . . . . 341 12.1 Batch Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 12.1.1 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342

Contents

xiii

12.2 Data Exchange Between OML and Activate . . . . . . . 12.2.1 Using the External-Context Workspace . . . . 12.2.2 Using SignalIn and SignalOut Blocks . . . . . . 12.2.3 Example . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3 Programmable Construction and Parameterization of Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4 Linearization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.1 Example: Inverted Pendulum on a Cart . . . . 12.4.2 Example: Inverted Pendulum on a Cart on an Inclined Surface . . . . . . . . . . . . . . . . 12.4.3 Control Ignoring the Inclination . . . . . . . . . 12.4.4 Linearization Around the Equilibrium Point . 12.4.5 Control Using an Integrator in the Loop . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

343 344 344 345

. . . . . . . . 346 . . . . . . . . 347 . . . . . . . . 349 . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

355 356 357 358

13 Construction of New Blocks . . . . . . . . . . . . . . . . . . . 13.1 Programmable Super Block . . . . . . . . . . . . . . . . 13.2 Using Custom Blocks to Construct Basic Blocks 13.2.1 Atomic Unit . . . . . . . . . . . . . . . . . . . . . 13.2.2 Examples . . . . . . . . . . . . . . . . . . . . . . . 13.3 Block Libraries . . . . . . . . . . . . . . . . . . . . . . . . . 13.3.1 Library Content . . . . . . . . . . . . . . . . . . 13.3.2 Library Management . . . . . . . . . . . . . . 13.4 IncludeDiagram Block . . . . . . . . . . . . . . . . . . . . 13.5 Block Builder . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

361 361 363 364 369 379 380 381 381 382

14 Modelica Support . . . . . . . . . . . . . . . . . . 14.1 Introduction . . . . . . . . . . . . . . . . . . 14.2 Modelica Libraries . . . . . . . . . . . . . 14.3 Modelica Language . . . . . . . . . . . . . 14.4 Modelica Custom Blocks . . . . . . . . 14.4.1 MoCustomBlock . . . . . . . . . . 14.4.2 MoCustomComponent Block . 14.5 Example . . . . . . . . . . . . . . . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

387 387 392 394 395 395 403 408

15 Other Activate Functionalities . . . . . . . . . . . . . . . . . . 15.1 Optimization Interface . . . . . . . . . . . . . . . . . . . . 15.2 Code Generator . . . . . . . . . . . . . . . . . . . . . . . . 15.2.1 Code Generation to Create a New Block 15.3 Activate Debugger . . . . . . . . . . . . . . . . . . . . . . 15.4 Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.5 Simulink® Import . . . . . . . . . . . . . . . . . . . . . . . 15.5.1 Frequently Encountered Problems . . . . . 15.5.2 Simport Interface . . . . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

415 415 417 419 421 422 423 424 426

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

xiv

Contents

15.6 Co-simulation . . . . . . 15.6.1 FMI . . . . . . . 15.6.2 MotionSolve 15.6.3 HyperSpice .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

426 426 427 428

Appendix A: Computational Function C APIs . . . . . . . . . . . . . . . . . . . . . 429 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439

Acronyms and Units

Acronyms API AU BDF BVP DAE FMI FMU GUI LTI MOL MSL NLP ODE OML PDE PID RPM SVD

Application Programming Interface Atomic Unit Backward Differentiation Formula Boundary Value Problem Differential Algebraic Equation Functional Mock-up Interface Functional Mock-up Unit Graphical User Interface Linear Time Invariant Method of Lines Modelica Standard Library Nonlinear Program Ordinary Differential Equation Open Matrix Language Partial Differential Equation Proportional Integral Derivative Revolutions per Minute Singular Value Decomposition

Units Hour Kilogram Kilogram meter squared Kilometer Kilometer per hour Meter

h kg kg m2 km km h−1 m

xv

xvi

Newton meter Second Meter per second Percent

Acronyms and Units

Nm s m/s or m s−1 %

Part I

Altair Compose and OML

Chapter 1

General Information

1.1 What Is OML? There exist two categories of general scientific software: computer algebra systems that perform symbolic computations, and general purpose numerical systems performing numerical computations and designed specifically for scientific applications. The best-known examples in the first category are Maple, Mathematica, Maxima, Axiom, and MuPad. The second category represents a larger market dominated by matlab and Matlab-like languages such as Octave, Scilab [11] and Julia. OML belongs to this second category. OML is a new language released for the first time as part of the Altair product Compose in Spring of 2017 and in 2018 as the supporting scripting language for Activate. An open-source version of OML has also been released in 2018. In this book, the OML distributed in the Activate package distributed and maintained by Altair is considered. But most of what is presented in this part of the book applies to OML generally. OML is an interpreted language with dynamically typed objects. OML can be used as a scripting language to test algorithms or to perform computations. But it is also a programming language, and the standard OML library contains a large number of predefined functions that facilitates the development of applications, especially in scientific and engineering domains. The OML syntax, which is very similar to that of matlab and Octave, is simple, and the use of matrices, which are the fundamental object of scientific calculus, is facilitated through specific functions and operators. These matrices can be real or complex. OML programs are thus quite compact and most of the time are smaller than their equivalents in C, C++, or Java. OML is mainly dedicated to scientific computing, and it provides easy access to large numerical libraries from such areas as linear algebra, numerical integration, and optimization. It is also simple to extend the OML environment. One can easily import new functionalities from external libraries into OML.

© Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_1

3

4

1 General Information

OML has • • • • • • • • •

Elementary functions of scientific calculation; Linear algebra, matrices; Polynomials; Classic and robust control; Nonlinear methods (optimization, ODE and DAE solvers); Activate, which is a hybrid dynamic systems modeler and simulator; Signal processing; Random sampling and statistics; Graphics, animation.

OML is open source. OML comes with both Activate and Compose. Free editions of Activate and Compose are available from the Altair company at www.altair.com/compose and www.altair.com/activate. The free editions, while very powerful pieces of software are referred to as the basic editions. Professional editions may be purchased from Altair. With the exception of a few comments in the last chapter, this book is about the free editions of Compose and Activate. In particular, when talking about running OML we shall do so using the Compose interface. OML can also be run from within Activate as will be shown in the second part of this book. Currently Compose and Activate run under the Windows operating systems. They can be easily run on a Macintosh computer by running Windows on a virtual machine such as provided by the open source software VirtualBox. There is also a version of Compose with OML that runs under Linux. Since OML is an interpretative language when run in Compose, then as is true for all interpretative languages, there is a price to pay in terms of performance but the difference in performance with compiled code depends very much on the type of code being developed. Programming in OML presents many advantages compared to using compiled languages, in particular the ease of programming (dynamic typing, easy debugging,...). But OML is of course not the right choice for coding everything: indeed a factor of 100 may exist when low-level algorithms are programmed in OML. But this is rarely the case for the type of applications OML is used for and are presented in this book. OML like similar software comes with a large body of functionalities made available through highly optimized libraries. These functionalities go way beyond matrix operations and user can create new OML functionalities by interfacing his own C/C++ code. The OML programmer, by relying on these functionalities, can avoid coding computation extensive algorithms in OML. So in general, the performance factor is not considerable and often it is not even relevant. For example, OML is used for controller and filter design. Constructing filters and controllers uses complex algorithms, which are made available through library functions. The performance is not an issue in such cases. However validating them through simulation can be computationally expensive. That is why in Activate models are compiled (OML scripts used to parameterize the model are only executed once) and the compilation result is very efficiently simulated without any use of OML, unless of course the user has made

1.1 What Is OML?

5

the choice to use OML Custom blocks in their model, something which is sometimes done in the prototyping stage). For simulations and optimizations performed in OML, if performance becomes an issue, the evaluation functions, which are called a large number of times by solver, may be hard coded in C/C++ and interfaced.

1.2 Compose OML A typical OML user spends most of his time going back and forth between the OML shell and a text editor. For the most part, OML programs contain very few lines of instructions, thanks to the powerful data types and primitives available in OML. These programs can be written using a built-in editor, which is activated when Compose is opened or using the user’s favorite text editor. When Compose is opened a window opens with several subwindows as shown in Figure 1.1. The right most subwindow gives access to other directories. We delete it by clicking the X on the right just above the subwindow giving Figure 1.2. The bottom right window of Figure 1.2 is called the OML Command Window and is where line commands are entered and where output will go unless directed to a file as explained later. The upper right window is where we can write and edit programs. For example, if we enter the commands

Fig. 1.1 Initial Compose OML Screen

6

1 General Information

Fig. 1.2 Initial Compose OML Screen without a list of directories

1 2 3

A-[1 2;3 4]; B=eye(2)+A C=inv(A)

and then click the start button at the top (black right facing triangle), we get the output B = [Matrix] 2 x 2 2 2 3 5 C = [Matrix] 2 x 2 1.25000 -0.50000 -0.75000 0.50000

as shown in Figure 1.3. Each of the windows can be deleted. Plots are done in a new window. Figure 1.4 shows the result of doing a simple plot using 1 2 3 4 5 6

tt=0:0.1:5; xt=sin(tt); yt=cos(tt); plot(tt,xt) hold plot(tt,yt)

and deleting the command line window.

1.2 Compose OML

Fig. 1.3 Running a simple program

Fig. 1.4 The plot window

7

8

1 General Information

There are a number of standard file and editing commands available under the File, Edit, View, and Tools menus in the upper left of the Compose window. Under View there is a list of all the windows. They can be opened or closed by clicking on their name. The Command Line Window may be cleared by using the clc command. Clicking the Top left File menu opens a new window. At the bottom is a blue disk with a white question mark inside. This will give access to tutorials and the Help for Compose. Help about a particular OML function can also be gotten on the command line with the help function. For example entering help rand will get information on the rand function. Opening the documentation of an OML function by clicking F1 on the function name in the OML window or inside the editor opens up the manual page of the function in the browser. The manual page contains more information than what help provides.

1.3 OML in Modeling and Simulation OML can be used in many scientific and engineering domains but the focus of this book is modeling and simulation so the presentation of the OML language will primarily be concerned with functionalities needed for implementing applications dedicated to modeling and simulation in OML or functionalities that are required in the use of the Activate modeler and simulator presented in the second part of the book.

Chapter 2

Introduction to OML

The OML language is formulated to handle matrix operations, and scientific and engineering applications are a major target. But the OML language includes powerful operators for manipulating a large variety of basic objects. In OML objects are never declared or allocated explicitly; they have a dynamic type and their sizes can dynamically change according to applied operators or functions. The following OML session illustrates the creation of an object, its dynamic change, and its deletion. Note that if “;" is present at the end of a command, then the result of the operation is not displayed. If ; is omitted, then the result is displayed on the screen. The text in a line following a % is a comment that is not read by OML. A block of code can be commented out by using %{ and %} at the beginning and end of the block of code. > a=rand(2,3); % creates a 2 by 3 random matrix > class(a) % checks what type of variable a is ans = double % double precision scalar > a=[a,zeros(2,1)] % changes a to a different matrix a = [Matrix] 2 x 4 0.54881 0.59284 0.71519 0.00000 0.84427 0.60276 0.85795 0.00000 > a=’OML’;class(a) % makes a character string, checks class ans = char > exist(’a’) % check if variable a exists ans = 1 % 1 means yes or true > clear(’a’);exist(’a’) % clear variable a & check if exists ans = 0 % variable a no longer exists. 0 means no or false.

Note that the function class returns the type of the object, exist tests the presence of the object, and clear destroys it and frees the corresponding memory. For every class there is a command to check if a given object is in that class. Examples are iscomplex, isreal, isbool for boolean, iscell, ischar for character, isempty, isfinite, isinf, isnan, and isnumeric. © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_2

9

10

2 Introduction to OML

By default, numbers in OML are coded as double-precision floats. The accuracy of double-precision computation can be obtained through the predefined OML variable eps, called the machine precision. The number of digits displayed can be set with the format function. format format format format format

% default short % scaled fixed point with 5 digits long % scaled fixed point format with 15 digits short E % floating point format with 5 digits long E % floating point format with 15 digits

The differences between these formats are illustrated in the following session > z=10ˆ7*e; >format; z z = 27182818.3 > format short; z z = 27182818.28459 > format long; z z = 27182818.28459045 > format short E; z z = 2.71828E+07 > format long E; z z = 2.71828183E+07

OML expressions are evaluated by the OML interpreter. The interpreter has access to a large set of functions. Some of these functions are OML-coded functions (it is seen later that OML is a programming language), some are hard-coded functions in C/C++ or Fortran. This ability of OML to include C/C++ or Fortran coded functions means that a large amount of existing scientific and engineering software can be used from within OML. OML is a rich and powerful programming environment because of this large number of available functions. The users can also enrich the basic OML environment with their own OML or hard-coded functions, and moreover this can be done dynamically (hard-coded functions can be dynamically loaded in a running OML session); how this can be done will be shown later. Thus, toolboxes can be developed to enrich and adapt OML to specific needs or areas of application. The built in OML functions include the standard and hyperbolic trigonometric functions such as sin, cos, tan, tanh, sinh, cosh from which it is easy to build any other needed trigonometric functions. The inverse trigonometric functions are given by asin, acos, atan, atanh, asinh, and acosh. The functions asind and acosd give the result in degrees rather than in radians. atan2 is a function of two variables. atan2(x,y) gives the angle in radians for any pair x,y. OML also includes square roots sqrt and the bth power of a written as aˆb.

2.1 OML Objects OML provides users with a large variety of basic objects starting with numbers and character strings up to more sophisticated objects such as booleans, polynomials, and structures.

2.1 OML Objects

11

As already mentioned, OML is devoted to scientific computing, and the basic object is a two-dimensional matrix with floating-point double-precision number entries. In fact, a scalar is nothing but a 1 × 1 matrix. The next OML session illustrates this type of object. Note that some numerical constants are predefined in OML. In particular, π is pi and e, the base of the natural log, is e. Note also that in OML a:b:c gives numbers starting from a to c spaced b units apart. > a=1:0.3:2 % a now a scalar matrix double precision a = [Matrix] 1 x 4 1.00000 1.30000 1.60000 1.90000 > b=[e,pi] % b is a 1x2 matrix with entries e and pi. b = [Matrix] 1 x 2 2.71828 3.14159 > a=eig(rand(3,3)) % eigenvalues of 3x3 matrix. a = [Matrix] 3 x 1 % Complex 3x1 matrix 1.81024 -0.30433 -0.04190

Note also that functions in OML may be considered as objects as well. Anonymous functions will be discussed in the section on functions. > a=’OML’ % a 1x1 character matrix a = OML > b=rand(2,2) % b a matrix b = [Matrix] 2 x 2 0.54881 0.59284 0.71519 0.84427 > b=b>=0.6 % b now boolean matrix; 0 false and 1 true b = [Matrix] 2 x 2 0 0 1 1 > a=eig(rand(3,3)) a = [Matrix] 3 x 1 1.81024 -0.30433 -0.04190 > A.x=32;A.y=’t’ % generates a structure A = struct [ x: 32 y: t ] > class(A) ans = struct

2.1.1 Matrix Construction and Manipulation This section highlights general functions and operators that are used to manipulate matrices. There are two matrix types, real and complex.

12

2 Introduction to OML

A matrix in OML refers to one- or two- or three-dimensional arrays, which are internally stored as a one-dimensional array (two-dimensional arrays are stored in column order and the same for three-dimensional arrays). It is therefore always possible to access matrix entries with one, two, or three indices. A special command slice is needed for three indices. This is explained later. Vectors and scalars are stored as matrices. Elementary construction operators are the row concatenation operator “ ;” and the column concatenation operator “,”. These two operators perform the concatenation operation when used in a matrix context, that is, when they appear between “[” and “]”. All the associated entries of a matrix must be of the same type. Note that in the same matrix context a white space means the same thing as “,” and a line feed means the same thing as “;”. However, this equivalence can lead to confusion when, for example, a space appears inside an entry, as illustrated in the following: > A 1 > A 1 > A 1 > A 1 1

A=[1,2,3 +5] % unary + treats 3 and +5 as different numbers = [Matrix] 1 x 4 2 3 5 A=[1,2,3+5] % treats 3+5 as sum = [Matrix] 1 x 3 2 8 A=[1,2,3 *5] % binary * same with or without space = [Matrix] 1 x 3 2 15 A=[A,0;1,2,3,4] % building bigger matrix from submatrices = [Matrix] 2 x 4 2 15 0 2 3 4

Some of these commands can be used in several ways. The allowable syntax for diag are R R R R R

= = = = =

diag(v) % vector v on diagonal, R is square diag(v,k) % vector v on the kth diagonal, R is square diag(v,m,n) % vector v on main diagonal R is m x n diag(M) % principal diagonal of matrix M diag(M,k) % kth diagonal of matrix M.

eye, ones, zeros, rand may be used with two arguments for a rectangular matrix or with one argument for a square matrix. Table 2.1 describes frequently used matrix functions that can be used to create special matrices. When discussing the mathematics behind a particular command we will use A T to denote the transpose of a matrix A rather than the OML command A’. Some of these matrix functions are illustrated in the following examples: > A 1 0 3 0 > d

A=[eye(2,1), 3*ones(2,3);linspace(3,9,4);zeros(1,4)] = [Matrix] 4 x 4 3 3 3 3 3 3 5 7 9 0 0 0 d=diag(A)’ % main diagonal of A as row vector = [Matrix] 1 x 4

2.1 OML Objects Table 2.1 A set of functions for creating matrices

1 > B 1 0 0 0 > C 1 3

13 ’ and .’ diag

transpose (conjugate or not) (m,n) matrix with given diagonal (or diagonal extraction) eye (m,n) matrix with one on the main diagonal integer part of a matrix fix linspace or : linearly spaced vector logarithmically spaced vector logspace reshape reshape an (m,n) matrix (m*n is kept constant) (m,n) matrix consisting of ones ones rand (m,n) random matrix (uniform or Gaussian) zeros (m,n) matrix consisting of zeros

3 7 0 B=diag(d) % builds a diagonal matrix = [Matrix] 4 x 4 0 0 0 3 0 0 0 7 0 0 0 0 C=reshape(d,2,2) % reshapes d into 2x2 matrix = [Matrix] 2 x 2 7 0

The majority of OML functions are implemented in such a way that they accept matrix arguments. Most of the time this is implemented by applying mathematical functions element-wise. For example, the exponential function exp applied to a matrix returns the element-wise exponential and differs from the important matrix exponential function expm. > A=rand(2,2); > B=exp(A) B = [Matrix] 2 x 2 1.40129 1.09104 1.91204 1.02042 > B=expm(A) B = [Matrix] 2 x 2 1.43716 0.10561 0.78567 1.05270

2.1.1.1

Extraction, Insertion, and Deletion

To specify a set of matrix entries for the matrix A use the syntax A(B) or A(B,C), where B and C are numeric or boolean matrices that are used as indices.

14

2 Introduction to OML

The interpretation of A(B) and A(B,C) depends on whether it is on the left- or right-hand side of an assignment = if an assignment is present. If A(B) or A(B,C) are on the left side, and the right-hand side evaluates to a nonnull matrix, then an assignment operation is performed. In that case the left member expression stands for a submatrix description whose entries are replaced by the ones of the right matrix entries. Of course, the right and left submatrices must have compatible sizes, that is, they must have the same size, or the right-hand-side matrix must be a scalar. If the right-hand-side expression evaluates to an empty matrix, then the operation is a deletion operation. Entries of the left-hand-side matrix expression are deleted. Assignment or deletion can change dynamically the size of the left-hand-side matrix as shown in the following command line session > clear A % there is now no A matrix > A(2,4)=1 % assign 1 to 2,4 entry of A A = [Matrix] 2 x 4 0 0 0 0 0 0 0 1 > A([1,2],[1,2])=fix(5*rand(2,2)) % assignment changes A = [Matrix] 2 x 4 % submatrix of A 4 1 0 0 1 2 0 1 > A(:,1)=8 % ":" stands for all indices, here all rows of A A = [Matrix] 2 x 4 8 1 0 0 8 2 0 1 > A(:,end) % "end" stands for the last index ans = [Matrix] 2 x 1 0 1 > A(:,end+1)=[4;5] % adding a new column through assignment A = [Matrix] 2 x 5 8 1 0 0 4 8 2 0 1 5

When an expression A(B) or A(B,C) is not the left member of an assignment, then it stands for a submatrix extraction and its evaluation builds a new matrix. > A=fix(10*rand(3,7)); % fix: integer part of random 3x7 matrix > B=A([1,3],end-1:end) % extracts submatrix using rows 1,3 and % last two columns of A B = [Matrix] 2 x 2 7 6 2 1

When B and C are boolean vectors and A is a numerical matrix, A(B) and A(B,C) specify a submatrix of matrix A where the indices of the submatrix are those for which B and C take the boolean value 1. This is discussed further in the section on boolean matrices. Three dimensional arrays are manipulated the same ways that one and two dimensional arrays are manipulated except many OML functions are unable to produce or

2.1 OML Objects

15

manipulate three dimensional arrays. For example, randn(2,2,3) produces an error message. Also matrix addition, matrix multiplication, and multiplication of a matrix by a scalar can not be applied to three dimensional arrays. However, some functions that operate element-wise on matrices such as exp, abs, sin can be applied to three dimensional arrays. Three dimensional arrays can be useful in manipulating data as will be seen later. The next script creates a three dimensional array and then shows how it is output using slice. for i=1:3 for j=1:3 for k=1:3 M(i,j,k)=i+j+k; end end end size(M) M

Which gives the size of M and then lists it. ans = [Matrix] 1 x 3 3 3 3 M = slice(:, :, 1) = [Matrix] 3 x 3 3 4 5 4 5 6 5 6 7 slice(:, :, 2) = [Matrix] 3 x 3 4 5 6 5 6 7 6 7 8 slice(:, :, 3) = [Matrix] 3 x 3 5 6 7 6 7 8 7 8 9

2.1.1.2

Elementary Matrix Operations

Unless stated otherwise the remainder of this book will only consider scalar matrices in OML which are one or two-dimensional matrices. Matrices in OML have entries that are either real numbers coded as floating-point double precision entries (double) or complex numbers coded as a couple of floating-point double-precision numbers. Their type is called double (double value returned by the class function).

16 Table 2.2 Operator precedence | & ~ ==, >=, , < ,, ~= +,+,.*, ./, .\, .*., ./., .\. , *, /, /., \. ˆ,** , .ˆ , .** ’, .’

2 Introduction to OML

element-wise logical or element-wise logical and logical not comparison operators binary addition and subtraction unary addition and subtraction “multiplications” and “divisions” power transpose

Cells are a way to define “matrices” of other types and are discussed later in Section 2.1.5. As expected, the type double is the one for which the highest number of operators and functions exists in OML. Table 2.2 contains common operators for matrix types and in particular numerical matrices. If an operator is not defined for a given type, it can be overloaded. That is, you can define an operator with the same name that does apply to that type. The operators in the table are listed in increasing order of precedence. In each row of the table, operators share the same precedence with left associativity except for the power operators, which are right associative. Operators whose name starts with the dot symbol “.” generally stand for termby-term (element-wise) operations. For example, C=A.*B is the term-by-term multiplication of matrix A and matrix B, which is the matrix C with entries C(i,j)= A(i,j)*B(i,j). Note that these operators include many important equation-solving operations such as finding least square solutions. The following calculations illustrate the use of several of these operators. > A=(1:3)’*ones(1,3) % transpose and usual matrix product A = [Matrix] 3 x 3 1 1 1 2 2 2 3 3 3 > A.*A’ % multiplication tables using a term by term product ans = [Matrix] 3 x 3 1 2 3 2 4 6 3 6 9 > t=(1:3)’;m=size(t)(1,1);n=3; > A=(t*ones(1,n+1)).ˆ(ones(m,1)*[0:n]) % term by term A = [Matrix] 3 x 4 % exponenation to build Vandermonde matrix 1 1 1 1 1 2 4 8 1 3 9 27 > A=[1,2;3,4];b=[5;6]; > x=A\b % solving linear system Ax=b x = [Matrix] 2 x 1 -4.00000

2.1 OML Objects

17

4.50000 > norm(A*x-b) % check answer with norm of Ax-b ans = 0 > A1=[A,zeros(size(A))] A1 = [Matrix] 2 x 4 1 2 0 0 3 4 0 0 > x=A1\b % underdetermined system. Gives minimum norm solution x = [Matrix] 4 x 1 -4.00000 4.50000 0.00000 0.00000 > norm(A1*x-b) ans = 5.32907e-15 % residual is numerically zero > A1=[A;A] A1 = [Matrix] 4 x 2 1 2 3 4 1 2 3 4 > x=A1\[b;7;8] % overdetermined system. Least squares solution x = [Matrix] 2 x 1 -5.00000 5.50000 > norm(A1*x-[b;7;8]) % Find norm of residual ans = 2

As seen above there are a large number of linear algebra commands. Many of these commands can be accessed through commands like A\b or through text commands. These commands fall roughly into three groups. Those that create a matrix of a certain type given certain parameters, those that take a matrix and compute new matrices from it, and those that carry out linear algebra operations. A full list is in the OML help. Here some of the more important commands are given. Among those that create a new matrix are 1. tril: Creates a lower triangular matrix from given data. 2. triu: Creates an upper triangular matrix from given data. 3. diag: Diagonal matrix. Among those that compute a new matrix are 1. 2. 3. 4. 5. 6. 7. 8. 9.

chol: Cholesky decomposition. eig: Eigen decomposition, eigenvalues and eigenvectors. expm: Matrix exponential. inv: Compute the inverse matrix. kron: Compute the Kronecker product of two matrices. linsolve: Solve the linear systems of equations. lu: LU decomposition. pinv: Compute the matrix pseudo-inverse [12]. qr: QR decomposition.

18

2 Introduction to OML

10. reshape: Reshape a matrix. 11. schur: Schur decomposition. 12. svd: Singular value decomposition. Among the several functions that return scalar values from a matrix are 1. 2. 3. 4. 5.

cond: Compute the condition number of a matrix. det: Compute the matrix determinant. norm: Compute matrix and vector norms. rank: Compute the rank. trace: Compute the trace. To illustrate the use of some of these commands consider the following script,

A=rand(3,5); B=[A;2*A]; % create 6x5 matrix b=1:1:6; % create a 1x6 matrix sol=linsolve(B,b’) % solve Bx= transpose of b r=rank([B,b’])-rank(B) if r==0 ’system is consistent’ elseif r>0 ’not consistent’ end D=pinv(B); % compute generalized inverse sol-D*b’ %verify linsolve gave least squares solution ’cond(B)’ cond(B) ’singular values’ svd(B)

which upon being executed gives Warning: rank deficient matrix in argument 1; matrix does not have full rank in call to function linsolve at line number 4 sol = [Matrix] 5 x 1 % least squares solution -0.02526 -0.91791 0.97720 1.52986 1.66890 r = 1 ans = not consistent ans = [Matrix] 5 x 1 % verifies least squares solution -4.99600e-16 -1.55431e-15 -6.66134e-16 4.44089e-16 1.11022e-15 ans = cond(B) ans = 6.45323917e+16 % large condition number ans = singular values ans = [Matrix] 5 x 1 % rank well conditioned 5.33957e+00 1.48911e+00

2.1 OML Objects

19

9.96415e-01 3.56515e-16 8.27424e-17

Here the svd was used to show the problem was well conditioned as a least squares problem since there was a large difference between the singular values near zero and the larger singular values. There are also commands which can produce a smaller sized matrix. 1. sum: Sum of a vector or column. 2. min: Minimum of a vector or column. 3. max: Maximum of a vector or column. If any of these three commands is applied to a row or column vector, then the operator is applied to the entire vector. However, if the command is applied to a matrix, then the operation is carried out column wise. To illustrate running the script A=[1 2 3;4 5 6] sum(A) B=[1 2 3] C =[1;2;3] min(C) min(B)

produces A = [Matrix] 2 x 1 2 3 4 5 6 ans = [Matrix] 1 5 7 9 ans = 21 B = [Matrix] 1 x 1 2 3 C = [Matrix] 3 x 1 2 3 ans = 1 % min of ans = 1 % min of

3

x 3 % column wise sum of A

3 1

entire row B entire column C

Some times there are multiple ways to carry out the same matrix calculation. For example, A\b gives the solution of Ax = b. However, this same request can also be carried out by x=linsolve(A,b). However, linsolve allows for options with a call of the form linsolve(A,b,opts) where opts is a structure that tells the solver something about the matrix. Currently the two options are positive definite (POSDEF) and rectangular (RECT). These need to be structures. To illustrate how much this can speed up computation we generate a 500 × 500 positive definite matrix A and time the solution with and without options. Since the matrix is generated randomly its rank is checked to verify that it is nonsingular. Time elapsed is found by using tic which starts the clock and toc which gives the elapsed time since tic. The script is

20

2 Introduction to OML

D=randn(500,500); B=randn(500,1); A=D’*D; rank(A) tic x1=A\B; toc norm(A*x1-B) opts.POSDEF=true; tic x2=linsolve(A,B,opts); toc norm(A*x2-B)

This produces the output ans = 500 Elapsed time is 0.609 seconds. ans = 5.26564e-09 Elapsed time is 0.031 seconds. ans = 5.02259e-09

The algorithm that exploited the positive definiteness was almost 20 times faster than the standard algorithm. It is also seen that the solutions had comparable accuracies. Note that the larger A is, the less accurate one should expect to be able to compute the solution unless A has some special structure. The Kronecker product is useful in constructing larger matrices from smaller ones and appears in some numerical algorithms. If A is m × n and B is p × q, then the Kronecker product is a pm × nq matrix. It is a p × q block matrix whose i j block is ai j B. For example, > kron([1 2;3 4;5 6],[1 1;2 2]) ans = [Matrix] 6 x 4 1 1 2 2 2 2 4 4 3 3 4 4 6 6 8 8 5 5 6 6 10 10 12 12

diag can be used to extract the diagonal of a matrix as illustrated earlier or to create a diagonal matrix. The diagonal matrix does not have to be square. If the desired matrix size is omitted, then the size is determined by the number of diagonal elements provided. > diag([1 2 3]) ans = [Matrix] 3 x 3 1 0 0 0 2 0 0 0 3 > diag([1 2 3],5,4) ans = [Matrix] 5 x 4 1 0 0 0 0 2 0 0

2.1 OML Objects 0 0 0

0 0 0

3 0 0

21

0 0 0

2.1.2 Strings In OML you do not have strings, you only have characters. You can create a matrix of characters. What represents a string is a row vector of characters. A row vector of characters is referred to as a string in what follows. Strings in OML are delimited by single quotes “ ’” and are of class char. If the character " ’" is to be inserted into a string, this is done by using a double ’. This is not the same as the quote symbol ". Basic operations on strings are the concatenation operator “+” and the function length, which gives the string length. As expected, a matrix whose entries are strings can be built in OML and the two previous operations extend to string matrix arguments as do the usual row and column concatenation operators. A string is just a 1x1 string matrix whose type is denoted by char (as returned by class). Currently in OML a matrix of characters must have the same length rows when it is being constructed. It does not pad the rows so that they have the same number of characters. To pad rows use the char command. > S=[’A’,’string’] % create a string S = Astring > class(S) ans = char > size(S) ans = [Matrix] 1 x 2 % string is a 1x7 matrix of characters 1 7 > length(S) ans = 7 > S=[S;’22’,’cats’] % rows must be same length to concatenate Error: could not create matrix > S=[S;’222’,’cats’] S = Astring 222cats > size(S) ans = [Matrix] 1 x 2 2 7 > length(S) ans = 7 > S=[’A’,’string’] S = Astring > S=char(S,[’22’,’cats’]) % cat operator does vertical % concaternation and pads lengths S = Astring 22cats > length(S) ans = 7

22

2 Introduction to OML

Table 2.3 Some string matrix functions strcat String concatenation toascii Conversion from string to ascii values String which consists of n spaces. blanks strfind Search for occurrences of a string in a string matrix remove leading and trailing white (blank) characters stripblanks strrep Searches and replaces all instances of a with a new pattern String substitution in a string matrix strsubst strsplit Tokenizes the string s with the given delimiter delim Splits string s at given delimiter, returns cell array with strtok elements substrings Remove blanks at the end strtrim toupper Changes lower case to upper case Changes upper case to lower case tolowerr length Length of string matrix entries

Some string matrix utility functions are listed in Table 2.3. Additional ones are given in the OML help. strtok splits the string at the given delimiter delim and returns a cell array whose elements are the substrings of string s. The next session shows how some of these functions can be used. Consider the script. A1=’Pie’; A2=’is’; A3=’good’; B=blanks(2); % create string with two blanks C=[A1,B,A2,B,A3] C=strrep(C,A1,’cake’) % change Pie to cake strfind(C,’o’) % find where o is C=strrep(C,’good’,’17’) % change good to 17 toupper(C) % make upper case tolower(C) % make lower case E=strtok(C,’1’) % string before the 1 toascii(E) length(E) % find length E=strtrim(E) % remove blanks at end of string length(E) % find new length

which results in the output C = C = ans 12 C = ans ans E = ans

Pie is good cake is good = [Matrix] 1 x 2 13 cake is 17 = CAKE IS 17 = cake is 17 cake is = [Matrix] 1 x 10

2.1 OML Objects 99 ans E = ans

97 107 101 = 10 cake is = 8

23 32

32

105

115

32

32

2.1.3 Boolean Matrices A boolean variable can take only the two values 1 for “true’ and 0 for “false”. Two predefined OML variables true and false respectively evaluate to 1 and 0 and can be used to build boolean matrices, for example through the use of concatenation operations. Comparison operators (==, >, >=, x=5; > if x>2 disp(’Hello’) end % test if x>2 Hello

then display "Hello"

The following OML session shows simple instructions involving booleans. In particular, it is seen that even though matrix booleans are not coded as numbers, they can be used in numerical computations without needing any conversion. > ˜(1>=2) ans = 1 > true & true ans = 1 > x=-10:0.1:10; > y=((x>=0).*exp(-x))+((x exp([true,false]) % automatic boolean to scalar conversion ans = [Matrix] 1 x 2 2.71828 1.00000 > exp([1,0]) ans = [Matrix] 1 x 2 2.71828 1.00000

The following script shows the difference in && and & and | and ||. A=[1 0 -3];B=[1 1 0];k=3; A&B A&&B false && k(4)

24

2 Introduction to OML

A|B A||B

Running it gives the following. %% are comments added to output. ans 1 0 ans ans ans 1 1 ans

= [Matrix} 1 x 3 0 %% element-wise and = 0 %% false & false is false =0 %% k(4) did not generate an error message since not evaluated = [Matrix] 1 x 3 1 %% element-wise or =0 %% false or false is false.

Two other useful commands are all and any. If all is applied to a matrix with one row or one column, then it is 0 if any entries are zero and 1 if all entries are nonzero. If it is applied to a matrix, then it is applied to each column creating a boolean vector. any is 1 if any entries are nonzero and 0 if all entries are zero. The full syntax of all is z=all(M) z=all(M,k)

where k specifies how many columns of M to use. any has a similar syntax and is also applied column wise to matrices which are not just a row or column. It was mentioned previously that submatrix extraction can be done with boolean vectors. This is illustrated in the following session, where the function find, which returns the indices of the true entries of a boolean matrix is also introduced. > A=fix(10*rand(1,7)) % make a 1x7 matrix A = [Matrix] 1 x 7 5 5 7 8 6 8 5 > A>=6 % test which values >= 0 gives a boolean matrix ans = [Matrix] 1 x 7 0 0 1 1 1 1 0 > A(A>=6) % extract those values >= 6 ans = [Matrix] 1 x 4 7 8 6 8 > A(A>=6)=0 % use boolean to set some entries equal to zero A = [Matrix] 1 x 7 5 5 0 0 0 0 5 > I=find(A==0) % find indices of A which are = 0. I = [Matrix] 1 x 4 3 4 5 6

2.1.4 Polynomial Matrices Polynomials are OML objects. They are a vector of coefficients listed from highest powers to lowest. Thus [0 1 2 3] and [1 2 3] both represent x 2 + 2x + 3.

2.1 OML Objects

25

Most operations available for constant matrices are also available for polynomial matrices. A polynomial can be defined using the OML function poly. It can be defined based either on its roots or its coefficients, as can be seen from the following OML session. If p=poly(A), then for a vector A, p is a polynomial with roots A. If A is a square matrix, then poly(A) is the coefficients of the characteristic polynomial of A. > p=poly([1 2 3]) % polynomial constructed from roots p = [Matrix] 1 x 4 1 -6 11 -6 > A = [1 1 2;0 3 1;1 -1 2]; > p=poly(A) % characteristic polynomial p = [Matrix] 1 x 4 1.00000 -6.00000 10.00000 -2.00000 > polyval(p,1) % evaluate polynomial p at 1. ans = 3 > roots(p) % find roots of polynomial p ans = [Matrix] 3 x 1 2.88465 + 0.58974i 2.88465 - 0.58974i 0.23071 + 0.00000i

Polynomials can be multiplied by using the conv function. If they are of different length, then the smaller one needs to have zeros added on the left side to make them the same length. > p1=poly([1 2]) % define poly p1 with roots 1, 2 p1 = [Matrix] 1 x 3 1 -3 2 > p2=poly([3 4 5]) % define poly p2 with roots 3, 4, 5 p2 = [Matrix] 1 x 4 1 -12 47 -60 > p1+p2 Error: incompatible dimensions % cannot add since different % lengths of coefficient vectors > [0,p1]+p2 % add zeros to left of shorter one and you can add ans = [Matrix] 1 x 4 1 -11 44 -58 > p3=conv(p1,p2) % multiply poly p1 and p2 p3 = [Matrix] 1 x 6 1 -15 85 -225 274 -120 > roots(p3) % verify roots of product are roots of factors ans = [Matrix] 5 x 1 5.00000 4.00000 3.00000 2.00000 1.00000

26

2 Introduction to OML

2.1.5 Structures and Cells Cell arrays are generic data containers. They are similar to matrices in that they have rows and columns, and specific elements can be accessed via one or more indices. The major difference is that the data in cell arrays does not have to be homogeneous. A cell can store a matrix, string, scalar, or even another cell array. Cell arrays are defined using the { } operators. Elements in cell arrays are separated by commas (or spaces) and semi-colons (or newlines), just like matrices. To access the contents of a particular cell, the { } operators are used again. Elements can be directly assigned into cells using two different syntaxes, both involving the { } operators such as a(2,2) = [1,2,3] or a2,2 = [1,2,3]. These two statements are equivalent. The size function can be used to determine the number of rows and columns in a cell array (just like for other entities). To delete cells in a cell array, set the index (using the ( ) index) of the spot being deleted to [ ]. For example a(2,2) = {[]}. To set a cell to an empty matrix, set the index (using the { } index) of the spot being set to an empty matrix to [ ]. Thus for a2,2 = [] an empty cell is created using just curly braces ({ }) such as a={}. > A={[1 2 3],’dog food’;rand(2,2),’cat’} A = { [1,1] [Matrix] 1 x 3 1 2 3 [1,2] dog food [2,1] [Matrix] 2 x 2 0.84725 0.42365 0.62356 0.64589 [2,2] cat } > class(A) ans = cell > A(1,1) ans = { [1,1] [Matrix] 1 x 3 1 2 3 } > A(1,2) ans = { [1,1] dog food }

Structures are a data type similar to cells. However, where cells use numeric indices to refer to specific pieces of data, structures use strings. These strings refer to entities called fields. Each field has its own value which can be of any datatype. Fields must be valid identifiers.

2.1 OML Objects

27

For example, to track data about students, the following structure could be used: student.name = ’Harry’ student.age = 22 student.id = 9028390911

Structures can be combined to make an array of structures, as to make a database of information. One way of doing this is to index to the end of the structure array and add the new information to that index of the array. student(end+1).name =’Nicole’ student(end).age = 21 student(end).id = 90294067

Another way to make a structure array is to combine multiple structures together in an array. However, there must be the same number of fields for this to work. stArray = [struct1 struct2]

A field inside a structure may contain another structure. The fields inside the child structure are accessed in the same manner as the parent, but they are placed after the parent, inner_struct.value = 5; outer_struct.data = inner_struct; outer_struct.data.value => 5

2.1.6 Functions Many OML functions have been used in the previous examples through function calls without precisely defining what a function is. A function is known through its calling syntax. For example, the calling syntax for the sine function sin is the same as that for the hyperbolic sine function sinh. A OML -coded function can be defined interactively using the keyword function at the start of the function and end at the end of the function. An elementary example is now looked at to give a feeling for the syntax. The following script defines a function called newfun of the variable x. The value of the function is denoted by y. Any other names may be chosen for x and y. Running function y=newfun(x) a=3; b=4; y=a*xˆ2+b; end newfun(4)

produces ans=52

28

2 Introduction to OML

However, in this example the variables a and b are only defined inside of newfun. It is often desirable to have variables defined and then used by a number of functions. This can be done by a=3; b=4; function y=newfun2(x,a,b) y=a*xˆ2+b; end newfun2(4)

and now the values of a, b are known in the general workspace. A function can also be passed on by assigning it a handle say myhandle=@newfunc

The @ operator can also be used to define a function. For example, newfun2 could also be defined by newfun2 = @(x,a,b)

a*xˆ2+b

However, one often wants to work with a function with some of its variables fixed. This is done through anonymous functions. The following script defines variables a and b and the function newfun(x,a,b). It then assign a name which defines a function just in terms of x for those values of a, b. It then verifies that changing a, b does not change the anonymous function. a=3; b=4; function y=newfun(x,a,b) y=a*xˆ2+b; end anonfun = @(x) newfun(x,a,b) anonfun(4) a=5;b=7; anonfun(4)

which gives the output anonfun = anonymous ans = 52 ans = 52

If it is desired to have the anonymous function be a function of say x and b one could write anonfun = @(x,b) newfun(x,a,b). Anonymous functions can also be used directly with formulas as in c=3; quad=@(x) 4*xˆ2-c*x +cˆ2; quad(2)

It is also possible to use anonymous functions as variables in other functions as shown in the next session. This session also illustrates that the same syntax works for both functions and matrices.

2.1 OML Objects

29

> function y=myeval(x,@g) y=g(x) end Syntax error at line number 1 near character position 1 % ignore > myeval(0,@cos) % g is a function giving g(0) ans = 1 > v=rand(1,5) v = [Matrix] 1 x 5 0.64589 0.38438 0.43759 0.29753 0.89177 > myeval(3,v) % function call and matrix extraction have ans = 0.43758721 % same syntax

As with other variables, functions can be removed or masked by assignment. For example, if a session starts with the command sin=4, then the sin variable is 4 and no longer the sin primitive. However, primitives and OML functions available through libraries (for example those provided by OML default libraries) are just hidden by this mechanism. If sin is cleared by the command clear sin, then the sin primitive will return to the current environment. > sin=[1,5]; > sin(2) % sin function is hidden by the sin variable ans = 5 > clear sin % clear the sin variable > sin(2) % sin primitive is found and cleared. ans = 0.909297427

OML-defined functions are looked up inside the list of paths. To examine the current paths, use the command path. to add a new path use the command addpath. The command addpath(’directory’) requires the directory to already exist. For saving or loading data files, if the absolute path of the file is not specified, the current directory is used. The current directory can be obtained using the command pwd. It can be changed with the command cd. The files for scripts and functions should end in .oml. The current directory is by default in path, and at the top of it so it is searched before any other path folder. rmpath can be used to remove a folder from path but the current directory cannot be removed.

2.2 OML Programming An OML program is a set of instructions to be executed in a specific order. These instructions can be typed one by one at OML’s prompt, but they can also be placed in an ASCII file (using for example OML’s built-in editor). Such a file is called a script and may contain function definitions even though this is not the usual way of defining new functions in OML. By convention, OML script file names are terminated with the file extension .oml. As mentioned earlier scripts and functions are looked up in paths. For example, to run a script myscript.oml already in a directory in path, it suffices to type

30

2 Introduction to OML

myscript in OML. A function named foo already defined in foo.oml in path may be used directly as foo(z) where z is an acceptable input for foo. The function even comes back after a clear. Note that for a file to define a function it must contain only function definitions with one of the functions having a name matching the name of the file. This function is then the only one that can be used, the others can only be used inside the file and are not visible outside. This is the normal good programming way to define functions. However, if there is a script with several functions in it, all the functions will all be available after running the script. Scripts open in the OML editor can also be executed by clicking Start. The Start button applies to the active script (in case of multiple scripts, the active one is displayed on top and its name is displayed in black). You can also execute a script with CTRL+E, or by right-clicking on the file and selecting Run File. You can select a part of the script (in the OML editor), right-click, and press Run Selection. This executes only the line(s) selected. Once a script is executed, all functions defined in the script are also available from the Command window, that is, they can be called from there, too. For example, the following script function y=myfun(A) y=A.*A end Z=[1,2;1,3] w=myfun(A)

was saved under the name example.oml. The script can be run by opening this file in the OML editor and clicking Start. Equivalently the script can be run using the run command as follows1 > run example.oml

This results in Z = [Matrix] 2 x 2 1 2 1 3 w = [Matrix] 2 x 2 1 4 1 9

The function myfun still is there as shown by > myfun(3*eye(4,4)) % myfun still available in the workspace ans = [Matrix] 4 x 4 9 0 0 0 0 9 0 0 0 0 9 0 0 0 0 9

Iteration and branching instructions are a fundamental part of programming, so we begin by looking at these instructions in OML. 1 If the file is in a directory defined in path or in the current directory, as it is assumed here, the script

can also be run by simply typing its name.

2.2 OML Programming

31

2.2.1 Branching Branching instructions are used to make block execution of code depend on boolean conditions. The simplest form of branching instruction in OML takes the following form if

end

Note that there is no “then” in OML. The block of instructions will be executed if the condition () evaluates to a boolean true (or equivalently 1). Since OML is a matrix language, the condition evaluation can be a boolean matrix or a scalar matrix. If it is a matrix, the condition is considered as a true boolean only if all the matrix entries are true boolean values or if all the scalar matrix entries are nonnull. Thus, implicitly is evaluated as an and(). The following session generates the logarithm of a random 3 × 3 matrix and checks whether it is real. Note that while this is an if-then in some languages, there is no then in OML. > A=log(rand(3,3)); % generate a 3x3 matrix > imag(A) % imaginary part of A ans = [Matrix] 3 x 3 0 0 0 0 0 0 0 0 0 > if imag(A)==0 % tests if all imaginary parts are zero disp(’A is real’) end A is real % this is output after entering previous three lines

In general OML supports conditional execution of statements using the if/elseif/ else construct. if condition1 block1 elseif condition2 block2 elseif conditionN blockN else blockElse end

Each condition is an expression. If the expression evaluates to a non-zero (for example, true) value, the code in that block is executed. The conditions are tested in order. At most one block will be executed for each set of if statements. The elseif and else statements are optional. The blockElse is run only if no other blocks were run. The following example has three cases > x=5 x = 5 > if x==4

32

2 Introduction to OML

disp(’it is 4’) elseif x==5 disp(’it is 5’) else disp(’it is not 4 or 5’) end it is 5 % this is output after previous commands

As soon as both evaluated expressions evaluate to equal values (== operator), the execution branches to the associated block. If no equal case is detected, then the else block, if present, will be executed. switch is just like an if-else statement but can only compare one variable. Each possibility is represented with a ‘case’ with the default case being ’otherwise’. The syntax is switch X case a statement1 case b statement2 otherwise statement3 end

As an example suppose that X is an integer and we want to check if it is between 1 and 8 and whether it is even or odd. Running the following script X=6 switch X case {1, 3, 5, 7} disp(’odd’) case {2, 4, 6, 8} disp(’even’) otherwise disp(’Not between 1 and 8’) end

produces even

A convenient type of branch for debugging is the try-catch. The try-catch block allows you to stop errors from being returned, and allows another block of code to execute instead of the error. The basic syntax is try tryBlock catch catchBlock end

The try/catch statement tries to run the code in the tryBlock, but if an error occurs, it will run the code in the catchBlock. As an example,

2.2 OML Programming

33

> A=rand(2,2); > B=rand(3,3); > try Z=A+B catch disp(’oops cannot do that’) end oops cannot do that % this is output after previous lines

Error messages can be generated and function execution stopped by using the error function. Consider the function function y = myfun(x) if x < 6 disp(’less than 6’) else error(’x is too big’) end end

which has been run. Then entering myfun(3) and myfun(7) on the command line gives > myfun(3) less than 6 > myfun(7) Error: x is too big in function myfun at line number 5

2.2.2 Iterations Loops are used to perform the same set of statements several times. For execution efficiency, one should carefully check to see whether iterative control structures can be replaced by matrix operations, which usually execute faster. The for loop runs the statements a set number of times based on the number of elements in the collection found on the first line of the for loop. for = end

The instruction is evaluated once. Then, the inner block will be iteratively executed, and at each iteration the variable will take a new value. If the instruction evaluation gives a matrix, then the number of iterations is given by the number of columns, and the loop variable will take as value the successive columns of the matrix. For example, > A=[1 2;3 4]; > for j=A disp(j) end 1

34

2 Introduction to OML

3 2 4

If the instruction evaluation gives a cell, then again the number of iterations is given by the number of columns and the loop variable will take as value the successive columns of the cell as illustrated by the next session > c={[1 2],’a’;’b’,3} c= { [1,1] [Matrix] 1 x 2 1 2 [1,2] 1 [2,1] b [2,2] 3 } > for j=c j end j = { [1,1] [Matrix] 1 x 2 1 2 [2,1] b } j= { [1,1] a [2,1] 3 }

If the instruction evaluation gives a list, then the number of iterations is given by the list length, and the loop variable will take as value the successive values of the list elements. As a simple example > for j=1:3 disp(j) j=j+4 end

results in 1 j = 5 2 j = 6 3 j = 7

If the loop variable is not changed, the final value of the loop variable is retained after the loop is completed. However, in the example above j is now 7. On the other hand,

2.2 OML Programming

35

> for j=1:3 disp(j) k=j+4 end

would finish with j = 3 and k = 7. Sometime a statement is executed while a condition holds. The while loop runs the statement until a condition is no longer met. while end

is an expression that is evaluated each time the loop is run. If evaluates to a nonzero value, the statements in blockWhile are run and the process is repeated. If condition evaluates to a zero value (false), the statements in are skipped. The number of times the loop is executed depends on and . If is initially false, the loop is never executed. As an example, > a=2; > while a x=1; > while exp(x)˜=Inf; x=x+1; end > [exp(x-1),exp(x)]==Inf ans = [Matrix] 1 x 2 0 1

36

2 Introduction to OML

2.2.3 OML Functions We have already introduced functions. We now will look at them more carefully. It is possible to define new functions in OML. What distinguishes a function from a script is that a function has a local environment that communicates with the outside through input and output arguments. A function is defined using the keyword function followed by its calling syntax, a set of OML instructions, and the keyword end. More precisely, the following form of syntax is used to define a function: function [,,...]=(,... ,...) end

Defining a function requires the function name (), the list of calling arguments (,,...), and the list of variables that are used to return values (,,...). Note that a function can return more than one value. Calling a function is done as follows: (,,...)

or [,,...,]=(,,...)

In the first case the returned value is the value of the first returned argument by the function evaluation. In the second case the p first returned values of the function evaluation will be copied in the p variables whose names are given by [,,...,]. When a function is called, the expressions given as arguments are first evaluated and their values are passed to the function evaluation. Thus, OML uses a calling by value mechanism for all argument types. However, if an argument of a calling function instruction is a variable name and if that variable is not changed in the function evaluation body, then the variable will not be copied during the function call. The following session gives additional examples of defining a function and evaluating it. The first is an example of a function involving strings. The second function defines the factorial function. function y=f(A) B=sign(A); B=num2str(B) B=strrep(B,’-1’,’-’); B=strrep(B,’1’,’+’); y=strrep(B,’ ’,”); end A=randn(1,8);

2.2 OML Programming

37

Then f(A) produces the output B = -1 1 1 ans = -++—–

-1

-1

-1

-1

-1

> function y=myfact(x) if x myfact(5) ans = 120

This next session defines several functions and illustrates the rules for searching variable values when a function is evaluated. This is important but quite technical and can be omitted by first-time readers. > function y=f(x) % define function with one input & one output y=2*x; end > f(5) ans = 10 > f(5,7) % too many inputs Error: invalid function call; incorrect number of input arguments > f([5,7]) % one vector input is ok ans = [Matrix] 1 x 2 10 14 > [a,b]=f(3) % two many outputs Error: missing return values > [a,b]=f([5,7]) % too many outputs Error: missing return values > a=f([5,7]) % one output which is a vector a = [Matrix] 1 x 2 10 14

As another example > function y=f(x) % new function f z=x end > y=89; > z=67; > f(89) z = 89 % this is done inside the function > z % value of z not changed since not output z = 67

If the function defined has n calling arguments, then you do not normally have the right to call a function with more than n calling arguments. Using varargin and varargout it is possible to define functions without specifying the number of arguments of a function. In the most general form, a definition of a function with both variable input and output arguments would be:

38

2 Introduction to OML

varargout = function myfunc(varargin)

Inside the function body, the varargin variable will be an OML list that contains as elements the values of the arguments from the nth one to the last one. The following function can be called a priori with any number of inputs and outputs. For the outputs it is the function content that sets the number. > function [a,b,varargout]=myfun(c,varargin) a=c; b=[c,varargin{:}]; varargout={a,varargin{1}}; end > [a,b,g]=myfun(1,2) % here varargin is a scalar 2 a = 1 b = [Matrix] 1 x 2 1 2 g = [Matrix] 1 x 2 % varargout is a scalar 1 2 > [a,b,g]=myfun(1,2,3) % varargin is 2,3 a = 1 b = [Matrix] 1 x 3 1 2 3 g = [Matrix] 1 x 3 % varargout is a 2 vector 1 2 3

Note that only one varargin and one varargout can be in the list of input and output arguments of the function definition and they must be the last ones in the list. Inside the function varargin and varargout are cell arrays. The elements of a cell array can be extracted using the { } operator (note that ( ) extracts subcells). In particular varargin{:} generates a list, separated by commas, that you can use to construct other cells, call functions, or as is the case here construct a vector. The varargout should also be constructed as a cell array. This is done here. Note that varagrout is a cell with 2 elements. It is helpful to be able to determine the number of inputs and outputs when the function is called. nargin gives the number of inputs and nargout gives the number of outputs. So the nargout of this function can at most be 4 (the function produces 4 return variables). We cannot call the function with more than 4 return values but we can call it with less. Thus the function can be called as follows > [x,y,z,t]=myfun(3,2,8,12) x = 3 y = [Matrix] 1 x 4 3 2 8 12 z = 3 t = 2

Changing a variable in a calling environment, as a side effect of a function call, can sometimes be useful. This is achieved in OML through the use of global variables. The global keyword can be used to declare a global variable. Once a variable is declared global in an environment its value can be changed from within that environment. For example, a global x statement must be present in the body definition of a function if the function is to be used to modify this global variable x.

2.2 OML Programming

39

> global a > isglobal(’a’) ans = 1 > a ans = [Matrix] 0 x 0 > function f(z) a=fix(10*rand(1,3)); end > f(2) > a %without global inside function value of a outside unchanged ans = [Matrix] 0 x 0 > function f(z) global a % with global inside, value of a changed outside a=fix(10*rand(1,3)); end > f(2) > a a = [Matrix] 1 x 3 5 5 7

A variable in a function can also be declared persistent. The value of a persistent variable is remembered from one function call to the next. They are not changed by commands external to the function. In the following example the persistent variable counts how many times n the function y = x 2 is called and the function prints out x 2 , and n. The script defines the function mfun and calls it three times. Persistent variables start out as an empty matrix. function y=myfun(x) persistent n if isempty(n) n=0 end n=n+1; y=[xˆ2,n]; end myfun(2) n=6 % External use of n does not change persistent variable myfun(3) myfun(4)

Results in ans = [Matrix] 1 x 2 4 1 n = 6 ans = [Matrix] 1 x 2 9 2 ans = [Matrix] 1 x 2 16 3

When programming in any language, it is nearly impossible to write large programs without errors. Programming in OML is not an exception to this rule. A set of OML utilities helps users detect and correct bugs in their code. In particular, one can interrupt the execution of OML code using the command pause or clicking the Stop icon (a square) next to the Start icon.

40

2 Introduction to OML

Finally, it should be noted that the built-in editor also provides some debugging facilities. Functions can be defined inside the body of other functions. function y= myfun (x) function z = titi (u) z = u*u; end y = 3*titi(x); titi(4) end myfun(3) titi(4)

Inside defined functions share their scopes with the function in which they are defined. So all variables not passed as arguments are global within the confines of the outer function. Thus running the script above results in ans = 16 ans = 27 Unknown function: titi at line number 9

The function titi is known inside myfun but not outside of it. An inner function cannot be defined in a conditional branch, for example, using else.

2.2.4 User Defined C/C++ Functions One of the reasons that OML can solve so many problems quickly is that the functions provided with OML are precompiled C/C++ functions and for many problems most of the computational effort takes place using these functions. OML has the built in capability of adding precompiled C/C++ functions written by a user. Once the functions are incorporated they are used and called just like any other OML function. While the interface is to C/C++, the C/C++ functions can call Fortran routines. In fact, many of the matrix functions in OML are from the SLICOT library and are written in Fortran. The key is the OML command addToolbox which is entered on the command line. It has the syntax addToolbox(’fullpath/file.dll’)

Here the user defined C/C++ function has been compiled into a dynamic link library in file.dll and fullpath is the full path needed to locate the file. Under the Linux operating system, a shared object file.so will be used. The C/C++ function must take one input, which will come from Compose and one output which will be sent back to Compose. The input and output can be a scalar, a matrix, or a structure. OML is an untyped language so the function being added will need to have all needed type declarations.

2.2 OML Programming

41

There is also a binary compatible interface. The benefit of using this interface is that the objects are size-invariant. This means that the code you compile can be used with any version of Compose that supports this interface (2017.2 or later), not just the version that the header file came from. It also allows compilation with different tools than the Compose executable uses. Any toolbox using this interface consists of two parts. First is an initialization function that is called by Compose. This is how your toolbox’s functions get registered with Compose. The second part is the functions themselves. Examples illustrating this procedure for an additional function that will become a regular part of a Toolbox function, as opposed to a one time run, may be found in [17, 25]. Here, in order to illustrate what is involved, we give a simple example. In this example we define a new OML function replace with three input arguments: two scalars and one matrix. The function returns a matrix obtained by replacing the entries of the third argument that match the first argument by the second argument. The C/C++ program saved in the file replaceccode.cxx is given below #include "OMLInterfacePublic.h" class OMLInterface;

//Header

#ifdef OS_WIN extern "C" { __declspec(dllexport) int InitToolbox(OMLInterface* eval); } #else extern "C" { int InitToolbox(OMLInterface* eval); } #endif bool replace(OMLInterface*, const OMLCurrencyList* inputs, OMLCurrencyList* outputs); int InitToolbox(OMLInterface* eval) { eval->RegisterFunction("replace", replace); // myfunc needs to be forward declared return 0; } bool replace(OMLInterface* eval, const OMLCurrencyList* inputs, OMLCurrencyList* outputs) { // check proper number of inputs if (inputs->Size() != 3) eval->ThrowError("Incorrect number of inputs"); const OMLCurrency* input1 = inputs->Get(0); const OMLCurrency* input2 = inputs->Get(1); const OMLCurrency* input3 = inputs->Get(2); // check proper input types

42

2 Introduction to OML if (input1->IsScalar() && input2->IsScalar()&& input3->IsMatrix()) { double d1 = input1->GetScalar(); double d2 = input2->GetScalar(); const OMLMatrix* mtx = input3->GetMatrix(); const double* data = mtx->GetRealData(); int size = mtx->GetRows() * mtx->GetCols(); double* new_data = outputs->AllocateData(size); for (int j=0; jCreateMatrix(mtx->GetRows(), mtx->GetCols(), new_data); outputs->AddMatrix(result); } else eval->ThrowError("Invalid input type"); return true;

}

In the first part of the code we register the function replace with OML. The C function replace contains the actual code, which starts by checking the number of input arguments, throwing an error if the function is not called with three input arguments. Then it checks that the first two arguments are scalars and the last one a matrix. The input arguments are then read and the output matrix is generated by looping over the elements of the third input argument matrix and comparing them with the first argument. There are a number of OMLCurrencyList Methods which are listed and described in [25]. This file must be compiled to obtain a dynamic link library. This can be done, for example, under the Windows operating system by Microsoft Visual C++ compilers using the following command cl /LD /DOS_WIN replaceccode.cxx /link /DLL /OUT:librepfun.dll

Under Linux, a shared object needs to be created, for example as follows g++ -c -o replace.o -c -g -fPIC -frtti -std=c++11 replaceccode.cxx g++ -o librepfun.so -shared replace.o

Then, assuming the file librepfun.dll is in the folder C:/Users/ Mathematics/, the new function replace can be added using the following command: addToolbox(’C:/Users/Mathematics/librepfun.dll’)

The new replace function is now available and can be used for example as follows > b=replace(3,4,[1,2,3;3,4,5]) b = [Matrix] 2 x 3 1 2 4 4 4 5

2.2 OML Programming

43

Error is thrown if the function is call with wrong arguments > replace(3,4) Incorrect number of inputs at line number 1 > replace(3,4,’r’) Invalid input type at line number 1

Note that the replace function can be realized using basic OML operations as follows > a=[1,2,3;3,4,5]; > b=a;b(find(b==3))=4 b = [Matrix] 2 x 3 1 2 4 4 4 5

2.3 Input and Output Functions The default for OML commands is to show the results in the command window unless they create a graphic, and then the default is to show the result in a graphics window. However, it is often desired to have the result saved in a file or printed on a printer. This section discusses how to control the input and output of different types of data.

2.3.1 Display of Variables As already seen in previous examples, when a OML instruction is followed by a comma or a line feed, a display of the instruction evaluation result is provided. If instructions are ended by a semicolon or belong to the body of a function, then no display occurs. Explicit display of the value of a variable, or of the result of an instruction evaluation, is achieved by the function disp. > function y=f(x) a=2*pi; y=x+a; end > f(2); % a is not displayed > function y=g(x) a=2*pi; disp(a); y=x+a; end > g(2); % value of a is displayed 6.28318531

44

2 Introduction to OML

If you want to have a string printed out during execution of a function, this can be done with the printf command. Sometimes one wants values of variables inside of functions to be displayed or output to a file. This is done using fprintf and will be discussed later. The format used by disp and printf for displaying real numbers can be controlled using the OML format function.

2.3.2 User Input During Computation Often during a simulation it is important for the program to stop and request input from the user. One example is given later in Section 13.2.2.1. This is carried out by the input function. The input function writes a message and waits until the user provides the required input. Then it resumes calculation. For example running x=3; y=input(’What is your age:’) x*y

results in > What is your age:

If you then enter 57 and press the return key you get > What is your age:57 y = 57 ans = 171

2.3.3 Formatted Input and Output Several OML functions can used to perform formatted input-output (Table 2.4). The function fopen is an OML implementation of the standard C function fopen with the following syntax depending on what you wish to accomplish fileID = fopen(filename) fileID = fopen(filename, ’mode’) [fileID, msg] = fopen(filename, ’mode’) [filepath, filemode] = fopen(fileID)

Here filename is a string that denotes a file name. The mode argument is also a string, whose length does not exceed three (its default value is ’rb’) that describes Table 2.4 Input-output functions

fprintf fopen fclose

output a string matrix in a file open a file stream close a file stream

2.3 Input and Output Functions

45

the stream mode to be used. The input stream is obtained with ’r’ and the output stream with ’w’. Append mode is obtained by adding an ’a’ character, and a bidirectional stream for input and output is obtained with ’r’. An added ’b’ character will specify that streams are to be used in binary mode. The fclose function can be used to close opened input or output streams, It is possible to close all the opened streams using the instruction fclose(’all’). The formatted input and output functions are very similar to functions provided by the standard C input-output library. For example, the format specification follows the format specification of C functions. However, OML input-output formatted functions automatically take care of the matrix aspect of OML objects. When using a formatted output stream, the arguments of the conversion specifiers are searched in the rows of the OML arguments. When using a formatted input it is possible to specify the number of times the format has to be repeated, for example, up to the end of file. Thus it is possible using one read instruction to obtain a matrix, or a set of matrices, row after row: fwrite, fread Variables can be saved to a file and loaded back into the workspace using the save and load commands. The save command has the following syntax save(filename, variables) save(filename, variables, format) save(filename) save(filename, format) save filename

The inputs are as follows. filename is the path and the name of the mat file to read. It is a string. variable is a list of the variables to save, separated by commas. If no variable is specified, all variables are saved. format specifies the format of the file to save. If omitted, format 7.3 is assumed. Valid entries for format are ’-v5’ indicating v5 format and ’-v4’ indicating v4 format. What the path is will be machine dependent. The following script will create two variables and save to a file called file2.mat. Then it will change the variables in the workspace and verify they are changed. It will then load a variable back into the workspace with the load command and verify the variable is back to its original value. myfile=’C:/Users/Mathematics/file2.mat’; A=[1 2 3 4]; B=[0 2]; save(myfile,’A’); A=1;B=1; A B R=load(myfile,’A’) A

results in myfile=’C:/Users/Mathematics/file2.mat’; A=[1 2 3 4]; B=[0 2]; save(myfile,’A’); A=1;B=1; A

46

2 Introduction to OML

B R=load(myfile,’A’) A

If load is used as R = load(filename) R = load(filename, variable) load filename

then R is a Struct with values read from the file. Note that file2.mat is a data file that can be read by matlab or OML or Octave. Thus it is possible to pass binary data back and forth between OML and matlab or Octave using data files and save and load.

2.4 OML Graphics There are numerous OML graphics commands. Here we will first introduce some of the more basic graphics commands that are regularly used in simulation and modeling. Once users can generate the basic graphs they need, they start to want to do more sophisticated graphics. For these we will just give some general rules for performing graphics in the subsequent sections and give an example that illustrates a part of what is possible. Details can be found in the on-line manual.

2.4.1 Basic Graphing One of the first things that someone interested in modeling and simulation wants to do is to generate plots. These plots can be graphs of functions, surfaces, curves, or data. Readers familiar with other matrix-based environments will have no problem with OML graphics. OML offers control over how and where the graphics occur and how they look. But all this control can be confusing at first. In this section we show how to quickly and simply generate some of the more common types of graphics. The remaining subsections will describe how to modify the basic graphical output. The plot command generates two-dimensional graphs. Given vectors x = [x1 , . . . , xn ] and y = [y1 , . . . , yn ], plot(x,y) will plot the points {(x1 , y1 ), . . . , (xn , yn )}. There are several options for connecting the points, which can be specified using optional calling arguments. The default in plot is to connect them with a straight line with blue line segments. This can be changed by using formats and properties. The more general call would be plot(x,y,fmt,property,value,....)

2.4 OML Graphics

47

Fig. 2.1 Graph of sin t and cos t

fmt is a formatting string for the curve. It can be any combination for the following strings: 1. line style: ’-’, ’-.’, ’:’, ’--". 2. line color: ’r’, ’g’, ’b’, ’c’, y’, ’m’, ’w’, ’b’. 3. marker style: ’s’, ’o’, ’d’, ’x’, ’v’, ’ˆ’, ’+’, ’*’, ’.’. property controls other aspects of the graphics. For example to plot sin(t) and cos(t) with different colors and line styles on the same graph we could use > > > >

t=0:0.1:2; x=sin(t); y=cos(t); z=plot(t,x,’r’,t,y,’g+’)

which gives Figure 2.1. Figures can be saved either from the editor window of OML or using the saveas command. The syntax is as follows where plot3 is a three dimensional plot of a curve. f=figure; plot3(t,t.*sin(t)/5,t.*cos(t)/5) saveas(f,’f:/tmp/f.png’)

By default, plot or any other plotting command, creates a graphics window called Figure 1. This window can be cleared by the command clf which stands for clear figure. Additional calls to plot with no clearing commands or redirection of output will result in all plots being on the same graph with the new plot replacing the old plot. Axes will automatically be adjusted. It is of course possible to have many graphics windows at the same time in a OML session. A new window is created with the figure command. If it is desired

48

2 Introduction to OML

to have more than one figure plotted in the same window this is done by using the hold command after the first figure is plotted. Later we will give some of the ways that the appearance of a plot can be altered with OML commands. But it is important to note that graphics routines start with matrices and this sometimes creates problems. For example, > tt=0:0.1:3; > plot(tt,sin(tt))

will generate the graph of sin(t) on the interval [0 3]. However, > function y=myfun(t) y=sin(t)*sin(t); end > plot(tt,myfun(tt)) Error: incompatible dimensions

will produce an error message and not the graph of sin2 (t). The problem is that the function myfun has to be able to take the vector tt and evaluate it entry by entry. The following code will generate the graph of sin2 (t): > function y=myfun(t) y=sin(t).*sin(t); end > plot(tt,myfun(tt))

Plots of a surface z = f (x, y) can be done with the command surf which works much like plot in that it has the syntax surf(x,y,z), where x, y, z are vectors. The default for plot3 is for the graph to appear in a graphics window. There are a number of other OML graphing commands such as bar for bar graphs, contour plots in the plane using contour, contour plots on a 3D surface using contour3, polar plots in the plane using polar, 2D and 3D scatter plots with scatter and scatter3. There are a number of other commands described in the user’s guide such as loglog, semilogx, semilogy. The area plot, plots areas over each other. There are also OML commands for specifying the labeling and types of axes as well as inserting text into the graph.

2.4.2 Interpolation An important tool in working with data and approximations is interpolation either to generate a function or to graph. OML provides two functions for interpolation. They are interp1 and interp2. interp1 provides one dimensional interpolation. If x, y are vectors of x values and accompanying y values, and xi are x values where we want to get interpolated y values, then yi are the interpolated values. The calling syntaxes are yi = interp1(x,y,xi) yi = interp1(x,y,xi,method)

2.4 OML Graphics

49

yi = interp1(x,y,xi,extrap) yi = interp1(x,y,xi,method,extrap)

There are three options which are ’linear’: Returns the linear interpolation from the nearest neighbors. ’pchip’: Returns shape preserving piece-wise cubic Hermite interpolation. ’spline’: Returns the cubic spline interpolation. extrap is an option that allows xi to have values outside the interval from the largest to the smallest values in x. Extrapolation outside the interval where the data is can often lead to difficulties and bad estimates so it should only be done with care. noextrap does not allow extrapolation and is the default. Which interpolation is best will depend on the problem. For example, is it important to try and preserve properties like convexity? Is smoothness of the curve important? The following script illustrates the three kinds of interpolation in interp1 x=0:1:10; % data points in x y=[4 4 1 0 0 -2 0 0 3 4 4]; % values at these x xi=0:0.1:10; % where we want the interpolants xlin=interp1(x,y,xi,’linear’); xpch=interp1(x,y,xi,’pchip’); xspl=interp1(x,y,xi,’spline’); figure plot(xi,xlin); % linear interpolant plot hold plot(x,y,’bo’); % plot of data figure plot(xi,xpch); % pchip interpolant plot hold plot(x,y,’bo’); % plot of data figure plot(xi,xspl); % spline interpolant plot hold plot(x,y,’bo’) % plot of data

The results are plotted in Figure 2.2. It is also possible to directly plot using spline using yi=spline(x,y,xi). Note that if y is the same length as x, then it does the interpolation with not a knot.

Fig. 2.2 From left to right; linear, pchip, and spline plots of data

50

2 Introduction to OML

The clamped spline is evaluated when the length of y equals the length of x plus 2. In this case the extra values of y provide derivatives of the interpolation at the endpoints. The function interp2 provides two dimensional interpolation. That is, it interpolates values defined on a rectangular grid. Its syntax is z=interp2(x,y,z,xi,yi,’method’)

The method can be either ’linear’ or ’spline’. The x and y vectors (matrices) give all the x, y coordinates on the grid and z gives the values at those grid points. The following script will illustrate how the notation works. We will break the script up with discussion but the script is run all at once. Suppose that we set up a 3 × 4 grid so that there are 12 grid points. Let us take the possible x and y values as x=[0 1 2]; y=[0 1 2 3];

For each possible x there are 4 possible y values. It is useful to use the meshgrid function [X,Y]=meshgrid(x,y);

then X and Y are both 4 × 3 matrices, ⎡ ⎡ ⎤ 0 012 ⎢1 ⎢0 1 2⎥ ⎢ ⎥ X=⎢ ⎣0 1 2⎦ , Y = ⎣2 3 012

0 1 2 3

⎤ 0 1⎥ ⎥. 2⎦ 3

Thus the (x, y) coordinates of the i, j entry in the grid is given by the i, j entries of X and Y. The rest of the script defines the values Z on the grid, plots these values on the original grid, then defines a finer grid, uses interp2 to interpolate onto this finer grid and then plots the interpolated values on the finer grid. Z=cos(X.*Y); figure surf(X,Y,Z); xi=0:0.1:2; yi=[0:0.1:3]; % define finer grid [Xi,Yi]=meshgrid(xi,yi); Zi=interp2(X,Y,Z,Xi,Yi,’linear’); figure surf(Xi,Yi,Zi);

The results are shown in Figure 2.3.

2.4.3 Graphic Tour We start with a number of scripts to make a tour of OML graphics functionalities.

2.4 OML Graphics

51

Fig. 2.3 From left to right; Plot of original data, plot of data interpolated onto a finer grid

Fig. 2.4 Plot of (t, t sin(t)/5, t cos(t)/5)

2.4.3.1

Parametric Curve Plot in R3

The parametric plot of (t, t sin(t)/5, t cos(t)/5), on [−5 10] using a uniform grid of 1500 points is given by > t=-5:0.01:10; > z=plot3(t,t.*sin(t)/5,t.*cos(t)/5)

The graph appears in Figure 2.4. The graph may be rotated by putting the cursor in the graphics window.

52

2 Introduction to OML

Fig. 2.5 Plot of z = sinh(x) cos(y)

2.4.3.2

Plot a Surface in R3

The surface plot of z = sinh(x) cos(y) on −π ≤ x ≤ π , −π ≤ y ≤ π is created by the script x=linspace(-pi,pi,40); y=x; p=surf(x,y,sinh(x)’*cos(y));

The result is shown in Figure 2.5. Note that contour3 will produce a figure that looks like Figure 2.5. A two dimension contour plot of the same function can be produced by x=linspace(-pi,pi,40); y=x; p=contour(x,y,sinh(x)’*cos(y));

which produces Figure 2.6. 2.4.3.3

Plot a Histogram

Histograms can be plotted by the hist function. The hist function has the form hist(a,n) were a is a vector of data, and n is the number of bins to put the data in. The histogram then counts the number of values of a in each bin. To illustrate we generate a random set of 300 data points with a normal distribution and use 15 bins. a=randn(1,300) hist(a,15)

which produces Figure 2.7.

2.4 OML Graphics

53

Fig. 2.6 2D contour plot of z = sinh(x) cos(y)

2.4.3.4

Bar Plot

bar plots a function but uses vertical bars. For example to get a bar plot of sin(4 ∗ x) on [0 2] we could run the following script. This script produces the two Figures 2.8 and 2.9 in different windows. Note that the values of the independent variable determine the centers of the bars with the centers evenly spaced. x=0:0.2:2; bar(x,sin(4*x)) figure x=[0 0.2 0.4 1 1.1 1.2 1.6 2] bar(x,sin(4*x))

54

2 Introduction to OML

Fig. 2.7 Histogram plot of normal random data

2.4.3.5

Polar Plot in R2

The plot in polar coordinates of ρ = sin(2θ ) cos(2θ ) for 0 ≤ θ ≤ 2π is created by the following commands: > theta=0:.01:2*pi; > rho=sin(2*theta).*cos(2*theta); > polar(theta,rho)

The result is shown in Figure 2.10.

2.4.3.6

Scatter Diagrams

2D and 3D scatter plots can be done with scatter and scatter3. We illustrate with a scatter plot of 100 points whose x and y coordinates are independent normally distributed random values with mean 2. x has twice the variance of y. The result is shown in Figure 2.11 using scatter.

2.4 OML Graphics

55

Fig. 2.8 Bar plot of sin(x) on an even grid

Fig. 2.9 Bar plot of sin(x) on an uneven grid

A scatter plot in 3D of data normally distributed along the curve (t, t, by xv=randn(1,101); yv=randn(1,101); zv=randn(1,101); x=0:0.2:20; y=x; z=sqrt(x); scatter3(x+xv,y+yv,z+zv)

The result is in Figure 2.12.



t) is given

56

Fig. 2.10 Polar plot of ρ = sin(2θ) cos(2θ) Fig. 2.11 Scatter plot of normal data

2 Introduction to OML

2.4 OML Graphics

57

Fig. 2.12 Scatter3 plot of normal data

2.4.3.7

Filled Polygons

There are also commands for inserting squares or filled polygons into a figure. The command takes the form of fill(x,y,’c’). Here x, y are column vectors of the same size and (xi , yi ) are the corners of the polygon. The endpoint is automatically taken as x1 , y1 and does not have to be listed a second time. ’c’ gives the fill color. The same colors are available as for lines. That is, ’r’ for red, ’b’ for blue, ’g’ for green, ’k’ for black, ’y’ for yellow, ’m’ for magenta, and ’w’ for white. The default is that the corners of the polygons are not plotted. They can be plotted by adding ’s’ for square, ’x’ for cross, ’d’ for diamond, ’o’ for circle, or ’v’ for a triangle with point down. Thus ’rx’ would be red fill with an x at the corners. If the color is omitted, for example, just ’s’ is used, then the color is blue with squares at the corners. Text can be inserted with the text command. The fill is opaque so that newer objects can overlay previous ones. Note the wheels and the window in Figure 2.13 overlay the red area which was done first. If we run the following script figure i=0:0.1:1; x1=[1 1 1 2 2 5 5]; y1=[1 3 4 4 3 3 1]; x1c=0.5*sin(2*pi*i); y1c=0.5*cos(2*pi*i); xw=[1.2 1.2 1.5 1.5];

58

2 Introduction to OML

Fig. 2.13 Use of the fill command

yw=[3.1 3.5 3.5 3.1]; xs=[4.5, 4 5.5 5]; ys=[3, 3.5 3.5 3]; smx=0.5*x1c; smy=0.5*y1c; fill(x1,y1,’r’); hold fill(xw,yw,’w’) fill(x1c+1.5,y1c+1,’b’); fill(x1c+4.5,y1c+1,’b’); fill(xs,ys,’b’); fill(smx+4.7,smy+4.2,’g’); fill(smx+4.7,smy+6.2,’g’); text(2,6,’Train’)

we get Figure 2.13.

2.4.3.8

Vector Fields

It is also possible to plot vector fields for two dimensional differential equations. For example, given the differential equation x˙1 = −x2 − x13 x˙2 = x1 − x23 ,

(2.1a) (2.1b)

the following script draws the vector field in the box −2 ≤ x1 ≤ 2, −2 ≤ x2 ≤ 2.

2.4 OML Graphics

59

Fig. 2.14 Plot of vector field for (2.1) without and with the direction shown

function z=myf(x) z=[-x(2)-x(1)ˆ3,x(1)-x(2)ˆ3]; end figure plot(0,0) hold for i =-2:0.2:2 for j =-2:0.2:2 %plot(i,j,’bo’); s=myf([i,j]); sd=[i j]+0.4*s/(1+norm(s)); plot([i, sd(1)]’,[j, sd(2)]’); end end

produces the plot in the left side of Figure 2.14. If we delete the % we get the figure on the right side of Figure 2.14.

2.4.4 Subplots It is also possible to put several plots into the same graphics window using subplot. The subplot command has the form of subplot(r,c,i) where r is the number of rows, c is the number of columns, and i is an integer index starting from 1 that says where that subplot goes. For example clf t=0:0.1:2; subplot(231) plot(t,sin(t)) subplot(232) plot(t,cos(2*t)) subplot(233)

60

Fig. 2.15 Illustration of subplots

plot(t,t) subplot(234) plot(t,t.ˆ2) subplot(235) plot(t,1-t) subplot(236) polar(t,sin(t))

produces Figure 2.15.

2 Introduction to OML

Chapter 3

Modeling and Simulation in OML

One of the fundamental problems in many areas of science and engineering is the problem of modeling and simulation. OML provides several tools for developing and simulating models of several types. When combined with Activate, the number and capabilities are greatly increased. For several of these tools it is possible to use them with abbreviated commands and default values of some parameters. However, to know how to choose the appropriate tools and how to get the kind of answers desired, it is often necessary to know something about how the algorithms are set up and what to do if there are difficulties. This chapter describes the types of models that are available in OML and Activate and some of the tools available for their simulation. It also gives some general comments about how to use the tools and how to choose between the tools. Section 3.1 will introduce the various types of models that are available in OML and Activate. Section 3.2 presents the specific simulation tools that are present in OML. The remainder of the chapter will discuss what additional capabilities might be desirable and give pointers to where those additional capabilities are given in the Activate portion of the book. The following sections illustrate the OML build-in simulation tools. It will be seen that one can can build a complete simulation of a hybrid system using only OML built-in functions. But the construction of such a code for hybrid modeling can rapidly become very complex, time consuming and very difficult to debug because of the size of the code. Furthermore, control engineers are used to describing the models in form of “black boxes” and “state diagrams” connected with “wires”. This kind of graphical representation is more convenient (in terms of rapid development and immediate and intuitive understanding) than thousands of lines of OML or any other code. This has lead to the the development of 100% graphical modeling tools such as LabVIEW, Scicos, Simulink, VisSim and Activate. These kind of graphical tools are a lot more difficult to develop, but a lot easier to use for the final user and make the user more productive. The second portion of this book discusses in detail the graphical modeling tool Activate. © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_3

61

62

3 Modeling and Simulation in OML

3.1 Types of Models 3.1.1 Ordinary Differential Equations One of the most popular types of model is that of ordinary differential equations (ODE) such as y˙ = f (t, y). (3.1) Here y and f may be vector valued, y is a function of the real variable t, and y˙ denotes the derivative of y with respect to t. System (3.1) is a first-order differential equation since it involves only first-order derivatives. If it is desired to emphasize the dependence of y on t, then (3.1) can be written as y˙ (t) = f (t, y(t)).

(3.2)

In general this book uses the notation of (3.1) and suppresses the t dependence of y. Some models are initially formulated in terms of higher derivatives, but they can always be rewritten as first-order systems by the introduction of additional variables. The OML and Activate tools assume that the differential equation has first been rewritten to be of first order. Example 3.1 The system of second-order differential equations y¨1 = y˙1 − y2 + sin(t)

(3.3a)

y¨2 = 3 y˙1 + y1 − 4y2 ,

(3.3b)

y˙1 = y3 y˙2 = y4

(3.4a) (3.4b)

y˙3 = y3 − y2 + sin(t) y˙4 = 3y3 + y1 − 4y2 .

(3.4c) (3.4d)

can be rewritten as

An ordinary differential equation (3.1) generally has a family of solutions. To perform a simulation, additional information must be provided to make the solution unique. An initial condition is the value of y at a particular value of t. A boundary condition is when more than one value of t is involved in the additional conditions. An example of a boundary condition is y(0) − 2y(π ) = 0. The basic existence and uniqueness result for differential equations in the form (3.1) says that if y(t0 ) is specified and f and f y = ∂ f /∂ y are continuous functions of t and y near (t0 , y(t0 )), then there is a unique solution to (3.1) satisfying the initial condition. The solution will continue to exist as long as these assumptions hold. Another important fact is that the more derivatives of f (t, y) that exist and are continuous, the more derivatives y has.

3.1 Types of Models

63

This may seem to be an esoteric fact, but it actually plays an important role in simulation. The reason is that most simulation tools try to deliver a requested accuracy and the error estimates are based on assumptions about the number of derivatives of the solutions. Suppose now that one has a controlled differential equation y˙ = f (t, y, u(t)),

(3.5)

with u(t) a given function. Then even if f has all the derivatives that one wants with respect to t, y, u, the solution y can have only one more derivative than u has. Thus if a control is only piecewise continuous, so that it has jumps, which often occurs in applications, the solution y will not have a continuous first derivative at the jumps. This in turn can lead to serious problems with many numerical tools unless the behavior of u is taken into account when one is requesting the simulation.

3.1.2 Boundary Value Problems Boundary value problems (BVP) are differential equations but with the information given at two or more times rather than at just one time. Two-point boundary value problems take the general form of y˙ = f (t, y), t0 ≤ t ≤ t f , 0 = B(y(t0 ), y(t f )).

(3.6a) (3.6b)

where B relates the values of y at the two times t0 , t f . If y in (3.6a) is n-dimensional, then there usually need to be n equations in (3.6b) in order to uniquely determine a solution. However, the boundary value problem theory is more complicated than that for initial value problems, as illustrated by the next example. Example 3.2 Suppose that one has the boundary value problem 

   0 1 0 y+ −1 0 1   y1 (0) . 0= y2 (t f ) y˙ =

(3.7a) (3.7b)

The solution of differential equation (3.7a) is y1 = c1 cos(t) + c2 sin(t) + 1 y2 = −c1 sin(t) + c2 cos(t),

(3.8a) (3.8b)

where c1 , c2 are arbitrary constants. The first boundary condition in (3.7b) combined with (3.8a) gives c1 = −1. The second boundary condition in (3.7b) then gives that

64

3 Modeling and Simulation in OML

0 = sin(t f ) + c2 cos(t f ).

(3.9)

But (3.9) has a solution for c2 only if cos(t f ) = 0. Thus the existence of a solution to this boundary value problem depends on the particular value of t f . Here t f cannot be π2 + mπ , where m is an integer. One of the nice features about ODEs is that the given initial conditions are at one point. This means that with the numerical methods given below, the computation can be local and move from one step to the next. This makes it easier to solve problems on longer time intervals or with higher state dimension. With a BVP, since the information occurs at more than one time, it is often necessary to use a more global algorithm that takes into account the full t interval. This leads to much larger systems of equations that have to be solved.

3.1.3 Difference Equations The second major class of models is that of difference equations. These problems occur when there is a quantity whose values are of interest only at discrete-time values or the values change only at discrete times. Difference equations can occur either because the process is naturally discrete and only undergoes changes at isolated times or because it is continuous but our observations occur only at isolated times. Also, many numerical methods for differential equations actually solve an approximating difference equation. In difference equations there is an integer variable, which we denote by k. The solution is a sequence y(k) and it has to solve a difference equation y(k + 1) = f (k, y(k)),

y(k0 ) = y0 .

(3.10)

Sometimes it is more natural to think of a sequence of times tk , k ≥ k0 , and a difference equation (3.11) z(tk+1 ) = g(tk , z(tk )), z(tk0 ) = z 0 . If the tk are evenly spaced, so that tk+1 − tk = h where h is a constant, then (3.11) can be rewritten in the form of (3.10) as follows: v(k + 1) = g(w(k), v(k)), v(k0 ) = z 0 ,

(3.12a)

w(k + 1) = w(k) + h, w(k0 ) = tk0 .

(3.12b)

Note that v(k) of (3.12a) is the same as z(tk ) from (3.11). Alternatively one can define y(k) to be the value of z at time tk and define f (k, y(k)) to be g(tk , z(tk )) and (3.11) becomes (3.10). For the remainder of this section it is assumed that the difference equation is in the form (3.10). The theory for solutions of difference equations is simpler than that

3.1 Types of Models

65

for differential equations. Given a starting time k0 and a value of y0 that gives the initial condition y(k0 ) = y0 , the values of y(k) for k > k0 are computed recursively using (3.10) and will exist as long as (k, y(k)) is in the domain of f . There is one important difference between the discrete and continuous theories that is worth mentioning. The uniqueness theorem for first order differential equations tells us that if two solutions start at the same time but with different initial values and if the continuity assumptions on f, f y are holding, then the solutions can never intersect. This is not true for difference equations. Example 3.3 The difference equation (3.13) is at the origin after two time steps no matter where it starts at k0 :   1 −1 y(k + 1) = y(k). (3.13) 1 −1 The difference equations (3.10) and (3.13) are of first order since there is maximal difference of one in the values of k that are present. Just as systems of differential equations can always be written as first-order differential equations, difference equations can always be written as first-order difference equations. Example 3.4 The equation (3.14) is of third order since (k + 3) − k = 3: y(k + 3) = 4y(k + 2) − y(k + 1)y(k).

(3.14)

The difference equation (3.14) can be rewritten as a first-order difference equation by introducing additional variables as shown in (3.15): y1 (k + 1) = y2 (k) y2 (k + 1) = y3 (k)

(3.15a) (3.15b)

y3 (k + 1) = 4y3 (k) − y2 (k)y1 (k).

(3.15c)

Tools for working with difference equations often assume that they have been written in first-order form.

3.1.4 Differential Algebraic Equations Many physical systems are most naturally initially modeled by systems composed of both differential and algebraic equations [9, 32]. These systems take the general form of F(t, y, y˙ ) = 0 (3.16) and are often called DAEs.

66

3 Modeling and Simulation in OML

Example 3.5 One example of a DAE is a model of a constrained mechanical system where the constraint is on the position variables. Such a system takes the general form x˙ = v v˙ = G(x, v, t) + Q(x, t)λ 0 = H (x, t).

(3.17a) (3.17b) (3.17c)

Here x is position, v is velocity, and λ is a generalized force. System (3.17) is a DAE in y = (x, v, λ). Equation (3.17c) gives the explicit constraints. Also Q(x, t) = Hx (x, t)T , and Q(x, t)λ gives the force generated by the constraint. Given a DAE model, there are two options. One option is to try to rewrite the DAE into an ODE or a simpler DAE. This is usually done by a mixture of differentiation and algebraic manipulations. See [13]. The other option is to try to simulate the DAE directly. The theory for DAEs is much more complex than the theory for ODEs. One problem is that there will exist solutions only for certain initial conditions that are called consistent initial conditions. Considerably more detailed information about DAEs is in [9, 32]. Here it is enough to know two things. First, the structure of the DAE is important, and second, there is a nonnegative integer called the index. An ODE is is said to have index zero. Example 3.6 The simple system y˙1 = y1 − cos(y2 ) + t 0=

y13

+ y2 + e , t

(3.18a) (3.18b)

is a DAE in y1 , y2 . From (3.18b) it is seen that the initial conditions must satisfy y1 (t0 )3 + y2 (t0 ) + et0 = 0, so that only some initial conditions are consistent. This particular example can be reduced to an ODE by solving (3.18b) for y2 and substituting into (3.18a) to get an ODE in y1 . Index-one DAE systems occur frequently and are the ones for which OML and Activate provide tools. They are also the ones that Activate is able to solve when they occur in the form of implicit blocks. Index-one systems in the form (3.16) have the additional property that {Fy˙ , Fy } is an index-one matrix pencil [24] all along the solution and Fy˙ has constant rank. Two important types of index-one DAEs are the implicit semiexplicit and semiexplicit index-one systems. The implicit semi-explicit index-one systems are in the form F1 (t, y1 , y2 , y˙1 ) = 0

(3.19a)

F2 (t, y1 , y2 ) = 0.

(3.19b)

Here ∂ F1 /∂ y˙1 and ∂ F2 /∂ y2 are both nonsingular. y1 is sometimes referred to as a differential variable and y2 as an algebraic variable.

3.1 Types of Models

67

The semiexplicit index-one DAE takes the form y˙1 = F1 (t, y1 , y2 ) 0 = F2 (t, y1 , y2 ),

(3.20a) (3.20b)

with ∂ F2 /∂ y2 nonsingular. The DAE (3.18) is semiexplicit of index one. Indexone DAEs that are not semiexplicit or linear in the derivative terms are called fully implicit. If (3.16) is to be solved by a numerical method, then a numerical integrator usually needs an initial value of both y and y˙ . There are two difficulties. As noted, only some values of y are consistent. In addition, since ∂ F/∂ y˙ is singular, (3.16) only partially determines y˙ . To illustrate, consider the problem of initializing (3.18) at t = 0. y1 (0) and y2 (0) must satisfy (3.18b). One consistent choice is y1 (0) = −1, y2 (0) = 0. Then y˙1 (0) = −2 from (3.18a). But there is no obvious choice for y˙2 (0). One can either try to compute y˙2 (0) from additional information about the problem or utilize some of the utilities of the integrator. The second option may be the only one for a complex problem and will be illustrated later. For the simple problem (3.18), one can differentiate (3.18b) and evaluate at t = 0 to get an equation that yields y˙2 (0).

3.1.5 Hybrid Systems Many systems involve a mixture of discrete- and continuous-time events. These types of systems are generally called hybrid systems. The discrete nature of the system can occur in several different ways. These differences have to be taken into account in the simulation. The times at which a discrete variable changes value are sometimes called events. When an event occurs, there may be a change in the differential equations or in the values of some of the state variables. The state dimension may also change. It then becomes important to determine new initial conditions. This is referred to as the initialization problem. Sometimes the event occurs when some quantity reaches a certain value. For example, in the simulation of a mechanical system, if contact is made with an obstacle, then the equations change. It thus becomes necessary for the simulation software to be able to determine when the event occurs. This is known as root-finding or zero-crossing ability. Even when an event does not change the dimension of the state or the form of the equations, it can interfere with the error control of the integrator being used unless care is taken. The Activate software described in Part 2 of this book was specifically designed to model and simulate hybrid systems.

68

3 Modeling and Simulation in OML

3.2 OML Simulation Functions The simulation functions in OML are easy to use and are designed for simpler problems. More complicated problems will require the capabilities in Activate. In choosing the method, several factors need to be taken into account. For problems with frequent restarts, there are advantages to one step methods such as the Runge– Kutta formulations over the multistep methods such as the backward differentiation formula (BDF) methods and Adams methods. The order of a numerical method is an indication of the error relative to the step size. Thus a fourth-order method would be expected to have error proportional to h 4 (assuming that a constant step h is used, and the steps are sufficiently small). On the other hand, multistep methods, for a given order, often require less computation. Some problems are referred to as stiff. There are lots of definitions of a stiff differential equation. Here stiff is taken to mean that if one had an explicit method, then the step sizes would have to be reduced to ensure stability of the error propagation rather than to get the desired accuracy. Stiffness is often caused by large negative eigenvalues. Generally, implicit methods can take bigger time steps than explicit methods on stiff problems. Higher order is usually desirable. However, for implicit methods the higher the order, the smaller the stability region. This means that the higher-order method might have to take smaller steps than expected. This is especially true for problems that have highly oscillatory solutions. In addition, it does not make sense to use a higher order method if the equations, or input functions, do not have enough continuous derivatives. The previous comments only touch on some of the issues involved in the choice of numerical method. Our experience has been that when the simple call does not work, then it is often better to alter the AbsTol and RelTol and use odeoptions, which is described shortly, rather than altering the method. The exception is with DAEs as discussed later. If code performance becomes an issue, then it is possible to have OML call C/C++ code that describes the differential equation. OML provides four numerical methods for simulation. They are ode15i: Solves a stiff system of differential algebraic equations by a BDF method which is an implicit multistep method. ode15s: Solves a stiff system of differential equations by a BDF method. ode45: Solves a system of non-stiff ordinary differential equations by the one step Runge-Kutta method Runge-Kutta-Fahlberg 45. ode113: Solves a system of non-stiff ordinary differential equations by a multistep Adams method. Generally for non-stiff problems the multistep methods are more efficient but the one step methods better handle events where restarts are needed. For each of these methods options are set using odeset. OML currently allows for two or three options depending on the method. More options are available in Activate and more integrators are available in Activate. Options are set by options = odeset(’option1’, value1, ’option2’, value2)

3.2 OML Simulation Functions

69

For example, to set the relative tolerance and absolute tolerances to 10−3 and 10−6 respectively the command is options = odeset(’RelTol’, 1.0e-3, ’AbsTol’, 1.0e-6)

Setting these tolerances too tight can increase computational time and, in some cases, lead to integrator failure when tolerances cannot be met. Setting the tolerances too loose can lead to inaccurate answers. It should be kept in mind that the step size decisions are based on estimates of the error. The actual error in the solution could be higher. The parameter jac is an external (function or character string or list) that provides a Jacobian for those methods that can utilize analytic Jacobians. These include the BDF based and other implicit methods for stiff problems. If jac is a function, then the syntax should be J=jac(t,y). J should evaluate to the matrix that is ∂ f /∂ x. ode15i has the syntax [t,y] = ode15i(@func,tin,y0,yp0) [t,y] = ode15i(@func,tin,y0,yp0,options) [t,y] = ode15i(...)

Here y0 is the initial value. yp0 is the initial derivative value. tin are the times that you want the solution output if that is different from wanting the output at all time steps. options can be AbsTol, RelTol, and Jacobian. @func is the function that describes the differential equation. Example 3.7 To solve the differential algebraic equation m y˙1 = y2 − y3 y˙3 = ky1 0 = mv − y2 − y1 c,

(3.21a) (3.21b) (3.21c)

where m, k, c, v are known parameters and y1 , y2 , y3 are the state variables. The following function can be used to simulate. function f = MSD(t,y,yp,v,m,k,c) % y = [x, mD, mS] f = [0, 0, 0]; % optional for initializing size of f f(1) = (y(2)-y(3)) - m*yp(1); % momentum equilibrium f(2) = y(1) - yp(3)/k; % displacement equilibrium f(3) = (m*v-y(2)) - y(1)*c; % momentum equilibrium end m v k c

= = = =

1.6; % mass 1.5; % initial velocity 1.25; % spring constant 1.1; % damping constant

handle = @(t,y,yp) MSD(t,y,yp,v,m,k,c); t = [0:0.2:12]; % time vector for output yi = [0, m*v,0]; % initial condition

70

3 Modeling and Simulation in OML

ypi = [v, -c*v, 0.0]; % initial derivative. [t,y] = ode15i(handle,t,yi,ypi);

The other three solvers ode45, ode15s, and ode113 have the same calling syntax but it is a little bit different from ode15i in that @func only describes the = f (t, y), no yp0 is needed, and there right hand side of the differential equation dy dt is no Jacobian option in odeset. The syntax for calling ode45 is [t,y] = ode45(@func,tin,y0) [t,y] = ode45(@func,tin,y0,options) [t,y] = ode45(...)

while the syntax for calling ode113 is [t,y] = ode113(@func,tin,y0) [t,y] = ode113(@func,tin,y0,options) [t,y] = ode113(...)

and the syntax for calling ode15s is [t,y] = ode15s(@func,tin,y0) [t,y] = ode15s(@func,tin,y0,options) [t,y] = ode15s(...)

where tin and y0 have the same meaning as for ode15i. As an illustration consider the Van Der Pol oscillator which is given by y¨ = μ(1 − y 2 )y y˙ − y.

(3.22)

Rewrite (3.22) as a first order system y˙1 = y2 y˙2 = μ(1 −

(3.23a) y12 )y2

− y1 .

Then the following OML script will do the simulation function dy = VDP(t,y,mu) dy = [0, 0]; dy(1) = y(2); dy(2) = mu*(1.0-y(1)ˆ2)*y(2)-y(1); end mu = 1.0; % mass handle = @(t,y) VDP(t,y,mu); t = [0:0.2:10]; % time vector for output yi = [2, 0]; % initial value [t,y] = ode15s(handle,t,yi);

(3.23b)

3.2 OML Simulation Functions

71

A careful discussion of all the factors in choosing between methods is a book in itself. The interested reader is referred to the classic volumes [26, 27]. But one question is, suppose that I am going to use default values. Should I worry about which method I use? The following example addresses the effect of method on time of computation. Actual timings are somewhat machine dependent. The important question of accuracy is not considered here but note that in the computations below, when the solutions were graphed they appeared the same. Example 3.8 Listed below is an OML script compode.oml, which defines several functions. The function comparison(a,b,c,d) generates an 8-dimensional linear system y˙ = Ay + g. The eigenvalues of A are constructed to be {a ± bi, a ± bi, c, c, d, d} and all modes appear in all entries of y. This differential equation is then integrated using ode113, ode15s, ode45, and the DAE integrator ode15i in that order. The output is the computational times for each method in seconds. The times are found using tic and toc. compode.oml is function zz=comparison(a,b,c,d) A=[a,-b,0,0;b,a,0,0;0,0,c,0;0,0,0,d]; Z=zeros(4,4); AA=[A,Z;Z,A]; Q=[1 3 2 0 -1 4 6 0 10 4 5 7 8 -3 6 -5]; Q=[Q,1,3,Q,3,6,8,9,Q,11,7,2,4,0,-3,6,3,9,-3]; QQ=reshape(Q,8,8); A2=inv(QQ)*AA*QQ; tt=[0:0.1:100]; t0=0; y0=[1 1 -1 1 2 0 -1 -1 ]’; ydot0=A2*y0+g(0); func1=@(t,y) func(t,y,A2); rhs1=@(t,y,ydot) rhs(t,y,ydot,A2); tic; yy1=ode113(func1,tt,y0); t1=toc(); tic; yy2=ode15s(func1,tt,y0); t2=toc(); tic; yy3=ode45(func1,tt,y0); t3=toc(); tic; yy4=ode15i(rhs1,tt,y0,ydot0); t4=toc(); zz=[t1,t2,t3,t4] end function w=g(t) w=[zeros(1,6),cos(t),3*sin(2*t)]’; end function ydot=func(t,y) ydot=A2*y+g(t);

72

3 Modeling and Simulation in OML

end function r=rhs(t,y,ydot) r=ydot-A2*y-g(t); end

The functions in compode.oml are loaded into the workspace, and to compare the different methods on an easy problem enter > comparison(-0.1,2,-3,0.1) ans = [Matrix] 1 x 4 0.03100 0.01500 0.18800 0.03100

which are Adams method ode113, the stiff BDF method ode15s, Runge-Kutta ode45, and stiff DAE ode15i respectively. Notice that the methods were comparable, with the RK method taking a bit longer. Adams is often fastest on problems that are not rapidly varying. RK is often secondbest. Generally, Runge–Kutta methods like ode45 take more work per time step than a multistep of the same oder such as ode113. Also, ode113 can go to higher order. However, some problems, such as those in electrical engineering and some mechanical systems can be highly oscillatory. In other areas such as chemical reactions there can be very rapidly decaying terms. To examine what happens with a rapidly decaying component, enter > comparison(-0.1,2,-500,0.1) ans = [Matrix] 1 x 4 3.41480 0.01400 2.33100 0.02800

Note that the implicit methods ode15s and de15i are much faster. ode113 takes 100 times as long and ode45 take 45 times as long as the stiff methods. ode15i is designed for implicit equations and will do a bit more work than ode15s and that is indicted in the times. If a system is highly oscillatory, then some of the methods designed for stiff problems have to reduce their step size or order for stability reasons. To illustrate, enter > comparison(-0.1,500,-3,0.1) ans = [Matrix] 1 x 4 8.96700 3.4130 13.8670 1.74700

Note that as expected the stiff integrators were much faster but now ode15i is faster by a factor of 2 than ode15s. Sometimes simulation is embedded into design or optimization loops so that the same differential equations will be integrated many times. As the previous example shows, the computational time can vary greatly with the choice of the method. Accuracy can also vary, so that for complex problems one needs to do a careful examination of which integrator will be fastest and also deliver the desired accuracy.

3.2 OML Simulation Functions

73

Generally speaking variable step size integrators with error control are best. However, there are some situations where a fixed step is desirable. Activate does have some fixed step integrators described later. We conclude this section with an example using odeset. Being able to set the absolute or relative error tolerances is often very helpful. The example is to numerically solve the differential equation y˙1 = y2 + 0.01y1 (y12 + y22 − 25) y˙2 = −y1 + 0.01y2 (y12 + y22 − 25),

(3.24a) (3.24b)

with the initial condition y1 (0) = 5, y2 (0) = 0. The solution is circular motion around a circle of radius 5. However, solutions just outside this circle spiral out and solutions just inside spiral in. The following script integrates the system with three different tolerances using ode45 and then plots the solutions trajectory. function dy = myf(t,y) dy(1)= y(2) + 0.01*y(1)*(y(1)ˆ2+y(2)ˆ2-25); dy(2)=- y(1) + 0.01*y(2)*(y(1)ˆ2+y(2)ˆ2-25); dy=[dy(1);dy(2)]; end tin=[0 15]; y0=[5,0]; options1=odeset(’RelTol’,1.0e-03); options2=odeset(’RelTol’,1.0e-04); options3=odeset(’RelTol’,1.0e-06); [t1,y1]=ode45(@myf,tin,y0,options1); [t2,y2]=ode45(@myf,tin,y0,options2); [t3,y3]=ode45(@myf,tin,y0,options3); figure plot(y1(:,1),y1(:,2)); figure plot(y2(:,1),y2(:,2)); figure plot(y3(:,1),y3(:,2));

The plots are shown in Figure 3.1. The plotting was chosen so that a straight line connects the computed values. Thus the graph also illustrates the different step sizes used. In the left most graph which was with RelTol equal to 10−3 we see that the solution spirals in. Note also that the first corner comes quickly and then after some big steps the corners start coming closer. This is typical ode45 behavior which often takes small steps at first, then tries to take larger steps but then sometimes has to reduce them. In this case this happened because the solutions were speeding up. Looking to the next graph we see that with smaller RelTol the approximation is better, has smaller steps, but still starts a slow spiral in. For this example, on this time interval, the right most graph finally looks right. Setting RelTol too small can create the problem of the integration taking too long, or integration failure due to the inability to meet requested tolerances.

74

3 Modeling and Simulation in OML

Fig. 3.1 Trajectory of numerical solution of (3.24) using three relative tolerances

3.2.1 Implicit Differential Equations In some application areas the models are most naturally initially formulated as differential equations in the form A(t, y) y˙ = g(t, y),

y(t0 ) = y0 .

(3.25)

If A(t, y) is not invertible for all t, y of interest, then (3.25) is a linearly implicit differential algebraic equation (but it is not a linear DAE). If A(y, t) is invertible for all t, y of interest, then (3.25) is called either a linearly implicit differential equation or an index-zero DAE. For this section it is assumed that A(t, y) is an invertible matrix. One could, of course invert A and get the ODE y˙ = A(t, y)−1 g(t, y),

y(t0 ) = y0 .

(3.26)

However, this reformulation is not always desirable. The implicit system (3.25) can often be integrated more efficiently and reliably than (3.26). The numerical methods for solving (3.25) are similar to those discussed later for DAEs of the form F(t, y, y˙ ) = 0, which require a way to evaluate F given estimates of y(t), y˙ (t). Traditionally this function F is called a residual since iterative numerical methods are used, and when approximations are substituted in for y and y˙ , the evaluation of F(t, y, y˙ ) tells us how far the approximations are from being solutions. In the implicit methods there are nonlinear equations that must be solved, and these require Jacobian information.

3.2.2 Linear Systems Since they occur so often in areas such as control engineering, there are a number of specialized functions for working with linear systems of the form

3.2 OML Simulation Functions

75

x˙ = Ax + Bu

(3.27a)

y = C x + Du,

(3.27b)

where A, B, C, D are matrices. System (3.27) is called the state-space form. Letting x(0) = 0, taking the Laplace transform of (3.27), and letting zˆ (s) denote the Laplace transform of z(t), shows that (3.27) can be written as ˆ = H (s)u(s), ˆ yˆ (s) = (D + C(s I − A)−1 B)u(s)

(3.28)

where H is a rational matrix function. That is, the entries of H are fractions of polynomials. Further manipulations would allow us to get D(s) yˆ (s) = N (s)u(s), ˆ

(3.29)

where D, N are matrices of polynomials in s. A number of commands for working with linear systems are described in Section 3.3 which is on the Control Toolbox which is included with OML.

3.2.3 Root Finding It is often desirable to simulate a differential equation up to the time something happens. In some cases the time is the quantity of interest, for example in an interception problem. In other cases the time will represent physical change in the dynamics such as when a tank is filling up and it starts to overflow. In all these cases there is the system (3.1) and it is desired to integrate it until some quantity g(t, y) is equal to 0. This is called root finding or zero-crossing. Root finding and zero-crossing integrators are available in Activate.

3.2.4 Boundary Value Problems A number of methods have been developed for solving BVP. The shooting methods take the given initial information and guess the rest of the initial information. They then adjust this initial guess by integrating over the full interval and using how far they miss the terminal boundary condition to correct the initial guess. Shooting methods are easy to program and can solve some problems, but they are not reliable for problems with long intervals or that are stiff in some sense. A more sophisticated approach is multiple shooting, which breaks the time interval into several subintervals and shoots over these. A shooting method is programmed in Section 5.1. Additional examples are given later in the Activate part of the book.

76

3 Modeling and Simulation in OML

The third approach is to discretize the differential equation using some numerical discretization, and then solve the large discrete system that results. For example, if one used Euler’s method with a fixed step of h as the discretization, then the BVP (3.6) would become the nonlinear system of equations xi+1 − xi − h f (t0 + i h, xi ) = 0, i = 0, . . . , N − 1, B(x0 , x N ) = 0.

(3.30a) (3.30b)

Of course, modern computer programs do not use Euler’s method to solve BVP, but (3.30) makes the key point that what must be solved is a large system of equations, and these equations are nonlinear if the differential equation or the boundary conditions are nonlinear. This means that the BVP solver must deal with all the usual problems of numerically solving a nonlinear system including having a good enough initial guess and needing some sort of Jacobian information. Boundary value solvers are not currently in OML or Activate.

3.2.5 Difference Equations In many ways the simulation of discrete systems is easier because there is no choice about the time step and no error is introduced by the approximation of derivatives. Any error is the usual function evaluation and roundoff error. Difference equations of the first-order form y(k + 1) = f (k, y(k)),

y(k0 ) = y0 ,

(3.31)

may be simulated in OML by directly programming the recurrence given by (3.31). As an example suppose that it is desired to compute the solution of x(k + 1) = sin(x(k) + y(x)) + (0.5)k y(k + 1) = 0.5(x(k) − y(k)),

(3.32a) (3.32b)

starting from [3; 1] on the interval k = 0, . . . , 10. The following script performs the simulation. function ynew=func(yold,k) ynew(1)=sin(yold(1)+yold(2)) + (1/2)ˆk; ynew(2)=0.5*(yold(1)-yold(2)); ynew=ynew’; % make output a column end y0=[3;1]; % initial state k0=0; % initial time kf=10; % final time state=y0; time=k0;

3.2 OML Simulation Functions

77

k=k0; yold=y0; while k

0 or absent -2 -1 0

Continuous-time model Static gain model Discrete-time model with unspecified sampling time Discrete-time model with sampling time TS

SYS is a table. ssdata is used to get the matrices back from a continuous-time state-space model or a transfer function model SYS. [A,B,C,D,TS] = ssdata(SYS)

dssdata is used to extract the information from a descriptor state-space model. [A,B,C,D,E,TS] = dssdata(SYS)

If U is an invertible matrix and we let x = U x˜ in (3.33), then we get a new statespace model in the variable x˜ with coefficient matrices {U −1 AU, U −1 B, CU, D} which is said to be equivalent to {A, B, C, D}. Equivalent systems have the same transfer function. But two systems with the same transfer function must be equivalent only if they are both controllable and observable. Such a state-space change of coordinates by a transformation U is carried out by the ss2ss command. SYS2=ss2ss(SYS,U)

The matrix U must be invertible and the same size as A. Whether a system is continuous or discrete time can be determined by the boolean valued functions isct and isdt. Here isct is a boolean variable that returns true if the system is a continuous-time model. isdt determines if the system is a discretetime model. If SYSIN is either a continuous-time state-space or transfer function model table, then SYS = ss(SYSIN,’minimal’)

constructs a minimal realization of SYSIN, that is, one without any unobservable or uncontrollable modes of A. The minimal realization will have the smallest state dimension of all equivalent realizations and is unique up to equivalence. A minimal realization of a state-space model may also be computed using minss which allows for specification of tolerances. The minimal realization of a state-space function can also be computed using minreal with the syntax [AM,BM,CM,DM] = minreal(A,B,C,D) [AM,BM,CM,DM] = minreal(A,B,C,D,TOL) SYSR = minreal(SYSIN,TOL) SYSR = minreal(SYSIN)

The command ss_size returns the size of a system’s submatrices. [P,N,M] = ss_size(SYSIN)

Here P, N , M are p, n, m respectively. The syntax also allows for ss_size (A,B,C,D).

3.3 Control Toolbox

81

Sometimes it is desirable to change a system into a different one. balreal produces a balanced real system from a stable system using a similarity matrix. [SYSB,G,T,TI] = balreal(SYSA)

SYSA is a stable state-space or transfer function model. SYSB is the new balanced system which has identical observability and controllability diagonal Grammians. G is the diagonal vector of the controllability and observability Grammians. T is the transformation. TI is the inverse of T. A continuous-time state-space model SYSC may be converted to a discrete-time state-space model SYSD using c2d. SYSD = c2d(SYSC,TSAM) SYSD = c2d(SYSC,TSAM,METHOD) SYSD = c2d(SYSC,TSAM,’prewarp’,W0)

Here TSAM is the sampling time in seconds. There are four options for METHOD. ’prewarp’: Prewarp method. This method requires also defining the W0 parameter (prewarp frequency). ’tustin’: Tustin approximation method. ’bilin’: Bilinear transformation. ’zoh’: Zero-Order-Hold method (default method). Conversely, a discrete-time system SYSD may be converted to a continuous-time system SYSC by d2c. SYSC = d2c(SYSD) SYSC = d2c(SYSD,METHOD) SYSC = d2c(SYSD,METHOD,W0)

The options for METHOD in d2c are the same options as those for c2d. Descriptor systems are constructed by SYS=dss(A,B,C,D,E,TS)

The system is discrete time if TS is present and continuous-time if TS is absent. TS is the sample time if TS>0. TS=-1 leaves the sample time unspecified which is also the default. A continuous-time state-space descriptor model SYSLTI can be converted to a regular state-space model by using dss2ss through either of [AR,BR,CR,DR,ER] = dss2ss(SYSLTI) [AR,BR,CR,DR,ER] = dss2ss(A,B,C,D,E)

If we have a continuous-time system (3.33), then one way to get a discrete-time system is by sampling. There are several ways to do this. Let tk be our sample points. Given values of u k = u(tk ) and xk = x(tk ), the model has to estimate the value of x(tk+1 ). The first question is how do we handle the effect of u(t). Do we assume it is piecewise constant and do we use interpolation on previous values of u? The next question is how the solution of the differential equation from tk to tk+1 is approximated. OML provides several options.

82

3 Modeling and Simulation in OML

Another popular approach for working with transfer functions is in the single input-single output (SISO) case, where H (s) is the fraction of two polynomials; H (s) =

N (s) . D(s)

If the system is not a descriptor system, the fraction is proper in that the nominator has the same or smaller degree than the denominator. In OML scalar polynomials are a vector with the coefficients of the powers listed from largest largest power to the smallest power. As a simple illustration, suppose that         12 C= 11 , A= , B= 12 , D= 0 . 03 Then a simple calculation shows that H (s) =

3s − 1 . s 2 − 4s + 3

(3.39)

The following code takes the state-space model {A, B, C, D} and produces the polynomial form of the transfer function (3.39) A=[1 2;0 3]; B=[1;2]; C=[1 1]; D=0; [NUM,DEN]=ss2tf(A,B,C,D)

which produces the output NUM = [Matrix] 1 x 2 3.00000 -1.00000 DEN = [Matrix] 1 x 3 1 -4 3

Notice that the vector NUM is the coefficients of the numerator 3s − 1 in (3.39) and the vector DEN is the coefficients of the denominator s 2 − 4s + 3 in (3.39). The command compreal constructs a realization of a transfer function using companion matrices. [A,B,C,D,E] = compreal(NUM,DEN)

Matrix E is empty (the identity matrix) if there are at least as many poles as zeros. Transfer function models are constructed with tf . There are a number of syntaxes for tf SYS=tf() SYS=tf(S) SYS=tf(SYSIN) SYS=tf(NUM,DEN): Continuous-time transfer function SYS=tf(NUM,DEN,TS): Discrete-time transfer function

3.3 Control Toolbox

83

Here S is a static gain, SYSIN is a state-space or transfer function model, NUM is a row vector representing a numerator polynomial, DEN is a row vector representing a denominator polynomial. TS is the sample time. If TS=-1, then the sample time is not specified and inputs are considered as in the continuous-time case. tf_eq provides an entry by entry test of equality of transfer functions. Its value is boolean. Transfer function models can be converted to state-space models and conversely by the ss2tf and tf2ss functions. tf2ss returns the parameters of the statespace function that is equivalent to the transfer function. Note that this depends on the realization used so it is in terms of the polynomials NUM and DEN. [A,B,C,D] = tf2ss(NUM,DEN)

To then make this a state-space system ss(A,B,C,D) is used. With ss2tf there is an option to only construct the transfer function from the K th input. [NUM,DEN] = ss2tf(A,B,C,D) [NUM,DEN] = ss2tf(A,B,C,D,K)

Then to make this a transfer function one uses tf(NUM,DEN). A (generalized) state-space realization of a transfer function can also be computed by compreal [A,B,C,D,E] = compreal(NUM,DEN)

Where A,B,C,D,E can be real or complex. If there are just as many poles as zeros, then E= I . Otherwise E is singular. While the OML functions on transfer functions apply to SISO systems, they can also be used when considering MIMO (multi-input multi-output) systems. To illustrate just one way how to do this, suppose that we have a 2 × 2 transfer function  H (s) =

 H1 (s) H2 (s) , H3 (s) H4 (s)

(3.40)

so that each Hi is a proper fraction of two polynomials N um i , Den i . Thus each Hi has a realization given by [Ai , Bi , Ci , Di ] = tf2ss (N um i , Den i ). Then if ⎡ B1   ⎢0 C1 C2 0 0 , B=⎢ A = Diag(Ai ), C = ⎣ B3 0 0 C3 C4 0

⎤ 0   B2 ⎥ ⎥ , D = D1 D2 , 0⎦ D3 D4 B4

we have that {A, B, C, D} is a realization of H . This realization can be converted to a minimal one by using sysbig=ss(A,B,C,D) and then ss(sysbig, ’minimal’) for a minimal realization of (3.40).

84

3 Modeling and Simulation in OML

Suppose that one has two linear time invariant systems x˙1 = A1 x1 + B1 u 1 y1 = C1 x1 + D1 u 1

(3.41a) (3.41b)

x˙2 = A2 x2 + B2 u 2 y2 = C2 x2 + D2 u 2 .

(3.41c) (3.41d)

Linear systems are in parallel if they have common inputs and outputs. That is, u 1 = u 2 and y1 = y2 in (3.41). This addition of systems SYS1 and SYS2 to produce SYS3 is done by the command ss_add. SYS3 = ss_add(SYS1,SYS2)

Parallel addition of systems is represented graphically in Figure 3.5. A more complex version of parallel addition can be done using parallel. If SYS1 and SYS2 are two state-space or transfer function models, then SYS3 = parallel(SYS1,SYS2) SYS4 = parallel(SYS1,SYS2,VIN1,VIN2,VOUT1,VOUT2)

Here SYS3 is the simple parallel sum, while SYS4 connects a subsystem SUBSYS1 of SYS1 in parallel with a subsystem SYBSYS2 of SYS2. The integer vectors VIN1 and VOUT1 are the input and output channels of SUBSYS1. The integer vectors VIN2 and VOUT2 are the input and output channels of SUBSYS2. The systems can be discrete or continuous time. If they are discrete, then the sample times need to be the same. The multiplication of two systems is a series connection and is done with ss_mul. It is another state-space system. SYS3 = ss_mul(SYS1,SYS2)

where SYS1 and SYS2 are state-space models. For a series connection y1 = u 2 in (3.41). A series connection can be illustrated graphically as in Figure 3.6.

Fig. 3.5 Parallel addition of two systems

H1 y

u H2

Fig. 3.6 Graphical representation of series connection

u

H1

H2

y

3.3 Control Toolbox

85

The equality of two state-space models is checked with ss_eq which returns a Boolean variable (true or false). The negation of a state-space model has transfer function −H (s) and is done by ss_neg with syntax SYS2 = ss_neg(SYS1) SYS2 = ss_neg(A,B,C,D)

A subsystem can be extracted from a linear time invariant state-space system using ss_select. The syntax is SYSSUB = ss_select(SYS1,vin,vout,states)

Here vin, vout, states are vectors of integers which specify the indices of the input, output, and state vectors which are used in the subsystem. Sometimes with two systems such as in (3.41) you want the two outputs in (3.41b) and (3.41d) to be different and you want the inputs for the two subsystems to be different. This operation is done by the append command which takes the form. SYS3 = append(SYS1,SYS2)

For some systems and control problems you wish to work with an augmented model which outputs not only y but also the state x. This is done with the augstate function. SYS2 = augstate(SYS1)

If SYS1 is System (3.33), then SYS2 is x˙ = Ax + Bu       y C D = x+ u x I 0

(3.42a) (3.42b)

There are a number of equations that are important in control theory. The continuous-time algebraic Riccati equation is solved by care. [X,L,G] = care(A,B,Q)

solves A T X + X A − X B B T X + Q = 0, [X,L,G] = care(A,B,Q,R)

solves A T X + X A − X B R −1 B T X + Q = 0. [X,L,G] = care(A,B,Q,R,S,E)

solves A T X E + E T X A − (E T X B + S)R −1 (B T X E + S T ) + Q = 0. Riccati equations often have more than one solution. Note that if R, S, E are omitted from the calling syntax, then the default values of I, 0, I are used. X is the unique positive definite solution if it exists of the algebraic Riccati equation, L are the closed loop eigenvalues, and G is the gain (feedback) matrix derived from the solution of the Riccati equation. That is, G = R −1 (B T X E + S T ) and L = eig(A − BG). If E = I , then L = eig(A − BG, E).

86

3 Modeling and Simulation in OML

The discrete-time Riccati equation is solved by dare. [X,L,G] = dare(A,B,Q,R)

solves A T X A − X − A T X B(B T X B + R)−1 B T X A + Q = 0. [X,L,G] = dare(A,B,Q,R,S, E)

solves A T X A − E T X E − (A T X B + S)(B T X B + R)−1 (B T X A + S T ) + Q = 0. G = (B T X B + R)−1 (B T X A + S T ) is the gain matrix, X is the solution of the Riccati equation, and L are the closed loop eigenvalues. The default values of R, S, E are again I, 0, I respectively. X, L, G have the same meanings as for care. If A, B, C, E are real matrices, then X = lyap(A,B) solves the Lyapunov equation AX + X A T = −B X = lyap(A,B,C) solves the Sylvester equation AX + X B = −C X = lyap(A,B,[],E) solves the generalized Lyapunov equation AX E T + E X A T = −B If A, B, C, E are real matrices, then the discrete-time equivalents are given by X = dlyap(A,B) solves the discrete Lyapunov equation AX A T − X = −B X = dlyap(A,B,C) solves the discrete Sylvester equation AX B T − X = −C X = dlyap(A,B,[],E) solves the generalized discrete-time Lyapunov equation AX A T − E X E T = −B The continuous-time Lyapunov equation can also be solved with lyapchol. It returns a Cholesky factorization X = U T U . U = lyapchol(A,B) solves AU T U + U T U A T = −B B T X = lyapchol(A,B,E) solves AU T U E T + EU T U A T = −B B T The discrete-time Lyapunov equation can also be solved with dylapchol which uses a square root solver. X = dlyapchol(A,B) solves AU T U A T − U T U = −B B T X = dlyapchol(A,B,E) solves AU T U A T − EU T U E T = −B B T There are also commands to carry out various matrix operations. blkdiag builds a block diagonal matrix Y = blkdiag(A,B,C,..)

In systems theory it is sometimes important to work with square roots and exponentials of matrices. R=sqrtm(X) attempts to compute a square root of the square matrix X, that is R*R=X. If X is not symmetric, then the square root may not exist, and if it exists, the computation may not be accurate. Note the command A=[4 1;1 9];[sqrt(A);sqrtm(A)] produces ans = [Matrix] 2 x 4 2.00000 1.00000 1.98991 0.20067 1.00000 3.00000 0.20076 2.99328

3.3 Control Toolbox

87

The left two columns give the square root of each entry of A, that is sqrt(A). The right two columns are the matrix square root sqrtm(A). The functions exp and log are the scalar functions. When applied to a matrix they operate on each entry. logm is the inverse of the matrix function expm. Thus if A=[4 1;1 9], we get expm(logm(A))=A but expm(log(A)) is 4.00000 1.00000 0.00000 9.00000

which differs in this example in the (2,1) entry. The observability and controllability Grammians are given by Wo =

0

Wc =





T

e A t C T Ce At dt T

e At B B T e A t dt,

(3.43) (3.44)

0

respectively. They play an important role in many systems theory results. They are computed by the gram function. W=gram(SYS,c)

The character string c is ’o’ for the observability Grammian and ’c’ for the controllability Grammian. Two transfer functions are added by tf_add. SYS3=tf_add(SYS1,SYS2)

where SYS1 and SYS2 are two transfer function models. This is a parallel interconnection. The multiplication of transfer functions is given by tf_mul. This is a series connection. TF3=tf_mul(TF!,TF2)

A more general series connection command is series. It can be used for the series connection of transfer functions, the series connection of state-space systems, or the series connection of subsystems of state-space systems. RSYS = series(TF1,TF2) RSYS = series(SS1,SS2) RSYS = series(SYS1,SYS2,VOUT1,VIN2)

Here VIN2 is an integer vector specifying the input channels of SYS2 and VOUT1 is an integer vector specifying the output channels of SYS1. The size of a transfer function is determined by the tf_size command. The size is the number of inputs P and outputs N and is computed from a polynomial representation, [P,M] = tf_size(NUM,DEN)

Here NUM is a matrix numerator and DEN is a matrix denominator of the transfer function. To recover the data from a transfer function model, tfdata is used.

88

3 Modeling and Simulation in OML

[NUM,DEN,TS] = tfdata(SYS)

Here NUM is a matrix numerator and DEN the denominator of the transfer function. TS is the sample time. If SYS is a state-space system or a transfer function issiso checks if the system is single input single output. The value of issiso is a boolean variable, 1 for true, 0 for false. OML also has ZPK (zero-pole-gain) models where Z is a vector whose entries are the zeros of the transfer function, P are the poles of the transfer function, and K are the gains of the transfer function. The syntax is SYS SYS SYS SYS

= = = =

zpk(’s’) zpk(’z’,TS) zpk(Z,P,K) zpk(Z,P,K,TS)

Sample time is TS (in seconds). TS=0 by default and TS=-1 to leave the sample time unspecified. The data can be retrieved from a ZPK model SYS with zpkdata [Z,P,K,TS] = zpkdata(SYS)

It is possible to change a ZPK model to a transfer function model with [NUM,DEN] = zp2tf(Z,P,K)

The numerator and denominator coefficients of NUM and DEN are in descending order of powers of s. Going from a transfer model to a ZPK model is given by tf2zpk for a discrete transfer function and by tf2zp for a continuous-time transfer function. [Z,P,K] = tf2zpk(NUM,DEN) [Z,P,K] = tf2zp(NUM,DEN)

Block diagonalization with Schur factorization is carried out by bdschur. [T,B] = bdschur(A) [T,B] = bdschur(A,CONDMAX)

Here A is a real square matrix, CONDMAX is a scalar which is the upper limit of the infinity norm of elementary submatrices of the transformations used for reduction. T is the transformation matrix and B is block upper triangular. The computed values satisfy B = T −1 AT . roots and poly are useful for working with polynomials. If A is a vector, then poly(A) is a polynomial with coefficients A. If A is a square matrix, then poly(A) is the characteristic polynomial of A. Given a polynomial p, then roots (p) gives the roots of the polynomial. Determining and altering the poles of a system through feedback is an important part of control design. pole computes the poles of a transfer function or state-space system SYS by way of P=pole(SYS). Poles (eigenvalues) are placed using state feedback by place. K = place(A,B,P)

3.3 Control Toolbox

89

Then A − B K will have the eigenvalues in the vector P. If A is n × n, then P needs to be 1 × n. It is less accurate, but for educational purposes, one can also use Ackermann’s formula K=acker(A,B,P). In this case P are the eigenvalues of A-BK. An example using place is in Section 7.3.2.2. Observability and controllability are two important properties of a system (3.33). If A is n × n, then the observability matrix O and controllability matrix C are given by ⎤ ⎡ C ⎢ CA ⎥   ⎥ ⎢ O = ⎢ . ⎥ , C = B AB · · · An−1 B . ⎣ .. ⎦ C An−1 The controllability matrix of {A, B} is given by C=ctrb(SYS) or C=ctrb(A,B). The observability matrix of {C, A} is computed by O=obsv(A,C) or O=obsv(SYS). The observability of {A, C} may be checked with the isobsv command. It returns a boolean value (true of false). The syntax is RES = isobsv(SYSIN) RES = isobsv(A,C)

If the system is observable, then all modes can be detected through the output and it is also possible to set the convergence rate of a Luenberger observer to be any desired rate. Controllability of {A, B} can be checked by isctrb RES = isctrb(SYSIN) RES = isctrb(A,B)

If a system is controllable, then given any x0 , x f and interval [t0 t f ] of positive length, it is possible to find a control to steer x from x(t0 ) = x0 to x(t f ) = x f . Also a system is controllable if and only if feedback u = K x can be used to place the eigenvalues (poles) of A − B K (or A − B K ) at any desired location. In working with linear time invariant control systems a variety of forms are used. ctrbf computes the controllability staircase form. [ABAR,BBAR,CBAR,T,K] = ctrbf(A,B,C) [ABAR,BBAR,CBAR,T,K] = ctrbf(A,B,C,TOL)

TOL specifies the tolerance level. The default is size(A,1)*norm(A,1)* eps(). Here T is a unitary transformation and A¯ = T AT T , B¯ = T B, and C¯ = C T T with       0 A11 0 , B¯ = , C¯ = C1 C2 . A¯ = A21 A22 B2 A11 has the uncontrollable modes, and {A22 , B2 } is controllable. As an illustration we shall compute the controller form of a system. We run the following script

90

3 Modeling and Simulation in OML

A=[1 -1 1 1;1 -1 0 1;1 2 -1 1;1 2 3 -3] B=[1 1 0 0]’; C=[1 1 1 1]; D=0; % defines matrices format(4,2); % shortens display to make easier to read eig(A) % eigenvalues of A isctrb(sys) % checks if controllable r=rank(ctrb(A,B)) % dimension of controllable subspace [AA,BB,CC,T,K]=ctrbf(A,B,C); [AA,BB] % In the controller form AU=AA(1,1); % Matrix A11 eig(AU) % uncontrollable eigenvalues AC=AA(2:4,2:4); % Matrix A22 eig(AC) % controllable eigenvalues

which produces the output A = [Matrix] 4 x 4 1 -1 1 1 1 -1 0 1 1 2 -1 1 1 2 3 -3 ans = [Matrix] 4 x 1 2.30 -1.00 -1.30 -4.00 ans = 0 r = 3 ans = [Matrix] 4 x 5 -4.00e+00 7.85e-17 -5.00e-01 0.00e+00 -2.00e+00 -1.00e+00 5.00e-01 2.00e+00 ans = -4.00 ans = [Matrix] 3 x 1 -1.30 -1.00 2.30

0.00e+00 5.00e-01 0.00e+00 1.50e+00

-2.36e-16 0.00e+00 3.00e+00 -3.33e-16

0.00e+00 0.00e+00 0.00e+00 -1.41e+00

We see that there is one uncontrollable eigenvalue −4 and three controllable eigenvalues −1.30, −1.00, 2.30 which can be placed arbitrarily by feedback. Thus this system can be stabilized by feedback. It is easier to recognize the controller form if we set numerically zero entries to 0 to get ⎤ 0 −4.00 0 0 0 ⎢ −0.50 0 0.50 0 0⎥ ⎥. [A A, B B] = ⎢ ⎣ −2.00 −1.00 0⎦ 0 3.00 0.5.0 2.00 1.50 0 −1.41 ⎡

A more elaborate version of computing the controllability form is contr. [N,U,IND,V,AC,BC] = contr(A,B) [N,U,IND,V,AC,BC] = contr(A,BTOL)

3.3 Control Toolbox

91

Here N: Dimension of the controllability space U: Orthogonal change of basis that puts A, B into canonical form IND: Vector associated with controllability indices V: Orthogonal matrix, change of basis in the control space AC: Matrix AC = U’*A*U (block Hessenberg matrix) BC: Matrix BC = U’*B*V obsvf computes the observability staircase form which is       B1 A11 A12 , B¯ = , C¯ = 0 C2 . A¯ = 0 A22 B2 A11 has the unobservable modes, and {A22 , C2 } is observable. It is desirable to be able to simulate a system. gensing generates an input signal for the lsim function. [U,T] = gensig(TYPESIG,TAU) [U,T] = gensig(TYPESIG,TAU,TF) [U,T] = gensig(TYPESIG,TAU,TF,TS)

Here TAU is the duration of one period in seconds, TF is the optional duration of the signal in periods (default is 5), TS is optional sampling time in seconds (default is TAU/64) The types of signals given by the character string TYPESIG are ’sin’: Sine wave ’cos’: Cosine wave ’square’: Square wave, ’pulse’: Periodic pulse. A state-space or transfer function linear system model SYS can be simulated with lsim. The model cannot have more zeros than poles. That is, it cannot be a descriptor system [Y,T,X] = lsim(SYS,U) [Y,T,X] = lsim(SYS,U,T) [Y,T,X] = lsim(SYS,U,T,X0)

Here T is a time vector, U is a vector or array of values of the input signal at times T. The initial condition is X0 (default value is zero). Both the output values Y and state values X have as many rows as the length of T. The ith row of Y is the value of the output at the ith time value in T and the same for X. The pair T and U in lsim can be generated by gensig. Alternatively, U can be generated by another OML function. As an example using lsim suppose that we wish to simulate    −1 1 1 x˙ = x+ u 1 −2 −1    T y = −1 0.1 x, x(0) = −1 2 , 

(3.45a) (3.45b)

92

3 Modeling and Simulation in OML

Fig. 3.7 Output y (left) and state trajectory (right) of (3.45)

with u(t) = e−t + 2 on the interval [0 10]. Then the following script carries out the simulation and produces the graphs in Figure 3.7, A=[-1 1;1 -2];C=[-1, 0.1];D=0;B=[1;2]; SYS=ss(A,B,C,D); T=0:0.1:10; x0=[-1;2]; U=exp(-T)+2; [Y,T,X]=lsim(SYS,U,T,x0); figure plot(T,Y) figure plot(T,X)

The continuous-time infinite horizon linear quadratic regulator problem is to find the optimal control u that minimizes J (x0 ) =



x T Qx + u T Ru + 2x T Su dt,

(3.46)

0

where x˙ = Ax + Bu,  = x0 . Q is positive semi-definite, R is positive defi and x(0) Q S is positive semi-definite. The optimal solution is given nite, and the matrix T S R by a feedback u = −Gx with the eigenvalues L = eig(A − BG). This problem is solved by the lqr command. [G,X,L] [G,X,L] [G,X,L] [G,X,L] [G,X,L]

= = = = =

lqr(SYS,Q,R) lqr(SYS,Q,R,S) lqr(A,B,Q,R) lqr(A,B,Q,R,S) lqr(A,B,Q,R,S,E)

Here E is used for descriptor systems. G is the feedback gain, X is the positive definite solution of the Riccati equation, and L are the closed loop eigenvalues. LQR solutions are used for computing stabilizing feedbacks and also to provide suboptimal solutions over finite time horizons.

3.3 Control Toolbox

93

The discrete-time infinite horizon LQR problem is solved by dlqr. [K,S,E] = dlqr(A,B,Q,R) [K,S,E] = dlqr(A,B,Q,R,N)

Here K is the feedback gain, E are the eigenvalues of A − B K , and S is the solution of the discrete-time algebraic Riccati equation. Sometimes the output is used instead of the state and instead of (3.46) the cost is taken to be ∞ y T Qy + u T Ru + 2y T Su dt. (3.47) J (x0 ) = 0

The optimal control problem is solved by lqry which has the same synax as lqr. The norm command has a variety of interpretations depending on whether it is applied to a matrix X, a linear time invariant system SYS, or a vector V. N = norm(X,2): 2-norm N = norm(X): 2-norm N = norm(X,1): 1-norm N = norm(X,Inf): infinity or sup norm N = norm(X,’fro’): Frobenius norm N = norm(V,p): p is 1 or 2. N = norm(V,Inf): Largest entry of abs(V) N = norm(V,-Inf): Smallest entry of abs(V) N = norm(SYSLTI): H 2 norm N = norm(SYSLTI,2): H 2 norm N = norm(SYSLTI,Inf): H ∞ norm [N,FPEAK] = norm(SYSLTI,Inf): [N,FPEAK] = norm(SYSLTI,InfTOL): FPEAK is the frequency where the gain is largest. The inverse command inv can be applied to a square invertible matrix or a statespace or transfer function model. If it is applied to a transfer function or state-space model, then the D matrix must be square and invertible. The inverse of a transfer function H (s) is H (s)−1 . If SYS is a state-space or transfer function model, then [P,Q] = covar(SYS,W)

returns the output covariances P and the state covariance Q given the intensity W of the Gaussian white noise. The DC gain of a state-space or transfer function is given by K = dcgain(SYS) K = dcgain(NUM,DEN) K = dcgain(A,B,C,D)

Here K is a scalar.

94

3 Modeling and Simulation in OML

It is often important to be able to estimate the state of a linear time invariant system. Given the system (3.33), then the Luenberger observer is z˙ = Az + Bu + L(y − yˆ )

(3.48a)

yˆ = C z + Du.

(3.48b)

z provides an estimate of x. If  = x − z is the measurement error, then ˙ = (A − LC). If L is chosen so that A − LC is asymptotically stable, then the estimation error will go to zero. estim returns the state estimator for a given estimator gain L and given system SYS. EST = estim(SYS,L) EST = estim(SYS,L,SENSORS,KNOWN)

Here SENSORS are the indices of measured output signals if not all outputs are measured. KNOWN are the indices of known input signals if not all are known. In terms of (3.33), estim is the system z˙ = Az + L(y − C z)     yˆ C = z xˆ I

(3.49a) (3.49b)

with input y and outputs xˆ the estimate of x and yˆ the estimate of y. Given the system SYS, state feedback gain K, and estimation gain L, then a state regulator is constructed by reg. SYSNEW = reg(SYS,K,L)

reg is the system that implements the estimate in feedback form. In particular, it has input y and output u and is the system z˙ = (A − LC − (B − L D)K )z + L y u = −K z.

(3.50a) (3.50b)

System (3.50) is derived by substituting (3.50b) into the Luenberger observer (3.48). [UM,TM] = rsf2csf(U,T) transforms the real upper quasi-triangular Schur form T to the Schur form TM. Both U and UM are unitary matrices and T is real. The Kalman filter is given by [kest,L,P,M,Z] = kalman(SYS,QN,RN,NN) [kest,L,P,M,Z] = kalman(SYS,QN,RN,NN,SENSORS,KNOWN)

Here SYS is the nominal plant state-space model, QN is the covariance of a white process noise, RN is the covariance of the white measurement noise, NN is the crosscovariance matrix between the process noise and the measurement noise, SENSORS

3.3 Control Toolbox

95

is a vector of indices of measured output signals, and KNOWN is the vector of indices of known input signals. It is often desirable to not only stabilize a system but to also reduce the effect of various disturbances. One way to do that is through H ∞ control. Suppose that we have the system x˙ = Ax + B1 u 1 + B2 u 2 y1 = C1 x + D11 u 1 + D12 u 2 y2 = C2 x + D21 u 1 + D22 u 2

(3.51a) (3.51b) (3.51c)

Here u 1 is a disturbance and y1 is a quantity that measures that disturbance. u 2 is a control input. y2 is an output that is available for control. The goal is to construct a feedback u 2 = K y2 so that not only is the system stabilized but also y1 is reduced relative to u 2 , y2 . hinf carries out H ∞ design of a continuous-time system. [AK,BK,CK,DK,RCOND] = hinf(A,B,C,D,NCON,NMEAS,GAMMA)

Here the n × n A, the n × m B, the p × n C, and D are the continuous-time state-space system coefficient matrices. NCON is the number of control inputs and m ≥ NCON ≥ 0. NMEAS is the number of measurements with p − NMEAS ≥ NCON, p − NMEAS ≥ 0, and m − NCON ≥ NMEAS. The matrices AK, BK, CK, DK are the new system matrices. RCOND is a vector giving some of the condition numbers. RCOND(1) contains the reciprocal condition number of the control transformation matrix TU. GAMMA is a nonnegative parameter which is used in H ∞ design. It has to be sufficiently large for a solution to exist. RCOND(2) contains the reciprocal condition number of the measurement transformation matrix TY, RCOND(3) contains an estimate of the reciprocal condition number of the X-Riccati equation, RCOND(4) contains an estimate of the reciprocal condition number of the Y-Riccati equation. The H ∞ design of a discrete-time system is carried out by dhinf and has identical syntax and meaning of variables as hinf. In terms of (3.51) we have C=

    D11 D12 C1 , D= . C2 D21 D22

Two models are equivalent if one can be transformed into the other with state coordinate changes. It is sometimes desirable to work with a better scaled representation. This can be done with prescale. [SYSNEW,INFO] = prescale(SYSOLD)

INFO is a table with fields: SL: Left scaling factors, SR: Right scaling factors, Equations used to scale a state-space model: As = Tl*A*Tr, Bs = Tl*B, Cs = C*Tr, Ds = D, Es = Tl*E*Tr, Tl = diag(info.SL); Tr = diag(info.SR), Tl and Tr are inverse of each other if the system is a proper state-space model. The H ∞ norm and the H 2 norm of a continuous-time system are computed by h_norm and h2_norm respectively. .

96

3 Modeling and Simulation in OML

[HINFNORM,FREQUENCY] [HINFNORM,FREQUENCY] [HINFNORM,FREQUENCY] [HINFNORM,FREQUENCY]

= = = =

h_norm(A,B,C,D,E) h_norm(A,B,C,D,E,TOL) h_norm(SYSLTI) h_norm(SYSLTI,TOL)

where FREQUENCY is the frequency where the maximum occurs. [H2NORM,NQ] [H2NORM,NQ] [H2NORM,NQ] [H2NORM,NQ]

= = = =

h2_norm(A,B,C,D) h2_norm(A,B,C,D,TOL) h2_norm(SYSLTI) h2_norm(SYSLTI,TOL)

NQ is the order of the resulting numerator Q of the right coprime factorization with inner denominator of G. There are other miscellaneous functions in the tool box. db2mag converts decibels to magnitude where as mag2db converts magnitude to decibels. padecoef computes the Pade coefficients of a time delayed system [NUM,DEN] = padecoef(T,N) [NUM,DEN] = padecoef(T)

Here T > 0, N is a positive integer with default value of 1. H = hankel(C) computes a square Hankel matrix whose first column is C, while H = verb+hankel(C,R)+ computes the Hankel matrix whose first column is C and whose last row is R. hsvd returns Hankel singular values of a state-space or transfer function model. HSV = hsvd(SYS) HSV = hsvd(SYS,’offset’,OFFSET) HSV = hsvd(SYS,’alpha’,ALPHA)

OFFSET is a positive real scalar for the stable/unstable boundary. ALPHS is the Alpha-stability boundary for the eigenvalues of the state dynamics. The control systems Toolbox continues to be updated. Additional capabilities will be included in future releases of OML.

Chapter 4

Optimization

Various optimization problems play a fundamental role in modeling and simulation. There are many optimization algorithms. Some of these are easy to program in OML. However, many of them are very sophisticated. After giving one example of programming an algorithm in OML, this chapter will cover some of the optimization utilities available in OML. Section 4.1 will present some overview comments about optimization which are useful in using the algorithms. Section 4.2 discusses the most general optimization utilities. There is a close relationship between optimization and solving equations in a least squares sense. This is examined in Section 4.3. One application of optimization is parameter fitting. Specialized utilities for this are given. As an OML example we have the Golden-Section search algorithm which is a type of bisection algorithm [50]. This algorithm will be used again later in the Activate part of the book. This algorithm finds where the maximum occurs of a scalar valued unimodal function f on a fixed interval [a, b]. The following script defines the algorithm as a function of f , the interval, and a tolerance. The script then defines a function f and finally applies the algorithm to f . function out=gss(f,a,b,tol) if nargintol if f(c)< f(d) b=d; else a=c; end c=b-(b-a)/gr; d=a+(b- )/gr; end out = [(b+a)/2, f((b+a)/2)]; © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_4

97

98

4 Optimization

end f = @(x) (xˆ2-3)ˆ2; gss(f,0,5)

Running the script gives ans = [Matrix] 1 x 2 1.73206e+00 8.31200e-10

The exact answer is



3 = 1.73205081..

4.1 Comments on Optimization and Solving Nonlinear Equations This chapter discusses the problem of solving the minimization problem min f (x), x

(4.1)

where f is a real-valued function of the vector variable x. Note that maximizing f is the same as minimizing − f , so that all of the utilities given here can also be used with maximization problems. There are a number of characteristics of (4.1) that determine which, if any, of the available utilities will work. They also affect how the optional parameters should be set if a simple call does not work. Constraints The first question is whether there are any restrictions on x in (4.1). If there are, the problem is said to be constrained. As far as OML is concerned there are three types of constraints. Bound, or box, constraints require different entries of x to lie in specified intervals. For example, if x is 3 dimensional, the constraints could be −2 ≤ x(1) ≤ 3 and 2 ≤ x(3) ≤ 4. Linear equality constraints take the form of b T x − c = 0 when b and x are written as column vectors. Linear inequality constraints take the form b T x − c ≤ 0 when b, x are written as column vectors. General nonlinear constraints of the form g(x) = 0. OML can solve problems with some nonlinear constraints. If instead of (4.1) the problem takes the form min x f (x),

(4.2a)

g(x) = 0,

(4.2b)

and f, g are differentiable, then the solution x ∗ of (4.2) satisfies the necessary conditions

4.1 Comments on Optimization and Solving Nonlinear Equations

f x (x) + λT gx (x) = 0 g(x) = 0,

99

(4.3a) (4.3b)

where gx is the Jacobian of g, which is discussed below, and λ is the Lagrange multiplier vector. It is sometimes possible to solve (4.3) using fsolve as discussed later in this chapter. The next question is whether f is a differentiable function and whether its gradient is known. If f is differentiable, then often some type of iterative method is used. Inside the iterative method at each iteration there is the determination of a search direction and a decision on how far to move in that direction. Then there are questions of how long the iteration will continue. Common choices are until f does not change much, until the gradient of f is small, or when the allowed number of iterations or function evaluations has been used. The last criterion can be important if function evaluations are computationally expensive. These types of iterative methods, when they find a minimum, usually find local minima. That is, they find where f is smaller than at nearby x values. Such local minima may or may not be a global minimum, that is, the place where f is smallest for all possible x. A different type of algorithm is sometimes called a “dart-throwing algorithm.” These algorithms vary in philosophy, but basically they continue to evaluate throughout the region but take more values where the function appears small. While usually much slower than iterative methods when both can be used, the dart-throwing algorithms are more apt to find a global minimum and multiple minimum values.

4.1.1 Nonlinear Equation Solving A nonlinear equation takes the form f (x) = 0.

(4.4)

In the simplest case this represents n equations in n unknowns. Such equations are also solved by iterative methods. A key role is played by the Jacobian matrix J (x). If f has m entries f k and x has n entries x p , then ⎤ · · · ∂∂xf1n ⎥ ⎢ J (x) = ⎣ ... . . . ... ⎦ . ∂ fm · · · ∂∂ xfmn ∂ x1 ⎡ ∂ f1

∂ x1

When m = n, and J (x) is invertible, the simplest iterative method is Newton’s method, which is x j+1 = x j − J (x j )−1 f (x j ).

100

4 Optimization

Actual solvers utilize a number of methods to increase the region of convergence and to provide estimates of J .

4.2 General Optimization There are two general optimization utilities in OML. One is fmincon and the other is ga. ga is a genetic algorithm. fmincon and the related fminunc are discussed first. fminunc finds the unconstrained minimum of a real valued function. Its calling syntax is x = fminunc(@func,x0) x = fminunc(@func,x0,options) [x,fval] = fminunc(...)

Here x0 is the initial guess for where the minimum occurs, fval is the optimum value, and x is where this optimum value occurs. func is a function that provides the value of the function to be minimized. Options are set by optimset. The full list of options available in optimset are the following. optimset can be used with fmincon, fminunc, fsolve, and lsqcurvefit. Not all options are available for all functions. For example, the ones that refer to constraints or the Jacobians of constraints do not apply to fminunc. MaxIter: The maximum number of iterations allowed. MaxFunEvals: The maximum number of function evaluations allowed. TolFun: The termination tolerance on the objective function convergence. TolX: The termination tolerance on the parameter convergence. TolCon: The constraint violation allowance, as a percent. TolKKT: The termination tolerance on the Karush-Kuhn-Tucker conditions. GradObj: An ’on’/’off’ flag to indicate whether the objective function will return the gradient as a second return value. GradConstr: An ’on’/’off’ flag to indicate whether the non-linear constraint function will return the gradients as the optional third and fourth return value. If a non-linear constraint is used, then GradConstr must be set the same as GradObj. (Only for fmincon). The function signature is as follows: function [c, ceq, cj, ceqj] = ConFunc(x)

where c and ceq contain inequality and equality constraints, respectively, and cj and ceqj contain their Jacobians. The inequality constraints are assumed to have upper bounds of 0. Jacobian: An ‘on’/’off’ flag to indicate whether the objective function will return the Jacobian as an optional second return value (Only for fsolve, lsqcurvefit). The function signature is as follows: function [res, jac] = System(x)

4.2 General Optimization

101

where res and jac contain the residuals vector of the system function and its Jacobian. Display: An ‘iter’/’off’ flag to indicate whether results at each iteration will be displayed. Note that one iteration may involve many function calls. We have seen examples where MacFunEvals had to be set much higher than MaxIter. Note that a wide variety of problems can be solved by fmincon including linear programs, quadratic programs, and semidefinite programs. As an illustration suppose that it is desired to minimize the function f (x, y, z) = (x − z)2 + 3(x + y + z − 1)2 + (x − z + 1)2 .

(4.5)

Its gradient is  ∇f =

∂f ∂f ∂f , , ∂ x ∂ y ∂z



= [2(x − z) + 6(x + y + z − 1) + 2(x − z + 1), 6(x + y + z − 1), −2(x − z + 1) + 6(x + y + z − 1)] , (4.6) and the initial guess is x0 =[0 0 0]. The following script minimizes (4.5) using the gradient. function z=myf(x) z=(x(1)-x(3))ˆ2+3*(x(1)+x(2)+x(3)-1)ˆ2+(x(1)-x(3)+1)ˆ2; end function z=myg(x) xs=x(1)+x(2)+x(3)-1; z=[2*(x(1)-x(3))+6*xs+2*(x(1)-x(3)+1);6*xs]; z=[z;-2*(x(1)-x(3))+6*xs-2*(x(1)-x(3)+1)]; end options=optimset(’GradObj’,’on’); function [f,g]=costf(x) f=myf(x); g=myg(x); end x0=[0 0 0]; %initial condition [xopt,fopt]=fminunc(@costf,x0,options) % x0 a row vector [xopt,fopt]=fminunc(@costf,x0’,options) % x0 a column vector

When executed, after listing the function definitions, the output gives the results: xopt = [Matrix] 1 x 3 0.08333 0.33333 0.58333 fopt = 0.5 xopt = [Matrix] 3 x 1 0.08333 0.33333 0.58333 fopt = 0.5

102

4 Optimization

For constrained optimization using fmincon, different types of constraints are called differently. The calling syntax of fmincon is x = fmincon(@func,x0) x = fmincon(@func,x0,A,b) x = fmincon(@func,x0,A,b,Aeq,beq) x = fmincon(@func,x0,A,b,Aeq,beq,lb,ub) x = fmincon(@func,x0,A,b,Aeq,beq,lb,ub,nonlcon) x = fmincon(@func,x0,A,b,Aeq,beq,lb,ub,nonlcon,options) [x,fval] = fmincon(...)

Here func is the function to be minimized. x0 is an estimate of where the minimum is located. A,b are a matrix and vector for any linear inequality constraints Ax ≤ b. Aeq,beq are a matrix and vector for any linear equality constraints Aeq x = b. lb lower bound for the design variables. ub upper bound for the design variables. nonlcon is the name of the nonlinear constraints function name. options are set by optimset. Note that there is a fixed order to the syntax. If something is not needed, but a later input is needed, then [ ] is used to indicate an input that is not needed. Note also that having lb and ub can sometimes help the optimization by reducing the region searched. x is where the min occurs and fval is the value at the minimum. As an example, x + y + z − 2 will be minimized over the sphere x 2 + y 2 + z 2 = 6 and with an initial guess [0 0 0]. It often is helpful to use lb and ub to help constrain the search region. The following script will find the solution. Note that the initial guess did not have to satisfy the constraint. Running function y=myf(x) y=x(1)+x(2)+ x(3)-2; end function y=myg(x) y=x(1)ˆ2+x(2)ˆ2+x(3)ˆ2-6; end x0=[0 0 0]; ub=[4 4 4]; lb=[-4 -4 -4]; [x,fval]=fmincon(@myf,x0,[],[],[],[],lb,ub,@myg)

results in the output x = [Matrix] 1 x 3 -1.41422 -1.41422 fval = -6.24264706

-1.41422

4.2 General Optimization

103

4.2.1 Genetic Algorithms Genetic algorithms have a very different philosophy than algorithms like fmincon. In a genetic algorithm one starts with a population of potential solutions. The members of the population have a fitness determined by the value of the cost function. Then on each iteration there is sampling and mutation of the population based on fitness and some heuristics. Genetic algorithms involve frequent evaluations of the cost and therefore are often not best when there is a large number of variables. On the other hand they do not require differentiability and can function without gradients. They are somewhat prone to finding local minima so it is important to check the answers. The OML provided genetic algorithm is ga. The type of optimization problems that ga can be applied to appears similar to the type that fmincon can be applied to. However, the options are quite different. ga finds the constrained minimum of a real function. The calling syntax is: x = ga(@func,nVars) x = ga(@func,nVars,A,b) x = ga(@func,nVars,A,b,Aeq,beq) x = ga(@func,nVars,A,b,Aeq,beq,lb,ub) x = ga(@func,nVars,A,b,Aeq,beq,lb,ub,nonlcon) x = ga(@func,nVars,A,b,Aeq,beq,lb,ub,nonlcon,options) [x,fval] = ga(...)

With the exception of nVars and options this is the same as fmincon. The options are set with gaoptimset. The inputs are func: The function to minimize nVars: The number of variables in the domain. A: A matrix used to compute Ax for inequality constraints. Use [ ] if unneeded. b: The upper bound of the inequality constraints Ax ≤ b. Use [ ] if unneeded. Aeq: A matrix used to compute Aeq x for equality constraints. Use [ ] if unneeded. beq: The right hand side of the equality constraints Aeq x = beq . Use [ ] if unneeded. lb:The design variable lower bounds.Use [ ] if unbounded. ub: The design variable upper bounds. Use [ ] if unbounded. nonlcon: The non-linear constraints function name. Use [ ] if unneeded. options: A struct containing options settings. The outputs are x which is the location of the function minimum and fval which is the minimum of the function. The available options are Generations: The maximum number of generations allowed. InitialPenalty: The initial penalty multiplier. InitialPopulation: The population to initialize the algorithm. PopInitialRange: A range from which the initial population is randomly selected.

104

4 Optimization

PopulationSize: The size of the population. TolCon: The constraint violation allowed as a percentage. Display: An ’iter’/’off’ flag to indicate whether results for each generation will be displayed. The default value of Generations is 100 times the number of variables, up to a maximum of 1000. The default value of PopulationSize is 100. PopInitialRange can be specified as a two element vector applied to each design variable, or as a 2 × N matrix, where N is the number of design variables. TolCon only applies when ga cannot find a feasible solution. In such cases the function will return the best infeasible solution found within the allowed violation, along with a warning. The algorithm does not attempt to minimize the utilized violation. The TolCon value is applied as a percent of the constraint bound, with an absolute minimum of 1.0e − 4 applied when the bound is zero or near zero. An elite count of 10% of the population is advanced to the next generation. Currently changing this value is not an option. As an example let us minimize | sin(x1 − π )| + | sin(x2 − 2)|. Note that this problem is not differentiable at the optimal solutions and has a number of minima. Using the script function val=objective(x) val=abs(sin(x(1)-pi))+abs(sin(x(2)-e)); end options=gaoptimset(’Generations’,20,’PopulationSize’,10); n=2; lb=[-2 -2]; ub=[5 4]; [x,fval]=ga(@objective,2,[],[],[],[],lb,ub,[],options)

results in x = [Matrix] 1 x 2 4.84887 -0.35880 fval = 0

while using options=gaoptimset(’Generations’,200,’PopulationSize’,100);

results in x = [Matrix] 1 x 2 -0.00001 -0.42332 fval = 2.20347616e-05

This section concludes with an example where ga performs better than fmincon. In this example there is no derivative at the minimum. The example is to minimize g(x) = (|x − π |)1/10 on the interval [−2 6]. The solution of course is π = 3.14159265. The script function z=cost(x) z=(abs(x-pi))ˆ(1/10); end

4.2 General Optimization

105

options1=gaoptimset(’Generations’,100,’PopulationSize’,10); [xa,fvala]=ga(@cost,1,[],[],[],[],-2,6,[],options1); [xa,fvala] options2=optimset(’MaxIter’,100); x0=0; [x,fval]=fmincon(@cost,x0,[],[],[],[],-2,6,[],options2);

produces the output ans = [Matrix] 1 x 2 3.14160 0.28957 % approximate solution x0 = 0 Warning: algorithm did not converge, returned best estimate in call to function fmincon at line number 9 ans = [Matrix] 1 x 2 3.13762 0.57530 % worse approximation.

Genetic algorithms sometimes do better on problems with a lot of local minimums. To illustrate let us minimize f (x) = |x − π |1/2 (2 + sin(5x)2 ) over [−1 7]. Running the script function z=mcost(x) z=((abs(x-pi)).ˆ(1/2)).*(2+sin(5*x).ˆ2); end x=-1:0.01:7; h=plot(x,mcost(x)) options1=optimset(’MaxIter’,100); x0=0; [a,v]=fmincon(@mcost,x0,[],[],[],[],-1,7,[],options1) options2=gaoptimset(’Generations’,100,’PopulationSize’,10); [aa,vv]=ga(@mcost,1,[],[],[],[],-1,7,[],options2)

results in a = 3.73599822 v = 1.56390971 aa = 3.14159052 vv = 0.00292258295

Notice that fmincon has stopped at a local minimum and ga has done a much better job. The graph of the cost function is shown in Figure 4.1.

4.3 Solving Nonlinear Equations The theory and algorithms for solving a nonlinear system of equations f (x) = 0

(4.7)

intertwines in a number of ways with those for optimization. Assuming that f is differentiable, the primary OML utility is fsolve. If fsolve converges to a

106

4 Optimization

Fig. 4.1 Graph of f (x) = |x − π |1/2 (2 + sin(5x)2 )

solution that is not a zero of the system, it will produce a warning indicating that a best fit value is being returned. fsolve has the calling sequence [x [,v]]=fsolve(@f,x0)

where @f is the handle for the function to be solved. Here x0 : Real vector that is the initial guess for the function argument. @f: External providing function in (4.7). Options are set with optimset. For example, to have up to 100 iterations and display intermediate results use options = optimset(’MaxIter’,100,’Display’,’iter’)

As an illustration of using fsolve consider the problem of min f (x, y, z) = min(x − z)2 + 3(x + y + z − 1)2 + (x − z + 1)2 ,

(4.8)

where g(x, y, z) = 1 − x − 3y − z 2 = 0.

(4.9)

As noted earlier, the necessary condition for the minimum of this problem is that it be a solution of ∇ f + λ∇g = 0 g = 0. Executing the next script:

(4.10) (4.11)

4.3 Solving Nonlinear Equations

107

function z=func(x) xs=x(1)+x(2)+x(3)-1; w1=[2*x(1)-x(3)+6*xs+2*(x(1)-x(3)+1),6*xs]; w1=[w1,-2*(x(1)-x(3))-6*xs-2*(x(1)-x(3)+1)]; w2=[-1 -3 -2*x(3)]; z=[w1’+x(4)*w2’;1-x(1)-3*x(2)-x(3)ˆ2]; end x0=[0 0 0 0]; [x,v]=fsolve(@func,x0);

gives > v v = [Matrix] 4 x 1 -4.16334e-15 -3.77476e-15 -6.38847e-11 -5.14742e-11 > x x = [Matrix] 1 x 4 0.19497 -0.17983 1.15954

0.34936

Note that v gives the value of func at the found solution and thus should be zero. This gives us an idea of how accurate our solution is.

4.4 Parameter Fitting Fitting formulas to data is a fundamental part of many scientific problems. OML has a utility that is especially designed for data fitting, lsqcurvefit . For a given function G( p, x), lsqcurvefit finds the best vector of parameters p for approximating G( p,

xi ) = 0 for a set of measurement vectors xi . The vector p is n G(x, z i )T G(x, z i ). That is, p is the solution of a weighted found by minimizing i=1 least squares problem. G with RG for an invertible matrix R we can

nBy replacing G(x, z i )T R T RG(x, z i ) which is a weighted least squares. get the minimum of i=1 The syntax is p = lsqcurvefit(@func,p0,xdata,ydata) p = lsqcurvefit(@func,p0,xdata,ydata,lb,ub) p = lsqcurvefit(@func,p0,xdata,ydata,lb,ub,options) [p,fval] = lsqcurvefit(...)

Here func: The function y = func( p, x) to minimize. p0: An estimate of the location of the minimum set of parameters. xdata: The domain values for which the best fit is performed. ydata: The range values for which the best fit is performed. lb: The fitting parameter lower bounds. Not currently supported, use [ ]. ub: The fitting parameter upper bounds. Not currently supported, use [ ].

108

4 Optimization

options+: A struct containing options settings. Options are set with optimset. As an example suppose it is desired to fit y = p1 + p2 e− p3 x to six data points and then graph the data points and the fitting function on the same graph. It is often the case that there is more than one y value measured for a given x value especially in the presence of measurement error and thus an exact fit is not always expected. This is illustrated in the following script. function y=func(p,x) y=p(1)+p(2)*exp(-p(3)*x); end x=[0;0;1;2;2;3]; y=[1;2;0.9;0.9;0.8;0.2]; p0=[1;1;1]; [p,resnorm]=lsqcurvefit(@func,p0,x,y) scatter(x,y); hold xx=0:0.1:4; yy=func(p,xx); plot(xx,yy)

which results in Warning: maximum iterations exceeded, returned last estimate in call to function lsqcurvefit at line number 7 p = [Matrix] 3 x 1 -51.07250 52.54752 0.00734 resnorm = 0.599288464 ans = 12.0720365

and the Figure 4.2. Note that the chosen function to fit is monotonic for all parameter values provided p2 , p3 are nonzero and it has no inflection points so the fit is as good as can be expected.

4.4.1 Linear Programs The basic linear programing problem is to minimize p T x subject to linear constraints. These linear constraints can be equality or inequality constraints. The inequality constraints can be one-sided or bound constraints. These problems can be solved by fmincon. The general form of the problem is min x p T x C1 x ≤ b1

(4.12a) (4.12b)

ci ≤ x ≤ cs C2 x = b2 .

(4.12c) (4.12d)

4.4 Parameter Fitting

109

Fig. 4.2 Parameter fit

Note that if there are no constraints at all, then the problem has no finite solution if p is not the zero vector. With linear programing problems the gradient is known to be just p T . Thus after the script provides the vector p and the matrices and vectors C1 , C2 , ci , cs , b1 , b2 , the following script will produce the answer. options=optimset(’GradObj’,’on’) function [val,p’]=cost(x,p) val=p’*x end costl = @(x) cost(x,p) [mval,mx]= fmincon(costl,x0,C1,b1,C2,b2,ci,cs,[],options)

Chapter 5

Examples

In this chapter we will give several examples of using OML to solve various problems from applications. A number of additional examples will be given in the Activate part of the book. Here we focus on problems that do not require the extra capabilities of Activate.

5.1 Boundary Value Problems by Shooting Boundary value problems arise in a number of application areas. There are a number of different approaches to solving boundary value problems [2]. Those that rely on differences also require the use of sparse linear algebra to deal with the large linear algebra problems that arise with repeated grid refinement. Here the focus is on the use of shooting methods [30]. There are more sophisticated versions of shooting, such as multiple shooting, but only single shooting is discussed in this Section. A general boundary value problem on the interval [t0 t1 ] would have the form y˙ = f (t, y)

(5.1a)

0 = B(y(t0 ), y(t1 )).

(5.1b)

Equation (5.1b) are the boundary conditions and there are usually n of them where y is n-dimensional. For our illustration assume that (5.1) has the form y˙1 = f 1 (t, y1 , y2 )

(5.2a)

y˙2 = f 2 ((t, y1 , y2 ) y1 (t0 ) = a0

(5.2b) (5.2c)

0 = B(y(t1 )),

(5.2d)

© Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_5

111

112

5 Examples

so that part of y1 (t0 ) is specified and part of y(t1 ) is specified. The shooting method works by treating y2 (t0 ) = p as a parameter to be solved for. If y(t, t0 , y0 ) is the solution given the initial condition y0 , then p is found by solving the equation B(y(t1 , t0 , [a; p]) = 0 for p. The function B(y(t1 , t0 , [a; p]) is evaluated by performing the numerical integration. This approach can work well on many problems but it can have numerical difficulty if some solutions become close on the interval [t0 t1 ]. As a simple illustration of how difficulty can occur consider y˙1 = A11 y1 , y˙2 = A22 y2 ,

y1 (0) = a y2 (T ) = b

(5.3a) (5.3b)

A shooting method has to be able to solve e A22 T y2 (0) = b for y2 (0). This problem can become very ill conditioned if A22 has any negative eigenvalues and T is large enough. As an example using shooting, consider the equations for the large motion of a lightly damped vertical pendulum. It is initially hanging vertical and it is desired to impart a velocity so that after T time units the pendulum is in an upright position. This is y¨ = − sin(y) − d y˙ y(0) = 0

(5.4a) (5.4b)

y(T ) = π.

(5.4c)

Here y is the angle the pendulum makes with the vertical and 0 is the downward position. For an ODE, existence and uniqueness of solutions follows from continuity statements about the equation and its derivatives. With a BVP it is important to keep in mind that even if the differential equation part of a given BVP may have nice smooth equations, a solution may not exist or the solution may not be unique for a given boundary condition. First (5.4) is rewritten as y˙1 = y2 y˙2 = − sin(y1 ) − dy2 y1 (0) = 0 y1 (T ) = π. The following script will solve this BVP by shooting. clf; function val=rhs(t,y) % diff eqn d=0.01; y1=y(2); y2=-sin(y(1))-d*y(2); val=[y1 y2];

(5.5a) (5.5b) (5.5c) (5.5d)

5.1 Boundary Value Problems by Shooting

113

end function val=bvfun(p) % error at end T=5; tin=[0,T]; y0=[0 p]; options=odeset(’AbsTol’,1d-8); [tt,yy]=ode45(@rhs,tin,y0,options); val=yy(end,1)-pi; end options2=optimset(’MaxIter’,100); p0= 3; z=fsolve(@bvfun,p0,options2) % find initial condition y0new=[0 z]; grid2=0:0.1:5; [ttt,yyy]=ode45(@(t,y) rhs(t,y),grid2,y0new); abs(yyy(end,1)-pi) plot(ttt,yyy(:,1)); % plot solution for initial cond hold plot(5,pi,’o’); % plot right hand side target

Running this script results in the output for the needed initial velocity and the final error z = 2.02093478 % initial value ans = 0.00651469365 % error at right boundary condition.

and the Figure 5.1. It is worth noting that if our initial guess was p=-0.3, then a solution was not obtained. In an alternative implementation of the shooting method, we can provide the Jacobian of the system solved by fsolve. The Jacobian can be computed by lin-

Fig. 5.1 Solution of BVP (5.5) for y1 found by shooting

114

5 Examples

earizing the system. Suppose the boundary value problem (for example System (5.5) is expressed as follows Y˙ = F(Y ) Then by introducing a variation in Y , we have ˙ = F(Y + δY ), Y˙ + δY so by neglecting high order terms we have ˙ = FY (Y )δY δY where FY =

∂F . ∂Y

This is a linear system, thus δY (T ) = Φ(T )δY (0)

(5.6)

where Φ is the transition matrix of the system, i.e., the solution of Φ˙ = FY (Y )Φ, Φ(0) = I. In the case of System (5.5), we have Φ˙ =



 0 1 Φ, Φ(0) = I. − cos(y1 ) −d

Note that this system must be integrated along with the original system because the value of y1 is required during integration. So we have ∂Y (T ) = Φ(T ). (5.7) ∂Y (0) In our example, the Jacobian we need to compute is   ∂(y1 (T ) − π ) ∂ y1 (T )   0 = = 1 0 Φ(T ) = Φ1,2 (T ). 1 ∂p ∂ y2 (0)

(5.8)

So the value of Φ1,2 (T ) can be provided as the Jacobian of the system being solved by fsolve. This method is implemented in the following OML code  where  the state of the differential equation being solved is augmented from Y to Φ Y : options3=optimset(’MaxIter’,100,’Jacobian’,’on’); function dPhiY=rhs(t,PhiY) % diff eqn

5.1 Boundary Value Problems by Shooting

115

PhiY=reshape(PhiY,2,3); d=0.01; Y=PhiY(:,end); Phi=PhiY(:,1:end-1); dy1=Y(2); dy2=-sin(Y(1))-d*Y(2); dPhi=[0,1;-cos(Y(1)),-d]*Phi; dPhiY=[dPhi,[dy1;dy2]]; dPhiY=dPhiY(:)’; end function [val,jac]=bvfun(p) % error at end T=5; tin=[0,T]; PhiY0=[eye(2,2),[0;p]]; % PhiY0=[Phi0,Y0] options=odeset(’AbsTol’,1d-8); [tt,YY]=ode45(@rhs,tin,PhiY0(:)’,options); PhiYT=YY(end,:);PhiYT=reshape(PhiYT,2,3); yT=PhiYT(:,end); PhiT=PhiYT(:,1:end-1); val=yT(1)-pi; jac=PhiT(1,2); end p0= 3; [z]=fsolve(@bvfun,p0,options3) % find initial condition

If the differential equation is linear, then it is not necessary to use an iterative solver like fsolve. Instead one may proceed as follows. Suppose the BVP is y˙1 = A11 y1 + A12 y2 y˙2 = A21 y1 + A22 y2 y1 (t0 ) = a0 0 = By(t1 ) − b.

(5.9a) (5.9b) (5.9c) (5.9d)

The key idea is that the solutions of (5.9) for a homogenous linear differential equation x˙ = Ax form a vector space and any other solution can be written in terms of a basis of this vector space. Again let y(t, t0 , y0 ) denote the solutions of y˙ = Ay, y(t0 ) = y0 . Suppose that A is n × n and y1 is r -dimensional. Let φi be an n-dimensional vector with 1 in the i-th place and zeros elsewhere. Let φ0 be [a0; zeros(n-r,1)]. Then every solution of (5.9a)–(5.9b) can be written as y = y(t, t0 , φ0 ) +

n 

  ci y(t, t0 , φi ) = y(t, t0 , φ0 ) + y(t, t0 , φr +1 ) . . . y(t, t0 , φn ) c

i=r +1

where c is a vector with n − r entries.

116

5 Examples

Then to solve the BVP one needs only to solve the algebraic equation   B y(t, t0 , φr +1 ) . . . y(t, t0 , φn ) c = Bb − By(t, t0 , φ0 ). To illustrate solving this with OML and to make some other points, consider the following example. It models a linear spring mass system with a spring connecting two masses and each mass also connected to a fixed object by a spring. The mathematical model is m 1 x¨1 = −k1 x1 − d1 x˙1 + k2 (x2 − x1 )

(5.10a)

m 2 x¨2 = −k2 (x2 − x1 ) − k3 x2 − d2 x˙2 .

(5.10b)

Here m 1 , m 2 are the two masses, k1 , k2 , k3 are the three spring constants, and d1 , d2 are coefficients of friction for each mass and may represent internal or external damping. x1 , x2 measure the displacement of the masses from the equilibrium rest position. Of course, this model is only reasonable for motions that do not totally compress a given spring. With the change of variables y1 = x1 , y2 = x˙1 , y3 = x2 , y4 = x˙2 , the linear system ⎤ ⎡ 0 10 0 ⎢− (k1 +k+2) −d1 − k2 0 ⎥ m1 m1 ⎥y (5.11) y˙ = ⎢ ⎣ 0 0 0 1 ⎦ k2 k2 +k3 0 − m 2 −d2 m2 results. The boundary conditions will be 

   y1 (0) y3 (T ) = a0 , =b y2 (0) y4 (T )

where T is the terminal time. The following generic script will solve this BVP and evaluate the solution by performing a simulation and seeing how close the terminal boundary condition is met. options=odeset(’AbsTol’,10ˆ(-7)); a0=[0.1, 0]; b=[-0.1 0.2]; phi0=[a0,0,0]; phi3=[0 0 1 0]; phi4=[0 0 0 1]; T=5.0; % final time function val=rhs(t,y) k1=1; k2=0.5; k3=1.5; m1=2; m2=0.7; d1=0.01;

5.1 Boundary Value Problems by Shooting

117

d2=0.02; A=[0 1 0 0;-(k1+k2)/m1,-d1,k2/m2,0;0 0 0 1;... k2/m2,0,-(k2+k3)/m2, -d2]; val=A*y; end B=[0 0 1 0;0 0 0 1]; [t0,y0]=ode45(@(t,y) rhs(t,y),[0 T], phi0,options); [t3,y3]=ode45(@(t,y) rhs(t,y),[0 T], phi3,options); [t4,y4]=ode45(@(t,y) rhs(t,y),[0 T], phi4,options); y0p=y0(end,:); y3p=y3(end,:); y4p=y4(end,:); c=B*[y3p’,y4p’]\(b’-B*y0p’) y0c=[a0,c’]; [t,ytest]=ode45(@(t,y) rhs(t,y),[0 T], y0c,options); ytest(end,[3 4])-b

Running this script results in the output c = [Matrix] 2 x 1 0.04254 -0.26061 ans = [Matrix] 1 x 2 -0.00006 -0.00002

and we see the right boundary condition holds to reasonable accuracy. For linear time invariant systems note that this example could be written as e

TA

    a0 X = c b

or b = E 21 a0 + E 22 c, where E i j are submatrices of e AT . For this example EE=expm(T*A); cc=EE([3 4],[3 4])\(b’-EE([1 2],[3 4])*a0’) y0cc=[a0,cc’] [t,ytest2]=ode45(@(t,y) rhs(t,y),[0 T], y0cc,options); ytest2(end,[3 4])-b

produces ans = [Matrix] 1 x 2 0.00009 0.00013

which is comparable accuracy. However, suppose that everything is the same except the problem is more strongly damped with d1 = 1.3 and d2 = 1.1. Now the error in meeting the terminal boundary condition is ans = [Matrix] 1 x 2 -0.00006 -0.00002

118

5 Examples

ans = [Matrix] 1 x 2 0.02719 2.53059

where the first error vector is for shooting using the numerical integrator while the second uses the matrix exponential so that on this example shooting was more accurate. In another problem it might be desirable to choose a different integrator and to set the tolerances differently.

5.2 Parameter Fitting and Implicit Models In many applications the scientist knows the general form of the equations that model the process, but specific parameter values are not known. Also, in many application areas the models are often differential algebraic equations (DAE). This section shall give an illustration of parameter fitting with a DAE model. The general procedure will be the following. Suppose that the model that is to be found is a DAE F( y˙ , y, t, p) = 0, (5.12) where p is a vector of unknown parameters. Suppose that the model is to be defined over the time interval [0 T ] and suppose that measurements are taken of the actual physical process for some function of y at times ti for i = 0, . . . , N . That is, there are the measured quantities z i = h(y(ti ), ti ), i = 0, . . . , N .

(5.13)

Suppose that J of these trials are done and let z i, j be the result of the j-th trial at time ti . The initial condition for (5.12) could be fixed or it could be viewed as more parameters to be determined. The initial condition is taken fixed in the example that follows, but that does not change the procedure. It is desired to determine p such that the solution of (5.12) fits the observation data as closely as possible. There are a couple of ways to do this in OML. One way would be to use fmincon or fminunc. Another way is to use the function parfit. The function parfit will fit a function e = G( p, z) to data. Here fminunc is used with a cost function of the same form that parfit uses except that by using fminunc it is possible to control the step used for the finite difference computation of the gradients. It is not efficient to call for the integration of (5.12) for every z i j . It is more efficient to do just one integration for each value of j. Thus the z in G( p, z) is take to be the vector of all z i, j for a fixed j.

5.2 Parameter Fitting and Implicit Models

119

5.2.1 Mathematical Model Many applications use polynomial models. In some cases these are argued for on first principles. In other applications they occur because if linear equations do not suffice, then the next natural thing to try is a polynomial equation. If a linear approximation is not adequate, then the next level of Taylor approximation uses quadratic functions. The DAE considered here has quadratic terms and arises as the model of a batch reactor and is sometimes used as a test problem in the chemical engineering literature [14, 35]. The equations are y˙1 = − p3 y2 y8

(5.14a)

y˙2 = − p1 y2 y6 + p2 y10 − p3 y2 y8 y˙3 = p3 y2 y8 + p4 y4 y6 − p5 y9

(5.14b) (5.14c)

y˙4 = − p4 y4 y6 + p5 y9 y˙5 = p1 y2 y6 − p2 y10

(5.14d) (5.14e)

y˙6 = − p1 y2 y6 − p4 y4 y6 + p2 y10 + p5 y9 0 = −0.0131 + y6 + y8 + y9 + y10 − y7

(5.14f) (5.14g)

0 = p7 y1 − y8 ( p7 + y7 ) 0 = p8 y3 − y9 ( p8 + y7 ) 0 = p6 y5 − y10 ( p6 + y7 ).

(5.14h) (5.14i) (5.14j)

In its original form this problem is known to be very stiff and is used for a test problem for parameter sensitivity software. A slightly modified set of initial conditions is used here.

5.2.2 OML Implementation The illustration of the procedure proceeds as follows. The observational data will be given by a simulation followed by the addition of random perturbations. Begin with a fixed value of p, which is denoted by ptrue. For the simulations the DAE integrator ode15i is used. The OML implementation of ode15i requires not only an initial value of y(0) but also of y˙ (0). In the current OML environment, the system is coded as follows: function [r]=reactor(t,y,ydot,p) r(1)=ydot(1)+p(3)*y(2)*y(8); r(2)=ydot(2)+p(1)*y(2)*y(6)-p(2)*y(10)+p(3)*y(2)*y(8); r(3)=ydot(3)-p(3)*y(2)*y(8)-p(4)*y(4)*y(6)+p(5)*y(9); r(4)=ydot(4)+p(4)*y(4)*y(6)-p(5)*y(9); r(5)=ydot(5)-p(1)*y(2)*y(6)+p(2)*y(10); r(6)=ydot(6)+p(1)*y(2)*y(6)+p(4)*y(4)*y(6)-p(2)*y(10)-p(5) *y(9);

120

5 Examples

r(7)=-0.0131+y(6)+y(8)+y(9)+y(10)-y(7); r(8)=p(7)*y(1)-y(8)*(p(7)+y(7)); r(9)=p(8)*y(3)-y(9)*(p(8)+y(7)); r(10)=p(6)*y(5)-y(10)*(p(6)+y(7)); end

Given a parameter value p and an initial state value y, the initial value of y˙ is found by function yp=ypinit(y,p) yp(1)=-p(3)*y(2)*y(8); yp(2)=-p(1)*y(2)*y(6)+p(2)*y(10)-p(3)*y(2)*y(8); yp(3)= p(3)*y(2)*y(8)+p(4)*y(4)*y(6)-p(5)*y(9); yp(4)=-p(4)*y(4)*y(6)+p(5)*y(9); yp(5)= p(1)*y(2)*y(6)-p(2)*y(10); yp(6)=-p(1)*y(2)*y(6)-p(4)*y(4)*y(6)+p(2)*y(10)+p(5)*y(9); A=[-1 1 1 1;y(8),y(7)+p(7),0, 0;y(9), 0, p(8)+y(7), 0]; A=[A;y(10), 0, 0, p(6)+y(7)]; B=[-yp(6);p(7)*yp(1);p(8)*yp(3);p(6)*yp(5)]; z=inv(A)*B; yp=[yp(1:6),z’]’; end

Since the model (5.14) is a DAE, only some initial conditions will be consistent. Assume that parameter values { p6 , p7 , p8 } are known and fixed at the values ptrue(6:8). In this case the space of consistent initial conditions is independent of the remaining values of pi and one does not have to worry about finding new consistent initial conditions as the parameters are varied. Take fixed initial values of the first 6 components of the initial condition y(0). The remaining values of y(0) are found by solving the last four equations in (5.14) using fsolve. This ensures that our y(0) is consistent to high order. ptrue=[21.893;2.14e3;32.318;21.893;1.07e3;6.65e-3;4.03e-4; 5.e-5/32]; function z=constraints2(y2,y1,p) r = reactor(0,[y1;y2],0*ones(10,1),p); z = r(7:10); end function [y,v]=initial_condition(y1,p) constraints = @(y2) constraints2(y2,y1,p); [y2,v]=fsolve(constraints,zeros(4,1)); y =[y1;y2];

The initial condition is generated and its accuracy tested with y01=[1.5776;8.32;0;0;0;0]; p=ptrue; [y0,v]=initial_condition(y01,p); norm(v)

5.2 Parameter Fitting and Implicit Models

121

Fig. 5.2 Simulation of (5.14)

which gives ans = 1.34396e-11

Simulations with ode15i using y(0) and ptrue show that the solutions are close to steady state by around t = 0.5. Accordingly our observations are taken on the interval [0 0.5]. These simulations, one of which is shown in Figure 5.2 also show that the components of yi vary greatly in size. Figure 5.3 plots the same solutions but with the last 7 multiplied by 100. A given experiment will consist of observing the value of the first six components of y every 0.05 seconds for a total of 10 time points. Ignore the initial value since it is fixed. Hence the observation times are 0.05:0.05:0.5. The experimental outcomes are generated by taking a simulation using ptrue and then perturbing the entries by a uniformly generated random vector. The perturbations are scaled so that they are of the same relative size for each entry and each observation time. Nine such observations are taken so that J = 9. The following code carries out the calculations. t0=0; tt=0:0.05:0.5; options=odeset(’AbsTol’,1d-10); yp0true=ypinit(y0,ptrue); reactrue = @(t,y,ydot) reactor(t,y,ydot,ptrue); [tt,yy]=ode15i(reactrue,tt,y0,yp0true,options); yy=yy(2:11,1:6); yy(:,4:6)=100*yy(:,4:6); rtrue=yy(:); rand(’seed’,20); N=9; obs= rtrue*ones(1,N); obs= obs.*(1+ 0.1*(rand(60,N)-0.5));

122 Fig. 5.3 Simulation of (5.14) with last 7 states multiplied by 100

function ee=G(p1,y0,ptrue,obs,tt) p=[p1;ptrue(6:end)] ; yp0=ypinit(y0,p); options=odeset(’AbsTol’,1d-10); reacp = @(t,y,ydot) reactor(t,y,ydot,p); [tt, rr]=ode15i(reacp,tt,y0,yp0,options); rr=rr(2:11,1:6); rr(:,4:6)=100*rr(:,4:6); rr=rr(:); ee=0; for i=1:size(obs,2) gg = (rr-obs(:,i)); ee = ee + gg’*gg; end end function [f,g]=costf(p,y0,ptrue,obs,tt) f=G(p,y0,ptrue,obs,tt); g=0*p; pa=sqrt(eps)*10*abs(p); for j=1:5 v=0*p; v(j)=pa(j); g(j)=(G(p+v,y0,ptrue,obs,tt)-f)/v(j); end end options2=optimset(’GradObj’,’on’,’MaxIter’,200); costff=@(p) costf(p,y0,ptrue,obs,tt); p0=ptrue(1:5)*0.5; [pest,err]=fminunc(costff,p0,options2);

5 Examples

5.2 Parameter Fitting and Implicit Models

123

[p0’;pest’;ptrue(1:5)’]

which results in a matrix whose first row is the initial parameters, the second row is the estimated parameters, and the third row is the true parameters, ans = [Matrix] 3 x 5 10.94650 1070.00000 10.79699 1070.30410 21.89300 2140.00000

16.15900 31.99602 32.31800

10.94650 18.30381 21.89300

535.00000 1079.27041 1070.00000

and in the cost associated with the initial guess, the estimated, and the true parameters. ans = [Matrix] 1 x 3 462.68452 4.59794 4.69817

The results are graphed by p=[ptrue]; yp0=ypinit(y0,p); reacp=@(t,y,ydot) reactor(t,y,ydot,p); [tt,krt]=ode15i(reacp,tt,y0,yp0,options); p=[p0;ptrue(6:end)]; yp0=ypinit(y0,p); reacp=@(t,y,ydot) reactor(t,y,ydot,p); [tt,kr0]=ode15i(reacp,tt,y0,yp0,options); p=[pest;ptrue(6:end)]; yp0=ypinit(y0,p); reacp=@(t,y,ydot) reactor(t,y,ydot,p); [tt,krf]=ode15i(reacp,tt,y0,yp0,options); scale_r=[ones(1,3),100*ones(1,3)]; for ii=1:6 figure(ii); plot(tt,krf(:,ii),’x’); hold plot(tt,krt(:,ii)); plot(tt,kr0(:,ii),’+’); nz=size(obs,2); for k=1:N obsk=obs(:,k); obsk=reshape(obsk,10,6); plot(tt(2:11)’,obsk(:,ii)./scale_r(ii),’o’); end end

The plots are shown in Figures 5.4, 5.5 and 5.6. Here the true solution is plotted by a solid line. The estimated solution is plotted with an x and the initial estimate is plotted by +. The observations are plotted by o. Note that the initial estimate was far away from the true solution, however, the estimated graph is quite close to the true graph.

5.2.2.1

Comments

fminunc calls an iterative solver. Each time the cost G is evaluated there is a call to ode15i. For more complicated problems with more parameters or longer

124

5 Examples

Fig. 5.4 Initial guess, truth, estimated solution, and observations for state variables y1 and y2

Fig. 5.5 Initial guess, truth, estimated solution, and observations for state variables y3 and y4

Fig. 5.6 Initial guess, truth, estimated solution, and observations for state variables y5 and y6

time intervals these calls can be computationally expensive. As implemented in the previous illustration there would be N calls for each value of p. If these calls are taking too much time, one can directly formulate the cost as i eiT ei , and have to do only one call to ode15i for each value of p.

5.2 Parameter Fitting and Implicit Models

125

Parameter estimation is an important part of many engineering and scientific procedures. The example given illustrates two important facts. One is that since one is using the data to construct a model that predicts the data, it is important to have enough data to cover the region in which one wishes to use the model. Secondly, the criterion is the ability to predict the observations. If the parameter estimates are of interest themselves, then considerable more analysis and care may be needed to determine how good the estimate is. Notice in this example that the graphs using the estimated parameters appear to be very close to the graphs for the true parameter values. So the numerical algorithm is doing a good job of giving us parameter values that give the desired behavior. However, the estimated parameter values are not always close to the true parameter values. Here the estimates of p1 , p2 are very close to the true p1 , p2 but that is not true for all the other values of p. In the nonlinear case there are the added problems of local minima when one is solving for parameter estimates. But even for the linear case y = Ax, it is important to keep in mind that the following three problems are distinct and can produce different estimates Aˆ for A: 1. Given data {xi , yi } find the value Aˆ that gives the best prediction law for y given an additional value of x. 2. Given data {xi , yi } find the value Aˆ that gives the best prediction law for x given an additional value of y. 3. Given data {xi , yi }, which is assumed to come from a model y = Ax, find the value of Aˆ that gives the best estimate of A. The functions parfit and fminunc, as described here are being used for the first type of problem since the error in the value of G is being minimized. The function G needs to be formulated differently if either problem 2 or 3 is to be solved. Finally, this example illustrates an important aspect of solving optimization problems. Finding the optimal solution even when it is known to exist can be difficult. It is important sometimes to determine that the gradient approximation is accurate enough. Another problem is that the large differences in magnitude of the components can lead to inaccuracy. Accordingly a factor of 100 is put in the function evaluation, which helps prevent stagnation and increases accuracy of gradients. In particular, rescaled y(4:6) gives these variables a range similar to those in y(1:3). This was necessary to increase the part dedicated to y(1:3) in the global cost. In trying to solve a parameter problem in practice when the solution is not known it is often helpful to try first what we have done here. That is, generate observations by simulation with known parameters and then try first to find the known parameters. This helps in checking that the problem is properly coded and gives insights into the problem’s behavior. Thus the problem solved in this section is not as academic as it appears and is representative of part of the solution of real problems.

126

5 Examples

Fig. 5.7 Pendulum on a horizontally moving cart

5.3 Open-Loop Control of a Pendulum It is often desired to design controls so that a given system performs correctly. In optimal control the control is designed to maximize or minimize some criteria which could be energy or fuel or time required or quantity produced but it is often called the cost. There are a number of techniques for solving optimal control problems [8, 34]. In our example here control parametrization will be used. In control parametrization the control is described by a finite set of parameters. The cost for a given set of parameters is evaluated using a simulation. This cost function is then minimized (or maximized) by an optimizer. The type of control, the parametrization, the cost, and the dynamics all interact to determine how best to solve the problem by control parametrization. If the control has discontinuities then the choice of integrator is affected since frequent restarts favor single step methods like Runge-Kutta methods since they start at higher order. The requested accuracy of any simulations has to be coordinated with the tolerances in an optimizer. Consider the classical control problem of a pendulum mounted on a motor-driven cart traveling horizontally. This is pictured in Figure 5.7. Two different problems are considered. One is a tracking problem on a fixed interval and the other is a swing up in minimum time. In each case the theory of optimal control can often shed light on what the optimal control looks like ahead of time and this information can be incorporated into our parametrization.

5.3.1 Model We assume that all motion takes place in a plane so this is a 2-D model. Assume the pendulum can swing in a plane and rotates around a shaft so that the pendulum can move a full 360 degrees. The mathematical model is (M + m)¨z + ml θ¨ cos(θ ) − ml θ˙ 2 sin(θ ) = u(t) l θ¨ + z¨ cos(θ ) − g sin(θ ) = 0.

(5.15a) (5.15b)

5.3 Open-Loop Control of a Pendulum

127

Here M is the mass of the cart, m is the mass at the end of the pendulum, θ is the angle that the pendulum makes with the vertical direction, z is the horizontal position of the cart, and u is a horizontal force acting on the cart. θ = 0 corresponds to the pendulum in the up position. Assume that there is no friction. The state of this system can be defined as follows: ⎡ ⎤ ⎡ ⎤ z z ⎢θ ⎥ ⎢ θ ⎥ ⎥ ⎢ ⎢ . (5.16) x =⎣ ⎦=⎣ ⎥ z˙ zd ⎦ θd θ˙ The system dynamics can then be expressed as follows: x˙ = f (x, u),

(5.17)

where f is easily obtained from (5.15a)–(5.15b) as z˙ = z d θ˙ = θ      d m Lθd2 sin(θ ) + u M + m ml z˙ d . = g sin(θ ) cos θ l θ˙d

(5.18a) (5.18b) (5.18c)

In both problems it will be assumed that there is only bounded control effort available so that |u(t)| ≤ Umax , 0 ≤ t ≤ T. (5.19) This is typical of many applications.

5.3.2 Control Problem Formulation: Tracking The tracking problem will be to have the mass M try to follow a moving target P(t). The target is given in z, y coordinates where y is orthogonal to the z axis. The cost to be minimized is the tracking error along with a penalty for making u too large. That is,  T

ρ1 (z − p1 )2 + ρ2 (L cos(θ ) − p2 )2 + ρ3 u 2 dt.

0

Here the ρi are nonnegative design parameters and z, θ are from the dynamics. It is known from optimal control theory that the solution is continuous and piecewise smooth. It may only be continuous at points where the control hits the bound (5.19). One does not know ahead of time where these corners are. Here the control is taken as continuous and linear on a fixed grid. That is, the control is linear between grid points. For a given problem one can sometimes exploit extra information to make the

128

5 Examples

Fig. 5.8 Control values (left) and cubic spline interpolation (right)

codes more efficient. Our development will follow here a more generic formulation. Suppose that there is a fixed uniform time grid of N subintervals of [0 T ]. The grid points are ti for i = 0, . . . N so that t0 = 0 and t N = T . There are N + 1 parameters U = [u 1 , . . . u N +1 ] so that U (i) is the value of the control at ti−1 . The value of the control in the i-th interval is given using interpolation. It is important to note that some types of interpolation respect the optimization bounds and others do not. For example, with a bound of |u(t)| ≤ 5 the parameter values shown on the left of Figure 5.8 were found. But the control given by interpolation of this function using spline is shown on the right side of Figure 5.8. Note that this violates the bounds by a noticeable amount. Since the control bounds are often physically important, in this example linear interpolation with interp1 is used. The following example is for illustration purposes. The code that solves it has the following components. First parameters and initial guesses are defined. global M m L g N T global rho1 rho2 rho3 M=1; m=.2; L=.6; g=10; N=20; T=10; U0=[4*ones(1,3),-2*ones(1,N-2)]; x0=[0;-pi;0;0;0]; Umax= 5; rho1=1; rho2=200; rho3=1;

Then there is the target to be tracked. function val=p1(t) val=0.2*t;

5.3 Open-Loop Control of a Pendulum

129

end function val=p2(t) val=0.5; end

This is a slowly moving target that is a fixed height. Then there is the control function parameterized by the N + 1 dimensional vector U . function val=cont(t,U) global N T delt=T/N; tc=0:delt:T; val=interp1(tc,U,t); end

and the dynamics, cost function, and call to the optimizer. Another integration for the optimal U value is done at the end for graphing purposes. function xd=fullmodel(t,x,U) global M m L g rho1 rho2 rho3 z=x(1); th=x(2); zd=x(3); thd=x(4); C=x(5); Mati=inv([M+m,m*L*cos(th);cos(th),L]); ydd=Mati*[m*L*sin(th)*thdˆ2+cont(t,U);g*sin(th)]; zdd=ydd(1); thdd=ydd(2); dC=rho1*(z-p1(t))ˆ2+rho2*(L*cos(th)-p2(t))ˆ2+rho3*cont(t,U)ˆ2; xd=[zd;thd;zdd;thdd;dC]; end function val=cost(U) global T x0 options1=odeset(’RelTol’,1.0e-7); x0=[0;-pi;0;0;0]; [tt,xx]=ode45(@(t,x) fullmodel(t,x,U),[0 T],x0,options1); val=xx(end,end); end bdd=Umax*ones(1,N+1); [UMIN,UVAL] = fmincon(@cost,U0,[],[],[],[],-bdd,bdd,[]) options1=odeset(’RelTol’,1.0e-7); x0=[0;-pi;0;0;0]; [tt,xx]=ode45(@(t,x) fullmodel(t,x,UMIN),[0 T],x0,options1);

The optimal cost was given by UVAL =943.797445

The optimal control, position z and angle θ found with the above parameter values N , T, ρ are in Figures 5.9, 5.10 and 5.11. Note that part of the time the optimal control rides the bounds and part of the time it does not.

130

5 Examples

Fig. 5.9 Optimal control for the tracking problem

Fig. 5.10 Cart position for the optimal solution of the tracking problem

5.3.3 Control Problem Formulation: Minimizing Time Now we consider the control problem of finding an input u(t) to move the pendulum from an initial position, hanging at rest with the cart at the origin, to a final position with the pendulum upright with the cart restored to its original position. Only an openloop control is sought. That is, the control is a function of time. In a real application such a control must be supplemented with a feedback control to stabilize the system

5.3 Open-Loop Control of a Pendulum

131

Fig. 5.11 Angle θ for the optimal solution of the tracking problem

around the open-loop trajectory. This problem is also considered in Section 9.7 using Activate. The solution to this open-loop control problem is not unique: there are many control functions u(t) over any interval [0 T ] that would move the state x(0) = [0, −π, 0, 0] to x(T ) = [0, 0, 0, 0]. Clearly there is a compromise between the interval length T and the size of u: the smaller T is, the bigger u is going to be. A common formulation is to consider u to be bounded: |u(t)| ≤ Umax , 0 ≤ t ≤ T, since actuators are limited in their behavior. A couple of different cost criteria will be considered. Our first one is to look for a time optimal solution. That is, the shortest control interval (smallest T ). In this formulation, since u enters the system equations linearly and there is no cost associated with it, from the optimality principle, it can be shown that the optimal open-loop control is bang-bang. This means that the optimal open-loop trajectory consists of a piecewise constant function taking values +Umax and −Umax . So the control starts off with u(t) equal to +Umax for a period of τ1 (which could be zero). This pushes the state to x1 . Then the control switches to −Umax and remains there over a period τ2 ; at the end of this period the state is at x2 , and so on until the end of the interval T is reached. With a time optimal problem it is often possible to parametrize all potentially optimal controls with a finite number of parameters. Another example will be given later where this is not the case. So the problem reduces to finding the number of “switches” and their “switching times.” To do so, fix the number of switches and optimize over the switching

132

5 Examples

times. The optimization problem can be run for different numbers of switches. The consequence of overestimating this number are shown in an example.

5.3.4 Optimization Problem The control problem is formulated as an optimization problem by defining the following cost function: J (τ ) = h(τ ) + x(h(τ ))T W x(h(τ )),

(5.20)

τ = [τ1 , . . . , τn ]

(5.21)

where

and h(τ ) =

n 

τi .

(5.22)

i=1

W is a positive semi-definite weighting function. The problem is then to minimize J over the τ ’s subject to the dynamics of the system. Here fmincon is used to solve the problem with the constraint that the τi are nonnegative. Using fminunc produced incorrect answers. Note that this cost puts a penalty on the final state not being at the origin. Thus the solution computed will not be time optimal but close to time optimal. This can be avoided but doing so requires having terminal boundary conditions and then one cannot just do a simulation to evaluate the cost function. The computation of J requires the computation of the final state xn given the control. This can be done with an OML function. Since the dynamics are not stiff and there will be restarts, a Runge-Kutta method will be used since they get up to full order more quickly than a multistep method does. Here ode45 is used. But fmincon preforms better if one has the gradient of J with respect to τ (= (τ1 , τ2 , . . . , τn )). The gradient can also be obtained using ode45 and the linearized model of the system. The linearized model can readily be obtained from (5.15a)–(5.15b): (M + m)δ z¨ − ml θ¨ sin(θ )δθ + ml cos(θ )δ θ¨ − ml θ˙ 2 cos(θ )δθ −2ml θ˙ sin(θ )δ θ˙ = δu ¨ lδ θ + cos(θ )δ z¨ − z¨ sin(θ )δθ − g cos(θ )δθ = 0. By straightforward algebra, it can be shown that the linearized model can be expressed as follows: ˙ = A(x, δx ˙ x, u)δx, (5.23) where

5.3 Open-Loop Control of a Pendulum

133

 A(x, ˙ x, u) =

0

I

V −1 F V −1 G

 ,

(5.24)

where   0 ml sin(θ )θ¨ + ml θ˙ 2 cos(θ ) 0 z¨ sin(θ ) + g cos(θ )   0 2ml θ˙ sin(θ ) G= 0 0   M + m ml cos(θ ) V = . cos(θ ) l F=

Note that z, θ , and their derivatives are all functions of u. Note also that ∂J ∂h ∂ x(h) = + x(h)T W . ∂τ ∂τ ∂τ

(5.25) (5.26) (5.27)

(5.28)

is simply a vector of ones. ∂ x(h) is the variation in the final state xn due to a ∂τ variation in τ . Thus it can be computed by computing δxn due to variations δτ . Let Ψ (t) be the fundamental solution of the linear system (5.23), i.e., the solution of the following equation: ∂h ∂τ

Ψ˙ = A(x, ˙ x, u)Ψ, Ψ (0) = I.

(5.29)

It is then straightforward to see that δx1 = f (x1 , Umax )δτ1

(5.30)

δx2 = Ψ (τ2 )δx1 + f (x2 , −Umax )δτ2 = Ψ (τ2 ) f (x1 , Umax )δτ1 + f (x2 , −Umax )δτ2    δτ1  ) f (x , U ) f (x , −U ) Ψ (τ . (5.31) = 2 1 max 2 max δτ2 By continuing in the same way, it can be shown that for all i > 0, ⎡

⎤ δτ1 ⎢ ⎥ δxi = Gi ⎣ ... ⎦ ,

(5.32)

δτi

where G is obtained from the following recursion:   Gi+1 = Ψ (τi )Gi f (xi , (−1)i+1 Umax ) , G0 = [ ].

(5.33)

Thus at the end there is δxn = Gn δτ,

(5.34)

134

which allows us to evaluate

5 Examples ∂J ∂τ

thanks to (5.28): ∂J = 1 + xnT W Gn , ∂τ

(5.35)

where 1 denotes a row vector of ones of size n.

5.3.5 Implementation in OML As seen in the previous section, the evaluation of the cost and the gradient of the cost require the solution of the system and the fundamental solution of the linearized system. These two systems cannot be solved separately because the linear system depends on the trajectory of the original system. The two systems are thus solved simultaneously by considering as state   X= xΨ .

(5.36)

Here this matrix differential equation is converted to a vector differential equation and solved by ode45. The following OML code computes the optimal solution. Note that since the pendulum arrives at the desired place using a cost for not being upright the solution is not strictly time optimal but rather a blend of time and error at the end of the interval. fmincon is used with the option of providing the gradient. W=100*eye(4,4); M=1; m=0.2; global N N=5; L=0.6; g=10; delt=1.2; T0=ones(1,N)*delt/N; x0=[0;-pi;0;0]; Umax=9.7; X0=reshape(eye(4,4),16,1); function [f,gg]=cost(Ti,x0,W,m,M,L,g,Umax,X0) global N options2=odeset(’RelTol’,1e-8,’AbsTol’,1e-6); xc=x0; tc=0; for i=1:N U=(-1)ˆ(i-1)*Umax; if Ti(i)>1d-9 fullm=@(t,X) fullmodel(t,X,U,M,m,L,g); [tt,XX]=ode45(fullm,[tc,tc+Ti(i)],[xc’,X0’],options2);

5.3 Open-Loop Control of a Pendulum

135

else XX=[xc’,X0’]; end xc=XX(end,1:4)’; tc=tc+Ti(i); Psi=XX(end,5:end); Psim=reshape(Psi,4,4); fm=fullmodel(0,XX(end,:),U,M,m,L,g); if i==1 dxdt=fm(1:4,1); else dxdt=[Psim*dxdt,fm(1:4,1)]; end end f=sum(Ti)+xc’*W*xc/2; gg=ones(1,N)+xc’*W*dxdt; gg=gg’; end function mval=fullmodel(t,X,U,M,m,L,g) z=X(1); th=X(2); zd=X(3); thd=X(4); Mati=inv([M+m,m*L*cos(th);cos(th),L]); ydd=Mati*[m*L*sin(th)*thdˆ2+U;g*sin(th)]; zdd=ydd(1); thdd=ydd(2); xd=[zd;thd;zdd;thdd]; F=[0,m*L*thdd*sin(th)+m*L*thdˆ2*cos(th); 0,zdd*sin(th)+g*cos(th)]; G=[0,2*m*L*thd*sin(th);0,0]; dx=reshape(X(5:20),4,4); dxd=[zeros(2,2),eye(2,2);Mati*F,Mati*G]*dx; dxd=reshape(dxd,1,16); mval=[xd;dxd’]; end options=optimset(’GradObj’,’on’,’GradConstr’,’on’); costl=@(Ti) cost(Ti,x0,W,m,M,L,g,Umax,X0); [Topt,cval]=fmincon(costl,T0,[],[],[],[],... zeros(size(T0)),ones(size(T0)),[],options)

Running this script produces the following Topt = [Matrix] 1 x 5 0.15596 0.46207 0.63028 cval = 1.9555133

0.51384

0.18982

The optimal time is then obtained by adding the time intervals: > tf=sum(Topt) tf = 1.95197146

136

5 Examples

The difference between tf and cval is explained by the final state of the system not being exactly at zero. Note that the final state includes not only the position and the angle but also their velocities. The final state in this case is very close to zero but its norm can be further reduced by increasing the weight W . The following script will simulate this optimal control and graph the optimal control, the four states, and the animation of the pendulum as it moves from the initial position to the end position. function xd=simul(t,x,U,M,m,L,g) z=x(1); th=x(2); zd=x(3); thd=x(4); Mati=inv([M+m,m*L*cos(th);cos(th),L]); ydd=Mati*[m*L*sin(th)*thdˆ2+U;g*sin(th)]; zdd=ydd(1); thdd=ydd(2); xd=[zd;thd;zdd;thdd]; end Ti=Topt; xc=x0;tc=0; XX=x0’;ttt=0 ; Tu=0;Vu=Umax; options=odeset(’RelTol’,1e-8,’AbsTol’,1e-6); for i=1:N U=(-1)ˆ(i-1)*Umax ; sim=@(t,x) simul(t,x,U, M, m, L, g); [tt,xx]=ode45(sim,[tc,tc+Ti(i)],xc’,options); xc=xx(end,1:4); tc=tc+Ti(i); Tu=[Tu,tc];Vu=[Vu,U]; if i 0 and the time interval is 0 ≤ t ≤ T . D is a scalar. The term with the D coefficient models diffusion and the F can represent other source or damping terms. With F = 0 this is the standard one dimensional heat equation that describes how heat flows along a homogenous rod. For our example the following boundary conditions are assumed:

5.4 PDEs and Time-Delay Systems Using MOL

139

u(0, x) = a(x)

(5.38a)

u(t, 0) = b(t) u(t, L) = c(t).

(5.38b) (5.38c)

Here a is the initial distribution of u along x at time t = 0, and b, c give the values of u at the left and right boundaries at a given time t. Thus b, c can also represent sources and sinks. Now divide the x interval [0, L] into N intervals for some integer N . Take the intervals of the same length so they are each of length Δx = NL . Some applications utilize an uneven x grid. Let M = N − 1. Let {x1 , . . . , x M } be the interior grid points so that xi = iΔx. Let x0 = 0 and x N = L. Finally let u i (t) = u(xi , t). That is, u i is u along the line x = xi . The first term u(xi , t)t in (5.37) is now just u˙ i (t). For the second term a difference approximation is used, the centered difference, u x x (xi , t) ≈

1 (u i+1 (t) − 2u i (t)uxi−1 (t)), i = 1, . . . M. (Δx)2

(5.39)

The initial conditions are u i (0) = a(xi ) and u 0 (t) = b(t) and u N (t) = c(t). The partial differential equation (5.37) is now approximated by the ODE u˙ i = D

1 (u i+1 (t) − 2u i (t) + u i−1 (t)) + F(t, xi , u i ). (Δx)2

(5.40)

Two illustrations follow. The first is a simple heat equation. To illustrate, if N = 4 D with δ = (Δx) 2 , then (5.40) becomes ⎡

1 −2 1 0 u˙ = δ ⎣0 1 −2 1 0 0 1 −2

⎤⎡ ⎤ 0 b 0⎦ ⎣u ⎦ . c 1

Of course, one usually takes N larger than just 4. Suppose that L = 4 and T = 8. Assume that the initial value a is zero. The edge b is held to zero. The right side has a heat source applied which takes the form of ⎧ ⎨ 0 for 0 ≤ t ≤ 2 c(t) = 3 for 2 < t =2)*(t=2).*(tt 1)(x < 2) for r (x, t) = 1 + 3(x > 7)(x < 8) for ⎪ ⎪ ⎩ 1 for

0≤t dsafe + doffset ,

(9.26)

where doffset introduces hysteresis to avoid chattering in the control. If Condition (9.26) is not satisfied, the adaptive cruise control device functions in the vehicle-following mode where the objective is to maintain the distance d close to dsafe . A simple implementation is shown in Figure 9.39. The control is based on a tunable PID. This block provides an interactive GUI that allows the user to change the parameter P, I and D as shown in Figure 9.38. By simulating the model in loop using the End block with Restart option, the tuning of the PID is greatly facilitated. The simulation results are given in Figures 9.40 and 9.41. The road grade profile is constant in this case.

246

9 Examples

Fig. 9.40 The cruise speed is set to 120 kmh−1 and the speed of the car in front starts at 100 kmh−1 , then jumps to 140 before going down to 65

Fig. 9.41 The distance to the car in front compared to the safe distance. Originally the distance is below the safe distance

Fig. 9.42 Top diagram

This PID is tuned for this particular scenario. The actual implementation of such a cruise control device would require a more complex control strategy. For example a bank of PID controllers can be designed for different speeds and implemented in a gain scheduling strategy. This and other control methods have been largely studied in the literature and will not be pursued here. The presented model can be used as a test bench for various control methods.

9.7 Swing-Up Pendulum Problem

247

Fig. 9.43 Model of cart-pendulum system

Fig. 9.44 Parameters of MathExpressions block Fig. 9.45 Content of the optimizer Super Block

9.7 Swing-Up Pendulum Problem The time-optimal swing-up pendulum problem was formulated as an optimization problem and solved in Section 5.3.3 using an OML program. The same problem is formulated here as an Activate model. The solution is obtained by simulating the model. The optimization problem is a part of the model; no additional scripting is required for solving it. This is done thanks to the use of the BobyqaOpt block presented in Section 8.2.

248 Fig. 9.46 Cost to minimize is computed inside the T+X’WX Super Block

Fig. 9.47 Open-loop trajectory (switching times)

Fig. 9.48 The displayed values of the parameters are their converged to optimal values. These values lead to the open-loop control solution in Figure 9.49

9 Examples

9.7 Swing-Up Pendulum Problem

249

Fig. 9.49 The open loop control solution. The corresponding state trajectories are given in Figure 9.50

Fig. 9.50 The state trajectories confirming that the pendulum ends in the vertical position with zero velocity

The equations of motion for this system are given in (5.15a) and (5.15b). The Activate model uses these equations directly without any manipulation. The Constraint block is used for this implicit formulation. In particular the equations are expressed thanks to a MathExpressions block and set to zero by the Constraint block. See the top diagram (Figure 9.42) where the Constraint block is used to set the residual, i.e., the values of the expressions on the left hand sides of the following equations

250

9 Examples

(M + m)¨z + ml θ¨ cos(θ ) − ml θ˙ 2 sin(θ ) − u(t) = 0 l θ¨ + z¨ cos(θ ) − g sin(θ ) = 0

(9.27) (9.28)

to zero. See Figure 9.43 for the content of the cart-pendulum model Super Block which provides the evaluation of the residual using a MathExpressions block. The parameters of the MathExpressions block are presented in Figure 9.44. The optimization is performed because of the presence of the BobyqaOpt block in Super Block optimize (see Figure 9.45). The cost consists of a cost on the final state and the simulation time. In particular it is taken to be the time plus a quadratic penalization term for ending away from the stable up right position. See Section 5.3.3 for more details on this formulation. The content of the T+X’WX Super Block is illustrated in Figure 9.46. The open-loop control is obtained from the timing vector TT. This is done by generating events to drive a Toggle block. This block’s output switches between two values at every activation. The content of the Super Block generating the time events corresponding to switching times and the final event is given in Figure 9.47. The optimal switching time parameters are shown in Figure 9.48.

Chapter 10

Formalism

To construct complex models, in particular models involving conditional activations, it is important to understand the formalism on which Activate is based upon. This is also essential for understanding important features of the tool such as synchronism.

10.1 From Graphical Model to Simulation Structure Before simulation or code generation, an Activate model goes through several steps of processing. As seen in the examples presented so far, the OML language plays a key role in the construction of Activate models. In particular it is in OML that all the block parameter expressions are defined. The model Initialization and diagram Context scripts are used to define variables, which are then used in the definition of block parameter expressions. Every diagram has a workspace containing the variables available for use in definition of block parameter expressions. The construction of these workspaces follows a precise scoping rule.

10.1.1 Scoping Rule The scoping rules here specify unambiguously how a block parameter expression depending on an OML variable is evaluated. In general, any variable defined in the Initialization script is available everywhere in the model for use in the definition of block parameter expressions and in Context scripts. However a variable defined in the Initialization script may be shadowed by another definition of the variable (with identical name) in a diagram Context script. So the variables available in the workspace of a diagram D depend not only on the model Initialization script and © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_10

251

252

10 Formalism

the Context script of D, but also on all the Context scripts of all the diagrams that encapsulate D. A simple way to understand the scoping rule specifying the workspace of the diagram D is to imagine an OML script obtained by concatenating the model Initialization script with the Context scripts of all the parent diagrams of D, in descending order. The workspace obtained by executing this script is then the workspace of D. There are two notable exceptions to this scoping rule: • Masked Super Blocks: The workspace of a masked Super Block is obtained from its mask parameters and its Context script. The scoping rule does not traverse the masked Super Block boundary. This makes the masked Super Block selfcontained. • external-context workspace: In batch simulation usage, Activate provides an option to inject a workspace (external-context workspace) after the evaluation of the Initialization script, before the evaluation of the diagram workspaces. This feature will be presented later in Section 12.1. The evaluation of the block parameter expressions (and thus the application of the scoping rule) is done in a pre-compilation phase called Evaluation.

10.1.2 Basic Blocks and Atomic Units In the Activate environment, a model is constructed using blocks and Super Blocks. The compiler however does not operate on these blocks; it interacts with what are referred to as Atomic Units (AU). In the Evaluation phase, all the blocks in the model are replaced with AUs. In many cases a basic block is associated with a single AU, but not always: a block may produce a network of AUs, or no AU. The term network is used in place of diagram to emphasize that at this stage, the nodes are AUs and not blocks. The network of AUs has no graphical representation contrary to diagrams. The AU or AUs produced by a block may depend on the values of the block parameters. Specifically, the choice of the AU(s), their parameters, and the topology of the network is specified by an OML function associated with the block and depends on the values of the block parameters. The ability to programmatically instantiate an AU or a network of AUs provides a powerful mechanism for constructing versatile blocks. Blocks creating a network of AUs are called programmable Super Blocks. Unlike regular Super Blocks, the content of a programmable Super Blocks may be very different for different values of parameters. Even the numbers and types of its inputs and outputs may be different. The programmable Super Blocks are similar to basic blocks at the graphical editor level; there is no graphical representation of their “interior”. In fact the network of AUs inside the programmable Super Block are not even constructed yet at the editor level.

10.1 From Graphical Model to Simulation Structure

10.1.2.1

253

Atomic Unit (AU)

It could be misleading to consider an AU as a “basic” block. An AU has ports that are connected to links, just like a basic block. It has parameters, like a basic block, but an AU is not a basic block. As seen previously a basic block can produce zero to many AUs and even if it produces just one, the parameters of this AU are not in general the same as the block parameters. Consider for example the Activate block that implements a transfer function (ConTransFunc block for example). The block parameters are the numerator and the denominator coefficients of the transfer function. The AU associated with this block operates in the time domain and implements the dynamics based on the state-space realization of the transfer function. The parameters of the AU in this case are the A, B, C, D matrices, which are computed by the OML function associated with the block. In general an AU is a computational unit providing Application Programming Interfaces, or APIs, to be used by the simulator. The APIs are C or OML functions that are called by the simulator at different stages of the simulation: computation of the output, of the continuous-time state derivative, of the next discrete-time state(s), etc. But the AUs can also be Modelica components. An AU may also be virtual. The systematic creation of AUs from Activate blocks based on the underlying scripting language OML provides a clear separation between the model at the graphical layer and at the compiler level.

10.1.2.2

Network of AUs

At the end of the Evaluation phase, the Activate model, including its diagrams and blocks are converted to a network of AUs. This network still retains hierarchical structure but the topology of this network may be very different from the original model block hierarchy. This network, along with the properties of the AUs that constitute its nodes, are the only information that is passed on to the compiler. None of the block parameter expressions and graphical information are present at this stage. This network of AUs is then passed through the first stage of compilation where the hierarchical structure is flattened and all the virtual blocks are removed. At this point the structure contains computational units connected in a flat network. The final compilation stage consists of typing the signals and computing the scheduling tables for both simulation and code generation. The result of this stage is a structure available in OML, which is then passed on to the simulator. Signal typing consists in finding the sizes and data types of all the signals associated with links connecting AUs. Most AUs support different data types and sizes on their regular input and output ports but impose constraints. For example an AU performing matrix multiplication of two inputs to generate an output requires that the corresponding matrix sizes be compatible with the usual matrix multiplication rules. Additional constraints come from the links connecting ports. The ports connected to

254

10 Formalism

the same link are associated with the same signal and thus have the same data type and size. The scheduling tables contain information on the order in which the outputs of the AUs are to be computed when they are synchronously activated (the order in which their computational functions to compute their outputs are called during simulation) under different circumstances. All scheduling in Activate is done statically, so no scheduling is performed at run time. The code generator relies on the same tables. It was noted earlier that it would be incorrect to confound the networks of AUs and the block diagrams but it could still be helpful to think of the network of AUs as a model containing very “basic blocks” where the block parameters are defined directly by numerical values. This is done in the following sections where fundamental properties of the formalism is illustrated through simple models containing basic blocks.

10.1.3 Masking A masked Super Block is a special type of Super Block to which a set of parameters are associated; similar to the way basic blocks have block parameters, masked Super Blocks have mask parameters and behave similarly at the graphical editor level. A masked Super Block is self contained in the sense that the evaluation of its content is possible by simply providing the values of the mask parameters. The masked Super Block can thus be used in any diagram as long as its mask parameter values are provided, just as is the case for a basic block. Masking a Super Block requires identifying the variables that are required for the evaluation of its content. An auto-masking tool is provided in Activate that automatically identifies these variables and creates the mask. A mask editor can then be used to customize the Super Block parameter GUI. Even though a masked Super Block behaves similarly to a basic block inside the graphical editor, i.e., double clicking on it opens up a parameter GUI, the content of the Super Block is still accessible. It can be reached not only by the contextual menu but also by double clicking on the block while holding down the Alt key.

10.2 Activation Signals A simulation function is associated to each Activate basic block (actually AU to be precise but for ease of presentation, the term basic block is used). This function is called when the block is activated. The activation times for a given block are specified by the activation signals received on the block’s activation input ports. Activation signals are generated by blocks on their output activation ports and transmitted to other blocks by activation links (visible as red links in the graphical editor). Activation signals are timing information. They can include isolated time

10.2 Activation Signals

255

instants (in which case they are referred to as events) or be present over time intervals. If an activation signal is present over the whole period of simulation, it is called always activation. Any block activated by such a signal is called always active. An activation present only at initial time is called initial activation and blocks activated by it are initially active.

10.2.1 Block Activation Blocks are activated by activation signals during simulation. When an activation signal becomes active, all the blocks associated with this signal (connected to it) are activated. The order in which these blocks’ outputs are evaluated is pre-computed by the compiler (and stored in scheduling tables) in such a way that any time a block computational function is called to compute the block’s output and this output depends on the value of one of the block’s inputs, then the value of this input is up to date. This output-input dependency is a key property of the block used by the compiler to construct the scheduling tables containing the order in which the computational function for the blocks should be called at each activation. A block’s input port is said to have the feedthrough property if any of its outputs depends directly on this input. A block may be associated with multiple activation signals, through a single or multiple activation input ports. Multiple activation inputs are useful for blocks that should behave differently depending on the way they have been activated. This is the case for example for the Selector block, which depending on the way it is activated, copies one of its inputs to its output. For this, the simulation function has access to an integer nevprt, which codes the ports through which the block is activated. If the block has n input activation ports, when the block is activated, a zero is associated to all ports not receiving any activation and a one to the ports receiving an activation, and the result is interpreted as an n bit binary coding of the integer nevprt. Note that two activations are considered received on two different input activation ports only if the two activations are synchronous. Consider for example the block AndActivations. This block, when activated, produces an output equal to one if it is activated synchronously through both its input activation ports. It produces zero otherwise. This output is computed by the simulation function by comparing the nevprt variable with the value 3. Depending on block properties such as the presence of internal states, block activation results in the simulator calling the block computational function in different ways. In the following presentation this process is presented via simple examples.

10.2.1.1

Memory-Less Case

Consider the model in Figure 10.1. In this model, the activation signal (event) activates synchronously the three blocks Source, Func_1, and Func_2. This

256

10 Formalism

Fig. 10.1 A synchronous diagram

Fig. 10.2 An asynchronous model

synchronous activation occurs because the blocks are activated by the same activation signal. The order in which the associated computational functions are called is determined by the Activate compiler. If the Func blocks are memory-less immediate functions, their inputs have feedthrough property so Func_1 needs the value of the output of the Source block before its computational function can be called, and similarly Func_2 needs the output of Func_1. The compiler orders the block executions accordingly, i.e., Source followed by Func_1 followed by Func_2. In this example, the activation times of the three blocks were the same. However, having the same activation time does not necessarily imply synchronism. Consider the diagram in Figure 10.2. In this case the two event generators are identical and the events they generate have the same timing but these events are not synchronized. When a diagram contains more than one independent activation source, the compiler computes an order (execution schedule) for each asynchronous activation separately. During the simulation, it is the timing of the activations that determines the order in which the events are fired, and consequently the blocks are activated. If, as is the case in Figure 10.2, two events have identical timing, then the order of firing is arbitrary. So Func_2 could be executed before or after the other two blocks resulting in very different simulation results. Note however that the Source comes always before Func_1.

10.2.1.2

Blocks with Internal State

In the previous example, the task of the block computational function was limited to computing the block outputs. If a block has for example a discrete-time internal state, then when the block is activated, an additional computational function is required for updating the value of the state. Consider the diagram in Figure 10.3. The DiscreteDelay block is simply a memory block holding in its internal state the value of its input at the time of activation. Its output corresponds to the previous value of the state. At its activation, this block is called first to compute its output (in this case a

10.2 Activation Signals

257

Fig. 10.3 A synchronous diagram with a memory (delay) block

Fig. 10.4 Diagram with feedback but without algebraic loop

simple copy of the state), and then it is called to compute its (new) state (a copy of its input to its internal state). The order in which block functions are called for state update, contrary to the case of output update, has no importance because the result has no bearing on the outputs of the blocks. But in this case, even the order in which the blocks are called for output update is not the same as in the case of the model in Figure 10.1. The DiscreteDelay block does not require the value of its input when it computes its output. This means that this block can very well be activated before the Source block. But in any case, Func_2 comes after the DiscreteDelay block. The blocks’ feedthrough property must be specified, otherwise the compiler cannot compute the correct order of execution. In the example of Figure 10.3 even if DiscreteDelay block is not specified as having this property, the blocks can be ordered. However, in the example in Figure 10.4, the compiler cannot compute the order of block activations due to the presence of an algebraic loop if it does not know about the absence of output-input dependency of the DiscreteDelay block. This is why the feedthrough property of the DiscreteDelay block is set to false and the compiler finds that the block functions must be called for output update in the following order: DiscreteDelay followed by Func_2 followed by Func_1. Then the DiscreteDelay is called for state update.

10.2.1.3

General Case

An Activate block can be more complex than just having an internal state and an output. The event generator, for example, has an output activation port. Blocks may also have continuous-time internal states such as the Integrator block. A general Activate block can be fairly complex and will be discussed in Chapter 13.

258

10 Formalism

Fig. 10.5 An event clock

10.2.2 Activation Generation The event generators in models of Figures 10.1, 10.2, 10.3 and 10.4 generate each an activation signal at a given time. This output activation is preprogrammed at the output activation port of this block. The block itself is never activated. Since only one activation can be preprogrammed at any output activation port, an Activate block cannot serve as an event clock (i.e., a block that generates events on a periodic basis). The SampleClock block used in Activate models seen in previous chapters is not a basic block. Such a block can however be constructed as a Super Block containing an EventDelay block with a feedback, as illustrated in Figure 10.5.1 The EventUnion is a virtual block. In this case the EventDelay block is activated initially by the InitialEvent block and subsequently by its own output events. In particular, this output event activates the EventDelay block itself. When this block is activated, its computational function schedules a new event on its output activation port by returning the delay (in this case T), after which the scheduled activation must be fired. When this activation is fired, it schedules in turn a new activation, and so on. This way, an event clock with period T is realized.

10.2.3 Activation Inheritance In the examples of the previous chapter, a number of blocks did not have activation input ports. Consider the model in Figure 10.6. Normally the Func_1 block should not be activated because it receives no activation signal. But by convention, as an 1 The

actual construction of this block is slightly more complex to avoid numerical errors due to adding floating point numbers (multiplying T by an integer n is more precise than adding T n times), but the idea is similar.

10.2 Activation Signals

259

Fig. 10.6 The block Func_1 is activated by inheritance

Fig. 10.7 The diagram after the precompilation phase

Fig. 10.8 Blocks Func_1 and Func_2 are activated by inheritance

editor facility, in the absence of input activation ports, a block inherits its activation from its regular input. The inheritance mechanism is implemented at a precompilation phase. For example, in the case of the model in Figure 10.6, the precompiler adds the missing activation port and link as illustrated in Figure 10.7. The user never sees this modified model; this pre-compilation phase is completely transparent to the user. If the block has more than one regular input, the inheritance mechanism makes it so that the block inherits from all its regular inputs. Depending on a block property, the mechanism can place a unique input activation port on the block receiving the union of all the inherited activations or it can place as many activation input ports on the block as the block has regular input ports. Each activation input port then receives the activation inherited from the corresponding regular input port. See the diagram in Figure 10.8 and the diagrams obtained after the precompilation phase illustrated in Figure 10.9 and Figure 10.10. The diagram in Figure 10.9 corresponds to the case where the block property of the block Func_1 is such that it inherits its activation through a unique activation input port. This is the default block property. If this is not the case, the inheritance mechanism leads to the diagram in Figure 10.10. When the block has more than one activation input ports, it is activated when it receives an event on any one of these ports. Thus in this case the Func_1 block is activated at the union of the two activation times. This explains how Func_2 inherits its activation.

260

10 Formalism

Fig. 10.9 Blocks Func_1 and Func_2 are activated by inheritance

Fig. 10.10 The diagram after the precompilation phase

10.2.4 Always Active Blocks Another way a block can be active in the absence of explicit activation through activation links is by being declared always active (having the always active property). Consider the SineWaveGenerator block in the first model created in Chapter 6 on page 157, Figure 6.3. This block is not explicitly activated, and it clearly does not inherit. But it is active because it is declared always active. An always active block is, at least as far as the formalism is concerned, always active. But during the simulation, the block computational functions are called by the simulator only when needed. For example, in the model in Figure 6.3, the output of the SineWaveGenerator block should evolve continuously. But since this value is used only by the Scope block, during the simulation, the output update function associated with the SineWaveGenerator block is only called at a periodic rate specified as a model simulation parameter, in particular as the maximum simulation step size. In the subsequent model (Figure 6.4), the Integrator block is also declared always active. But even if it were not, it would not have made any difference because it would have inherited always activation from the SineWaveGenerator block. In this case, since the output of the SineWaveGenerator block affects a differential equation, the times that the computational functions associated with this block are called are the times (integration time steps) imposed by the numerical solver. The always activation signal can be obtained from the AlwaysActive block. Declaring a block always active amounts to connecting its input activation port num-

10.2 Activation Signals

261

Fig. 10.11 Inheritance from a block declared only initially active

Fig. 10.12 Explicit activation of the initially active block

Fig. 10.13 Inheritance of the activation

ber zero (invisible port) to the AlwaysActive block. There is an exception to this rule, in particular in the presence of the EventPortZero block, which will be discussed later.

10.2.5 Initially Active Blocks Consider a Constant block. This block does not inherit (has no inputs). It is not explicitly activated and it is not declared always active. Yet the output of this block needs to be set at the initial time. For such blocks, the initial active property of the block must be set. Blocks with this property are only activated at initial time. At precompiling stage a link is added connecting its invisible input activation port zero to an InitialEvent block. So the initially active Constant block’s computational function is only called at initial time, which is the appropriate behavior for a Constant block. This is also the case for all blocks inheriting their activations from such blocks. See for example the model in Figure 10.11. If Source is only initially active, then its output is constant like a Constant block. If Func_1 is not always active, it inherits its activation from the Source block. The Func_1 block’s computational function is called only at initial time. This is of course reasonable because the output of Func_1 does not evolve in time. The inheritance process can be seen in Figures 10.11, 10.12 and 10.13.

262

10 Formalism

Fig. 10.14 Incorrect way of implementing decimation

10.2.6 Conditional Blocks In many applications, in particular in signal processing, signals with different frequencies interact in the same model. A common situation is the decimation operation, which consists in generating a signal B from a signal A by taking one out of every n values of A. The frequency of signal B is then that of signal A divided by n. To implement this operation, one might consider using two independent clocks to fix the two frequencies. This is done in the model of Figure 10.14 using a SampleHold block. But it was seen that two activation sources generate asynchronous events. So even if the period of the slow clock were set to exactly n times that of the fast clock, at times when the two events have the same time, the order of block executions is not predictable. This example shows that there is a need for being able to define synchronism between two nonidentical activation signals. The events generated by the fast clock do not always have the same timing as that of the slow clock. However, when they do (one out of every n times), they must be considered synchronized. This is particularly important when the fast and slow signals are used in common operations later such as being added together. This type of synchronous signals can be constructed in Activate using two special blocks: the IfThenElse and SwitchCase blocks, which can be found in the ActivationOperations palette. Strictly speaking, these blocks are not “blocks”. They do not generate new activation signals. Rather they redirect the activation signal they receive.2 The output activation ports of these blocks are secondary activation sources. The activation produced (or redirected to be more precise) by them are associated with a primary activation signal. Consider the model in Figure 10.15. The SampleHold block, when activated, copies its input on its output. The IfThenElse block activates the SampleHold block when the value of its input is positive. The output of this block is then a signal with an activation that depends on values of the signal generated by the Source block. In this case, it is said that this signal is obtained by conditional subsampling. In this case, since the Source and SampleHold have identical activation sources (remember that the IfThenElse block only redirects activations), they are considered synchronous by the Activate compiler and ordered accordingly. In particular, in this case the output of the SampleHold block is always positive. 2 In

that respect, they are similar to the EventUnion block.

10.2 Activation Signals

263

Fig. 10.15 Conditional subsampling

Fig. 10.16 A correct way to implement decimation

Returning to the decimation problem previously discussed, the model in Figure 10.14 did not function properly because the Source and the SampleHold blocks were not synchronized. Using the IfThenElse block, the decimation operation can be implemented correctly as illustrated in Figure 10.16. The ModuloCounter block counts up to n − 1 and then returns to zero. The SampleHold block is activated only when the output of the counter block is zero (activation through the else branch), that is, one out of every n times. And in this case, the Source and SampleHold blocks are synchronized. The combination of the ModuloCounter block and the IfThenElse block provides a versatile mechanism for implementing frequency division. The division factor can be set by fixing the value of n, and the phase, by the initial state of the counter. The above process for generating synchronous clocks with different frequencies can become cumbersome for the designer when one frequency is not a multiple of another and/or when there are more than two frequencies involved. That is why Activate provides the special block, SampleClock block. This block is used very much like a regular event clock, however, the activation signals generated by such blocks anywhere in the model are synchronized. For these blocks, Activate finds automatically the smallest frequency from which the frequencies of all the SampleClock blocks can be derived and implements all the corresponding conditional blocks. See Figure 10.17. In this case, the slowest clock generating synchronous clocks of periods 3 and 5 by subsampling is a clock with period 1. Conditional blocks work also for “always active” activation. Consider the diagram in Figure 10.18. The IfThenElse block is always active (inheriting its activation from the SineWaveGenerator block) but activates the SampleHold block only when its input is positive. So the Integrator receives on its input port the signal sin(t) if it is

264

10 Formalism

Fig. 10.17 SampleClock blocks generate synchronous events

Fig. 10.18 Conditional blocks function also with continuous-time activation

Fig. 10.19 Simulation result. At the bottom, the output of the SineWaveGenerator block, and on top sin(t), t 0 max(sin(τ ), 0)dτ

positive, and zero otherwise. Zero is the last value produced by SampleHold before deactivation. When a block is not active, its output remains constant. The simulation result is given in Figure 10.19.

10.2 Activation Signals

265

Fig. 10.20 The Super Block realizing an activated integrator

Fig. 10.21 The Super Block contains an EventPortZero block

10.2.7 EventPortZero Block The conditional blocks can be used to control the activation of blocks. This is done by explicitly connecting their output activation ports to the blocks’ input activation ports. But as it was seen earlier, always activation can be defined as a block property. Clearly conditional blocks cannot be used on activations defined in this way. The invisible activation port zero, and its invisible connection to the always activation block is not accessible at the graphical editor level. The way to access this port is by using the EventPortZero block inside a Super Block. If this block is placed inside a Super Block, all the activation ports numbered zero of always active blocks within the Super Block are connected to this block instead of the AlwaysActive block. The EventPortZero block is a virtual block, used to redirect activation signals. So feeding this block an activation signal amounts to feeding it to all the always active blocks inside the Super Block. This way, always active blocks within the Super Block may be activated by any desired activation signal as it can be seen in the model in Figure 10.20 where the Super Block acts like an integrator when it is activated and when the block is inactive, its state and output remain constant. The content of the Super Block is shown in Figure 10.21. The simulation result for a sine wave input, integrated when its value is positive, is shown in Figure 10.22. The EventPortZero block plays a key role in the implementation of hybrid systems later in Chapter 11.

266

10 Formalism

Fig. 10.22 The simulation result shows that the Super Block integrates the input signal only when it is activated

10.3 Synchronous Versus Asynchronous Events Two events are considered synchronous if they are generated by the same activation source or if they can be traced back to the same primary activation source through IfThenElse, SwitchCase or EventUnion blocks. These blocks do not generate new activations; they redirect their activations to one of their output activation ports. Two activation signals generated on two different activation ports of two basic blocks (or even the same basic block) are always asynchronous. The reason is that the output activation signal of a basic block is never synchronous with its input activation signal (unlike for the IfThenElse and SwitchCase blocks where the output is just a redirection of the input). The above simple rule is strictly applied by the compiler, and has no exception. But for the user at the editor level, it is not always trivial to identify synchronous and asynchronous events. The reason is that some of the blocks in the Activate palettes are in fact Super Blocks (masked or programmable) containing IfThenElse or SwitchCase blocks in such a configuration that makes the input and output activation signals of the block synchronous. For example the EventIntersection block produces an output activation signal which is synchronous with its inputs. The same holds for the FrequencyDivider and IfExpressions blocks. Other “synchronous” blocks include the SampleClock, ResampleClock and EdgeTrigger. For advanced programming, in particular to efficiently construct hybrid systems, it is important to understand the synchronous nature of these blocks. Their synchronous nature is explained below.

10.3 Synchronous Versus Asynchronous Events

267

10.3.1 SampleClock Block Versus EventClock Block The SampleClock block and the EventClock block look very similar. They both generate events on a periodic basis on their output activation ports. The EventClock block is actually implemented very much like in Figure 10.5. This is also the case for the SampleClock block, if no other SampleClock block or ResampleClock block is present in the model. Otherwise, Activate precompiler performs a complex model transformation, adding counters and conditional blocks if needed, so that the events generated by all the SampleClock and ResampleClock blocks in the model become synchronous.3 This is not the case for EventClock blocks. They generate asynchronous events even if the blocks have identical parameters.

10.3.2 Zero-Crossing Events Zero-crossing events are generated when the value of a signal crosses zero under certain conditions. Different conditions are used by different blocks. The blocks generating zero crossing events in the Activate palettes can be placed in two categories: the ones that generate an event when the input signal crosses the value zero as a continuous function (the ZeroCross, ZeroCrossUp and ZeroCrossDown blocks) and the EdgeTrigger block, which generates an event even if the input signal jumps across the zero value. The zero crossing blocks ZeroCross, ZeroCrossUp and ZeroCrossDown generate an event if the input signal crosses zero, crosses zero with a positive slope and crosses zero with a negative slope, respectively. The generated event is always asynchronous. Even if two identical zero crossing blocks receive the same input signal, the events they generate are considered asynchronous by the compiler (even if they are simultaneous). The EdgeTrigger block has similar behavior when it detects a continuous zero crossing. But when it detects a jump in the input signal across the value zero, the event it generates is synchronous with the event at the origin of the jump. To illustrate the difference between these two blocks, consider the following system x˙ = −1, x(0) = 1, with a jump in the state x from 0 to 1 every time the value of x reaches zero. This system can be implemented in Activate as in Figure 10.23. The simulation result is given in Figure 10.24. Replacing the ZeroCrossDown block by an EdgeTrigger block, as done in Figure 10.25, however results in an incorrect model. The Activate compiler raises an Algebraic loop error. Indeed the output of the Integrator block 3 The

SyncTag can be used to define separate synchronization domains. In particular if the block is placed inside a Super Block, the SampleClock and ResampleClock blocks inside this Super Block are not synchronized with those that are outside the Super Block.

268

10 Formalism

Fig. 10.23 System implemented using a zero-crossing block

Fig. 10.24 The simulation result shows that the state x jumps back to 1 when it reaches zero, as expected

Fig. 10.25 System implemented using a EdgeTrigger block. The model is incorrect and the compiler raises an algebraic loop error

may jump due to the event generated by the EdgeTrigger block, which in turn depends on the output of the Integrator block. This means that as long as the event is not generated, it is not possible to know if the event has to be generated. Such situations are rejected by the Activate compiler.

10.4 Periodic Activations

269

10.4 Periodic Activations The SampleClock and ResampleClock blocks produce synchronous activation signals. Another feature of these signals is that they are periodic. Any block activated by these signals is activated on a periodic basis. A block may be activated on regular intervals by other activation signals as well but only blocks activated by activation signals produced by SampleClock and ResampleClock blocks are said to be periodically activated. Periodically activated blocks are identified at compile time and have access to the period and offset of their activations. Thus, these block can use this information to specify their simulation behavior. Consider, for example, the SampledData block. This block, which must be periodically activated, takes as parameter a continuoustime linear state-space system (A, B, C, D) and implements a discrete-time linear state-space system (Ad , Bd , Cd , Dd ) where this latter is obtained by discretizing the former using either the exact discretization method: Ad = e AT , Bd =  T As 0 e Bds, C d = C, and Dd = D, or the bilinear transformation method: Ad = (I − AT /2)−1 (I + AT /2), Bd = (I − AT /2)−1 BT /2, Cd = C(I + Ad ), and Dd = D + C Bd , where T is the block activation period. This block must be periodically activated so that it can have access to T , which it needs as a block parameter. An alternative implementation would require the user to provide T directly as a block parameter. The result would then require the user to make sure that the block activation is done on a periodic basis with period corresponding to the user provided parameter T .

10.5 Repeat Activations The RepeatActivation block has an activation input port. When this block is activated, the current event is flagged to be repeated once the activation of all the blocks is terminated. Thus at the end of the activation process associated with the current event, the event is fired again. The newly fired event is not synchronous with the original event; it comes immediately after it but it is guaranteed that no other event is fired in the meantime. The same event can thus be repeated many times without any advancement of time. The RepeatActivation block has many uses. It is used, in particular, to implement operations that require iterations and also for state machines. The following example illustrates how this block can be used in a model.

270

10 Formalism

Fig. 10.26 The block counts up to the value read on the input and starts over

Fig. 10.27 The top discrete delay block is initialized to zero indicating that the input value must be read. In subsequent iteration the value is one. Once the output matches the stored input value, the state of the delay block is set back to zero so that at the next activation the input is read again

Fig. 10.28 As expected the output starts from zero and counts up to five and returns to zero

10.5.1 Example: Simple Counter Consider the model in Figure 10.26. The Super Block Count Up, shown in Figure 10.27, at first activation reads the value of the input and generates the value zero on its output. Then it increments the output at subsequent activations until the output value matches the input value. It then starts over again. An external activation signal is generated at every iteration until the last iteration where the block is again ready to receive a new input. The simulation result is shown in Figure 10.28. If the block RepeatActivation is used as in Figure 10.29, at every activation the activation event is repeated until the output count reaches the input. The simulation result shows that the “counting up” process is done instantaneously; see Figure 10.30.

10.5 Repeat Activations

271

Fig. 10.29 When activated, the block counts instantaneously up to the value read on the input

Fig. 10.30 The output starts from zero and counts up to five instantaneously and stays at five until the next activation where it goes back to zero and starts over, counting up

This counter block can now be used to implement computations that are more naturally modeled in imperative languages.

10.5.2 Example: Random Permutation The following is an implementation of “Algorithm P”, the shuffling algorithm found in [31]. In this algorithm the shuffling of the elements of a vector is performed, starting from the first element, by exchanging the element with a randomly chosen element among the current and following elements of the vector, and then moving to the next element. The algorithm stops after treating the second-to-last element of the vector. The model in Figure 10.31 contains the implementation of the shuffle algorithm. The initial state of the DiscreteDelay block is the vector to be shuffled. The counter block introduced in the previous example iterates by outputs ranging from zero to n − 2, where n is the size of the vector. The exchange of the i-th element with the randomly chosen element is done using an extraction (MatrixExtractor block) and an insertion (Assignment block). The Rand block generates a random integer uniformly distributed from zero to the value provided by the input to the block. Its implementation uses the standard Random block, which generates a uniformly distributed value of type double. The implementation of Rand is illustrated in Figure 10.32.

272

10 Formalism

Fig. 10.31 The implementation of the shuffle algorithm

Fig. 10.32 The output is uniformly distributed from zero to the input value and can be of any type

Fig. 10.33 The mask of the permute block

The permute Super Block is masked and can, almost, be used as a random shuffle basic block. The block parameters are shown in Figure 10.33. There is however an important problem to consider. The RepeatActivation block forces the re-firing of the events that activate the permute block. For example in Model in Figure 10.34, the Display block is activated more than once at every unit of time, as expected. In fact the Display block is activated at every iteration of the shuffle algorithm. To avoid this problem, the permute Super Block must be declared Atomic. Atomic Super Blocks are presented in Section 10.6. Basically, by declaring the Super Block atomic, the interior of the Super Block is compiled separately and it is seen on the outside as a basic block. The Super Block can be declared atomic through its contextual menu.

10.5 Repeat Activations

273

Fig. 10.34 The main diagram where the shuffle algorithm is tested. The permute block contains the diagram in Figure 10.31

10.5.3 Example: Golden-Section Search The Golden-section search algorithm presented at the beginning of Chapter 4 is used to find the minimum (or maximum) of a unimodal function over a finite interval [a b]. The OML program in Chapter 4 has a while loop. The Activate implementation of this algorithm presented here illustrates how such while loops can be modeled. In Activate, while loops can be modeled using the RepeatActivation block. The diagram in Figure 10.35 is an implementation of the Golden-section search algorithm for solving the following optimization problem min f (u 1 , u 2 , p)

a≤u 1 ≤b

where u 2 is a possibly time-varying input of the diagram and p a list of constant parameters. The function f is defined by OmlExpression blocks with their expressions defined by the string-valued variable func. This expression may depend on u1, u2 and par. The latter is an OML structure for coding parameters. The variables a, b, tol, par and func are provided through the diagram mask. This masked Super Block can be used as a generic solver block. The model in Figure 10.36 is an example of the usage of this solver block. In this model, the problem is to find the solution to min

−10≤u 1 ≤10

(2 − cos(u 2 ))u 21 − sin(u 2 )u 1 + 2u 2

for u 2 = sin(t), for t = 0.1 × k, k = 0, 1, · · · . Figure 10.37 shows how the Goldensection search block is parameterized. The solution u 1 and the corresponding minimum value f are compared to analytically computed solution u ∗1 = sin(u 2 )/(2(2 − cos(u 2 )))

274

10 Formalism

Fig. 10.35 The Super Block implementing the Golden-section search algorithm

Fig. 10.36 The main diagram using the Golden-section search block in Figure 10.35

and the corresponding minimum f ∗ . The simulation results are shown in Figures 10.38 and 10.39.

10.6 Atomic Super Block Super Blocks are primarily used for organizational purposes. A hierarchical model is easier to develop and use. This is in part due to the scoping rules but also the special

10.6 Atomic Super Block

Fig. 10.37 The parameters of the Golden-section search block

Fig. 10.38 The simulation shows u 1 and the corresponding value f

Fig. 10.39 The scope showing the differences between u 1 and u ∗1 , and f and f ∗

275

276

10 Formalism

treatment in case of EventPortZero blocks. But the modularity introduced by the use of Super Blocks is not functional modularity. Comparing to the C language, a Super Block is comparable to a C macro and not a C function. When a Super Block is declared as Atomic, then it behaves more like a function. The use of the atomic property is particularly useful when the Super Block contains one or more RepeatActivation blocks. The RepeatActivation block forces a reactivation of the current event so its consequence may go beyond the Super Block, which is often not its intended usage. Note that it is the primary event that is reactivated by the RepeatActivation block so, for example, in case of events emanating from SampleClock blocks, the reactivation affects all the blocks driven by all the SampleClock blocks in the model. Making the Super Block atomic, seals it by providing a barrier to the application of the repeat process (an atomic Super Block is compiled separately where the activation input blocks of the Super Block are seen as primary activation sources).

Chapter 11

Hybrid Systems

11.1 Introduction Activate provides an environment for modeling systems where continuous-time dynamics and discrete-time and event driven dynamics interact. Strictly speaking such systems are hybrid systems. But a hybrid system is commonly seen as a set of dynamical systems described by differential equations associated each with a mode. The systems associated with different modes may share some of their variables and/or states. At any time only one mode is active; the equations associated with other dynamical systems are not present. The passage from one mode to another can be conditioned on the values of variables and states of the active mode. The events causing mode changes can re-initialize system variables specifying the initial condition of the dynamical system associated with the new mode. Hybrid systems come in many flavors: hybrid automaton, switched systems, state machines, etc. Modes are often referred to as (discrete) states. A number of formalisms have been developed for modeling such systems, which in general are very different from the signal based tools such as Activate. These tools provide in general a graphical view of different states and the associated transitions. The dynamical systems are described often textually, but they can be described otherwise for example via block diagrams. A simple example often used to illustrate hybrid systems is the vertical motion of a bouncing ball. The ball is modeled as a point mass at height y(t) above the ground subject to the force of gravity: y¨ (t) = −g. (11.1) When the falling ball hits the ground (y = 0), the ball bounces off of the ground with the ball’s velocity reversing and attenuating according to y˙ (τ ) = −α y˙ (τ − ), where 0 < α < 1 and τ is the time of impact, i.e., when y = 0 and y˙ < 0. © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_11

277

278

11 Hybrid Systems

Fig. 11.1 Bouncing ball system

Fig. 11.2 An Activate implementation of the hybrid system in Figure 11.1

Equation (11.1) can be re-expressed as a first order system of ODEs by introducing the velocity v(t) as the time derivative of y(t). This system is presented as a hybrid system in Figure 11.1. This simple system presents already both theoretical and practical challenges. In particular, the ball, in theory, would bounce an infinite number of times over a finite time period (Zeno effect). Such a model is not only numerically intractable, it does not even correspond to a good description of the actual physical phenomenon. In a naive implementation of the simulator, the ball eventually falls through the ground due to numerically error. An Activate model realizing this model is given in Figure 11.2. The simulation result is given in Figure 11.3. A modified version of the system representing the dynamics of the bouncing ball example is given in Figure 11.4. In this system if the ball’s velocity at the time of impact is under a threshold value, then the ball does not bounce anymore. The ball remains motionless on the ground. An Activate implementation of the system is given in Figure 11.5. The simulation works properly now as it can be seen in Figure 11.6. But the Activate model in Figure 11.5 does not correspond exactly to the original hybrid system. In this model,

11.1 Introduction

279

Fig. 11.3 Simulation result for Activate model in Figure 11.2 Fig. 11.4 Modified version of the bouncing ball system

when the ball ceases to bounce, the system equations become y˙ (t) = v(t) v˙ (t) = 0, with y and v initialized at the time of last impact by y(τ ) = 0, v(τ ) = 0. The solution of the system for all t ≥ τ is y(t) = 0, v(t) = 0; which corresponds to the desired behavior as indicated in the second state in Figure 11.4. But these latter equations are not explicitly imposed by the model. To impose these equations explicitly would mean that the integrator should no longer function subsequent to the last impact (discrete state change). Since the Integrator block is an always active block, the only way to do so would require the use of the EventPortZero block (presented in Section 10.2.7). This block once placed in a Super Block replaces the AlwaysActive block so that all the blocks declared as being always active get their activations from the output port of this EventPortZero block. This allows one to control the activation of blocks declared always active.

280

11 Hybrid Systems

Fig. 11.5 An Activate implementation of the hybrid system in Figure 11.4

Fig. 11.6 Simulation result for Activate model in Figure 11.5. Strictly speaking this result is not incorrect because such a trajectory is consistent if error tolerance is taken into account

An alternative implementation of the System in Figure 11.4 is given in Figures 11.7, 11.8 and 11.9. Note the use of Selector blocks to merge the signal values y and v produced in different states. The signals are never produced synchronously (if they did, the Selector block would give priority to the first input over the second).

11.1 Introduction

281

Fig. 11.7 An alternative Activate implementation of the hybrid system in Figure 11.4. The contents of the Super Blocks are given in Figures 11.8 and 11.9

Fig. 11.8 Inside of the Bounce State Super Block. The activation of the CLK0 block activates all the always active blocks in the diagram

The model in Figure 11.7 already resembles to some extent the diagram in Figure 11.4, in particular if the activation signals are seen as transitions. The self activation of the first state however is done internally in the Activate model. To make the model resemble even more the original diagram, an alternative implementation of the System in Figure 11.4 is proposed in Figures 11.11, 11.12 and 11.13. In this model, the self activating loop is taken outside the Super Block and the blocks SetSignal and GetSignal are used to pass the values of the signals y and v to the outside of the Super Blocks.

282

11 Hybrid Systems

Fig. 11.9 Inside of the Rest State Super Block. Note that this construction is not equivalent to the one in Figure 11.10 which would incorrectly indicate that the signals y and v are the same signal

Fig. 11.10 Incorrect model of the Rest State Super Block. If this diagram is used the signals y and v would always be identical because they refer to the same link

The model in Figure 11.13 can now be seen as a direct implementation of the hybrid system in Figure 11.4 where a Super Block is interpreted as a state and an activation link as a transition. In order for this analogy to hold, the Super Block must satisfy certain conditions, in particular its content should be activated when it receives an event, and the activation should end when it produces an event. In the following sections these conditions will be discussed in more detail and a systematic approach to modeling hybrid systems in this way will be presented.

11.2 Hybrid System Modeling The state machine (hybrid system diagram) formulation and block diagram formulation can be seen as two very different and opposing ways of modeling systems. In a hybrid system diagram (state machine), one and only one state is considered active at any time. This is in contrast with Activate type models where many blocks

11.2 Hybrid System Modeling

283

Fig. 11.11 Another implementation of the hybrid system in Figure 11.4. The contents of the Super Blocks are given in Figures 11.12 and 11.13

Fig. 11.12 Inside of the Bounce State Super Block in Figure 11.11

284

11 Hybrid Systems

Fig. 11.13 Inside of the Rest State Super Block. Note the difference with the diagram in Figure 11.9. The SetSignal blocks are used to name a signal so that their values can be retrieved in other diagrams without having to create actual links. If this diagram was built using a single source block as in Figure 11.9, then the two signal names y and v would refer to the same signal, which is not the intention here

are simultaneously/synchronously active. These two approaches however are not as contradictory as it may seem. Block diagram modeling formalisms such as Activate are not based on a data-flow concept. The inheritance mechanism provides a data-flow like behavior as an editor facility, but the blocks in an Activate model are event (or more generally activation) driven. On the other hand, the more recent state machine formalisms now not only support hierarchy but also parallel (concurrent, AND) states. This means that in a state machine diagram more than one state may be simultaneously active at the same level of hierarchy in two parallel sub-diagrams exchanging data. With these extensions of state diagrams and with the ability to explicitly manipulate activation signals in block diagram based modeling environments, it is not difficult to see a tendency of convergence between these two approaches. The objective of this chapter is to show how Activate can be used to model naturally hybrid system diagrams. The example in the previous section has shown the possibility of treating the states and transitions in hybrid system diagrams as Super Block and activation links (events) in Activate under certain conditions. To build, based on this idea, a systematic approach for modeling hybrid systems, there are a number of techniques that must be applied rigorously when designing the model. Some of these techniques were discussed when dealing with the examples presented in the previous section. An even more systematic approach to modeling state machines will be presented in Section 11.4.

11.2.1 Activating and Deactivating a Super Block If the Super Block is to be used as a discrete state, it has to activate itself when it receives an event and when it generates an event out, the internal dynamics must be

11.2 Hybrid System Modeling

285

turned off, and the Super Block should no longer produce events until it is reactivated. This may seem simple to verify but there are a number of subtle points to consider that are discussed here and in the next section when the examples are presented. Blocks are activation driven in Activate so turning them on and off conditionally is straightforward except for certain types of activations which are declared implicitly. Implicit activations are the ones that are not explicitly specified via red activation links. They include activation by inheritance, always activation, and initial activation. Implicit activations have been discussed in Section 10.2. In particular, the activation of the blocks declared always active can be controlled using the EventPortZero (CLK0) block as seen in the bouncing ball example. This block is a key element in the approach presented here. Thus in order to use a Super Block to represent a discrete state of a hybrid system, it is necessary to be able to activate and deactivate the Super Block. The activation is done from the outside (when an event is received) and the Super Block deactivates itself when it generates an output event. The Super Block may have one or more input activation ports and any number of output activation ports (including zero). The main condition to use the Super Block as a hybrid discrete state is that when the Super Block receives an event on any of its input activation ports, it “turns itself on” and when it decides to generate an event, “it turns itself off”. In the bouncing ball example, the turning on and off mechanisms were implemented using the blocks Constant, Selector, IfThenElse and AlwaysActive to provide the proper activation signal to feed to the EventPortZero (CLK0) block. See Figures 11.8 and 11.12. A similar construction is used in many of the states presented later. While the Super Block is active, no event should be sent to it, and the Super Block should not generate any events after it has been turned off. These conditions seem simple but their implementation requires certain considerations that will be discussed here.

11.2.2 Dynamics Common to all Discrete States Different discrete states of a hybrid system may correspond to completely different dynamical systems, with no common continuous-time states. On the other hand, in some cases, the dynamics may be common to all the states and the change of state simply produce jumps in the continuous-time states and parameter changes. In general, part of the hybrid system discrete dynamics is common to all states and each state has also its own private dynamics. Common dynamics can be modeled outside the Super Blocks, once. The choice of what is to be placed outside the Super Blocks depends on the system under consideration. There is not always a unique way to proceed.

286

11 Hybrid Systems

Fig. 11.14 Integrator with saturation

11.2.3 Use of SetSignal and GetSignal Blocks The use of SetSignal and GetSignal blocks are not recommended in standard Activate models because they hide the dependency between various components of the model. They actually go against the spirit of block diagrams where the links represent data connections. In state machine diagrams, the transitions do not represent data exchanges and are similar to activation links. The data exchanges, for example between concurrent states, are done through the use of the same variable names, somewhat similar to the way SetSignal and GetSignal blocks operate. So when modeling state machines in Activate, it is convenient to use SetSignal and GetSignal blocks and avoid placing regular data ports on the Super Blocks representing discrete states. These blocks can be used to communicate between different discrete states but also with the common area, outside the Super Blocks. The use of “Scoped” scoping avoids all risk of conflict with the rest of the model. This can be done thanks to the ActivationSignalScoping block. If the SetSignal and GetSignal blocks are used to eliminate signal links going in and out of the Super Blocks representing discrete states, the Activate diagram could be made to look very similar to the state machine diagram. This makes the model easier to understand and debug.

11.3 Examples 11.3.1 Integrator with Saturation Indicator The development of an integrator block with saturation is considered. This is a toy code: only the scalar case is considered and other simplifying assumptions are made. The existing Activate Integrator block handles already saturation in a more general setting. But here the integrator block will also output a saturation indicator, i.e., a signal that indicates whether or not the integrator is saturated. The dynamics of this system can be expressed by the state diagram in Figure 11.14. The outputs are the state x and a saturation variable not shown in this diagram.

11.3 Examples

287

Fig. 11.15 Sine wave input is integrated with saturation

Fig. 11.16 The simulation result shows that the state x is saturated as expected

Fig. 11.17 The block parameter GUI of the masked block

This system is implemented in Activate as a masked Super Block and tested in the model shown in Figure 11.15, with the simulation result in Figure 11.16. The mask parameters of the block can be seen in Figure 11.17.

288

11 Hybrid Systems

Fig. 11.18 The content of the masked Super Block (new block) Fig. 11.19 The output corresponds to the last event received

The content of the masked Super Block is shown in Figure 11.18. The three states in the state diagram in Figure 11.14 correspond to the Super Blocks integrate, satur...lower and satur...upper. In addition to these Super Blocks, the diagram contains the handling of the initial condition and the saturation indicator (Fig. 11.19). The content of the integrate is given in Figure 11.20. This Super Block corresponds to the unsaturated state of the integrator (the middle state in the state diagram in Figure 11.14). When the on event is received, the content of the Super Block becomes active thanks to the active Super Block. The Integrator block is used with re-initialization option and it re-initializes its input and starts integrating. The zero-crossing blocks are used to detect if the value of the state has reached any of the saturation levels. When it does, the corresponding event is fired and the Super Block is “turned off”. Depending on which event is fired, one of the other two Super Blocks corresponding to saturated states are activated. Their contents are presented in Figures 11.21 and 11.22. For detecting if the signal u has changed sign, the EdgeTrigger block is used instead of a zero crossing block. The reason is that unlike x, the signal u is not necessarily continuous so it may change sign by jumping across the zero value. A zero crossing block would not detect the sign change and would not generate an event,

11.3 Examples

289

Fig. 11.20 The content of the Super Block corresponding to unsaturated mode Fig. 11.21 The content of the state corresponding to lower saturation

which would be incorrect. This was discussed in Section 10.3.2. The EdgeTrigger block being a synchronous block, the EventDelay block is necessary to avoid an algebraic loop. The EdgeTrigger block inherits its activation. That is why a SampleHold is placed before EdgeTrigger block to make sure this block remains inactive when the corresponding Super Block is “turned off”.

290

11 Hybrid Systems

Fig. 11.22 The content of the state corresponding to upper saturation

11.3.2 Auto-Tuning PID Controller PID controllers are commonly used for control in the chemical process industry. A PID controller is a system made of the sum of weighted constant, integral and derivative feedbacks. In its simplest from, the transfer function of a PID controller can be expressed as follows   1 + τD s , Kc 1 + τI s where K c is the controller gain, τ I the integral or reset time, and τ D the derivative time. A large number of methods have been proposed for designing PIDs. The most popular method is the classical Ziegler-Nichols rule introduced in the 40s [51]. This heuristic rule provides values for the PID parameters based on the period Pu of the oscillation frequency at the stability limit and the gain margin K u for loop stability. More recently relay feedback identification has been used to estimate the values of the period Pu and the gain margin K u [3]. This can be used to implement an auto-tuning regulator where at start-up, a period of time is used to identify the system parameters (in particular Pu and K u ), which are subsequently used in the implementation of a PID controller. The implementation of such a model uses two states: the initial state where the parameters are identified and a final state where the PID control is applied. A simple implementation is illustrated in Figure 11.23. The system starts in the auto-tuning state and after a given period of time, when the PID parameters are determined, goes to the pid state. The auto-tuning is done by using a sign function in the feedback loop to generate a limit cycle oscillation. The period and gain of the oscillation is then measured and produced at the end of the

11.3 Examples

291

Fig. 11.23 Model implementing a PID auto-tuning methodology

Fig. 11.24 The auto-tuning state

tuning period as illustrated in Figure 11.24. Note that the Sign block is not used here since this block produces zero output for a zero input. The PID (more specifically PI in this case, i.e., τ D = 0) controller is activated after the auto tuning period and is implemented as shown in Figure 11.25. The PID parameters are computed as follows: K c = K u /2.2, τ I = Pu /1.2. e−0.4s The controlled plant has transfer function (s+3) 2 (s+1) and its implementation is illustrated in Figure 11.26. The auto-tuning period and the subsequent control corresponding to a square wave reference input is shown in Figure 11.27.

292

11 Hybrid Systems

Fig. 11.25 The pid state

Fig. 11.26 The plant model

Fig. 11.27 The auto-tuning is active until t = 40. Then the PID parameters are calculated and the PID control takes over

11.3 Examples

293

11.3.3 Clutch Mechanism The clutch is a mechanism that transmits the torque between the engine and the transmission. It is made of two rotating plates which are pressed against each other with an external force. In the absence of the force, the plates turn independently and no torque is transmitted. When a force is applied, the torque is transmitted but the plates do not necessarily turn with the same speed. This is called the slipping mode. If the applied force is sufficient, the plates do not slip and instead turn as a unit. This is called the lockup mode.

11.3.3.1

Clutch Model

The clutch mechanism can be modeled as a hybrid system with two states: Slip and Lock. In the Slip state, the dynamics contains two continuous-time states ωe and ωv denoting the angular velocity of the plates on the engine side and the transmission side. In the Lock state, ω is the unique continuous-time state representing both angular velocities. The state diagram corresponding to this system is presented in Figure 11.28 where the function Tf specifies the friction force: TFriction = Tf (Tin , Tout , ω) =

Iv Ie + Iv

 Tin − (be + bv )ω −

Ie Tout Iv

 (11.2)

and 2R μk Fn 3 2R = μs Fn . 3

Tfmaxk = Tfmaxs

11.3.3.2

Activate Model of the Clutch

The hybrid system diagram in Figure 11.28 is modeled in Activate as in Figure 11.29 which shows the top level diagram. The contents of the Super Blocks are in Figures 11.30, 11.31, 11.32, 11.33, 11.34, 11.35 and 11.36. The clutch system is tested in the model illustrated in Figures 11.37, 11.38 and 11.39. The simulation result for inputs Tin and Fn depicted in Figure 11.40 and a constant Tout are given in Figure 11.41.

294

11 Hybrid Systems

Fig. 11.28 Clutch system: Slip state on the left and Lock state on the right Fig. 11.29 Model of the clutch in Activate corresponding to the hybrid system in Figure 11.28. The Slip and Lock state Super Block are illustrated in Figures 11.30 and 11.34

11.3.4 Simple Two Dimensional Car Model A simple two dimensional half car (or bike) model is considered consisting of a body and front and rear suspensions. Several simplifying assumptions are made in order to reduce the complexity of the model, yet keep the essence of the mechanical structure so that the model’s dynamic behavior remains realistic. It would be straightforward to modify this example to make it even more realistic. This model corresponds to a hybrid system because depending on whether or not a wheel is touching the ground, the equations of motion are different. In fact the degree of freedom of the system (state size) are different in different states. The two wheels

11.3 Examples

295

Fig. 11.30 The diagram corresponding to the Slip state. The continuous-time dynamics of the system in this state is modeled in the free dynamics Super Block illustrated in Figure 11.31. The locking is detected by the Super Block illustrated in Figure 11.32. The Super Block Friction, illustrated in Figure 11.33 realizes the function Tf defined in (11.2)

Fig. 11.31 Continuous-dynamics of the system in Slip state

can be on the ground, or not, and the corresponding transitions are asynchronous. This can be modeled by asynchronous concurrent states as it is presented below.

296

11 Hybrid Systems

Fig. 11.32 Detection of locking in the Slip state

Fig. 11.33 The friction function realized by the Friction Super Block

Fig. 11.34 The diagram corresponding to the Lock state. The continuous-time dynamics of the system in this state is modeled in the stuck dynamics Super Block illustrated in Figure 11.35. The locking is detected by the Super Block illustrated in Figure 11.36

11.3 Examples

Fig. 11.35 Dynamics of the system in Lock state

Fig. 11.36 Detection of slipping in the Lock state

Fig. 11.37 Activate model for testing the clutch mechanism

297

298

11 Hybrid Systems

Fig. 11.38 Content of the Shaft Super Block: a simple Activate model of a shaft

Fig. 11.39 Content of the Inertia Super Block: an Activate model for the inertia on the transmission side

Fig. 11.40 The input torque Tin and force Fn

11.3.4.1

Basic Model

The simple 2D model of the car considered here includes (see Figure 11.42): • two parallel suspensions which are mass-less but have internal damping,

11.3 Examples

299

Fig. 11.41 The simulation result

Fig. 11.42 Simple model of the 2D car

• mass-less wheels of size zero rolling on the ground with no loss of energy due to friction, • a mass m with rotational inertia J in the middle of the mass-less rod connecting the top of the suspensions. The length of the rod connecting the top of the suspensions is a constant denoted by l. The model uses the following variables: • θ : angle the car body makes with the horizontal. This is equal to the angles of the suspensions with the vertical. • ξ and η: length of the two suspensions. • λ1 and λ2 (respectively λ3 and λ4 ): the horizontal and vertical forces exerted by the ground on the rear (respectively front) wheel. • ground modeled by the function y = F(x).

300

11 Hybrid Systems

• (x0 , y0 ) (respectively (x1 , y1 )), which represent the coordinates of the rear (respectively front) wheel. They may or may not be on the ground (i.e., on the curve F(x)). • (x, y): coordinate of the center of gravity of the mass m (the only object with mass in the model). The two suspensions are assumed to have the parameters k, γ , and d. The forces produced by the suspensions are k(ξ − d) + γ ξ˙ for the rear suspension and k(η − d) + γ ξ˙ for the front suspension.

11.3.4.2

Equations of Motion

The equations of motion are obtained from basic principles of physics. The sum of external forces in the x and y directions are computed in order to obtain the acceleration of the mass m in each of these directions. The torque around its center of gravity is also computed to obtain an equation for θ¨ . The remaining equations are obtained from the dynamics of the suspensions. Since in the model each wheel can be on or above the ground, normally four different sets of equations are required to describe the motion of the car. However, it turns out that once the model with both wheels on the ground is obtained, the other models can be obtained from it very easily. So first the assumption is made that both wheels are on the ground. The equations of motion for the system are obtained from basic principles: m x¨ = λ1 + λ3

(11.3a)

m y¨ = −mg + λ2 + λ4 0 = k(ξ − d) + γ ξ˙ − λ1 sin(θ ) + λ2 cos(θ )

(11.3b) (11.3c)

0 = k(η − d) + γ η˙ − λ3 sin(θ ) + λ4 cos(θ ) J θ¨ = λ1 φ0 − λ2 ψ0 + λ3 φ1 + λ4 ψ1 ,

(11.3d) (11.3e)

φ0 = ξ cos(θ ) + l sin(θ )/2 φ1 = η cos(θ ) − l sin(θ )/2 ψ0 = −ξ sin(θ ) + l cos(θ )/2

(11.4a) (11.4b) (11.4c)

ψ1 = η sin(θ ) + l cos(θ )/2.

(11.4d)

where

System (11.3) gives a complete characterization of the dynamics of the system if the λ’s are known. The ground applies orthogonal forces to the wheels; it also applies a tangential force if a torque is applied to the wheel (propulsion or braking). The rear wheel is assumed to produce a propulsion force u. Thus

11.3 Examples

301

 λ1 = 1 + Fx (x0 )2 u − λ2 Fx (x0 ) λ3 = −λ4 Fx (x1 ), where Fx (x) = Let

∂f (x). ∂x

 λr = λ2 1 + Fx (x0 )2 − Fx (x0 )u,

(11.5) (11.6)

(11.7)

(11.8)

then λ1 and λ2 can be expressed as follows −λr Fx (x0 ) + u λ1 =  1 + Fx (x0 )2 λr + Fx (x0 )u . λ2 =  1 + Fx (x0 )2

(11.9a) (11.9b)

λr is the value of the force applied orthogonal to the ground. Similarly for the front wheel λ3 and λ4 can be expressed in terms of a unique force λ f (force orthogonal to the ground on the front wheel):  λ f = λ4 1 + Fx (x1 )2 .

(11.10)

In particular λ3 = − 

λ f Fx (x1 )

1 + Fx (x1 )2 λf . λ4 =  1 + Fx (x1 )2

(11.11a) (11.11b)

λr and λ f are defined when the corresponding wheels are on the ground. If a wheel is not in contact with the ground, then the corresponding λ is simply set to zero in the equations of the system. When a wheel is on the ground, its location satisfies the equation describing the ground profile F: y0 = F(x0 ) y1 = F(x1 ).

(11.12) (11.13)

For each wheel independently, either the wheel is on the ground and the corresponding ground constraint is satisfied or the wheel is off the ground and the corresponding λ is set to zero. This means that the system equations change over time as the wheels come in contact and leave the ground.

302

11 Hybrid Systems

The state of the car is completely characterized in terms of the variables x, y, θ , their derivatives, and ξ and η. Thus the wheel positions can be obtained from these variables as follows

11.3.4.3

x0 = x − ψ0 y0 = y − φ0 x1 = x + ψ1

(11.14a) (11.14b) (11.14c)

y1 = y − φ1 .

(11.14d)

Simulation Model

The complete model of the system can be separated into the dynamics model of the car, which receives external forces represented by λi ’s, and the part that models the production of the λi ’s. The latter depends on the state of the system (wheels touching or not the ground) and is modeled using concurrent states. The dynamics of the car can be expressed as follows: 0 = x˙ − vx 0 = y˙ − v y 0 = θ˙ − ω

(11.15a) (11.15b)

0 = γ ξ˙ + k(ξ − d) − λ1 sin(θ ) + λ2 cos(θ )

(11.15c) (11.15d)

0 = γ η˙ + k(η − d) − λ3 sin(θ ) + λ4 cos(θ ) 0 = −m v˙ x + λ1 + λ3 0 = −m v˙ y − mg + λ2 + λ4

(11.15e) (11.15f) (11.15g)

0 = −J ω˙ + λ1 φ0 − λ2 ψ0 + λ3 φ1 + λ4 ψ1 ,

(11.15h)

where the λi ’s are defined in (11.9) and (11.11) when the wheels are on the ground. The values of λi ’s corresponding to wheels off the ground are zero. The system can be expressed in the following standard first order ODE form x˙ = vx y˙ = v y θ˙ = ω ξ˙ = (1/γ )(−k(ξ − d) + λ1 sin(θ ) − λ2 cos(θ ))

(11.16c) (11.16d)

η˙ = (1/γ )(−k(η − d) + λ3 sin(θ ) − λ4 cos(θ )) v˙ x = (λ1 + λ3 )/m

(11.16e) (11.16f)

v˙ y = (mg − λ2 − λ4 )/m ω˙ = (λ1 φ0 − λ2 ψ0 + λ3 φ1 + λ4 ψ1 )/J.

(11.16g) (11.16h)

(11.16a) (11.16b)

11.3 Examples

303

By expressing the equations of the system in this latter form, the system can be realized by standard Activate blocks by associating an Integrator block with each state variable. In particular the output of the Integrator is the signal representing the variable and the input corresponds to the expression on the right hand-side of the corresponding differential equation. In this case the model can be constructed as illustrated in Figure 11.43. Note that all the variables needed to create an animation, in particular the position of the car and its orientation, and the positions of the wheels, are provided by this Super Block. The λi ’s are generated by two concurrent state machines, one corresponding to the state of the rear wheel and the other to the state of the front wheel. The complete model is presented in Figure 11.44. The road profile function F and its derivative Fx are defined using expression parameters in MathExpression blocks so that they can be changed easily. For each wheel, the state machine contains two states: wheel off the ground and wheel on the ground. When the wheel is off the ground, the corresponding λi ’s are zero (see Figures 11.45 and 11.48), and remain zero until the wheel touches the ground. This event is detected by the zero crossing block, which generates an event to leave the state. The input to the block is the difference between the vertical position of the wheel and the vertical position of the ground at the same horizontal position. When the wheel is on the ground the λi ’s are given by (11.9) in the case of the rear wheel and (11.11) in the case of the front wheel. The content of the corresponding states for the two wheels are illustrated in Figures 11.46 and 11.47. The constraint that the wheel be on the ground is imposed by the Constraint block. The block does that by generating the appropriate force applied orthogonal to the ground: λr for the rear wheel and λ f for the front wheel. The state remains active as long as the the orthogonal force remains positive, i.e., the wheel is pushing against the ground. When this is no longer the case, an event is detected by a zero crossing block and the state exits. Note that the derivative output of the Constraint block is used to represent λr and λ f . This amounts to replacing these state variables by their time derivatives λ˙ r and λ˙ f in the original DAE equation thus reducing the index of the DAE system from two to one making it amenable to numerical simulation by the DAE solvers available in Activate. The simulation result can be seen in Figure 11.50 generated by the Anim2D block. After a successful landing, the car accelerates too much and end up on its roof. The force u(t) causing the acceleration is shown in Figure 11.49. The mode changes can be seen in Figure 11.51 where the top diagram shows the periods where the rear wheel is off and on the ground, and the bottom diagram shows the same thing for the front wheel.

Fig. 11.43 The dynamics of the car corresponding to Equations 11.16. The inputs are the forces λ applied to the wheels

304 11 Hybrid Systems

Fig. 11.44 The complete model of the car containing two concurrent states machines, one associated to each wheel

11.3 Examples 305

306

11 Hybrid Systems

Fig. 11.45 This state corresponds to the front wheel being off the ground. No forces are applied to the front wheel while in this state. The state exits when the wheel hits the ground

Fig. 11.46 This state corresponds to the rear wheel being on the ground. The orthogonal force λr is produced by the constraint block, which is used to detect the time the wheel leaves the ground and, in conjunction with the value of the force u, provides the values of λ1 and λ2

11.4 Systematic Approach to Constructing State Machines In previous sections, it was shown that the ability to work explicitly with activation signals can be used to construct hybrid systems where various continuoustime dynamics are associated with distinct discrete states. The construction of these

11.4 Systematic Approach to Constructing State Machines

307

Fig. 11.47 This state corresponds to the front wheel being on the ground

Fig. 11.48 This state corresponds to the rear wheel being off the ground

exclusive discrete states, however was not systematic and required specific developments for each individual case. A systematic approach to designing state machines in Activate is presented in this section. In this approach the exclusive and concurrent states are clearly specified and constructed following a standardized method. This approach is not the best choice for modeling systems in all cases, in particular in

308

11 Hybrid Systems

Fig. 11.49 Force u applied to accelerate forward

simple cases it may lead to additional complexity, but it can facilitate model construction in many situations. The method is illustrated through reformulation of models previously presented.

11.4.1 Exclusive and Concurrent States A hybrid system represented by discrete states may have both exclusive and concurrent states. Consider the car model presented in Section 11.3.4. This model contained four states: two corresponding to the rear wheel and in particular whether or not the wheel is on the ground, and the other two similarly corresponding to the front wheel. Clearly a wheel is either on the ground or it is not, so the states associated with the same wheel are mutually exclusive. On the other hand states associated with different wheels can run in parallel (for example both the rear and the front wheel can be simultaneously on the ground). The construction of exclusive states can be done by associating a unique number to each exclusive state. The choice of the active state can then be made using the SwitchCase block, which generates an activation signal only on one of its outputs depending on the value of its input. This input would then be the number of the current state. In addition to a number, a letter can also be associated with the activation signal in case of concurrent states. For example in the car model, the activation signals may be named R1, R2, B1, B2; the rear wheel activations R1 and R2 are exclusive, and, the front wheel activation B1 and B2 are exclusive. Each state receives an initialization event (called entry) in which case it sets the state value to its state number and does other initialization tasks if needed. The state is not considered active at this point. Subsequent to the entry event, the state receives

Fig. 11.50 Snapshots of the car over the interval of simulation

11.4 Systematic Approach to Constructing State Machines 309

310

11 Hybrid Systems

Fig. 11.51 State changes during the interval of simulation

activation signals (during activation events) until a new state is activated. This is done in general by an outgoing event generated by the current state used as entry event to another state. To illustrate this approach, the bouncing ball example presented on page 277 is reformulated as a hybrid system with two exclusive states: off the ground and ground.

11.4.2 Examples 11.4.2.1

Bouncing Ball

In this example the first state represents the dynamics of the system when the ball is off the ground and the second, what happens when the ball hits the ground. The model is shown in Figure 11.52. The always active activation signal is separated into the initial event and its complement as illustrated in Figure 11.53. The bouncing ball Super Block (state) contains two states as seen in Figure 11.54. The during activations of these states are not passed through input activation ports; they are passed to the Super Blocks via set and get signal blocks (SetActivationSignal and GetActivationSignal blocks) to simplify the diagram. These signals are produced and set in SetActivations_B Super Block; see Figure 11.55. They are consumed inside the two states as illustrated in Figures 11.56 and 11.57. In the off the ground state, the dynamics of the system is similar to the one used previously but the detection of the ground is done using an IfThenElse block producing the exit event used as entry event to the ground state. In this latter state the during activation is directly used as exit activation thus returning to system to the off the

11.4 Systematic Approach to Constructing State Machines

311

Fig. 11.52 Main diagram of the bouncing ball model

Fig. 11.53 The content of the Super Block separating the initial event from always activation in main diagram of the bouncing ball model

ground state, in addition to generating the new, post impact, values of the position and velocity of the ball. This model produces the expected result up to certain point but then the simulation becomes very slow and practically stops. This is somewhat expected (because in theory advancing the time requires an infinite number of bounces) and is an improvement over the model in Figure 11.2 where the ball goes through the table. An extension of this model was presented in Figure 11.4 with the assumption that if the ball’s velocity at the time of impact is under a threshold value, then the ball does not bounce anymore. The implementation of this extension using the systematic approach of this section yields the model in Figure 11.58. The main states in this model are the bounce and the rest states. As long as the ball bounces with sufficient speed, the system remains in the bounce state, then it goes to the rest state. Here the states off the ground and ground become the substates of the bounce state as it can

312

11 Hybrid Systems

Fig. 11.54 Inside the bouncing ball state Fig. 11.55 Exclusive during activation signals are produced for different states

be seen in Figure 11.59. The content of the ground state is shown in Figure 11.60 and the rest state is shown in Figure 11.61.

11.4.2.2

Traffic Light

Here the traffic light model presented in Section 6.2.1 (Figure 6.27) is revisited. The model considered here is illustrated in Figure 11.62. Note the use of an EventClock block used to drive the new state machine. The Traffic light Super Block used previously, shown in Figure 6.28, contained five states. The same states are considered again but this time the state are constructed using the exclusive strategy presented earlier with a periodic

11.4 Systematic Approach to Constructing State Machines

Fig. 11.56 The off the ground state Fig. 11.57 The ground state

Fig. 11.58 The system is in the bounce state then moves to the rest state and stays

313

314

Fig. 11.59 The previous bouncing ball state is now a substate Fig. 11.60 Inside of the ground state. Two ways to leave this state immediately, either by generating a bounce event or a stop event, depending on the value of the velocity

Fig. 11.61 The ball no longer moves once the system is in the rest state

11 Hybrid Systems

11.4 Systematic Approach to Constructing State Machines

315

Fig. 11.62 Top diagram of the new model of the traffic light example

Fig. 11.63 The new version of the state machine model in Figure 6.28

event source. For that, the state signal is introduced and a StateActivations Super Block is used to produce activation signals by subsampling the period event signal; see Figure 11.63. The exclusive activation signals produced inside the StateActivations Super Block are shown in Figure 11.64. The contents of the five states of the model are illustrated in Figures 11.65, 11.66, 11.67, 11.68 and 11.69. The delays are implemented using a counter with reset. The counter is initialized to zero when activated through its reset port and is incremented when activated through the tick port. An event is outputted synchronously

316

11 Hybrid Systems

Fig. 11.64 The StateActivations Super Block produces exclusive during activation signals for different states

Fig. 11.65 The initial state Red Red

when the count reaches a value determined by the block mask parameter. The implementation of the counter is shown in Figure 11.70. The RepeatActivation blocks (Repeat Activation) are systematically introduced to avoid delays in state transitions. In the absence of these blocks, each transition will introduce one period of delay, in particular the first during event of the state will come one period after its entry event. Since a state may exit immediately, several state transitions may occur immediately, which without the usage of RepeatActivation blocks can introduce large delays in the model. The state changes are shown in Figure 11.71.

11.4.2.3

Sticky Balls

The model considered in this section is a variation of the sticky masses model presented in [33], Chapter 4. The physical system in Figure 11.72, considered here is made of two sticky balls attached to two springs on opposite sides. The two balls,

11.4 Systematic Approach to Constructing State Machines

317

Fig. 11.66 The state Green Red Fig. 11.67 The state Yellow Red

considered point masses, can slide freely with no friction on the surface. Their movements are governed by the spring forces and their contacts with each other. When the balls come into contact, they stick together. They remain stuck as long as the spring forces are unable to tear them apart. To be torn apart the masses should be pulled apart with a force exceeding a stickiness force. The stickiness force is initialized at a maximum value at the time of contact and then decays exponentially as a function of time. Denoting the spring constants k1 and k2 and their neutral position a and b respectively, and the positions of the balls x1 and x2 , the spring forces applied to the balls when they are not in contact can be expressed as follows:

318

11 Hybrid Systems

Fig. 11.68 The state Red Green Fig. 11.69 The state Red Yellow

F1 = −k1 (x1 − a) F2 = −k2 (x2 − b).

(11.17) (11.18)

So if m 1 and m 2 denote the masses of the balls, the equations of motion of the system can be expressed as follows: x¨1 = −k1 (x1 − a)/m 1

(11.19)

x¨2 = −k2 (x2 − b)/m 2 .

(11.20)

When the balls are stuck together, the system can be seen as a single body with mass m 1 + m 2 subject to force F1 + F2 . The equation of motion can thus be expressed as:

11.4 Systematic Approach to Constructing State Machines

319

Fig. 11.70 The counter implementation

Fig. 11.71 The state trajectory plotted by the Scope block Fig. 11.72 Sticky balls

x¨3 = −(k1 (x3 − a) + k2 (x3 − b))/(m 1 + m 2 ),

(11.21)

where x3 denotes the position of the balls. When the balls collide, x3 is defined as x3 := x1 = x2

(11.22)

320

11 Hybrid Systems

Fig. 11.73 Spring and contact forces

and the velocity of the stuck balls are obtained from the law of conservation of momentum: (11.23) x˙3 = (m 1 x˙1 + m 2 x˙2 )/(m 1 + m 2 ). The collision occurs when x1 − x2 becomes zero. On the other hand, the stuck masses get separated when the forces pulling them apart exceeds the stickiness force. Let F denote the force of contact between the two balls (see Figure 11.73). Then the value of the force tearing the balls apart is −2F. When the balls are stuck together, they have identical acceleration γ satisfying m 1 γ = F1 − F

(11.24)

m 2 γ = F2 + F,

(11.25)

from which the following expression for F can be obtained F = (m 2 F1 − m 1 F2 )/(m 1 + m 2 ).

(11.26)

At separation time, the positions and velocities of the two balls are the same and equal the position and velocity of the stuck balls just before separation: x1 := x3 , x2 := x3 , x˙1 := x˙3 , x˙2 := x˙3 .

(11.27)

The separation condition −2F > s can be expressed as 2

(m 2 k1 − m 1 k2 )x3 − (m 2 k1 a − m 1 k2 b) > s. (m 1 + m 2 )

(11.28)

The stickiness force s satisfies the following differential equation s˙ = −s/τ

(11.29)

where the state s is re-initialized to smax every time the balls come into contact. In case m 1 = m 2 , Equation (11.28) reduces to (k1 − k2 )x3 + k2 b − k1 a > s,

(11.30)

11.4 Systematic Approach to Constructing State Machines

321

Fig. 11.74 Top diagram of the sticky balls model

the condition used in [33] for the general case, which does not seem to be correct. Condition (11.30) is also used in a Ptolemy demo1 but the simulation model turns out to be correct since the model makes the implicit assumption that m 1 = m 2 . The Activate model representing the dynamics of the sticky balls system is constructed using two Super Blocks each representing a system state: free for when the balls are separate and stuck for when they are not. The dynamics of the free state and stuck state are alternatively turned on and off as the balls collide and get separated. Here the free and stuck dynamics are modeled separately. The continuous-time states (x1 , x2 ) and x3 are considered distinct states. An alternative approach would be to consider common dynamics with parameter changes with x3 = x1 = x2 in the stuck state. This approach is not considered here. Examples with common dynamics will be presented later. The top diagram of the model is illustrated in Figure 11.74. The content of the Sticky masses model Super Block is shown in Figure 11.75. The Super Blocks Free state and Stock state represent the discrete states of the system. When they receive an event, they are activated (their always active blocks become active). They are de-activated when they produce an event. Such events are used to activate another Super Block and so on. An initial event is used to “turn on” (activate) the free state. As it can be seen on Figure 11.75, the Free state Super Block is initially made active. Upon the collision of the balls detected inside this Super Block, the finale values of the positions and velocities of the balls are provided and an event (stuck) is generated. This event activates the Stuck state Super Block which thanks to the input stuck event re-initializes its internal states (x3 , x˙3 , s and s˙ ). This Super Block remains active until the separation of the balls is detected in which case the Super Block generates a free event turning itself off and turning on the Free state Super Block. 1 http://ptolemy.eecs.berkeley.edu/ptolemyII/ptII8.1/ptII/ptolemy/domains/ct/demo/Sticky

Masses/StickyMasses.htm

322

11 Hybrid Systems

Fig. 11.75 The content of the Sticky masses model Super Block in the diagram of the sticky balls model

Fig. 11.76 Simulation result showing the positions of the balls and the total energy of the system

A typical simulation result is illustrated in Figure 11.76. On top the positions of the ball are traced as a function of time. The two curves are superposed when the system is in Stuck state. The bottom figure show the total energy of the system. The collisions result in loss of energy as expected, otherwise there is no loss since no friction is accounted for in the model. Figure 11.77 shows the inside of the Free state Super Block. Note the use of the EventPortZero (CLK0) block receiving the activation signal of the Super Block.

11.4 Systematic Approach to Constructing State Machines

323

Fig. 11.77 Diagram inside the Free state Super Block

When this block is placed in a Super Block, all the always active blocks within the Super Block are activated by the activation signal received by the EventPortZero block. In the actual implementation of this functionality (which is transparent to the end user), an always active block has an invisible activation port numbered 0 connected to the always active clock. By placing an EventPortZero block in the Super Block, all the activation links to these ports are made to have the same activation origin as the EventPortZero block. So the EventPortZero block can be used to turn on and off the always active dynamics within the Super Block. The Free state Super Block contains the free dynamics Super Block (illustrated in Figure 11.78) which contains a realization of Equations (11.19) and (11.20) and the mechanism to re-initialize the states (x1 , x2 , x˙1 , x˙2 ) using the values of x3 and x˙3 . The Free state Super Block also contains a zero-crossing detection mechanism generating a stuck event when the balls collide (see Figure 11.79). Figure 11.80 shows the inside of the Stuck state Super Block. The velocity of the balls after collision, x˙3 expressed in (11.23) is realized using a MathExpression block. The equation of motion in the stuck state, Equation (11.21), is realized inside the stuck dynamics Super Block (illustrated in Figure 11.81) along with the mechanism to re-initialize x3 and x˙3 . The condition for leaving the stuck state is implemented in a Super Block the content of which is illustrated in Figure 11.82. Condition (11.28) is tested both upon entry (using the IfThenElse block) and subsequently using a zero-crossing block. Note that an event delay block is required to delay the exit from the state in case the condition is satisfied upon entry. In absence of delay, the compiler flags a potential algebraic loop. Indeed the Super Block must either be active or not active when the event is received. The delay however can be set to zero. The use of this delay implies that the balls get stuck upon collision even if the conditions are such that they are immediately pulled away.

324

Fig. 11.78 Diagram inside the Free dynamics Super Block

Fig. 11.79 Diagram generating the stuck event when balls collide

Fig. 11.80 Model of the stuck state

11 Hybrid Systems

11.4 Systematic Approach to Constructing State Machines

325

Fig. 11.81 Stuck dynamics

Fig. 11.82 Diagram generating the free event when balls are pulled apart

The Super Blocks on the top diagram generating the activation signals for the two states are realized as in Figure 11.19. The activation signal is obtained by subsampling the always active activation signal produced by the SampleClock with period zero.

11.4.3 Two Dimensional Car or Bike Model Here the model of the two dimensional car system presented in Section 11.3.4 is reconsidered. The model in Figure 11.44 includes the four discrete states of the system: off the ground rear wheel, on the ground rear wheel, off the ground front wheel, and on the ground front wheel. These states are both concurrent and exclusive,

326

11 Hybrid Systems

in particular a wheel cannot be on and off the ground at the same time but the front and rear wheels dynamics are active simultaneously. The standard approach presented in this section is applied to this system. The top diagram of the resulting model is shown in Figure 11.83. The two concurrent states, each associated with each wheel, are represented by the Rear and Front Super Blocks. The Rear and Front Super Blocks each contain two exclusive substates as shown in Figures 11.84 and 11.85. The contents of these substates are shown in Figures 11.86, 11.87, 11.88 and 11.89.

11.4.4 Racing Cars In this example, a model is constructed where multiple state machines run concurrently (in parallel). Each state machine is used in the modeling of a car. The complete model contains N cars that run and interact on the same track. Car models are identical so the number of cars racing on the track can easily be modified. In the configuration considered here, the cars cannot pass each other on the track but they regularly have to leave the track and stop to get fuel in which case other cars can pass them. After refueling, a car can return to the track provided it has enough clearance on the track. Cars can have different reservoir capacities, top speeds, etc. Specifically, each car can be in any of the following states: • State 0 (fuel up): Car off the track, stopped, fueling. • State 1 (ready to go): Car off the track waiting for clearance. • State 2 (to cruise): Car accelerating towards or maintaining its cruising speed in the absence of other cars ahead up to a given distance. • State 3 (follow): Car following other car. • State 4 (go to stop): Car slowing down to stop at the fueling station. The top diagram of the model is shown in Figure 11.90. In this case the model contains 4 cars. A car can be represented by the Vehicle Super Blocks but since these Super Blocks are identical, only one is required, others can reference it. Three IncludeDiagram blocks are used to reference the unique Vehicle Super Block in this model. The number of cars can be modified by adding or removing similar IncludeDiagram blocks (or equivalently Vehicle Super Blocks). The content of the Vehicle Super Block is shown in Figure 11.91. The Vehicle model contains a Super Block (Schart) containing the state machine representing various states of the vehicle. The content of Schart is shown in Figure 11.92. There are 5 possible states. The dynamics of the vehicle is modeled in the car dynamics Super Block. The main signals in the model are: • x: the traveled (absolute) distance. The position of the car on the track is then obtained from x modulo L (the length of the track) and stored in the signal xm. • v: the speed of the car.

Fig. 11.83 The complete model of the car containing two concurrent states machines, one associated to the rear wheel and one to the front wheel

11.4 Systematic Approach to Constructing State Machines 327

328

11 Hybrid Systems

Fig. 11.84 The rear wheel state

Fig. 11.85 The front wheel state

• e: the amount of fuel left in the tank. • u: the force applied to the car in the forward direction by the engine or brakes (the value of the force is negative in the case of brake). • idx: A constant integer value signal uniquely identifying each vehicle. Its value is defined via the variable idx in the Context of the Super Block at evaluation time as follows: global IIdx; IIdx=IIdx+1 idx=IIdx

The global variable IIdx is initially set to zero in the model Initialization script. When the Context of the Super Block is evaluated, the value of this global vari-

11.4 Systematic Approach to Constructing State Machines

329

Fig. 11.86 The on the ground rear wheel substate Fig. 11.87 The off the ground rear wheel substate

able is incremented and assigned to the local variable idx. So the Super Blocks associated with different vehicles end up with idx values ranging from 1 to N . • d: distance to the closest vehicle ahead on the track. If no other vehicles are on the track, then the value is L. The value of the signal d, unlike the previous signals, depends on the signals corresponding to other vehicles, in particular the vehicles positions on the track. • x1, x2, x3,· · · : global signals with corresponding x values for different vehicles. These signals are combined to form the global signal X. • e1, e2, e3,· · · : global signals with corresponding e values for different vehicles. These signals are combined to form the global signal Ec.

330

11 Hybrid Systems

Fig. 11.88 The on the ground front wheel substate

Fig. 11.89 The off the ground front wheel substate

• s1, s2, s3,· · · : global signals designating the active state of each vehicle. They take values ranging from 0 to 4 corresponding to vehicle states presented earlier. These signals are combined to form the global signal S. The global signals X, Ec and S are constructed inside the Graphics Super Block as shown (for X) in Figures 11.102 and 11.103.

11.4 Systematic Approach to Constructing State Machines

331

Fig. 11.90 The Activate model of the car racing example Fig. 11.91 The Super Block Vehicle modeling each vehicle’s behavior

11.4.4.1

Vehicle Dynamics

The vehicle continuous-time dynamics is modeled in the car dynamics Super Block and is shown in Figure 11.93: x˙ = v(t) v˙ = −av(t)2 + bu e (t) e˙ = −cv(t) max(0, u e (t)) where a, b and c are positive parameters and the effective force applied to the vehicle is defined as follows  u(t) if e(t) > 0 u e (t) = , min(u(t), 0) if e(t) = 0

332

11 Hybrid Systems

Fig. 11.92 The state machine formulation of the vehicle’s states

Fig. 11.93 The dynamical system governing the continuous-time behavior of the vehicle is modeled in car dynamics Super Block. The content of the Super Block computing the distance d is given in Figure 11.94

11.4 Systematic Approach to Constructing State Machines

333

Fig. 11.94 In the computation of the distance to vehicle in front, the vehicles that are not on the track are excluded Fig. 11.95 The vehicle remains in state 5 for a period of time proportional to the quantity of fuel it loads (maximum capacity minus the current level)

where u(t) is the reference force corresponding to the driver’s action. It is assumed that the effective force is equal to the reference force except when the reference force is positive but the fuel tank is empty. The fuel start and fuel end events re-initialize respectively the vehicle’s speed to zero and the amount of fuel to its maximal capacity given by the global vector E for all the cars. The distance d is computed by the Super Block in Figure 11.94 using the signal dX (distance of the vehicle to all vehicles) and the vector of all vehicles’ states. The computation consists in finding the minimum over dX modulo L by excluding the current vehicle and other vehicles that are either in state 0 or state 1 (i.e., off the track).

11.4.4.2

Discrete States

The five discrete states of the vehicle are described below. • fuel up: the content of this Super Block is given in Figure 11.95. In this state the reference force is set to zero, and since the event activating this state is communicated to the fuel start activation input of the car dynamics Super Block

334

11 Hybrid Systems

Fig. 11.96 The implementation of an event delay using a counter. The delay is the value received by the block times the period of the master clock dt

Fig. 11.97 The vehicle still off the track and not moving, monitoring the track for clearance to take off

setting the vehicle’s speed to zero, the vehicle does not move in this state. The state exits after a delay implemented by the Super Block shown in Figure 11.96, which initializes its state to the desired number of iterations when it is reset and then decrements the state until reaching zero in which case it generates an event. • ready to go: the content of this Super Block is given in Figure 11.97. Every dt units of time, the track over the interval starting a distance fb behind the position of the vehicle up to a distance of ff ahead is checked and an event is generated if this interval is clear (no vehicle in it). The reference force remains zero in this state and the value of the corresponding s is set 1. • to cruise: the content of this Super Block is given in Figure 11.98. The state exits in two different ways: either because a vehicle ahead comes within a fb2 distance, in which case the state transitions to the follow state, or the fuel level

11.4 Systematic Approach to Constructing State Machines

Fig. 11.98 The vehicle is on the track and no car ahead is closer than fb2

Fig. 11.99 The vehicle is on the track following a vehicle ahead

335

336

11 Hybrid Systems

Fig. 11.100 The reference force when the vehicle is following another vehicle ahead at a distance d is computed in this diagram

Fig. 11.101 The vehicle slows down and stops at the fueling station

Fig. 11.102 The global vector signals are constructed by Mux blocks. For example X could be constructed as in Figure 11.103

Fig. 11.103 The global vector X is obtained by multiplexing the position values x1 to x4. This Super Block is actually implemented as a programmable Super Block parameterized by the value N , the number of vehicles

11.4 Systematic Approach to Constructing State Machines

337

Fig. 11.104 The travelled distance of the vehicles as a function of time

is below a threshold value while the vehicle arrives within a specified distance (dsta) of the location of the fueling station (xsta). In the latter case the state exists in the direction of go to stop state. In the to cruise state, the reference force is computed to stabilize the speed of the vehicle close to a reference speed V(idx). This is done by setting the reference force u proportional to the difference between the current speed and the reference speed. • follow: the content of this Super Block is given in Figure 11.99. The state exits for refueling under the same conditions that the to cruise exited. If the distance to the vehicle ahead becomes larger than fb2, the state exits with event cruise activating the cruise state. While in this state, the reference force is computed using the Super Block DMF. The content of this Super Block is provided in Figure 11.100 realizing the following formula  u(t) = Fa 1 −



v(t) Vref



 −

fb d(t)

2  .

• go to stop: the content of this Super Block is given in Figure 11.101. This state is activated when the vehicle is close to the fueling station. While in this state, the vehicle reduces its speed to target value Vs. The state exits when the vehicle reaches the fueling station. Note that even in this state, the control strategy guarantees that the vehicle cannot come into collision with a vehicle ahead. The global vector signals X, S and Ec are defined in the Global variables Super Block. See Figure 11.102.

338

11 Hybrid Systems

Fig. 11.105 Cars’ positions on the track as a function of time

Fig. 11.106 The states of the vehicles as a function of time

11.4.4.3

Simulation Result

The car positions are shown in Figures 11.104 (travelled distance) and 11.105 (position on the track). The vehicles’ positions on the track are plotted as a function of time in Figure 11.107. The evolutions of discrete states associated with vehicles are presented in 11.106. In this simulation, the four cars are initially positioned closely near the zero position on the track and start off at t = 0 with zero velocity.

11.4 Systematic Approach to Constructing State Machines

339

Fig. 11.107 The fuel level of the vehicles as a function of time

As it can be seen, the vehicles cannot pass each other except when a vehicle is off the track (i.e., it is stopped at the fueling station or waiting for clearance to get back on the track). The cars’ fuel levels are shown in Figure 11.107.

Chapter 12

Activate-OML Interactions and Batch Simulation

Most Activate functionalities are available from the OML environment. Hundreds of APIs allow users to interactively or programmatically construct, modify, compile, simulate, save, load, ..., Activate models in OML. An OML API is an OML function that in general takes as argument a model, or a model component such as a diagram or a block and modifies it or performs an action associated with it, such as running a simulation if the argument is a model. There exist three categories of APIs acting on • the full model structure at the block diagram editor level, • the diagram and block structures at the evaluation level, • on the block structure at the simulation level for blocks with simulation functions expressed in OML. Some of these APIs are presented in this chapter but the emphasis is placed on batch simulation (running Activate simulations from an OML script), and in particular its application to optimization. APIs used for linearization are also presented.

12.1 Batch Simulation In many applications, Activate models are created to be simulated multiple times. This was introduced in Chapter 8 where the End block with the Restart option was used to restart simulations. This method of implementing multi-run simulations is simple to use and very efficient in certain applications such as optimization, but is less versatile than batch simulation, which consists of programming, using an OML script, the calls to the simulator and exchanging data between the simulator and the OML environment. Batch simulation gives user access to all the functionalities available in the OML environment. On the OML side, an Activate simulation can be © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_12

341

342

12 Activate-OML Interactions and Batch Simulation

seen as a mere function call where some model parameters are the function arguments and some simulation results are function outputs. The simulation of an existing Activate model requires in general a simulation object and an evaluator. The main APIs used for running programmatically simulations of Activate models are the following • bdeCreateSimulationObject for creating a simulation object, • vssCreateEvaluator for creating an evaluator, and • vssRunSimulation to run the simulation. The simulation object holds the structures used to communicate with the graphical interface, in particular the Scope and Display blocks. The simulation object is not required if such graphical outputs are not needed. In many batch simulation applications, graphical outputs are inhibited to speed up the simulation. For example, when multiple simulations are done for optimization purposes, the scope and display outputs are usually not needed. In some cases however such outputs can provide clues as to the way the optimization algorithm operates. The evaluator is an OML script, specifically generated for the model being considered. The execution of this script creates the simulation structure that is used by the simulator to run simulations. The evaluator script needs not be regenerated as long as the model is not edited. Note that the model can use new parameter values by using an external-context workspace (presented later in this section) or by reading values from the base workspace using the FromBase function inside the Initialization script or a Context script, without being edited. The execution of the evaluator updates the model by taking into account these changes. The evaluator itself needs not be regenerated. In case model parameter changes are not used in the model, the evaluator only needs to be executed once (new evaluations will result in identical simulation structures). This is in particular the case where the model exchanges data through SignalIn, SignalOut or FromBase, ToBase blocks. The vssRunSimulation function runs a simulation with or without a simulation object. It can take as argument the evaluator, which is used to create and run the simulation. It also takes a workspace to be used to SignalIn and SignalOut signals and the external-context workspace. The final argument is the simulation object, which is optional. The simulation object is not mandatory. Not providing a simulation object will simply inhibit all graphical outputs.

12.1.1 Example Consider the Bouc-Wen model introduced in Section 7.2.2 where the simulation was done for a unique value of the current. The following OML script is used to run simulations for different values of the current and the results are superimposed. This is done by setting the window option of the AnimXY block to Overlay.

12.1 Batch Simulation

343

Fig. 12.1 The result of executing the script

me = omlfilename(’fullpath’); p = fileparts(me); model = [p , ’/bouc-wen-batch_.scm’]; simobj = bdeCreateSimulationObject(model); ev=vssCreateEvaluator(model,simobj); env=getnewenv; context = struct; I0=[0,0.3,1,2,10]; for k = 1:length(I0) i0 = I0(k); context.i0 = i0; vssRunSimulation(ev,context,env,simobj); end

The result is shown in Figure 12.1. Note the use of the external-context workspace to pass different values of the current i0 to the model for simulation. The way the external-context workspace works is explained below.

12.2 Data Exchange Between OML and Activate A key element in the implementation of multi-run simulations is the ability to exchange data, in particular to impose an Activate model parameter value from the OML environment, and once the simulation is completed, to obtain Activate simulation results in the OML environment. There are various ways to exchange data between the OML environment and the Activate model.

344

12 Activate-OML Interactions and Batch Simulation

12.2.1 Using the External-Context Workspace A workspace contains the definition of a set of OML variables. It is usually constructed as a result of executing OML commands within a script. For example in an Activate model, the Initialization script creates a model workspace and each diagram has its own workspace, which is obtained from the execution of its Context within its parent diagram workspace. In the case of the top-level diagram, the Context is executed in the model workspace. The variables available in a diagram workspace, and no other variables, can be used in the expressions defining the block parameter values for the blocks inside the diagram. When a simulation is run in the batch mode, the workspace external-context is injected in the model workspace before the evaluation of the diagram workspaces. This way, the variables in external-context may modify the values of the variables defined in the Initialization script. The original values of the variables in the Initialization script can thus be considered as default or initial values, which can be modified during batch simulation via the external-context workspace. Specifically, the OML batch simulation script would create a external-context workspace with the desired content defining the new values of some of the variables and then run the simulation. The Activate model then uses these new variables as model parameters without the model having to be modified. This mechanism is very versatile because it allows significant changes, including structural changes, in the model but requires re-evaluation and recompilation for every simulation run creating an overhead in terms of performance. Such an overhead is often negligible unless the simulation time is very short.

12.2.2 Using SignalIn and SignalOut Blocks The SignalIn and SignalOut blocks can be used to exchange time signals between Activate and the OML environment calling the vssRunSimulation function. When the simulation is run interactively, the SignalIn and SignalOut signals use the base workspace, similar to FromBase and ToBase blocks. These latter blocks always work in the base environment. The other difference between the SignalIn and SignalOut blocks and the FromBase and ToBase blocks is that signals contain values as a function of time whereas FromBase and ToBase blocks exchange a single value when activated. There is in general no point activating these blocks more than once. Signals read and produced by the SignalIn and SignalOut blocks are OML structures called signal. A signal contains a field time, a vector of increasing time values. It contains one or more fields ch(1), ch(2), etc., called channel. Each channel contains a field type and a field data. The type is a string coding of the type of the signal (double, int8, etc.). The data is a matrix obtained from the row concatenation of the values of the signal at time instances associated with the time vector. In the following example a SignalOut block is used to return the final value of an Activate signal.

12.2 Data Exchange Between OML and Activate

345

Fig. 12.2 Model is modified to provide the difference between the range and the desired range

12.2.3 Example The problem of computing the range of a projectile fired from a cannon was considered in Section 8.1.1.1 where the problem considered was that of finding the optimal firing angle to maximize the range. Here a different problem is considered: finding the firing angle to attain a given range. This is done using batch simulation and in particular using the OML fsolve function. The model illustrated in Figure 12.2, is a modified version of the original model, providing the range (more specifically the range minus the desired range D) through a SignalOut block as an OML variable X. The following script uses the fsolve function where the residual to the function is obtained by running a simulation and reading X, the value produced by the SignalOut block. function dx = dist(th,ev,env) context = struct; context.th = th; vssRunSimulation(ev,context,env); X=getenvvalue(env,’X’); dx = X.ch{1}.data; end me = omlfilename(’fullpath’); p = fileparts(me); model = [p , ’/projectile_target.scm’]; simobj = bdeCreateSimulationObject(model); ev=vssCreateEvaluator(model,simobj); env=getnewenv; f=@(th) dist(th,ev,env); th_init = [0.1]; th_opt = fsolve(f, th_init); disp(th_opt) context = struct; context.th = th_opt; vssRunSimulation(ev,context,env,simobj);

346

12 Activate-OML Interactions and Batch Simulation

Fig. 12.3 The result of executing the script

For multiple simulations performed to find the value of the firing angle, no simulation object is created so the scope display is inhibited. Such a display is not useful in this case and slows down the process of simulation.1 Once the value of the firing angle is obtained, it is printed and a single simulation is performed with this angle, with a simulation object so that the scope can display the corresponding trajectory as illustrated in Figure 12.3.

12.3 Programmable Construction and Parameterization of Models A large set of OML APIs are provided to construct and edit models. Every property of the model, and its diagrams and blocks can be inquired and edited. Complete models can be constructed through these APIs providing an alternative to graphical model construction. Being able to construct and inspect Activate models by OML programs is a powerful feature allowing users to develop new custom functionalities. Consider for example a function to generate a specific type of documentation for Activate models (a generic report generator is already available in Activate). An OML code can be developed to go through the complete model, registering the required parameters and properties of diagrams and models, and generate a documentation. Similarly a program can be developed to search for specific block parameters and replace their values. It can also be used to modify graphical properties, or even replace blocks with other blocks (for example replacing scopes with blocks that save their input signals to a file). 1 For

such simple examples the process time would not be a factor.

12.3 Programmable Construction and Parameterization of Models

347

As seen previously, the OML APIs can also be used for running simulations and reading the simulation results. OML programs can thus be developed to run simulations for multiple scenarios (for example multiple set of parameters) to compare simulation results with reference values, thus implementing fully automatic Q/A testing procedures. The OML APIs can be used for many applications and the list of these APIs is long. See Activate documentations for details.

12.4 Linearization Creating an approximate linear model associated with the continuous-time dynamics of a Super Block inside a model is often needed in various applications such as control and signal processing. If the dynamics of the Super Block is time-invariant and is given by x˙ = f (x, u) y = h(x, u) and (ueq , xeq , yeq ) is an equilibrium point, i.e., 0 = f (xeq , ueq ) yeq = h(xeq , ueq ), then the linear time-invariant (LTI) system (A, B, C, D): ˙ = Aδx + Bδu δx δy = Cδx + Dδu is obtained by linearization where δx = x − xeq , δu = u − ueq and δy = y − yeq , and ∂f ∂f ∂h ∂h (xeq , ueq ), B = (xeq , ueq ), C = (xeq , ueq ), D = (xeq , ueq ). ∂x ∂u ∂x ∂u (12.1) ˙ and yeq + δy. For small values of δu and δx, x˙ and y are then approximated by δx Activate provides an API for obtaining this linear model. The model and the Super Block must be designated and the final simulation time must be provided. A=

348

12 Activate-OML Interactions and Batch Simulation

In general the final simulation time is set to zero and the model is parameterized such that the input, output and state of the Super Block to be linearized correspond to an equilibrium point. But in some cases the linearization needs to be done after simulation is run over a period of time, in particular so that the system can converge to an equilibrium point. The linearization API has the following syntax [A,B,C,D] = vssLinearizeSuperBlock(model,sblk,inps,outs,tf,ctx);

where model can either be an Activate model, for example the model currently open in Activate, which can be obtained as follows model = bdeGetCurrentModel;

or it can be a string designating a file (extension scm) where the model is saved. sblk is the full name of the Super Block to be linearized. inps and outs are vectors containing respectively input and output port numbers of the Super Block. In some cases the Super Block may contain inputs and outputs that are used for passing parameters or discrete-time signals and must be excluded when considering the continuous-time dynamics of the Super Block. tf is the final simulation time (often set to 0). Finally ctx is the external-context workspace. As seen previously, the external-context can be used to redefine variables defined in the model’s Initialization script. The external-context had been used earlier in particular for model optimization. It is important to note that the linearization must be performed at (or close to) an equilibrium point. The Super Block can be in an equilibrium point at initial time, in which case tf can be set to 0. If not, the model can be simulated up to a given finale time tf before linearization. This can be done so that the system reaches an equilibrium point. This latter approach cannot in general be used if the model is not locally asymptotically stable. In some cases, it is useful to adjust some model parameters in order for the Super Block to be linearized to be in an equilibrium state. Activate provides an API for that: [ctx,err]=vssEquilibriumPointSuperBlock(model,sblk,ctx,params);

params contains the list of variables in the ctx workspace that can be adjusted by the API. The returned workspace ctx contains the adjusted parameters and can be used directly for linearization. The returned value err provides the value of the state derivative at the returned equilibrium point. If successful, this returned value must be zero or very close to it. The vssLinearizeSuperBlock and vssEquilibriumPointSuperBlock APIs can also be used within the Initialization script of the model. This is a powerful feature, which can be used for example to completely integrate the controller design process within the simulation model, as will be illustrated through an example in the next section.

12.4 Linearization

349

12.4.1 Example: Inverted Pendulum on a Cart Most control design methodologies are based on using an approximate linear model of the system to be controlled. This linear model is obtained by linearizing the system around an equilibrium point. Linear control theory then provides various methods for designing controllers for this linear model, which is then applied to the original nonlinear model. As long as the system state remains close enough to the equilibrium state, the linear controller stabilizes the system. However, numerical simulation is required to fully assess the stability margin and performance of the controller. In this example the stabilization of an inverted pendulum system is considered. The stabilizing controller is designed as an observer-based controller. Observer-based controller design is based on the principle of separation. In particular for the LTI system (6.2a)–(6.2b), a stabilizing state feedback matrix K is computed (i.e., a matrix K such that the eigenvalues of A + BK have strictly negative real parts) and applied not to the state x (the value of which is not known) but to xˆ , an estimate of x produced by an observer, for example the Luenberger observer (6.3). The control law u = K xˆ can then be shown to stabilize the system.   The observer can be represented by the LTI system (A + LC, B + LD −L , I , 0):     u x˙ˆ = (A + LC)ˆx + B + LD −L y xˆ = xˆ This is a slight generalization of (6.3); the D matrix of the original system is not considered to be zero. The parameters of this observer-based controller are then the matrices K and L, which must be chosen such that the eigenvalues of A + BK and A + LC have strictly negative real parts. They can be computed for example using pole placement and implemented using the OML place function. The inverted pendulum system was presented in Section 9.7; the equations were given in (9.27)–(9.28). Here a variation of this model is considered. In the previous model the mass of the pendulum was considered to be concentrated at the end of the pendulum. Here the pendulum is supposed to have constant density along its length so that its rotational inertia around its center of mass is given by J = ml 2 /12 where l is the length of the pendulum and m its mass. The new equations of motion are the following (M + m)¨z + ml θ¨ cos(θ )/2 − ml θ˙ 2 sin(θ )/2 = u(t) (J + ml 2 /4)θ¨ + ml¨z cos(θ )/2 − mgl sin(θ )/2 = 0. These equations can be expressed as follows

350

12 Activate-OML Interactions and Batch Simulation

Fig. 12.4 Activate model of the inverted pendulum on a cart system with an observer-based controller. Activate supports the use of non-ASCII characters. Block names, annotations, documentation, etc., can be expressed in Chinese, Hindi, Japanese, ..., and in this case Persian characters



0 M +m ⎢1 0 ⎢ ⎣0 ml cos(x3 )/2 0 0

⎤ 0 ml cos(x3 )/2 ⎥d 0 0 ⎥ 2 0 J + ml /4 ⎦ dt 1 0

⎡ ⎤ ⎡ 2 ⎤ x1 mlx4 sin(x3 )/2 + u ⎢x2 ⎥ ⎢ ⎥ x2 ⎢ ⎥=⎢ ⎥ ⎣x3 ⎦ ⎣ mgl sin(x3 )/2 ⎦ , x4 x4

where x = (x1 , x2 , x3 , x4 ) = (z, z˙ , θ, θ˙ ), which can be re-expressed as x˙ = f (x, u) = F −1 v,

(12.2)

where ⎡

0 M +m ⎢1 0 F =⎢ ⎣0 ml cos(x3 )/2 0 0

⎤ ⎤ ⎡ 2 mlx4 sin(x3 )/2 + u 0 ml cos(x3 )/2 ⎥ ⎥ ⎢ 0 0 x2 ⎥ ⎥, v = ⎢ ⎣ mgl sin(x3 )/2 ⎦ . 0 J + ml 2 /4 ⎦ 1 0 x4

Note that F is invertible for all values of x3 . The system can be linearized around the equilibrium point x = 0, u = 0, using (12.1) yielding the LTI system ⎡

0 ⎢0 x˙ = ⎢ ⎣0 0

⎤ ⎤ ⎡ 0 1 0 0 ⎥ ⎢ 2 0 −m2 gl 2 /(4Δ) 0⎥ ⎥ x + ⎢ ml /(3Δ) ⎥ u, ⎦ ⎦ ⎣ 0 0 1 0 0 (M + m)mgl/(2Δ) 0 −ml/(2Δ)

(12.3)

where Δ = (M + m)ml 2 /3 − m2 l 2 /4. The observer-based controller for the linearized inverted pendulum system applied to the original nonlinear system is modeled in Activate as illustrated in Figure 12.4. The nonlinear model of the inverted pendulum system is shown in Figure 12.5 and

12.4 Linearization

351

Fig. 12.5 The nonlinear model of the pendulum on a cart

Fig. 12.6 The observer for the nonlinear model of the pendulum on a cart is implemented using a state-space LTI system. The parameters of this system are shown in Figure 12.7

Fig. 12.7 Block parameters of the obs block used to implement the observer

the observer in Figure 12.6. Noise is added to the measurements z and θ used by the controller. The controller parameters are computed in the Initialization script of the model. See Figure 12.8. The simulation (Figure 12.9) shows that the controller stabilizes the system for the given initial condition. For large initial angles (pendulum far from vertical position),

352

12 Activate-OML Interactions and Batch Simulation

Fig. 12.8 The Initialization script of Model in Figure 12.4

Fig. 12.9 Simulation result shows stabilization of the pendulum on the cart system when analytical linearization is used

the controller will fail to stabilize the system. System simulation can be used to evaluate the domain of stability of the system. Automatic linearization The linearized model cannot always be computed analytically. In this example the system equations were available and were not too complex. But even then the computation of the linearized model is not simple. For large systems, computer algebra systems, such as Maple, can be used, but in most cases the system equations are not

12.4 Linearization

353

Fig. 12.10 The modified Initialization script for Model in Figure 12.4

readily available. The Activate linearization functionality introduced earlier provides an alternative to symbolic computation for the construction of linearized models. The linearization of a Super Block of a model can even be done inside the Initialization script of the model. So the model used to simulate the nonlinear system can for example perform all the steps for the construction of the observer-based controller, and uses the resulting controller in the simulation. This is illustrated on the inverted pendulum model where the linear model (12.3) is not used; instead the linear model is obtained by using the vssLinearizeSuperBlock function. Consider again the model in Figure 12.4 where the Initialization script has been modified as in Figure 12.10. In this case the linearized model is computed by the vssLinearizeSuperBlock function. Note that in this case the model is compiled twice: once for simulation and once for linearization. The variable vssIsInLinearization indicates whether the Initialization script is being evaluated for simulation or linearization. When the system is simulated, at the start of the model compilation the Initialization script is evaluated. In this case vssIsInLinearization has false value. So the vssLinearizeSuperBlock function is reached. This function runs a new simulation to linearize the system. This results in a new evaluation of the Initialization script. But this time the vssIsInLinearization has true value. The values of obs, K and x0 are provided in the ctx workspace. They are used only in the linearization mode and are chosen such that the Super Block to linearize is at an equilibrium point. In this case, the equilibrium point is known: the initial state of the Super Block (pendulum) x0 and its input u are zero. That is why x0 is set to zero and the observer and the controller gain matrix K are defined such that u = 0 at the initial time.

354

12 Activate-OML Interactions and Batch Simulation

Fig. 12.11 Simulation result when automatic linearization is used, to be compared with Figure 12.9 Fig. 12.12 Inverted pendulum on a cart on an inclined surface

The function vssIsInLinearization computes and returns the (A, B, C, D) matrices of the linearized model back in the evaluation of the original Initialization script. They are used to compute the controller parameters obs and K, and the system is simulated. The simulation result, illustrated in Figure 12.11, is virtually identical to the simulation result obtained using the controller obtained by analytical linearization.

12.4 Linearization

355

12.4.2 Example: Inverted Pendulum on a Cart on an Inclined Surface When the inverted pendulum on the cart is placed on an inclined surface, the control problem becomes more challenging. If the surface angle is denoted by φ, see Figure 12.12, then the equations of motion can be expressed as follows (M + m)¨z + ml θ¨ cos(θ − φ)/2 − ml θ˙ 2 sin(θ − φ)/2 = u(t) − (M + m)g sin(φ) (J + ml 2 /4)θ¨ + ml¨z cos(θ − φ)/2 − mgl sin(θ )/2 = 0. The Activate model in Figure 12.4 used a generic construction of the observer-based control strategy so the new model uses the same overall construction. Only the plant is modified. See Figure 12.13. The surface angle φ is included as an additional input and the plant model is expressed in Modelica thanks to a MoCustomBlock. This is done to show that the linearization methods work also if the Super Block contains Modelica components or blocks. See Figure 12.14; the Modelica code used in the MoCustomBlock is given below. model pend //parameters parameter Real M = 10; parameter Real m = 1; parameter Real l = 0.5; parameter Real th0 = 0; parameter Real z0 = 0; //input variables Real u; Real ph; //output variables Real z(start=z0), th(start=th0); Real zd(start=0), thd(start=0); Real g=9.81; Real J=m*lˆ2/12; equation der(th)=thd; der(z)=zd; (M+m)*der(zd)+m*l*der(thd)*cos(th-ph)/2m*l*thd*thd*sin(th-ph)/2 = u-(M+m)*g*sin(ph); (J+m*l*l/4)*der(thd)+m*l*der(zd)*cos(th-ph)/2m*g*l*sin(th)/2 = 0; end pend;

There are different ways to control this system. Three different methods are presented in the following sections. In each case, the implementation is fully integrated within the simulation model and requires very little modification compared to the model used in the non inclined case considered previously.

356

12 Activate-OML Interactions and Batch Simulation

Fig. 12.13 Activate model of the inverted pendulum on a cart on an inclined surface controlled by an observer-based controller

Fig. 12.14 Inside the pend Super Block

12.4.3 Control Ignoring the Inclination The main difference between this control problem and the original problem (no surface inclination) is that the zero input, state and output do not constitute an equilibrium point if φ is not zero. Indeed in this case if no force is applied to the cart, it will not stay in place; it will slide down the surface. One solution is to ignore the inclination and find a controller as before by assuming φ = 0 and apply it to the actual system having a non-zero φ. One would expect that for small values of φ, the controller stability can still be maintained. This strategy is implemented by the following Initialization script: M=10; m=1; l=0.5; J=m*lˆ2/12; g=9.81; nx=4;nu=1;ny=2; ph=0.01; th0=pi/15; z0=-2; if ˜vssIsInLinearization ctx=struct; ctx.K=zeros(1,nx); ctx.obs=ss([],zeros(0,nu+ny),zeros(nx,0),zeros(nx,nu+ny)); ctx.th0=0;ctx.z0=0;ctx.ph=0; [A,B,C,D]=vssLinearizeSuperBlock(bdeGetCurrentModel,... ’pend’,[1],[1],0,ctx); L=-place(A’,C’,-3*ones(nx,1))’; obs=ss(A+L*C,[B+L*D,-L],eye(nx),zeros(nx,nu+ny)); K=-place(A,B,-3*ones(nx,1)); end

Note that the linearization is done with respect to the first input of the pend Super Block. The second input is ignored since it is used to pass the constant value φ. This

12.4 Linearization

357

Fig. 12.15 The system is stabilized but the cart can end-up far from the origin

is done by specifying the inps argument of the vssLinearizeSuperBlock function to be 1. The simulation result, given in Figure 12.15 shows that the system is stabilized but the cart does not converge to the origin. It is stabilized at some distance from the origin. This in general is not acceptable.

12.4.4 Linearization Around the Equilibrium Point If the angle φ is known, the equilibrium point can be computed and the linearization can be done around this point. The state and the output of the system at the equilibrium point are zero (the cart should be at the origin with the pendulum at the vertical position pointing up and not moving). The value of the input u, u0 , at equilibrium point can be computed analytically2 but here the function vssEquilibriumPointSuperBlock is used instead. The model is modified as in Figure 12.16 with the following Initialization script:

2 Clearly in this case u 0

task.

= (M + m)g sin(φ) but finding the equilibrium point is not always an easy

358

12 Activate-OML Interactions and Batch Simulation

Fig. 12.16 Activate model of the inverted pendulum on a cart on an inclined surface controlled by an observer-based controller obtained by linearizing the model around an equilibrium point

M=10; m=1; l=0.5; J=m*lˆ2/12; g=9.81; nx=4;nu=1;ny=2; ph=0.05; th0=pi/15; z0=-0.5; if ˜vssIsInLinearization ctx=struct; ctx.K=zeros(1,nx); ctx.obs=ss([],zeros(0,nu+ny),zeros(nx,0),zeros(nx,nu+ny)); ctx.th0=0;ctx.z0=0;ctx.u0=0; model=bdeGetCurrentModel; ctx=vssEquilibriumPointSuperBlock(model,’pend’,ctx,{’u0’}); [A,B,C,D]=vssLinearizeSuperBlock(model,... ’pend’,[1],[1],0,ctx); L=-place(A’,C’,-3*ones(nx,1))’; obs=ss(A+L*C,[B+L*D,-L],eye(nx),zeros(nx,nu+ny)); K=-place(A,B,-3*ones(nx,1)); u0=ctx.u0; end

Note that the equilibrium value u0 is introduced as a bias on the input signal u. The simulation result is given in Figure 12.17. The cart converges to the origin and the control u to the value u0 .

12.4.5 Control Using an Integrator in the Loop In practice, the angle φ is usually unknown and the controller must be designed in such a way as to reject a constant φ. This can be done by introducing an integrator in the loop, in particular on the output z of the system. The integration action in the feedback loop introduces infinite static gain resulting in a complete rejection of the constant value φ. The model is again very similar to the one in Figure 12.13 but the Super Block pend is modified. An output is added to display the result of the simulation as can be seen in Figure 12.18 and the content is modified to include the addition of the

12.4 Linearization

359

Fig. 12.17 The system is stabilized at the origin Fig. 12.18 The model used for control using integral action

Fig. 12.19 Inside the pend Super Block

Integrator block as seen in Figure 12.19. There are now two outputs, one used for control (y) and one to display the location and the angle of the cart, respectively denoted z and θ , as before. The following Initialization script is used in this model:

360

12 Activate-OML Interactions and Batch Simulation

Fig. 12.20 The system is stabilized at the origin thanks to the integrator action in the feedback loop

M=10; m=1; l=0.5; J=m*lˆ2/12; g=9.81; nx=4;nu=1;ny=2; ph=0.05; th0=pi/15; z0=-0.5; if ˜vssIsInLinearization ctx=struct; ctx.K=zeros(1,nx); ctx.obs=ss([],zeros(0,nu+ny),zeros(nx,0),zeros(nx,nu+ny)); ctx.th0=0;ctx.z0=0;ctx.u0=0; model=bdeGetCurrentModel; ctx=vssEquilibriumPointSuperBlock(model,’pend’,ctx,{’u0’}); [A,B,C,D]=vssLinearizeSuperBlock(model,... ’pend’,[1],[1],0,ctx); L=-place(A’,C’,-3*ones(nx,1))’; obs=ss(A+L*C,[B+L*D,-L],eye(nx),zeros(nx,nu+ny)); K=-place(A,B,-3*ones(nx,1)); u0=ctx.u0; end

Note that this script is virtually identical to the script used in the model used in Section 12.4.3 except for the size of the state, nx, which is now 5 and not 4. This is due to the addition of the Integrator block. The simulation result is given in Figure 12.20. The cart converges to the origin and the control u to the value u0 again. This controller works for small enough values of φ.

Chapter 13

Construction of New Blocks

For most applications, blocks provided already by Activate are enough to construct models. Complex expressions can be encapsulated in Expression blocks presented in Chapter 7 and if it is desired to expose an advanced functionality through a single block, there is always the possibility of using a masked Super Block where the functionality is realized by a diagram. So there is little need to construct truly new Activate blocks. Constructing such new blocks is usually done mainly by library developers. Developing a programmable Super Block or a new basic block is not always an easy task but a block builder (BlockBuilder) tool is provided in Activate that facilitates such developments. The BlockBuilder GUI contains multiple tabs that can be used to define various properties of the new block. This graphical interactive tool will be briefly presented in Section 13.5. Not all aspects of constructing a new block are considered here. First block construction is considered in the case of programmable Super Blocks and basic blocks realized as custom blocks. This is a limitation for many library blocks that should work for different data types, but it is sufficient for most end-user applications. The construction of basic blocks will be briefly discussed later in Section 13.5.

13.1 Programmable Super Block A programmable Super Block is seen as a basic block on the block diagram editor level but it defines a diagram containing blocks and links. This is done programmatically in OML in particular by using APIs available for the instantiation of blocks and the construction of links. A programmable Super Block can be constructed using the BlockBuilder tool. The code defining the diagram inside constitute the body of the setparams function of the block. The setparams function body can be edited inside the SetParameters entry of the Atom tab of the BlockBuilder GUI. © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_13

361

362

13 Construction of New Blocks

Fig. 13.1 A possible implementation of a 3-delay block

Inside the setparams function, the variables _diagram, _label and all block parameters are available. _diagram is a structure defining the diagram in which the new block is being defined and _label is the name of this new block. The role of code is to define a _block variable (the returned value of the setparams function). For basic blocks, the variable _block is instantiated as follows _block=vssAddNewObject(’Block’,_diagram);

whereas for a programmable Super Block, it is done as follows _block = vssAddNewObject(’SubSystem’,_diagram);

The properties of _block are then defined through APIs. For basic blocks, these APIs include functions to set the sizes of the inputs, outputs, the initial state, the computational function and its parameters, etc. Note that the block parameters are known at this time. The codes associated with the existing library blocks can be examined by opening the BlockBuilder tool on these blocks, once placed inside a model. Basic blocks require the definition of one or more computational functions and may also require the definition of two other OML functions SetInputsOuputs and ResetParameters, in addition to setparams. The use of custom blocks is an alternative way to define basic blocks. It will be presented later in Section 13.2. For a programmable Super Block, the variable _block contains a new diagram, which is programmatically constructed in setparams and placed inside _block using the vssSet_SubSystem API. To illustrate the construction of programmable Super Blocks, an example is presented here. The block being defined is an N -delay obtained by the cascade of N DiscreteDelay blocks (1/z). N being a parameter of the block, the diagram inside the Super Block has different topologies depending on the value of parameter N . For example for N = 3, the diagram may be presented as in Figure 13.1. The code to generate such a diagram for an arbitrary N is given below; note that no graphical information needs to be provided since the diagram is never displayed. diagr= vssCreateObject(’Diagram’); params=struct();params.init_cond=0; params.typ=’double’;params.externalActivation=1;

13.1 Programmable Super Block

363

_vss._palettes._system.Dynamical.DiscreteDelay.setparams(diagr,... ’DiscreteDelay1’,params); params=struct();params.portNumber=1;params.outsize=[-1;-2]; params.outtyp=’inherit’;params.dept=0; _vss._palettes._system.Ports.Input.setparams(diagr,’Input’,... params); params=struct();params.portNumber=1; _vss._palettes._system.Ports.EventInput.setparams(diagr,... ’EventInput’,params); params=struct();params.portNumber=1; params.insize=[-1;-2];params.intyp=’inherit’; _vss._palettes._system.Ports.Output.setparams(diagr,’Output’,... params); for i = 2:N params=struct();params.init_cond=0;params.typ=’double’; params.externalActivation=0; _vss._palettes._system.Dynamical.DiscreteDelay.setparams(diagr,... [’DiscreteDelay’,num2str(i)],params); vssAdd_Link(diagr,[’DiscreteDelay’num2str(i-1)],... [’DiscreteDelay’,num2str(i)],1,1,0,1,1); end vssAdd_Link(diagr,’Input’,’DiscreteDelay1’,1,1,0,1,1); vssAdd_Link(diagr,’EventInput’,’DiscreteDelay1’,1,1,0,1,-1); vssAdd_Link(diagr,[’DiscreteDelay’,num2str(N)],’Output’,1,1,0,1,1); _block = vssAddNewObject(’SubSystem’,_diagram); vssSet_SubSystem(_block,1,1,1,0,0,_label,diagr);

In the above example, a programmable Super Block allowed the adjustment of the inside diagram topology to the block parameter of the block, something that is not possible using masked Super Blocks. Another situation where masked Super Blocks cannot be used and programmable Super Blocks are needed is when the number of input and output ports of the block is to be made dependent on the block parameter. For example to make a block optionally externally activated, the block should be made to have zero or one input activation port. Note that in such cases, the block’s activation port should be defined as having variableport type. The ports are defined in the Ports tab of the BlockBuilder GUI.

13.2 Using Custom Blocks to Construct Basic Blocks The development of single-AU blocks is made simple thanks to CCustomBlock and OmlCustomBlock blocks in Activate. These blocks provide a generic interface at the editor level but allow the complete definition of the block simulation behavior respectively in C and OML languages. Even for developing a new block for a new block library, the CCustomBlock and OmlCustomBlock blocks provide a convenient way of testing simulation codes before proceeding with the rest of the construction.

364

13 Construction of New Blocks input activations i2

state derivative

continuous-time state

inputs

i1

discrete-time states outputs mode vector

zero-crossing surfaces

tevo output activations

Fig. 13.2 Atomic Unit (AU) components

Custom blocks can be placed inside masked Super Blocks to provide them with custom block parameter GUIs, hiding their generic interfaces.

13.2.1 Atomic Unit An AU can be connected through input and output ports, and, activation input and output ports. Input and output ports are used to communicate signals, which in general can be matrices of different types: double, complex double, int8, uint8, int16, uint16, int32, uint32 and Boolean. Activation ports transmit activation signals. An AU can be a complex entity. It can have multiple inputs and outputs, a continuous-time state, a list of discrete-time states, zero-crossing surfaces, modes, etc., as shown in Figure 13.2. Not all of these features are present in every AU and depending on their presence, different computational functions must be defined for the AU.

13.2.1.1

Computational Functions

The computational functions associated with a block are implemented, at least for simulation purposes, as a single C or OML function. The choice of the computation task is designated by a flag. This flag is the way the simulator tells the block what operation needs to be performed. The computational function receives thus two arguments: a structure containing block information and a flag.

13.2 Using Custom Blocks to Construct Basic Blocks

365

The flag indicates the job that the computational function must perform. This job usually consists in updating some of the fields of the block structure. The main jobs of the computational functions are the followings: • Initialization: In this case the continuous and discrete states can be initialized, or more specifically, reinitialized (if necessary) because they are generally already initialized during evaluation. Nothing is done for this flag in most blocks; the flag is only used by the blocks that read and write data from files, for opening the file, or by Scope blocks for initializing the graphics window. It is also used by blocks, which require dynamically allocated memory; the allocation is done under this flag. Each block is called once and only once at the beginning of the simulation with this flag. • Reinitialization: Right after initialization, the computational function may be called a number of times to modify its internal states if needed. At this stage the inputs to the block are available but may change from one call to the next. The objective of this stage is to impose constraints at the initial time. If successful, these calls lead to the convergence of the states and inputs. • OutputUpdate: With this flag, the simulator is requesting the outputs of the block. The computational function should use the needed information within the block’s structure (inputs, states, nevprt, which codes the way by which the block is activated, etc.) to compute the outputs of the block. The function is called with this flag even if the block has no outputs. Note that if the block contains different modes, then the way the output is computed depends on the simulation phase. This is explained later in Section 13.2.1.2. • StateUpdate: When the simulator calls the function with this flag, a request is made to update the internal state(s) of the block. The activation resulting in this request is characterized by nevprt. Activations from the outside (direct or by inheritance) yields positive nevprt values, indicating in particular the ports through which the block is activated. The activation may also be due to an internal zero-crossing event, in which case nevprt is equal to −1. When nevprt= −1, indicating that the activation is due to an internal zero-crossing event, then a vector jroot in the structure of the block specifies which surfaces have been crossed and in which direction. In particular, if the ith entry of jroot is 0, then the ith surface (counting from zero) has not crossed zero. If it is +1 (respectively −1), then it has crossed zero with a positive (respectively negative) slope. Note that with this flag, the computational function can update both the continuous and the discrete-time states of the block. • Derivatives: This flag is used following the numerical solvers request for the evaluation of the time derivative x˙ of the block’s continuous-time state x. The computational function must compute x. ˙ If the block has an implicit computational function, instead the residue f (x, x) ˙ is returned. Calls with this flag are done on a periodic basis when fixed step numerical solvers are used but not when variable step solvers are used.

366

13 Construction of New Blocks

• ZeroCrossings: Most numerical solvers assume model smoothness. This means that the behavior of blocks, which contain or affect continuous-time states of the system must be smooth, or at least piece-wise smooth. In this latter case, the points of non-smoothness must be specified in such a way that the solver can, if needed, issue a cold restart when going through such points. See Section 13.2.1.2. Note that the block is activated following a zero-crossing so that it can change its states or schedule an output event. Thus Zero-Crossings are not only used to handle modes. In fact a block may have more zero-crossings than modes. For example, the ZeroCross block, which generates an event when its input crosses zero, has one zero-crossing surface but no mode. • EventScheduling: To update the table of scheduled events, the simulator calls the computational function with this flag. This happens if the block has output activation ports. The computational function can in this case program events on one or more of its activation ports. Only one event can be programmed on each port. If an event is already programmed on a port, it can be re-programmed, i.e., its firing time can be modified. The computational function specifies the firing time of events by returning a positive delay time for the associated port. Programmed events can also be de-programmed. This can be done by returning a negative delay time. An event can be programmed with zero delay but that does not imply that the output event is synchronous with the event activating the block. The output event is simultaneous, however, it comes “after”. Indeed in Activate variables may take multiple values for a given time instant. This behavior can be treated rigorously using the notion of dense time but it is not pursued here. • Terminate: At the end of the simulation interval, the simulator calls each block’s computational function with this flag, once. This is useful, for example, for closing files that have been opened by the block at the beginning or during the simulation, to flush buffered data, etc. Table 13.1 summarizes the role of each flag. Note that in this table time-invariant quantities such as the parameters are not specifically stated as input arguments. The function clearly has access to these parameters and can use them for its computations. In this table, t designates the simulation time, nevprt, the activation code presented in Section 10.2.1, x, the continuous-time state, z, all the discrete-time states of the block, u_i, the values of the inputs to the block and y_i, the values of its outputs. Note that the input values are not necessarily up-to-date for all flags if they do not have the feedthrough property. The state derivative is available as an input argument only in the DAE case. In case the block has zero-crossing surfaces, mode designates the block mode vector and jroot is a vector indicating the direction in which zero-crossings have occurred. A value of zero in this vector implies the absence of crossing. The behavior of a block often depends on the way the block is activated (presented in Chapter 10) and the simulation phase, in particular whether the call is made in try phase or the modes are fixed. These are discussed in the following section.

13.2 Using Custom Blocks to Construct Basic Blocks

367

Table 13.1 This table summarizes the jobs that the computational function must perform for different flags flag inputs returned description Derivatives

OutputUpdate StateUpdate State update EventScheduling Initialization Terminate Reinitialization ZeroCrossings ZeroCrossings

13.2.1.2

xd (res in DAE case) compute the derivative of continuous-time state or the residual in case of DAE t, nevprt, x, z, y_i compute the outputs of u_i, mode, the block t, nevprt>0, x, z, x, z update states due to u_i external activation t, nevprt=-1, x, z, x, z update states due to u_i, jroot internal zero-crossing t, x, z, u_i, jroot evout program activation output delay times t, x, z x, z, y_i initialize states and other initializations x, z, u_i x, z, y_i final call to block for ending the simulation x, z, u_i x, z, y_i re-initialization of states t, if mode fixed, g, mode compute zero-crossing nevprt, x, z, u_i surfaces and set modes t, if mode not fixed, g compute zero-crossing nevprt, x, z, u_i surfaces t, nevprt, x, z, u_i, mode, (xd in DAE case)

Simulation Phases

The model to be simulated is in general hybrid. This means that the dynamics includes both discrete-time and continuous-time dynamics. The simulator needs to deal with both of these simulation phases and calls the computational functions of the blocks accordingly. When a variable-step numerical solver is used, then the treatment of the continuous-time dynamics becomes more complex. A numerical solver adapts its time-steps during simulation taking as large a step as possible while satisfying tolerated error bounds. This is done by implementing an error estimation mechanism. When the solver takes a step and the error mechanism indicates that the error bounds are violated, the solver invalidates the step and starts over with a smaller step. So the calls to the computational functions of the blocks are made in this case knowing that the call may be invalidated later. The call is considered then to be a try. This information may be important for certain blocks, and is made available to the computational function through the isinTryPhase API. On discrete events and on mesh-points (definitive solver time steps) the block computational functions are no longer called in try phase. The functions are called in try phase also when the solver is determining the instant of the zero-crossings.

368

13 Construction of New Blocks

Another difficulty with the use of variable step solvers is the treatment of nonsmooth dynamics. The computational functions of all the blocks with continuoustime dynamics with non-smooth dynamics must handle properly the use of variablestep numerical solvers. The main difficulty with the usage of variable-step numerical solvers in this case is that such solvers expect the system they are solving to be smooth. If the system contains a discontinuity or even if it is not differentiable enough, then the solver may fail or become very inefficient. The reason is that the error control mechanism used to adjust the solver step makes smoothness assumption about the dynamics of the system. To solve non-smooth systems with variable step solvers, the solver must be stopped and restarted at the points of non-smoothness. This process is called a cold restart and has a cost. The Activate simulator must determine and implement a cold restart only when it is required. Restarts are usually quicker with one step methods like Runge-Kutta methods than with multistep methods like BDF or Adams. Not all blocks have smooth input-output relations. For example, the output of the Sign block is not a smooth function of its input; the function sign is not even continuous. Other functions exhibiting non-smooth behavior include abs, max, min, saturation functions, etc. These blocks must use a specific mechanism to make sure the numerical solver does not encounter their non-smooth behavior. This is done through the usage of modes and zero-crossings. Consider the abs function for example. The computational function of this block, instead of exposing the function abs to the solver, exposes the smooth functions y = u or y = −u, depending on the mode. In this case the mode indicates whether the input is positive or negative, so it can take two values. As long as the mode is “positive”, the computational function realizes the function y = u, otherwise it realizes y = −u. For this method to work, the mode must be updated when the input changes sign. This is done through the use of a zero-crossing surface. In this case the surface is u = 0. So the Abs block contains a mode and a zero-crossing, which are used when the block is part of the of continuous-time dynamics of the system and a variablestep numerical solver is used. In this case, the solver detects the time instant of zero crossing and restarts the solver from that time instant. The computational functions of blocks with modes and zero-crossings are called in different ways. In particular in some cases the modes are considered fixed and others, not fixed and it is up to the computational function to fix it. A specific API, areModesFixed is available to the computational function, which can be used to determine its behavior. This information is only relevant for simulation flags OutputUpdate and ZeroCrossings. In the case of OutputUpdate, when modes are fixed the output is computed based on the mode. So in the case of the Abs block, the function returns u or -u. When the mode is not fixed, it returns abs(u). Note that the output produced by this block may be negative (in particular when the mode is fixed). Similarly in the case of ZeroCrossings, the value of the surface is computed based on the mode or not depending whether the modes are fixed or not. But in addition in this case when the modes are not fixed, the function computes the values of the

13.2 Using Custom Blocks to Construct Basic Blocks

369

modes and sets them in the structure of the block. In the Abs block example, the zero-crossing surface is given by the input u and does not depend on the block mode. But if the modes are not fixed, the block mode is set based on the sign of u.1 Thus the continuous-time simulation phases include two (sub) phases: fixed modes and free modes, and the computational functions of some blocks should use this information, available through the API areModesFixed, when called with flags OutputUpdate and ZeroCrossings. In general the simulation is in try phase when the modes are fixed except on mesh-points. The computational function receives the flag and the block structure as argument. The block structure contains block properties that can be accessed in the computational function via a number of APIs. The list of C language APIs can be found in Appendix A. The same APIs are also available in OML for when the computational function of the block is expressed in OML. Some of these APIs, both OML and C, are illustrated through examples in the next section. The complete list of APIs can be found in the Activate documentation.

13.2.2 Examples 13.2.2.1

Human in the Loop Simulation

One of the many applications of simulations is training and evaluating human operators. In these applications, the human interaction with the simulator can be highly interactive for example in flight simulators or in event based such as decision making when an unexpected situation is detected by a monitoring system. The example considered here is of the latter type where the simulated system represents a patient (a complex model of human physiology or prerecorded scenarios). An OmlCustomBlock is used to monitor some of the patients physiological parameters and when a possible anomaly is detected, request for human intervention. A toy example is considered here. The patient is supposed to be receiving a drug by continuous intravenous infusion. The dosage of this drug should be adjusted under certain conditions, in particular depending on the physiological parameters, which are automatically monitored on a regular basis, for example every minute (for the fastest measurement; not all parameters are necessarily updated every minute). Here these parameters, referred to as signals hereafter, are the patient’s heart rate, systolic blood pressure and temperature. If any of these signals go over preset prescribed thresholds, a warning is generated. The human operator is provided with the values of these signals and is expected to provide a new value of the drug dosage used in the intravenous infusion. The values of the measured physiological signals and the actions of the human operator are written in a log file for record keeping and/or assessment. 1 The

Abs block in Activate may use more than a single mode and zero-crossing since this block accepts matrices as inputs.

370

13 Construction of New Blocks

Fig. 13.3 The first tab of the OmlCustomBlock parameter GUI. The block inputs and outputs are specified

The block to be constructed then has three inputs (patient’s heart rate, systolic blood pressure and temperature) and one output, the drug dosage. The block parameters are the threshold values corresponding to the input signals. The dosage is stored in a state of the block. Another state is used to keep the time of the previous change of dosage so that it can be used to turn off warnings over a period of time (the expected time that the change of dosage takes effect). Finally a state is used to keep the file ID of the log file used to record the history. The first step to construct this block is to place an OmlCustomBlock in a diagram. Then the block parameters are set. The parameter GUI of this block has multiple tabs to be used for properly defining the block’s parameters and behavior. The first tab is used to define the block’s inputs and outputs. In this case the block has three regular inputs and one regular output. The tab, after filling the information, can be seen in Figure 13.3. The inputs and the output are given proper names2 and their sizes and data types are specified. In this case they are simple scalars. The block’s states are defined in the second tab, as shown in Figure 13.4. Block parameters are similarly defined in the third tab (Figure 13.5). The block’s behavior can now be defined by an OML function. This function uses the provided APIs to read the block’s inputs, write the output, update the states, etc. To simplify the development of this function, a ‘generate skeleton’ functionality is provided in the fourth tab; see Figure 13.6. This functionality creates a skeleton OML function adapted to the information provided in other tabs. In this case, the following OML function is generated: 2 The

signal names must be valid OML variable names.

13.2 Using Custom Blocks to Construct Basic Blocks

371

Fig. 13.4 The second tab of the OmlCustomBlock parameter GUI used for defining the block’s initial states

Fig. 13.5 The third tab of the OmlCustomBlock parameter GUI. The block parameters are defined here

372

13 Construction of New Blocks

Fig. 13.6 The fourth tab of the OmlCustomBlock parameter GUI. The OML simulation function is defined here

function OmlBlockFunction(block,flag) heartrate=vssGetInputData(block,1); spressure=vssGetInputData(block,2); temperature=vssGetInputData(block,3); nevprt=vssGetEventCode(block); dosage=vssGetOzData(block,1); prevchangetime=vssGetOzData(block,2); fileID=vssGetOzData(block,3); maxrate=vssGetOparData(block,1); maxpressure=vssGetOparData(block,2); maxtemperature=vssGetOparData(block,3); waitinterval=vssGetOparData(block,4); if flag == vssBlockInitializeFlag elseif flag == vssBlockReinitializeFlag elseif flag == vssBlockTerminateFlag elseif flag == vssBlockOutputUpdateFlag %%vssSetOutputData(block,1,admindose,vssGetOutputDataType(block,1)); elseif flag == vssBlockStateUpdateFlag %%vssSetOzData(block,1,dosage,vssGetOutputDataType(block,1)); %%vssSetOzData(block,2,prevchangetime,vssGetOutputDataType(block,2)); %%vssSetOzData(block,3,fileID,vssGetOutputDataType(block,3)); end end

13.2 Using Custom Blocks to Construct Basic Blocks

373

Note that the generated skeleton is fully adapted to the block information provided in other tabs. Most of the APIs needed are already included in the function considerably simplifying the task of implementing the block’s behavior. The skeleton function can be edited using the provided text editor and saved in the model. The desired behavior is implemented by testing the input signals against their thresholds, provided enough time has elapsed since the last dosage adjustment, and prompting the user if any of the signals exceeds its threshold. This is done using the OML function input presented in Section 2.3.2. When prompted, the user can type in a new value of dosage followed by a carriage return, or just a carriage return to maintain the previous dosage. The edited function is as follows: function OmlBlockFunction(block,flag) heartrate=vssGetInputData(block,1); spressure=vssGetInputData(block,2); temperature=vssGetInputData(block,3); nevprt=vssGetEventCode(block); dosage=vssGetOzData(block,1); prevchangetime=vssGetOzData(block,2); fileID=vssGetOzData(block,3); maxrate=vssGetOparData(block,1); maxpressure=vssGetOparData(block,2); maxtemperature=vssGetOparData(block,3); waitinterval=vssGetOparData(block,4); if flag == vssBlockInitializeFlag [fileID,msg]=fopen(’logfile.txt’,’w’); if fileIDwaitinterval if heartrate>maxrate || spressure>maxpressure... || temperature>maxtemperature txt=[’Time = ’,num2str(t),... ’. Last adjustment time = ’,num2str(prevchangetime),... char(10),’Heart rate = ’,num2str(heartrate),... ’, Blood Pressure = ’,num2str(maxpressure),... ’, Temperature = ’,num2str(temperature),char(10),... ’Current dosage = ’,num2str(dosage),’. Enter new dosage: ’]; y=input(txt); if isempty(y) y=dosage;end prevchangetime=t; dosage=y; vssSetOzData(block,1,dosage,1); vssSetOzData(block,2,prevchangetime,1); fprintf(fileID,... ’t=%f, hrate=%f, spress=%f, temp=%f, dosage=%f\n’,... t, heartrate, spressure, temperature,dosage);

374

13 Construction of New Blocks

end end end end

The only API used in this function not already provided by the skeleton generator is vssGetTime, which returns the current simulation time. During simulation, the user is prompted when an unexpected signal is encountered. The following is an example: > Time = 32. Last adjustment time = 21 Heart rate = 96, Blood Pressure = 160, Temperature = 37 Current dosage = 2.1. Enter new dosage:

At this point the simulation is halted. The simulation resumes once the user types a carriage return, after providing a new value of dosage or not. These values are all saved also in the log file logfile.txt, in the current directory in text format.

13.2.2.2

Sound of an Event

In this example a CCustomBlock is used to play a beep sound every time the block is activated by an event. The CCustomBlock parameter GUI is very similar to that of the OmlCustomBlock seen in the previous section. The tabs should be filled similarly and a C code is generated by the ‘skeleton generator’. The block contains an activation input port but no regular inputs and outputs, no states and no parameters. The CCustomBlock C code can be as follows #include "machine.h" #include #pragma comment(lib,"user32.lib") #include "vss_block4.h" VSS_EXPORT void CBlockFunction(vss_block *block,int flag) { switch (flag){ case VssFlag_OutputUpdate: MessageBeep(MB_ICONERROR); } }

This C code is called when the block is activated. This block can be used to add beeping sounds during simulation. For example it can be used to add sound effects to the bouncing ball demo. This can be done as in Figure 13.7. Real time scaling should be used for realistic effect.

13.2.2.3

Car Model

The car model presented in Section 11.3.4 is re-considered. The construction of the dynamics of the car had required a lot of effort and a large number of blocks as can be

13.2 Using Custom Blocks to Construct Basic Blocks

375

Fig. 13.7 The beeping block is added to the bouncing ball demo. A beep sound is produced every time the ball hits the ground

Fig. 13.8 The car model equivalent to the model in Figure 11.44

seen in Figure 11.42. In the model in Figure 11.44 a CCustomBlock is used to model not only the dynamics of the car but also the state changes. This is an interesting example since the block should model a DAE (implicit computation function), has discrete states and contains zero-crossings to model state changes (Fig. 13.8). In this formulation, in addition to the equations representing the dynamics of the car (11.5), the system may contain one or two or more equations. The number of equations changes when switching states. In particular, when a wheel is off the ground, the road constraint equation is not active and λr or/and λ f are set to zero. Since in CCustomBlock block the number of equations must remain constant over the whole simulation interval, the trivial algebraic equations λr = 0 or/and λ f = 0 are added if the rear or/and front wheels are off the ground.

376

13 Construction of New Blocks

In summary, the system contains 4 states and the corresponding additional equations are 1. if both wheels are on the ground,  y0 − F(x0 ) , y1 − F(x1 )

(13.1)

 y0 − F(x0 ) 0= , λf

(13.2)

 0= 2. if only rear wheel is on the ground, 

3. if only front wheel is on the ground,  0= 4. if no wheel is on the ground,

 λr , y1 − F(x1 )

 λr . 0= λf

(13.3)



(13.4)

The state changes are detected by zero-crossing surfaces which depend on the state. In particular if the system is in state 1 (both wheels on the ground), then the zero-crossing surfaces are   λ (13.5) s= r . λf The reason for this is that as long as the wheels are on the ground, the vertical forces exerted on them from the ground are positive. As soon as any of them goes negative, the corresponding wheel leaves the ground. If the system is in state 2 (only rear wheel on the ground), then the test on the rear wheel (λ2 ) remains the same, but the other zero-crossing consists in finding whether the front wheel has come to contact with the ground. So in this case the zero-crossing surfaces are   λr . (13.6) s= y1 − F(x1 ) Similarly, for state 3 the zero-crossing surfaces are  y0 − F(x0 ) , λf

(13.7)

 y0 − F(x0 ) s= . y1 − F(x1 )

(13.8)

 s= and for state 4,



13.2 Using Custom Blocks to Construct Basic Blocks

377

It turns out that the above DAE has index higher than one in the case at least one wheel is on the ground. General DAE solvers such as the ones implemented in Activate cannot solve high index DAEs (except in special cases). In this particular situation, it is possible to reduce the index by simply making a change of variable by replacing λr and λ f with their time derivatives λ˙ r and λ˙ f everywhere (this is possible since the time derivatives of these variables are absent from the equations of the system). This results in an index 1 DAE, which can be simulated with Activate’s DAE solvers. The C code used in the CCustomBlock, given below, may seem complicated but the block interface generates automatically the skeleton of the code based on the information provided concerning the block parameters, inputs and outputs. Users need only to fill in the empty sections with codes corresponding to system equations. It is fairly straightforward to see the correspondence between this C code and the system equations. #include "vss_block4.h" VSS_EXPORT void CBlockFunction(vss_block *block,int flag) { // Block input SCSREAL_COP *u=(SCSREAL_COP *)GetInPortPtrs(block,1); SCSREAL_COP *yr0=(SCSREAL_COP *)GetInPortPtrs(block,2); SCSREAL_COP *yr1=(SCSREAL_COP *)GetInPortPtrs(block,3); SCSREAL_COP *yrd0=(SCSREAL_COP *)GetInPortPtrs(block,4); SCSREAL_COP *yrd1=(SCSREAL_COP *)GetInPortPtrs(block,5); // Block outputs SCSREAL_COP *x=(SCSREAL_COP *)GetOutPortPtrs(block,1); SCSREAL_COP *y=(SCSREAL_COP *)GetOutPortPtrs(block,2); SCSREAL_COP *theta=(SCSREAL_COP *)GetOutPortPtrs(block,3); SCSREAL_COP *x0=(SCSREAL_COP *)GetOutPortPtrs(block,4); SCSREAL_COP *y0=(SCSREAL_COP *)GetOutPortPtrs(block,5); SCSREAL_COP *x1=(SCSREAL_COP *)GetOutPortPtrs(block,6); SCSREAL_COP *y1=(SCSREAL_COP *)GetOutPortPtrs(block,7); SCSREAL_COP *z0=(SCSREAL_COP *)GetOutPortPtrs(block,8); SCSREAL_COP *z1=(SCSREAL_COP *)GetOutPortPtrs(block,9); SCSREAL_COP _x, _y, _vx, _vy, _xsi, _eta, _theta, _omega; SCSREAL_COP lr, lf, lam1, lam2, lam3, lam4, w0, w1; SCSREAL_COP _xd, _yd, _vxd, _vyd, _xsid, _etad, _thetad, ... _omegad; SCSREAL_COP _phi0, _psi0, _phi1, _psi1, _x0, _y0, _x1, _y1; // Discrete state indicating modes of the system SCSREAL_COP *z=GetDstate(block); // Conitnuous state, state derivative and residual SCSREAL_COP *X=GetState(block); SCSREAL_COP *Xd=GetDerState(block); SCSREAL_COP *res=GetResState(block); // System constant parameters SCSREAL_COP *l=(SCSREAL_COP *)GetOparPtrs(block,1); SCSREAL_COP *m=(SCSREAL_COP *)GetOparPtrs(block,2); SCSREAL_COP *g=(SCSREAL_COP *)GetOparPtrs(block,3); SCSREAL_COP *ga=(SCSREAL_COP *)GetOparPtrs(block,4);

378 SCSREAL_COP SCSREAL_COP SCSREAL_COP SCSREAL_COP SCSREAL_COP SCSREAL_COP

13 Construction of New Blocks *k=(SCSREAL_COP *a=(SCSREAL_COP *b=(SCSREAL_COP *f=(SCSREAL_COP *d=(SCSREAL_COP *J=(SCSREAL_COP

*)GetOparPtrs(block,5); *)GetOparPtrs(block,6); *)GetOparPtrs(block,7); *)GetOparPtrs(block,8); *)GetOparPtrs(block,9); *)GetOparPtrs(block,10);

SCSREAL_COP rear_c, front_c, hr, hf, lrz, lfz; // zero-crossing surfaces and the direction of crossings SCSREAL_COP *G=GetGPtrs(block); int *jroot = GetJrootPtrs(block); // DAE States _x = X[0]; _y = X[1]; _vx = X[2]; _vy = X[3]; _xsi = X[4]; _eta = X[5]; _theta = X[6]; _omega = X[7]; _xd = Xd[0]; _yd = Xd[1]; _vxd = Xd[2]; _vyd = Xd[3]; _xsid = Xd[4]; _etad = Xd[5]; _thetad = Xd[6]; _omegad = Xd[7]; lr=Xd[8];lf=Xd[9]; _phi0 = _xsi * cos(_theta) + *l * sin(_theta) / 2; _phi1 = _eta * cos(_theta) - *l * sin(_theta) / 2; _psi0 = -_xsi * sin(_theta) + *l * cos(_theta) / 2; _psi1 = _eta * sin(_theta) + *l * cos(_theta) / 2; // Wheel postions _x0 = _x - _psi0; _y0 = _y - _phi0; _x1 = _x + _psi1; _y1 = _y - _phi1; // Computation of lambda forces hr = sqrt(1 + *yrd0 * *yrd0); hf = sqrt(1 + *yrd1 * *yrd1); switch (flag){ case VssFlag_Initialize: z[0] = (_y0 - *yr0) > 0; z[1] = (_y1 - *yr1) > 0; break; case VssFlag_StateUpdate: if (isZeroCrossing(block)) { if (jroot[0] == -1) z[0] = 1 - z[0]; if (jroot[1] == -1) z[1] = 1 - z[1]; } break; case VssFlag_Derivatives: if (z[0] == 1){ rear_c = lr; lam2 = 0; lam1 = 0; }else { rear_c = _y0 - *yr0; lam2 = (lr + *u * *yrd0) / hr; lam1 = (-lr* *yrd0 + *u) / hr; } if (z[1] == 1){ front_c = lf;

13.2 Using Custom Blocks to Construct Basic Blocks

379

lam4 = 0; lam3 = 0; }else { front_c = _y1 - *yr1; lam4 = lf / hf; lam3 = -lf * *yrd1 / hf; } res[0] = _xd - _vx; res[1] = _yd - _vy; res[2] = _thetad - _omega; res[3] = *k * (_xsi - *d) + *ga * _xsid lam1 * sin(_theta) + lam2 * cos(_theta); res[4] = *k * (_eta - *d) + *ga * _etad lam3 * sin(_theta) + lam4 * cos(_theta); res[5] = -*m * _vxd + lam1 + lam3; res[6] = -*m * _vyd - *m* *g + lam2 + lam4; res[7] = -*J * _omegad + lam1 * _phi0 - lam2 * _psi0 + lam3 * _phi1 + lam4 * _psi1; res[8] = rear_c; res[9] = front_c; break; case VssFlag_OutputUpdate: *x = _x; *y=_y; *theta = _theta; *x0 = _x0; *y0 = _y0; *x1 = _x1; *y1 = _y1; *z0 = z[0]; *z1 = z[1]; break; case VssFlag_ZeroCrossings: G[0] = (z[0] == 0) ? lr : _y0 - *yr0; G[1] = (z[1] == 0) ? lf : _y1 - *yr1; break; } }

The simulation result is identical to what was obtained in Section 11.3.4 and illustrated in Figure 11.50.

13.3 Block Libraries A new block, defined as a masked Super Block or by the BlockBuilder as a regular block or a programmable Super Block, is part of the model in which it is created. The new block however can be saved separately in a file with extension scb. This can be done using Save Selected in the File menu, after selecting the block in the model. The scb file can then be dragged and dropped in other models. This operation however again includes a complete copy of the definition of the new block in the model. The model in this case will not have any dependency on the scb file.

380

13 Construction of New Blocks

Another way to store and use the new block is to include it in a block library. By placing the new block in a library and using it in a model as such, the definition of the block is not included in the model. The model simply contains a reference to the block and information that is specific to the instance of the block such as its parameters, block graphical properties in the diagram such as its position, size, color, etc. There are many advantages in using block libraries. The non-inclusion of the block definitions inside the model significantly reduces the size of model files when the same blocks appear many times. It also facilitates the updating of the blocks. In particular, if a new improved version of the block is available, a new version of the library can be created. Otherwise, every instance of the block used in every model needs to be updated manually. Note however, the usage of a library block creates a dependency on the library. In particular, a model containing a library block can be used only if the corresponding library (or a new version of it) is installed. For private libraries, this means that the library must be provided along with the model if the model is distributed.

13.3.1 Library Content A library provides new functionalities to Activate. When installed, new OML functions, Activate blocks or even new menus may be made available. Block libraries provide many new blocks, which can be used through palettes in the palette browser window. A block library is defined within a folder containing in general: • A _key file identifying the library and its version using a unique key. The file may contain older keys associated with older versions of the same library used for identifying and updating old library blocks found in models. • Initialization scripts used to load the library. • A model file defining the library palette exposing some or all library blocks for use. • A folder for each block defined in the library including the scb file of the block and the associated (and automatically generated) OML script file. • If library blocks use computational functions, then their dll and lib files are included in the _sim subfolder. • Other subfolders may provide tests, demos and documentation. The library and its palette may have hierarchical structure as well. This is the case for example for the Activate library shipped with Activate and the Modelica library.

13.3 Block Libraries

381

13.3.2 Library Management The Activate and Modelica libraries are pre-installed in Activate and ready to be used. Other libraries, if needed, must be installed by the user. This can be done through the menu File/Libraries, which gives access to a library manager widget. This widget contains a number of facilities for the management of libraries including installation, which can be used to install a library by selecting its folder. The installation automatically makes the associated library palette available in the palette browser. User installed libraries can be un-installed. More library management functionalities are available, see the product documentation for details.

13.4

IncludeDiagram

Block

The IncludeDiagram block, strictly speaking, is not a way to construct a new block, but rather this block provides a mean to use a Super Block in the model where its content is defined elsewhere, in a different model. This block can be seen as a reference not to a library block but to a diagram defined in a different model. To use the IncludeDiagram block the user must specify the number of ports of the block and the diagram to which it references. The diagram, specified by its model name and its path inside the model, must have block ports that correspond to the number of ports specified in the block. More than one diagram can be specified in a IncludeDiagram block. The one to be used for simulation is specified by a block parameter. This feature is particularly useful when multiple models of the same process exist, for example with more or less refinement, which should be used in different circumstances. These models can then be realized by different diagrams and be associated with the IncludeDiagram block. The choice of which model is to be used can then be parameterized. For each included diagram, a Context script can be provided inside the block. This script is evaluated before the Context script of the diagram itself and in general can be used to define variables that may have been defined in the Initialization script of the model in which the diagram is defined. Note that the inclusion of a diagram does not affect the way the model is compiled. The diagrams associated with IncludeDiagram blocks are included in the model before compilation. Not including a diagram but referring to an external file is useful when the diagram is needed in multiple places. This enables the reduction of the size of the model file. It also allows updating the diagram once regardless of the number of times the diagram is used. The drawback, however, is that the model file is no longer self-contained and cannot be simulated without the model containing the definition of diagrams referred to within its IncludeDiagram blocks. In a way the other model can be seen as a diagram library.

382

13 Construction of New Blocks

Fig. 13.9 The block builder tool GUI: main tab

The IncludeDiagram block in a model can also refer to a diagram in the same model. This can be done by setting the block parameter Model path to the name of the model. It can also be set to bdeGetModelFilePath(bdeGetCurrentModel)

which returns the full path of the model. The advantage of using this function is that the model will continue to function properly even if it is renamed. Models using self referring IncludeDiagram blocks remain self-contained.

13.5 Block Builder The block builder tool can be used to construct a new basic Activate block. The tool is used to edit the block properties interactively. In most cases, it is more convenient to start from an existing block when a new block is to be constructed. So to use the block builder, an existing block with similar properties can be placed from any palette inside a diagram. Then the block should be selected and the block builder opened from the Tools menu. The block builder GUI is shown in Figure 13.9. Here the selected block is the SampledData block already encountered in Section 10.4. The first tab (Label) can be used to specify the name (label) of the block and its disposition around the block. Note that the block builder does not modify the selected block, it creates a copy of it and modifies the copy. When the block builder is closed, the copied block appears in the diagram next to the selected block.

13.5 Block Builder

383

Fig. 13.10 The Atom tab is used to edit the evaluation functions and specify the computational functions of the block

The Atom tab is used to define OML codes used during evaluation and compilation, and the name and location of computational functions. In the case of the SampledData block, as it can be seen in Figure 13.10, the block has two different computational functions csslti4 and dsslti4. These functions correspond to the computational functions of continuous-time and discrete-time state-space systems. The SampledData block in general implements a discrete-time state-space system, but by convention, when its activation period is zero (i.e., when the block is continuously activated) then it implements the original continuous-time system corresponding to its parameters. The choice of the computational function is in general made in the first OML code defining the SetParameters evaluation function. In this case however the choice is made in the ResetParameters function, which is called at the end of the compilation process when the blocks are given the possibility to change some of their properties based on the result of compilation, before the simulation begins. In this case the activation period of the block, which is available only through compilation, is used in the ResetParameters to select the proper computational function and, in case the period is not zero, to compute parameters of the discrete-time computational function. The OML source codes of the SetParameters, SetInputsOutputs and Reset -Parameters function bodies can be edited by clicking on the “helper” buttons placed on the right hand side of the corresponding entry widgets. These OML functions instantiate the block based on the values of the block parameters using specific OML APIs. The best way to learn about these APIs and their usage is to examine the codes of existing blocks.

384

13 Construction of New Blocks

Fig. 13.11 Definition of block parameters

Fig. 13.12 Definition of the input-output properties

The Parameters tab is used to define the parameters of the block. It resembles the mask editor used to edit the mask of masked Super Blocks. In the case of the SampledData block, there are 5 parameters: the (A, B, C, D) matrices defining the state-space system and the initial condition of the system. See Figure 13.11. The helper button opens up a GUI where various parameter properties, such as its default value, type and short description can be specified.

13.5 Block Builder

385

The Ports tab is used to define the block ports and their positions around the block. It also defines the port types and their index (or numbers in case of variable ports). A variable port may define zero, one, or more ports. Many blocks in Activate have a variable number of ports such as the Mux or the Sum blocks. Variable ports are also useful for defining optional ports. For example, in the case of the SampledData block, the activation input port is optional so it is defined as variable as can be seen in Figure 13.12. Other tabs of the block builder GUI are used to specify graphical properties of the block such as size, color, icon, etc. Once the block builder is closed, the new block appears in the current diagram. It can then be saved using the Save Selected action in the File menu. The resulting scb file can then be placed in a library or used directly in other models.

Chapter 14

Modelica Support

14.1 Introduction An extension to Activate that makes physical component-level modeling possible is presented in this chapter. Regular Activate is not always suited for physical component-level modeling. For example, when modeling an electrical circuit, it is not possible to construct an Activate model with a one-to-one correspondence between the electrical components (resistor, diode, capacitor,…) and the regular blocks in the Activate model. In fact, the Activate model does not in general look like the original electrical circuit. To illustrate this point, consider the electrical circuit depicted in Figure 14.1. This circuit contains a voltage source, a resistor, and a capacitor. To model and simulate this circuit in Activate, Kirchoff’s law is used to obtain the system equations. It states that the voltage drops (or increases) around a circuit loop must add up to zero. This gives Vs + Ri +

1 C

 i dt = 0,

(14.1)

where Vs is the voltage across the voltage source and i is the current through the circuit. So the voltage V across the capacitor can be computed as follows:  1 V =− i dt. (14.2) C These two equations can be implemented in Activate by using an Integrator block receiving i as an input. The resulting Activate model is depicted in Figure 14.2. Note that this Activate model does not look like the original electrical circuit in Figure 14.1. An extension of Activate can be used to model physical components directly within the Activate models. This is done by lifting the causality constraint on Activate blocks and by introducing the possibility of describing block behaviors in the Modelica language. With this extension not only systems containing electrical com© Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_14

387

388

14 Modelica Support 0.01 ~ 220

0.01

Fig. 14.1 A simple electrical circuit

Fig. 14.2 Activate diagram realizing the dynamics of the electrical circuit in Figure 14.1 using regular blocks Fig. 14.3 Activate model using Modelica components corresponding to the electrical circuit in Figure 14.1. A voltmeter is added for measuring the voltage across the capacitor

ponents but also mechanical, hydraulic, thermal, and other physical systems, can be more naturally modeled. For example, the electrical circuit in Figure 14.1 can be modeled and simulated by constructing the Activate model in Figure 14.3. The electrical components come from the Electrical sub-palette inside the Modelica palette. The Activate model in Figure 14.3 contains only Modelica components. But these components can be used along with regular Activate blocks in the same model, as illustrated in Figure 14.4 comparing the two formulations of the system. Connection

14.1 Introduction

389

Fig. 14.4 Modelica components and regular Activate blocks may co-exist in the same Activate model. The simulation result is shown in Figure 14.5

between Modelica components and regular Activate blocks is possible. Only Modelica signal types can be connected and an interface block must be used. In the model in Figure 14.3, the only signal on the Modelica side is produced by the Voltmeter (measured voltage). This signal is connected to the second port of the Scope block through the interface block FromModelica. This block is inserted automatically when a connection is made from the port of a Modelica component to a port of a regular Activate block. The ToModelica interface block is used for an opposite connection. The model in Figure 14.6 shows the interconnection between regular Activate blocks and Modelica components in both directions. The model is obtained from a classical Modelica demo where the signal producing blocks have been replaced by regular Activate blocks. In this model, which represents a coupled clutch system, the input torque and the clutch commands are modeled by regular Activate source blocks. The regular and Modelica blocks can co-exist also at different levels of hierarchy. In particular Super Blocks may contain mixed port types. This is particularly important for importing Modelica models from other tools. Such models may contain components that are not provided by libraries. We shall see later in Section 14.4.2 how to include such components using the MoCustomComponent block. But by doing so, if the component contains a subsystem (a Modelica model containing connected components), its graphical representation is lost. In the case of subsystems it is possible to recreate the model using a Super Block. Care must be taken since the notions of Super Block in Activate and subsystem in Modelica do not have the exact same semantics.

390

14 Modelica Support

Fig. 14.5 The simulation result shows that the two formulations in Figure 14.4 give identical results, as expected

Fig. 14.6 The coupled clutch Modelica demo reformulated in Activate

The CauerLowPassSC example of the Electrical.Analog library of MSL is used to show how a Modelica model with components that are not available in the Activate library can be recreated in Activate. In this model, two components of type subsystem, Rp and Rn are used, which are defined inside of the definition of the CauerLowPassSC model. These subsystems should be defined inside Super Blocks in the Activate version of this example. The Modelica component Rp is shown in Figure 14.7. The corresponding Activate Super Block can be constructed using exactly the same components but here the component generating pulses to control the switches are replaced and uses a SampleClock block. It is more natural to model in this way events in Activate to switch values between 0 and 1. A ModuloCounter

14.1 Introduction

391

Fig. 14.7 OpenModelica’s rendering of the Rp component model used inside the CauerLowPassSC example

Fig. 14.8 The Activate implementation of the Modelica subsystem in Figure 14.7

block is used in this case as it can be seen in Figure 14.8 implementing the Modelica component Rp and Figure 14.9 implementing the Modelica component Rn Using these Rp and Rn Activate Super Blocks, the Activate version of the CauerLowPassSC example can be created as in Figure 14.10. The simulation result is given in Figure 14.11. The integration of Modelica components in the Activate environment has been a challenging endeavor, which started many years ago in Scicos (www.scicos.org). Some information on challenges posed by this integration can be found in the following publications: [37, 38, 40, 41, 43], and [44].

392

14 Modelica Support

Fig. 14.9 The Activate implementation of the Modelica component Rn used in the CauerLowPassSC example

So far the presentation has been limited to the use of provided Modelica components in Activate libraries. But Modelica is also a programming language, which can be used to define new components by defining underlying mathematical equations. This aspect of the language, and its use in the Activate environment are presented in the rest of this chapter.

14.2 Modelica Libraries A Modelica library cannot be used directly as an Activate library; it must be imported. The import of a Modelica library consists in creating an Activate block for every component in the Modelica library. Such an import functionality is available in Activate and can be applied to any Modelica library. Once imported, the Modelica components of the library are made available in new Activate palettes and can be used in the construction of Activate models. A large portion of the Modelica standard library (MSL) is already included in Activate. These libraries cover many physical domains: electrical circuits, magnetics, mechanics, thermal, etc. The Blocks library is also part of the MSL providing explicit components acting on signals. This library is supported in Activate for legacy reasons but it is not exposed as a palette since these block functionalities are covered by regular Activate blocks and there is no need for them when creating new models.

Fig. 14.10 The Activate version of the CauerLowPassSC example from MSL

14.2 Modelica Libraries 393

394

14 Modelica Support

Fig. 14.11 The voltage across the R11 component produced by a voltage sensor component and displayed using a regular scope

14.3 Modelica Language Modelica is a typed object oriented language for which a large set of libraries for modeling in various physical domains are available. The Modelica language is primarily designed to facilitate the expression of dynamical systems, in particular the definition of systems of differential-algebraic equations. In Modelica, equations are expressed very closely to the way they are expressed mathematically. Unlike OML and most other programming languages, Modelica is a declarative language. The system of equations can be “programmed” in any order and the semantics of the equal sign is that of the mathematical equality (i.e, the equality of the value of expressions on the two sides of the equality) and not an assignment. Using the language constructs der (time derivative), delay (time delay), pre (previous discrete-time value), time (current time), · · · , dynamical systems of one independent variable can be expressed naturally as Modelica equations. This includes not only continuous-time systems described by differential-algebraic equations but also discrete-time systems. But the Modelica language provides more than just a way to express equations. It can be used to define classes, inheritance, functions, records and data types. It also provides the possibility to use an imperative style of programming (algorithmic sections) and to interface with programs developed in other languages such as C (external functions). Annotations are used in Modelica to provide mainly graphical information. They are used by the tool to provide a graphical view of the model but do not affect the

14.3 Modelica Language

395

dynamics of the system it represents. Annotations are also used to define documentation. The Modelica language will not be presented here, a large body of literature is available on the subject [22, 36, 39–41, 44]. Information on Modelica can also be found on www.modelica.org and a nice tutorial is available on http://book.xogeny. com. Information on Modia a fork of Modelica based on Julia, can be found in [19, 20]. Only simple programs will be used in the next sections to illustrate the usage of the Modelica language in Activate.

14.4 Modelica Custom Blocks The Activate environment can be used to construct models using Modelica components imported as Activate libraries but it cannot be considered a Modelica tool. Modelica tools such as Dymola and OpenModelica [23] provide a dual vision of Modelica models: graphical and textual. Both can be used for editing models. Even though in most cases a Modelica model is either a basic component (i.e., defined by a set of equations) or a subsystem (i.e., a diagram of connected basic components and other subsystems), nothing prevents a user from introducing equations inside subsystems. The dual view provided in Modelica tools in particular facilitates its implementation. Such models are difficult to create in Activate which does not provide such a dual vision. There is no textual representation of models in Activate and the Modelica components available in Activate libraries are exposed similarly to regular Activate blocks. Activate however does provide facilities to develop custom blocks based on Modelica. The textual definition in this case is defined as block parameters and remains purely textual; no graphical representation would be provided, even in case the Modelica code defines a subsystem. An analogy can be made with regular programmable Super Blocks where the diagram inside the Super Block has no graphical representation. Two custom blocks available in CustomBlock palette allow users to define block/component behavior using Modelica code: the MoCustomBlock and MoCustomComponent blocks presented below.

14.4.1

MoCustomBlock

The block MoCustomBlock in CustomBlock palette can be used to define an Activate regular block where the behavior of the block is given by a Modelica program. This block is similar to the OmlCustomBlock and CCustomBlock presented in Chapter 13 in that its behavior during simulation is defined interactively during model editing in the graphical editor by the user as a program. As with the other two blocks, MoCustom-

396

14 Modelica Support

Fig. 14.12 Block parameter GUI used to customize the block

Block is a regular block, not a Modelica block. The Modelica program inside the block is processed automatically by the Modelica compiler and the block is converted into an FMU block. Even if this block is not a true Modelica block, it provides the user the option of describing its internal dynamics in the Modelica language and thus taking advantage of the features of the language.

14.4.1.1

Example: Chaotic System

The following dynamical system with chaotic behavior will be modeled in the Modelica language inside a MoCustomBlock. x˙ = y y˙ = x − x 3 − εy + γ cos(t). In this system, ε and γ may be considered constant parameters and programmed as such in the block, or may be considered as inputs in which case they can be time varying signals. The MoCustomBlock properties such as the inputs, outputs, parameters and the block’s Modelica code are defined inside the block parameter GUI as shown in Figure 14.12. Here ε and γ are programmed as inputs, as it can be seen from the block’s Modelica code:

14.4 Modelica Custom Blocks

397

Fig. 14.13 The model of the chaotic system

Fig. 14.14 Simulation result

model generic //parameters //input variables Real epsilon; Real gamma; //output variables Real x(start=0); Real y(start=1); equation der(x)=y; der(y)=x-xˆ3-epsilon*y+gamma*cos(time); end generic;

But these inputs are later set to constants in Figure 14.13. The simulation result is shown in Figure 14.14. Note the usage of the der keyword to specify the derivative with respect to time. The Modelica code is very similar to the original mathematical equations. In this case, the equations describe directly an explicit system of ODEs. Often the equations describing the dynamics of physical systems are not expressed in this way: they contain algebraic relations and multiple derivatives in single equations. Such systems can also be described directly in Modelica, in most cases without any manipulation of the original equations. A simple example is presented in the next section.

398

14 Modelica Support

Fig. 14.15 Super Block implementing the Bouc-Wen model

Fig. 14.16 The definition of the block’s input and outputs

14.4.1.2

Examples: Bouc-Wen Model

The Bouc-Wen model considered in Section 7.2.2 is re-implemented here using a MoCustomBlock. The top diagram is identical to the Activate diagram in Figure 7.3 but now the Bouc-Wen MR damper Super Block contains a MoCustomBlock realizing the system equations (7.1) and (7.2), as illustrated in Figure 14.15. The model parameters in this case are defined as block parameters (alternatively they could have been given numerical values inside the Modelica code). The tabs of the block parameter GUI defining the block’s input and outputs are shown in Figures 14.16 and 14.17. The Modelica code associated with the block (defined in block’s SimFunction tab of its GUI) is the following model boucwen //parameters parameter Real parameter Real parameter Real parameter Real parameter Real parameter Real parameter Real

a1 = a1; a2 = a2; c1 = c1; c2 = c2; beta = beta; gamma = gamma; delta = delta;

14.4 Modelica Custom Blocks

399

Fig. 14.17 The definition of some of the block’s parameters can be seen here

Fig. 14.18 The Bouc-Wen MR damper Super Block is masked and exposes only the value of the electrical current

parameter Real n = n; parameter Real i0 = i0; parameter Real c=c1+c2*i0; parameter Real alpha=a1+a2*i0; //input variables Real thd; //output variables Real T; Real z(start=0.1); Real zn; equation T = alpha * z + c * thd; zn = abs(z)ˆn; der(z) = -gamma * abs(thd) * z * zn beta * thd * zn + delta * thd; end boucwen;

All the parameters of the model are passed to the block from the outside except for c and alpha, which are computed internally. The use of the MoCustomBlock is made transparent by masking the Bouc-Wen MR damper Super Block. The only mask parameter in this case is the current i, as can be

400

14 Modelica Support

Fig. 14.19 The Modelica version of the Model in Figure 7.7

seen in Figure 14.18. The other parameters are defined in the Context of the Super Block as follows: J=1; k=109; teta0=0; A=.3; i0=1; f0=1.6;

The Modelica language allows defining system of equations where the number of equations is a parameter. This can be seen in the heat equation example presented in Section 5.4.1, in particular the model in Figure 7.7 with insulation at one end and a varying temperature at the other end, is here reconstructed using the MoCustomBlock as in Figure 14.19. The output of the block contains the measurement of the temperature of the end point of the rod. If needed, additional outputs must be added for other locations since the inputs and outputs of the MoCustomBlock are of scalar type. The simulation result is shown in Figure 14.20. The tabs of the block parameter GUI defining the block’s input, outputs and parameters are shown in Figures 14.21 and 14.22. The Modelica code associated with the block (defined in block’s SimFunction tab of its GUI) is the following model heat //parameters parameter Real a = a; parameter Real T00 = T00; parameter Real TN0 = TN0; parameter Integer N = N; //input variables Real T0; Real T[N]; //output variables Real TN; equation TN = T [N]; der(T[1]) = a*(T[2]-2*T[1]+T0); for i in 2:(N-1) loop der(T[i]) = a*(T[i+1]-2*T[i]+T[i-1]); end for; der(T[end]) = a*(-T[end]+T[end-1]);

14.4 Modelica Custom Blocks

401

Fig. 14.20 The simulation result for Model in Figure 14.19 shows the temperature of the rod at the extremity x = L

Fig. 14.21 The definition of the block’s input and outputs

initial equation T = linspace(T00,TN0,N); end heat;

The initial temperature of the rod is supposed to vary linearly from one end to the other. At the end x = 0, the temperature is set to 300 and at x = L, to 400. The section initial equation contains equations that must hold at the initial time. Here this section is used to initialize the temperature of the rod (T00 and TN0 specify the initial temperatures at the two ends of the rod). The variables T0 and TN represent the evolution of these temperature over time, the former is the input to the block, the latter is the block’s output.

402

14 Modelica Support

Fig. 14.22 The definition the block’s parameters

Fig. 14.23 The complete model of the car with the car dynamics modeled in Modelica language

14.4.1.3

Example: Bike or Half Car Model

The car model presented in Section 11.3.4 and re-considered in Section 13.2.2.3 is used again. It was noted that the construction of the dynamics of the car using basic blocks required a lot of effort and in addition it was error prone (model in Figure 11.42). Using the MoCustomBlock, it is possible to implement the equations of the system in a very natural way, very close to the actual mathematical model, in particular Equations (11.4), (11.14), (11.15). The model presented in Figure 14.23 is identical to the original model in Figure 11.44 except that the dynamics Super Block is replaced with a MoCustomBlock block. The Modelica script associated with the

14.4 Modelica Custom Blocks

403

block is given below. Note that the Modelica equations are simple transcriptions of the mathematical equations of the system. model generic //parameters parameter Real th0, xi, yi; parameter Real m, g, J; parameter Real xsi0, eta0; parameter Real l, d, k, ga; //input variables Real lm1, lm2, lm3, lm4; //output variables Real x(start=xi), y(start=yi), th(start=th0); Real vx(start=0), vy(start=0), om(start=0); Real x0, y0, x1, y1; //internal variables Real phi0, phi1, psi0, psi1; Real xsi(start=xsi0); Real eta(start=eta0); equation phi0 = xsi*cos(th)+l*sin(th)/2; phi1 = eta*cos(th)-l*sin(th)/2; psi0 = -xsi*sin(th)+l*cos(th)/2; psi1 = eta*sin(th)+l*cos(th)/2; x0 = x-psi0; y0 = y-phi0; x1 = x+psi1; y1 = y-phi1; 0 = der(x)-vx; 0 = der(y)-vy; 0 = der(th)-om; 0 = ga*der(xsi)+k*(xsi-d)-lm1*sin(th)+lm2*cos(th); 0 = ga*der(eta)+k*(eta-d)-lm3*sin(th)+lm4*cos(th); 0 = -m*der(vx)+lm1+lm3; 0 = -m*der(vy)-m*g+lm2+lm4; 0 = -J*der(om)+lm1*phi0-lm2*psi0+lm3*phi1+lm4*psi1; end generic;

14.4.2

MoCustomComponent

Block

Unlike the MoCustomBlock, which is Modelica inside but regular Activate outside, the MoCustomComponent block can be used to create an actual Modelica block. For example, a block that can model a Modelica component such as the electrical components presented earlier in this chapter. Such a component may be a simple electrical resistor or a complex hydraulics system. For example, consider an electrical resistor where the voltage/current dependence is nonlinear: (14.3) v = R1 i + R2 i 3 , where v and i represent respectively the voltage and the current. This component can be defined in Modelica language as follows

404

14 Modelica Support

Fig. 14.24 The definition of the block’s intput and outputs

model nonlinresistor "Nonlinear resistor, v=R1*i+R2*iˆ3" Modelica.Electrical.Analog.Interfaces.PositivePin p; Modelica.Electrical.Analog.Interfaces.NegativePin n; parameter Modelica.SIunits.Resistance R1 = 1, R2 = 0; Modelica.SIunits.Current i; Real v; equation v = R1*i + R2*iˆ3; v = p.v - n.v; n.i = -i; p.i = i; end nonlinresistor;

This code can be placed inside the MoCustomComponent parameterized as in Figures 14.24 and 14.25. This new component can now be connected to other electrical components; see Figure 14.26. The simulation result is shown in Figure 14.27. In the previous example the MoCustomComponent was used to represent a simple Modelica component but this block can also be used to represent complex components modeled by Modelica diagrams. This is in particular useful when such a Modelica component is not available in an Activate library and the user does not need to have access to its diagram. In this case, the Modelica code of the component can be simply copied inside the MoCustomComponent. The model presented in Figure 14.28 is inspired by the MSL example model SimpleTriacCircuit in Electrical.Analog.Examples. The simple triac component is a library component; its model is provided in the Electrical.Analog.Semiconductors library. Triac stands for triode for alternating current. It is a three terminal component that can conduct current in either direction and is controlled by a small voltage. Here a MoCustomComponent is used to implement this model. This is done by simply copying the Modelica code of the Model inside the MoCustomComponent

14.4 Modelica Custom Blocks

405

Fig. 14.25 The definition of some of the block’s parameters can be seen here Fig. 14.26 The nonlinear resistor used in a model

and defining its block parameters, inputs and outputs. The model annotations can be discarded to simplify the model. The MoCustomComponent block’s generic interface is generally not convenient for the end user. For this reason, the block is masked here as seen in Figure 14.29. The auto masking is used in this case. For that, the MoCustomComponent block parameters are first defined in the Initialization script and then removed after auto masking. The MoCustomComponent block’s GUI is shown in Figures 14.30 and 14.31. The original model contains an optional port (HeatPort), which is not supported here for simplicity. To support an optional port, a programmable Super Block must be used to implement the component and auto masking cannot be used. The presence of the optional port is tested in the Context of the Super Block: useHeatPort=useHeatPort==1 if useHeatPort then error(’Heat port not supported’) end

The mask GUI of the Super Block realizing the triac is shown in Figure 14.32. This is to be compared with the original MSL component’s GUI as it can be seen for example in OpenModelica. OpenModelica’s rendering of the simple triac parameter GUI is shown in Figure 14.36.

406

14 Modelica Support

Fig. 14.27 The simulation result for model in Figure 14.26

Fig. 14.28 A simple model to demonstrate simple triac’s behavior. This model is inspired by the MSL example SimpleTriacCircuit

This implementation of the simple triac component illustrates the powerful feature provided by the MoCustomComponent block to insert Modelica components using their code inside Activate but it is not by itself interesting since this component is al-

14.4 Modelica Custom Blocks

407

Fig. 14.29 The MoCustomComponent is placed inside a diagram and the diagram is masked

Fig. 14.30 The first Tab of the block GUI is used to define inputs and outputs. In the case of Modelica blocks, inputs and outputs merely specify the positions of the ports: inputs on the left and outputs on the right

Fig. 14.31 The second Tab of the block GUI is used to define block parameters. In this case numerical values are not assigned to parameters; they are defined by OML variables to allow masking of the block

408

14 Modelica Support

Fig. 14.32 By masking the block, and placing an appropriate image icon, the block can be used as a triac component

ready available in MSL; see the same Activate model using the triac component from the Modelica/Electrical/Analog/Semiconductors palette in Figure 14.33. But often new components are designed starting off from an existing component. It is then easy to edit the Modelica code inside the MoCustomComponent block to achieve the desired behavior. The interactive editing capability of the Modelica code is a particularly interesting feature, which replaces to some extent the absence of dual text/diagram editing facilities in specialized Modelica tools such as Dymola and OpenModelica. The simulation results are identical for both models, as expected. The scope contents are shown in Figures 14.34 and 14.35 (Fig. 14.36).

14.5 Example Modelica components can be used in an Activate model without limiting the available functionalities. For example, optimization through the BobyqaOpt block can still be used even if the model contains Modelica components. We give an example due to Livio Mariano of Altair. The model in Figure 14.37 contains a simple spring-damper system using Modelica components from the MSL library. The system is controlled using a PID block.

14.5 Example

409

Fig. 14.33 The same model as the one in Figure 14.28 but using the simple triac component from the MSL library

Fig. 14.34 The signal controlling the input current source

410

14 Modelica Support

Fig. 14.35 The measured output current

The parameters of the PID block are obtained through optimization. The cost function is a distance between a reference tranjectory (a step function in this case) and the output of the system. The distance is obtained by computing the integral of the square of the difference between the two signals. The difference is multiplied by a factor of 100 when it is negative. This is done to penalize overshoot. The three variables over which the optimization is performed are P, I and D, the parameters of the PID block, as it can be seen in block’s parameter GUI shown in Figure 14.38. These parameters are read from the Base environment in the initialization script: T=10; P=GetFromBase(’P’,1); D=GetFromBase(’D’,1); I=GetFromBase(’I’,1); K=4;

Here T is the simulation end time defining the interval over which the cost function is computed, and K is the spring constant. The values of the P, I and D variables are initially set to 1. These values are returned by the GetFromBase functions when the corresponding variables are not present in the Base environment, i.e., the first iteration. In subsequent iterations these variables are set by the ToBase blocks in the model at the end of each simulation. The values are of course provided by the BobyqaOpt block.

14.5 Example

Fig. 14.36 OpenModelica’s rendering of the simple triac parameter GUI

411

412

14 Modelica Support

Fig. 14.37 The parameters of a PID controller controlling a simple spring-damper system modeled in Modelica are computed through optimization

Fig. 14.38 The parameter GUI of the PID block

14.5 Example

413

Fig. 14.39 System responses for values tried by the BobyqaOpt block during optimization

To illustrate the evolution of the system response corresponding to P, I and D values tried by the BobyqaOpt block during optimization, the Scope block is put in Overlay mode. The result is illustrated in Figure 14.39.

Chapter 15

Other Activate Functionalities

15.1 Optimization Interface There are various ways to perform optimization based on model simulation. Two methods were already introduced: the use of the BobyqaOpt block presented in Section 8.2, and the use of batch simulation presented in Section 12.1. The Optimization tool provides an interactive facility to formulate optimization problems associated with Activate models and to solve them. The tool is based on batch simulations, however it frees the user from having to code any OML script. The tool generates automatically the script based on the information provided in the optimization tool GUI. Example The problem of finding the optimal gear ratios for a 5 speed vehicle, presented in Section 8.2.1.2, is considered again. In this case the objective is to minimize the time to reach a given target speed with the constraint that the vehicle’s RPM never go beyond a certain value. This optimization problem cannot be formulated using the BobyqaOpt block as in Section 8.2.1.2. The only constraints supported by the BobyqaOpt block are bounds on the optimization variables. The RPM constraint is not of this type. The solution requires the use of optimization methods with general nonlinear constraints (see Chapter 4). The optimization can be preformed using an OML script (batch simulation was presented in Chapter 12) where an Activate model would evaluate the cost and the constraint values for a given set of variables. For this problem the Activate model can be constructed as is illustrated in Figure 15.1. The simulation runs until the speed of the vehicle reaches the target speed. At this time a zero-crossing event activates the block End with parameter Stop. The optimization tool is an alternative to developing an OML script for batch simulation. An interactive GUI is used to specify the optimization problem and associate it with a model. The content of the optimization GUI can be saved in a file with extension scopt. For this optimization problem, the GUI can be used as illustrated in Figure 15.2. © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3_15

415

416

15 Other Activate Functionalities

Fig. 15.1 The model used for optimization via optimization tool. The car model is the same as in the model in Figure 8.12

In this case the optimization variables are the vector of gear ratios and the vector of shifting times, as before. Initial guess values and bounds on these variables should be provided in the optimization GUI. The optimization cost and constraints are defined in the Optimization script. The cost is provided by defining the variable _cost and the constraints by defining the vector _constraints. Every element of the constraint vector will be bounded above by zero. The cost here is the final time of simulation Tf recorded when the speed of the vehicle reaches the target speed. In case the target speed is never reached the cost is set to tf, which is the model’s final simulation time (in this case tf=25). The constraint is the difference between the maximum of the vehicle’s RPM signal w and the threshold rpm_max. The Optimization script is formulated as follows: if isempty(Tf.ch{1}.data) _cost=tf; else _cost=Tf.ch{1}.data; end; w=max(omega.ch{1}.data); _constraint=w-max_rpm;

The optimization GUI also provides for the definition of an Initialization script, which is evaluated after the Initialization script of the model but before the evaluation of the Contexts. This can be used in particular to modify model parameters defined in the model’s Initialization script for the particular optimization problem considered (equivalent of the external-context introduced in Section 8.1.2). The optimization variables (in this case gear and T) are also redefined by values calculated by the optimization algorithm at this level.

15.1 Optimization Interface

417

Fig. 15.2 The graphical user interface of the optimization tool used to formulate the optimization problem associated with the model in Figure 15.1

The optimization tool GUI also provides the ability to choose among various optimization algorithms and options. Once all the information is included, the optimization can be started by clicking on the run button at the top of the GUI. Note that the associated Activate model must be saved since the optimization tool uses the model saved on file (and not the current state of the model in the editor). The results of the optimizations are illustrated in Figures 15.3 and 15.4. The target velocity is 100 km h−1 and the maximum RPM, 5500. The values of the optimized variables and the optimal cost are shown in the GUI but they are also provided in a structure named _optim provided in the base environment, at the end of the optimization.

15.2 Code Generator The simulation of an Activate model, in most cases, does not generate any C code and does not require a C compiler to run. C code is generated in very specific situations, in particular when an atomic Super Block is present in the model. A Super Block can be explicitly declared as atomic by the user (see Section 10.6), or it can be temporarily

418

15 Other Activate Functionalities

Fig. 15.3 Engine RPM as a function of time for the optimal strategy

Fig. 15.4 The optimal strategy consists of switching gears when reaching the maximum RPM allowed for the first three gears, and switching the fourth gear slightly before

declared as such in the process of linearization or finding the equilibrium point; these functionalities were presented in Section 12.4. The code generation in these cases consists of transforming a Super Block into a single basic block. This transformation, which is automatic and transparent to the user, generates the C code of this basic block preserving as much as possible

15.2 Code Generator

419

the dynamic behavior of the original Super Block. The new block’s states, zerocrossings and modes are the concatenations of the states, zero-crossings and modes of the blocks within the Super Block. And the generated C code contains calls to simulation functions of these blocks. The way and the order in which these functions are called are determined by compiling the diagram inside the Super Block. The new block is a standard Activate block so once the Super Block has been transformed into this block, the compilation and simulation of the model can proceed as usual. Ideally the generated block should behave exactly like the original Super Block, and it does in most cases, but not always. In some cases the difference in behavior is desired and constitute the reason for which the user declares a Super Block atomic; see Section 10.6 for examples. The main cause of discrepancy in the behaviors of the block and the Super Block is the presence of asynchronous activations, especially when they are inherited through multiple input ports. This however is not an issue in the process of linearization since the subsystem to be linearized should be always active (the linearization is done to obtain a linear continuous-time system).

15.2.1 Code Generation to Create a New Block The code generator can also be explicitly invoked to transform a Super Block. This can be done by selecting the Super Block in the diagram and using the C Code Generation item in the tools menu. This action replaces the original Super Block with a new Super Block containing a CCustomBlock. The CCustomBlock contains the generated C code representing the behavior of the original Super Block and is activated in such a way as to preserve the inheritance mechanism to which the original Super Block has been subjected to.

15.2.1.1

Example

Consider the Activate Model in Figure 6.18 used to illustrate the effect of jitter. Consider now regrouping the three central blocks into a Super Block as it can be seen in Figures 15.5 and 15.6. This Super Block can be selected and C code generation can be performed. The resulting model has an identical top diagram but the interior of the Super Block is different as shown in Figure 15.7. Note that the CCustomBlock block has three activation input ports (two obtained from the original Super Block and one from activation inheritance from the regular input). This allows the resulting model to behave exactly as the original model. This Super Block could not have been declared atomic because it has more than one activation input port. In general transforming a Super Block by code generation results in slightly better simulation performance but the gain is small and it is in general not the motivation for doing this transformation. The main motivation is protecting intellectual property. The Super Block is like a source code; the content is visible and readable by

420

15 Other Activate Functionalities

Fig. 15.5 Obtained from Model in Figure 6.18 by placing three blocks inside a Super Block. The content of the Super Block is shown in Figure 15.6

everybody. Transforming the Super Block by C code generation allows the user to create a new block that can be distributed to others without source code. Only the C function’s dll needs to be provided to third parties. Another application of C code generation for a Super Block is the FMI export. This allows using the block in other simulation tools. The FMI is presented later in this chapter. An alternative C code generator is also available in Activate as a beta release. The C code generation menu offers two options: the first one, considered so far, generates a C code that calls the blocks’ codes. The second generates a C code where the blocks’ codes are inlined producing highly efficient self-contained C code. This generator currently supports only a subset of Activate blocks. The code is generated based on OML descriptions of block behaviors. Originally developed in Scilab/NSP and Scicos [15], it has now been implemented for OML and Activate. Note that there exists another situation where C code is generated in Activate; that is when the model contains Modelica components. In this case, the Modelica compiler generates a C code representing the behavior of the Modelica part of the model. This was presented in Chapter 14.

15.3 Activate Debugger

421

Fig. 15.6 The diagram inside the Super Block

Fig. 15.7 The diagram inside the Super Block

15.3 Activate Debugger When a simulation does not yield the expected result, it is often useful to have access to the time history of all the signals present in the model to identify the problem. A signal in Activate can be visualized or recorded using various blocks, such as the Scope, SignalOut or ToTextFile. Even though debugging can be done by using these blocks, the process is cumbersome. By running the simulation in debug mode, an option available in the Simulation Parameters menu, all the signals are recorded in a debug file. The location of the file can be specified by the user. See Figure 15.8. A special viewer is provided to display the content of the debug file. By checking the View debug file option, this viewer is launched automatically at the end of the

422

15 Other Activate Functionalities

Fig. 15.8 The debug tab of the Simulation Parameters menu

simulation. The time history of all the signals present in the model can then be conveniently examined. When a model is simulated in debug mode, in addition to the debug file, a CSV file is generated in the model’s temporary folder containing profiling information such as the number of calls to each block, the time spent, etc. This information is useful both for debugging and optimizing the model. The debug file contains a lot more information on the simulation history than the value of the signals, which are displayed by the viewer. The information contained in this file is intended to be used in the future by a debugger providing facilities such as single-stepping, placement of conditional break-points, viewing of the block’s internal states, etc.

15.4 Animation A simple 2D animation can be very valuable for examining a simulation result. A number of models presented in this book, for example the rocket model presented in Section 7.3.2.2 and the 2D car model in Section 11.3.4, use animations, which are illustrated in Figures 7.16 and 11.50. These animations are created using the Anim2D block. The Anim2D block can be used to create animations of simple graphical objects. The object’s types: rectangle, circle, and, open and closed polylines, are specified as block parameters as are their colors. The locations of the objects, and their orientations in case of polylines, are specified by the block input signals providing the ability to move the objects defined by the block, thus creating animations.

15.4 Animation

423

The Anim2D block has few parameters and is straightforward to use. See the block documentation for details. An alternative way of creating animations is to use an OML block (for example the OmlCustomBlock) and program the animation code directly in OML language. OML provides special functions for creating and parameterizing graphical objects. This approach can be used to construct sophisticated animations that cannot be constructed using the Anim2D block but requires developing nontrivial OML programs. For the list of OML functions associated with graphical objects, see the OML documentation.

15.5 Simulink® Import Developed by P. Weis at INRIA and J. Ph. Chancelier at ENPC, Simport [49] has been originally developed as a Simulink import utility for Scicos. Later Activate was added as a target. Modelica is currently being considered as another target for Simport. There are large differences between Scicos and Activate semantics and Simulink semantics. The explicit presence of activation signals in Scicos and Activate also results in important differences in block behaviors, even for very basic blocks. The management of block libraries are also radically different. Because of these fundamental differences, any automatic import facility should at best be considered an “import assistant”. So even though Simport can be used to import Simulink models in the Activate environment, even if all the blocks present in the model are supported by Simport, the resulting model may not have the same behavior as the original model. So by no means Simport should be considered a full featured translator; users will often need to complete the translation process manually. Note also that Simport provides virtually no support for Simscape and the Stateflow portions of the Simulink diagrams are not translated at all. Differences in Activate (Scicos) and Simulink semantics make it virtually impossible to develop a full featured translator. Simport maps Simulink diagrams into Activate models by taking a pragmatic approach: it identifies Activate features that are similar to the Simulink features present in the original diagram to construct the Activate model. In some cases, this results in model discrepancies that are hard to identify. Such problems are encountered in particular with constructions including various types of atomic, triggered and enabled Subsystems. To a lesser degree problems may be encountered in translating masked subsystems, in particular for masked Subsystems containing matlab commands using specific APIs to programmatically define or change the properties of mask parameters. Simport preserves the topology of the original model (block, link and annotation placements, and model hierarchy) and attempts to replace every supported Simulink block with a corresponding Activate block, if a block with “similar behavior” is available, but in most cases a single block is translated into a Super Block. But even for supported blocks, there are combinations of block parameters for which Simport

424

15 Other Activate Functionalities

cannot provide a translation, in which case, as for unsupported blocks, the block is translated into an empty Super Block, to be edited by the user. Virtual buses exist in Activate but their semantics are not identical to that of Simulink buses. Simport creates the corresponding Activate buses, when possible, but the imported model should be thoroughly tested. Simport translates Simulink non virtual buses also into virtual buses. Activate does not support anything similar to Simulink’s non virtual buses. Activate does not support variable size signals, i.e., signals that change size at run time (during simulation). So any Simulink model relying on this feature would not be easy to port to Activate and the imported model would require substantial modifications.

15.5.1 Frequently Encountered Problems The problems often encountered with the imported models include the followings: • Supported versions: Simport accepts slx file formats and mdl file formats corresponding to version 6.0 and higher. • Undefined variables: Simulink mdl and slx files are usually not self contained. The models defined within these files reference matlab variables defined in the matlab workspace. These variables are often defined via one or more script files associated with the model file. It is important to include these files when using Simport. Simport includes these scripts inside the Activate model (unlike Simulink models; Activate models are self-contained so they should include the definition of all parameters used in the model). The translated scripts are placed inside the Initialization script of the Activate model. Such scripts may work without any modification, but in some cases the user has to edit them. • Error when evaluating block expressions: in addition to undefined variables, other problems may be encountered in evaluating expressions defining block parameter values. For example the presence of matlab functions not available in OML or functions that have different names or syntax. • Incompatible port sizes: there exists a data type vector in Simulink, which is distinct from a matrix type. In Activate, inputs, outputs, parameters and states are of type matrix. Vectors are special cases of matrices and operations on these vectors take into account whether they are row matrices or column matrices. In general vectors are coded as single column matrices. In Simulink vectors can be coded as singlerow or single-column matlab matrices. So some block parameters or initial states may have to be modified (usually simply transposed) in imported models. • Undefined variables within masked subsystems: normally masked subsystems are self-contained in Simulink, i.e., variables used in the definition of block parameter values are passed as mask parameters or defined in the mask initialization script. But matlab workspace variables are also available inside mask subsystems. In Activate however, the masked Super Block contents are strictly self-contained.

15.5 Simulink® Import

425

So in some cases, to circumvent this difference, the user is required to add mask parameters to translated Super Blocks or define additional variables within the Context of the Super Block. • matlab Function block: this block is used to define block behavior in the matlab language. This block generates C code for embedded applications. Simport translates this block into an OmlCustomBlock with no code generation facilities. • Unsupported blocks: unsupported blocks are translated into empty Super Blocks on the Activate side. The Contexts of these empty Super Blocks contain information found in the original model regarding the block parameters, which can be used by the user to construct an equivalent Activate diagram within the Super Block. The following is a list of some widely-used unsupported basic Simulink block types: – Assertion In most cases, this block can be implemented by testing the input signal using an IfThenElse block and connecting of one of its output activation ports to an End block. – Assignment An assignment block is available in Activate with similar features but the automatic translation is not available. – Buffer This block may be replaced with the Buffer or SerialToParallel block in Activate, in many cases despite significant semantic differences. – DataStoreMemory, DataStoreRead, DataStoreWrite These blocks are not available in Activate. Similar functionalities can be obtained by using a DiscreteDelay block to store a value and SetSignal and GetSignal blocks. Note, however, that SetSignal and GetSignal blocks do not communicate across the boundaries of Atomic Super Blocks. – DiscreteFir – ForIterator, WhileIterator, ForEach Iterator blocks are not currently supported and are difficult to support, however, iteration in Activate may be implemented using the RepeatActivation block. – FromFile, ToFile File I/O blocks exist in Activate and can often be used as replacement for these blocks but the differences are such that an automatic translation is difficult to implement. – Interpolation_n_D – LookupNDDirect – ModelReference A similar block is available in Activate but it is not used for automatic translation. – PermuteDimensions – PreLookup – SecondOrderIntegrator – ArithShift – Find • Unsupported features: – Matrices with more than 2 dimensions: Activate signals are two dimensional.

426

15 Other Activate Functionalities

– Fixed point arithmetic: Fixed points are not currently available in Activate so Simport does not translate this information. – int64 and uint64 data types: – Multiple configuration settings: Activate does not support multiple configurations. The simulation parameters are only partially imported since the available solvers in the two environments are not similar.

15.5.2 Simport Interface Once installed, Simport can be used through the pull-down menu Import. After designating the mdl or slx file to import, user may select one or more matlab script files (called companion files) to be used during the import process. These files should contain the definition of Simulink model parameters. These definitions are included in the resulting Activate model; unlike Simulink, Activate models contain in general the definition of all the parameters used within the model. After the selection of the companion file(s) (if any), the import can be initiated. This creates the corresponding Activate model, which is loaded in the environment. The import can be initiated also by simply opening an mdl or slx file using the standard file open menu. This could be used only if no companion files need to be specified. In case the Simulink diagram contains blocks that Simport is not able to translate (thus creating an empty Super Block for each), a warning popup GUI provides the list of these Super Blocks. This GUI provides direct access to the Super Blocks for user inspection and modification. The translated model is a standard Activate model not requiring any special libraries. It can be saved and used in any Activate environment, even if Simport is not installed.

15.6 Co-simulation 15.6.1 FMI The Functional Mock-up Interface (or FMI) is a standard developed to facilitate model exchange and co-simulation between different simulation tools. This is done by defining a common interface to be used in the export and import of model components from one tool to another. The imported/exported component, called an FMU (Functional Mock-up Unit) is packaged in a compressed file containing: • XML file. It contains in particular the definition of the variables used in the FMU,

15.6 Co-simulation

427

• C code or shared libraries. They implement the APIs required by the solvers to interact with the FMU at run time. They represent the dynamics (differential equations) of the component, • Optional data. In some cases additional information is packaged inside the FMU such as documentation, parameter tables, etc. An FMU may be used both in model exchange and co-simulation modes. In model exchange mode, the FMU can be compared to an Activate block with continuoustime dynamics. When imported into a simulation environment and placed inside a model, it provides the component equations to the environment to be simulated along with the rest of the model to the environment’s simulation solver. In co-simulation mode, the FMU contains its own solver used to perform continuous-time simulation. When imported in a simulation environment and placed inside a model, its differential equations are not visible to the environment. It can be compared to an Activate block with discrete-time dynamics. The solution of the dynamics of the FMU from one discrete-time instant to the next is obtained by the solver packaged inside the FMU and remains transparent to the simulation environment. Activate supports both model exchange and co-simulation of FMUs. The FMI standards FMI-1.0 and FMI-2.0 are supported. Specification documents of various FMI standards are available from www.fmi-standard.org. The import of FMUs in Activate is done through the block FMU available in the CoSim - ulation palette. Thus the imported FMU component is seen as a block in the Activate environment. Even though in most cases this block could be a basic block, the actual implementation is done with a programmable Super Block in order to fully take advantage of the output-input dependency information provided by the FMU.1 The underlying implementation, however, should not matter to the end user; additional information can be found in [44].

15.6.2 MotionSolve MotionSolve is a multibody mechanical system modeler and simulator. It is widely used in particular in automotive and aerospace industries. MotionSolve provides a specialized graphical editor for building multibody mechanical systems. Activate provides co-simulation blocks with MotionSolve. A typical application would use Activate for designing controllers for mechanical systems modeled in MotionSolve. Two special blocks for co-simulating with MotionSolve, MotionSolve and MotionSolveSignals, are provided in the CoSimulation palette. The MotionSolve model can be designated in these blocks both as MotionSolve XML or MotionView mdl files. In case a MotionView mdl file is used, the MotionView product can be invoked from 1 Unlike

in Activate where the output-input dependency (feedthrough) is a property of the inputs alone (an input has this property if any output depends on it) the FMU provides the dependency property for all input-output pairs.

428

15 Other Activate Functionalities

within the Activate blocks to view and edit the MotionView model. When the Activate model is simulated, the MotionView mdl file is converted into a MotionSolve XML file. The MotionSolve model must contain Control_PlantInputs and Control_PlantOutputs, which are associated with block input and output port signals. These signals represent in general forces or torques, for inputs and measured outputs, such as displacements or velocities, for outputs. The use of these co-simulation blocks requires that the Altair MotionSolve solver be installed on the system.

15.6.3 HyperSpice HyperSpice, the Altair Spice solver, is a high performance electrical simulator based on the Spice language dedicated to electrical circuit simulation in DC, Transient and AC modes. HyperSpice has an interface to Berkeley device models and can handle the BSIM series of MOS models. Activate provides a block for co-simulation with HyperSpice. The SpiceCustomBlock is provided in the CustomBlocks palette and is similar to MoCustomBlock presented in Section 14.4.1. The circuit description however is defined as a Spice Netlist. Another difference between the two blocks is that the circuit model defined in the SpiceCustomBlock is co-simulated with Activate thanks to the HyperSpice simulator, as opposed to the MoCustomBlock, which is transformed into an FMI in model exchange mode. This difference is transparent to the user. This functionality requires that HyperSpice be installed.

Appendix A

Computational Function C APIs

C language APIs provide information about the number of inputs and outputs, their sizes and types. They also provide pointers to the corresponding data for reading and writing. See Table A.1 for the list of available C language APIs used to inquire about the inputs and the outputs of the block and a short description of each one. The APIs needed to process the block input and output activation information are described in Table A.2. The C APIs giving access to various block parameters are given in Table A.3. An Activate block can have continuous-time and discrete-time states. The block can also create additional work spaces by using memory allocation. The APIs in Table A.4 can be used to access the block structure fields associated with states and workspaces. The zero-crossing and mode selection are advanced features that are used in blocks with non-smooth dynamics. The associated APIs are given in Table A.5. All these APIs are also available in OML and can be used when the block’s computational function is an OML function. The details are provided in the Activate documentation. In addition to the above APIs, the vss_block4.h header file provides utility functions to interact with the simulator in the computational functions. • int isinTryPhase(blk); This API returns 1 or 0 depending on whether the simulator is calling the block computational function in try phase or non try phase. • int isExitInitialization(blk); At the end of the initialization stage where initially active blocks’ computational functions are called in try phase, possibly multiple times, these functions are called once in non try phase mode for OutputUpdate, and if required, StateUpdate and EventScheduling. The stage is called exit initialization. This API returns 1 or 0 depending on whether the simulator is in exit initialization stage or not. • int areModesFixed(blk); This API returns 1 or 0 depending on whether the simulation is calling the block computational function in fixed mode phase or non fixed mode phase. © Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3

429

430

Appendix A: Computational Function C APIs

Table A.1 C APIs corresponding to block regular inputs and outputs Macro Type Description GetNin(blk) GetInPortRows(blk,x)

int int

GetInPortCols(blk,x)

int

GetInPortSize(blk,x,y)

int

GetInType(blk,x)

int

GetInPortPtrs(blk,x)

void *

GetRealInPortPtrs(blk,x)

double *

GetImagInPortPtrs(blk,x)

double *

Getint8InPortPtrs(blk,x)

char *

Getint16InPortPtrs(blk,x)

short *

Getint32InPortPtrs(blk,x)

long *

Getuint8InPortPtrs(blk,x)

unsigned char *

Getuint16InPortPtrs(blk,x)

unsigned short *

Getuint32InPortPtrs(blk,x)

unsigned long *

GetBoolInPortPtrs(blk,x)

signed long *

GetSizeOfIn(blk,x)

int

GetNout(blk) GetOutPortRows(blk,x)

int int

GetOutPortCols(blk,x)

int

GetOutPortSize(blk,x,y)

int

GetOutType(blk,x) GetOutPortPtrs(blk,x) GetRealOutPortPtrs(blk,x)

int void * double *

the number of regular input ports the number of rows (first dimension) of the regular input port numbered x the number of columns (second dimension) of the regular input port numbered x the regular input port size numbered x (y = 1 for the first dimension, y = 2 for the second dimension) the type of the regular input port numbered x the regular input port pointer of the port number x the pointer of real part of the regular input port number x a pointer to the imaginary part of the regular input port number x a pointer to the int8 typed regular input port number x a pointer to the int16 typed regular input port number x a pointer to the int32 typed regular input port number x pointer to the uint8 typed regular input port number x pointer to the uint16 typed regular input port number x a pointer to the uint32 typed regular input port number x a pointer to the int32 typed regular input port number x the size of the type of the regular input port number x in bytes the number of regular output ports number of rows (first dimension) of the regular output port number x the number of columns (second dimension) of the regular output port number x the size of the regular output port number x (y = 1 for the first dimension, y = 2 for the second dimension) the type of the regular output port number x a pointer to the regular output port number x a pointer to the real part of the regular output port number x (continued)

Appendix A: Computational Function C APIs Table A.1 (continued) Macro

431

Type

Description

GetImagOutPortPtrs(blk,x)

double *

Getint8OutPortPtrs(blk,x)

char *

Getint16OutPortPtrs(blk,x)

short *

Getint32OutPortPtrs(blk,x)

long *

Getuint8OutPortPtrs(blk,x)

unsigned char *

Getuint16OutPortPtrs(blk,x)

unsigned short *

Getuint32OutPortPtrs(blk,x)

unsigned long *

GetBoolOutPortPtrs(blk,x)

signed long *

GetSizeOfOut(blk,x)

int

a pointer to the imaginary part of the regular output port number x a pointer to the int8 typed regular output port number x a pointer to the int16 typed regular output port number x a pointer to the int32 typed regular output port number x a pointer to the uint8 typed regular output port number x a pointer to the uint16 typed regular output port number x a pointer to the uint32 typed regular output port number x a pointer to the int32 typed regular output port number x the size of the type of the regular output port number x in bytes

Table A.2 Activation related C APIs Macro Type GetEventCode(blk) GetNevOut(blk) GetNevOutPtrs(blk) GetInfoPeriod(blk) GetInfoOffset(blk)

int int double * double * double *

Description nevprt, the input activation code the number of activation output ports a pointer to the activation output register the period of periodic block activation the offset of periodic block activation

• void DoColdRestart(blk); This API forces the solver to do a cold restart. It should be used in situations where the block creates a non smooth signal. Note that in most situations, non smooth situations are detected by zero-crossings and this function is not needed. This function is used in very exceptional situations. • double GetVssTime(blk); This function returns the current time of the simulation. • double GetVssInitialTime(blk); This function returns the initial time of the simulation. • double GetVssFinalTime(blk); This function returns the final time of the simulation. • int GetSimulatorSimulationNumber(blk); This function returns an integer: the block index in the compiled structure. Each

432

Appendix A: Computational Function C APIs

Table A.3 C APIs for obtaining block parameter values Macro Type Description GetNipar(blk) GetIparPtrs(blk) GetNrpar(blk) GetRparPtrs(blk) GetNopar(blk) GetOparType(blk,x) GetOparSize(blk,x,y)

GetOparPtrs(blk,x) GetRealOparPtrs(blk,x) GetImagOparPtrs(blk,x) Getint8OparPtrs(blk,x) Getint16OparPtrs(blk,x) Getint32OparPtrs(blk,x) Getint64OparPtrs(blk,x) Getuint8OparPtrs(blk,x) Getuint16OparPtrs(blk,x) Getuint32OparPtrs(blk,x) Getuint64OparPtrs(blk,x) GetStringOparPtrs(blk,x) GetSizeOfOpar(blk,x)

int int * int double * int int int

the number of integer parameters a pointer to the integer parameters register the number of real parameters a pointer to the real parameters register the number of object parameters the type of object parameters number x the size of object parameters number x (y = 1 for the first dimension, y = 2 for the second dimension) void * a pointer to the object parameters number x double * a pointer to the real object parameters number x double * a pointer to the imaginary part of the object parameters number x char * a pointer to the int8 typed object parameters number x short * a pointer to the int16 typed object parameters number x long * a pointer to the int32 typed object parameters number x signed long long * a pointer to the int64 typed object parameters number x unsigned char * a pointer to the uint8 typed object parameters number x unsigned short * a pointer to the uint16 typed object parameters number x unsigned long * a pointer to the uint32 typed object parameters number x unsigned long long a pointer to the uint64 typed object * parameters number x char * a pointer to the char typed object parameters number x int the size of the object parameters number x

block in the simulated diagram has a single index, and blocks are numbered from 1 to nblk (the total number of blocks in the compiled structure). • void SetBlockError(blk, int); Function to set a specific error number during the simulation for the current block. If used, after the execution of the computational function of the block, the simulator ends and returns an error message associated with the number given as integer argument. The integers 1 and 4 are used respectively to indicate that the system

Appendix A: Computational Function C APIs Table A.4 States and workspace C APIs Macro Type GetNstate(blk) GetState(blk) GetDerState(blk)

int double * double *

GetResState(blk)

double *

GetXpropPtrs(blk)

int *

GetNdstate(blk) GetDstate(blk) GetNoz(blk) GetOzType(blk,x) GetOzSize(blk,x,y)

int double * int int int

GetOzPtrs(blk,x) GetRealOzPtrs(blk,x) GetImagOzPtrs(blk,x)

void * double * double *

Getint8OzPtrs(blk,x)

char *

Getint16OzPtrs(blk,x)

short *

Getint32OzPtrs(blk,x)

long *

Getuint8OzPtrs(blk,x)

unsigned char *

Getuint16OzPtrs(blk,x)

unsigned short *

Getuint32OzPtrs(blk,x)

unsigned long *

GetSizeOfOz(blk,x) GetWorkPtrs(blk)

int void *

433

Description the size of the continuous-time state vector a pointer to the continuous-time state a pointer to the derivative of the continuous-time state a pointer to the residual of the continuous-time state (used only for implicit blocks) a pointer to the continuous-time state properties vector the size of the discrete-time state vector a pointer to the discrete-time state the number of object states the type of object state number x the size of object state number x (y = 1 for the first dimension, y = 2 for the second dimension) a pointer to the object state number x a pointer to the real object state number x a pointer to the imaginary part of the object state number x a pointer to the int8 typed object state number x a pointer to the int16 typed object state number x a pointer to the int32 typed object state number x a pointer to the uint8 typed object state number x a pointer to the uint16 typed object state number x a pointer to the uint32 typed object state number x the size of the object state number x a pointer to the Work space

cannot allocate the requested memory and that the input of the block is out of its domain of definition. • void Coserror(block, char *fmt,...); Function to return a specific error message in the OML window. If used, after the execution of the computational function of the block, the simulator will end and will return the error message specified in its argument (of type char*).

434

Appendix A: Computational Function C APIs

Table A.5 Zero-crossing and mode related C APIs Macro Type Description GetNg(blk) GetGPtrs(blk) GetJrootPtrs(blk)

int double * int *

GetNmode(blk) GetModePtrs(blk)

int int *

the number of zero-crossing surfaces a pointer to the zero-crossing vector a pointer to jroot, the vector that indicates which surfaces have been crossed and in which direction the number of modes a pointer to the mode register

• void *vss_malloc(blk, size_t); This function is used to do allocation of memory, for use over the course of simulation, inside the computational function of the block and in particular in the Initialization flag. The returned pointer can be stored in the work pointer obtained by GetWorkPtrs. This allocated memory is freed automatically by the simulator at the end of the simulation. • void *vss_tmp_malloc(blk, size_t); This function is similar to vss_malloc but the content of the allocated memory is not preserved from one call to the next. This memory can be used as temporary workspace needed for example to compute the SVD of a matrix. The simulator may provide the same memory space to various blocks during simulation. The list of APIs presented here is not exhaustive. The full list is available in the Activate documentation.

References

1. Altair Engineering, Extended Definitions for Altair Activate 2019 (2018). Available by download 2. U.M. Ascher, R.M.M. Mattheij, R.D. Russell, Numerical Solution of Boundary Value Problems for Ordinary Differential Equations (SIAM, Philadelphia, 1995) 3. K.J. Åström, T. Hägglund, PID Controllers: Theory, Design, and Tuning (Instrument Society of America, Research Triangle Park, 1995) 4. A. Bartlomiejczyk, H. Leszczynski, Method of lines for physiologically structured models with diffusion. Appl. Numer. Math. 94, 140–148 (2015) 5. P. Benner, V. Mehrmann, V. Sima, S.V. Huffel, A. Varga, SLICOT - A Subroutine Library in Systems and Control Theory, chap. 10 (Birkauser, 1999), pp. 499–539 6. A. Benveniste, Compositional and uniform modeling of hybrid systems. IEEE Trans. Autom. Control 43, 579–584 (1998) 7. J. Betts, S.L. Campbell, K. Thompson, Optimal control of delay partial differential equations, in Control and Optimization with Differential-Algebraic Constraints (Siam, Philadelphia, 2012), pp. 213–231 8. J.T. Betts, Practical Methods for Optimal Control and Estimation Using Nonlinear Programming, 2nd edn. (SIAM, Philadelphia, 2009) 9. K.E. Brenan, S.L. Campbell, L.R. Petzold, The Numerical Solution of Initial Value Problems in Differential-Algebraic Equations (SIAM, Philadelphia, 1996) 10. D. Brown, A. Herbison, J. Robinson, R. Marrs, G. Leng, Modelling the luteinizing hormonereleasing hormone pulse generator. Neuroscience 63(3), 869–879 (1994) 11. S.L. Campbell, J.-P. Chancelier, R. Nikoukhah, Modeling and Simulation in Scilab/Scicos with ScicosLab 4.4 (Springer, New York, 2009) 12. S.L. Campbell, C.D. Meyer jr., Generalized Inverses of Linear Transformations (SIAM, Philadelphia, 2009) 13. S.L. Campbell, V. Mehrmann, P. Kunkel, Regularization of linear and nonlinear descriptor systems (SIAM, Philadelphia, 2012), pp. 17–36 14. M. Caracotsios, W.E. Stewart, Sensitivity analysis of initial value problems with mixed ODEs and algebraic equations. Comp. Chem. Eng. 9(4), 359–365 (1985) 15. J. Chancelier, R. Nikoukhah, A novel code generation methodology for block diagram modeler and simulators scicos and VSS, in CoRR (2015), arXiv:1510.02789 16. M. Crow, M. Iliˇc, The waveform relaxation method for systems of differential/algebraic equations. Math. Comput. Model. 19, 67–84 (1994) 17. C. documentation, Writing an oml toolbox using the binary-compatible interface. Technical report, Altair Corporation (2017)

© Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3

435

436

References

18. K. Drake, Analysis of Numerical Methods for Fault Diagnosis and Model Identification in Linear Systems with Delays,. Ph.D. thesis, North Carolina State University, Raleigh, NC, USA (2003) 19. H. Elmqvist, T. Henningsson, M. Otter, Systems modeling and programming in a unified environment based on julia, in Proceedings of the ISoLA 2016 - 7TH International Symposium On Leveraging Applications of Formal Methods, Verification and Validation (2016), pp. 198– 217 20. H. Elmqvist, T. Henningsson, M. Otter, Innovations for future modelica, in Proceedings of the Modelica Conference - 12th International Modelica Conference (2017) 21. H. Elmqvist, M. Otter, S.E. Matsson, Fundamentals of synchronous control in modelica, in Proceedings of the 9th International MODELICA Conference; Munich; Germany; September 3–5 (2012), pp. 15–26 22. P. Fritzson, Principles of Object-Oriented Modeling and Simulation with Modelica 2.1 (WileyIEEE Press, Piscataway, 2004) 23. P. Fritzson, P. Aronsson, H. Lundvall, The openmodelica modeling, simulation, and development environment, in Proceedings of the 46th Conference on Simulation and Modeling (SIMS05) (2005), pp. 83–90 24. F.R. Gantmacher, The Theory of Matrices (Chelsea, New York, 1959) 25. S. George, Application note: Add custom/user defined functions to st compose using c/c++ codes from visual studio 2015. Technical report, Altair Corporation, August 2017 26. E. Hairer, S.P. Norsett, G. Wanner, Solving Ordinary Differential Equations I. Nonstiff Problems, vol. 8, Springer Series in Computational Mathematics (Springer, Berlin, 1993) 27. E. Hairer, G. Wanner, Solving Ordinary Differential Equations II. Stiff and DifferentialAlgebraic Problems, vol. 14, Springer Series in Computational Mathematics (Springer, Berlin, 1991) 28. Y. Iskandarani, H.R. Karimi, Hysteresis modeling for the rotational magnetorheological damper, in Recent Researches in Geography, Geology, Energy, Environment and Biomedicine: Proceedings of the 4th WSEAS International Conference on Engineering Mechanics, Structures, Engineering Geology (EMESEG ’11) Pro. Wseas LLC (2011) 29. A. Kandler, R. Unger, Population dispersal via diffusion-reaction equations. Technical report, Institute of Archaeology, University College London, 31-34 Gordon Square, London WC1H 0PY, UK (2010) 30. H.B. Keller, Numerical Solution of Two Point Boundary Value Problems (SIAM, Philadelphia, 1976) 31. D.E. Knuth, The Art of Computer Programming, Volume 1: Fundamental Algorithms, 3rd edn. (Addison Wesley Longman Publishing Co. Inc, Redwood City, 1997) 32. P. Kunkel, V. Mehrmann, Differential-Algebraic Equations: Analysis and Numerical Solution (European Mathematical Society, Zurich, 2006) 33. E.A. Lee, S.A. Seshia, Introduction to Embedded Systems: A Cyber-physical Systems Approach (2011), www.LeeSeshia.org 34. F.L. Lewis, D.L. Vrabie, V.L. Syrmos, Optimal Control (Wiley, New York, 2012) 35. T. Maly, L. Petzold, Numerical methods and software for sensitivity analysis of differentialalgebraic systems. Appl. Numer. Math. 20, 57–79 (1996) 36. M. Najafi, Z. Benjelloun-Dabaghi, Modeling and simulation of a drilling station in modelica, in Proceedings of 16th Mediterranean Conference on Control and Automation, Ajaccio, France (2008) 37. M. Najafi, S. Furic, R. Nikoukhah, Scicos: a general purpose modeling and simulation environment, in Proceedings of 4th International Modelica Conference, Germany (2005) 38. M. Najafi, R. Nikoukhah, Modelica components and toolboxes in scicos, in Proceedings of Scilab Workshop, Foshan China (2007) 39. M. Najafi, X. Shen, Z. Benjelloun-Dabaghi, P. Moulin, Simulation of the mean-value internal combustion engine in modelica, in Proceedings of 6th MATHMOD, Vienna, Austria (2009) 40. R. Nikoukhah, Extensions to modelica for efficient code generation and separate compilation, in Proceedings of ECOOP, Berlin, Germany (2007)

References

437

41. R. Nikoukhah, Hybrid dynamics in modelica: should all events be considered synchronous, in SNE Journal, Special Issues on OO/Hybrid/Structural Dynamic Modeling 17 (2008) 42. R. Nikoukhah, Integrated optimization in system models, in Proceedings of The 3rd International Workshop on Simulation at the System Level for Industrial Applications; Ecole Normale Supérieure de Cachan, France; October 14–16 (2015) 43. R. Nikoukhah, S. Furic, Synchronous and asynchronous events in modelica: proposal for an improved hybrid model, in Proceedings of Modelica Conference, Bielefeld, Germany (2008) 44. R. Nikoukhah, M. Najafi, F. Nassif, A simulation environment for efficiently mixing signal blocks and modelica components, in Proceedings of the Modelica conference - 12th International Modelica Conference (2017) 45. M.J.D. Powell, The bobyqa algorithm for bound constrained optimization without derivatives. Technical Report DAMTP2009/NA06, Department of Applied Mathematics and Theoretical Physics, Cambridge University, June 2009 46. W.E. Schiesser, The Numerical Method of Lines (Academic Press, San Diego, 1991) 47. L.F. Shampine, S. Thompson, Solving delay differential equations with dde23. Technical report, Radford University, March 2000 48. A. Sutherland, Course note: CE 295 - Energy systems and control (2016), https://ecal. berkeley.edu/files/ce295/. Last visited on 2018/03/31 49. P. Weis, Simport: a simulink model importer for scicos, in Proceedings of The 3rd International Workshop on Simulation at the System Level for Industrial Applications; Ecole Normale Supérieure de Cachan, France; October 14–16 (2015) 50. Wikipedia. Golden section search. https://en.wikipedia.org/wiki/Golden-section_search. Accessed 22 May 2018 51. J.B. Ziegler, N.B. Nichols, Optimum settings for automatic controllers. ASME Trans. 64, 759– 768 (1942)

Index

Symbols %, 9 &&, 23 ,, 394 ,, 12 ., 16 :, 11 %{ %}, 9 &, 16, 23 ;, 12 ~, 16, 23 =, 23

A abcd, 169 abs, 15 AbsTol, 69 acker, 89 Ackermann’s algorithm, 89 acos, 10, 192 acosd, 10 acosh, 10, 192 Activate model parameters, 169 Activation always, 255 during, 310 event, 255 inheritance, 258 initial, 255

link, 254 periodic, 269 port, 254 primary, 266 signal, 158, 254 synchronous, 256 timing, 256 Activation signals, 171 Activation source primary, 185, 262, 276 secondary, 185, 262 Active always, 255 initially, 255 addpath, 29 AddToBase, 207 addToolbox, 40 Algebraic loop, 289 Algebraic variable, 66 all, 24 Always active, 260 and, 23 Animation, 422 append, 85 Application Programming Interface (API), 253 area, 48 asin, 10, 192 asind, 10 asinh, 10, 192 atan, 10, 192 atan2, 10, 192 atanh, 10, 192 Atomic, 272, 274, 417 Atomic Unit (AU), 252, 253, 364 augstate, 85

© Springer Nature Switzerland AG 2018 S. L. Campbell and R. Nikoukhah, Modeling and Simulation with Compose and Activate, https://doi.org/10.1007/978-3-030-04885-3

439

440 B balreal, 81 Bang-bang control, 131 bar, 48, 53 Bar graphs, 48 Base environment, 207 Batch reactor, 119 bdeCreateSimulationObject, 342 bdeGetCurrentModel, 348, 382 bdeGetModelFilePath, 382 BDF, 68 bdschur, 88 Bike model, 402 bilin, 81 Binary interface, 41 blanks, 22 Block AndActivations, 255 Anim2D, 202, 303, 422 basic, 364 builder, 361 BusCreator, 177 BusExtractor, 177 CCustomBlock, 363 conditional, 262 Constant, 165, 261 Constraint, 249 DiscreteDelay, 184, 256 Display, 218 EdgeTrigger, 266 end, 205 EventClock, 267 EventDelay, 258 EventPortZero, 265, 279, 285, 323 EventUnion, 258 EventVariableDelay, 218 ExtractActivation, 177 feedthrough property, 255 FFT, 234 FixedDelay, 170 FromBase, 207 FromModelica, 389 Gain, 165 GetSignal, 177, 281, 286 hierarchy, 173 Hysteresis, 221 IfThenElse, 183, 262, 285, 323 IncludeDiagram, 381 InitialEvent, 258 initialization, 365 Integrator, 161, 164, 237 interface, 389 internal state, 256

Index LastInput, 230 library, 379 MathExpression, 226, 250 MatrixExpression, 165, 166, 226 MoCustomBlock, 395, 428 MoCustomComponent, 403 Mux, 161, 164 name, 159 OmlCustomBlock, 363, 369 order, 255 Programmable Super Block, 252, 361 RandomGenerator, 236 RepeatActivation, 269, 271, 273 ResampleClock, 266 SampleClock, 234, 266 SampledData, 269, 382 SampleHold, 262 Scope, 159, 164 ScopeXY, 165 Selector, 280 SetSignal, 177, 281, 286 SignalIn, 207 SignalOut, 207 SineWaveGenerator, 159 SquareWaveGenerator, 184 Super Block, 173, 258 SwitchCase, 183 SyncTag, 267 ToBase, 207 Toggle, 250 ToModelica, 389 type, 159 VariableDelay, 170 VectorScope, 235 virtual, 177 ZeroCross, 267 ZeroCrossDown, 267 zero-crossing, 221 ZeroCrossUp, 267 Block parameters, 161 Boolean variable, 23 Bouc-Wen model, 190 Boundary condition, 62 Boundary Value Problems (BVP), 63 multiple shooting, 75 shooting methods, 75 break, 35

C c2d, 81, 168 Call array, 26 Car model, 294, 325, 374

Index care, 85 catch, 32 CauerLowPassSC, 390 cd, 29 Cell, 26 Centered difference, 139 Characteristic polynomial, 88 Characters, 21 chol, 17 Class double, 15 string, 21 class, 9, 15 clc, 8 clear, 9, 29 clf, 47 Code generator, 417 Cold restart, 366, 368 Color black, 57 blue, 47, 57 cyan, 47 green, 47, 57 magenta, 47, 57 red, 47, 57 white, 47, 57 yellow, 47 Command line window clear, 8 Comment, 9 block, 9 Commented out code, 9 Comparison operators, 23 compreal, 82, 83 Computational function, 364 API, 429 flag, 429 Concatenation column, 12 row, 12 cond, 18 Condition number, 18 Conditional subsampling, 183, 262 Constraint bound, 98 box, 98 general nonlinear, 98 linear inequality, 98 Continuous Riccati equation, 85 Contour, 52 contour, 48, 140 Contour plots, 48 Contour surface plots, 48

441 contour3, 48, 52, 141 contr, 90 Control flow else, 31 elseif, 31 end, 31 if, 31 Control parametrization, 126 Control Toolbox, 75, 78 Controllability, 89 Controllability staircase form, 89 conv, 25 ’cos’, 91 cos, 10, 192 cosh, 10, 192 covar, 93 Covariance, 93 Cruise control, 238 ctrb, 89 ctrbf, 89 Cyber-physical, 157

D d2c, 81 dare, 86 Data types, 364 db2mag, 96 DC gain, 93 dcgain, 93 Debug CSV file, 422 file, 421 file view, 422 mode, 421 Debugger, 421 Decibels, 96 Decimation operation, 262 Delay, 144, 170 random, 172 Descriptor system, 81 det, 18 Determinant, 18 dhinf, 95 diag, 13, 17, 20 Diagonal, 17, 20 Diagonalization, 88 Diagram context, 169, 251 Difference equation, 64, 76 Differential Algebraic Equation (DAE), 65, 79, 118 fully implicit, 67

442 index reduction, 303 index zero, 74 semiexplicit, 67 Differential variable, 66 Discrete-time LQR, 93 Discrete-time Riccati, 86 disp, 23, 43 Display, 101, 104 dlqr, 93 dlyap, 86 dlyapchol, 86 Down-sampling, 234 dscr, 169 dss, 81 dds2ss, 81 dssdata, 80 Dymola, 395, 408 Dynamic link library, 42

E e, 11 eig, 11, 17 Eigenvalue assignment, 168 else, 31 elseif, 31 end, 36 Epsilon eps, 10 Equation discrete generalized Lyapunov, 86 discrete Lyapunov, 86 discrete Sylvester, 86 generalized Lyapunov, 86 Lyapunov, 86 nonlinear, 99 Sylvester, 86 Equilibrium point, 357 Error algebraic loop, 268 error, 33 Esterel, 157 estim, 94 Euler-Lagrange equation, 196 Evaluation, 365 Evaluation, 252 Event, 67, 173 asynchronous, 266 entry, 308 exit, 310 firing, 256 synchronous, 266 every, 24

Index Exact discretization, 269 exist, 9 Existence and uniqueness, 62 exp, 13, 15, 87 expm, 13, 17, 87 Extended Kalman Filter, 226, 229 External-context, 208, 342, 344, 348 extrap, 49 eye, 13

F Factorial, 36 Failure detection, 234 false, 23 Fast Fourier Transform (FFT), 234 fclose, 45 Feedthrough, 257 figure, 47 File extension c, 419 csv, 422 dll, 40, 42, 380, 420 lib, 380 mat, 46, 170 mdl, 424, 426, 427 oml, 29 scb, 379 scm, 164, 348 scopt, 415 slx, 424, 426 so, 40, 42 XML, 427 fill, 57 find, 24 First-order, 62, 65 fix, 13 FMI, 420, 426 fmincon, 100, 118 fminunc, 100, 118 FMU, 426, 427 fopen, 44 For loop, 33 Form companion, 82 format, 10, 44 Format 7.3, 45 Fortran, 40 fprint, 44 fprintf, 44 fread, 45 Free activate, 4 Free compose, 4

Index fsolve, 105, 120 Function anonymous, 28 C++, 40 definition, 36 function, 36 handle, 28 return, 35 fwrite, 45

G ga, 100, 103 gaoptimset, 103 Generations, 104 Genetic algorithm, 100, 103 gensing, 91 GetFromBase, 207 Ghost points, 194 global, 38 Golden-section, 97 Golden-section search, 273 gr, 17 GradConstr, 100 Gradient, 99 computation, 118 GradObj, 101 gram, 87 Grammian controllability, 87 observability, 87 Graphical editor, 159

H h2_norm, 95 Handle, 28 hankel, 96 Hankel singular values, 96 Heat equation, 138 Help manual, 8 help, 8 hinf, 95 h_norm, 95 hist, 52 hold, 48 Hormone pulse generator, 236 hsvd, 96 Hybrid, 67 Hybrid systems, 78

443 I if, 23, 31 Implicit differential equation, 74 Implicit semiexplicit DAE, 66 Index of a DAE, 66 Inf, 35 Initial condition, 62 consistent, 66, 120 Initially active, 261 InitialPenalty, 104 InitialPopulation, 104 input, 44, 373 Integrator fixed step, 73 Interpolation interp1, 48, 128 interp2, 48, 50 not a knot, 50 inv, 17, 93 Inverse, 93 Inverted pendulum, 349 inclined surface, 355 isbool, 9 iscell, 9 ischar, 9 iscomplex, 9 isct, 80 isctrb, 89 isdt, 80 isempty, 9 isfinite, 9 isglobal, 38 isinf, 9 isnan, 9 isnumeric, 9 isobsv, 89 isreal, 9 issiso, 88

J Jacobian, 99 Jacobian, 69, 101 Jitter, 172, 419 Jroot, 365

K Kalman, 94 kalman, 94 Kirchoff’s law, 387 kron, 17, 20 Kronecker, 20

444 L Lagrangian, 196 Laplace, 153 Least squares, 16 length, 21, 22 Library Electrical.Analog.Semiconductor, 404 linear, 49 Linear DAE, 74 Linear Quadratic Regulator (LQR), 92 Linear system, 74, 167 Linear Time Invariant (LTI), 167, 347 Linearization, 347 Linearization API, 348 linsolve, 17, 19 linspace, 13 Little’s theorem, 176 load, 45 log, 87 loglog, 48 Logical or, 16 logm, 87 logspace, 13 Lorenz attractor, 165 lqr, 92 lqry, 93 lsim, 91 lsqcurvefit, 107 LTI system, 349 lu, 17 Luenberger observer, 167 Lustre, 157 lyap, 86 lyapchol, 86

M Machine precision, 10 mag2db, 96 Maple, 352 Masking, 254 auto, 254, 405 Matrix, 11 block diagonal, 86 concatenation, 12 controllability, 89 exponential, 13, 87 Hankel, 96 how stored, 12 multiplication, 16 observability, 89 square root, 86 term by term, 16

Index three dimensional, 15 Vandermonde, 16 Matrix log, 87 Matrix palette, 165 max, 19 MaxFunEvals, 100 MaxIter, 101 Mechatronics, 157 meshgrid, 50 Method of steps, 145 Microsoft Visual Compiler, 42 Mimima local, 99 min, 19 minreal, 80 Minima global, 99 Minimal realization, 80 minss, 80 Model fisheries, 219 Initialization, 161, 169, 251, 348 population, 143 predator prey, 219 zero-pole-gain, 88 Modelica, 157, 387, 389 electrical, 389 signal, 389 Modelica Standard Library (MSL), 392 Modeling component-level, 387 MOL, 138, 193 method of lines, 138 Monte-Carlo simulations, 207 MotionSolve, 427 rmpath, 29 Multibody mechanical system, 427 N nargin, 38 nargout, 38 Netlist, 428 nevprt, 255 Newton’s method, 100 noextrap, 49 Nonlcon, 103 Norm Frobenius, 93 H 2 , 93 sup, 93 norm, 18, 19, 93 not, 23 nVars, 103

Index O Observability, 89 Observability staircase form, 91 Observer, 167, 223, 349 Observer-based controller, 349 obsv, 89 obsvf, 91 ode15s, 68 ode113, 68 ode15i, 68, 119 ode45, 68 odeset, 68 OML Command Window, 207 ones, 13 Open-loop control, 130 OpenModelica, 395, 405, 408 Optimization, 415 optimset, 101, 106 opts, 19 or, 23 Ordinary Differential Equation (ODE), 62, 397 external, 69 Overlay mode, 413 Overloading, 16 Overshoot, 410

P padecoef, 96 Palettes, 158, 380 ActivationOperations, 183 parallel, 84 parfit, 118 Partial Differential Equation (PDE), 138 path, 29 pause, 39 pchip, 49 PDE with diffusion, 138 Pendulum, 126 Permutation, 271 persistent, 39 pi, 11 pinv, 17 place, 88, 168, 201, 225, 349 Plot parametric, 51 polar, 48 scatter, 48 scatter3, 48 surface, 48 plot, 46, 140 plot3, 47, 48, 140

445 Poisson process, 173 polar, 48 pole, 88 Pole placement, 168, 200, 349 poly, 25, 88 Polygons color, 57 corners, 57 filled, 57 Polynomials multiplication, 25 polyval, 25 PopInitialRange, 104 PopulationSize, 104 POSDEF, 19 Predator-prey system, 147 prescale, 95 prewarp, 81 Program linear, 101 quadratic, 101 semidefinite, 101 Proper, 82 Proportional Integral Derivative (PID), 290, 408 autotuning, 290 ’pulse’, 91 pwd, 29 Q Quadratic regulator, 92 Queuing system, 173 R rand, 13 rank, 18 Reaction diffusion, 142 Realization, 79, 83 minimal, 80 RECT, 19 reg, 94 Regulator, 94 RelTol, 69 reshape, 13, 18 Residual, 74 return, 35 Rocket, 195, 196 Root finding, 67, 75 roots, 25, 88 Rotational inertia, 349 rsf2csf, 94 Run, 30

446 Runge-Kutta-Fahlberg 45, 68

S Saturation, 286 save, 45 saveas, 47 scatter, 48, 54 scatter3, 48, 54 Scheduling table, 253 schur, 18 Schur factorization, 88 Schur form complex, 94 real, 94 Scicos, 157, 391, 423 Scoping rule, 251, 274 Scripts, 29 Select else, 32 semilogy, 48 semilogx, 48 series, 87 Setpoint, 222 Shared object, 40 Signal, 157, 344 typing, 253 Signal processing, 262 Simport, 423 Simscape, 423 Simulation, 91 flag, 364 human in the loop, 369 object, 342 phase, 367 step size, 260 Simulink, 423 ’sin’, 91 sin, 10, 15, 192 Single Input-Single Output (SISO), 82 Singular system, 79 sinh, 10, 192 slice, 15 SLICOT, 40, 78 Solution fundamental, 133 Solver fixed step, 365 step, 365 variable step, 365 Spice, 428 Spline, 128 clamped, 50

Index spline, 49 Spring-damper, 408 sqrt, 10 sqrtm, 86 ’square’, 91 ss, 79 ss2ss, 80 ss2tf, 83 ss_add, 84 ssdata, 80 ss_eq, 85 ss_mul, 84 ss_neg, 85 ss_select, 85 ss_size, 80 Start, 30 State concurrent, 295, 307, 308 exclusive, 307, 308 Stateflow, 423 State machine, 177 State-space form, 75 Stiff, 68 Stop icon, 39 strcat, 22 Stream input, 45 output, 45 strfind, 22 Strings, 21 concatenation, 21 stripblanks, 22 strrep, 22 strsplit, 22 strsubst, 22 strok, 22 strtrim, 22 Structure, 26 fields, 27 structure, 19 Submatrix deletion, 14 extraction, 14 subplot, 59 Subsystem, 85 atomic, 423 enabled, 423 triggered, 423 sum, 19 surf, 48, 141 svd, 18 Switch, 184 switch, 32

Index Synchronism, 183 Synchronization, 183 System augmented, 85 balanced real, 81 equivalent, 80 series connection, 84 single input single output, 88

T Tab Atom, 383 Parameters, 384 Ports, 385 tan, 10, 192 tanh, 10 text, 57 tf, 82 tf2ss, 83 tf2zp, 88 tf2zpk, 88 tf_add, 87 tfdata, 87 tf_eq, 83 tf_mul, 87 tic, 19, 71 Time elapsed, 19 toascii, 22 toc, 19, 71 TolCon, 100, 104 TolFun, 100 TolKKT, 100 tolower, 22 TolX, 100 Torque converter, 239 toupper, 22 trace, 18 Transfer function, 79 add, 87 equality, 83 multiplication, 87 Transpose, 12 ’, 13

447 Triac, 404 tril, 17 triu, 17 true, 23 try, 32 Try mode, 189 tustin, 81

U Unimodal function, 273

V V4 format, 45 V5 format, 45 Van Der Pol oscillator, 70 varargin, 37 varargout, 37 Vector field plot, 58 VirtualBox, 4 vssCreateEvaluator, 342 vssEquilibriumPoint SuperBlock, 348 vssGetTime, 374 vssLinearizeSuperBlock, 348 vssRunSimulation, 342

W Waveform relaxation, 210 While, 35 while, 35 Window command line, 5

Z Zero crossing, 75, 376 internal, 365 zeros, 13 zoh, 81 zpk, 88 zpkdata, 88

Smile Life

When life gives you a hundred reasons to cry, show life that you have a thousand reasons to smile

Get in touch

© Copyright 2015 - 2024 AZPDF.TIPS - All rights reserved.