Ejemplo n.º 1
0
void WellConnections::init(const Opm::EclipseStateConstPtr eclipseState,
                           const std::array<int, 3>& cartesianSize,
                           const std::vector<int>& cartesian_to_compressed)
{
    std::vector<const Opm::Well*>  wells  = eclipseState->getSchedule()->getWells();
    int last_time_step = eclipseState->getSchedule()->getTimeMap()->size()-1;
    well_indices_.resize(wells.size());

    // We assume that we know all the wells.
    int index=0;
    for (const auto well : wells) {
        std::set<int>& well_indices = well_indices_[index];
        Opm::CompletionSetConstPtr completionSet = well->getCompletions(last_time_step);
        for (size_t c=0; c<completionSet->size(); c++) {
            Opm::CompletionConstPtr completion = completionSet->get(c);
            int i = completion->getI();
            int j = completion->getJ();
            int k = completion->getK();
            int cart_grid_idx = i + cartesianSize[0]*(j + cartesianSize[1]*k);
            int compressed_idx = cartesian_to_compressed[cart_grid_idx];
            if ( compressed_idx >= 0 ) // Ignore completions in inactive cells.
            {
                well_indices.insert(compressed_idx);
            }
        }
        ++index;
    }
}
Ejemplo n.º 2
0
    void
    PolymerInflowFromDeck::setInflowValues(Opm::DeckConstPtr deck,
                                           Opm::EclipseStateConstPtr eclipseState,
                                           size_t currentStep)
    {
        Opm::DeckKeywordConstPtr keyword = deck->getKeyword("WPOLYMER");
        
        //        Schedule schedule(deck);
        ScheduleConstPtr schedule = eclipseState->getSchedule();
        for (size_t recordNr = 0; recordNr < keyword->size(); recordNr++) {
            DeckRecordConstPtr record = keyword->getRecord(recordNr);

            const std::string& wellNamesPattern = record->getItem("WELL")->getTrimmedString(0);
            std::string wellName = record->getItem("WELL")->getTrimmedString(0);
            std::vector<WellPtr> wells = schedule->getWells(wellNamesPattern);
            for (auto wellIter = wells.begin(); wellIter != wells.end(); ++wellIter) {
                WellPtr well = *wellIter;
                WellInjectionProperties injection = well->getInjectionProperties(currentStep);
                if (injection.injectorType == WellInjector::WATER) {
                    WellPolymerProperties polymer = well->getPolymerProperties(currentStep);
                    wellPolymerRate_.insert(std::make_pair(wellName, polymer.m_polymerConcentration));
                } else {
                    OPM_THROW(std::logic_error, "For polymer injector you must have a water injector");
                }
            }
        }
    }
