diff --git a/opm/core/well_controls.h b/opm/core/well_controls.h index 6998f4829..83817bd57 100644 --- a/opm/core/well_controls.h +++ b/opm/core/well_controls.h @@ -22,7 +22,10 @@ #include - +/** + * @file + * API for managing sets of well controls. + */ #ifdef __cplusplus extern "C" { @@ -42,6 +45,16 @@ well_controls_equal(const struct WellControls *ctrls1, const struct WellControls struct WellControls * well_controls_create(void); +/** + * Create deep copy (clone) of an existing set of well controls. + * + * @param[in] ctrl Existing set of well controls. + * + * @return Deep copy of @c ctrl. + */ +struct WellControls * +well_controls_clone(const struct WellControls *ctrl); + void well_controls_destroy(struct WellControls *ctrl); diff --git a/opm/core/wells/well_controls.c b/opm/core/wells/well_controls.c index 78742643c..1ce6679e7 100644 --- a/opm/core/wells/well_controls.c +++ b/opm/core/wells/well_controls.c @@ -181,6 +181,65 @@ well_controls_reserve(int nctrl, struct WellControls *ctrl) } +/* ---------------------------------------------------------------------- */ +struct WellControls * +well_controls_clone(const struct WellControls *ctrl) +/* ---------------------------------------------------------------------- */ +{ + int ok, i, n; + double target; + const double *distr; + struct WellControls *new; + enum WellControlType type; + + new = well_controls_create(); + + if (new != NULL) { + /* Assign appropriate number of phases */ + well_controls_assert_number_of_phases(new, ctrl->number_of_phases); + + n = well_controls_get_num(ctrl); + ok = well_controls_reserve(n, new); + + if (! ok) { + well_controls_destroy(new); + new = NULL; + } + else { + for (i = 0; ok && (i < n); i++) { + type = well_controls_iget_type (ctrl, i); + distr = well_controls_iget_distr (ctrl, i); + target = well_controls_iget_target(ctrl, i); + + ok = well_controls_add_new(type, target, distr, new); + } + + if (i < n) { + assert (!ok); + well_controls_destroy(new); + + new = NULL; + } + else { + i = well_controls_get_current(ctrl); + well_controls_set_current(new, i); + + if (well_controls_well_is_open(ctrl)) { + well_controls_open_well(new); + } + else { + well_controls_shut_well(new); + } + } + } + } + + assert (well_controls_equal(ctrl, new, true)); + + return new; +} + + int well_controls_get_num(const struct WellControls *ctrl) { return ctrl->num; } diff --git a/tests/test_wellcontrols.cpp b/tests/test_wellcontrols.cpp index 8424ab0b5..c5b1f9466 100644 --- a/tests/test_wellcontrols.cpp +++ b/tests/test_wellcontrols.cpp @@ -116,3 +116,28 @@ BOOST_AUTO_TEST_CASE(OpenClose) well_controls_destroy( ctrls ); } + +BOOST_AUTO_TEST_CASE(Clone) +{ + std::shared_ptr + ctrls(well_controls_create(), + & well_controls_destroy); + + const WellControlType type1 = BHP; + const WellControlType type2 = SURFACE_RATE; + + const int num_phases = 3; + const double dist1[] = { 0, 1, 2}; + const double dist2[] = {10, 11, 12}; + const double target = 77; + + well_controls_assert_number_of_phases(ctrls.get(), num_phases); + well_controls_add_new(type1, target, dist1, ctrls.get()); + well_controls_add_new(type2, 2*target, dist2, ctrls.get()); + + std::shared_ptr + c(well_controls_clone(ctrls.get()), + & well_controls_destroy); + + BOOST_CHECK(well_controls_equal(ctrls.get(), c.get(), false)); +}