From b076f777df4d07dab78eadd27b1c7239baa3f6ca Mon Sep 17 00:00:00 2001 From: ch Date: Tue, 22 Jun 2021 15:21:32 +0200 Subject: [PATCH] release 1.0 --- AUTHORS | 3 + CITATION | 6 +- CODE | 12 +- DEMO.m | 26 +- README.md | 496 +++++++++++++----- RUNME.m => RUNME_HimpeGB21.m | 13 +- SETUP.m | 5 +- VERSION | 3 +- doc/{morgen-0.99.pdf => morgen-1.0.pdf} | Bin 1321864 -> 1322379 bytes models/ode_end.m | 13 +- models/ode_mid.m | 13 +- models/private/D_f.m | 3 +- models/private/D_g.m | 2 +- models/private/D_p.m | 2 +- models/private/D_q.m | 2 +- {utils => models/private}/circsurf.m | 2 +- models/template_model.m | 4 +- morgen.ini | 28 +- morgen.m | 370 +++++++------ morgen.png | Bin 0 -> 2522 bytes networks/{PamBD16.net => AzePA19.net} | 7 +- networks/AzePA19/period.ini | 6 + networks/AzePA19/training.ini | 6 + networks/BerS19.net | 12 + networks/BerS19/training.ini | 6 + networks/EkhDLetal19.net | 28 +- networks/EkhDLetal19/training.ini | 2 +- networks/GasLib11.net | 2 +- networks/GasLib40/training.ini | 2 +- networks/GruHKetal13.net | 32 +- networks/GruHKetal13/training.ini | 2 +- networks/GruJHetal14.net | 80 +-- networks/GruJHetal14/training.ini | 4 +- networks/Kiu94.net | 32 +- networks/Kiu94/training.ini | 4 +- networks/PamBD16/day.ini | 6 - networks/PamDB16.net | 8 + networks/PamDB16/period.ini | 6 + networks/{PamBD16 => PamDB16}/training.ini | 2 +- networks/PamEBetal17.net | 42 ++ networks/PamEBetal17/training.ini | 7 + networks/{norway.net => SciGrid_NO.net} | 0 networks/{norway => SciGrid_NO}/training.ini | 0 networks/paratest.net | 6 + networks/paratest/training.ini | 6 + networks/template_network.net | 2 + networks/template_network/training.ini | 6 + reductors/bpod_ro.m | 31 +- reductors/bpod_ro_l.m | 33 +- reductors/dmd_r.m | 27 +- reductors/ebg_ro.m | 34 +- reductors/ebg_ro_l.m | 36 +- reductors/ebg_wx.m | 30 +- reductors/ebg_wx_l.m | 32 +- reductors/ebg_wz.m | 30 +- reductors/ebg_wz_l.m | 32 +- reductors/ebt_ro.m | 31 +- reductors/ebt_ro_l.m | 33 +- reductors/ebt_wx.m | 27 +- reductors/ebt_wx_l.m | 29 +- reductors/ebt_wz.m | 27 +- reductors/ebt_wz_l.m | 29 +- reductors/eds_ro.m | 30 +- reductors/eds_ro_l.m | 32 +- reductors/eds_wx.m | 26 +- reductors/eds_wx_l.m | 28 +- reductors/eds_wz.m | 26 +- reductors/eds_wz_l.m | 28 +- reductors/gopod_r.m | 32 +- reductors/pod_r.m | 27 +- reductors/private/balgn.m | 2 +- reductors/private/balro.m | 2 +- reductors/private/bpod.m | 2 +- reductors/private/dmd.m | 2 +- reductors/template_reductor.m | 14 +- solvers/generic.m | 26 +- solvers/imex1.m | 37 +- solvers/imex2.m | 37 +- solvers/rk4.m | 60 +-- solvers/template_solver.m | 21 +- tests/mor_Cha09.m | 4 +- tests/mor_DeWS00.m | 5 +- tests/mor_GasLib134.m | 6 +- tests/mor_MORGEN.m | 6 +- tests/mor_PamDB16.m | 48 ++ tests/mor_debug.m | 16 +- tests/mor_komso.m | 2 +- tests/mor_pipeline.m | 2 +- tests/mor_template.m | 44 ++ tests/sim_AzeJ07.m | 2 +- tests/sim_AzePA19.m | 13 + tests/sim_BerS19.m | 13 + tests/sim_Cha09.m | 2 +- tests/sim_DeWS00.m | 2 +- tests/sim_EkhDLetal19.m | 13 + tests/sim_GasLib11.m | 2 +- tests/sim_GasLib134.m | 2 +- tests/sim_GasLib135.m | 2 +- tests/sim_GasLib24.m | 2 +- tests/sim_GasLib40.m | 2 +- tests/sim_GasLib4197.m | 2 +- tests/sim_GasLib582.m | 2 +- tests/sim_GruHKetal13.m | 8 +- tests/sim_GruJHetal14.m | 13 + tests/sim_Guy67.m | 2 +- tests/sim_Kiu94.m | 4 +- tests/sim_MORGEN.m | 2 +- tests/sim_PamDB16.m | 13 + tests/sim_PamEBetal17.m | 13 + tests/sim_RodS18.m | 2 +- tests/{sim_norway.m => sim_SciGrid_NO.m} | 4 +- tests/sim_comptest.m | 2 +- tests/sim_debug.m | 2 +- tests/sim_diamond.m | 2 +- tests/sim_fork1.m | 2 +- tests/sim_fork2.m | 2 +- tests/sim_paratest.m | 13 + tests/sim_pipeline.m | 2 +- tests/sim_template.m | 13 + tools/cmp_compressibility.m | 13 + tools/cmp_friction.m | 2 +- tools/csv2net.m | 4 +- tools/json2net.m | 6 +- utils/cfl.m => tools/psi2bar.m | 8 +- tools/randscen.m | 20 +- tools/vf2kgs.m | 49 ++ tools/vf2mf.m | 14 - tools/xml2net.xsl | 2 +- utils/assert_warn.m | 7 +- utils/cleanup.m | 14 +- utils/cmov.m | 2 +- utils/compressibility/compressibility_aga88.m | 2 +- utils/compressibility/compressibility_dvgw.m | 2 +- utils/compressibility/compressibility_ideal.m | 2 +- utils/compressibility/compressibility_papay.m | 2 +- utils/constant/constant_gravity.m | 2 +- utils/format/format_ini.m | 2 +- utils/format/format_network.m | 61 +-- utils/format/format_scenario.m | 17 +- utils/format/save_ini.m | 2 +- utils/friction/friction_altshul.m | 2 +- utils/friction/friction_hofer.m | 2 +- utils/friction/friction_igt.m | 2 +- utils/friction/friction_nikuradse.m | 2 +- utils/friction/friction_pmt1025.m | 2 +- utils/friction/friction_schifrinson.m | 2 +- utils/inifield.m | 2 +- utils/logger.m | 123 +++++ utils/make_rom.m | 58 +- utils/morscore.m | 2 +- utils/norm/norm_l0.m | 2 +- utils/norm/norm_l1.m | 2 +- utils/norm/norm_l2.m | 2 +- utils/norm/norm_l8.m | 2 +- utils/plot/plot_breven.m | 11 +- utils/plot/plot_error.m | 13 +- utils/plot/plot_offline.m | 7 +- utils/plot/plot_online.m | 11 +- utils/plot/plot_output.m | 55 +- utils/plot/private/legend_print.m | 2 +- utils/plot/private/lines13.m | 2 +- utils/setfields.m | 2 +- utils/sparsegrid.m | 2 +- utils/steadystate.m | 28 +- utils/thunklog.m | 47 -- utils/training/training_impulse.m | 2 +- utils/training/training_randombinary.m | 2 +- utils/training/training_step.m | 2 +- utils/training/training_whitenoise.m | 2 +- utils/units/celsius2kelvin.m | 2 +- utils/units/kelvin2celsius.m | 2 +- utils/varfield.m | 2 +- 172 files changed, 2029 insertions(+), 1106 deletions(-) rename RUNME.m => RUNME_HimpeGB21.m (51%) rename doc/{morgen-0.99.pdf => morgen-1.0.pdf} (94%) rename {utils => models/private}/circsurf.m (91%) create mode 100644 morgen.png rename networks/{PamBD16.net => AzePA19.net} (53%) create mode 100644 networks/AzePA19/period.ini create mode 100644 networks/AzePA19/training.ini create mode 100644 networks/BerS19.net create mode 100644 networks/BerS19/training.ini delete mode 100644 networks/PamBD16/day.ini create mode 100644 networks/PamDB16.net create mode 100644 networks/PamDB16/period.ini rename networks/{PamBD16 => PamDB16}/training.ini (84%) create mode 100644 networks/PamEBetal17.net create mode 100644 networks/PamEBetal17/training.ini rename networks/{norway.net => SciGrid_NO.net} (100%) rename networks/{norway => SciGrid_NO}/training.ini (100%) create mode 100644 networks/paratest.net create mode 100644 networks/paratest/training.ini create mode 100644 networks/template_network.net create mode 100644 networks/template_network/training.ini create mode 100644 tests/mor_PamDB16.m create mode 100644 tests/mor_template.m create mode 100644 tests/sim_AzePA19.m create mode 100644 tests/sim_BerS19.m create mode 100644 tests/sim_EkhDLetal19.m create mode 100644 tests/sim_GruJHetal14.m create mode 100644 tests/sim_PamDB16.m create mode 100644 tests/sim_PamEBetal17.m rename tests/{sim_norway.m => sim_SciGrid_NO.m} (78%) create mode 100644 tests/sim_paratest.m create mode 100644 tests/sim_template.m create mode 100644 tools/cmp_compressibility.m rename utils/cfl.m => tools/psi2bar.m (61%) create mode 100644 tools/vf2kgs.m delete mode 100644 tools/vf2mf.m create mode 100644 utils/logger.m delete mode 100644 utils/thunklog.m diff --git a/AUTHORS b/AUTHORS index 0ef925b..614f2e3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,6 @@ Christian Himpe (orcid:0000-0003-2194-6754) - Design, Architecture, Coding, Testing, Debugging, Documentation Sara Grundel (orcid:0000-0002-0209-6566) - Coding, Testing, Debugging +Stephen Werner (orcid:0000-0003-1667-4862) - Code Review, Testing +Tim Mitchell (orcid:0000-0002-8426-0242) - Code Review, Testing +Jens Saak (orcid:0000-0001-5567-9637) - Code Review, Testing diff --git a/CITATION b/CITATION index 76b3f33..d6db602 100644 --- a/CITATION +++ b/CITATION @@ -1,8 +1,8 @@ Cite As: -C. Himpe, S. Grundel, P. Benner (2021): -"Model Order Reduction for Gas and Energy Networks"; -arXiv (math.OC): 2011.12099. +C. Himpe, S. Grundel, P. Benner: +Model Order Reduction for Gas and Energy Networks; +arXiv (math.OC): 2011.12099, 2021. https://arxiv.org/abs/2011.12099 BibTeX Entry: diff --git a/CODE b/CODE index e8c71fb..d1d67c8 100644 --- a/CODE +++ b/CODE @@ -1,12 +1,12 @@ # code.ini name: Model Order Reduction for Gas and Energy Networks shortname: morgen -version: 0.99 -release-date: 2021-04-12 -id: 10.5281/zenodo.4680265 +version: 1.0 +release-date: 2021-06-22 +id: 10.5281/zenodo.4288509 id-type: doi author: Christian Himpe, Sara Grundel -orcid: 0000-0003-2194-6754, +orcid: 0000-0003-2194-6754, 0000-0002-0209-6566 topic: Gas Network Simulation type: Platform license: BSD-2-Clause @@ -15,6 +15,6 @@ repository: github.com/mpcsc/morgen repository-type: git language: Matlab dependencies: Octave >=6.1, Matlab >=2020b -systems: Linux, Windows -website: github.com/mpcsc/morgen +systems: Linux, Windows, macOS +website: git.io/morgen keywords: Model Reduction, Model Order Reduction, Gas Network, Gas Transport, Digital Twin diff --git a/DEMO.m b/DEMO.m index 63504ef..9e0129d 100644 --- a/DEMO.m +++ b/DEMO.m @@ -1,9 +1,29 @@ %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Basic demonstration of simulation and model reduction. -SETUP -mor_pipeline +morgen('pipeline', ... % Network + 'day', ... % Scenario + 'ode_end', ... % Model + 'imex1', ... % Solver + { ... % Reductors: + 'pod_r', ... % Proper Orthogonal Decomposition (Reachability-Based) + 'eds_ro_l', ... % Empirical Dominant Subspaces (Reachability-Observability-Based) Primal-Dual Variant + 'eds_wx_l', ... % Empirical Dominant Subspaces (Minimality-Based) Primal-Dual Variant + 'eds_wz_l', ... % Empirical Dominant Subspaces (Averaged-Minimality-Based) Primal-Dual Variant + 'bpod_ro_l', ... % Balanced Proper Orthogonal Decomposition (Reachability-Observability-Based) Primal-Dual Variant + 'ebt_ro_l', ... % Empirical Balanced Truncation (Reachability-Observability-Based) Primal-Dual Variant + 'ebt_wx_l', ... % Empirical Balanced Truncation (Minimality-Based) Primal-Dual Variant + 'ebt_wz_l', ... % Empirical Balanced Truncation (Averaged-Minimality-Based) Primal-Dual Variant + 'gopod_r', ... % Goal-Oriented Proper Orthogonal Decomposition (Reachability-Based) + 'ebg_ro_l', ... % Empirical Balanced Gains (Reachability-Observability-Based) Primal-Dual Variant + 'ebg_wx_l', ... % Empirical Balanced Gains (Minimality-Based) Primal-Dual Variant + 'ebg_wz_l', ... % Empirical Balanced Gains (Averaged-Minimality-Based) Primal-Dual Variant + 'dmd_r', ... % Dynamic Mode Decomposition Galerkin (Reachability-Based) + }, ... % Ad-hoc configuration: + 'dt=10', ... % Use 10s time-steps + 'ord=50', ... % Maximum reduced order 50 (computation and evaluation) + 'compact'); % Make compact plot instead of individual diff --git a/README.md b/README.md index 936ceb9..a474ec1 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,34 @@ -morgen -- Model Order Reduction for Gas and Energy Networks (Version 0.99) -========================================================================== +![morgen logo](morgen.png) morgen -- Model Order Reduction for Gas and Energy Networks (1.0) +============================================================================================ **morgen** is an open-source MATLAB and OCTAVE test platform to compare models, -solvers, and model reduction methods for gas networks and other energy network -systems, based on the isothermal Euler equations, against each other. - -## Development Guidelines - -* The main branch must complete tests successfully **!** -* Source headers must include: project, version, authors, license, summary **!** -* Understand [closures](https://en.wikipedia.org/wiki/Closure_%28computer_programming%29) **!** +solvers, and model reduction methods (reductors) for gas networks and other +energy network systems that are based on the isothermal Euler equations. ## Compatibility -* Mathworks [MATLAB](https://matlab.com) >= 2020b +* Mathworks [MATLAB](https://www.mathworks.com/products/matlab.html) >= 2020b * GNU [Octave](https://octave.org) >= 6.1 ## Dependencies -* [emgr](https://gramian.de) == 5.9 (included) +* [emgr](https://gramian.de) == 5.9 (included, see `reductors/private`) ## License -**morgen** is licensed under the [BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause) license. +**morgen** is licensed under the [BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause) license, +with copyright (c) 2020--2021: _Christian Himpe_, _Sara Grundel_; see [LICENSE](LICENSE). ## Disclaimer -**morgen** is research software and under ongoing development. +**morgen** is research software. ## Citation Please cite the **morgen** platform via its companion paper: C. Himpe, S. Grundel, P. Benner: -**Moder Order Reduction for Gas and Energy Networks**; +**Model Order Reduction for Gas and Energy Networks**; arXiv (math.OC): 2011.12099, 2021. [arXiv:2011.12099](https://arxiv.org/abs/2011.12099) @@ -42,39 +37,88 @@ arXiv (math.OC): 2011.12099, 2021. To try **morgen**: ``` -> SETUP % adds the "tests" folder to the path and lists scripts > DEMO % runs a sample pipeline model reduction code ``` +To setup simulation and reduction tests: + +``` +> SETUP % adds the "tests" folder to the path and lists scripts +``` + +Tests can then be called directly as listed. + +### Reproducibility + +To reproduce the experiments from the companion paper, +**Model Order Reduction for Gas and Energy Networks**, run: + +``` +> RUNME_HimpeGB21 +``` + +### Extending **morgen** + +**morgen**'s modules can be easily extended in the following ways: + +* to add a new model, see and modify: `models/template_model.m` +* to add a new solver, see and modify: `solvers/template_solver.m` +* to add a new reductor, see and modify: `reductors/template_reductor.m` +* to add a new network, see and modify: `networks/template_network.net` +* to add a new scenario, see and modify: `networks/template_network/training.ini` +* to add a new simulation test, see and modify: `tests/sim_template.m` +* to add a new reduction test, see and modify: `tests/mor_template.m` + ## Usage -The **morgen** platform is called via the `morgen` function: +The **morgen** platform is called via the `morgen.m` function: ``` -morgen(network_id,scenario_id,model_id,solver_id,reductor_ids,varargin) +R = morgen(network_id,scenario_id,model_id,solver_id,reductor_ids,varargin) ``` -and has five mandatory arguments: +and has four mandatory arguments: -* `network_id` (string) The network identifier -* `scenario_id` (string) The scenario identifier -* `model_id` (string) The model identifier -* `solver_id` (string) The solver identifier -* `reductor_ids` (cell) An array of reductor identifiers +* `network_id` (**string**) The network identifier +* `scenario_id` (**string**) The scenario identifier +* `model_id` (**string**) The model identifier +* `solver_id` (**string**) The solver identifier -as well as additional variable length argument list: +as well as an optional argument and an additional variable length argument list: -* `varargin` (cell) an array of flag identifiers +* `reductor_ids` (**cell**) An array of reductor identifiers (can be empty, too) +* `varargin` Variable argument list each containing a string (see below) -all of which are described below: +All admissible additional (**string**) arguments are described below: -* `dt=X` - Override requested time step in configuration with X (in seconds) +* `dt=X` - Override time step in configuration with X (in seconds) +* `tf=X` - Override tunable efficiency factor in configuration with X (positive real) * `ys=X` - Force minimum y-scale for error plots with 10^X (default: -16) * `ord=X` - Override evaluation order in configuration with X (natural number) * `pid=X` - Add custom string identifier to plots (default: '') * `notest` - Do not test the reduced order models * `compact` - Display plots all in one figure +The `morgen.m` function returns a structure `R` with members depending on the +arguments. +If only reduced order models are computed: + +* `.reductors` (**cell**) Array of strings with names of the reductors +* `.offline` (**cell**) Array of offline times for the reductors + +If reduced order models are computed and tested: + +* `.name` (**string**) Output name of the experiment (as used by saved plots and scores) +* `.reductors` (**cell**) Array of strings with names of the reductors +* `.orders` (**vector**) The tested reduced orders +* `.l0error` , `.l1error` , `.l2error` , `.l8error` (**cell**) Arrays of per reduced order average errors +* `.l0score` , `.l1score` , `.l2score` , `.l8score` (**cell**) Arrays of per reduced order average [MORscores](https://doi.org/10.1007/978-3-030-72983-7_7) +* `.offline` (**cell**) Array of offline times for the reductors +* `.online` (**cell**) Array of average relative online times for the reductors +* `.breven` (**cell**) Array of average relative offline/online break even numbers + +If only a simulation is run, `R` contains the discrete output trajectory as an outputs-times-time-steps matrix. + ### Network A network is described by a (directed) graph, given through an edgelist, @@ -86,36 +130,38 @@ which also specifies its edge type, and their physical dimensions and properties * All boundary nodes (supply or demand) must connect by exactly one edge! * Short pipes can be inserted to enforce this. * The edge from a supply node must be directed away from it! - * Hence: No two supply nodes may be directly connected. + * Hence, no two supply nodes can be directly connected. * The edge to a demand node must be directed toward it! + * Hence, no two demand nodes can be directly connected. -#### Available +#### Available Networks All available network datasets are listed with the network's number of - * internal junction nodes (n0), - * supply boundary nodes (nS), and - * demand boundary nodes (nD). + * internal junction nodes (`n0`), + * supply boundary nodes (`nS`), and + * demand boundary nodes (`nD`). -##### Toy +##### Toy Networks * `diamond` - Diamond Network (`n0=8, nS=1, nD=1`) * `fork1` - Forked Pipeline (`n0=12, nS=1, nD=2`) * `fork2` - Forked Pipeline (`n0=12, nS=2, nD=1`) * `comptest` - Compressor Test (`n0=1, nS=1, nD=1`) +* `paratest` - Parallel Pipes Test (`n0=2, nS=1, nD=1`) * `PamBD16` - Triangle Network (`n0=0, nS=1, nD=2`) -##### Synthetic +##### Synthetic Networks * `MORGEN` - Small Network (`n0=27, nS=2, nD=4`) -* `AzeJ07` - Small Network (`n0=5, nS=1, nD=2`) +* `AzeJ07` - Small Network (`n0=5, nS=1, nD=2`) * `GruHKetal13` - Small Network (`n0=11, nS=1, nD=8`) * `Kiu94` - Small Network (`n0=8, nS=1, nD=14`) -* `GruJHetal14` - Medium Network (`n0=?, nS=4, nD=2`) +* `GruJHetal14` - Medium Network (`n0=45, nS=4, nD=2`) * `GasLib11` - Medium Network (`n0=6, nS=3, nD=3`) * `GasLib24` - Medium Network (`n0=14, nS=3, nD=5`) -* `GasLib40` - Medium Network (`n0=?, nS=3, nD=29`) -* `GasLib135` - Medium Network (`n0=?, nS=3, nD=45`) +* `GasLib40` - Medium Network (`n0=40, nS=3, nD=29`) +* `GasLib135` - Medium Network (`n0=135, nS=3, nD=45`) ##### Pipelines @@ -124,13 +170,16 @@ All available network datasets are listed with the network's number of * `RodS18` - Tree (`n0=6, nS=1, nD=4`) * `Guy67` - Tree (`n0=8, nS=1, nD=8`) -##### Realistic +##### Realistic Networks -* `DeWS00` - Belgium (`n0=20, nS=6, nD=9`) -* `EkhDLetal19` - Ireland (`n0=26, nS=3, nD=10`) -* `GasLib134` - Greece (`n0=?, nS=3, nD=45`) -* `GasLib582` - Germany (`n0=?, nS=31, nD=129`) -* `GasLib4197` - Germany (`n0=?, nS=11, nD=1009`) +* `AzePA19` - Portugal (`n0=0, nS=1, nD=1`) +* `BerS19` - Spain (`n0=6, nS=1, nD=5`) +* `DeWS00` - Belgium (`n0=20, nS=6, nD=9`) +* `EkhDLetal19` - Ireland (`n0=26, nS=3, nD=10`) +* `GasLib134` - Greece (`n0=134, nS=3, nD=45`) +* `GasLib582` - Germany (`n0=582, nS=31, nD=129`) +* `GasLib4197` - Germany (`n0=4197, nS=11, nD=1009`) +* `SciGrid_NO` - Norway (`n0=44, nS=11, nD=9`) #### Data Origin @@ -138,48 +187,90 @@ The GasLib network data-sets are derived from: M. Schmidt, D. Aßmann, R. Burlacu, J. Humpola, I. Joormann, N. Kanelakis, T. Koch, D. Oucherif, M.E. Pfetsch, L. Schewe, R. Schwarz, M. Sirvent: -"GasLib - A Library of Gas Network Instances"; +**GasLib - A Library of Gas Network Instances**; Data 2(4): 40, 2017. -and licensed under **CC-BY**, see: https://gaslib.zib.de +and licensed under **CC-BY 3.0**, see: https://gaslib.zib.de #### File Format -A network is encoded in a [CSV](https://en.wikipedia.org/wiki/Comma-separated_values) file with the file extension `.net`. -The first line is a comment header with a description of the columns, their meaning, and units. +A network is encoded in a [CSV](https://en.wikipedia.org/wiki/Comma-separated_values) +file with the file extension `.net`. The first line is a comment header with a +description of the columns, their meaning, and units. +``` +# type, identifier-in, identifier-out, pipe-length [m], pipe diameter [m], height difference [m], pipe roughness [m] +``` Each line below the first holds one edge definition with the columns: * Edge type (`P`:pipe, `S`:shortpipe, `C`:compressor, `V`:valve) * Start node identifier (positive integer) * End node identifier (positive integer) -* Pipe lengths [m] (positive real) -* Pipe diameters [m] (positive real) -* Pipe height difference [m] (positive real) -* Pipe roughness [m] (positive real) - -Thus, the gas network's directed graph is represented as an edge list. +* Pipe length [`m`] (positive real) +* Pipe diameter [`m`] (positive real) +* Pipe height difference [`m`] (positive real) +* Pipe roughness [`m`] (positive real) + +Thus, the gas network's directed graph is represented as an edge list, whereas +the edge directions are not corresponding to flow directions except for boundary +nodes. Note, currently only positive integers can be used as start and end identifiers. +#### Parsed Network Structure + +A parsed network `.net` file is given as a `network` structure with members: + +* `network` (**struct**) + * `.length` (**vector**) Pipe lengths + * `.incline` (**vector**) Pipe inclines + * `.diameter` (**vector**) Pipe diameters + * `.roughness` (**vector**) Pipe roughnesses + * `.nomLen` (**vector**) Per pipe length + * `.A0` (**matrix**) Incidence matrix reduced by supply nodes + * `.Ac` (**matrix**) Incidence matrix of only compressor outlet nodes + * `.Bs` (**matrix**) Incidence matrix of supply nodes + * `.Bd` (**matrix**) Incidence matrix of demand nodes + * `.Fc` (**vector**) Load vector of compressors + * `.nEdges` (**scalar**) Number of edges + * `.nSupply` (**scalar**) Number of supply nodes + * `.nDemand` (**scalar**) Number of demand nodes + * `.nInternal` (**scalar**) Number of internal nodes + * `.nCompressor` (**scalar**) Number of compressors + ### Scenario -A scenario data set describes the boundary values and external inhomogeneities of the gas net. -Transient behaviour of supply and demand functions is represented as step functions in compressed form by only marking changes. -Each network has a training scenario (`training.ini`), which has constant boundary values for reduced order model assembly. +A scenario data set describes the boundary values and external inhomogeneities +of the gas net. Transient behaviour of supply and demand functions is +represented as step functions in compressed form by only marking changes. +Each network has a training scenario (`training.ini`), which has constant +boundary values for reduced order model assembly. #### File Format -A scenario is encoded in an [INI](https://en.wikipedia.org/wiki/INI_file) file, with the extension `.ini`. -Each line holds a key-value pair, for the following keys: - -* `T0` - Average ambient temperature [C] -* `Rs` - Average specific gas constant [J/(kg*K)] -* `tH` - Time horizon [s] -* `vs` - Valve setting [1] (pipe separated list of {0,1}) -* `cp` - Compressor (output) pressure [bar] (pipe separated list) -* `up` - Supply pressure changes [bar] (pipe separated list of semi-colon separated series) -* `uq` - Demand flow changes [kg/s] (pipe separated list of semi-colon separated series) +A scenario is encoded in an [INI](https://en.wikipedia.org/wiki/INI_file) file, +with the extension `.ini`. Each line holds a key-value pair, for the following +keys: + +* `T0` - Average ambient temperature [`C`] +* `Rs` - Average specific gas constant [`J/(kg*K)`] +* `tH` - Time horizon [`s`] +* `vs` - Valve setting [`1`] (pipe separated list of {0,1}) {UNDER CONSTRUCTION} +* `cp` - Compressor (output) pressure [`bar`] (pipe separated list) +* `up` - Supply pressure changes [`bar`] (pipe separated list of semi-colon separated series) +* `uq` - Demand flow changes [`kg/s`] (pipe separated list of semi-colon separated series) * `ut` - Time markers for changes in `up` and `uq` [s] +#### Parsed Scenario Structure + +A parsed network `.ini` file is given as: + +* `scenario` (**struct**) + * `.T0` (**scalar**) Global mean temperature + * `.Rs` (**scalar**) Global mean + * `.tH` (**scalar**) Time horizon + * `.us` (**vector**) Steady-state input + * `.ut` (**handle**) Function handle with signature u_t = ut(t) + * `.cp` (**vector**) Compressor outlet pressures + ### Model A model encodes a spatially discrete input-output system of the form: @@ -210,14 +301,14 @@ and an (uni-directionally coupled algebraic) output equation. - `.nPorts` (**scalar**) Number of ports - `.E` (**handle**) Mass matrix function handle Ertz = E(rtz) - `.A` (**matrix**) System matrix - - `.As` (**matrix**) Copy of the system matrix (see template) - `.B` (**matrix**) Input matrix (models boundary nodes) - `.F` (**matrix**) Source matrix (models the compressor action) - `.C` (**matrix**) Output matrix (sensors at boundary nodes) - `.f` (**handle**) Nonlinear vector field x = f(xs,x,u,rtz) - `.J` (**handle**) Jacobian x = J(xs,x,u,rtz) + - `.dual` (**bool**) This is only a member (of any value) if it is a dual model! -#### Available +#### Available Models * `ode_mid` - ODE model using the mid-point discretization * `ode_end` - ODE model using the end-point discretization (port-Hamiltonian) @@ -226,15 +317,17 @@ and an (uni-directionally coupled algebraic) output equation. * The argument `xs` is the steady state computed in the solver. * The argument `x` in nonlinearity `f` and Jacobian `J` refers to the difference to the steady-state. - This means the `xs+x` yields the actual state. + This means `xs + x` yields the actual state. * Only the components `E`, `f` and `J` are parametrized. Particularly, `A` and `B` do not depend on the parameter. +* Compressors can only be operated in discharge pressure control mode. * The argument `rtz` is the product `Rs*T0*z0` formed in the solver. ### Solver -A solver is a time stepper that simulates a trajectory of a model and a scenario. -The prerequisite steady-state initial value is computed from the scenario's boundary values. +A solver is a time stepper that simulates a trajectory of a model and a +scenario. The prerequisite steady-state initial value is computed from the +scenario's boundary values. #### Interface @@ -248,34 +341,31 @@ The prerequisite steady-state initial value is computed from the scenario's boun #### Returns -* `solution` (**struct**) - * `t` (**vector**) Time-steps vector - * `u` (**matrix**) Discrete inputs-times-steps trajectory - * `y` (**matrix**) Discrete outputs-times-steps trajectory - * `steady` (**struct**) Steady-state solution structure - * `xs` (**vector**) Steady-state - * `ys` (**vector**) Steady-state output - * `z0` (**scalar**) Global average compressibility - * `err` (**scalar**) Steady-state error - * `iter1` (**scalar**) Algebraic steady-state iterations - * `iter2` (**scalar**) Differential steady-state iterations - * `runtime` (**scalar**) Transient solver runtime - -#### Available - -* `rk4` - Fourth-order "classic" explicit Runge-Kutta solver +* `solution` (**struct**) + * `t` (**vector**) Time-steps vector + * `u` (**matrix**) Discrete inputs-times-steps trajectory + * `y` (**matrix**) Discrete outputs-times-steps trajectory + * `steady_z0` (**scalar**) Global average compressibility + * `steady_error` (**scalar**) Steady-state error + * `steady_iter1` (**scalar**) Algebraic steady-state iterations + * `steady_iter2` (**scalar**) Differential steady-state iterations + * `runtime` (**scalar**) Transient solver runtime + +#### Available Solvers + * `generic` - Second-order implicit adaptive `ode23s` Rosenbrock solver * `imex1` - First-order implicit-explicit solver * `imex2` - Second-order implicit-explicit Runge-Kutta solver +* `rk4` - Fourth-order "classic" explicit Runge-Kutta solver (unstable, use only for testing) ### Reductors -A reductor computes a reduced order discrete model, -aiming to approximate the input-output (boundary-quantity-of-interest) behavior. +A reductor computes a reduced order discrete model, aiming to approximate the +input-output (boundary-quantity-of-interest) behavior. #### Interface -`ROM = reductor(solver,discrete,scenario,config)` +`[proj,name] = reductor(solver,discrete,scenario,config)` #### Arguments @@ -286,88 +376,139 @@ aiming to approximate the input-output (boundary-quantity-of-interest) behavior. #### Returns -* `ROM` (handle) Function handle with signature: `discrete = ROM(n)`; - the `ROM` function assembles a `discrete` model structure of order `n`. +* `proj` (**cell**) Array of projectors `{LP,RP;LQ,RQ}` (Petrov Galerkin) or `{LP;LQ}` (Galerkin) +* `name` (**string**) Detailed name of reductor -#### Available +#### Available Reductors -These structured reductors approximate pressure and mass-flux components separately: +These structured reductors approximate pressure and mass-flux components +separately ("Structured" is abbreviated as "Struct."): -* `pod_r` (Structured Proper Orthogonal Decomposition) -* `eds_ro` / `eds_ro_l` (Structured Empirical Dominant Subspaces) -* `eds_wx` / `eds_wx_l` (Structured Empirical Cross-Gramian-Based Dominant Subspaces) -* `eds_wz` / `eds_wz_l` (Structured Empirical Non-Symmetric-Cross-Gramian-Based Dominant Subspaces) -* `bpod_ro` / `bpod_ro_l` (Structured Empirical Balanced Proper Orthogonal Decomposition) -* `ebt_ro` / `ebt_ro_l` (Structured Empirical Balanced Truncation) -* `ebt_wx` / `ebt_wx_l` (Structured Empirical Cross-Gramian-Based Balanced Truncation) -* `ebt_wz` / `ebt_wz_l` (Structured Empirical Non-Symmetric-Cross-Gramian-Based Balanced Truncation) -* `gopod_r` (Structured Goal-Oriented Proper Orthogonal Decomposition) -* `ebg_ro` / `ebg_ro_l` (Structured Empirical Balanced Gains) -* `ebg_wx` / `ebg_wx_l` (Structured Empirical Cross-Gramian-Based Balanced Gains) -* `ebg_wz` /`ebg_wz_l` (Structured Empirical Non-Symmetric-Cross-Gramian-Based Balanced Gains) -* `dmd_r` (Structured Dynamic Mode Decomposition Galerkin) +* `pod_r` _Struct. Proper Orthogonal Decomposition_ +* `eds_ro` / `eds_ro_l` _Struct. Empirical Dominant Subspaces_ +* `eds_wx` / `eds_wx_l` _Struct. Empirical Cross-Gramian-Based Dominant Subspaces_ +* `eds_wz` / `eds_wz_l` _Struct. Empirical Non-Symmetric-Cross-Gramian-Based Dominant Subspaces_ +* `bpod_ro` / `bpod_ro_l` _Struct. Empirical Balanced Proper Orthogonal Decomposition_ +* `ebt_ro` / `ebt_ro_l` _Struct. Empirical Balanced Truncation_ +* `ebt_wx` / `ebt_wx_l` _Struct. Empirical Cross-Gramian-Based Balanced Truncation_ +* `ebt_wz` / `ebt_wz_l` _Struct. Empirical Non-Symmetric-Cross-Gramian-Based Balanced Truncation_ +* `gopod_r` _Struct. Goal-Oriented Proper Orthogonal Decomposition_ +* `ebg_ro` / `ebg_ro_l` _Struct. Empirical Balanced Gains_ +* `ebg_wx` / `ebg_wx_l` _Struct. Empirical Cross-Gramian-Based Balanced Gains_ +* `ebg_wz` /`ebg_wz_l` _Struct. Empirical Non-Symmetric-Cross-Gramian-Based Balanced Gains_ +* `dmd_r` _Struct. Dynamic Mode Decomposition Galerkin_ All reductors utilizing observability information are available in two variants. By default the nonlinear variant (no suffix) is used. The `_l` suffix signifies -a linear variant of the reductor, which assumes a dual system is applicable. +a "linear" variant of the reductor, which assumes a dual system is available. While either method can be applied to both, `ode_mid` and `ode_end`, models, theory suggest to use the linear variant only with the port-Hamiltonian `ode_end`. -### Loading Reduced Order Models +### Tests + +A test defines an experiment, which is implemented as a script whose filename +consists of a prefix and the tested network's name. Two types of experiments are +currently implemented: -Reduced order models are saved in the `z_roms` folder. -A reduced order model is saved by storing the projectors and encoding the associated: -network, model, and reductor in the filename as follows: +* A simulation experiment is prefixed with `sim_` and executes the `morgen.m` + function for combinations of models and solvers against a fixed network and + scenario. + +* A model order reduction experiment is prefixed with `mor_` and executes the + `morgen.m` function for combinations of models, solvers and reductors against + a network and scenario while using the `training.ini` scenario for computing + the reduced order model. + +Note that tests can only be called from the **morgen** base directory, +after running the `SETUP` script or manually adding the `tests` folder to the path +``` +addpath('tests'); +``` + +#### Available Tests + +The available experiments are listed by running the `SETUP` script, which lists +the contents of the `tests` folder. + +#### Reduced Order Models + +Reduced order models are saved in the `z_roms` folder (or the folder specified +by the `morgen_roms` configuration entry). + +A reduced order model is saved by storing the projectors and encoding the +associated: network, model, and reductor in the filename as follows: `network--model--reductor--pid.rom` with `pid` being custom identifier configurable via optional arguments. -To load a reduced order model provide a filename of a saved reduced order model instead of the reductor identifier. +To load a reduced order model provide a filename of a saved reduced order model +instead of the reductor identifier. + +#### Results + +Plots and [MORscores](https://doi.org/10.1007/978-3-030-72983-7_7) computed by `morgen.m` +are stored in the `z_plots` folder (or the folder specified by the `morgen_plots` +configuration entry). ## Configuration -The **morgen** platform assumes a configuration [INI](https://en.wikipedia.org/wiki/INI_file)-file in the base folder named `morgen.ini`, -if not found hard-coded default values are used. +The **morgen** platform assumes a configuration [INI](https://en.wikipedia.org/wiki/INI_file)-file +in the base folder named `morgen.ini`, if not found hard-coded default values +are used. * `morgen_plots` (**String**) Folder to store plots, default: `z_plots` * `morgen_roms` (**String**) Folder to store reduced order models, defaut: `z_roms` -* `network_dt` (**Positive float**) Requested time step width in seconds, default: `60` -* `network_vmax` (**Positive float**) Maximum velocity of gas in meters per second, default: `20` +* `network_dt` (**Positive float**) Requested time step width in seconds, default: `60.0` +* `network_vmax` (**Positive float**) Maximum velocity of gas in meters per second, default: `20.0` +* `network_cfl` (**Positive float**) Target CFL constant of spatial discretization, default: `0.5` -* `model_reynolds` (**Positive float**) Estimated Reynolds number, default: `1000000` +* `model_tuning` (**Positive float**) Tunable efficiency factor scaling the friction term, default: `1.0` +* `model_reynolds` (**Positive float**) Estimated Reynolds number, default: `1000000.0` * `model_friction` (**String**) Friction factor model, select from `hofer`, `nikuradse`, `altshul`, `schifrinson`, `pmt1025`, `igt`, default: `schifrinson` -* `model_compressibility` (**String**) Compressibility factor model, select from: `ideal`, `dvgw`, `aga88`, `papay`, default: `ideal` +* `model_compressibility` (**String**) Compressibility factor model, select from: `ideal`, `dvgw`, `aga88`, `papay`, default: `aga88` * `model_compref` (**String**) Reference for compressibility: `steady`, `normal`, default: `steady` * `steady_maxiter` (**Positive Integer**) Number of iterations to refine steady-state estimation, default: `1000` -* `steady_maxerror` (**Positive Integer**) Maximal error of refined steady-state, default: `1e-6` +* `steady_maxerror` (**Positive Float**) Maximal error of refined steady-state, default: `1e-6` * `steady_Tc` (**Float**) Critical temperature in Celsius, default: `-82.595` * `steady_pc` (**Float**) Critical pressure in Bar, default: `45.988` * `steady_pn` (**Float**) Normal pressure in Bar, default: `1.01325` -* `solver_relax` (**Positive float <1**) IMEX solver relaxation, default: `1.0` +* `solver_relax` (**Float in (0,1]**) IMEX solver relaxation, default: `1.0` -* `T0_min` (**Float**) Minimum ambient temperature in Celsius, default: `0` -* `T0_max` (**Float**) Maximum ambient temperature in Celsius, default: `25` +* `T0_min` (**Float**) Minimum ambient temperature in Celsius, default: `0.0` +* `T0_max` (**Float**) Maximum ambient temperature in Celsius, default: `25.0` * `Rs_min` (**Float**) Minimum specific gas constant in [J/(kg*K)], default: `500.0` * `Rs_max` (**Float**) Maximum specific gas constant in [J/(kg*K)], default: `600.0` * `mor_excitation` (**String**) Generic training input type, select from: `impulse`, `step`, `random-binary`, `white-noise`, default: `step` -* `mor_max` (**Positive Integer**) Maximum reduced order, default: `250` -* `mor_parametric` (**String**) Use parametric model order reduction, select from `yes`, `no`, default: `yes` +* `mor_max` (**Positive Integer**) Maximum reduced order, default: `200` +* `mor_parametric` (**Boolean**) Use parametric model order reduction, select from `true`, `false`, default: `true` * `mor_pgrid` (**Positive Integer**) Sparse parameter grid refinement level, default: `1` * `eval_pnorm` (**Float**) Parameter norm: `1`, `2`, `Inf`, default: `2` * `eval_skip` (**Positive Integer**) Evaluate every n-th reduced order model, default: `3` -* `eval_max` (**Positive Float**) Maximum reduced order to evaluate, default: `Inf` -* `eval_parametric` (**String**) Parametric reduced order model evaluation: `yes`, `no`, default: `yes` +* `eval_max` (**Positive Integer**) Maximum reduced order to evaluate, default: `200` (use `Inf` for maximum possible) +* `eval_parametric` (**Boolean**) Parametric reduced order model evaluation: `true`, `false`, default: `true` * `eval_ptest` (**Positive Integer**) Number of test parameters, default: `5` +### Internal Configuration Structure + +Internally, the configuration is stored in a structure of structures as follows: + +* `config` (**struct**) + * `.network` (**struct**) Members: `.dt`, `.vmax`, `.cfl` + * `.model` (**struct**) Members: `.reynolds`, `.friction` + * `.steady` (**struct**) Members: `.dt`, `.maxiter`, `.maxerror`, `.Tc`, `.pc`, `.pn`, `.compressibility` + * `.solver` (**struct**) Members: `.dt`, `.relax` + * `.mor` (**struct**) Members: `.rom_max`, `.parametric`, `.solver`, `.excitation`, `.T0_min`, `.T0max`, `.Rs_min`, `.Rs_max`, `.pgrid` + * `.eval` (**struct**) Members: `.parametric`, `.ptest`, `T0_min`, `.T0max`, `.Rs_min`, `.Rs_max`, `.skip`, `.max`, `.pnorm` + ## Temperature Units -All input temperatures, i.e. in: +All input temperatures, i.e., in: * `morgen.ini` configuration * `XXXXXX.ini` scenario @@ -389,35 +530,100 @@ csv2net('X_Y_PipeSegments.csv','myX_Y') ``` json2net('X.json','myX') ``` -* `mf2vf.m` Converts m3/h to kg/s -* `randscen.m` Generates a random scenario given a training scenario +* `vf2kgs.m` Converts volume flow to kg/s (default gas density is 0.7) +``` +vf2kgs(value,vol_unit,time_unit,density) +``` +* `psi2bar.m` Converts psi to bar +``` +b = psi2bar(p) +``` +* `randscen.m` Generates a random scenario given a network, implicitly defining training scenario +``` +randscen(network,scenario_name) +``` * `cmp_friction.m` Compare friction factors +``` +cmp_friction(Re,D,k) +``` +* `cmp_compressibility.m` Compare compressibility factors +``` +cmp_compressibility(p,T,pc,Tc) +``` ## Log +* 1.0 (2021-06-22): [doi:10.5281/zenodo.5012357](https://doi.org/10.5281/zenodo.5012357) + * `ADDED` configurable CFL constant + * `ADDED` networks and tests + * `ADDED` psi2bar converter tool + * `ADDED` tunable efficiency factor + * `IMPROVED` steady-state interface + * `IMPROVED` model-solver interface + * `IMPROVED` reductor interface + * `IMPROVED` rk4 solver + * `IMPROVED` logging + * `IMPROVED` vf2kgs tool + * 0.99 (2021-04-12): [doi:10.5281/zenodo.4680265](https://doi.org/10.5281/zenodo.4680265) - * IMPROVED model structure - * ADDED gopod reductor - * ADDED linear reductor variants - * ADDED SciGRID_gas CSV converter - * ADDED DEMO code + * `ADDED` gopod reductor + * `ADDED` linear reductor variants + * `ADDED` SciGRID_gas CSV converter + * `ADDED` DEMO code + * `IMPROVED` model structure * 0.9 (2020-11-24): [doi:10.5281/zenodo.4288510](https://doi.org/10.5281/zenodo.4288510) - * Initial release + * Initial release + +## References + +* C. Himpe, S. Grundel, P. Benner: **Model Order Reduction for Gas and Energy Networks**; + arXiv (math.OC): 2011.12099, 2021. [arXiv:2011.12099](https://arxiv.org/abs/2011.12099) + * See also the references listed therein. + +* C. Himpe: **Comparing (Empirical-Gramian-Based) Model Order Reduction Algorithms**; + in: Model Reduction of Complex Dynamical Systems: Accepted, 2021. [doi:10.1007/978-3-030-72983-7_7](https://doi.org/10.1007/978-3-030-72983-7_7) + +* P. Benner, S. Grundel, C. Himpe, C. Huck, T. Streubel, C. Tischendorf: **Gas Network Benchmark Models**; + in: Applications of Differential-Algebraic Equations: Examples and Benchmarks: 171--197, 2019. [doi:10.1007/11221_2018_5](https://doi.org/10.1007/11221_2018_5) + +* T. Clees, A. Baldin, P. Benner, S. Grundel, C. Himpe, B. Klaassen, F. Küsters, N. Marheineke, L. Nikitina, I. Nikitin, J. Pade, N. Stahl, C. Strohm, C. Tischendorf, A. Wirsen: **MathEnergy – Mathematical Key Technologies for Evolving Energy Grids**; + in: Mathematical Modeling, Simulation and Optimization for Power Engineering and Management: 233--262, 2021. [doi:10.1007/978-3-030-62732-4_11](https://doi.org/10.1007/978-3-030-62732-4_11) + +* P. Benner, S. Grundel, C. Himpe: **Efficient Gas Network Simulations**; + in: German Success Stories in Industrial Mathematics, In Press, 2021. ## Roadmap -### 1.0 +### 1.1 -* [Model] ADD scenario valve handling -* [Octave] FIX incompatibilities in `format_network` (`textscan`) -* [Octave] FIX slow `ode23s` +* [Main] `ADD` gain match testing +* [Solver] `ADD` stabilized explicit solver +* [Solver] `ADD` steady state stopping criteria +* [Plots] `ADD` reduced order network visualization +* [Gui] `ADD` launcher +* [Docu] `FIX` update references and citation +* [Main] `FIX` use `filesep` instead of `/` +* [Plots] `FIX` axis labels depending on single or compact plot +* [Octave] `FIX` incompatibilities in `format_network` (`textscan`) +* [Octave] `FIX` slow `ode23s` ### 2.0 -* [Model] ADD DAE models -* [Model] ADD tuning factor -* [Hyper] ADD hyper-reductors (DMD, DEIM, Q-DEIM, Numerical linearization) +* [Model] `ADD` scenario valve handling +* [Model] `ADD` DAE model +* [Model] `ADD` decouplers module +* [Model] `ADD` generic compressors as input/output combination +* [Solver] `ADD` DAE Euler solver +* [Solver] `ADD` co-simulation interface +* [Reductor] `ADD` hyper-reductor module (i.e. DMD, DEIM, Q-DEIM, Numerical linearization) + +## Development Guidelines + +* The main branch must complete cleared system tests successfully **!** +* All source code headers must include: project, version, authors, license, summary **!** +* Understand closures in [Matlab](https://research.wmz.ninja/articles/2017/05/closures-in-matlab.html) **!** +* This project uses [Readme-Driven Development](https://tom.preston-werner.com/2010/08/23/readme-driven-development.html) **!** ## Authors diff --git a/RUNME.m b/RUNME_HimpeGB21.m similarity index 51% rename from RUNME.m rename to RUNME_HimpeGB21.m index fbec689..25c133e 100644 --- a/RUNME.m +++ b/RUNME_HimpeGB21.m @@ -1,14 +1,17 @@ %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) -%%% summary: Numerical experiments for morHimGB21. +%%% summary: Numerical experiments for HimpeGB21. +fprintf('\n'); fprintf('# Numerical Experiments for:\n\n'); -fprintf(' C. Himpe, S. Grundel, P. Benner: \n'); -fprintf(' "Model Order Reduction for Gas and Energy Networks"; 2021.\n\n'); +fprintf(' C. Himpe, S. Grundel, P. Benner: \n'); +fprintf(' "Model Order Reduction for Gas and Energy Networks";\n'); +fprintf(' arXiv (math.OC): 2011.12099, 2021. \n\n'); + +addpath('tests'); -SETUP mor_Cha09 mor_MORGEN mor_GasLib134 diff --git a/SETUP.m b/SETUP.m index 09579b3..145f2dc 100644 --- a/SETUP.m +++ b/SETUP.m @@ -1,5 +1,5 @@ %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Basic setup script. @@ -10,7 +10,8 @@ fprintf('\n'); fprintf('## Cite as:\n\n'); fprintf(' C. Himpe, S. Grundel, P. Benner: \n'); -fprintf(' "Model Order Reduction for Gas and Energy Networks"; 2021. \n\n'); +fprintf(' "Model Order Reduction for Gas and Energy Networks"; \n'); +fprintf(' arXiv (math.OC): 2011.12099, 2021. \n\n'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% ADD FOLDERS diff --git a/VERSION b/VERSION index 0338f8d..b9b0237 100644 --- a/VERSION +++ b/VERSION @@ -1 +1,2 @@ -0.99 +1.0 + diff --git a/doc/morgen-0.99.pdf b/doc/morgen-1.0.pdf similarity index 94% rename from doc/morgen-0.99.pdf rename to doc/morgen-1.0.pdf index 49412fda647789a3ed2ebb739e746ef8e313494a..f8f930b8acbddc6c59e5330965bc956805a0dfa8 100644 GIT binary patch delta 70508 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 z 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 delta 69974 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 diff --git a/models/ode_end.m b/models/ode_end.m index 0c2968f..27a2315 100644 --- a/models/ode_end.m +++ b/models/ode_end.m @@ -1,6 +1,6 @@ function discrete = ode_end(network,config) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Nonlinear implicit ODE endpoint model. @@ -10,14 +10,11 @@ discrete.nP = size(network.A0,1); % number of pressure states discrete.nQ = size(network.A0,2); % number of mass-flux states discrete.nPorts = network.nSupply + network.nDemand; % number of ports - - discrete.refine = blkdiag(network.node_op,network.edge_op); - discrete.np = size(network.node_op,2); - discrete.nq = size(network.edge_op,2); + discrete.unrefine = blkdiag(network.unrefine_nodes,network.unrefine_edges); %% Helper Variables - F_k = network.length ./ network.nomLen; % actual-nominal length fraction + F_k = config.tuning * (network.length ./ network.nomLen); % actual-nominal length fraction scaled by tuning factor A_R = 0.5 * (network.A0 + abs(network.A0))'; % partial "entering" incidence matrix @@ -57,8 +54,6 @@ discrete.A = [sparse(discrete.nP, discrete.nP), -1e-5 * network.A0; ... 1e5 * (network.A0 - network.Ac)', sparse(discrete.nQ, discrete.nQ)]; - discrete.As = discrete.A; - % Linear input matrix % % / 0 B_D \ @@ -95,7 +90,7 @@ f_local = @(p,q) [zeros(discrete.nP, 1); ... -( d_g .* p + (d_q * d_f) .* F_k .* (q .* abs(q)) ./ p)]; - discrete.f = @(xs,x,u,rtz) f_local(p2q(xs(iP) + x(iP))./rtz,xs(iQ) + x(iQ)); + discrete.f = @(xs,x,u,rtz) discrete.A * xs + f_local(p2q(xs(iP) + x(iP))./rtz,xs(iQ) + x(iQ)); % Local Jacobian % diff --git a/models/ode_mid.m b/models/ode_mid.m index 189ae05..bfb0c2e 100644 --- a/models/ode_mid.m +++ b/models/ode_mid.m @@ -1,6 +1,6 @@ function discrete = ode_mid(network,config) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Nonlinear implicit ODE midpoint model. @@ -10,14 +10,11 @@ discrete.nP = size(network.A0,1); % number of pressure states discrete.nQ = size(network.A0,2); % number of mass-flux states discrete.nPorts = network.nSupply + network.nDemand; % number of ports - - discrete.refine = blkdiag(network.node_op,network.edge_op); - discrete.np = size(network.node_op,2); - discrete.nq = size(network.edge_op,2); + discrete.unrefine = blkdiag(network.unrefine_nodes,network.unrefine_edges); %% Helper Variables - F_k = network.length ./ network.nomLen; % actual-nominal length fraction + F_k = config.tuning * (network.length ./ network.nomLen); % actual-nominal length fraction scaled by tuning factor absA0 = abs(network.A0); absA0T = abs(network.A0)'; @@ -59,8 +56,6 @@ discrete.A = [sparse(discrete.nP, discrete.nP), -1e-5 * network.A0; ... 1e5 * (network.A0 - network.Ac)', sparse(discrete.nQ, discrete.nQ)]; - discrete.As = discrete.A; - % Input matrix % % / 0 B_d \ @@ -97,7 +92,7 @@ f_local = @(p,q) [zeros(discrete.nP, 1); ... -( d_g .* p + (d_q * d_f) .* F_k .* ((q .* abs(q)) ./ p))]; - discrete.f = @(xs,x,u,rtz) f_local(p2q(xs(iP) + x(iP),u(iS))./rtz,xs(iQ) + x(iQ)); + discrete.f = @(xs,x,u,rtz) discrete.A * xs + f_local(p2q(xs(iP) + x(iP),u(iS))./rtz,xs(iQ) + x(iQ)); % Local Jacobian % diff --git a/models/private/D_f.m b/models/private/D_f.m index dbdf6a7..4475231 100644 --- a/models/private/D_f.m +++ b/models/private/D_f.m @@ -1,9 +1,10 @@ function r = D_f(D_k, lambda_k) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Friction component coefficients. r = lambda_k ./ (2.0 * D_k .* circsurf(D_k)); end + diff --git a/models/private/D_g.m b/models/private/D_g.m index 86a38b0..19aa1f1 100644 --- a/models/private/D_g.m +++ b/models/private/D_g.m @@ -1,6 +1,6 @@ function r = D_g(h_k) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Gravity component coefficients. diff --git a/models/private/D_p.m b/models/private/D_p.m index d1f8c7b..a677627 100644 --- a/models/private/D_p.m +++ b/models/private/D_p.m @@ -1,6 +1,6 @@ function r = D_p(D_k, L_k) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Inverse (!) pressure component coefficients (as diagonal matrix). diff --git a/models/private/D_q.m b/models/private/D_q.m index 6720f98..318016a 100644 --- a/models/private/D_q.m +++ b/models/private/D_q.m @@ -1,6 +1,6 @@ function r = D_q(D_k, L_k) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Inverse (!) mass-flux component coefficients (as diagonal matrix). diff --git a/utils/circsurf.m b/models/private/circsurf.m similarity index 91% rename from utils/circsurf.m rename to models/private/circsurf.m index ba59658..8b27be2 100644 --- a/utils/circsurf.m +++ b/models/private/circsurf.m @@ -1,6 +1,6 @@ function a = circsurf(diam) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Vectorized circle surface for given diameter. diff --git a/models/template_model.m b/models/template_model.m index ea85324..09bd073 100644 --- a/models/template_model.m +++ b/models/template_model.m @@ -1,6 +1,6 @@ function discrete = template_model(network,config) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Template model @@ -24,8 +24,6 @@ discrete.A = % nP+nQ x nP+nQ **sparse** system matrix - discrete.As = discrete.A % This is needed for efficient ROM computation, leave as is. - discrete.B = % nP+nQ times nS+nD **sparse** input matrix discrete.F = % np+nQ x nC sparse load matrix diff --git a/morgen.ini b/morgen.ini index b0e9655..288e770 100644 --- a/morgen.ini +++ b/morgen.ini @@ -1,35 +1,37 @@ morgen_plots = z_plots # Path to plot folder: **z_plots** morgen_roms = z_roms # Path to reduced order models folder: **z_roms** -network_dt = 60.0 # Requested solver time-step [s]: **60** -network_vmax = 20.0 # Maximum gas velocity [m/s]: **20** +network_dt = 60.0 # Requested solver time-step [s]: **60.0** +network_vmax = 20.0 # Maximum gas velocity [m/s]: **20.0** +network_cfl = 0.5 # Target CFL constant [1]: **0.5** -model_reynolds = 1000000.0 # Estimated Reynolds number [1]: 1000000 -model_friction = schifrinson # Friction factor model: **hofer** , nikuradse , altshul , schifrinson , pmt1025 , igt +model_tuning = 1.0 # Tunable efficiency factor scaling the friction term [1]: 1.0 +model_reynolds = 1000000.0 # Estimated Reynolds number [1]: 1000000.0 +model_friction = schifrinson # Friction factor model: hofer , nikuradse , altshul , **schifrinson** , pmt1025 , igt model_compressibility = aga88 # Compressibility factor model: **ideal** , dvgw , aga88 , papay model_compref = steady # Reference for compressibility: **steady** , normal -steady_maxiter = 1000 # Number of iterations to refine steady-state estimation: **500** (r >= 1) +steady_maxiter = 1000 # Number of iterations to refine steady-state estimation: **1000** (r >= 1) steady_maxerror = 1e-6 # Maximal error of refined steady-state: **1e-6** (=10^-6) steady_Tc = -82.595 # Critical temperature [C]: -82.595 steady_pc = 45.988 # Critical pressure [bar]: 45.988 steady_pn = 1.01325 # Normal pressure [bar]: 1.01325 -solver_relax = 1.0 # Solver relaxation: **1.0** (0 > r >= 1.0) +solver_relax = 1.0 # Solver relaxation: **1.0** (0 < r <= 1.0) T0_min = 0.0 # Minimum ambient temperature [C]: 0 -T0_max = 15.0 # Maximum ambient temperature [C]: 15.0 +T0_max = 20.0 # Maximum ambient temperature [C]: 20.0 Rs_min = 500.0 # Minimum specific gas constant [J/(kg*K)]: 500.0 (Natural gas: 518.3) -Rs_max = 600.0 # Maximum specific gas constant [J/(kg*K)]: 900.0 (Hydrogen: 4124.2) +Rs_max = 600.0 # Maximum specific gas constant [J/(kg*K)]: 600.0 (Hydrogen: 4124.2) mor_excitation = step # Generic training input type: **step** , impulse , random-binary , white-noise -mor_max = 200 # Maximum reduced order: **250** (r > 2) -mor_parametric = yes # Parametric model order reduction: **yes** , no -mor_pgrid = 1 # Sparse parameter grid level: **1** (1 < r < 4) +mor_max = 200 # Maximum reduced order: **200** (r > 2) +mor_parametric = true # Parametric model order reduction: **true** , false +mor_pgrid = 1 # Sparse parameter grid level: **1** (1 <= r < 4) eval_pnorm = 2 # Parameter norm: 1 , **2** , Inf eval_skip = 3 # Evaluate every n-th reduced order model: **3** (r >= 1) -eval_max = 200 # Maximum reduced order to evaluate : **Inf** (r >= 2, use Inf for maximum possible) -eval_parametric = yes # Parametric reduced order model evaluation: **yes**, no +eval_max = 200 # Maximum reduced order to evaluate : **200** (r >= 2, use Inf for maximum possible) +eval_parametric = true # Parametric reduced order model evaluation: **true**, false eval_ptest = 5 # Number of test parameters: **5** (r >= 1) diff --git a/morgen.m b/morgen.m index 3c7c547..3d4c79c 100644 --- a/morgen.m +++ b/morgen.m @@ -1,25 +1,31 @@ function R = morgen(network_id,scenario_id,model_id,solver_id,reductor_ids,varargin) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Model reduction test platform and task master. +% +% For help on morgen please see the file. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% INIT MORGEN %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Version constant - MORGEN_VERSION = 0.99; + MORGEN_VERSION = 1.0; - % Print welcome message - fprintf('\n'); - fprintf('# morgen - Model Order Reduction for Gas and Energy Networks\n'); - fprintf('============================================================\n'); - fprintf('\n'); + % Random number seeding + SEED = 1009; + rand('seed',SEED); + randn('seed',SEED); - % Add paths + % Add util path (recursively) addpath(genpath('utils')); + + % Print welcome message + logger('head','morgen - Model Order Reduction for Gas and Energy Networks'); + + % Add module paths addpath('models'); addpath('solvers'); addpath('reductors'); @@ -28,51 +34,50 @@ ocu = onCleanup(@cleanup); % Report version - fprintf(' * Version: _ _ _ _ _ _ _ _ _ _ _ _ _ _ %.2f \n',MORGEN_VERSION); + logger('output','Version',MORGEN_VERSION,'%.2f'); - % Report environment + % Report environment and turn off specific warnings (restored by cleanup) if not(exist('OCTAVE_VERSION','builtin')) - vec = @(m) m(:); - fprintf(' * Environment: _ _ _ _ _ _ _ _ _ _ _ _ MATLAB \n'); + vec = @(m) m(:); % MATLAB does not have this functional definition of : (colon) operator + warning('off','MATLAB:nearlySingularMatrix'); % Turn off warning potentially bloating the log + logger('output','Environment','MATLAB','%s'); else % Octave has "vec" built-in - fprintf(' * Environment: _ _ _ _ _ _ _ _ _ _ _ _ OCTAVE \n'); + warning('off','Octave:nearly-singular-matrix'); % Turn off warning potentially bloating the log + warning('off','Octave:lu:sparse_input'); % Octave warns by default about sparse matrices in LU decompositions + warning('off','Octave:negative-data-log-axis'); % Octave warns by default about negative data in log plots + logger('output','Environment','OCTAVE','%s'); end%if - fprintf('\n'); + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SETUP ARGUMENTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Selected Ensemble:\n\n'); + logger('head','Parsing Ensemble: ...'); % Check if "network_id" argument leads to a network file assert(isfile(['networks/',network_id,'.net']), ... ['morgen: unknown network: ',network_id]); network_path = ['networks/',network_id,'.net']; - fprintf(' * Network:_ _ _ _ _ _ _ _ _ _ _ _ _ _ %s \n',network_id); % Check if "scenario_id" argument leads to a scenario file assert(isfile(['networks/',network_id,'/',scenario_id,'.ini']), ... ['morgen: unknown scenario: ',scenario_id]); scenario_path = ['networks/',network_id,'/',scenario_id,'.ini']; - fprintf(' * Scenario: _ _ _ _ _ _ _ _ _ _ _ _ _ %s \n',scenario_id); % Check if "model_id" argument refers to a supported model assert(any(strcmpi({vec(dir('models/')).name}, ... - [model_id,'.m'])),['morgen: unknown model: ',model_id]); - %model_list = - model = str2func(model_id); - fprintf(' * Discretization: _ _ _ _ _ _ _ _ _ _ %s \n',model_id); + [model_id,'.m'])),['morgen: unknown model: ',model_id]); + model_fun = str2func(model_id); % Check if "solver_id" argument refers to a supported solver assert(any(strcmpi({vec(dir('solvers/')).name}, ... [solver_id,'.m'])),['morgen: unknown solver: ',solver_id]); - solver = str2func(solver_id); - fprintf(' * Time Stepper: _ _ _ _ _ _ _ _ _ _ _ %s \n',solver_id); + solver_fun = str2func(solver_id); % Check if "reductor_ids" argument refers to a list of supported reductors if exist('reductor_ids','var') && not(isempty(reductor_ids)) @@ -84,18 +89,32 @@ reductor = cell(numel(reductor_ids),1); reductor(reductor_func_mask) = cellfun(@(c) str2func(c),reductor_ids(reductor_func_mask),'UniformOutput',false); reductor(reductor_file_mask) = reductor_ids(reductor_file_mask); - fprintf(' * Reductor(s):_ _ _ _ _ _ _ _ _ _ _ _ '); - cellfun(@(c) fprintf('%s \n ',c),reductor_ids,'UniformOutput',false); - if numel(reductor_ids) == 0, fprintf('\n'); end%if end%if - fprintf('\n'); + logger('done'); + + logger('input','Network',network_id,'%s'); + logger('input','Scenario',scenario_id,'%s'); + logger('input','Discretization',model_id,'%s'); + logger('input','Time Stepper',solver_id,'%s'); + + logger('line'); + + if exist('reductor_ids','var') && not(isempty(reductor_ids)) + + for k = reductor_ids + + logger('input','Reductor',k{:},'%s'); + end%for + end%if + + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SETUP CONFIGURATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Reading Configuration ... '); + logger('head','Reading Configuration ...'); % Read configuration file try @@ -116,77 +135,79 @@ rom_path = inifield(ini,'morgen_roms','z_roms'); if not(exist(rom_path, 'dir')), mkdir(rom_path); end%if - fprintf('Done.\n\n'); + logger('done'); - fprintf(' < Configuration:_ _ _ _ _ _ _ _ _ _ _ %s \n',ini_path) + logger('input','Configuration',ini_path,'%s'); - fprintf('\n'); + logger('line'); - fprintf(' > Plot path:_ _ _ _ _ _ _ _ _ _ _ _ _ %s \n',plot_path); - fprintf(' > ROM path: _ _ _ _ _ _ _ _ _ _ _ _ _ %s \n',rom_path); + logger('output','Plot path',plot_path,'%s'); + logger('output','ROM path',rom_path,'%s'); - fprintf('\n'); + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SETUP NETWORK GRAPH %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Loading Topology ... '); + logger('head','Loading Topology ...'); config.network.dt = varfield(varargin,'dt',inifield(ini,'network_dt',180)); config.network.vmax = inifield(ini,'network_vmax',20); + config.network.cfl = inifield(ini,'network_cfl',0.5); network = format_network(network_path,config.network); - fprintf('Done.\n\n'); + logger('done'); - fprintf(' < Time step [s]:_ _ _ _ _ _ _ _ _ _ _ %g \n',config.network.dt); - fprintf(' < Maximum gas velocity [m/s]: _ _ _ _ %g \n',config.network.vmax); + logger('input','Time step [s]',config.network.dt,'%g'); + logger('input','Maximum gas velocity [m/s]',config.network.vmax,'%g'); + logger('input','Enforced CFL constant',config.network.cfl,'%.2g'); - fprintf('\n'); + logger('line'); - fprintf(' > Homogenized pipe length [m]:_ _ _ _ %g \n',network.nomLen); - fprintf(' > Associated CFL constant:_ _ _ _ _ _ %.2g \n',cfl(network.nomLen,config.network.dt,config.network.vmax)); - fprintf(' > Number of refined edges:_ _ _ _ _ _ %u \n',network.nEdges); - fprintf(' > Number of refined internal nodes: _ %u \n',network.nInternal); - fprintf(' > Number of supply nodes: _ _ _ _ _ _ %u \n',network.nSupply); - fprintf(' > Number of demand nodes: _ _ _ _ _ _ %u \n',network.nDemand); - fprintf(' > Number of compressor edges: _ _ _ _ %u \n',network.nCompressor); + logger('output','Homogenized pipe length [m]',network.nomLen,'%g'); + logger('output','Number of refined edges',network.nEdges,'%u'); + logger('output','Number of refined internal nodes',network.nInternal,'%u'); + logger('output','Number of supply nodes',network.nSupply,'%u'); + logger('output','Number of demand nodes',network.nDemand,'%u'); + logger('output','Number of compressor edges',network.nCompressor,'%u'); - fprintf('\n'); + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SETUP DISCRETE MODEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Initializing Model ... '); + logger('head','Initializing Model ...'); + config.model.tuning = varfield(varargin,'tf',inifield(ini,'model_tuning',1.0)); config.model.reynolds = inifield(ini,'model_reynolds',1e6); friction_name = inifield(ini,'model_friction','hofer',{'hofer','nikuradse','altshul','schifrinson','pmt1025','igt'}); friction_fun = str2func(['friction_',friction_name]); config.model.friction = @(D,k) friction_fun(config.model.reynolds,D,k); - discrete = model(network,config.model); + discrete = model_fun(network,config.model); - fprintf('Done.\n\n'); + logger('done'); - fprintf(' < Approx. Reynolds number [1]:_ _ _ _ %u \n',config.model.reynolds); - fprintf(' < Friction model: _ _ _ _ _ _ _ _ _ _ %s \n',friction_name); + logger('input','Approx. Reynolds number [1]',config.model.reynolds,'%u'); + logger('input','Friction model',friction_name,'%s'); - fprintf('\n'); + logger('line'); - fprintf(' > Number of total states: _ _ _ _ _ _ %u \n',discrete.nP + discrete.nQ); - fprintf(' > Number of pressure states:_ _ _ _ _ %u \n',discrete.nP); - fprintf(' > Number of mass-flux states: _ _ _ _ %u \n',discrete.nQ); - fprintf(' > Number of boundary ports: _ _ _ _ _ %u \n',discrete.nPorts); + logger('output','Number of total states',discrete.nP + discrete.nQ,'%u'); + logger('output','Number of pressure states',discrete.nP,'%u'); + logger('output','Number of mass-flux states',discrete.nQ,'%u'); + logger('output','Number of boundary ports',discrete.nPorts,'%u'); - fprintf('\n'); + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SETUP STEADY-STATE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Initializing Steady-State ... '); + logger('head','Initializing Steady-State ...'); config.steady.dt = config.network.dt; config.steady.maxiter = max(1,round(inifield(ini,'steady_maxiter',1))); @@ -207,48 +228,49 @@ config.steady.compressibility = @(p,T) compressibility_fun(p,T,config.steady.pc,config.steady.Tc); end%if - fprintf('Done.\n\n'); + logger('done'); - fprintf(' < Maximum steady state error: _ _ _ _ %g \n',config.steady.maxerror); - fprintf(' < Maximum steady state iterations:_ _ %u \n',config.steady.maxiter); - fprintf(' < Critical temperature [C]: _ _ _ _ _ %g \n',kelvin2celsius(config.steady.Tc)); - fprintf(' < Critical pressure [bar]:_ _ _ _ _ _ %g \n',config.steady.pc); - fprintf(' < Normal pressure [bar]:_ _ _ _ _ _ _ %g \n',config.steady.pn); - fprintf(' < Compressibility model:_ _ _ _ _ _ _ %s \n',compressibility_name); + logger('input','Maximum steady state error',config.steady.maxerror,'%g'); + logger('input','Maximum steady state iterations',config.steady.maxiter,'%u'); + logger('input','Critical temperature [C]',kelvin2celsius(config.steady.Tc),'%g'); + logger('input','Critical pressure [bar]',config.steady.pc,'%g'); + logger('input','Normal pressure [bar]',config.steady.pn,'%g'); + logger('input','Compressibility model',compressibility_name,'%s'); - fprintf('\n'); + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SETUP SOLVER %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Initializing Solver ... '); + logger('head','Initializing Solver ...'); config.solver.dt = config.network.dt; config.solver.relax = min(1.0,max(0,inifield(ini,'solver_relax',1))); - config.solver.steadystate = @(s) steadystate(discrete,s,config.steady); - fprintf('Done.\n\n'); + solver = @(d,s,c) solver_fun(d,s,setfield(c,'steady',steadystate(discrete,s,config.steady))); + + logger('done'); - fprintf(' < Solver relaxation:_ _ _ _ _ _ _ _ _ %.2f \n', config.solver.relax); + logger('input','Solver relaxation',config.solver.relax,'%.2f'); - fprintf('\n'); + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% SETUP SCENARIO %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Loading Scenario ... '); + logger('head','Loading Scenario ...'); scenario = format_scenario(scenario_path,network); - fprintf('Done.\n\n'); + logger('done'); - fprintf(' > Ambient temperature [C]:_ _ _ _ _ _ %.2g \n',kelvin2celsius(scenario.T0)); - fprintf(' > Specific gas constant [J/(kg K)]: _ %g \n',scenario.Rs); - fprintf(' > Time horizon [s]: _ _ _ _ _ _ _ _ _ %g \n',scenario.Tf); + logger('output','Ambient temperature [C]',kelvin2celsius(scenario.T0),'%.2g'); + logger('output','Specific gas constant [J/(kg K)]',scenario.Rs,'%g'); + logger('output','Time horizon [s]',scenario.tH,'%g'); - fprintf('\n'); + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% MODEL REDUCTION OFFLINE PHASE @@ -256,17 +278,19 @@ if exist('reductor_ids','var') && not(isempty(reductor_ids)) - fprintf('## Computing Reduced Order Models ... \n\n'); + logger('head','Computing Reduced Order Models ...'); rom_max = varfield(varargin,'ord',inifield(ini,'mor_max',250)); config.mor.rom_max = min([ceil(0.5 * rom_max),discrete.nP,discrete.nQ]); - config.mor.excitation_name = inifield(ini,'mor_excitation','step',{'impulse','step','random-binary','white-noise'}); - config.mor.parametric = inifield(ini,'mor_parametric','yes',{'no','yes'}); + config.mor.parametric = inifield(ini,'mor_parametric','true',{'false','true'}); config.mor.solver = config.solver; - switch config.mor.excitation_name + excitation_name = inifield(ini,'mor_excitation','step',{'impulse','step','random-binary','white-noise'}); + + % Set training input + switch excitation_name case 'step' config.mor.excitation = @training_step; @@ -275,20 +299,20 @@ config.mor.excitation = @(t) training_impulse(t,config.network.dt); case 'random-binary' - rand('seed',1009); config.mor.excitation = @training_randombinary; case 'white-noise' - randn('seed',1009); config.mor.excitation = @training_whitenoise; end%switch - fprintf(' < Training excitation:_ _ _ _ _ _ _ _ %s \n',config.mor.excitation_name); - fprintf(' < Maximum reduced order per variable: %u \n',config.mor.rom_max); - fprintf(' < Parametric reduction? _ _ _ _ _ _ _ %s \n',config.mor.parametric); + logger('input','Training excitation',excitation_name,'%s'); + logger('input','Max reduced order per variable',config.mor.rom_max,'%u'); + logger('input','Parametric reduction?',config.mor.parametric,'%s'); + + logger('line'); % Configuration only relevant for parametric model order reduction - if isequal(config.mor.parametric,'yes') + if strcmp(config.mor.parametric,'true') config.mor.T0_min = celsius2kelvin(inifield(ini,'T0_min', 0.0)); config.mor.T0_max = celsius2kelvin(inifield(ini,'T0_max',25.0)); @@ -296,9 +320,9 @@ config.mor.Rs_max = inifield(ini,'Rs_max',900.0); config.mor.pgrid = inifield(ini,'mor_pgrid',0); - fprintf(' < Temperature range [C]:_ _ _ _ _ _ _ [%g,%g] \n',kelvin2celsius(config.mor.T0_min),kelvin2celsius(config.mor.T0_max)); - fprintf(' < Gas constant range [J/(kg K)]:_ _ _ [%g,%g] \n',config.mor.Rs_min,config.mor.Rs_max); - fprintf(' < Parameter Grid Level: _ _ _ _ _ _ _ %u \n',config.mor.pgrid); + logger('output','Temperature range [C]',[kelvin2celsius(config.mor.T0_min),kelvin2celsius(config.mor.T0_max)],'[%g,%g]'); + logger('output','Gas constant range [J/(kg K)]',[config.mor.Rs_min,config.mor.Rs_max],'[%g,%g]'); + logger('output','Parameter Grid Level',config.mor.pgrid,'%u'); config.mor.samples = sparsegrid([config.mor.T0_min;config.mor.Rs_min],[config.mor.T0_max;config.mor.Rs_max],config.mor.pgrid); else @@ -306,7 +330,7 @@ config.mor.samples = [scenario.T0;scenario.Rs]; end%if - fprintf('\n'); + logger('line'); nReductors = numel(reductor_ids); @@ -317,27 +341,21 @@ % Compute (or load) reduced order model (ROM) for each selected reductor for k = 1:nReductors - fprintf('### '); - % Compute and save ROM if isa(reductor{k},'function_handle') - clear(func2str(solver)); - thunklog(100) - off = tic; - ROM{k} = reductor{k}(solver,discrete,scenario,config.mor); - offline{k} = toc(off); - thunklog(0) + id_off = tic; + [proj,name] = reductor{k}(solver,discrete,scenario,config.mor); + offtime = toc(id_off); % Offline time used by reductor + + save([rom_path,'/',network_id,'--',model_id,'--',solver_id,'--',reductor_ids{k},'.rom'],'proj','name','offtime','-v7'); - fprintf('\n'); - fprintf(' > Offline Time [s]: _ _ _ _ _ _ _ _ _ %d\n',offline{k}); + logger('line',2); - spaces = ROM{k}('save'); - name = ROM{k}('name'); - off = offline{k}; - save([rom_path,'/',network_id,'--',model_id,'--',solver_id,'--',reductor_ids{k},'.rom'],'spaces','name','off','-v7'); + logger('output','Offline Time [s]',offtime,'%.1f'); + logger('output','Saved as',[network_id,'--',model_id,'--',solver_id,'--',reductor_ids{k},'.rom'],'%s'); - fprintf(' > Saved as: _ _ _ _ _ _ _ _ _ _ _ _ _ %s \n\n',[network_id,'--',model_id,'--',solver_id,'--',reductor_ids{k},'.rom']); + logger('next'); % Load ROM else @@ -348,40 +366,51 @@ load([rom_path,'/',reductor_ids{k}],'-mat'); - ROM{k} = @(n) make_rom(name,discrete,spaces,n); - offline{k} = off; - fprintf('%s\n\n',ROM{k}('name')); - fprintf(' > Loaded from file:_ _ _ _ _ _ _ _ _ %s\n\n',reductor_ids{k}); + logger('head',name); + + logger('line'); + + logger('output','Loaded from file',reductor_ids{k},'%s'); + + logger('next'); else - fprintf(' > Incompatible ROM: %s\n\n',reductor_ids{k}); % TODO emit error! + error(['Incompatible ROM: ',reductor_ids{k}]); end%if + + reductor_ids{k} = reductor_ids{k}(find(reductor_ids{k} == '-',1,'last')+1:find(reductor_ids{k} == '.',1,'last')-1); % NOTE: Argument mutation! end%if labels{k} = name; + ROM{k} = @(n) make_rom(discrete,proj,n); + offline{k} = offtime; end%for + % Exit if only ROMs are to be computed and not tested if not(isempty(varargin)) && any(strcmp(varargin,'notest')) - R = struct('offline',offline, ... - 'method',labels); + R = struct('reductors',labels, ... + 'offline',offline); - fprintf(' > Orderly exit:_ _ _ _ _ _ _ _ _ _ _ _ '); + logger('exit'); return; end%if + + logger('next'); + end%if %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% FULL ORDER SIMULATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - fprintf('## Computing Reference Solution(s) ... \n\n'); + logger('head','Computing Reference Solution(s) ...'); - config.eval.parametric = inifield(ini,'eval_parametric','yes',{'no','yes'}); + config.eval.parametric = inifield(ini,'eval_parametric','true',{'false','true'}); % Sample test parameters - if strcmp(config.eval.parametric,'yes') && exist('reductor_ids','var') && not(isempty(reductor_ids)) + if strcmp(config.eval.parametric,'true') && exist('reductor_ids','var') && not(isempty(reductor_ids)) prom = 1; config.eval.ptest = inifield(ini,'eval_ptest',1); @@ -393,12 +422,11 @@ config.eval.Rs_min = inifield(ini,'Rs_min',500.0); config.eval.Rs_max = inifield(ini,'Rs_max',900.0); - rand('seed',1009); t0_samples = [config.eval.T0_min + abs(config.eval.T0_max - config.eval.T0_min) * rand(1,nSamples), scenario.T0]; ... rs_samples = [config.eval.Rs_min + abs(config.eval.Rs_max - config.eval.Rs_min) * rand(1,nSamples), scenario.Rs]; - fprintf(' < Parametric evaluation?_ _ _ _ _ _ _ %s \n',config.eval.parametric); - fprintf(' < Number of parameter samples:_ _ _ _ %u \n',config.eval.ptest); + logger('input','Parametric evaluation?',config.eval.parametric,'%s'); + logger('input','Number of parameter samples',config.eval.ptest,'%u'); else prom = 0; @@ -407,11 +435,9 @@ t0_samples = scenario.T0; rs_samples = scenario.Rs; - fprintf(' < Parametric evaluation?_ _ _ _ _ _ _ no \n'); + logger('input','Parametric evaluation?','false','%s'); end%if - fprintf('\n '); - n1 = cell(nSamples + prom,1); n2 = cell(nSamples + prom,1); n8 = cell(nSamples + prom,1); @@ -435,19 +461,19 @@ n0{p} = norm_l0(ref_output{p}.y,config.network.dt); end%for - fprintf('\n\n'); + logger('line',2); - fprintf(' > Steady state iterations:_ _ _ _ _ _ %u \n', ceil(mean(cellfun(@(s) s.steady.iter1,ref_output)))); - fprintf(' > Steady state extra steps: _ _ _ _ _ %u \n', ceil(mean(cellfun(@(s) s.steady.iter2,ref_output)))); - fprintf(' > Steady state error: _ _ _ _ _ _ _ _ %g \n', mean(cellfun(@(s) s.steady.err,ref_output))); - fprintf(' > Mean compressibility: _ _ _ _ _ _ _ %g \n', mean(cellfun(@(s) s.steady.z0,ref_output))); - fprintf(' > Integration time [s]: _ _ _ _ _ _ _ %g \n', mean(cellfun(@(s) s.runtime,ref_output))); + logger('output','Steady state iterations',ceil(mean(cellfun(@(s) s.steady_iter1,ref_output))),'%u'); + logger('output','Steady state extra steps',ceil(mean(cellfun(@(s) s.steady_iter2,ref_output))),'%u'); + logger('output','Steady state error',mean(cellfun(@(s) s.steady_error,ref_output)),'%g'); + logger('output','Mean compressibility',mean(cellfun(@(s) s.steady_z0,ref_output)),'%g'); + logger('output','Integration time [s]',mean(cellfun(@(s) s.runtime,ref_output)),'%.1f'); % Plot input-output of reference solution compact = not(isempty(varargin)) && any(strcmp(varargin,'compact')); plot_output(plot_path,[network_id,'--',scenario_id,'--',model_id,'--',solver_id],ref_output{end},network,compact); - fprintf('\n') + logger('next'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% REDUCED ORDER MODEL EVALUATION @@ -455,7 +481,7 @@ if exist('reductor_ids','var') && not(isempty(reductor_ids)) - fprintf('## Evaluating Reduced Order Models ... \n\n'); + logger('head','Testing Reduced Order Models ...'); config.eval.skip = max(round(inifield(ini,'eval_skip',2)),2); @@ -463,15 +489,12 @@ config.eval.max = min([floor(0.5*eval_max),config.mor.rom_max,discrete.nP,discrete.nQ]); - eff_order = 2 * config.eval.max; - config.eval.pnorm = inifield(ini,'eval_pnorm',2,{1,2,Inf}); - fprintf(' < Test every n-th ROM:_ _ _ _ _ _ _ _ %u \n',config.eval.skip); - fprintf(' < Maximum reduced order:_ _ _ _ _ _ _ %u \n',eff_order); - fprintf(' < Parameter norm: _ _ _ _ _ _ _ _ _ _ %u \n',config.eval.pnorm); + logger('input','Test every n-th ROM',config.eval.skip,'%u'); + logger('input','Maximum reduced order',2 * config.eval.max,'%u'); % NOTE: config.eval.max means max red order per variable - fprintf('\n'); + logger('line'); redOrder = 1:config.eval.skip:config.eval.max; redOrders = numel(redOrder); @@ -491,7 +514,7 @@ for k = 1:nReductors % For each reductor ... - fprintf('### %s\n\n',ROM{k}('name')); + logger('head',labels{k}); % Preallocate error and timing storage online{k} = NaN(nSamples,redOrders); @@ -502,7 +525,8 @@ l8{k} = NaN(nSamples,redOrders); l0{k} = NaN(nSamples,redOrders); - thunklog(redOrders) + logger('solver','reset'); + for p = 1:nSamples % For each test parameter ... for l = 1:redOrders % For each reduced order @@ -516,8 +540,11 @@ l8{k}(p,l) = norm_l8(ref_output{p}.y - red_output.y,config.network.dt) / n8{p}; l0{k}(p,l) = norm_l0(ref_output{p}.y - red_output.y,config.network.dt) / n0{p}; end%for + + logger('solver','reset'); end%for - thunklog(0) + + logger('line'); % Replace NaNs by worst case relative error l1{k}(isnan(l1{k}) | (l1{k} > 1.0)) = 1.0; @@ -540,13 +567,19 @@ online{k} = mean(online{k},1); breven{k} = mean(breven{k},1); - fprintf('\n\n'); + logger('next'); end%for + logger('next'); + + logger('next'); + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% VISUALIZE RESULTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + logger('head','Generating Plots ...'); + yscale = varfield(varargin,'ys',-16); plot_id = varfield(varargin,'pid',''); @@ -556,36 +589,57 @@ base_name = [base_name,'--',plot_id]; end%if - plot_error(plot_path,base_name,'L_0',2*redOrder,l0,labels,s0,compact,yscale); - plot_error(plot_path,base_name,'L_1',2*redOrder,l1,labels,s1,compact,yscale); - plot_error(plot_path,base_name,'L_8',2*redOrder,l8,labels,s8,compact,yscale); - plot_error(plot_path,base_name,'L_2',2*redOrder,l2,labels,s2,compact,yscale); + plot_error(plot_path,base_name,'L0',2 * redOrder,l0,labels,s0,compact,yscale); + plot_error(plot_path,base_name,'L1',2 * redOrder,l1,labels,s1,compact,yscale); + plot_error(plot_path,base_name,'L8',2 * redOrder,l8,labels,s8,compact,yscale); + plot_error(plot_path,base_name,'L2',2 * redOrder,l2,labels,s2,compact,yscale); + + plot_offline(plot_path,[network_id,'--',model_id,'--',solver_id],offline,labels,compact); + plot_online(plot_path,base_name,2 * redOrder,online,labels,compact); + plot_breven(plot_path,base_name,2 * redOrder,breven,labels,compact); + + logger('done'); + + logger('next'); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% PRINT AND SAVE RESULTS +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + logger('head',['L2 MORscores (',base_name,')']); + + logger('input','State norm',2,'%u'); + logger('input','Parameter norm',config.eval.pnorm,'%u'); + logger('input','Numerical precision',10.0^floor(log10(eps)),'%e'); + logger('input','Maximum reduced order',2 * config.eval.max,'%u'); + + logger('line'); close(figure()); - fprintf(' > L2 MORscores (%s):\n\n',base_name); - maxlen = max(cellfun(@numel,labels)); - cellfun(@(l,s) fprintf([' %s:',repmat(' ',[1,maxlen-numel(l)]),' %.2f \n'],l,s),labels,s2); - save_ini([plot_path,'/',base_name,'_morscore_l2.ini'],labels,s2); - fprintf('\n'); + % For each reductor print L2 MORscore + for k = 1:nReductors - plot_offline(plot_path,[network_id,'--',model_id,'--',solver_id],offline,labels,compact); - plot_online(plot_path,base_name,2*redOrder,online,labels,compact); - plot_breven(plot_path,base_name,2*redOrder,breven,labels,compact); + logger('output',reductor_ids{k},s2{k},'%.4f'); + end%for + + save_ini([plot_path,'/',base_name,'_morscore_l2.ini'],labels,s2); R = struct('name',base_name, ... + 'reductors',labels, ... 'orders',redOrder, ... 'l0error',l0, 'l0score',s0, ... 'l1error',l1, 'l1score',s1, ... 'l2error',l2, 'l2score',s2, ... 'l8error',l8, 'l8score',s8, ... - 'online',online, 'breven',breven, ... - 'method',labels); + 'offline',offline, ... + 'online',online, ... + 'breven',breven); else - R = []; + R = ref_output{1}.y; end%if - fprintf(' > Orderly exit:_ _ _ _ _ _ _ _ _ _ _ _ '); + logger('exit'); end diff --git a/morgen.png b/morgen.png new file mode 100644 index 0000000000000000000000000000000000000000..bbf93d9dcb3263ea3b833360f08591d377851568 GIT binary patch literal 2522 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 short pipe TODO - diameter = str2num(raw.(fields{k}).d); - csv{curr} = ['S,', ... num2str(node1,'%u'),',', ... num2str(node2,'%u')]; diff --git a/utils/cfl.m b/tools/psi2bar.m similarity index 61% rename from utils/cfl.m rename to tools/psi2bar.m index b646521..d39af1f 100644 --- a/utils/cfl.m +++ b/tools/psi2bar.m @@ -1,9 +1,9 @@ -function c = cfl(dx,dt,v) +function b = psi2bar(p) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) -%%% summary: Compute Courant-Friedrichs-Levy constant. +%%% summary: Convert pound per square inch (psi) to bar - c = v * (dt / dx); + b = p ./ 14.503773800722; end diff --git a/tools/randscen.m b/tools/randscen.m index 6666956..e86f109 100644 --- a/tools/randscen.m +++ b/tools/randscen.m @@ -1,13 +1,13 @@ -function randscen(training,output) +function randscen(network,scenario_name) %%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) +%%% version: 1.0 (2021-06-22) %%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) %%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) %%% summary: Generate random scenario from training scenario %% Read Training Scenario - f = fopen(['../networks/',training,'/training.ini'],'r'); + f = fopen(['../networks/',network,'/training.ini'],'r'); co = textscan(f,'%s = %s','CommentStyle','#'); @@ -17,19 +17,19 @@ function randscen(training,output) %% Write Random Scenario - f = fopen([output,'.ini'],'w'); + f = fopen([scenario_name,'.ini'],'w'); - fprintf(f,'T0 = %g\n',str2num(ini.T0)); - fprintf(f,'Rs = %g\n',str2num(ini.Rs)); + fprintf(f,'T0 = %g\n',str2double(ini.T0)); + fprintf(f,'Rs = %g\n',str2double(ini.Rs)); fprintf(f,'tH = %g\n',86400.0); %% Compressor Pressures if isfield(ini,'cp') - compressor_pressure = cell2mat(cellfun(@(c) str2num(c),strsplit(ini.cp,'|'),'UniformOutput',false))'; + compressor_pressure = cell2mat(cellfun(@(c) str2double(c),strsplit(ini.cp,'|'),'UniformOutput',false))'; fprintf(f,'cp = '); - for l = 1:(numel(compressor_pressure) - 1); + for l = 1:(numel(compressor_pressure) - 1) fprintf(f,'%g|',compressor_pressure(l)); end%for @@ -39,7 +39,7 @@ function randscen(training,output) %% Supply Pressures - supply_pressure = cell2mat(cellfun(@(c) str2num(c),strsplit(ini.up,'|'),'UniformOutput',false))'; + supply_pressure = cell2mat(cellfun(@(c) str2double(c),strsplit(ini.up,'|'),'UniformOutput',false))'; fprintf(f,'up = '); for k = 1:24 @@ -61,7 +61,7 @@ function randscen(training,output) %% Demand Mass-Fluxes - demand_massflux = cell2mat(cellfun(@(c) str2num(c),strsplit(ini.uq,'|'),'UniformOutput',false))'; + demand_massflux = cell2mat(cellfun(@(c) str2double(c),strsplit(ini.uq,'|'),'UniformOutput',false))'; rand_demand = [demand_massflux; demand_massflux .* (0.75 + 0.5*rand(23,numel(demand_massflux)))]; diff --git a/tools/vf2kgs.m b/tools/vf2kgs.m new file mode 100644 index 0000000..34fb291 --- /dev/null +++ b/tools/vf2kgs.m @@ -0,0 +1,49 @@ +function kgs = vf2kgs(value,vol_unit,time_unit,gas_density) +%%% project: morgen - Model Order Reduction for Gas and Energy Networks +%%% version: 1.0 (2021-06-22) +%%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) +%%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) +%%% summary: Convert volume flow in mass flow [kg/s] + + switch vol_unit + + case {'m3','m^3','sm3','sm^3'} + vf = 1.0; + + case {'ksm3','ksm^3'} + vf = 1000.0; + + case {'km3','km^3'} + vf = 1000000.0; + + case {'cf'} + vf = 1.0 / 35.315; + + case {'mcf'} + vf = 1000.0 / 35.315; + + case {'mmcf'} + vf = 1000000.0 / 35.315; + + end%switch + + switch time_unit + + case 's' + uf = vf; + + case 'h' + uf = vf / 3600.0; + + case 'd' + uf = vf / 86400.0; + + end%switch + + if 3 == nargin + + gas_density = 0.7; % [kg/m^3] for high caloric natural gas + end%if + + kgs = value .* uf .* gas_density; +end diff --git a/tools/vf2mf.m b/tools/vf2mf.m deleted file mode 100644 index b09bce9..0000000 --- a/tools/vf2mf.m +++ /dev/null @@ -1,14 +0,0 @@ -function mf = vf2mf(vf,den) -%%% project: morgen - Model Order Reduction for Gas and Energy Networks -%%% version: 0.99 (2021-04-12) -%%% authors: C. Himpe (0000-0003-2194-6754), S. Grundel (0000-0002-0209-6566) -%%% license: BSD-2-Clause (opensource.org/licenses/BSD-2-clause) -%%% summary: Convert volume flow [m^3/h] in mass flow [kg/s] - - if 1 == nargin - - den = 0.7; % [kg/m^3] for high caloric natural gas - end%if - - mf = (vf / 3600.0) * den; -end diff --git a/tools/xml2net.xsl b/tools/xml2net.xsl index 57871ca..34b4297 100644 --- a/tools/xml2net.xsl +++ b/tools/xml2net.xsl @@ -1,7 +1,7 @@