Ejemplo n.º 3
0
std::unordered_set<std::string>
computeDefunctWellNames(const std::vector<std::vector<int> >& wells_on_proc,
                        const Opm::EclipseStateConstPtr eclipseState,
                        const CollectiveCommunication<MPI_Comm>& cc,
                        int root)
{
    std::vector<const Opm::Well*>  wells  = eclipseState->getSchedule()->getWells();
    std::vector<int> my_well_indices;
    const int well_information_tag = 267553;

    if( root == cc.rank() )
    {
        std::vector<MPI_Request> reqs(cc.size(), MPI_REQUEST_NULL);
        my_well_indices = wells_on_proc[root];
        for ( int i=0; i < cc.size(); ++i )
        {
            if(i==root)
            {
                continue;
            }
            MPI_Isend(const_cast<int*>(wells_on_proc[i].data()),
                      wells_on_proc[i].size(),
                      MPI_INT, i, well_information_tag, cc, &reqs[i]);
        }
        std::vector<MPI_Status> stats(reqs.size());
        MPI_Waitall(reqs.size(), reqs.data(), stats.data());
    }
    else
    {
        MPI_Status stat;
        MPI_Probe(root, well_information_tag, cc, &stat);
        int msg_size;
        MPI_Get_count(&stat, MPI_INT, &msg_size);
        my_well_indices.resize(msg_size);
        MPI_Recv(my_well_indices.data(), msg_size, MPI_INT, root,
                 well_information_tag, cc, &stat);
    }

    // Compute defunct wells in parallel run.
    std::vector<int> defunct_wells(wells.size(), true);

    for(auto well_index : my_well_indices)
    {
        defunct_wells[well_index] = false;
    }

    // We need to use well names as only they are consistent.
    std::unordered_set<std::string> defunct_well_names;

    for(auto defunct = defunct_wells.begin(); defunct != defunct_wells.end(); ++defunct)
    {
        if ( *defunct )
        {
            defunct_well_names.insert(wells[defunct-defunct_wells.begin()]->name());
        }
    }

    return defunct_well_names;
}
Ejemplo n.º 4
0
CombinedGridWellGraph::CombinedGridWellGraph(const CpGrid& grid,
                                             const Opm::EclipseStateConstPtr eclipseState,
                                             const double* transmissibilities,
                                             bool pretendEmptyGrid)
    : grid_(grid), eclipseState_(eclipseState), transmissibilities_(transmissibilities)
{
    if ( pretendEmptyGrid )
    {
        // wellsGraph not needed
        return;
    }
    wellsGraph_.resize(grid.numCells());
    const auto& cpgdim = grid.logicalCartesianSize();
    // create compressed lookup from cartesian.
    std::vector<Opm::WellConstPtr> wells  = eclipseState->getSchedule()->getWells();
    std::vector<int> cartesian_to_compressed(cpgdim[0]*cpgdim[1]*cpgdim[2], -1);
    int last_time_step = eclipseState->getSchedule()->getTimeMap()->size()-1;
    for( int i=0; i < grid.numCells(); ++i )
    {
        cartesian_to_compressed[grid.globalCell()[i]] = i;
    }
    // We assume that we know all the wells.
    for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) {
        Opm::WellConstPtr well = (*wellIter);
        std::set<int> well_indices;
        Opm::CompletionSetConstPtr completionSet = well->getCompletions(last_time_step);
        for (size_t c=0; c<completionSet->size(); c++) {
            Opm::CompletionConstPtr completion = completionSet->get(c);
            int i = completion->getI();
            int j = completion->getJ();
            int k = completion->getK();
            int cart_grid_idx = i + cpgdim[0]*(j + cpgdim[1]*k);
            int compressed_idx = cartesian_to_compressed[cart_grid_idx];
            if ( compressed_idx >= 0 ) // Ignore completions in inactive cells.
            {
                well_indices.insert(compressed_idx);
            }
        }
        addCompletionSetToGraph(well_indices);
    }
}
Ejemplo n.º 5
0
void
WellsManager::init(const Opm::EclipseStateConstPtr eclipseState,
                   const size_t                    timeStep,
                   int                             number_of_cells,
                   const int*                      global_cell,
                   const int*                      cart_dims,
                   int                             dimensions,
                   const C2F&                      cell_to_faces,
                   FC                              begin_face_centroids,
                   const double*                   permeability)
{
    if (dimensions != 3) {
        OPM_THROW(std::runtime_error,
                  "We cannot initialize wells from a deck unless "
                  "the corresponding grid is 3-dimensional.");
    }

    if (eclipseState->getSchedule()->numWells() == 0) {
        OPM_MESSAGE("No wells specified in Schedule section, "
                    "initializing no wells");
        return;
    }

    std::map<int,int> cartesian_to_compressed;
    setupCompressedToCartesian(global_cell, number_of_cells,
                               cartesian_to_compressed);

    // Obtain phase usage data.
    PhaseUsage pu = phaseUsageFromDeck(eclipseState);

    // These data structures will be filled in this constructor,
    // then used to initialize the Wells struct.
    std::vector<std::string> well_names;
    std::vector<WellData> well_data;


    // For easy lookup:
    std::map<std::string, int> well_names_to_index;

    ScheduleConstPtr          schedule = eclipseState->getSchedule();
    std::vector<WellConstPtr> wells    = schedule->getWells(timeStep);
    std::vector<int>          wells_on_proc;

    well_names.reserve(wells.size());
    well_data.reserve(wells.size());

    typedef GridPropertyAccess::ArrayPolicy::ExtractFromDeck<double> DoubleArray;
    typedef GridPropertyAccess::Compressed<DoubleArray, GridPropertyAccess::Tag::NTG> NTGArray;

    DoubleArray ntg_glob(eclipseState, "NTG", 1.0);
    NTGArray    ntg(ntg_glob, global_cell);

    EclipseGridConstPtr eclGrid = eclipseState->getEclipseGrid();

    // use cell thickness (dz) from eclGrid
    // dz overwrites values calculated by WellDetails::getCubeDim
    std::vector<double> dz(number_of_cells);
    {
        std::vector<int> gc = compressedToCartesian(number_of_cells, global_cell);
        for (int cell = 0; cell < number_of_cells; ++cell) {
            dz[cell] = eclGrid->getCellThicknes(gc[cell]);
        }
    }

    createWellsFromSpecs(wells, timeStep, cell_to_faces,
                         cart_dims,
                         begin_face_centroids,
                         dimensions,
                         dz,
                         well_names, well_data, well_names_to_index,
                         pu, cartesian_to_compressed, permeability, ntg,
                         wells_on_proc);

    setupWellControls(wells, timeStep, well_names, pu, wells_on_proc);

    {
        GroupTreeNodeConstPtr fieldNode =
            schedule->getGroupTree(timeStep)->getNode("FIELD");

        GroupConstPtr fieldGroup =
            schedule->getGroup(fieldNode->name());

        well_collection_.addField(fieldGroup, timeStep, pu);
        addChildGroups(fieldNode, schedule, timeStep, pu);
    }

    for (auto w = wells.begin(), e = wells.end(); w != e; ++w) {
        well_collection_.addWell(*w, timeStep, pu);
    }

    well_collection_.setWellsPointer(w_);
    well_collection_.applyGroupControls();

    setupGuideRates(wells, timeStep, well_data, well_names_to_index);

    // Debug output.
#define EXTRA_OUTPUT
#ifdef EXTRA_OUTPUT
    /*
      std::cout << "\t WELL DATA" << std::endl;
      for(int i = 0; i< num_wells; ++i) {
      std::cout << i << ": " << well_data[i].type << "  "
      << well_data[i].control << "  " << well_data[i].target
      << std::endl;
      }

      std::cout << "\n\t PERF DATA" << std::endl;
      for(int i=0; i< int(wellperf_data.size()); ++i) {
      for(int j=0; j< int(wellperf_data[i].size()); ++j) {
      std::cout << i << ": " << wellperf_data[i][j].cell << "  "
      << wellperf_data[i][j].well_index << std::endl;
      }
      }
    */
#endif
}
    void SimulatorFullyImplicitBlackoilPolymer<GridT>::
    computeRepRadiusPerfLength(const Opm::EclipseStateConstPtr eclipseState,
                               const size_t                    timeStep,
                               const GridT&                    grid,
                               std::vector<double>&            wells_rep_radius,
                               std::vector<double>&            wells_perf_length,
                               std::vector<double>&            wells_bore_diameter)
    {

        // TODO, the function does not work for parallel running
        // to be fixed later.
        int number_of_cells = Opm::UgGridHelpers::numCells(grid);
        const int* global_cell = Opm::UgGridHelpers::globalCell(grid);
        const int* cart_dims = Opm::UgGridHelpers::cartDims(grid);
        auto cell_to_faces = Opm::UgGridHelpers::cell2Faces(grid);
        auto begin_face_centroids = Opm::UgGridHelpers::beginFaceCentroids(grid);

        if (eclipseState->getSchedule()->numWells() == 0) {
            OPM_MESSAGE("No wells specified in Schedule section, "
                        "initializing no wells");
            return;
        }

        const size_t n_perf = wells_rep_radius.size();

        wells_rep_radius.clear();
        wells_perf_length.clear();
        wells_bore_diameter.clear();

        wells_rep_radius.reserve(n_perf);
        wells_perf_length.reserve(n_perf);
        wells_bore_diameter.reserve(n_perf);

        std::map<int,int> cartesian_to_compressed;

        setupCompressedToCartesian(global_cell, number_of_cells,
                                   cartesian_to_compressed);

        ScheduleConstPtr          schedule = eclipseState->getSchedule();
        std::vector<WellConstPtr> wells    = schedule->getWells(timeStep);

        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);
                 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()) {
                             OPM_THROW(std::runtime_error, "Cell with i,j,k indices " << i << ' ' << j << ' '
                                       << k << " not found in grid (well = " << well->name() << ')');
                         }
                         int cell = cgit->second;

                         {
                             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);
                             }

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

                             WellCompletion::DirectionEnum direction = completion->getDirection();

                             double re; // area equivalent radius of the grid block
                             double perf_length; // the length of the well perforation

                             switch (direction) {
                                 case Opm::WellCompletion::DirectionEnum::X:
                                     re = std::sqrt(cubical[1] * cubical[2] / M_PI);
                                     perf_length = cubical[0];
                                     break;
                                 case Opm::WellCompletion::DirectionEnum::Y:
                                     re = std::sqrt(cubical[0] * cubical[2] / M_PI);
                                     perf_length = cubical[1];
                                     break;
                                 case Opm::WellCompletion::DirectionEnum::Z:
                                     re = std::sqrt(cubical[0] * cubical[1] / M_PI);
                                     perf_length = cubical[2];
                                     break;
                                 default:
                                     OPM_THROW(std::runtime_error, " Dirtecion of well is not supported ");
                             }

                             double repR = std::sqrt(re * radius);
                             wells_rep_radius.push_back(repR);
                             wells_perf_length.push_back(perf_length);
                             wells_bore_diameter.push_back(2. * radius);
                         }
                     } else {
                         if (completion->getState() != WellCompletion::SHUT) {
                             OPM_THROW(std::runtime_error, "Completion state: " << WellCompletion::StateEnum2String( completion->getState() ) << " not handled");
                         }
                     }

                 }
            }
            well_index++;
        }
    }
