Coder Social home page Coder Social logo

powergrids / powergrids Goto Github PK

View Code? Open in Web Editor NEW
37.0 37.0 17.0 1.2 MB

This repository contains the code for PowerGrids, a Modelica library for electro-mechanical modelling of power systems.

License: Mozilla Public License 2.0

Modelica 87.95% Motoko 12.05%
modelica open-source-models power-systems

powergrids's Introduction

PowerGrids - A Modelica library for electro-mechanical modelling of power systems

This repository contains the code for PowerGrids, a Modelica library for electro-mechanical modelling of power systems. This library was originally developed by RTE with help from Dynamica s.r.l. It is part of a larger effort to promote both the use of Modelica for power system modelling and the advantages of open-source approaches (for more detail, go to Dynaωo website).

Table of Contents

About PowerGrids

The PowerGrids library is a library for the modelling of power generation and transmission systems for electro-mechanical phenomena ("phasor" approximation).

The main goal of the library is to demonstrate how it is possible to exploit the power of the Modelica language to develop fully declarative electro-mechanical models of power generation and transmission systems that are self-documented, easy to understand, and easy to modify and improve. For physical component models, the code is as close as possible to the model description as found in textbooks and basic theory manuals, entirely leaving to the Modelica tool the task of solving the equations. For control systems, block diagrams are used, as they are immediately recognized by domain experts.

To achieve this goal, the following features were implemented:

  • Base classes for one-port and two-port components to factor out common code as much as possible.
  • Use of Complex numbers for maximum readability.
  • Use of physical SI units wherever appropriate, e.g., in connectors.
  • Proper scaling of the underlying differential-algebraic equations for numerical robustness achieved by using the nominal attribute of variables, rather than implementing it explicitly in the models.
  • Use of initial equations to compute all strictly necessary start values in a declarative, easy-to-understand way, starting from power-flow analysis results.
  • Use of initial equations for steady-state initialization of models.
  • Use of homotopy to improve the convergence of initial equations where necessary.

The library is meant to be used to model small-scale systems, e.g. for teaching, as well as medium-scale systems. Small system models can be built and managed with the graphical user interface of Modelica tools, while larger models can be built automatically by suitable scripts.

PowerGrids was developed and tested using OpenModelica and is expected to run on all Modelica tools that fully support the Modelica standard, including Complex numbers and the homotopy transformation. Numerically robust and efficient simulation performance requires certain types of symbolic manipulations and numerical solvers to be used by the Modelica tool; this may require to activate special flags or advanced options in some cases. For more details, please read the Tool Support section of the embedded documentation of the library. If you are using OpenModelica to run the simulations, we recommend using the latest released version for the best end-user experience.

For more details about PowerGrids, its rationale, and its implementation and numerical details, please consult the library documentation and the Modelica Conference paper.

Getting started!

To begin using the PowerGrids library, we recommend you to open it in your favorite Modelica environment and to follow the tutorial available in the UsersGuide section. The tutorial provides a large overview of the library main features while helping you to be accustomized to the library main concepts and choices.

You can also have a look to the existing models, available in the Electrical and Control directories, as well as the test cases provided with the library, available in the Examples part.

Get involved!

PowerGrids is an open-source project and as such, questions, discussions, contributions and feedbacks are very welcome. It is also an ongoing project and we are actively working on improving it and making it better so we encourage you to regularly check the project status and progresses.

Contributions in different forms, such as the addition of a new model, the creation of a new test case or any correction on the existing code, will be greatly appreciated. The final procedure to accept a new contribution is still under discussion but in the meantime, we encourage you to submit pull request associated to an issue, explaining the reason of your development. We will go through it and use it as a basis for discussion before inserting your modifications into the library. In any case, when adding new Modelica code, please follow the coding style available in the NamingConventions file.

Quoting PowerGrids

If you use the PowerGrids library in your work or paper, it is not mandatory but we kindly ask you to cite the following paper in your presentations or publications:

A. Bartolini, F. Casella, and A. Guironnet, “Towards Pan-European Power Grid Modelling in Modelica: Design Principles and a Prototype for a Reference Power System Library,” Proceedings of the 13th International Modelica Conference, Regensburg, Germany, March 4–6, 2019, Feb. 2019

License

PowerGrids is licensed under the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, you can obtain one at http://mozilla.org/MPL/2.0. You can also see the LICENSE file for more information.

Maintainers

PowerGrids has been originally developed by RTE with the help from F. Casella (Politecnico di Milano, Dynamica s.r.l.) and A. Bartolini (Dynamica s.r.l.). It is currently maintained by the following people in RTE:

In case of questions or issues, you can also send an e-mail to [email protected].

Links

If you are interested by the use of Modelica for power system modelling and by open-source approaches, please have a look to the following projects:

  • Dynaωo, an open source hybrid C++/Modelica time-domain simulation tool for power system simulation.
  • OpenModelica, an open source Modelica based modelling and simulation environment.

If you want to get additional information related to RTE or Dynamica s.r.l., please go to our websites.

powergrids's People

Contributors

adriguir avatar andreabartolini avatar casella avatar christiankral avatar marcochiaramello avatar max-privato avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

powergrids's Issues

Propagate UStart and UPhaseStart values from Bus to connected components

In general the UStart value (default = UNom) and the UPhaseStart value (default = 0) should be set by the user in every component of the network based on the results of the initial power flow problem. This creates a redundancy because in case of connected components the UStart is the same for all of that.
One possibility to solve this redundancy is to use buses to connect the components and to propagate the UStart value from the Bus to the components connected to it, by adding input/output variables to terminalAC.
This has been partially discussed in the issue #49 (last 14 comments), the discussion is moved here because it is an extension of the original issue and the implementation of the solution is independent from the one necesary to close the #49.

Introduce overconstrained connectors in PowerGrids

State of the art

The electro-mechanical modelling of power systems with synchronous generators requires to share a common reference frequency for each synchronously connected sub-system. Libraries such as Modelica.Electrical.QuasiStatic.SinglePhase or PowerSystems share such reference by means of overconstrained connectors, where the overconstrained variable is a phase angle or a reference frequency.

When the PowerGrids project was started several years ago, we decided not to use this mechanism, because overconstrained connection graphs in the current Modelica Language Specification are static, so they cannot change at runtime.

In case a synchronous system is split into two (or more) synchronous systems because of breakers opening at the connection between different areas, one ends up with two systems that need a different frequency reference each. This is necessary for efficient variable step-size simulation: if the two new areas end up working at different frequencies, e.g. one at 49.5 Hz and one at 50.5 Hz, using only one reference, e.g. at 49.5 Hz, would mean that the phasors of the other sub-system would rotate at 1 Hz also in steady-state, thus requiring to shorten the time step very much below 1 s, and recomputing Jacobians all the time. This is not necessary if, after the splitting, each synchronously connected island gets its own frequency reference, because in that case, all phasors will become constant at steady-state.

