text: /* Siconos is a program dedicated to modeling, simulation and control
   * of non smooth dynamical systems.
   *
   * Copyright 2021 INRIA.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
  */
  
  /*! \file SiconosGraphs.hpp
   * \brief Definitions of the graphs used in Siconos
   */
  
  #ifndef SimulationGraphs_H
  #define SimulationGraphs_H
  
  #include "SiconosGraph.hpp"
  #include "SiconosProperties.hpp"
  #include "SiconosPointers.hpp"
  #include "SiconosFwd.hpp" // for SP::DynamicalSystem, ...
  #include "SiconosAlgebraTypeDef.hpp" // for VectorOfVectors, ...
  #include "SimulationTypeDef.hpp"
  
  /** the graph structure :
   *
   * InteractionsGraph = L(DynamicalSystemsGraph)
   *
   * where L is the line graph
   * transformation
   *
   *
   * Properties on graph :
   * --------------------
   *
   * The properties on the graph enable to store the data that are specific to a simulation
   * strategy. It avoids to burden the modeling classes that should be as independent as possible from
   * the simulation choices.
   *
   * There are mainly two types of properties
   * <ul>
   * <li>  Mandatory properties DynamicalSystemProperties and InteractionProperties .
   *       These properties are always  instanciated for any kind of simulation.
   *       The accessors to the property are illustrated in the following example :
   *       For a given SP::DynamicalSystem ds and a given graph SP::DynamicalSystemsGraph DSG
   *
   *       DynamicalSystemsGraph::VDescriptor dsv = DSG->descriptor(ds);
   *       SP::OneStepintegrator osi = DSG->properties(dsv).osi;
   * </li>
   * <li> Optional Properties
   *      They are installed thanks to the macro INSTALL_GRAPH_PROPERTIES.
   *
   *      The accessors to the property are illustrated in the following example :
   *      For a given SP::DynamicalSystem ds and a given graph SP::DynamicalSystemsGraph DSG
   *
   *      DynamicalSystemsGraph::VDescriptor dsv = DSG->descriptor(ds);
   *      DSG->name.insert(dsv, name); // insert the name in the property
   *      const std::string& name =  DSG[*dsv]->name;
   *
   *
   * </li>
   * </ul>
   */
  
  /** \struct InteractionProperties mandatory properties for an Interaction  */
  struct InteractionProperties
  {
    SP::SiconosMatrix block;             /**< diagonal block */
    SP::DynamicalSystem source;
    unsigned int source_pos;
    SP::DynamicalSystem target;
    unsigned int target_pos;
    unsigned int absolute_position;      /**< Absolute position of the interaction variables in the unknown vector in osnsp*/
    unsigned int absolute_position_proj; /**< Absolute position of the interaction variables in the unknown vector in osnsp
                                            for projection*/
    bool forControl;                     /**< true if the relation is used to add a control input to a DS */
    SP::VectorOfVectors workVectors;     /**< set of SiconosVector, useful to ensure contiguous memory vectors, used as buffers in OneStepIntegrator classes. */
    SP::VectorOfBlockVectors workBlockVectors;     /**< set of BlockVector, used as buffers in OneStepIntegrator classes. */
    SP::VectorOfSMatrices workMatrices;  /**< Internal buffers used on simulation size, to store jacobians or other temporary matrices. */
  
    ACCEPT_SERIALIZATION(InteractionProperties);
  };
  
  /** \struct DynamicalSystemProperties mandatory properties for a DynamicalSystems */
  struct DynamicalSystemProperties
  {
    SP::SiconosMatrix upper_block;          /**< i,j block i<j */
    SP::SiconosMatrix lower_block;          /**< i,j block i>j */
    SP::VectorOfVectors workVectors;        /**< Used for instance in Newton iteration */
    SP::VectorOfMatrices workMatrices;      /**< Mostly for Lagrangian system.*/
    SP::OneStepIntegrator osi;              /**< Integrator used for the given DynamicalSystem */
    SP::SimpleMatrix W;                     /**< Matrix for integration */
    SP::SimpleMatrix WBoundaryConditions;   /**< Matrix for integration of boundary conditions*/
    SP::SimpleMatrix Winverse;              /**< Matrix for integration */
    unsigned int absolute_position;         /**< Absolute position of the ds variables in the unknown vector in osnsp*/
  //  SP::SiconosMemory _xMemory            /**< old value of x, TBD */
  
    ACCEPT_SERIALIZATION(DynamicalSystemProperties);
  };
  
  // Note FP : workMatrices in DSProperties is used only in  NewmarkAlphaOSI => maybe it should be replaced with interprop workMat?
  
  struct GraphProperties
  {
    bool symmetric;
  
    ACCEPT_SERIALIZATION(GraphProperties);
  };
  
  
  
  class _DynamicalSystemsGraph :
    public SiconosGraph < std::shared_ptr<DynamicalSystem>,
                          std::shared_ptr<Interaction>,
                          DynamicalSystemProperties, InteractionProperties,
                          GraphProperties >
  {
    ACCEPT_SERIALIZATION(_DynamicalSystemsGraph);
  };
  
  
  class _InteractionsGraph :
    public SiconosGraph < std::shared_ptr<Interaction>,
                          std::shared_ptr<DynamicalSystem>,
                          InteractionProperties, DynamicalSystemProperties,
                          GraphProperties >
  {
    ACCEPT_SERIALIZATION(_InteractionsGraph);
  };
  
  struct DynamicalSystemsGraph : public _DynamicalSystemsGraph
  {
    /** optional properties : memory is allocated only on first access */
    INSTALL_GRAPH_PROPERTIES(DynamicalSystems,
                             ((VertexSP, MatrixIntegrator, Ad)) // for ZOH Integration
                             ((VertexSP, MatrixIntegrator, AdInt)) // for ZOH Integration
                             ((VertexSP, MatrixIntegrator, Ld)) // For Observer (ZOH Integration)
                             ((VertexSP, MatrixIntegrator, Bd)) // For Controlled System (ZOH Integration)
                             ((VertexSP, SiconosMatrix, B)) // For Controlled System
                             ((VertexSP, SiconosMatrix, L)) // For Observer
                             ((VertexSP, PluggedObject, pluginB)) // For Controlled System
                             ((VertexSP, PluggedObject, pluginL)) // For Observer
                             ((VertexSP, SiconosVector, e)) // For Observer
                             ((VertexSP, SiconosVector, u)) // For Controlled System
                             ((VertexSP, PluggedObject, pluginU)) // For Controlled System (nonlinear w.r.t u)
                             ((VertexSP, PluggedObject, pluginJacgx)) // For Controlled System (nonlinear w.r.t u); compute nabla_x g(x, u)
                             ((VertexSP, SiconosVector, tmpXdot)) // For Controlled System (nonlinear w.r.t u); tmpXdot = g(x, u)
                             ((VertexSP, SimpleMatrix, jacgx)) // For Controlled System (nonlinear w.r.t u); jacgx = nabla_x g(x, u)
                             ((Vertex, std::string, name)) // a name for a dynamical system
                             ((Vertex, unsigned int, groupId))); // For group manipulations (example assign
                                                                 // a material id for contact law
                                                                 // determination
    // always needed -> DynamicalSystemProperties
  
    /** serialization hooks */
    ACCEPT_SERIALIZATION(DynamicalSystemsGraph);
  
    // to be installed with INSTALL_GRAPH_PROPERTIES
    void eraseProperties(_DynamicalSystemsGraph::VDescriptor vd)
    {
      Ad._store->erase(vd);
      AdInt._store->erase(vd);
      Ld._store->erase(vd);
      Bd._store->erase(vd);
      B._store->erase(vd);
      L._store->erase(vd);
      pluginB._store->erase(vd);
      pluginL._store->erase(vd);
      e._store->erase(vd);
      u._store->erase(vd);
      pluginU._store->erase(vd);
      pluginJacgx._store->erase(vd);
      tmpXdot._store->erase(vd);
      jacgx._store->erase(vd);
      name._store->erase(vd);
      groupId._store->erase(vd);
    }
  };
  
  struct InteractionsGraph : public _InteractionsGraph
  {
    /** optional properties : memory is allocated only on first access */
    INSTALL_GRAPH_PROPERTIES(Interactions,
                             ((Vertex, SP::SimpleMatrix, blockProj))        // ProjectOnConstraint
                             ((Edge, SP::SimpleMatrix, upper_blockProj))    // idem
                             ((Edge, SP::SimpleMatrix, lower_blockProj))  // idem
                             ((Vertex, std::string, name)));
  
    // to be installed with INSTALL_GRAPH_PROPERTIES
    void eraseProperties(_InteractionsGraph::VDescriptor vd)
    {
      blockProj._store->erase(vd);
      name._store->erase(vd);
    }
  
    // to be installed with INSTALL_GRAPH_PROPERTIES
    void eraseProperties(_InteractionsGraph::EDescriptor ed)
    {
      upper_blockProj._store->erase(ed);
      lower_blockProj._store->erase(ed);
    }
  
    /** serialization hooks */
    ACCEPT_SERIALIZATION(InteractionsGraph);
  };
  
  
  
  #endif
  