Commit b9133771 authored by Dmitry Yu. Naumov's avatar Dmitry Yu. Naumov
Browse files

Merge branch 'BHE_PNW' into 'master'

Adjust the data exchange functions in OGS-TESPy pipeline network interface for BHEHeatTransport process

See merge request ogs/ogs!3089
parents 42526301 c218fef1
......@@ -37,24 +37,16 @@ public:
initializeDataContainer);
}
std::tuple<bool, bool, std::vector<double>> tespyThermalSolver(
std::tuple<bool, bool, std::vector<double>, std::vector<double>>
tespySolver(
double t,
std::vector<double> const& Tin_val,
std::vector<double> const& Tout_val) const override
{
using Ret = std::tuple<bool, bool, std::vector<double>>;
using Ret = std::tuple<bool, bool, std::vector<double>, std::vector<double>>;
PYBIND11_OVERLOAD(Ret,
BHEInflowPythonBoundaryConditionPythonSideInterface,
tespyThermalSolver, t, Tin_val, Tout_val);
}
std::tuple<bool, std::vector<double>> tespyHydroSolver(
double t) const override
{
using Ret = std::tuple<bool, std::vector<double>>;
PYBIND11_OVERLOAD(Ret,
BHEInflowPythonBoundaryConditionPythonSideInterface,
tespyHydroSolver, t);
tespySolver, t, Tin_val, Tout_val);
}
};
......@@ -71,12 +63,9 @@ void bheInflowpythonBindBoundaryCondition(pybind11::module& m)
pybc.def("initializeDataContainer",
&BHEInflowPythonBoundaryConditionPythonSideInterface::
initializeDataContainer);
pybc.def("tespyThermalSolver",
pybc.def("tespySolver",
&BHEInflowPythonBoundaryConditionPythonSideInterface::
tespyThermalSolver);
pybc.def(
"tespyHydroSolver",
&BHEInflowPythonBoundaryConditionPythonSideInterface::tespyHydroSolver);
tespySolver);
}
} // namespace ProcessLib
......@@ -41,35 +41,23 @@ public:
}
/*!
* transfer BHE network dataframe to TESPy and get Tin from TESPy
* transfer BHE network dataframe to TESPy and get Tin and flow rate from TESPy
*
* \return a tuple (if use tespyThermalSolver, if convergence achieved
* in tespy, BHE Tin and Tout value from TESPy)
* in tespy, BHE Tin value, BHE flow rate from TESPy)
* indicating if tespyThermalSolver shall be used at that position, if
* themal convergence has been achieved in the tespy and the new
* inflow temperature of all BHEs.
* themal convergence has been achieved in the tespy, the new
* inflow temperature and flow rate for all BHEs.
*/
virtual std::tuple<bool, bool, std::vector<double>> tespyThermalSolver(
virtual std::tuple<bool, bool, std::vector<double>, std::vector<double>>
tespySolver(
double /*t*/,
std::vector<double> const& /*Tin_val*/,
std::vector<double> const& /*Tout_val*/) const
{
_overridden_tespyThermal = false;
return std::tuple<bool, bool, std::vector<double>>{false, false, {}};
}
/*!
* call Tespy hydraulic solver to get flow velocity in each pipe
*
* \return a tuple (if use tespyHydroSolver, f_velocity) indicating if
* tespyHydroSolver shall be used at that position and the flow velocity
* in each pipe of all BHEs.
*/
virtual std::tuple<bool, std::vector<double>> tespyHydroSolver(
double /*t*/) const
{
_overridden_tespyHydro = false;
return std::tuple<bool, std::vector<double>>{false, {}};
_overridden_tespy = false;
return std::tuple<bool, bool, std::vector<double>, std::vector<double>>{
false, false, {}, {}};
}
//! Tells if initializeDataContainer() has been overridden in the derived
......@@ -79,17 +67,11 @@ public:
//! once.
bool isOverriddenEssential() const { return _overridden_essential; }
//! Tells if tespyThermalSolver() has been overridden in the derived class
//! in Python.
//!
//! \pre tespyThermalSolver() must already have been called once.
bool isOverriddenTespyThermal() const { return _overridden_tespyThermal; }
//! Tells if tespyHydroSolver() has been overridden in the derived class
//! Tells if tespySolver() has been overridden in the derived class
//! in Python.
//!
//! \pre tespyHydroSolver() must already have been called once.
bool isOverriddenTespyHydro() const { return _overridden_tespyHydro; }
//! \pre tespySolver() must already have been called once.
bool isOverriddenTespy() const { return _overridden_tespy; }
// BHE network dataframe container
std::tuple<double,
......@@ -105,11 +87,8 @@ private:
//! Tells if initializeDataContainer() has been overridden in the derived
//! class in Python.
mutable bool _overridden_essential = true;
//! Tells if tespyThermalSolver() has been overridden in the derived class
//! Tells if tespySolver() has been overridden in the derived class
//! in Python.
mutable bool _overridden_tespyThermal = true;
//! Tells if tespyHydroSolver() has been overridden in the derived class in
//! Python.
mutable bool _overridden_tespyHydro = true;
mutable bool _overridden_tespy = true;
};
} // namespace ProcessLib
......@@ -208,57 +208,37 @@ NumLib::IterationResult HeatTransportBHEProcess::postIterationConcreteProcess(
return NumLib::IterationResult::SUCCESS;
// Here the task is to get current time flowrate and flow temperature from
// TESPy
// TESPy and determine whether it converges.
auto const Tout_nodes_id =
std::get<3>(_process_data.py_bc_object->dataframe_network);
const std::size_t n_bc_nodes = Tout_nodes_id.size();
// update flowrate in network if network exist a dynamic flowrate in time
auto const cur_time =
std::get<0>(_process_data.py_bc_object->dataframe_network);
if (std::get<0>(_process_data.py_bc_object->tespyHydroSolver(cur_time)))
{
// calculate the current flowrate in each BHE from TESPy
auto const cur_flowrate =
std::get<1>(_process_data.py_bc_object->tespyHydroSolver(cur_time));
for (std::size_t i = 0; i < n_bc_nodes; i++)
std::get<4>(_process_data.py_bc_object->dataframe_network)[i] =
cur_flowrate[i];
if (!_process_data.py_bc_object->isOverriddenTespyHydro())
{
DBUG(
"Method `tespyHydroSolver' not overridden in Python "
"script.");
}
}
// get the outflow temperature,
// transfer it to TESPy and to get inflow temperature,
// and determine whether it converges.
for (std::size_t i = 0; i < n_bc_nodes; i++)
{
// read the T_out and store them in dataframe
std::get<2>(_process_data.py_bc_object->dataframe_network)[i] =
x[Tout_nodes_id[i]];
}
// Tout transfer to Python
auto const tespy_result = _process_data.py_bc_object->tespyThermalSolver(
// Transfer Tin and Tout to TESPy and return the results
auto const tespy_result = _process_data.py_bc_object->tespySolver(
std::get<0>(_process_data.py_bc_object->dataframe_network),
std::get<1>(_process_data.py_bc_object->dataframe_network),
std::get<2>(_process_data.py_bc_object->dataframe_network));
if (!_process_data.py_bc_object->isOverriddenTespyThermal())
if (!_process_data.py_bc_object->isOverriddenTespy())
{
DBUG(
"Method `tespyThermalSolver' not overridden in Python "
"Method `tespySolver' not overridden in Python "
"script.");
}
auto const cur_Tin = std::get<2>(tespy_result);
// update the T_in
// update the Tin and flow rate
for (std::size_t i = 0; i < n_bc_nodes; i++)
{
std::get<1>(_process_data.py_bc_object->dataframe_network)[i] =
cur_Tin[i];
std::get<2>(tespy_result)[i];
std::get<4>(_process_data.py_bc_object->dataframe_network)[i] =
std::get<3>(tespy_result)[i];
}
auto const tespy_has_converged = std::get<1>(tespy_result);
if (tespy_has_converged == true)
return NumLib::IterationResult::SUCCESS;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -13,22 +13,22 @@ from pandas import read_csv
import OpenGeoSys
from tespy.networks import load_network
# User setting +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# User setting ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# parameters
# refrigerant parameters
refrig_density = 992.92 # kg/m3
# refrigerant density
rho_f = 992.92 # kg/m3
# switch for special boundary conditions
# 'on','off', switch of the function for dynamic thermal demand from consumer
switch_dyn_demand = 'on'
# 'on','off', switch of the function for dynamic flowrate in BHE
switch_dyn_frate = 'off'
# switch of the function for manually specified dynamic flowrate
switch_dyn_frate = 'off' # 'on','off'
# switch of the function for manually specified dynamic thermal demand
switch_dyn_demand = 'on' # 'on','off'
# network status setting
def network_status(t):
nw_status = 'on'
# month for closed network
timerange_nw_off_month = [-9999] # No month for closed network
timerange_nw_off_month = [] # No month for closed network
# t-1 to avoid the calculation problem at special time point,
# e.g. t = 2592000.
t_trans = int((t - 1) / 86400 / 30) + 1
......@@ -56,18 +56,18 @@ def consumer_demand(t): # dynamic thermal demand from consumer
return month_demand[t_trans - 1]
# dynamic hydraulic flow rate
def dyn_frate(t): # dynamic flowrate in BHE
# dynamic hydraulic flow rate at the network inlet
def dyn_frate(t):
# time conversion
t_trans = int((t - 1) / 86400 / 30) + 1
if t_trans > 12:
t_trans = t_trans - 12 * (int(t_trans / 12))
# flow rate in kg / s time curve in month
month_frate = [-9999]
month_frate = []
return month_frate[t_trans - 1]
# End User setting+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# End User setting +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# create network dataframe
......@@ -80,98 +80,75 @@ def create_dataframe():
return (df_nw)
# TESPy hydraulic calculation process
def get_hydraulics(t):
# TESPy calculation process
def get_tespy_results(t):
# bhe network boundary conditions re parametrization
# if network exist dynamic flowrate
if switch_dyn_frate == 'on':
cur_frate = dyn_frate(t)
localVars['inlet_name'].set_attr(m=cur_frate)
# solve imported network
nw.solve(mode='design')
# get flowrate #m ^ 3 / s
for i in range(n_BHE):
for c in nw.conns.index:
if c.target.label == data_index[i]: # t:inlet comp, s:outlet comp
df.loc[df.index[i], 'flowrate'] = c.get_attr('m').val_SI / refrig_density
return df
# TESPy Thermal calculation process
def get_thermal(t):
# bhe network thermal re parametrization
# if network exist dynamic thermal demand
if switch_dyn_demand == 'on':
# consumer thermal load:
cur_month_demand = consumer_demand(t)
# print('cur_month_demand', cur_month_demand)
nw.busses[bus_name].set_attr(P=cur_month_demand)
# T_out:
# T_out re parametrization:
for i in range(n_BHE):
localVars['outlet_BHE' + str(i + 1)].set_attr(T=df.loc[data_index[i],
'Tout_val'])
# print('Tout=', df.loc[data_index[i], 'Tout_val'])
'Tout_val'])
# solving network
nw.solve(mode='design')
# get Tin_val
# get Tin_val and flow rate
for i in range(n_BHE):
# get Tin_val
df.loc[df.index[i],
'Tin_val'] = localVars['inlet_BHE' +
str(i + 1)].get_attr('T').val_SI
# print('Tin=', df.loc[df.index[i], 'Tin_val'])
return df['Tin_val'].tolist()
str(i + 1)].get_attr('T').val
# get flowrate
df.loc[df.index[i],
'flowrate'] = localVars['inlet_BHE' +
str(i + 1)].get_attr('m').val / rho_f
return df['Tin_val'].tolist(), df['flowrate'].tolist()
# OGS setting
# Dirichlet BCs
class BC(OpenGeoSys.BHENetwork):
def initializeDataContainer(self):
# initialize network and get data from the network
nw.solve(mode='design')
get_tespy_results(0)
# convert dataframe to column list
t = 0 # 'initial time'
data_col_1 = df['Tin_val'].tolist() # 'Tin_val'
data_col_2 = df['Tout_val'].tolist() # 'Tout_val'
data_col_3 = df['Tout_node_id'].astype(int).tolist() # 'Tout_node_id'
get_hydraulics(0)
data_col_4 = df['flowrate'].tolist() # 'BHE flow rate'
return (t, data_col_1, data_col_2, data_col_3, data_col_4)
def tespyThermalSolver(self, t, Tin_val, Tout_val):
def tespySolver(self, t, Tin_val, Tout_val):
# network status:
nw_status = network_status(t)
# if network closed:
# print('nw_status = ', nw_status)
if nw_status == 'off':
return (True, True, Tout_val)
df.loc[:,'flowrate'] = 0
cur_flowrate = df['flowrate'].tolist()
return (True, True, Tout_val, cur_flowrate)
else:
# read Tout_val to dataframe
for i in range(n_BHE):
df.loc[df.index[i], 'Tout_val'] = Tout_val[i]
# TESPy solver
cur_cal_Tin_val = get_thermal(t)
cur_Tin_val, cur_flowrate = get_tespy_results(t)
# check norm if network achieves the converge
if_success = False
pre_cal_Tin_val = Tin_val
pre_Tin_val = Tin_val
norm = np.linalg.norm(
abs(np.asarray(pre_cal_Tin_val) - np.asarray(cur_cal_Tin_val)))
abs(np.asarray(pre_Tin_val) - np.asarray(cur_Tin_val)))
if norm < 10e-6:
if_success = True
# return to OGS
return (True, if_success, cur_cal_Tin_val)
def tespyHydroSolver(self, t):
if_dyn_frate = False
data_flowrate = df['flowrate'].tolist()
if switch_dyn_frate == 'on':
if_dyn_frate = True
# network status:
nw_status = network_status(t)
if nw_status == 'off':
for i in range(n_BHE):
df.loc[df.index[i], 'flowrate'] = 0
data_flowrate = df['flowrate'].tolist()
else:
dataframe = get_hydraulics(t)
data_flowrate = dataframe['flowrate'].tolist()
# return to OGS
return (if_dyn_frate, data_flowrate)
return (True, if_success, cur_Tin_val, cur_flowrate)
# main
......@@ -200,13 +177,6 @@ for i in range(n_BHE):
if c.source.label == data_index[i]: # outlet conns of bhe
localVars['outlet_BHE' + str(i + 1)] = c
# time depended consumer thermal demand
if switch_dyn_demand == 'on':
# import the name of bus from the network csv file
bus_name = read_csv('./pre/tespy_nw/components/bus.csv',
delimiter=';',
index_col=[0]).index[0]
# time depended flowrate
if switch_dyn_frate == 'on':
# import the name of inlet connection from the network csv file
......@@ -218,5 +188,13 @@ if switch_dyn_frate == 'on':
if c.source.label == inlet_name: # inlet conns of bhe
localVars['inlet_name'] = c
# time depended consumer thermal demand
if switch_dyn_demand == 'on':
# import the name of bus from the network csv file
bus_name = read_csv('./pre/tespy_nw/components/bus.csv',
delimiter=';',
index_col=[0]).index[0]
# instantiate BC objects referenced in OpenGeoSys
bc_bhe = BC()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment