int
main(int argc, char* argv[])
{
    const Opm::parameter::ParameterGroup param(argc, argv, false);
    const Opm::GridManager               gm(5, 5);

    const UnstructuredGrid*              g  = gm.c_grid();
    const int                            nc = g->number_of_cells;
    const Opm::BlackoilPropertiesBasic   oldprops(param, 2, nc);
    const Opm::BlackoilPropsAd           props(oldprops);

    typedef AutoDiff::ForwardBlock<double>      ADB;

    Wells* wells = create_wells(2, 2, 5);
    const double inj_frac[] = { 1.0, 0.0 };
    const double prod_frac[] = { 0.0, 0.0 };
    const int num_inj = 3;
    const int inj_cells[num_inj] = { 0, 1, 2 };
    const int num_prod = 2;
    const int prod_cells[num_prod] = { 20, 21 };
    const double WI[3] = { 1e-12, 1e-12, 1e-12 };
    bool ok = add_well(INJECTOR, 0.0, num_inj, inj_frac, inj_cells, WI, "Inj", wells);
    ok = ok && add_well(PRODUCER, 0.0, num_prod, prod_frac, prod_cells, WI, "Prod", wells);
    ok = ok && append_well_controls(BHP, 500.0*Opm::unit::barsa, 0, 0, wells);
    // ok = ok && append_well_controls(BHP, 200.0*Opm::unit::barsa, 0, 1, wells);
    double oildistr[2] = { 0.0, 1.0 };
    ok = ok && append_well_controls(SURFACE_RATE, 1e-3, oildistr, 1, wells);
    if (!ok) {
        THROW("Something went wrong with well init.");
    }
    set_current_control(0, 0, wells);
    set_current_control(1, 0, wells);

    double grav[] = { /*1.0*/ 0.0, 0.0 };
    Opm::DerivedGeology geo(*g, props, grav);
    Opm::LinearSolverFactory linsolver(param);
    Opm::ImpesTPFAAD ps(*g, props, geo, *wells, linsolver);

    Opm::BlackoilState state;
    initStateBasic(*g, oldprops, param, 0.0, state);
    initBlackoilSurfvol(*g, oldprops, state);
    Opm::WellState well_state;
    well_state.init(wells, state);

    ps.solve(1.0, state, well_state);

    std::cout << "Cell pressure:" << std::endl;
    std::copy(state.pressure().begin(), state.pressure().end(), std::ostream_iterator<double>(std::cout, " "));
    std::cout << std::endl;
    std::cout << "Face flux:" << std::endl;
    std::copy(state.faceflux().begin(), state.faceflux().end(), std::ostream_iterator<double>(std::cout, " "));
    std::cout << std::endl;
    std::cout << "Well bhp pressure:" << std::endl;
    std::copy(well_state.bhp().begin(), well_state.bhp().end(), std::ostream_iterator<double>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}
Beispiel #2
0
/* ---------------------------------------------------------------------- */
struct Wells *
clone_wells(const struct Wells *W)
/* ---------------------------------------------------------------------- */
{
    int                  np, nperf, ok, pos, w;
    const int           *cells;
    const double        *WI, *comp_frac;

    struct WellControls *ctrl;
    struct Wells        *newWells;

    if (W == NULL) {
        newWells = NULL;
    }
    else {
        np  = W->number_of_phases;
        newWells = create_wells(W->number_of_phases, W->number_of_wells,
                                W->well_connpos[ W->number_of_wells ]);

        if (newWells != NULL) {
            pos = W->well_connpos[ 0 ];
            ok  = 1;

            for (w = 0; ok && (w < W->number_of_wells); w++) {
                nperf = W->well_connpos[w + 1] - pos;
                cells = W->well_cells + pos;

                WI        = W->WI        != NULL ? W->WI        + pos  : NULL;
                comp_frac = W->comp_frac != NULL ? W->comp_frac + w*np : NULL;

                ok = add_well(W->type[ w ], W->depth_ref[ w ], nperf,
                              comp_frac, cells, WI, W->name[ w ], newWells);

                if (ok) {
                    ok = (ctrl = well_controls_clone(W->ctrls[w])) != NULL;
                }

                if (ok) {
                    /* Destroy control set implied by add_well() */
                    well_controls_destroy(newWells->ctrls[w]);

                    /* Assign complete clone of w's control set */
                    newWells->ctrls[w] = ctrl;
                }

                pos = W->well_connpos[w + 1];
            }

            if (! ok) {
                destroy_wells(newWells);
                newWells = NULL;
            }
        }
    }

    assert (wells_equal(newWells, W, false));

    return newWells;
}
Beispiel #3
0
void WellsManager::createWellsFromSpecs(std::vector<WellConstPtr>& wells, size_t timeStep,
                                        const C2F& c2f,
                                        const int* cart_dims,
                                        FC begin_face_centroids,
                                        int dimensions,
                                        std::vector<double>& dz,
                                        std::vector<std::string>& well_names,
                                        std::vector<WellData>& well_data,
                                        std::map<std::string, int>& well_names_to_index,
                                        const PhaseUsage& phaseUsage,
                                        const std::map<int,int>& cartesian_to_compressed,
                                        const double* permeability,
                                        const NTG& ntg,
                                        std::vector<int>& wells_on_proc)
{
    if (dimensions != 3) {
        OPM_THROW(std::domain_error,
                  "WellsManager::createWellsFromSpecs() only "
                  "supported in three space dimensions");
    }

    std::vector<std::vector<PerfData> > wellperf_data;
    wellperf_data.resize(wells.size());
    wells_on_proc.resize(wells.size(), 1);

    int well_index = 0;
    for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) {
        WellConstPtr well = (*wellIter);

        if (well->getStatus(timeStep) == WellCommon::SHUT) {
            continue;
        }

        {   // COMPDAT handling
            CompletionSetConstPtr completionSet = well->getCompletions(timeStep);
            // shut completions and open ones stored in this process will have 1 others 0.
            std::vector<std::size_t> completion_on_proc(completionSet->size(), 1);
            std::size_t shut_completions_number = 0;
            for (size_t c=0; c<completionSet->size(); c++) {
                CompletionConstPtr completion = completionSet->get(c);
                if (completion->getState() == WellCompletion::OPEN) {
                    int i = completion->getI();
                    int j = completion->getJ();
                    int k = completion->getK();

                    const int* cpgdim = cart_dims;
                    int cart_grid_indx = i + cpgdim[0]*(j + cpgdim[1]*k);
                    std::map<int, int>::const_iterator cgit = cartesian_to_compressed.find(cart_grid_indx);
                    if (cgit == cartesian_to_compressed.end()) {
                        if ( is_parallel_run_ )
                        {
                            completion_on_proc[c]=0;
                            continue;
                        }
                        else
                        {
                            OPM_MESSAGE("****Warning: Cell with i,j,k indices " << i << ' ' << j << ' '
                                      << k << " not found in grid. The completion will be igored (well = "
                                      << well->name() << ')');
                        }
                    }
                    else
                    {
                        int cell = cgit->second;
                        PerfData pd;
                        pd.cell = cell;
                        {
                            const Value<double>& transmissibilityFactor = completion->getConnectionTransmissibilityFactorAsValueObject();
                            const double wellPi = completion ->getWellPi();
                            if (transmissibilityFactor.hasValue()) {
                                pd.well_index = transmissibilityFactor.getValue();
                            } else {
                                double radius = 0.5*completion->getDiameter();
                                if (radius <= 0.0) {
                                    radius = 0.5*unit::feet;
                                    OPM_MESSAGE("**** Warning: Well bore internal radius set to " << radius);
                                }

                                std::array<double, 3> cubical =
                                    WellsManagerDetail::getCubeDim<3>(c2f, begin_face_centroids, cell);

                                // overwrite dz values calculated in getCubeDim.
                                if (dz.size() > 0) {
                                    cubical[2] = dz[cell];
                                }

                                const double* cell_perm = &permeability[dimensions*dimensions*cell];
                                pd.well_index =
                                    WellsManagerDetail::computeWellIndex(radius, cubical, cell_perm,
                                                                         completion->getSkinFactor(),
                                                                         completion->getDirection(),
                                                                         ntg[cell]);
                            }
                            pd.well_index *= wellPi;
                        }
                        wellperf_data[well_index].push_back(pd);
                    }
                } else {
                    ++shut_completions_number;
                    if (completion->getState() != WellCompletion::SHUT) {
                        OPM_THROW(std::runtime_error, "Completion state: " << WellCompletion::StateEnum2String( completion->getState() ) << " not handled");
                    }
                }
            }
            if ( is_parallel_run_ )
            {
                // sum_completions_on_proc includes completions
                // that are shut
                std::size_t sum_completions_on_proc = std::accumulate(completion_on_proc.begin(),
                                                                      completion_on_proc.end(),0);
                // Set wells that are not on this processor to SHUT.
                // A well is not here if only shut completions are found.
                if ( sum_completions_on_proc == shut_completions_number )
                {
                    // Mark well as not existent on this process
                    wells_on_proc[wellIter-wells.begin()] = 0;
                    continue;
                }
                else
                {
                    // Check that the complete well is on this process
                    if ( sum_completions_on_proc < completionSet->size() )
                    {
                        std::cout<< "Well "<< well->name() << " semms not be in "
                                 << "completely in the disjoint partition of "
                                 << "process deactivating here." << std::endl;
                        // Mark well as not existent on this process
                        wells_on_proc[wellIter-wells.begin()] = 0;
                        continue;
                    }
                }
            }
        }
        {   // WELSPECS handling
            well_names_to_index[well->name()] = well_index;
            well_names.push_back(well->name());
            {
                WellData wd;
                wd.reference_bhp_depth = well->getRefDepth();
                wd.welspecsline = -1;
                if (well->isInjector( timeStep ))
                    wd.type = INJECTOR;
                else
                    wd.type = PRODUCER;
                well_data.push_back(wd);
            }
        }

        well_index++;
    }
    // Set up reference depths that were defaulted. Count perfs.

    const int num_wells = well_data.size();

    int num_perfs = 0;
    assert (dimensions == 3);
    for (int w = 0; w < num_wells; ++w) {
        num_perfs += wellperf_data[w].size();
    }

    // Create the well data structures.
    w_ = create_wells(phaseUsage.num_phases, num_wells, num_perfs);
    if (!w_) {
        OPM_THROW(std::runtime_error, "Failed creating Wells struct.");
    }


    // Add wells.
    for (int w = 0; w < num_wells; ++w) {
        const int           w_num_perf = wellperf_data[w].size();
        std::vector<int>    perf_cells  (w_num_perf);
        std::vector<double> perf_prodind(w_num_perf);

        for (int perf = 0; perf < w_num_perf; ++perf) {
            perf_cells  [perf] = wellperf_data[w][perf].cell;
            perf_prodind[perf] = wellperf_data[w][perf].well_index;
        }

        const double* comp_frac = NULL;

        // We initialize all wells with a null component fraction,
        // and must (for injection wells) overwrite it later.
        const int ok =
            add_well(well_data[w].type,
                     well_data[w].reference_bhp_depth,
                     w_num_perf,
                     comp_frac,
                     perf_cells.data(),
                     perf_prodind.data(),
                     well_names[w].c_str(),
                     w_);

        if (!ok) {
            OPM_THROW(std::runtime_error,
                      "Failed adding well "
                      << well_names[w]
                      << " to Wells data structure.");
        }
    }
}