From 37fa48cfbe14abeab9d1c9f72fb1fc347601a727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 11 Feb 2015 14:03:47 +0100 Subject: [PATCH 1/4] Added computeWellPairs() function. --- opm/core/flowdiagnostics/FlowDiagnostics.cpp | 60 ++++++++++++++++++++ opm/core/flowdiagnostics/FlowDiagnostics.hpp | 19 +++++++ 2 files changed, 79 insertions(+) diff --git a/opm/core/flowdiagnostics/FlowDiagnostics.cpp b/opm/core/flowdiagnostics/FlowDiagnostics.cpp index 9df570e6..26f22206 100644 --- a/opm/core/flowdiagnostics/FlowDiagnostics.cpp +++ b/opm/core/flowdiagnostics/FlowDiagnostics.cpp @@ -18,6 +18,7 @@ */ #include +#include #include #include @@ -163,4 +164,63 @@ namespace Opm + + + /// \brief Compute volumes associated with injector-producer pairs. + /// + /// \param[in] wells wells structure, containing NI injector wells and NP producer wells. + /// \param[in] porevol pore volume of each grid cell + /// \param[in] ftracer array of forward (injector) tracer values, NI per cell + /// \param[in] btracer array of backward (producer) tracer values, NP per cell + /// \return a vector of tuples, one tuple for each injector-producer pair, + /// where the first and second elements are well indices for the + /// injector and producer, and the third element is the pore volume + /// associated with that pair. + std::vector > + computeWellPairs(const Wells& wells, + const std::vector& porevol, + const std::vector& ftracer, + const std::vector& btracer) + { + // Identify injectors and producers. + std::vector inj; + std::vector prod; + const int nw = wells.number_of_wells; + for (int w = 0; w < nw; ++w) { + if (wells.type[w] == INJECTOR) { + inj.push_back(w); + } else { + prod.push_back(w); + } + } + + // Check sizes of input arrays. + const int nc = porevol.size(); + if (nc * inj.size() != ftracer.size()) { + OPM_THROW(std::runtime_error, "computeWellPairs(): wrong size of input array ftracer."); + } + if (nc * prod.size() != btracer.size()) { + OPM_THROW(std::runtime_error, "computeWellPairs(): wrong size of input array btracer."); + } + + // Compute associated pore volumes. + std::vector > result; + const int num_inj = inj.size(); + const int num_prod = prod.size(); + for (int inj_ix = 0; inj_ix < num_inj; ++inj_ix) { + for (int prod_ix = 0; prod_ix < num_prod; ++prod_ix) { + double assoc_porevol = 0.0; + for (int c = 0; c < nc; ++c) { + assoc_porevol += porevol[c] + * ftracer[num_inj * c + inj_ix] + * btracer[num_prod * c + prod_ix]; + } + result.push_back(std::make_tuple(inj[inj_ix], prod[prod_ix], assoc_porevol)); + } + } + return result; + } + + + } // namespace Opm diff --git a/opm/core/flowdiagnostics/FlowDiagnostics.hpp b/opm/core/flowdiagnostics/FlowDiagnostics.hpp index 96b51234..b5bb8c07 100644 --- a/opm/core/flowdiagnostics/FlowDiagnostics.hpp +++ b/opm/core/flowdiagnostics/FlowDiagnostics.hpp @@ -23,7 +23,9 @@ #include #include +#include +struct Wells; namespace Opm { @@ -79,6 +81,23 @@ namespace Opm computeSweep(const std::vector& flowcap, const std::vector& storagecap); + + /// \brief Compute volumes associated with injector-producer pairs. + /// + /// \param[in] wells wells structure, containing NI injector wells and NP producer wells. + /// \param[in] porevol pore volume of each grid cell + /// \param[in] ftracer array of forward (injector) tracer values, NI per cell + /// \param[in] btracer array of backward (producer) tracer values, NP per cell + /// \return a vector of tuples, one tuple for each injector-producer pair, + /// where the first and second elements are well indices for the + /// injector and producer, and the third element is the pore volume + /// associated with that pair. + std::vector> + computeWellPairs(const Wells& wells, + const std::vector& porevol, + const std::vector& ftracer, + const std::vector& btracer); + } // namespace Opm #endif // OPM_FLOWDIAGNOSTICS_HEADER_INCLUDED From fbdc0ab9bbdb75b4aa2fdd57b2927592af471f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 11 Feb 2015 16:00:24 +0100 Subject: [PATCH 2/4] Compute both directions always in compute_tof. --- examples/compute_tof.cpp | 116 ++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 56 deletions(-) diff --git a/examples/compute_tof.cpp b/examples/compute_tof.cpp index be465dec..c882a781 100644 --- a/examples/compute_tof.cpp +++ b/examples/compute_tof.cpp @@ -203,14 +203,6 @@ try } bool compute_tracer = param.getDefault("compute_tracer", false); - bool start_from_injectors = true; - std::string trace_start = param.getDefault("trace_start", "Injectors"); - if (trace_start == "Producers") { - start_from_injectors = false; - } else if (trace_start != "Injectors") { - OPM_THROW(std::runtime_error, "Unknown trace_start specification (allowed is Injectors or Producers): " << trace_start); - } - // Write parameters used for later reference. bool output = param.getDefault("output", true); std::ofstream epoch_os; @@ -252,68 +244,80 @@ try std::cout << "Pressure solver took: " << pt << " seconds." << std::endl; ptime += pt; - // Turn direction of flux if starting from producers. - if (!start_from_injectors) { - for (auto it = flux.begin(); it != flux.end(); ++it) { - (*it) = -(*it); + std::string tof_filenames[2] = { output_dir + "/ftof.txt", output_dir + "/btof.txt" }; + std::string tracer_filenames[2] = { output_dir + "/ftracer.txt", output_dir + "/btracer.txt" }; + + // We compute tof twice, direction == 0 is from injectors, 1 is from producers. + for (int direction = 0; direction < 2; ++direction) { + // Turn direction of flux if starting from producers. + if (direction == 1) { + for (auto it = flux.begin(); it != flux.end(); ++it) { + (*it) = -(*it); + } } - } - // Process transport sources (to include bdy terms and well flows). - std::vector src(num_cells, 0.0); - std::vector transport_src; - computeTransportSourceSinglePhase(grid, src, flux, 1.0, - &wells, wellrates, transport_src); + // Process transport sources (to include bdy terms and well flows). + std::vector src(num_cells, 0.0); + std::vector transport_src; + computeTransportSourceSinglePhase(grid, src, flux, 1.0, + &wells, wellrates, transport_src); - // Solve time-of-flight. - transport_timer.start(); - std::vector tof; - std::vector tracer; - Opm::SparseTable tracerheads; - if (compute_tracer) { - buildTracerheadsFromWells(wells, start_from_injectors, tracerheads); - } - if (use_dg) { + // Solve time-of-flight. + transport_timer.start(); + std::vector tof; + std::vector tracer; + Opm::SparseTable tracerheads; if (compute_tracer) { - dg_solver->solveTofTracer(flux.data(), porevol.data(), transport_src.data(), tracerheads, tof, tracer); + buildTracerheadsFromWells(wells, direction == 0, tracerheads); + } + if (use_dg) { + if (compute_tracer) { + dg_solver->solveTofTracer(flux.data(), porevol.data(), transport_src.data(), tracerheads, tof, tracer); + } else { + dg_solver->solveTof(flux.data(), porevol.data(), transport_src.data(), tof); + } } else { - dg_solver->solveTof(flux.data(), porevol.data(), transport_src.data(), tof); + Opm::TofReorder tofsolver(grid, use_multidim_upwind); + if (compute_tracer) { + tofsolver.solveTofTracer(flux.data(), porevol.data(), transport_src.data(), tracerheads, tof, tracer); + } else { + tofsolver.solveTof(flux.data(), porevol.data(), transport_src.data(), tof); + } } - } else { - Opm::TofReorder tofsolver(grid, use_multidim_upwind); - if (compute_tracer) { - tofsolver.solveTofTracer(flux.data(), porevol.data(), transport_src.data(), tracerheads, tof, tracer); + transport_timer.stop(); + double tt = transport_timer.secsSinceStart(); + if (direction == 0) { + std::cout << "Forward "; } else { - tofsolver.solveTof(flux.data(), porevol.data(), transport_src.data(), tof); + std::cout << "Backward "; } - } - transport_timer.stop(); - double tt = transport_timer.secsSinceStart(); - std::cout << "Transport solver took: " << tt << " seconds." << std::endl; - ttime += tt; - total_timer.stop(); + std::cout << "time-of-flight/tracer solve took: " << tt << " seconds." << std::endl; + ttime += tt; - // Output. - if (output) { - std::string tof_filename = output_dir + "/tof.txt"; - std::ofstream tof_stream(tof_filename.c_str()); - tof_stream.precision(16); - std::copy(tof.begin(), tof.end(), std::ostream_iterator(tof_stream, "\n")); - if (compute_tracer) { - std::string tracer_filename = output_dir + "/tracer.txt"; - std::ofstream tracer_stream(tracer_filename.c_str()); - tracer_stream.precision(16); - const int nt = tracer.size()/num_cells; - for (int i = 0; i < nt*num_cells; ++i) { - tracer_stream << tracer[i] << (((i + 1) % nt == 0) ? '\n' : ' '); + // Output. + if (output) { + std::string tof_filename = tof_filenames[direction]; + std::ofstream tof_stream(tof_filename.c_str()); + tof_stream.precision(16); + std::copy(tof.begin(), tof.end(), std::ostream_iterator(tof_stream, "\n")); + if (compute_tracer) { + std::string tracer_filename = tracer_filenames[direction]; + std::ofstream tracer_stream(tracer_filename.c_str()); + tracer_stream.precision(16); + const int nt = tracer.size()/num_cells; + for (int i = 0; i < nt*num_cells; ++i) { + tracer_stream << tracer[i] << (((i + 1) % nt == 0) ? '\n' : ' '); + } } } } + total_timer.stop(); + std::cout << "\n\n================ End of simulation ===============\n" - << "Total time taken: " << total_timer.secsSinceStart() - << "\n Pressure time: " << ptime - << "\n Transport time: " << ttime << std::endl; + << "Total time taken: " << total_timer.secsSinceStart() + << "\n Pressure time: " << ptime + << "\n Tof/tracer time: " << ttime << std::endl; } catch (const std::exception &e) { std::cerr << "Program threw an exception: " << e.what() << "\n"; From 0de85da48781bfa0d2eba5741c058136b18b8a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 12 Feb 2015 10:13:33 +0100 Subject: [PATCH 3/4] Compute and output well pairs. Only if already computing tracer information. --- examples/compute_tof.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/examples/compute_tof.cpp b/examples/compute_tof.cpp index c882a781..5aed682b 100644 --- a/examples/compute_tof.cpp +++ b/examples/compute_tof.cpp @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -246,6 +247,7 @@ try std::string tof_filenames[2] = { output_dir + "/ftof.txt", output_dir + "/btof.txt" }; std::string tracer_filenames[2] = { output_dir + "/ftracer.txt", output_dir + "/btracer.txt" }; + std::vector tracers[2]; // We compute tof twice, direction == 0 is from injectors, 1 is from producers. for (int direction = 0; direction < 2; ++direction) { @@ -308,10 +310,22 @@ try for (int i = 0; i < nt*num_cells; ++i) { tracer_stream << tracer[i] << (((i + 1) % nt == 0) ? '\n' : ' '); } + tracers[direction] = tracer; } } } + // If we have tracers, compute well pairs. + if (compute_tracer) { + auto wp = Opm::computeWellPairs(wells, porevol, tracers[0], tracers[1]); + std::string wellpair_filename = output_dir + "/wellpairs.txt"; + std::ofstream wellpair_stream(wellpair_filename.c_str()); + const int nwp = wp.size(); + for (int ii = 0; ii < nwp; ++ii) { + wellpair_stream << std::get<0>(wp[ii]) << ' ' << std::get<1>(wp[ii]) << ' ' << std::get<2>(wp[ii]) << '\n'; + } + } + total_timer.stop(); std::cout << "\n\n================ End of simulation ===============\n" From c56d69cb8a234255b97c06de8c44b23b28101163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 12 Feb 2015 11:13:29 +0100 Subject: [PATCH 4/4] Fix treatment of source terms for backwards tracing. --- examples/compute_tof.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/compute_tof.cpp b/examples/compute_tof.cpp index 5aed682b..6945fa76 100644 --- a/examples/compute_tof.cpp +++ b/examples/compute_tof.cpp @@ -245,25 +245,28 @@ try std::cout << "Pressure solver took: " << pt << " seconds." << std::endl; ptime += pt; + // Process transport sources (to include bdy terms and well flows). + std::vector src(num_cells, 0.0); + std::vector transport_src; + computeTransportSourceSinglePhase(grid, src, flux, 1.0, + &wells, wellrates, transport_src); + std::string tof_filenames[2] = { output_dir + "/ftof.txt", output_dir + "/btof.txt" }; std::string tracer_filenames[2] = { output_dir + "/ftracer.txt", output_dir + "/btracer.txt" }; std::vector tracers[2]; // We compute tof twice, direction == 0 is from injectors, 1 is from producers. for (int direction = 0; direction < 2; ++direction) { - // Turn direction of flux if starting from producers. + // Turn direction of flux and flip source terms if starting from producers. if (direction == 1) { for (auto it = flux.begin(); it != flux.end(); ++it) { (*it) = -(*it); } + for (auto it = transport_src.begin(); it != transport_src.end(); ++it) { + (*it) = -(*it); + } } - // Process transport sources (to include bdy terms and well flows). - std::vector src(num_cells, 0.0); - std::vector transport_src; - computeTransportSourceSinglePhase(grid, src, flux, 1.0, - &wells, wellrates, transport_src); - // Solve time-of-flight. transport_timer.start(); std::vector tof;