Renamed UDQInput -> UDQCOnfig
UDQConfig object has merged DEFINE & ASSIGN Log use of UDA for output purposes Output UDQ keywords to restart file Add size() method to UDQConfig Add UDQVarTYpe member to UDQInput class Add UDQIndex type to keep track of sequence number of variable types Add unit to UDQInput class use maps Add operator[] to UDQConfig class Use UDQInput class when creating restart file UDQInput: use correct input index Add UDQActive::get() method Make sure UDQ DEFINE overwrite correctly WIP WIP - further code to output IGPH vector WIP Fix IUAD input index Output use_index for IUAD Fix bug with size of IUAD array UAD usage hashing based on udqstring and controltype Add UDQ test and input file Refactor UDQActive - handles vanishing UDA minor correction for iuad[1] and for test_UDQ_x.cpp Further work for making unit tests for UDQ restart data WIP Further work unit tests WIP some minor corrections WIP changes to add first version of BOOST test for IUDQ WIP Added code to write InteHead and DoubHead data as well as IGPH to restart file, Further added unit tests to the writing of UDQ data add code to output IUAP array Fixed group-group2 transition, disable Restart output WIP Initial changes to add DUDW array to restart output WIP further work on DUDW data WIP - further work to output and test DUDW vector data to restart file Further changes to write DUDW array to Restartfile
This commit is contained in:
committed by
Jostein Alvestad
parent
f2bc961bd4
commit
16a8f4040c
@@ -24,7 +24,7 @@ EQLDIMS
|
||||
2 /
|
||||
|
||||
WELLDIMS
|
||||
4 20 4 2 /
|
||||
5 20 4 2 /
|
||||
|
||||
UNIFIN
|
||||
UNIFOUT
|
||||
@@ -336,10 +336,10 @@ UDQ
|
||||
DEFINE WUOPRL (WOPR PROD1 - 150) * 0.90 /
|
||||
DEFINE WULPRL (WLPR PROD1 - 200) * 0.90 /
|
||||
DEFINE WUOPRU (WOPR PROD2 - 250) * 0.80 /
|
||||
DEFINE GUOPRU (GOPR WGRP2 - 449) * 0.77 /
|
||||
DEFINE GUOPRU (GOPR GRP1 - 449) * 0.77 /
|
||||
DEFINE WULPRU (WLPR PROD2 - 300) * 0.80 /
|
||||
ASSIGN WULPRL 400. /
|
||||
DEFINE FULPR (FLPR - 543) * 0.65 /
|
||||
DEFINE FULPR (FLPR - 543) * 0.65 /
|
||||
DEFINE WUOPRL (WOPR PROD1 - 170) * 0.60 /
|
||||
-- units
|
||||
UNITS WUOPRL SM3/DAY /
|
||||
@@ -347,7 +347,7 @@ UNITS WULPRL SM3/DAY /
|
||||
UNITS GUOPRU SM3/DAY /
|
||||
UNITS WUOPRU SM3/DAY /
|
||||
UNITS WULPRU SM3/DAY /
|
||||
UNITS FULPR SM3/DAY /
|
||||
UNITS FULPR SM3/DAY /
|
||||
--
|
||||
/
|
||||
|
||||
|
||||
@@ -1240,6 +1240,7 @@ UDQ
|
||||
BOOST_CHECK( fuopr.is<UDQDefine>() );
|
||||
const auto& def2 = fuopr.get<UDQDefine>();
|
||||
BOOST_CHECK_EQUAL(def2.input_string(), "MAX(WOPR)");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1370,6 +1371,208 @@ WCONPROD
|
||||
|
||||
|
||||
|
||||
)";
|
||||
auto schedule = make_udq_schedule(udq_string);
|
||||
|
||||
// First timestep
|
||||
{
|
||||
const auto& udq_active = schedule.udqActive(0);
|
||||
BOOST_CHECK(udq_active);
|
||||
BOOST_CHECK_EQUAL(udq_active.IUAD_size(), 2);
|
||||
|
||||
const auto& record0 = udq_active[0];
|
||||
BOOST_CHECK_EQUAL( record0.uad_code, 300004);
|
||||
BOOST_CHECK_EQUAL( record0.input_index, 2);
|
||||
BOOST_CHECK_EQUAL( record0.use_count, 2);
|
||||
BOOST_CHECK_EQUAL( record0.use_index, 0);
|
||||
|
||||
const auto& record1 = udq_active[1];
|
||||
BOOST_CHECK_EQUAL( record1.uad_code, 600004);
|
||||
BOOST_CHECK_EQUAL( record1.input_index, 3);
|
||||
BOOST_CHECK_EQUAL( record1.use_count, 2);
|
||||
BOOST_CHECK_EQUAL( record1.use_index, 2);
|
||||
}
|
||||
|
||||
{
|
||||
// Second timestep
|
||||
// - The WUOPRU and WULPRU udq are still used in the same manner for the PROD1 well.
|
||||
// - The new UDQs WUXO and WUXL are now used for the PROD2 well.
|
||||
const auto& udq_active = schedule.udqActive(1);
|
||||
BOOST_CHECK(udq_active);
|
||||
BOOST_CHECK_EQUAL(udq_active.IUAD_size(), 4);
|
||||
|
||||
const auto& record0 = udq_active[0];
|
||||
BOOST_CHECK_EQUAL( record0.uad_code, 300004);
|
||||
BOOST_CHECK_EQUAL( record0.input_index, 2);
|
||||
BOOST_CHECK_EQUAL( record0.use_count, 1);
|
||||
BOOST_CHECK_EQUAL( record0.use_index, 0);
|
||||
|
||||
const auto& record1 = udq_active[1];
|
||||
BOOST_CHECK_EQUAL( record1.uad_code, 600004);
|
||||
BOOST_CHECK_EQUAL( record1.input_index, 3);
|
||||
BOOST_CHECK_EQUAL( record1.use_count, 1);
|
||||
BOOST_CHECK_EQUAL( record1.use_index, 1);
|
||||
|
||||
const auto& record2 = udq_active[2];
|
||||
BOOST_CHECK_EQUAL( record2.uad_code, 300004);
|
||||
BOOST_CHECK_EQUAL( record2.input_index, 4);
|
||||
BOOST_CHECK_EQUAL( record2.use_count, 1);
|
||||
BOOST_CHECK_EQUAL( record2.use_index, 2);
|
||||
|
||||
const auto& record3 = udq_active[3];
|
||||
BOOST_CHECK_EQUAL( record3.uad_code, 600004);
|
||||
BOOST_CHECK_EQUAL( record3.input_index, 5);
|
||||
BOOST_CHECK_EQUAL( record3.use_count, 1);
|
||||
BOOST_CHECK_EQUAL( record3.use_index, 3);
|
||||
}
|
||||
|
||||
{
|
||||
// Third timestep
|
||||
// - The new UDQs WUXO and WUXL are now used for the PROD2 well.
|
||||
// - The PROD1 well does not use UDQ
|
||||
const auto& udq_active = schedule.udqActive(2);
|
||||
BOOST_CHECK(udq_active);
|
||||
BOOST_CHECK_EQUAL(udq_active.IUAD_size(), 2);
|
||||
|
||||
const auto& record0 = udq_active[0];
|
||||
BOOST_CHECK_EQUAL( record0.uad_code, 300004);
|
||||
BOOST_CHECK_EQUAL( record0.input_index, 4);
|
||||
BOOST_CHECK_EQUAL( record0.use_count, 1);
|
||||
BOOST_CHECK_EQUAL( record0.use_index, 0);
|
||||
|
||||
const auto& record1 = udq_active[1];
|
||||
BOOST_CHECK_EQUAL( record1.uad_code, 600004);
|
||||
BOOST_CHECK_EQUAL( record1.input_index, 5);
|
||||
BOOST_CHECK_EQUAL( record1.use_count, 1);
|
||||
BOOST_CHECK_EQUAL( record1.use_index, 1);
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_USAGE) {
|
||||
UDQActive usage;
|
||||
UDQParams params;
|
||||
UDQConfig conf(params);
|
||||
BOOST_CHECK_EQUAL( usage.IUAD_size(), 0 );
|
||||
|
||||
UDAValue uda1("WUX");
|
||||
conf.add_assign(uda1.get<std::string>(), {}, 100);
|
||||
|
||||
usage.update(conf, uda1, "W1", UDAControl::WCONPROD_ORAT);
|
||||
BOOST_CHECK_EQUAL( usage.IUAD_size(), 1 );
|
||||
BOOST_CHECK_EQUAL( usage[0].use_count, 1);
|
||||
|
||||
usage.update(conf, uda1, "W1", UDAControl::WCONPROD_GRAT);
|
||||
BOOST_CHECK_EQUAL( usage.IUAD_size(), 2 );
|
||||
BOOST_CHECK_EQUAL( usage[1].use_count, 1);
|
||||
|
||||
const auto& rec = usage[0];
|
||||
BOOST_CHECK_EQUAL(rec.wgname, "W1");
|
||||
BOOST_CHECK_EQUAL(rec.udq, "WUX");
|
||||
BOOST_CHECK(rec.control == UDAControl::WCONPROD_ORAT);
|
||||
|
||||
|
||||
for (std::size_t index = 0; index < usage.IUAD_size(); index++) {
|
||||
const auto& record = usage[index];
|
||||
BOOST_CHECK_EQUAL(record.input_index, 0);
|
||||
BOOST_CHECK_EQUAL(record.wgname, "W1");
|
||||
|
||||
if (index == 0)
|
||||
BOOST_CHECK(record.control == UDAControl::WCONPROD_ORAT);
|
||||
else
|
||||
BOOST_CHECK(record.control == UDAControl::WCONPROD_GRAT);
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(IntegrationTest) {
|
||||
#include "data/integration_tests/udq.data"
|
||||
auto schedule = make_schedule(deck_string);
|
||||
{
|
||||
const auto& active = schedule.udqActive(1);
|
||||
BOOST_CHECK_EQUAL(active.IUAD_size(), 4);
|
||||
|
||||
BOOST_CHECK(active[0].control == UDAControl::WCONPROD_ORAT);
|
||||
BOOST_CHECK(active[1].control == UDAControl::WCONPROD_LRAT);
|
||||
BOOST_CHECK(active[2].control == UDAControl::WCONPROD_ORAT);
|
||||
BOOST_CHECK(active[3].control == UDAControl::WCONPROD_LRAT);
|
||||
|
||||
BOOST_CHECK(active[0].wgname == "OPL02");
|
||||
BOOST_CHECK(active[1].wgname == "OPL02");
|
||||
BOOST_CHECK(active[2].wgname == "OPU02");
|
||||
BOOST_CHECK(active[3].wgname == "OPU02");
|
||||
|
||||
BOOST_CHECK(active[0].udq == "WUOPRL");
|
||||
BOOST_CHECK(active[1].udq == "WULPRL");
|
||||
BOOST_CHECK(active[2].udq == "WUOPRU");
|
||||
BOOST_CHECK(active[3].udq == "WULPRU");
|
||||
|
||||
BOOST_CHECK(active[0].input_index == 0);
|
||||
BOOST_CHECK(active[1].input_index == 1);
|
||||
BOOST_CHECK(active[2].input_index == 2);
|
||||
BOOST_CHECK(active[3].input_index == 3);
|
||||
|
||||
BOOST_CHECK(active[0].use_count == 1);
|
||||
BOOST_CHECK(active[1].use_count == 1);
|
||||
BOOST_CHECK(active[2].use_count == 1);
|
||||
BOOST_CHECK(active[3].use_count == 1);
|
||||
}
|
||||
}
|
||||
|
||||
Schedule make_udq_schedule(const std::string& schedule_string) {
|
||||
#include "data/integration_tests/udq2.data"
|
||||
deck_string += schedule_string;
|
||||
return make_schedule(deck_string);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(IntegrationTest2) {
|
||||
const std::string udq_string = R"(
|
||||
UDQ
|
||||
DEFINE WUOPRL (WOPR PROD1 - 150) * 0.90 /
|
||||
DEFINE WULPRL (WLPR PROD1 - 200) * 0.90 /
|
||||
DEFINE WUOPRU (WOPR PROD2 - 250) * 0.80 /
|
||||
DEFINE WULPRU (WLPR PROD2 - 300) * 0.80 /
|
||||
DEFINE WUOPRL (WOPR PROD1 - 170) * 0.60 /
|
||||
DEFINE WUXO (WOPR PROD1 - 170) * 0.60 /
|
||||
DEFINE WUXL (WOPR PROD1 - 170) * 0.60 /
|
||||
-- units
|
||||
UNITS WUOPRL SM3/DAY /
|
||||
UNITS WULPRL SM3/DAY /
|
||||
UNITS WUOPRU SM3/DAY /
|
||||
UNITS WULPRU SM3/DAY /
|
||||
/
|
||||
|
||||
WCONPROD
|
||||
'PROD1' 'OPEN' 'GRUP' WUOPRU 1* 1* WULPRU 1* 60.0 / single wells
|
||||
/
|
||||
|
||||
|
||||
WCONPROD
|
||||
'PROD2' 'OPEN' 'GRUP' WUOPRU 1* 1* WULPRU 1* 60.0 / single wells
|
||||
/
|
||||
|
||||
WCONINJE
|
||||
'WINJ1' 'WAT' 'OPEN' 'BHP' 1* 1200 3500 1* /
|
||||
'WINJ2' 'WAT' 'OPEN' 'BHP' 1* 800 3500 1* /
|
||||
/
|
||||
|
||||
TSTEP
|
||||
5 /
|
||||
|
||||
WCONPROD
|
||||
'PROD2' 'OPEN' 'GRUP' WUXO 1* 1* WUXL 1* 60.0 / single wells
|
||||
/
|
||||
|
||||
TSTEP
|
||||
5 /
|
||||
|
||||
WCONPROD
|
||||
'PROD1' 'OPEN' 'GRUP' 100 1* 1* 100 1* 60.0 / single wells
|
||||
/
|
||||
|
||||
|
||||
|
||||
|
||||
)";
|
||||
auto schedule = make_udq_schedule(udq_string);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace {
|
||||
Opm::Deck first_sim(std::string fname) {
|
||||
return Opm::Parser{}.parseFile(fname);
|
||||
}
|
||||
|
||||
/*
|
||||
Opm::UDQActive udq_active() {
|
||||
int update_count = 0;
|
||||
// construct record data for udq_active
|
||||
@@ -67,8 +67,41 @@ namespace {
|
||||
}
|
||||
return udq_act;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Opm::SummaryState sum_state()
|
||||
{
|
||||
auto state = Opm::SummaryState{};
|
||||
state.update_well_var("PROD1", "WUOPRL", 210.);
|
||||
state.update_well_var("PROD2", "WUOPRL", 211.);
|
||||
state.update_well_var("WINJ1", "WUOPRL", 212.);
|
||||
state.update_well_var("WINJ2", "WUOPRL", 213.);
|
||||
|
||||
state.update_well_var("PROD1", "WULPRL", 230.);
|
||||
state.update_well_var("PROD2", "WULPRL", 231.);
|
||||
state.update_well_var("WINJ1", "WULPRL", 232.);
|
||||
state.update_well_var("WINJ2", "WULPRL", 233.);
|
||||
|
||||
state.update_well_var("PROD1", "WUOPRU", 220.);
|
||||
state.update_well_var("PROD2", "WUOPRU", 221.);
|
||||
state.update_well_var("WINJ1", "WUOPRU", 222.);
|
||||
state.update_well_var("WINJ2", "WUOPRU", 223.);
|
||||
|
||||
state.update_group_var("WGRP1", "GUOPRU", 360.);
|
||||
state.update_group_var("WGRP2", "GUOPRU", 361.);
|
||||
state.update_group_var("GRP1", "GUOPRU", 362.);
|
||||
state.update_group_var("GRP2", "GUOPRU", 363.);
|
||||
|
||||
state.update_well_var("PROD1", "WULPRU", 160.);
|
||||
state.update_well_var("PROD2", "WULPRU", 161.);
|
||||
state.update_well_var("WINJ1", "WULPRU", 162.);
|
||||
state.update_well_var("WINJ2", "WULPRU", 163.);
|
||||
|
||||
state.update("FULPR", 460.);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
//int main(int argc, char* argv[])
|
||||
@@ -76,8 +109,8 @@ struct SimulationCase
|
||||
{
|
||||
explicit SimulationCase(const Opm::Deck& deck)
|
||||
: es { deck }
|
||||
, grid { deck }
|
||||
, sched{ deck, es }
|
||||
, grid { deck }
|
||||
, sched{ deck, es }
|
||||
{}
|
||||
|
||||
// Order requirement: 'es' must be declared/initialised before 'sched'.
|
||||
@@ -97,11 +130,11 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data)
|
||||
const auto simCase = SimulationCase{first_sim("UDQ_TEST_WCONPROD_IUAD-2.DATA")};
|
||||
|
||||
Opm::EclipseState es = simCase.es;
|
||||
Opm::SummaryState st = sum_state();
|
||||
Opm::Schedule sched = simCase.sched;
|
||||
Opm::EclipseGrid grid = simCase.grid;
|
||||
const auto& ioConfig = es.getIOConfig();
|
||||
const auto& restart = es.cfg().restart();
|
||||
//Opm::UDQActive udq_act = udq_active();
|
||||
//const auto& restart = es.cfg().restart();
|
||||
|
||||
// Report Step 1: 2008-10-10 --> 2011-01-20
|
||||
const auto rptStep = std::size_t{1};
|
||||
@@ -112,9 +145,9 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data)
|
||||
Opm::EclIO::OutputStream::ResultSet { outputDir, baseName },
|
||||
rptStep,
|
||||
Opm::EclIO::OutputStream::Formatted { ioConfig.getFMTOUT() },
|
||||
Opm::EclIO::OutputStream::Unified { ioConfig.getUNIFOUT() }
|
||||
Opm::EclIO::OutputStream::Unified { ioConfig.getUNIFOUT() }
|
||||
};
|
||||
|
||||
|
||||
double secs_elapsed = 3.1536E07;
|
||||
const auto ih = Opm::RestartIO::Helpers::createInteHead(es, grid, sched,
|
||||
secs_elapsed, rptStep, rptStep);
|
||||
@@ -125,14 +158,15 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data)
|
||||
|
||||
const auto udqDims = Opm::RestartIO::Helpers::createUdqDims(sched, rptStep, ih);
|
||||
auto udqData = Opm::RestartIO::Helpers::AggregateUDQData(udqDims);
|
||||
udqData.captureDeclaredUDQData(sched, rptStep, ih);
|
||||
udqData.captureDeclaredUDQData(sched, rptStep, st, ih);
|
||||
|
||||
rstFile.write("IUDQ", udqData.getIUDQ());
|
||||
rstFile.write("IUAD", udqData.getIUAD());
|
||||
rstFile.write("IGPH", udqData.getIGPH());
|
||||
rstFile.write("IUAP", udqData.getIUAP());
|
||||
rstFile.write("ZUDN", udqData.getZUDN());
|
||||
rstFile.write("ZUDL", udqData.getZUDL());
|
||||
rstFile.write("IUDQ", udqData.getIUDQ());
|
||||
rstFile.write("DUDW", udqData.getDUDW());
|
||||
rstFile.write("IUAD", udqData.getIUAD());
|
||||
rstFile.write("IUAP", udqData.getIUAP());
|
||||
rstFile.write("IGPH", udqData.getIGPH());
|
||||
|
||||
{
|
||||
/*
|
||||
@@ -327,19 +361,18 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data)
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "0) * 0.6"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "0 "); // udq NO. 1
|
||||
|
||||
/*start = 1*udqDims[5];
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WLPR PR"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "OD1 - 20"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "0) * 0.9"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "0 "); // udq NO. 1
|
||||
*/
|
||||
|
||||
start = 3*udqDims[5];
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(GOPR WG"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "RP2 - 44"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "9) * 0.7"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "7 "); // udq NO. 1
|
||||
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(GOPR GR"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "P1 - 449"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , ") * 0.77"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , " "); // udq NO. 1
|
||||
|
||||
start = 4*udqDims[5];
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WLPR PR"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "OD2 - 30"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "0) * 0.8"); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "0 "); // udq NO. 1
|
||||
|
||||
start = 5*udqDims[5];
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(FLPR - "); // udq NO. 1
|
||||
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "543) * 0"); // udq NO. 1
|
||||
@@ -348,6 +381,34 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data)
|
||||
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
/*
|
||||
'DUDW ' 24 'DOUB'
|
||||
|
||||
Dimension = max no wells * no of UDQ's
|
||||
Value = value of UDQ for the different wells
|
||||
*/
|
||||
|
||||
const auto& dUdw = udqData.getDUDW();
|
||||
|
||||
auto start = 0*udqDims[8];
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 0] , 210); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 1] , 211); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 2] , 212); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 3] , 213); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 4] , -0.3E+21); // duDw NO. 1
|
||||
|
||||
start = 1*udqDims[8];
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 0] , 230); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 1] , 231); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 2] , 232); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 3] , 233); // duDw NO. 1
|
||||
BOOST_CHECK_EQUAL(dUdw[start + 4] , -0.3E+21); // duDw NO. 1
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user