PowerGrids 1.0.x was then designed to operate in three possible modes, set by the System object:

  • nominal frequency: the reference frequency is fixed at the nominal value; this is fine for grids that are connected to a strong node
  • fixed reference generator: the reference frequency is provided by a suitably selected generator: this is fine for a single synchronous island
  • adaptive reference generator: this was meant to allow dynamic islanding, with one reference generator for each island, decided at runtime based on the breakers' status and on the corresponding actual connection topology

It turned out, programming the third choice, albeit technically possible with Modelica 3.5, is quite complicated: it requires an external object inside the system object with a lot of external C code to manage the dynamically changing topology at runtime, and also a lot of ugly connections to-from the system objects, with ugly things like connection numbers generated at initialization to manage the topology analyzer. A lot of imlementation work, and a not really object-oriented way do do things.

We recently prototype a new concept that allows to dynamically change the overconstrained connection topology at runtime, see #30 and references therein. The prototype works very well, it was written using OpenModelica.jl, but it can be easily ported into any Modelica tool. Most importantly, it requires really minimal and very straightforward changes to the library source code, compared to regular static overconstrained connections. The required change in the Modelica Language Definition is also minimal and does not require any new syntax, it just eliminates one constraint in the structure of if-equations.

Given this result, it is clear that the original adaptive reference generator concept will never be implemented, because it is so much simpler and so much more elegant to do it in a truly object-oriented way with dynamic overconstrained connectors. Even if that requires a (small) change in the Modelica language, and in the tools supporting it. We won't have an implementation of the adaptive reference generator anytime soon anyway, so I believe it's best to invest this time into getting dynamic overconstrained connectors into the language. BTW, this allow to also support other use cases that need dynamic overconstrained connectors, e.g., incompressible fluid networks.

Proposal

I would therefore propose that version 2.0.0 of PowerGrids scraps the current architecture, where the reference frequency is managed by the system object, and used overconstrained connectors instead, to carry around the reference frequency information. The way to do that is detailed in this paper and has already been tested successfully with the conceptual library DynamicOverconstrainedConnectors. The resulting code is actually more compact and nicer.

As a first step, we can re-implement the currently available options (nominal frequency for grids connected to one or more infinite buses, fixed reference generator for islanded grids) using regular overconstrained connectors. Thus, we get the same functionality, but with a much nicer object-oriented formulation. This works out of the box with current Modelica 3.5-compatible tools.

It is then possible to add the option of using dynamic overconstrained connectors to actually split the connection diagram at runtime when breaker opening form separate synchronous islands. This option could be triggered in the system object, and would of course only work with tools that implement this feature.

The changes to the library source code to implement this are really minimal: a few lines in the system object, and a couple of lines in the models including breakers. Note that this additional code does not prevent to use the library in tools that do not support this feature, as long as it is not activated in the system object.

Invalid root when simulating a short circuit on IEEE14

I'm trying to see the effects of a short circuit at node 4 using a model obtained with a minimal modification from the PowerGrids.Examples.IEEE13bus.IEEE14BusStaticNetwork.
I Just added the short at node 4. The resulting file is here (pls remove "txt" from the name):
IEEE14busShort4.mo.txt

I've chosen this example because it is already available on OpenIpsl. Although the OpenIpsl IEEE14 model is not perfectly equivalent to PowerGrids', it is near to it, so it would be interesting to compare the two results.

When I run it with OpenModelica 1.19 I get several instances of the error:
IEEE14busShort4_12jac.c:14213: Invalid root: (0)^(-0.5).

The simulation continues, but the result is plainly wrong, since the voltage on node 4 is nearly zero after the fault is removed, while it should rapidly get back to the previous value.

The troubles seem to start when the fault is removed since the following message is also issued:
While solving non-linear system an assertion failed at time 1.20006.

Looking at the algorithm in BusFault model, I see this:

algorithm
   when pre(fault) then
     Y := 1/Complex(R, X);
   end when;

   when not pre(fault) then
     Y := Complex(0);
   end when;
equation
   i = Y*v;

So there is a division by Complex(R,X). Maybe this is the culprit? The error mentions division by the square root of zero, which could be the output of a Complex() call. However, it should not be the case, since in my example R>0 (actually 0.05 ohms)

For completeness, I show below the node 14 voltage with OpenIpsl and PowerGrids (first 4 seconds):

OpenIPSL:
openIpsl

PowerGrids:
PowerGrids

LineConstantImpedanceFault has a wrong modifier and wrong description

In the LineConstantImpedanceFault model the modifier of the R parameter of the lineA is the following: R = faultLocationPu. It gives the right value = 0 (but wrong Unit) when the fault is located at the portA but it gives the wrong value = 1 (instead of R or a fraction of R) if the fault is located at the portB or at an intermediate position along the line.
The right modifier should be R = faultLocationPu*R.

Moreover, the current description of the model is the same of the LineConstantImpedance one, it should be updated according to the behavior of the model.

Are reference results available?

As a tool developer, it would be of interest to have reference results/baselines for expected results available, for the simulateable models in the library. This would allow for a tool to verify that the library works correctly in the tool.

Are such results available in any form?

Improve voltage control in IEEE14Bus test cases

Voltage control in the IEEE14Bus test cases has some stability issues. In all the test cases where some perturbations of the voltage are applied, the AVRs eventually bring the voltages to completely irrealistic values, possibly over 2 p.u., with consequent increase of the power adsorption by the PQ loads and eventual frequency collapse.

The AVRs should be re-tuned so as to ensure stable operation in all the transient scenarios.

PowerGrids.Examples.Tutorial.IslandOperation.TwoGeneratorsLocalInitialization fails at initialization

Model PowerGrids.Examples.Tutorial.IslandOperation.TwoGeneratorsLocalInitialization fails at initialization, and was temporarily removed from the set that is tested by the OMC CI.

Some analysis and comparisons was carried out on a reduced version of the model, only including the left-hand-side of the network. As the line is unloaded at initialization, this doesn't change the solution. This reduced model is available on branch https://github.com/PowerGrids/PowerGrids/tree/TestInit

Comparison with PowerGrids.Examples.Tutorial.IslandOperation.TwoGeneratorsOneReferenceGenerator model, which should give the same results, reveal that the solution of the split sub-system corresponding to the network equations starts from the same start values that immediately lead to convergence of the global initialization problem, but stray away from it dramatically already at the first Newton iteration. For example:

TGEN1.iA.re  =        40895.151   step =        27253.764   old =        13641.387

this result was obtained by using the default solver; also Kinsol fails in the same place, though it is harder to understand why by looking at the logs.

It seems that the network sub-system equations are wrong for some reason, since they do converge to a wrong solution. This should be investigated.

