{"id":20612609,"url":"https://github.com/pypsa/nomopyomo","last_synced_at":"2025-10-17T19:34:29.122Z","repository":{"id":84861550,"uuid":"202335791","full_name":"PyPSA/nomopyomo","owner":"PyPSA","description":null,"archived":false,"fork":false,"pushed_at":"2020-11-25T08:47:06.000Z","size":114,"stargazers_count":7,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T07:07:42.736Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PyPSA.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-08-14T11:20:59.000Z","updated_at":"2022-12-07T09:28:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"fda25f13-26a8-451f-9aaa-e2630487806c","html_url":"https://github.com/PyPSA/nomopyomo","commit_stats":{"total_commits":31,"total_committers":1,"mean_commits":31.0,"dds":0.0,"last_synced_commit":"57dd09b6276fd3cfb298969ce06beb3a011d6326"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyPSA%2Fnomopyomo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyPSA%2Fnomopyomo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyPSA%2Fnomopyomo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyPSA%2Fnomopyomo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PyPSA","download_url":"https://codeload.github.com/PyPSA/nomopyomo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249023723,"owners_count":21199960,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T11:05:52.900Z","updated_at":"2025-10-17T19:34:29.052Z","avatar_url":"https://github.com/PyPSA.png","language":"Python","readme":"\n\n**WARNING**: This repository is no longer under development and cannot\nbe supported. The nomopyomo code has been incorporated into\n[PyPSA](https://github.com/PyPSA/PyPSA) and further developed\nthere. To use it, pass the `network.lopf()` the `pyomo=False`\nargument:\n\n```python\nnetwork.lopf(pyomo=False)\n```\n\n\n# nomopyomo - no more pyomo\n\nThis script takes an unsolved [PyPSA](https://github.com/PyPSA/PyPSA)\nnetwork and solves an investment and operation linear optimisation\nproblem with power flow (LOPF) using a custom handler for the\noptimisation solver, rather than the [pyomo](http://www.pyomo.org)\noptimisation framework used by PyPSA.\n\nnomopyomo is both faster than pyomo and uses considerably less\nmemory.\n\nHere is an example of the memory usage when solving investments and\noperation for a zero-net-emission sector-coupled 50-node model of\nEurope 3-hourly for a year (9 million variables, 5 milion constraints,\n22 million non-zero values in the constraint matrix). Pyomo takes up\nmore than three quarters of the total memory used, whereas nomopyomo\nis so memory-efficient that the solver gurobi dominates the memory\nusage.\n\n![pyomo-nomopyomo comparison](https://www.nworbmot.org/pyomo-versus-nomopyomo-190828-1100.png)\n\nThe final memory surge can probably be eliminated by managing the\nmemory in pyomo's GUROBI_RUN.py script better (nomopyomo uses this\nscript to run gurobi and return the values of dual variables).\n\nThe fact that the gurobi solving time is shorter with nomopyomo than\npyomo is not a general feature, but a random speed-up for this problem\nthat comes from a different ordering of the variables and\nconstraints. It will not hold for all problems.\n\nThe results are identical (within the solver tolerances) and have been\ntested with a variety of standard PyPSA test cases.\n\nOn the negative side, nomopyomo is harder to customise and cannot\ncurrently be used for non-linear problems.\n\nnomopyomo works by writing an .lp file for the problem, solving it, and\nreading back in the solution.\n\nThe script currently works for Load, Generator, Link, Line,\nTransformer, Store and GlobalConstraint components, and with the\nsolvers cbc/clp and gurobi.\n\nIt has been tested against the standard PyPSA examples.\n\nTODO:\n\n- constant term in objective function\n- handle non-optimal solutions\n- calculate nodal imbalances\n- calculate voltage angles\n- implement glpk solver\n- logfile for cbc\n\nNo planned support for StorageUnit (replace with Store and Links\nfollowing [this\nexample](https://pypsa.org/examples/replace-generator-storage-units-with-store.html)).\n\n# Usage\n\nThe usage is similar to PyPSA's `network.lopf()`:\n\n```python\nimport nomopyomo\n\nnomopyomo.network_lopf(network, solver_name=\"cbc\")\n```\n\n# Customisation\n\nJust like PyPSA's `network.lopf()` you can add `extra_functionality`\nand `extra_postprocessing` arguments, however the code must be\nmodified from the PyPSA case to use nomopyomo instead of pyomo. For an\nexample, see the [changes made for the model.energy\ncode](https://github.com/PyPSA/whobs-server/commit/0908ed45d7758bb75f2f52ad028a170093e1a8a0).\n\n\n\n# How it works\n\nnomopyomo gives each variable and constraint a unique integer label,\nthen writes the linear objective function, variable bounds and\nconstraints to a .lp problem file. It is solved, then the result is\nread back in. nomopyomo stores very little in memory beyond the\noriginal pypsa.Network.\n\nThe integer assignments are determined by an implicit ordering of the\nvariables and constraints. Within each group (shown below), the\nvariables are indexed in order by several index sets. The start and\nfinish integers for each group are stored in the pandas.DataFrames\n`network.variable_positions` and `network.constraint_positions`.\n\nThe variables are organised into the following groups:\n\n| group name | variables | index by |\n| --- | --- | --- |\n| Generator-p | generator dispatch | network.generators.index, snapshots |\n| Generator-p_nom | extendable generator capacity | network.generators.index[network.generator.p_nom_extendable] |\n| Link-p | link dispatch | network.links.index, snapshots |\n| Link-p_nom | extendable link capacity | network.links.index[network.link.p_nom_extendable] |\n| Store-p | store dispatch | network.stores.index, snapshots |\n| Store-e | store state of charge | network.stores.index, snapshots |\n| Store-e_nom | extendable store capacity | network.stores.index[network.store.e_nom_extendable] |\n| Line-p | line dispatch | network.lines.index, snapshots |\n| Line-s_nom | extendable line capacity | network.lines.index[network.line.s_nom_extendable] |\n| Transformer-p | transformer dispatch | network.transformers.index, snapshots |\n| Transformer-s_nom | extendable transformer capacity | network.transformers.index[network.transformer.s_nom_extendable] |\n\n\n\nThe constraints are organised into the following groups:\n\n| group name | constraints | index by |\n| --- | --- | --- |\n| Generator-p_lower | dispatch limit for extendable generators | network.generators.index[network.generator.p_nom_extendable], snapshots |\n| Generator-p_upper | dispatch limit for extendable generators | network.generators.index[network.generator.p_nom_extendable], snapshots |\n| etc for other components | |\n| Cycle | Kirchhoff Voltage Law for passive branches | cycles, snapshots |\n| Store | store state of charge consistency | network.stores.index, snapshots |\n| nodal_balance | energy conservation at each bus | network.buses.index, snapshots |\n| global_constraints | constraints on e.g. CO2 emissions | network.global_constraints.index |\n\n# Licence\n\n\nCopyright 2019 Tom Brown (KIT)\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either [version 3 of the\nLicense](./LICENSE.txt), or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the [GNU\nGeneral Public License](./LICENSE.txt) for more details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpypsa%2Fnomopyomo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpypsa%2Fnomopyomo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpypsa%2Fnomopyomo/lists"}