Ejemplo n.º 7
0
std::vector<std::vector<int> >
postProcessPartitioningForWells(std::vector<int>& parts,
                                const Opm::EclipseStateConstPtr eclipseState,
                                const WellConnections& well_connections,
                                std::size_t no_procs)
{
    std::vector<const Opm::Well*>  wells  = eclipseState->getSchedule()->getWells();
    // Contains for each process the indices of the wells assigned to it.
    std::vector<std::vector<int> > well_indices_on_proc(no_procs);

    if( ! well_connections.size() )
    {
        // No wells to be processed
        return well_indices_on_proc;
    }

    // prevent memory allocation
    for(auto& well_indices : well_indices_on_proc)
    {
        well_indices.reserve(wells.size());
    }

    // Check that all completions of a well have ended up on one process.
    // If that is not the case for well then move them manually to the
    // process that already has the most completions on it.
    int well_index = 0;

    for (const auto* well: wells) {
        const auto& well_completions = well_connections[well_index];
        std::map<int,std::size_t> no_completions_on_proc;
        for ( auto completion_index: well_completions )
        {
            ++no_completions_on_proc[parts[completion_index]];
        }

        int owner = no_completions_on_proc.begin()->first;

        if ( no_completions_on_proc.size() > 1 )
        {
            // partition with the most completions on it becomes new owner
            int new_owner = std::max_element(no_completions_on_proc.begin(),
                                             no_completions_on_proc.end(),
                                             [](const std::pair<int,std::size_t>& p1,
                                                const std::pair<int,std::size_t>& p2){
                                                 return ( p1.second > p2.second );
                                             })->first;
            std::cout << "Manually moving well " << well->name() << " to partition "
                      << new_owner << std::endl;

            for ( auto completion_cell : well_completions )
            {
                parts[completion_cell] = new_owner;
            }

            owner = new_owner;
        }

        well_indices_on_proc[owner].push_back(well_index);
        ++well_index;
    }
    return well_indices_on_proc;

}