It is also worth noting that, after converging to the wrong solution at lambda = 0, the solver restarts at the (correct) value when tackling the first non-zero lambda step. This shouldn't happen, the solution found at lambda = 0 should be kept as initial guess for subsequent steps.

Bad power expression detected by Dymola

Consider model Compare_SI_PU.wipSI in
Test.mo.txt

It runs in OM, but Dymola gives the following error:

Error: The following error was detected at time: 0
Model error - power: (pv33x2.port.u.re^2+pv33x2.port.u.im^2) ^ (-0.5) = (0) ^ (-0.5)

So, Dymola detects a power with negative exponent with base is zero.

TestFreeOffset not working

I tried Controls.Test.TestFreeOffset with Dymola 2020x (I chose this a bit old because it is distributed with MSL 3.2.3) and OM (1.21.0-dev-148 and 1.22.0-dev-39).
Screenshot from Dymola:
image

Screehsot from OM
image

Confusing info in Infinitebus

In PowerGrids.Electrical.Buses.InfiniteBus i read the following info:
Infinite bus model with constant voltage e and internal impedance Z. The port voltage is v = e + Zi, where i is the current entering the bus. The default value of the series impedance Z = R + jX is zero.

From this it is unclear how to specify "e". the use of lowercase letters and the change of internal e.m.f. from, "E" to Uref in the info do not help. After some study one understands that this it is to be specified by means of parameters URef and theta. I propose to modify the info things clearer,

A possible substite for the info could be (if this is accepted parameter URef should be changed into ERef and theta into thetaE):

Infinite bus model with constant voltage phasor E and internal impedance Z. The port voltage is U = E + ZI, where I is the current entering the bus and E has as amplutude parameter ERef, and phase thetaE. The default value of the internal impedance Z = R + jX is zero.

Why in PortAC we hide pu variables when portVariablesPu=true?

Consider #47.
It used to work with Dymola 2020, while does not with 2023.
After some analysis I found that the reason is that in PortAC Vpu, Ppu, Qpu, have HideResult=portVariablesPu. So, when I choose to add per-unit variables to model, I get HideResult=true.
Is this intended? Maybe it should be the opposite?

To make #47 work also with Dymola 2023 I had to write (in my personal version of PowerGrids) HideResult=not portVariablesPu, which appears reasonable to me.

Use different symbols for different classes

LoadImpedancePQ and LoadPQVoltageDependence inside Electrical.Loads share the same symbols, which is inconvenient.
I propose making a change so that they are different from each other. Maybe LoadImpedancePQ can have a "Z" in its symbol, while LoadPQVoltageDependence a greek alpha?

Conversion of loads unclear

In the system object mask I see the variable loadLowVoltageAsImpedance.

I know what is behind this, since I partecipated at the definition of the behaviour.
Nevertheless, as a user I find this very difficult to understand:

  1. the system object info does not say anything about this
  2. probabily something is written in the tutorial, but the tutorial is large and complex, and it is not easy to find spot pieces of info, without a link from where they are needed.y

I propose to write something in the system object info, with a possible link to other parts in the documentation where maibe further details are added.
Maybe it is sufficient just to say what the "low-voltage conditions" to determine the load swich into fixed impedances are. AFAICR it is just a voltage threshold. Probably just this needs to be said, and and whether this threshold is fixed or can be changed by the library user.

Initialization coordination issues

Consider a typical case of a line connected to busses at its terminals.
Powergrids allows defining the initial value of voltage magnitude and angle for both bus and line terminal. But what value will be used for actual initialisation (obviously the two values must necessarily be equal)? The user does not know and gets confused.

Active and reactive power flows share this issue: two components connected together must have initial powers such that their sum is zero, and similar requirements occur in the case of multiple connections.

A possibility to solve this redundancy is to add a flag in the masks for each initial value (voltage amplitude, voltage phase, active and reactive power) possibly named "use this value".
So, in case of a bus connecting n nodes, the user can set (at most) n-1 active and reactive powers and one voltage amplitude and phase, leaving the "use this value" unchecked for the remaining items.

I said "at most", since in several cases PowerGrids can be able to solve the initial problem even without having good initial values for, say, voltages for buses and line terminals.

For compatibility with the present behaviour, I would leave it possible also to set all voltages and powers; in this case, as it is today, it is highly advisable that the values be consistent, e.g. the voltage magnitude of all terminals connected together be exactly equal to each other.

A later note.
This issue message assumes that initialization data for lines play an important role in the initialization of PowerGrids network.
This is not totally granted since in the IEEE14bus example all terminal line initialization data are left to their default values (voltages and active powers to their nominals, reactive powers and voltage angles to zero).

However, once it is decided to let the user define these initial values, they must be consistent. This justifies this ticket.

Issue in PowerGrids.Electrical.Test.TwoBusesResistiveTransmissionLineFault

The frontend reports:

[/home/hudson/saved_omc/libraries/.openmodelica/libraries/PowerGrids 2.0.0-develop/Electrical/BaseClasses/TwoPortAC.mo:11:3-12:47:writable] 
Error: Trying to override final element UStartA with modifier '= UStartA'.
Notification: Performance of FrontEnd: time 0.1697/0.267, allocations: 5.571 MB / 427 MB, free: 36.78 MB / 350.1 MB

Probably something went wrong with the refactoring, or has not yet been properly updated.

Use unique power base for power display on diagrams

This ticket regards only the PF feature of the new PowerGrids.

Now we have the possibility to see the PF results directly on the system diagrams. This is a very important and useful feature. Indeed, when doing PF studies, I think users will 90% of the time have a look at just the diagram with numerical result on it, and only rarely will read other results through the output variables.

I like to seee these results in PU. However, for this case, I think it is important to make a change to make it even more useful.

Now active and reactive powers are referred to the nominal machines they belong to, which in general are different from different machines in the system. For instance a 100 MVA generator can be connected to a 130 MVA transformer.
So, when we output the PF results on the diagram in PU, PU numbers are not directly comparable.
Consider for instance bus33 in the picture below. the power coming from pv33 is 100 MW, which goes into the two transformers below it. In fact their nominal powers are 75 MVA, so they receive 0.6667*75= 50 MW each. This is not immediately evident from the numerical labels on the diagram, since they refer to different base units.

The situation could be improved a lot if all active and reactive powers are shown in a unique base, e.g. 100 MVA for the whole grid.

My proposal is therefore to add to the SystemObject an option to be selected through a checkBox, whose name could be "Use unique power base for power display on diagrams".
The this checkbox is selected an input field should become active, allowing specifying the value of the unique power base (e.g. 100 MVA).

In that case the user would have a clear picture of the power flow just having a look at the diagram:

  • they could select the UNom value for buses that to correspond to the adjacent transformer windings
  • they could select a unique power base for the system e.g. 100 MVA. This will override local nominal values for the computation of the PQ active and reactive powers displayed on diagrams.

