LCOV - code coverage report
Current view: top level - src/utils/traction_wire - Circuit.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 6 6
Test Date: 2026-07-26 16:30:20 Functions: - 0 0

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    Circuit.h
      15              : /// @author  Jakub Sevcik (RICE)
      16              : /// @author  Jan Prikryl (RICE)
      17              : /// @date    2019-12-15
      18              : ///
      19              : /// @note    based on console-based C++ DC circuits simulator,
      20              : ///          https://github.com/rka97/Circuits-Solver by
      21              : ///          Ahmad Khaled, Ahmad Essam, Omnia Zakaria, Mary Nader
      22              : ///          and available under MIT license, see https://github.com/rka97/Circuits-Solver/blob/master/LICENSE
      23              : ///
      24              : // Representation of electric circuit of overhead wires
      25              : /****************************************************************************/
      26              : #pragma once
      27              : #include <config.h>
      28              : 
      29              : #include <vector>
      30              : #ifdef HAVE_EIGEN
      31              : #ifdef _MSC_VER
      32              : #pragma warning(push)
      33              : #pragma warning(disable: 4127 4464 5031)
      34              : #endif
      35              : // avoid warnings in clang
      36              : #ifdef __clang__
      37              : #pragma clang system_header
      38              : #endif
      39              : #include <Eigen/Dense>
      40              : #include <Eigen/Geometry>
      41              : #include <Eigen/Sparse>
      42              : #ifdef _MSC_VER
      43              : #pragma warning(pop)
      44              : #endif
      45              : #endif
      46              : 
      47              : #include "Element.h"
      48              : 
      49              : // ===========================================================================
      50              : // class declarations
      51              : // ===========================================================================
      52              : class Node;
      53              : 
      54              : 
      55              : // ===========================================================================
      56              : // class definitions
      57              : // ===========================================================================
      58              : /**
      59              :  * All interactions will be through this class, the user will know nothing about the other classes,
      60              :  * and will interact only through the names of the elements/nodes.
      61              :  */
      62              : class Circuit {
      63              : 
      64              : public:
      65              :     /// @brief whether per-substation overhead-wire current limits should be enforced
      66              :     static void enforceCurrentLimits(const bool val) {
      67        42780 :         myCurrentLimits = val;
      68              :     }
      69              : 
      70              : private:
      71              : 
      72              :     std::vector<Node*>* nodes;
      73              :     std::vector<Element*>* elements;
      74              :     std::vector<Element*>* voltageSources;
      75              : 
      76              :     int lastId;
      77              :     bool iscleaned;
      78              : 
      79              :     /// @brief The electric current limit of the voltage sources.
      80              :     double circuitCurrentLimit;
      81              : 
      82              :     /**
      83              :     * @brief Best alpha scaling value.
      84              :     *
      85              :     * This parameter is used to scale down the power demands of current sources (vehicles
      86              :     * that draw power from the circuit) so that a solution of the system can be found.
      87              :     * Note: the system is nonlinear (quadratic), hence in some cases (typically too high
      88              :     * power demands) a solution cannot be found. In that moment we decrease all power
      89              :     * requirements by `alpha` and try to solve again, until we find alpha that ensures
      90              :     * stable solution. This is then reported as alphaBest.
      91              :     */
      92              :     double alphaBest;
      93              : 
      94              :     /// @brief whether per-substation overhead-wire current limits should be enforced
      95              :     static bool myCurrentLimits;
      96              : public:
      97              :     /**
      98              :      * @brief Flag of alpha scaling parameter
      99              :      *
     100              :      * returns ALPHA_NOT_APPLIED => alpha should be 1
     101              :      * returns ALPHA_CURRENT_LIMITS => alpha is lower than one due to electric current limits of the substation
     102              :      * returns ALPHA_VOLTAGE_LIMITS => alpha is not one due to inability of network to transfer requested power due to overhead wire resistance
     103              :      * returns ALPHA_NOT_CONVERGING => number of allowed iterations exceeded
     104              :      */
     105              :     enum alphaFlag {
     106              :         /// @brief The scaling alpha is not applied (is one)
     107              :         ALPHA_NOT_APPLIED = 0,
     108              :         /// @brief The scaling alpha is applied (is not one) due to current limits
     109              :         ALPHA_CURRENT_LIMITS,
     110              :         /// @brief The scaling alpha is applied (is not one] due to voltage limits
     111              :         ALPHA_VOLTAGE_LIMITS,
     112              :         /// @brief The Newton-Rhapson method has reached maximum iterations and no solution of circuit has been found with actual value of alpha
     113              :         ALPHA_NOT_CONVERGING
     114              :     };
     115              : private:
     116              :     alphaFlag alphaReason;
     117              : 
     118              : public:
     119              :     Node* getNode(std::string name);
     120              :     Element* getElement(std::string name);
     121              :     Node* getNode(int id);
     122              :     Element* getVoltageSource(int id);
     123              :     std::vector<Element*>* getCurrentSources();
     124              : 
     125              :     /// @brief The sum of voltage source powers in the circuit
     126              :     double getTotalPowerOfCircuitSources();
     127              :     /// @brief The sum of voltage source currents in the circuit
     128              :     double getTotalCurrentOfCircuitSources();
     129              :     /// @brief List of currents of voltage sources as a string
     130              :     std::string& getCurrentsOfCircuitSource(std::string& currents);
     131              : 
     132              :     void lock();
     133              :     void unlock();
     134              : 
     135              :     /// @brief return alphaBest variable, the best alpha scaling value
     136              :     double getAlphaBest() {
     137          360 :         return alphaBest;
     138              :     }
     139              : 
     140              :     /// @brief return the reason why `alpha` scaling value has been used
     141              :     alphaFlag getAlphaReason() {
     142          180 :         return alphaReason;
     143              :     }
     144              : 
     145              : private:
     146              : 
     147              :     Element* getElement(int id);
     148              :     /*
     149              :     *    detects removable nodes = sets node variable "isremovable" to true if node is removable and adds id of such node to "removable_ids" vector
     150              :     *    node is denoted as removable if it is connected just to 2 elements and both of them are resistor
     151              :     *    the reason is that in such case there are two serial resistor and we can only sum their resistance value
     152              :     *
     153              :     *    "removable_ids" vector is sort from the least to the greatest
     154              :     */
     155              :     void detectRemovableNodes(std::vector<int>* removable_ids);
     156              : 
     157              :     void deployResults(double* vals, std::vector<int>* removable_ids);
     158              : 
     159              : #ifdef HAVE_EIGEN
     160              :     /*
     161              :     *    creates all of the equations that represent the circuit
     162              :     *    in the form Ax = B(1/x) where A and B are matrices
     163              :     *    @param eqn : A
     164              :     *    @param vals : B
     165              :     */
     166              :     bool createEquationsNRmethod(double*& eqs, double*& vals, std::vector<int>* removable_ids);
     167              : 
     168              :     /*
     169              :     *    creates the nodal equation of the node 'node' GV = I
     170              :     *    in the form Ax = B(1/x) where A is a matrix with one row
     171              :     *    @param node : the node to be analyzed
     172              :     *    @param eqn : A
     173              :     *    @param val : B
     174              :     */
     175              :     bool createEquationNRmethod(Node* node, double* eqn, double& val, std::vector<int>* removable_ids);
     176              : 
     177              :     /**
     178              :      * @brief Create the equation of the voltage source.
     179              :      * Create the equation V2 - V1 = E of the voltage source in the form Ax = B,
     180              :      * where A is a matrix with one row, B a value
     181              :      * @param[in] vsource The voltage source
     182              :      * @param[in] eqn : A
     183              :      * @param[in] val : B
     184              :      * @return ???
     185              :     */
     186              :     bool createEquation(Element* vsource, double* eqn, double& val);
     187              : 
     188              :     /*
     189              :      *    removes the "colToRemove"-th column from matrix "matrix"
     190              :      */
     191              :     void removeColumn(Eigen::MatrixXd& matrix, const int colToRemove);
     192              : 
     193              :     /*
     194              :      * solves the system of nonlinear equations Ax = B(1/x)
     195              :      * @param eqn : A
     196              :      * @param vals : B
     197              :      */
     198              :     bool solveEquationsNRmethod(double* eqn, double* vals, std::vector<int>*);
     199              : 
     200              :     bool _solveNRmethod();
     201              : 
     202              : #endif
     203              : public:
     204              : 
     205              :     // a Constructor, same functionality as "init" functions
     206              :     Circuit();
     207              :     // RICE_CHECK: Is this a traction substation current limit, global for all substations?
     208              :     /// @brief Constructor with user-specified current limit parameter.
     209              :     Circuit(double currentLimit);
     210              : 
     211              :     // adds an element with name "name", type "type" and value "value" to positive node "pNode" and negative node "nNode""
     212              :     Element* addElement(std::string name, double value, Node* pNode, Node* nNode, Element::ElementType et);
     213              : 
     214              :     void eraseElement(Element* element);
     215              : 
     216              :     // adds a node with name "name"
     217              :     Node* addNode(std::string name);
     218              : 
     219              :     // erases a node with name "name"
     220              :     void eraseNode(Node* node);
     221              : 
     222              :     // gets current through element "name"
     223              :     double getCurrent(std::string name);
     224              : 
     225              :     // gets voltage across element or node "name"
     226              :     double getVoltage(std::string name);
     227              : 
     228              :     // gets the resistance of an element.
     229              :     double getResistance(std::string name);
     230              : 
     231              :     // gets the number of voltage sources in the circuit.
     232              :     int getNumVoltageSources();
     233              : 
     234              :     // checks if the circuit's connections are correct.
     235              :     bool checkCircuit(std::string substationId = "");
     236              : 
     237              : #ifdef HAVE_EIGEN
     238              :     // solves the circuit and deploys the results
     239              :     bool solve();
     240              : #endif
     241              : 
     242              :     // cleans up after superposition.
     243              :     void cleanUpSP();
     244              : 
     245              :     //replaces unusedNode with newNode everywhere in the circuit, modifies the ids of other nodes and elements, decreases the id by one and deletes unusedNode
     246              :     void replaceAndDeleteNode(Node* unusedNode, Node* newNode);
     247              : 
     248              :     // returns lastId
     249              :     int getLastId() {
     250          203 :         return lastId;
     251              :     };
     252              : 
     253              :     // decreases lastId by one
     254              :     void decreaseLastId() {
     255          195 :         lastId--;
     256              :     };
     257              : 
     258              :     /// RICE_CHECK: Is this identical to the current limit of a traction substation?
     259              :     /// @brief Set the electric current limit of this circuit.
     260              :     void setCurrentLimit(double myCurrentLimit) {
     261              :         circuitCurrentLimit = myCurrentLimit;
     262              :     };
     263              : 
     264              :     /// @ brief Get the electric current limit of this circuit.
     265              :     double getCurrentLimit() {
     266          180 :         return circuitCurrentLimit;
     267              :     };
     268              : };
        

Generated by: LCOV version 2.0-1