Merge pull request #2128 from bska/wpi-smry-output
Support Outputting Preferred Phase PI to Summary File
This commit is contained in:
commit
a3df631aab
@ -48,6 +48,7 @@ struct SummaryNode {
|
|||||||
Pressure,
|
Pressure,
|
||||||
Count,
|
Count,
|
||||||
Mode,
|
Mode,
|
||||||
|
ProdIndex,
|
||||||
Undefined,
|
Undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -958,6 +958,74 @@ inline quantity potential_rate( const fn_args& args ) {
|
|||||||
return { sum, rate_unit< phase >() };
|
return { sum, rate_unit< phase >() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline quantity preferred_phase_productivty_index(const fn_args& args) {
|
||||||
|
if (args.schedule_wells.empty())
|
||||||
|
return potential_rate<rt::productivity_index_oil>(args);
|
||||||
|
|
||||||
|
switch (args.schedule_wells.front().getPreferredPhase()) {
|
||||||
|
case Opm::Phase::OIL:
|
||||||
|
return potential_rate<rt::productivity_index_oil>(args);
|
||||||
|
|
||||||
|
case Opm::Phase::GAS:
|
||||||
|
return potential_rate<rt::productivity_index_gas>(args);
|
||||||
|
|
||||||
|
case Opm::Phase::WATER:
|
||||||
|
return potential_rate<rt::productivity_index_water>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::invalid_argument {
|
||||||
|
"Unsupported \"preferred\" phase: " +
|
||||||
|
std::to_string(static_cast<int>(args.schedule_wells.front().getPreferredPhase()))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline quantity connection_productivity_index(const fn_args& args) {
|
||||||
|
const quantity zero = { 0.0, rate_unit<rt::productivity_index_oil>() };
|
||||||
|
|
||||||
|
if (args.schedule_wells.empty())
|
||||||
|
return zero;
|
||||||
|
|
||||||
|
auto xwPos = args.wells.find(args.schedule_wells.front().name());
|
||||||
|
if (xwPos == args.wells.end())
|
||||||
|
return zero;
|
||||||
|
|
||||||
|
// The args.num value is the literal value which will go to the
|
||||||
|
// NUMS array in the eclipse SMSPEC file; the values in this array
|
||||||
|
// are offset 1 - whereas we need to use this index here to look
|
||||||
|
// up a completion with offset 0.
|
||||||
|
const auto global_index = static_cast<std::size_t>(args.num) - 1;
|
||||||
|
|
||||||
|
const auto& xcon = xwPos->second.connections;
|
||||||
|
const auto& completion =
|
||||||
|
std::find_if(xcon.begin(), xcon.end(),
|
||||||
|
[global_index](const Opm::data::Connection& c)
|
||||||
|
{
|
||||||
|
return c.index == global_index;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (completion == xcon.end())
|
||||||
|
return zero;
|
||||||
|
|
||||||
|
switch (args.schedule_wells.front().getPreferredPhase()) {
|
||||||
|
case Opm::Phase::OIL:
|
||||||
|
return { completion->rates.get(rt::productivity_index_oil, 0.0),
|
||||||
|
rate_unit<rt::productivity_index_oil>() };
|
||||||
|
|
||||||
|
case Opm::Phase::GAS:
|
||||||
|
return { completion->rates.get(rt::productivity_index_gas, 0.0),
|
||||||
|
rate_unit<rt::productivity_index_gas>() };
|
||||||
|
|
||||||
|
case Opm::Phase::WATER:
|
||||||
|
return { completion->rates.get(rt::productivity_index_water, 0.0),
|
||||||
|
rate_unit<rt::productivity_index_water>() };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::invalid_argument {
|
||||||
|
"Unsupported \"preferred\" phase: " +
|
||||||
|
std::to_string(static_cast<int>(args.schedule_wells.front().getPreferredPhase()))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
template < bool isGroup, bool Producer, bool waterInjector, bool gasInjector>
|
template < bool isGroup, bool Producer, bool waterInjector, bool gasInjector>
|
||||||
inline quantity group_control( const fn_args& args ) {
|
inline quantity group_control( const fn_args& args ) {
|
||||||
|
|
||||||
@ -1444,6 +1512,7 @@ static const std::unordered_map< std::string, ofun > funs = {
|
|||||||
{ "CSIT", mul( crate< rt::brine, injector >, duration ) },
|
{ "CSIT", mul( crate< rt::brine, injector >, duration ) },
|
||||||
{ "CSPT", mul( crate< rt::brine, producer >, duration ) },
|
{ "CSPT", mul( crate< rt::brine, producer >, duration ) },
|
||||||
{ "CTFAC", trans_factors },
|
{ "CTFAC", trans_factors },
|
||||||
|
{ "CPI", connection_productivity_index },
|
||||||
|
|
||||||
{ "FWPR", rate< rt::wat, producer > },
|
{ "FWPR", rate< rt::wat, producer > },
|
||||||
{ "FOPR", rate< rt::oil, producer > },
|
{ "FOPR", rate< rt::oil, producer > },
|
||||||
@ -1587,10 +1656,12 @@ static const std::unordered_map< std::string, ofun > funs = {
|
|||||||
{ "SPRDF", segpress<Opm::data::SegmentPressures::Value::PDropFriction> },
|
{ "SPRDF", segpress<Opm::data::SegmentPressures::Value::PDropFriction> },
|
||||||
{ "SPRDA", segpress<Opm::data::SegmentPressures::Value::PDropAccel> },
|
{ "SPRDA", segpress<Opm::data::SegmentPressures::Value::PDropAccel> },
|
||||||
// Well productivity index
|
// Well productivity index
|
||||||
|
{ "WPI", preferred_phase_productivty_index },
|
||||||
{ "WPIW", potential_rate< rt::productivity_index_water >},
|
{ "WPIW", potential_rate< rt::productivity_index_water >},
|
||||||
{ "WPIO", potential_rate< rt::productivity_index_oil >},
|
{ "WPIO", potential_rate< rt::productivity_index_oil >},
|
||||||
{ "WPIG", potential_rate< rt::productivity_index_gas >},
|
{ "WPIG", potential_rate< rt::productivity_index_gas >},
|
||||||
{ "WPIL", sum( potential_rate< rt::productivity_index_water >, potential_rate< rt::productivity_index_oil>)},
|
{ "WPIL", sum( potential_rate< rt::productivity_index_water, true, false >,
|
||||||
|
potential_rate< rt::productivity_index_oil, true, false >)},
|
||||||
// Well potential
|
// Well potential
|
||||||
{ "WWPP", potential_rate< rt::well_potential_water , true, false>},
|
{ "WWPP", potential_rate< rt::well_potential_water , true, false>},
|
||||||
{ "WOPP", potential_rate< rt::well_potential_oil , true, false>},
|
{ "WOPP", potential_rate< rt::well_potential_oil , true, false>},
|
||||||
|
@ -255,6 +255,17 @@ namespace {
|
|||||||
|| is_in_set(countkw, keyword.substr(1));
|
|| is_in_set(countkw, keyword.substr(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_prod_index(const std::string& keyword) {
|
||||||
|
static const keyword_set countkw {
|
||||||
|
"PI", "PI1", "PI4", "PI5", "PI9",
|
||||||
|
"PIO", "PIG", "PIW", "PIL",
|
||||||
|
};
|
||||||
|
|
||||||
|
return !keyword.empty()
|
||||||
|
&& ((keyword[0] == 'W') || (keyword[0] == 'C'))
|
||||||
|
&& is_in_set(countkw, keyword.substr(1));
|
||||||
|
}
|
||||||
|
|
||||||
bool is_liquid_phase(const std::string& keyword) {
|
bool is_liquid_phase(const std::string& keyword) {
|
||||||
return keyword == "WPIL";
|
return keyword == "WPIL";
|
||||||
}
|
}
|
||||||
@ -1125,6 +1136,7 @@ SummaryConfigNode::Type parseKeywordType(std::string keyword) {
|
|||||||
if (is_pressure(keyword)) return SummaryConfigNode::Type::Pressure;
|
if (is_pressure(keyword)) return SummaryConfigNode::Type::Pressure;
|
||||||
if (is_count(keyword)) return SummaryConfigNode::Type::Count;
|
if (is_count(keyword)) return SummaryConfigNode::Type::Count;
|
||||||
if (is_control_mode(keyword)) return SummaryConfigNode::Type::Mode;
|
if (is_control_mode(keyword)) return SummaryConfigNode::Type::Mode;
|
||||||
|
if (is_prod_index(keyword)) return SummaryConfigNode::Type::ProdIndex;
|
||||||
|
|
||||||
return SummaryConfigNode::Type::Undefined;
|
return SummaryConfigNode::Type::Undefined;
|
||||||
}
|
}
|
||||||
|
@ -621,6 +621,14 @@ WTHPH
|
|||||||
/
|
/
|
||||||
WPI
|
WPI
|
||||||
/
|
/
|
||||||
|
WPIO
|
||||||
|
/
|
||||||
|
WPIG
|
||||||
|
/
|
||||||
|
WPIW
|
||||||
|
/
|
||||||
|
WPIL
|
||||||
|
/
|
||||||
WBP
|
WBP
|
||||||
/
|
/
|
||||||
WBP4
|
WBP4
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||||
|
|
||||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||||
|
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
#include <opm/io/eclipse/ESmry.hpp>
|
#include <opm/io/eclipse/ESmry.hpp>
|
||||||
|
|
||||||
@ -92,6 +93,15 @@ namespace {
|
|||||||
*/
|
*/
|
||||||
static const int day = 24 * 60 * 60;
|
static const int day = 24 * 60 * 60;
|
||||||
|
|
||||||
|
double liquid_PI_unit()
|
||||||
|
{
|
||||||
|
return UnitSystem::newMETRIC().to_si(UnitSystem::measure::liquid_productivity_index, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double gas_PI_unit()
|
||||||
|
{
|
||||||
|
return UnitSystem::newMETRIC().to_si(UnitSystem::measure::gas_productivity_index, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is quite misleading, because the values prepared in the test
|
This is quite misleading, because the values prepared in the test
|
||||||
@ -125,9 +135,9 @@ data::Wells result_wells(const bool w3_injector = true)
|
|||||||
rates1.set( rt::reservoir_water, -10.6 / day );
|
rates1.set( rt::reservoir_water, -10.6 / day );
|
||||||
rates1.set( rt::reservoir_oil, -10.7 / day );
|
rates1.set( rt::reservoir_oil, -10.7 / day );
|
||||||
rates1.set( rt::reservoir_gas, -10.8 / day );
|
rates1.set( rt::reservoir_gas, -10.8 / day );
|
||||||
rates1.set( rt::productivity_index_water, -10.9 / day );
|
rates1.set( rt::productivity_index_water, 10.9*liquid_PI_unit());
|
||||||
rates1.set( rt::productivity_index_oil, -10.11 / day );
|
rates1.set( rt::productivity_index_oil, 10.11*liquid_PI_unit());
|
||||||
rates1.set( rt::productivity_index_gas, -10.12 / day );
|
rates1.set( rt::productivity_index_gas, 10.12*gas_PI_unit());
|
||||||
rates1.set( rt::well_potential_water, -10.13 / day );
|
rates1.set( rt::well_potential_water, -10.13 / day );
|
||||||
rates1.set( rt::well_potential_oil, -10.14 / day );
|
rates1.set( rt::well_potential_oil, -10.14 / day );
|
||||||
rates1.set( rt::well_potential_gas, -10.15 / day );
|
rates1.set( rt::well_potential_gas, -10.15 / day );
|
||||||
@ -144,9 +154,9 @@ data::Wells result_wells(const bool w3_injector = true)
|
|||||||
rates2.set( rt::reservoir_water, -20.6 / day );
|
rates2.set( rt::reservoir_water, -20.6 / day );
|
||||||
rates2.set( rt::reservoir_oil, -20.7 / day );
|
rates2.set( rt::reservoir_oil, -20.7 / day );
|
||||||
rates2.set( rt::reservoir_gas, -20.8 / day );
|
rates2.set( rt::reservoir_gas, -20.8 / day );
|
||||||
rates2.set( rt::productivity_index_water, -20.9 / day );
|
rates2.set( rt::productivity_index_water, 20.9*liquid_PI_unit());
|
||||||
rates2.set( rt::productivity_index_oil, -20.11 / day );
|
rates2.set( rt::productivity_index_oil, 20.11*liquid_PI_unit());
|
||||||
rates2.set( rt::productivity_index_gas, -20.12 / day );
|
rates2.set( rt::productivity_index_gas, 20.12*gas_PI_unit());
|
||||||
rates2.set( rt::well_potential_water, -20.13 / day );
|
rates2.set( rt::well_potential_water, -20.13 / day );
|
||||||
rates2.set( rt::well_potential_oil, -20.14 / day );
|
rates2.set( rt::well_potential_oil, -20.14 / day );
|
||||||
rates2.set( rt::well_potential_gas, -20.15 / day );
|
rates2.set( rt::well_potential_gas, -20.15 / day );
|
||||||
@ -163,16 +173,15 @@ data::Wells result_wells(const bool w3_injector = true)
|
|||||||
rates3.set( rt::reservoir_water, 30.6 / day );
|
rates3.set( rt::reservoir_water, 30.6 / day );
|
||||||
rates3.set( rt::reservoir_oil, 30.7 / day );
|
rates3.set( rt::reservoir_oil, 30.7 / day );
|
||||||
rates3.set( rt::reservoir_gas, 30.8 / day );
|
rates3.set( rt::reservoir_gas, 30.8 / day );
|
||||||
rates3.set( rt::productivity_index_water, -30.9 / day );
|
rates3.set( rt::productivity_index_water, 30.9*liquid_PI_unit());
|
||||||
rates3.set( rt::productivity_index_oil, -30.11 / day );
|
rates3.set( rt::productivity_index_oil, 30.11*liquid_PI_unit());
|
||||||
rates3.set( rt::productivity_index_gas, -30.12 / day );
|
rates3.set( rt::productivity_index_gas, 30.12*gas_PI_unit());
|
||||||
rates3.set( rt::well_potential_water, 30.13 / day );
|
rates3.set( rt::well_potential_water, 30.13 / day );
|
||||||
rates3.set( rt::well_potential_oil, 30.14 / day );
|
rates3.set( rt::well_potential_oil, 30.14 / day );
|
||||||
rates3.set( rt::well_potential_gas, 30.15 / day );
|
rates3.set( rt::well_potential_gas, 30.15 / day );
|
||||||
rates3.set( rt::polymer, 30.16 / day );
|
rates3.set( rt::polymer, 30.16 / day );
|
||||||
rates3.set( rt::brine, 30.17 / day );
|
rates3.set( rt::brine, 30.17 / day );
|
||||||
|
|
||||||
|
|
||||||
data::Rates rates6;
|
data::Rates rates6;
|
||||||
rates6.set( rt::wat, 60.0 / day );
|
rates6.set( rt::wat, 60.0 / day );
|
||||||
rates6.set( rt::oil, 60.1 / day );
|
rates6.set( rt::oil, 60.1 / day );
|
||||||
@ -183,14 +192,15 @@ data::Wells result_wells(const bool w3_injector = true)
|
|||||||
rates6.set( rt::reservoir_water, 60.6 / day );
|
rates6.set( rt::reservoir_water, 60.6 / day );
|
||||||
rates6.set( rt::reservoir_oil, 60.7 / day );
|
rates6.set( rt::reservoir_oil, 60.7 / day );
|
||||||
rates6.set( rt::reservoir_gas, 60.8 / day );
|
rates6.set( rt::reservoir_gas, 60.8 / day );
|
||||||
rates6.set( rt::productivity_index_water, -60.9 / day );
|
rates6.set( rt::productivity_index_water, 60.9*liquid_PI_unit());
|
||||||
rates6.set( rt::productivity_index_oil, -60.11 / day );
|
rates6.set( rt::productivity_index_oil, 60.11*liquid_PI_unit());
|
||||||
rates6.set( rt::productivity_index_gas, -60.12 / day );
|
rates6.set( rt::productivity_index_gas, 60.12*gas_PI_unit());
|
||||||
rates6.set( rt::well_potential_water, 60.13 / day );
|
rates6.set( rt::well_potential_water, 60.13 / day );
|
||||||
rates6.set( rt::well_potential_oil, 60.14 / day );
|
rates6.set( rt::well_potential_oil, 60.14 / day );
|
||||||
rates6.set( rt::well_potential_gas, 60.15 / day );
|
rates6.set( rt::well_potential_gas, 60.15 / day );
|
||||||
rates6.set( rt::polymer, 60.16 / day );
|
rates6.set( rt::polymer, 60.16 / day );
|
||||||
rates6.set( rt::brine, 60.17 / day );
|
rates6.set( rt::brine, 60.17 / day );
|
||||||
|
|
||||||
/* completion rates */
|
/* completion rates */
|
||||||
data::Rates crates1;
|
data::Rates crates1;
|
||||||
crates1.set( rt::wat, -100.0 / day );
|
crates1.set( rt::wat, -100.0 / day );
|
||||||
@ -388,12 +398,14 @@ double ecl_sum_get_general_var(const EclIO::ESmry* smry,
|
|||||||
return smry->get(var)[timeIdx];
|
return smry->get(var)[timeIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool ecl_sum_has_well_var( const EclIO::ESmry* smry,
|
bool ecl_sum_has_well_var( const EclIO::ESmry* smry,
|
||||||
const std::string& wellname,
|
const std::string& wellname,
|
||||||
const std::string& variable )
|
const std::string& variable )
|
||||||
{
|
{
|
||||||
return smry->hasKey(variable + ':' + wellname);
|
return smry->hasKey(variable + ':' + wellname);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
double ecl_sum_get_well_var( const EclIO::ESmry* smry,
|
double ecl_sum_get_well_var( const EclIO::ESmry* smry,
|
||||||
const int timeIdx,
|
const int timeIdx,
|
||||||
@ -526,6 +538,28 @@ BOOST_AUTO_TEST_CASE(well_keywords) {
|
|||||||
BOOST_CHECK_CLOSE( 30.13, ecl_sum_get_well_var( resp, 1, "W_3", "WWPI" ), 1e-5 );
|
BOOST_CHECK_CLOSE( 30.13, ecl_sum_get_well_var( resp, 1, "W_3", "WWPI" ), 1e-5 );
|
||||||
BOOST_CHECK_CLOSE( 60.15, ecl_sum_get_well_var( resp, 1, "W_6", "WGPI" ), 1e-5 );
|
BOOST_CHECK_CLOSE( 60.15, ecl_sum_get_well_var( resp, 1, "W_6", "WGPI" ), 1e-5 );
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE( 10.9 , ecl_sum_get_well_var( resp, 1, "W_1", "WPIW" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 10.11, ecl_sum_get_well_var( resp, 1, "W_1", "WPIO" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 10.12, ecl_sum_get_well_var( resp, 1, "W_1", "WPIG" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 10.11, ecl_sum_get_well_var( resp, 1, "W_1", "WPI" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 21.01, ecl_sum_get_well_var( resp, 1, "W_1", "WPIL" ), 1.0e-5 );
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE( 20.9 , ecl_sum_get_well_var( resp, 1, "W_2", "WPIW" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 20.11, ecl_sum_get_well_var( resp, 1, "W_2", "WPIO" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 20.12, ecl_sum_get_well_var( resp, 1, "W_2", "WPIG" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 20.11, ecl_sum_get_well_var( resp, 1, "W_2", "WPI" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 41.01, ecl_sum_get_well_var( resp, 1, "W_2", "WPIL" ), 1.0e-5 );
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE( 30.9 , ecl_sum_get_well_var( resp, 1, "W_3", "WPIW" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 30.11, ecl_sum_get_well_var( resp, 1, "W_3", "WPIO" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 30.12, ecl_sum_get_well_var( resp, 1, "W_3", "WPIG" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 30.9 , ecl_sum_get_well_var( resp, 1, "W_3", "WPI" ), 1.0e-5 );
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE( 60.9 , ecl_sum_get_well_var( resp, 1, "W_6", "WPIW" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 60.11, ecl_sum_get_well_var( resp, 1, "W_6", "WPIO" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 60.12, ecl_sum_get_well_var( resp, 1, "W_6", "WPIG" ), 1.0e-5 );
|
||||||
|
BOOST_CHECK_CLOSE( 60.12, ecl_sum_get_well_var( resp, 1, "W_6", "WPI" ), 1.0e-5 );
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE( 123.456, ecl_sum_get_well_var(resp, 1, "W_1", "WOPGR"), 1.0e-5);
|
BOOST_CHECK_CLOSE( 123.456, ecl_sum_get_well_var(resp, 1, "W_1", "WOPGR"), 1.0e-5);
|
||||||
BOOST_CHECK_CLOSE(2345.67 , ecl_sum_get_well_var(resp, 1, "W_1", "WGPGR"), 1.0e-5);
|
BOOST_CHECK_CLOSE(2345.67 , ecl_sum_get_well_var(resp, 1, "W_1", "WGPGR"), 1.0e-5);
|
||||||
BOOST_CHECK_CLOSE( 654.321, ecl_sum_get_well_var(resp, 1, "W_2", "WWPGR"), 1.0e-5);
|
BOOST_CHECK_CLOSE( 654.321, ecl_sum_get_well_var(resp, 1, "W_2", "WWPGR"), 1.0e-5);
|
||||||
@ -1218,7 +1252,6 @@ BOOST_AUTO_TEST_CASE(skip_unknown_var) {
|
|||||||
const auto* resp = res.get();
|
const auto* resp = res.get();
|
||||||
|
|
||||||
/* verify that some non-supported keywords aren't written to the file */
|
/* verify that some non-supported keywords aren't written to the file */
|
||||||
BOOST_CHECK( !ecl_sum_has_well_var( resp, "W_1", "WPI" ) );
|
|
||||||
BOOST_CHECK( !ecl_sum_has_field_var( resp, "FGST" ) );
|
BOOST_CHECK( !ecl_sum_has_field_var( resp, "FGST" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user