With these choices, the output will be as in textbooks, where a unique base is taken for sthe system and all the numbers are meaningul without conversions.

Is this possible with a reasonable effort?
Does anyone agree that this could be helpful?

image

Questionable nominal and initial power values of buses and loads

The behaviour that induced me to write the following description was observed using OpenModelica 1.18.0. Maybe part of the wrong is not due to PowerGrids library itself but to some flaw of OpenModelica 1.18.0.

Regarding PowerGrids.Electrical.buses.Bus and referenceBus, InfiniteBus, BusFault, InfiniteBusVariableVoltage:

  • In their General page the mask prompts for SNom. but what's the meaning of it? Buses should not absorb neither deliver any power, so their S is always zero and this field should not appear
  • In Initialization page the mask prompts for PStart and QStart. But what's the meaning of them? buses should not absorb neither deliver any power, so their Q and Q are always zero and this value should not appear
  • if we set PStart=0 in the Initialization page, an error message is issued stating that that value cannot be changed. This confirms that that field must not be there.

regarding
Powergrids.Electrical.Loads.LoadPQVoltageDependence and LoadImpedancePQ:

  • In initialization page the mask prompts for PStart and QStart. The user assumes they are active and reactive initially absorbed by the load. But they should not be there, since we know them from the Ustart value (and PRefConst, QRefConst, alpha and beta values). The default values are also strange sinte they are not consistent with the values set in the General page

Obscure warning

Consider Model Umach1WIP in the following package.
Test.mo.txt

Running it gives the following warnigs, that, I'm afraid I'm unable to decode.
image

Since the model does not run, understanding this warning is therefore critical for me. Is it my fault or something in the diagnostics can be improved?

Tested with OM 1.23.0-310 and Powergrids 2.0.0-develop dated 15/1/2024

Simple possible improvement

@adriguir
I'm planning to use PowerGrids as a tool for University courses, so I tend to evaluate it also with the student's eyes in mind. That's Why I'm proposing this ticket related to a minor issue, whose solution, however, would clarify and simplify the use of the component.

Regarding EquivalentGrid, I wonder why the c-factor for calculation of short-circuit capacity is introduced.
The equation in which it is used is:

final parameter Types.ComplexPower Ssc=ComplexMath.fromPolar(SSC/c, atan(1/
      R_X)) ;

It seems to me that this parameter could be omitted, thus simplifying the component dialog box, which is rather rich in parameters.

Moreover, I would suggest, in the documentation of this component, to substitute
The impedance is computed to provide a power flow SSC/c out of the voltage source,
with

The impedance is computed to provide an apparent power flow SSC/c out of the voltage source,
or, in case it is acceptable to omit c:
The impedance is computed to provide an apparent power flow SSC out of the voltage source,
Regards.

Update the compatibility & solver section of the README

Hello,

Present version of README includes a quite technical paragraph about compatibility and efficiency:

PowerGrids was developed and tested using OpenModelica 1.14.1, but is expected to run on all Modelica tools that fully support Complex numbers and the homotopy transformation. For numerical efficiency of models with more than a few buses, it is necessary that the tool does not transform the equations into ODE form, but rather directly uses a sparse DAE solver. The reason for this requirement is that while the DAE is sparse, the corresponding ODE is dense. Note that most of the models and test cases run with this version of OpenModelica but some solver issues are still under consideration and should only be available from OpenModelica 1.16 - in case you want to benefit from the latest developments, we recommend you to download the nightly-build from OpenModelica.

Since OM 1.16 was released in late 2020, I proposed to simplify the message, because newcomers may not be interested in the full history and may not be aware of technical details like homotopy initialization and DAE vs ODE solver:

Paragraph labeled PowerGrids is developed and tested using OpenModelica (≥1.16), but is expected to run on all Modelica tools that fully support Complex numbers and the homotopy transformation [I would add here 2-3 major compilers that enter this category, if any].

Of course, the ≥1.16 recommendation should be incremented if some planned bugfix were delayed.

Then, I would split the paragraph about the solver selection and reformulate more towards what I should do, as a user. For example, when I open an example in OMEdit 1.18, and enter the simulation setup, the default solver is dassl, and I have no idea if it's good or not (searching for it on the web sends me to a Petzold, 1982 technical report where I understand that it's a DAE solver, but the short tooltip in OMEdit is silent on this fact). So I recommend adding a list of reasonable solvers. If I need to tinker with the "Translation flags" in OM's Simulation Setup dialog, this should be stated here. This is how I imagine the paragraph:

For numerical efficiency of models with more than a few buses, it is necessary that the tool does not transform the equations into ODE form, but rather directly uses a sparse DAE solver. The reason for this requirement is that while the DAE is sparse, the corresponding ODE is dense. Practically, for OpenModelica users, this implies doing this and that... [and perhaps add similar explanations for other common tools, if applicable]

All these paragraphs could be headed by a title "Compiler and solver compatibility and recommendations"

Publish version 1.0.2 in OpenModelica?

Hello,

I'm not familiar with how libraries are pushed to the OpenModelica library distribution, but I see that installing PowerGrids with the Linux version of OpenModelica (through the deb http://build.openmodelica.org/apt buster stable Debian package source which currently serves OM 1.18 beta 2), I can only install version 1.0.0 (package omlib-powergrids-1.0.0). What steps are needed to publish the latest release to OM?

Best,
Pierre

Boxed components should not be transparent.

Consider the following screenshot.
As you see, all MSL boxed components are not transparent, while many Powergrids' are.
Having transparent boxed components makes a bit more difficult to drag them with mouse movement.

