2016-01-05 12:32:36 -06:00
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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 < http : //www.gnu.org/licenses/>.
2016-03-14 07:21:47 -05:00
Consult the COPYING file in the top - level source directory of this
module for the precise wording of the license and the list of
copyright holders .
2016-01-05 12:32:36 -06:00
*/
/*!
* \ file
2024-02-02 03:46:44 -06:00
* \ copydoc Opm : : AluGridVanguard
2016-01-05 12:32:36 -06:00
*/
2024-02-02 03:46:44 -06:00
# ifndef OPM_ALUGRID_VANGUARD_HPP
# define OPM_ALUGRID_VANGUARD_HPP
2016-01-05 12:32:36 -06:00
2023-08-02 04:36:47 -05:00
# include <dune/alugrid/common/fromtogridfactory.hh>
# include <dune/alugrid/dgf.hh>
# include <dune/alugrid/grid.hh>
2022-11-15 04:25:54 -06:00
# include <opm/common/OpmLog/OpmLog.hpp>
2018-02-08 05:20:17 -06:00
# include <opm/grid/CpGrid.hpp>
2024-10-01 09:22:46 -05:00
# include <opm/grid/cpgrid/LevelCartesianIndexMapper.hpp>
2023-08-02 04:36:47 -05:00
# include <opm/models/common/multiphasebaseproperties.hh>
2024-02-02 03:46:44 -06:00
# include <opm/simulators/flow/AluGridCartesianIndexMapper.hpp>
2024-10-01 09:22:46 -05:00
# include <opm/simulators/flow/AluGridLevelCartesianIndexMapper.hpp>
2024-02-02 03:46:44 -06:00
# include <opm/simulators/flow/FlowBaseVanguard.hpp>
2024-02-02 03:46:44 -06:00
# include <opm/simulators/flow/Transmissibility.hpp>
2021-12-01 07:00:21 -06:00
# include <opm/simulators/utils/ParallelEclipseState.hpp>
2016-01-05 12:32:36 -06:00
2023-08-02 04:36:47 -05:00
# include <array>
2023-08-15 02:32:10 -05:00
# include <cstddef>
2023-08-02 04:36:47 -05:00
# include <memory>
# include <tuple>
# include <vector>
2019-09-05 10:04:39 -05:00
namespace Opm {
2016-01-05 12:32:36 -06:00
template < class TypeTag >
2024-02-02 03:46:44 -06:00
class FlowAluGridVanguard ;
2016-01-05 12:32:36 -06:00
2019-09-05 10:04:39 -05:00
} // namespace Opm
2018-06-14 09:06:05 -05:00
2020-08-21 06:42:08 -05:00
namespace Opm : : Properties {
2018-06-14 09:06:05 -05:00
2020-08-27 03:30:29 -05:00
namespace TTag {
2024-02-02 03:46:44 -06:00
struct AluGridVanguard {
2024-02-02 03:46:44 -06:00
using InheritsFrom = std : : tuple < FlowBaseVanguard > ;
2020-08-27 03:30:29 -05:00
} ;
}
2016-01-05 12:32:36 -06:00
// declare the properties
2020-08-27 04:38:38 -05:00
template < class TypeTag >
2024-02-02 03:46:44 -06:00
struct Vanguard < TypeTag , TTag : : AluGridVanguard > {
using type = Opm : : FlowAluGridVanguard < TypeTag > ;
2020-08-27 04:38:38 -05:00
} ;
template < class TypeTag >
2024-02-02 03:46:44 -06:00
struct Grid < TypeTag , TTag : : AluGridVanguard > {
2021-12-01 07:00:21 -06:00
# if HAVE_MPI
using type = Dune : : ALUGrid < 3 , 3 , Dune : : cube , Dune : : nonconforming , Dune : : ALUGridMPIComm > ;
# else
using type = Dune : : ALUGrid < 3 , 3 , Dune : : cube , Dune : : nonconforming , Dune : : ALUGridNoComm > ;
# endif //HAVE_MPI
2020-08-27 04:38:38 -05:00
} ;
template < class TypeTag >
2024-02-02 03:46:44 -06:00
struct EquilGrid < TypeTag , TTag : : AluGridVanguard > {
2020-08-27 04:38:38 -05:00
using type = Dune : : CpGrid ;
} ;
2018-06-14 09:06:05 -05:00
2020-08-21 06:42:08 -05:00
} // namespace Opm::Properties
2018-06-14 09:06:05 -05:00
2019-09-05 10:04:39 -05:00
namespace Opm {
2016-01-05 12:32:36 -06:00
/*!
2024-02-02 03:46:44 -06:00
* \ ingroup BlackOilSimulator
2016-01-05 12:32:36 -06:00
*
* \ brief Helper class for grid instantiation of ECL file - format using problems .
*
* This class uses Dune : : ALUGrid as the simulation grid .
*/
template < class TypeTag >
2024-02-02 03:46:44 -06:00
class AluGridVanguard : public FlowBaseVanguard < TypeTag >
2016-01-05 12:32:36 -06:00
{
2024-02-02 03:46:44 -06:00
friend class FlowBaseVanguard < TypeTag > ;
using ParentType = FlowBaseVanguard < TypeTag > ;
2016-01-05 12:32:36 -06:00
2021-12-01 07:00:21 -06:00
using ElementMapper = GetPropType < TypeTag , Properties : : ElementMapper > ;
2020-08-26 03:49:52 -05:00
using Scalar = GetPropType < TypeTag , Properties : : Scalar > ;
using Simulator = GetPropType < TypeTag , Properties : : Simulator > ;
2016-01-05 12:32:36 -06:00
public :
2020-08-26 03:49:52 -05:00
using Grid = GetPropType < TypeTag , Properties : : Grid > ;
using EquilGrid = GetPropType < TypeTag , Properties : : EquilGrid > ;
2021-12-01 07:00:21 -06:00
using GridView = GetPropType < TypeTag , Properties : : GridView > ;
2022-08-10 05:31:15 -05:00
using CartesianIndexMapper = Dune : : CartesianIndexMapper < Grid > ;
2024-10-01 09:22:46 -05:00
using LevelCartesianIndexMapper = Opm : : LevelCartesianIndexMapper < Grid > ;
2022-08-10 05:31:15 -05:00
using EquilCartesianIndexMapper = Dune : : CartesianIndexMapper < EquilGrid > ;
2024-02-02 03:46:44 -06:00
using TransmissibilityType = Transmissibility < Grid , GridView , ElementMapper , CartesianIndexMapper , Scalar > ;
2022-08-10 05:31:15 -05:00
using Factory = Dune : : FromToGridFactory < Grid > ;
2016-01-05 12:32:36 -06:00
2022-08-10 05:31:15 -05:00
static constexpr int dimension = Grid : : dimension ;
static constexpr int dimensionworld = Grid : : dimensionworld ;
2023-08-02 04:36:47 -05:00
2025-01-21 03:54:54 -06:00
explicit AluGridVanguard ( Simulator & simulator )
2024-02-02 03:46:44 -06:00
: FlowBaseVanguard < TypeTag > ( simulator )
2024-02-02 03:46:44 -06:00
{
this - > mpiRank = FlowGenericVanguard : : comm ( ) . rank ( ) ;
2021-12-01 07:00:21 -06:00
this - > callImplementationInit ( ) ;
2019-10-01 14:18:17 -05:00
}
2016-01-05 12:32:36 -06:00
/*!
* \ brief Return a reference to the simulation grid .
*/
Grid & grid ( )
{ return * grid_ ; }
/*!
* \ brief Return a reference to the simulation grid .
*/
const Grid & grid ( ) const
{ return * grid_ ; }
/*!
* \ brief Returns a refefence to the grid which should be used by the EQUIL
* initialization code .
*
* The EQUIL keyword is used to specify the initial condition of the reservoir in
* hydrostatic equilibrium . Since the code which does this is not accepting arbitrary
* DUNE grids ( the code is part of the opm - core module ) , this is not necessarily the
* same as the grid which is used for the actual simulation .
*/
const EquilGrid & equilGrid ( ) const
{ return * equilGrid_ ; }
/*!
* \ brief Indicates that the initial condition has been computed and the memory used
* by the EQUIL grid can be released .
*
* Depending on the implementation , subsequent accesses to the EQUIL grid lead to
* crashes .
*/
void releaseEquilGrid ( )
{
2016-01-17 14:15:18 -06:00
delete equilCartesianIndexMapper_ ;
2022-08-10 05:31:15 -05:00
equilCartesianIndexMapper_ = nullptr ;
2016-01-17 14:15:18 -06:00
2016-01-05 12:32:36 -06:00
delete equilGrid_ ;
2022-08-10 05:31:15 -05:00
equilGrid_ = nullptr ;
2016-01-05 12:32:36 -06:00
}
/*!
* \ brief Distribute the simulation grid over multiple processes
*
* ( For parallel simulation runs . )
*/
void loadBalance ( )
{
auto gridView = grid ( ) . leafGridView ( ) ;
auto dataHandle = cartesianIndexMapper_ - > dataHandle ( gridView ) ;
grid ( ) . loadBalance ( * dataHandle ) ;
// communicate non-interior cells values
grid ( ) . communicate ( * dataHandle ,
Dune : : InteriorBorder_All_Interface ,
Dune : : ForwardCommunication ) ;
2021-12-01 07:00:21 -06:00
if ( grid ( ) . size ( 0 ) )
{
2022-08-10 05:31:15 -05:00
globalTrans_ = std : : make_unique < TransmissibilityType > ( this - > eclState ( ) ,
this - > gridView ( ) ,
this - > cartesianIndexMapper ( ) ,
this - > grid ( ) ,
this - > cellCentroids ( ) ,
getPropValue < TypeTag ,
Properties : : EnableEnergy > ( ) ,
getPropValue < TypeTag ,
2023-10-25 12:46:55 -05:00
Properties : : EnableDiffusion > ( ) ,
getPropValue < TypeTag ,
Properties : : EnableDispersion > ( ) ) ;
2022-08-10 05:31:15 -05:00
// Re-ordering for ALUGrid
2024-06-06 08:15:56 -05:00
globalTrans_ - > update ( false , TransmissibilityType : : TransUpdateQuantities : : Trans ,
[ & ] ( unsigned int i ) { return gridEquilIdxToGridIdx ( i ) ; } ) ;
2021-12-01 07:00:21 -06:00
}
}
template < class DataHandle >
2023-05-31 02:33:01 -05:00
void scatterData ( DataHandle & /*handle*/ ) const
2021-12-01 07:00:21 -06:00
{
// not existing for this type of grid yet
}
template < class DataHandle >
2023-05-31 02:33:01 -05:00
void gatherData ( DataHandle & /*handle*/ ) const
2021-12-01 07:00:21 -06:00
{
// not existing for this type of grid yet
}
template < class DataHandle , class InterfaceType , class CommunicationDirection >
2023-05-31 02:33:01 -05:00
void communicate ( DataHandle & /*data*/ , InterfaceType /*iftype*/ ,
CommunicationDirection /*dir*/ ) const
2021-12-01 07:00:21 -06:00
{
// not existing for this type of grid yet
}
/*!
* \ brief Free the memory occupied by the global transmissibility object .
*
* After writing the initial solution , this array should not be necessary anymore .
*/
void releaseGlobalTransmissibilities ( )
{
globalTrans_ . reset ( ) ;
2016-01-05 12:32:36 -06:00
}
/*!
* \ brief Returns the object which maps a global element index of the simulation grid
* to the corresponding element index of the logically Cartesian index .
*/
const CartesianIndexMapper & cartesianIndexMapper ( ) const
{ return * cartesianIndexMapper_ ; }
2024-10-01 09:22:46 -05:00
/*!
* \ brief Returns the object which maps a global element index of the simulation grid
* to the corresponding element index of the level logically Cartesian index .
2024-11-06 02:36:40 -06:00
* No refinement is supported for AluGrid so it coincides with CartesianIndexMapper .
2024-10-01 09:22:46 -05:00
*/
const LevelCartesianIndexMapper levelCartesianIndexMapper ( ) const
2024-11-06 02:36:40 -06:00
{ return LevelCartesianIndexMapper ( * cartesianIndexMapper_ ) ; }
2024-10-01 09:22:46 -05:00
2016-01-17 14:15:18 -06:00
/*!
* \ brief Returns mapper from compressed to cartesian indices for the EQUIL grid
*/
const EquilCartesianIndexMapper & equilCartesianIndexMapper ( ) const
{ return * equilCartesianIndexMapper_ ; }
2021-09-30 04:50:22 -05:00
/*!
* \ brief Get function to query cell centroids for a distributed grid .
*
* Currently this only non - empty for a loadbalanced CpGrid .
* It is a function return the centroid for the given element
* index .
*/
std : : function < std : : array < double , dimensionworld > ( int ) >
cellCentroids ( ) const
{
2023-09-28 04:12:44 -05:00
return this - > cellCentroids_ ( this - > cartesianIndexMapper ( ) , false ) ;
2021-12-01 07:00:21 -06:00
}
const TransmissibilityType & globalTransmissibility ( ) const
{
assert ( globalTrans_ ! = nullptr ) ;
return * globalTrans_ ;
2021-09-30 04:50:22 -05:00
}
2021-12-01 07:00:21 -06:00
const std : : vector < int > & globalCell ( )
{
return cartesianCellId_ ;
}
std : : vector < int > cellPartition ( ) const
{
// not required for this type of grid yet
return { } ;
}
unsigned int gridEquilIdxToGridIdx ( unsigned int elemIndex ) const {
return equilGridToGrid_ [ elemIndex ] ;
}
unsigned int gridIdxToEquilGridIdx ( unsigned int elemIndex ) const {
return ordering_ [ elemIndex ] ;
}
2016-01-05 12:32:36 -06:00
protected :
void createGrids_ ( )
{
// we use separate grid objects: one for the calculation of the initial condition
// via EQUIL and one for the actual simulation. The reason is that the EQUIL code
// cannot cope with arbitrary Dune grids and is also allergic to distributed
// grids.
/////
// create the EQUIL grid
/////
2021-12-01 07:00:21 -06:00
const EclipseGrid * input_grid = nullptr ;
std : : vector < double > global_porv ;
// At this stage the ParallelEclipseState instance is still in global
// view; on rank 0 we have undistributed data for the entire grid, on
// the other ranks the EclipseState is empty.
if ( mpiRank = = 0 ) {
2022-11-15 04:25:54 -06:00
// Processing grid
input_grid = & this - > eclState ( ) . getInputGrid ( ) ;
global_porv = this - > eclState ( ) . fieldProps ( ) . porv ( true ) ;
OpmLog : : info ( " \n Processing grid " ) ;
}
2021-12-01 07:00:21 -06:00
2022-11-15 04:25:54 -06:00
# if HAVE_MPI
2024-02-02 03:46:44 -06:00
this - > equilGrid_ = std : : make_unique < Dune : : CpGrid > ( FlowGenericVanguard : : comm ( ) ) ;
2022-11-15 04:25:54 -06:00
# else
this - > equilGrid_ = std : : make_unique < Dune : : CpGrid > ( ) ;
# endif
2022-08-10 05:31:15 -05:00
// Note: removed_cells is guaranteed to be empty on ranks other than 0.
2021-12-01 07:00:21 -06:00
auto removed_cells =
this - > equilGrid_ - > processEclipseFormat ( input_grid ,
& this - > eclState ( ) ,
/*isPeriodic=*/ false ,
/*flipNormals=*/ false ,
/*clipZ=*/ false ) ;
cartesianCellId_ = this - > equilGrid_ - > globalCell ( ) ;
2016-01-05 12:32:36 -06:00
for ( unsigned i = 0 ; i < dimension ; + + i )
2021-12-01 07:00:21 -06:00
cartesianDimension_ [ i ] = this - > equilGrid_ - > logicalCartesianSize ( ) [ i ] ;
2016-01-05 12:32:36 -06:00
2021-12-01 07:00:21 -06:00
equilCartesianIndexMapper_ = std : : make_unique < EquilCartesianIndexMapper > ( * equilGrid_ ) ;
2016-01-17 14:15:18 -06:00
/////
// create the simulation grid
/////
2016-01-05 12:32:36 -06:00
2021-12-01 07:00:21 -06:00
factory_ = std : : make_unique < Factory > ( ) ;
grid_ = factory_ - > convert ( * equilGrid_ , cartesianCellId_ , ordering_ ) ;
2024-09-26 03:27:13 -05:00
OpmLog : : warning ( " Space Filling Curve (SFC) ordering is enabled: see flow_blackoil_alugrid for more informations on disabling/enabling SFC reordering " ) ;
2021-12-01 07:00:21 -06:00
equilGridToGrid_ . resize ( ordering_ . size ( ) ) ;
2023-08-15 02:32:10 -05:00
for ( std : : size_t index = 0 ; index < ordering_ . size ( ) ; + + index ) {
2021-12-01 07:00:21 -06:00
equilGridToGrid_ [ ordering_ [ index ] ] = index ;
}
cartesianIndexMapper_ = std : : make_unique < CartesianIndexMapper > ( * grid_ , cartesianDimension_ , cartesianCellId_ ) ;
this - > updateGridView_ ( ) ;
this - > updateCartesianToCompressedMapping_ ( ) ;
this - > updateCellDepths_ ( ) ;
this - > updateCellThickness_ ( ) ;
2016-01-05 12:32:36 -06:00
}
2018-06-28 08:49:45 -05:00
void filterConnections_ ( )
2018-02-07 04:21:57 -06:00
{
// not handling the removal of completions for this type of grid yet.
}
2021-12-01 07:00:21 -06:00
std : : unique_ptr < Grid > grid_ ;
std : : unique_ptr < EquilGrid > equilGrid_ ;
2016-01-05 12:32:36 -06:00
std : : vector < int > cartesianCellId_ ;
2021-12-01 07:00:21 -06:00
std : : vector < unsigned int > ordering_ ;
std : : vector < unsigned int > equilGridToGrid_ ;
2016-01-05 12:32:36 -06:00
std : : array < int , dimension > cartesianDimension_ ;
2021-09-30 04:50:22 -05:00
std : : unique_ptr < CartesianIndexMapper > cartesianIndexMapper_ ;
2021-12-01 07:00:21 -06:00
std : : unique_ptr < EquilCartesianIndexMapper > equilCartesianIndexMapper_ ;
std : : unique_ptr < Factory > factory_ ;
2024-06-04 04:25:24 -05:00
// \Note: this globalTrans_ is used for domain decomposition and INIT file output.
// It only contains trans_ due to permeability and does not contain thermalHalfTrans_,
// diffusivity_ abd dispersivity_. The main reason is to reduce the memory usage for rank 0
// during parallel running.
2021-12-01 07:00:21 -06:00
std : : unique_ptr < TransmissibilityType > globalTrans_ ;
int mpiRank ;
2016-01-05 12:32:36 -06:00
} ;
2019-09-05 10:04:39 -05:00
} // namespace Opm
2016-01-05 12:32:36 -06:00
2024-02-02 03:46:44 -06:00
# endif // OPM_ALUGRID_VANGUARD_HPP