diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index 9cd3982c4..a34d27b04 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -472,6 +472,7 @@ if(ENABLE_ECL_INPUT)
examples/opmi.cpp
examples/opmpack.cpp
examples/opmhash.cpp
+ examples/wellgraph.cpp
)
endif()
diff --git a/examples/wellgraph.cpp b/examples/wellgraph.cpp
new file mode 100644
index 000000000..6d6227f0b
--- /dev/null
+++ b/examples/wellgraph.cpp
@@ -0,0 +1,135 @@
+/*
+ Copyright 2013, 2020 Equinor ASA.
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OPM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OPM. If not, see .
+*/
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+inline void createDot(const Opm::Schedule& schedule, const std::string& casename)
+{
+ std::cout << "Writing " << casename << ".gv .... "; std::cout.flush();
+ std::ofstream os(casename + ".gv");
+ os << "// This file was written by the 'wellgraph' utility from OPM.\n";
+ os << "// Find the source code at github.com/OPM.\n";
+ os << "// Convert output to PDF with 'dot -Tpdf " << casename << ".gv > " << casename << ".pdf'\n";
+ os << "strict digraph " << casename << "\n{\n";
+ const auto groupnames = schedule.groupNames();
+ const std::size_t last = schedule.getTimeMap().last();
+ // Group -> Group relations.
+ for (const auto& gn : groupnames) {
+ const auto& g = schedule.getGroup(gn, last);
+ const auto& children = g.groups();
+ if (!children.empty()) {
+ os << " " << gn << " -> {";
+ for (const auto& child : children) {
+ os << ' ' << child;
+ }
+ os << " }\n";
+ }
+ }
+ // Group -> Well relations.
+ os << " node [shape=box]\n";
+ for (const auto& gn : groupnames) {
+ const auto& g = schedule.getGroup(gn, last);
+ const auto& children = g.wells();
+ if (!children.empty()) {
+ os << " " << gn << " -> {";
+ for (const auto& child : children) {
+ os << ' ' << child;
+ }
+ os << " }\n";
+ }
+ }
+ // Color wells by injector or producer.
+ for (const auto& w : schedule.getWellsatEnd()) {
+ os << " " << w.name();
+ if (w.isProducer() && w.isInjector()) {
+ os << " [color=purple]\n";
+ } else if (w.isProducer()) {
+ os << " [color=red]\n";
+ } else {
+ os << " [color=blue]\n";
+ }
+ }
+ os << "}\n";
+ std::cout << "complete." << std::endl;
+}
+
+
+inline Opm::Schedule loadSchedule(const std::string& deck_file)
+{
+ Opm::ParseContext parseContext({{Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputError::IGNORE},
+ {Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputError::WARN},
+ {Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputError::WARN},
+ {Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputError::WARN}});
+ Opm::ErrorGuard errors;
+ Opm::Parser parser;
+ auto python = std::make_shared();
+
+ std::cout << "Loading and parsing deck: " << deck_file << " ..... "; std::cout.flush();
+ auto deck = parser.parseFile(deck_file, parseContext, errors);
+ std::cout << "complete.\n";
+
+ std::cout << "Creating EclipseState .... "; std::cout.flush();
+ Opm::EclipseState state( deck );
+ std::cout << "complete.\n";
+
+ std::cout << "Creating Schedule .... "; std::cout.flush();
+ Opm::Schedule schedule( deck, state, python);
+ std::cout << "complete." << std::endl;
+
+ return schedule;
+}
+
+
+int main(int argc, char** argv)
+{
+ std::ostringstream os;
+ std::shared_ptr string_log = std::make_shared(os, Opm::Log::DefaultMessageTypes);
+ Opm::OpmLog::addBackend( "STRING" , string_log);
+ try {
+ for (int iarg = 1; iarg < argc; iarg++) {
+ const std::string filename = argv[iarg];
+ const auto sched = loadSchedule(filename);
+ const auto casename = Opm::filesystem::path(filename).stem();
+ createDot(sched, casename);
+ }
+ } catch (const std::exception& e) {
+ std::cout << "\n\n***** Caught an exception: " << e.what() << std::endl;
+ std::cout << "\n\n***** Printing log: "<< std::endl;
+ std::cout << os.str();
+ std::cout << "\n\n***** Exiting due to errors." << std::endl;
+ }
+}
+