I would recomment to fill all of them with white (I can issue a PR in case I'm requested to do so).
Also generator (and, possibly, transformer) circles, for me, should be filled with white.
Doing this for transformer is just slightly trickier, since it involves for one winding using two overlapped circles, the lower filled, the uper transparent.

image

Introduce system-wide validity limits

It often happens that numerical simulation of PowerGrids models reach values of voltage, current, and frequency which are completely unrealistic and way beyond the validity assumptions of some component.

In some cases, this eventually leads to simulation failure, which is potentially problematic because the feedback from the solver in that case does not give any indication about the root cause of the problem. Even worse, in some cases, these solutions are still numerically sound and thus accepted by the simulation tool, even though they actually don't make much sense. See for example #110: the IEEE14Bus have some AVR stability problems that mostly went unnoticed and only caused failures in some test cases but not in others, even though they reach values of frequency and current which are clearly unrealistic.

Currently, on the develop branch there are some hard-wired assertions enforcing a maximum current of 1.5 p.u in loads, which was meant to catch bogus initial equations with very low voltage and very high current.

In order to improve usability and diagnostics, particularly for inexperienced novice users, we should probably expand this feature by adding more such assertions, making the limits customizable from the system object. On the other hand, it should probably also be possible to disable these checks in case the generated code is meant to be used inside some other software system, which takes care of enforcing those limits.

Proposal:

  • add parameter Boolean enableAssertions = true annotation(Evaluate = true) in the system object, to globally activate and de-activate such limits
  • add the system-level defaults in the system object:
    • VPuMin = 0.7
    • VPuMax = 1.3
    • IPuMax = 1.5
    • omegaPuMin = 0.9
    • omegaPuMax = 1.1

The voltage limits should be applied to all buses and synchronous generators, with default values set by the system object; the current limits should be applied to all loads, with default values set by the system object; the frequency limits should be applied to all generator models, with default values set by the system object.

In this way, the default set up ensures reasonable operational limits with zero set-up effort, allowing to immediately pin-point potentially critical points in the sytem - the limits can then easily be customized, either at the system level, or locally, or possibly completely disabled if deemed necessary.

The idea

Embedded Power Flow feature

In the original design of the PowerGrids library, the initialization of the system is based on power flow data provided at the port of components as parameters: amplitude and phase of the voltage, active and reactive power flows. The idea was that in general solving a power flow problem may require specialized software, possibly including features as optimization, and this was out of scope for Modelica models, which are mostly aimed at running transient simulations. This is true in particular for large systems, whose models may be automatically built from net-lists inside software that uses Modelica as a service to run the transient simulations but already has robust power-flow computation capabilities, that can be used to compute such initialization parameters. Hence, the library was designed to provide reliable initialization, assuming that proper power-flow parameters are supplied.

It turned out, for simple systems one can also use the PowerGrids library directly from a Modelica editor such as OMEdit or Dymola, e.g. for teaching or research purposes. For such simple systems, it is possible to build power flow models using PowerGrids, relying on the Modelica tool solver to obtain such power flows, and then use the results of their simulations, either manually, or via scripts, to provide the appropriate parameter values for the transient simulations. However, this is not particularly convenient; moreover, lack of properly computed initialization parameters can lead to initialization problems, or possibly to convergence to bogus initial conditions.

The alternative is to optionally embed power flow models in the library, so they can be used automatically to compute the power flow initialization parameters. The idea is to use conditional components for this purpose: sub-connectors to carry the PF current and voltage can be added to the Terminal connector, and suitable conditional embedded power flow (EPF) models attached to these connectors can be conditionally instantiated inside each component, with provisions to compute the PF initialization parameters for the initialization of the full dynamic models during initialization.

A sketch of the implementation is reported here:

  1. A Boolean parameter computeEPF (compute embedded power flow) is added to the system object.

  2. The TerminalAC connector can be defined as:

connector TerminalAC "Terminal for phasor-based AC connections"
  Types.ComplexVoltage v "Phase-to-ground voltage phasor";
  flow Types.ComplexCurrent i "Line current phasor";
  parameter Boolean computeEPF "= true includes embedded power flow sub-connector";
  TerminalAC terminalEPF(final computeEPF = false) if computeEPF "Conditional sub-connector for emedded power flow computation";
end TerminalAC;
  1. The OnePortAC model can then be expanded as follows:
partial model OnePortAC "Base class for AC components with one port"
  final parameter Boolean computeEPF = systemPowerGrids.computeEPF "Embedded power flow computation required";
  parameter Boolean hasSubEPF = false "= true if the model contains a sub-network with its own EPF";
  PowerGrids.Interfaces.TerminalAC terminal
    (v(re(start = port.vStart.re), im(start = port.vStart.im)),
     i(re(start = port.iStart.re), im(start = port.iStart.im)),
     computeEPF = computeEPF,
     terminalEPF(v = vEPF, i = iEPF);
  replaceable OnePortAC componentEPF if computeEPF and not hasSubEPF "Conditional embedded power flow component";

  parameter Types.Voltage UStart = if computeEPF then UstartEPF else UNom "Start value of phase-to-phase voltage phasor, absolute value";
  parameter Types.Angle UPhaseStart = if computeEPF then UPhaseStartEPF else 0 "Start value of phase-to-phase voltage phasor, phase angle";
  parameter Types.ActivePower PStart =  if computeEPF then PStartEPF else SNom "Start value of active power flowing into the port";
  parameter Types.ReactivePower QStart =  if computeEPF then QStartEPF else 0 "Start value of reactive power flowing into the port";

  parameter Types.Voltage UStartEPF(fixed = false) "Start value of phase-to-phase voltage phasor, absolute value, computed by the EPF";
  parameter Types.Angle UPhaseStartEPF(fixed = false) "Start value of phase-to-phase voltage phasor, phase angle, computed by the EPF";
  parameter Types.ActivePower PStartEPF(fixed = false) "Start value of active power flowing into the port, computed by the EPF";
  parameter Types.ReactivePower QStartEPF(fixed = false) "Start value of reactive power flowing into the port, computed by the EPF";

  Types.ComplexVoltage vEPF "Phase-to-ground voltage phasor of embedded power flow model";
  Types.ComplexCurrent iEPF "Line current phasor of embedded power flow model";
  ...
initial equation
  if computeEPF then
    // set values of initialization parameters based on EPF solution
    UStartEPF = CM.'abs'(vEPF)*sqrt(3);
    UPhaseStartEPF = CM.arg(vEPF);
    PStartEPF = 3*CM.real(vEPF*CM.conj(iEPF));
    QStartEPF = 3*CM.imag(vEPF*CM.conj(iEPF);
  else
    // set dummy values (not used)
    UStartEPF = 0;
    UPhaseStartEPF = 0;
    PStartEPF = 0;
    QStartEPF = 0;
  end if;
equation
  ...
  // set dummy values if the conditional sub-connectors with their binding equations are not activated
  if not computeEPF then
     vEPF = Complex(0) "Dummy value";
     iEPF = Complex(0) "Dummy value";
  if not hasSubEPF then
    connect(componentEPF.terminal, terminal.terminalEPF);
  end if;
  ...
  1. The TwoPortAC model can be handled similarly
  2. Every time a new component is defined that extends the base OnePortAC or TwoPortAC models, the conditional componentEPF sub-component must be redeclared to the desired model for the EPF computation, and parameterized accordingly. For example, the model of a transmission line with breakers can use the model of a constant impedance line as an EPF model, of course setting computeEPF = false for it to avoid infinite recursion:
model LineConstantImpedanceWithBreakers "Transmission line with constant impedance and breakers"
  extends BaseClasses.PiNetwork(
    redeclare LineConstantImpedance componentEPF(
      computeEPF = false,
      R = R, X = X, G = G, B = B,
      UNomA = UNom, UNomB= UNomA, SNom = SNom),
    UNomA = UNom, UNomB = UNomA,);
  parameter Types.Voltage UNom(start = 400e3) "Nominal/rated voltage";
  parameter Types.Resistance R "Series resistance";
  parameter Types.Resistance X "Series reactance";
  parameter Types.Conductance G = 0 "Shunt conductance";
  parameter Types.Conductance B = 0 "Shunt susceptance";
  ...

If computeEPF = false, there is actually no runtime overhead compared to the current architecture: the conditional EPF components and sub-connectors are not instantiated, and the dummy variables are set to zero once and for all during initialization. Start values for the PF can be set from some upstream source, or computed by default based on the nominal parameters, exactly as in the current architecture.

If computeEPF = true, a "mirror" system made by the componentEPF sub-components of the instantiated components, connected in the same way the main components are, is automatically built by the Modelica compiler when flattening the model. This sub-system does not depend on the main component equations, so it can be solved independently. In fact, since the power flow models have all constant inputs (e.g. PQ or PV values), the corresponding sub-system can be solved once and for all at initialization.

However, if the component is internally described by a sub-network of components that also have EPFs, then the EPF component should not be instantiated, and the EPF left to the sub-network components to handle. In this case, one needs to set hasSubEPF = true.

The dependency analysis of the Modelica compiler then automatically finds out that the parameters providing the start values for the main component equations depend on the solution of the EPF sub-system. In this way, the generated code automatically provides the right sequence of computations: first the EPF problem is solved, then the steady-state initialization problem for the transient model is solved, using start values obtained from the EPF model, and finally the dynamic simulation is carried out from the found initial steady-state.

Also note that most of the modifications to the existing library are found in the OnePortAC and TwoPortAC base classes. The impact on the actual model definitions is just the need to define the model for the EPF computation via a redeclare statement, using existing components. There is no need to add extra equations anywhere, when developing new component models with this enhancement.

IEEE14 models do not run on Dymola 2022 (Power Grids 1.0.2)

When I try to run IEEE14busStaticNetwork I get the following error message:

dymosim started
... "PowerGrids.Examples.IEEE14bus.IEEE14busStaticNetwork" simulating
... "dsin.txt" loading (dymosim input file)
... initial variable "_dummy" in file "dsin.txt" ignored (not in model).
... initial variable "_derdummy" in file "dsin.txt" ignored (not in model).
... initial variable "bus1.port.S.re" in file "dsin.txt" ignored (not in model).
... initial variable "bus1.port.S.im" in file "dsin.txt" ignored (not in model).
... initial variable "bus1.U" in file "dsin.txt" ignored (not in model).
... initial variable "bus1.theta" in file "dsin.txt" ignored (not in model).
... initial variable "Load2.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load2.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load3.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load3.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load4.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load4.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load5.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load5.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load6.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load6.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load9.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load9.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load10.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load10.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load11.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load11.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load12.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load12.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load13.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load13.Q" in file "dsin.txt" ignored (not in model).
... initial variable "Load14.P" in file "dsin.txt" ignored (not in model).
... initial variable "Load14.Q" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.localInit" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.SBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.UBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.VBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.IBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.VStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.IStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.vStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.vStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.iStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.iStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.u.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.u.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.S.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.I" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.PPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.QPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.vPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.vPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.VPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.iPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.iPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.IPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.UPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.IPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.port.IGenPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.P" in file "dsin.txt" ignored (not in model).
... initial variable "GEN1.U" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.localInit" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.SBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.UBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.VBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.IBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.VStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.IStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.vStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.vStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.iStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.iStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.u.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.u.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.S.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.I" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.PPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.QPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.vPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.vPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.VPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.iPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.iPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.IPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.UPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.IPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.port.IGenPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.P" in file "dsin.txt" ignored (not in model).
... initial variable "GEN2.U" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.localInit" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.SBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.UBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.VBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.IBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.VStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.IStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.vStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.vStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.iStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.iStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.u.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.u.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.S.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.I" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.PPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.QPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.vPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.vPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.VPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.iPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.iPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.IPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.UPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.IPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.port.IGenPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.P" in file "dsin.txt" ignored (not in model).
... initial variable "GEN3.U" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.localInit" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.SBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.UBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.VBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.IBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.VStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.IStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.vStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.vStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.iStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.iStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.u.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.u.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.S.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.I" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.PPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.QPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.vPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.vPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.VPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.iPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.iPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.IPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.UPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.IPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.port.IGenPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.P" in file "dsin.txt" ignored (not in model).
... initial variable "GEN6.U" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.localInit" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.SNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.UNom" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.SBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.UBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.PStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.QStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.UStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.UPhaseStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.portVariablesPhases" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.portVariablesPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.generatorConvention" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.VBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.IBase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.VStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.IStart" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.vStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.vStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.iStart.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.iStart.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.u.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.u.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.S.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.I" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.PPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.QPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.vPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.vPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.VPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.iPu.re" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.iPu.im" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.IPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.UPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.IPhase" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.port.IGenPu" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.P" in file "dsin.txt" ignored (not in model).
... initial variable "GEN8.U" in file "dsin.txt" ignored (not in model).
... solving initial value problem with non-linear equation solver
    (12 non-linear equations, tolerance=1.000000e-006).

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[5]
  For debugging information enable
  Simulation/Setup/Debug/Nonlinear solver diagnostics/Detailed logging of failed nonlinear solutions.
Trying to solve non-linear system using global homotopy-method.

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[6]
Trying to solve non-linear system using global homotopy-method.

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[6]
Error: Integrator failed to start model.

ERROR: The simulation of PowerGrids.Examples.IEEE14bus.IEEE14busStaticNetwork FAILED

When I try to run IEEE14busGen2Disconnection I get the following error message:

... "PowerGrids.Examples.IEEE14bus.IEEE14busGen2Disconnection" simulating
... "dsin.txt" loading (dymosim input file)

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[5]
  For debugging information enable
  Simulation/Setup/Debug/Nonlinear solver diagnostics/Detailed logging of failed nonlinear solutions.
Trying to solve non-linear system using global homotopy-method.

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[6]
Trying to solve non-linear system using global homotopy-method.

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[6]
Error: Integrator failed to start model.

ERROR: The simulation of PowerGrids.Examples.IEEE14bus.IEEE14busGen2Disconnection FAILED

When I try to run IEEE14busLine1to5Opening I get the following error message:

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[5]
  For debugging information enable
  Simulation/Setup/Debug/Nonlinear solver diagnostics/Detailed logging of failed nonlinear solutions.
Trying to solve non-linear system using global homotopy-method.

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[6]
Trying to solve non-linear system using global homotopy-method.

Warning: Failed to solve nonlinear system using Newton solver.
  During initialization at time: 0
  Tag: initialization.nonlinear[6]
Error: Integrator failed to start model.

ERROR: The simulation of PowerGrids.Examples.IEEE14bus.IEEE14busLine1to5Opening FAILED

Group all parameters needed for embedded power flow computations

PowerGrids 2.0.0 will feature an optional embedded power flow computation, to get the start values of voltage and power on the ports. This feature requires some parameters, that only need to be set if the embedded power flow is actually used, otherwise they can be left at their default values and will be ignored.

I would recommend to add the annotation(Dialog(group = "Embedded power flow"), enable = computePF) to all such parameters, so that they are easily identified, and automatically greyed out when they are not required.

Numerical problem at initialization when the AVR is saturated

The model in the tutorial that is initialized in steady-state with the AVR in saturation, PowerGrids.Examples.Tutorial.GridOperation.Controlled.ControlledGridWithReferenceCalculationSat fails because of singular initialization. This error was not caught in the past by our CI infrastructure because of a bug that made the outcome of the simulation look positive, while in fact there was none.

I have briefly checked the problem. My current understanding is that the culprit is the AVR model. When there is no saturation involved, the steady-state system equations determine efdPu, and then the blocks of the AVR are solved backwards in steady-state until the fixed=false offset value for the voltage set point is computed in the offset block.

When I lower the VrMax parameter of the AVR, this affects the firstOrderWithNonWindupLimiter block. However, the initial equation in the IEEE_AC4A model considers the input limiter, not the output limitation, so I guess this somehow creates a singularity because there are some variables in-between the two that may be undetermined.

We should carefully analyze this issue and improve the AC4A model so that this doesn't happen anymore.

Bus icon should be shorter

Buses are somewhat accessory parts of diagrams.

Power system diagrams are often filled of several components, and to have clear view of everything accurate choice of model icon locations is important.

This brings to the need to put buses near to other components, e.g. generators.
An example is in the following diagram:
image
Here I selected the bus. As you can see, the area that can be used for dragging buses (the four small red squares) overlaps generator's.
This is suboptimal, since makes trickier to move generators on some tools: in OpenModelica, clicking on the lower part of the generator icon and dragging moves the bus instead of the generator (in Dymola this does not occur, however).

I propose to make the vertical span of buses smaller. E.g. (-40,40) or (-30,30) instead of (-100, +100).

Translation errors with examples

Hi, I am getting the following translation errors on running any example

Variable S.re not found in scope PowerGrids.Electrical.BaseClasses.PortAC$GEN$port.

I am testing it on OpenModelica 1.16.0

Duplicated but nonidentical definitions

When validating PowerGrids.Examples.Tutorial.HowToBuild.Examples.TestLoadPQ from the develop branch in Wolfram System Modeler, I get:

Error: PowerGrids.Electrical.Buses.InfiniteBus: Invalid class definition. Element BUSINF.terminalAC is duplicated, but its definitions are not identical.

We can see this is the case when we compare:

redeclare PowerGrids.Interfaces.TerminalACBus terminalAC);

with:

redeclare PowerGrids.Interfaces.TerminalACBus terminalAC(
final computePF = computePF,
UStart = UStart, UPhaseStart = UPhaseStart,
v(re(start = port.vStart.re), im(start = port.vStart.im)),
i(re(start = port.iStart.re), im(start = port.iStart.im)),
terminalACPF(v = vPF, i = iPF)),

This is not valid Modelica.

Update tutorial with latest partial class structure

Recent commits to the develop branch changed the partial class structure, removing the OnePortACBus base class and the associated input/output mechanism for the propagation of voltage start values. The tutorial should be updated accordingly.

terminal hides terminal()

I'm trying to create a model that at the end of simulation writes some data on disk.
To do this I would use, inside a PVBus model

when terminal()
...
end when;

Unfortunately, this is impossible, since terminal() is hid by terminal.
In Dymola I get:
Error: Attempting to use the variable terminal as if it were a function.
Could be a spelling error, the local variable hiding a function in an enclosing scope, or using () instead of [] for subscripts.
Variable terminal declared at File: C:/Program Files/Dymola 2021/Modelica/Library/PowerGrids 1.0.2/Electrical/BaseClasses/OnePortAC.mo, line 21

I would use a different name for terminals in PowerGrids, e.g. PowerTerminal, or PGTerminal

Correction into local initialization for OnePortAC

In the OnePortAC, as noticed by an user, there seems to be a mistake in the local initialization PQ:

port.i.re*port.iStart.im = port.i.re*port.iStart.im;

should be:

 port.i.re*port.iStart.im = port.iStart.re*port.i.im;

PowerGrids.Electrical.Test.TestTransformerWithTapChangerInterval uses partial model

The TestTransformerWithTapChangerInterval model tries to access the enumeration value ActionType.direct inside the partial model PowerGrids.Electrical.Branches.BaseClasses.TapChangerPhaseShifterLogicCommon:

PowerGrids.Electrical.Branches.TransformerWithTapChangerInterval trafo(B = 0, G = 0, K = {2, 3, 4, 5, 6}, Ntap = 5, R = 1, SNom = 1e+06, UMax = 4000, UMin = 2000, UNomA = 1000, UNomB = 1000, X = 1, actionSel = PowerGrids.Electrical.Branches.BaseClasses.TapChangerPhaseShifterLogicCommon.ActionType.direct, portVariablesPu = true, t1st = 1, tNext = 0.1, tapStart = 2) annotation(

This is not allowed by the name lookup rules of Modelica, so either the model needs to be made non-partial or the enumeration value moved to some other non-partial scope.

Erroneously null current and voltage phases

Consider model mdl inside the following package:
Test.mo.txt
It shows the transient due to a short circuit at bus42, initiated at t=0.1 and removed at t=0.2.
Angular speeds and voltage amplitudes all are very reasonable.

However, a lot of phases are strangely exactly zero, such as:

  • phases of voltage and current at ports A and B of line L2_1
  • phases of voltage and current at ports of loads pq13 and pq42.

They cannot be all zero. In particular (in a line with zero resistance) if some power flows the phases of the two terminal voltages cannot be equal to each other, and therefore cannot be both zero.

Restructure tutorial

The current tutorial is organized in two sections:

  • Library Architecture
  • Examples

The first section goes very deep into the description of the library structure, which is interesting if you want to understand more and possibly develop your own models, but is definitely not necessary to start using the library. The tutorial should be restructured in three sections

  • Using the Library
  • Examples
  • Library Architecture

where the first section provides an introduction to the drag-n-drop use of the library without getting into the details on how it is organized internally.

Extend overconstrained connector semantics to allow runtime islanding and reconnection

The discussion in OMC #6240 comment 2 puts forward a proposal for an extension of the current overconstrained connector semantics, that could be used to allow runtime islanding and reconnection in PowerGrids with a nice object-oriented description and with very little additional code to the library.

Of course this requires a prototype implementation in OpenModelica and, if successful, to start the MCP process to get it into the Modelica specification. I believe the prototype implementation should be relatively straightforward.

@adriguir, @RomainLosseauRTE, @MarianneSaugierRTE, @max-privato, @dietmarw, I'd like to have your feedback on this.

Issue with machine parameters in IEEE14bus model

Simulate PowerGrids.Examples.IEEE14bus.IEEE14busStaticNetwork.

With OpenModelica, one gets GEN8.GEN.rQ2Pu = -0.035367765. Dymola actually fails during initialization while trying to compute GEN8.GEN.rQ2Pu.

Action 1: we should add asserts and/or min/max attributes to all the machine parameters that are found by means of nonlinear initial equations, to guard against bogus solutions.

Action 2: we should figure out if there is something wrong with the initial equations / parameter values / start values that hampers the convergence to a sensible value of that parameter.

Add documentation to ThreePhaseShort component

When looking for a bus fault the average user wonders what the difference between ThreePhaseFault and ThreePhaseShort is.
Unfortunately, Faults (as a folder) and ThreePhaseShort have no info, and therefore this question remains unanswered.

Indeed the two icons are clear enough, so I understantd that the "short" is a permanent connection, not really a fault, so I just miss one or two rows of explanation in the info.

BTW, what's the use of ThreePhaseShort?

Add reference files to OMC CI

Currently, we test PowerGrids on the OMC continuous integration infrastructure, but we do not have reference files. We should add them now, for regression testing between PowerGrids 1.0.2 and PowerGrids 2.0.0 and for testing with the new backend.

  1. Simulate all models of 1.0.2 with output filter port.v|port.i|omega
  2. Load them as references for 1.0.2. This helps for regression testing when using the new backend, which still doesn't work with 2.0.0
  3. Load them as references for 2.0.0. Check there are no regressions for models that already existed in 1.0.2
  4. Once it is sure there are no regressions between 1.0.2 and 2.0.0, simulate all models of 2.0.0 with output filter port.v|port.i|omega and generate reference results for 2.0.0
  5. Load them as references for 2.0.0, replacing the ones for 1.0.2

Errors in hydro governor models

Hi,
Many thanks for the nice library and your work. I recently started using the library and I think there are errors in the hydrogovernor models. For the damping term you use omegaPu instead of deltaOmegaPu (refer to equation (5) in [1]). Also the division in your model seems to be inverted compared to equation (4) in [1].

If you are interested I made my own working model. However, it uses a PI regulator and I also use the servo gate opening as the set point instead of the electrical power. This is inspired by the modelling in [2]. Otherwise, it is the same as the one you have implemented.

Cheers Sigurd

References
[1] Working Group Prime Mover and Energy Supply, "Hydraulic turbine and turbine control models for system dynamic studies," in IEEE Transactions on Power Systems, vol. 7, no. 1, pp. 167-179, Feb. 1992, doi: 10.1109/59.141700.
[2] L. Saarinen, P. Norrlund and U. Lundin, "Field Measurements and System Identification of Three Frequency Controlling Hydropower Plants," in IEEE Transactions on Energy Conversion, vol. 30, no. 3, pp. 1061-1068, Sept. 2015, doi: 10.1109/TEC.2015.2425915.

Convert PowerGrids to MSL 4.0.0?

@adriguir, MSL 4.0.0 has been out for a while, should we make a 2.0.0 release which is MSL 4.0.0 compatible? Future versions of MSL will be backwards compatible for a few years, so I think we should do this ASAP to avoid new users the trouble of converting later to that.

What do you think?

BusFault model

@AndreaBartolini @casella I planned to add a new test case with a bus fault for IEEE14 system as well as potentially developing a line fault model (ie having a fault applied somewhere on a line) and thus I had a look to the bus fault model.

The most natural implementation of such a model for me would have been something like:
when (t >= tBegin and t < tEnd) then ZI = V elsewhen then I = 0
which directly reflects the fact that I add a link between the port and the earth during the short-circuit.

Is there a particular reason to have implemented the when loop inside algorithm blocks? Is there an advantage of using the intermediate fault boolean value?

Data on diagram issues

I find some issues on the option of "ShowDataOndiagrams" feature:

  1. I suppose not all people need to see all those labels, that clutter large diagrams. If one selects ShowDataOnDiagramsPu=false and ShowDataOnDiagramsSi=false numerical data should be omitted from diagrams, I suppose.
  2. no info on this feature is in the documentation (which is lacking for a lot of other aspects). For instance I had to see by trial that the data showen in a transient are those at the beginning of the it (at the end of PF computation) and not at the end of it.

A third issue is more involed. Consider a line icon. The instance name can be put above o below the line through a flip operation (here I used PowerGrids 1.0, because of the issue 1 above):
image

The name above the icon is the "classic" position of MSL.

In PowerGrids now it is possible to visualize also P and Q;
image

The natural order of P and Q is, first P, then Q, because they are always listed this way, which is also the importance and alphabetic order. To do this, one has to use the line icon in such a way that P and Q are below the line. This is somewhat unnatural, since usually fluxes are shown above lines and components.

This part of this ticket it to propose to exchange positions of P and Q for lines and transformers. If we do this, we obtain P and Q in the right order when they are above the line. This implies that the instance name is below, but this is a minor inconvenience, because those that do not use display of P and Q can always flip the icon to have names above them (if issue 1 above is solved).

Model verification with discrete keyword

Apparently, the two following models (LineConstantImpedanceWithBreakers and IEEEbusPowerFlow which is using the first mentioned) don't validate with Dymola.
The problem comes from the variable YA_Actual, YB_Actual and Y_Actual that are defined with the prefix discrete and used outside a when loop (indeed into an if condition statement, itself depending on an algorithm output). What I see in the language specification is that a discrete variable can only change its value at events during simulation. I suppose that the condition of the if being set by a when, this statement is verified in the current implementation but I would like to have other advices.

@casella @AndreaBartolini what is your opinion?

Base for the SM excitation current

I see that PowerGrids library proposes examples from IEEE, so I expect it to be written having IEEE 421.5 in mind.
In Annex B of IEEE 421.5-2005 (IEEE 421.5-2016 says the same) I read:
one pu generator field current is that current required to produce rated synchronous machine terminal voltage on the air-gap line, and one pu field voltage is the corresponding field voltage.

This implies that in steady-state the ratio field voltage/field current must be always 1, for linear machines such as PowerGrid's.

In PowerGrid's ENTSOE-TestCase1 I see in the first times (when the machine has no load), ufPuIn=1.0000 and ifPu=0.540541, so the ratio is 1.85. Where does this value come from?

A correct pu value for field currents is important if one wants to use exciters requiring it. I'm currently working on ExcAC6A, which needs this current, but also IEEE_ST4B, included in PowerGrids, receives it as input.

Do I miss something?

Recommend Projects

  • React photo React

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

  • Vue.js photo Vue.js

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

  • Typescript photo Typescript

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

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

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

  • web

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

  • server

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

  • Machine learning

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

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

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

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.