Skip to content

Commit d907db8

Browse files
committed
Added CoupledInjectionProductionPhysics
Closes #31899
1 parent d8769bb commit d907db8

File tree

9 files changed

+397
-0
lines changed

9 files changed

+397
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# CoupledInjectionProduction
2+
3+
This [Physics](syntax/Physics/index.md) object adds dirac kernels for mass and energy
4+
sources at injection and production points within a porous matrix, where the sources
5+
are provided by post-processor values transferred from another application.
6+
7+
This object creates the following post-processors:
8+
9+
- `p_inj1`, ..., `p_inj<n_inj>`: Pressure at each injection point, via [PointValue.md].
10+
- `T_inj1`, ..., `T_inj<n_inj>`: Temperature at each injection point, via [PointValue.md].
11+
- `p_pro1`, ..., `p_pro<n_pro>`: Pressure at each production point, via [PointValue.md].
12+
- `T_pro1`, ..., `T_pro<n_pro>`: Temperature at each production point, via [PointValue.md].
13+
- `mass_rate_inj1`, ..., `mass_rate_inj<n_inj>`: Mass source rate at each injection point, to be transferred from the other application using [Receiver.md].
14+
- `energy_rate_inj1`, ..., `energy_rate_inj<n_inj>`: Energy source rate at each injection point, to be transferred from the other application using [Receiver.md].
15+
- `mass_rate_pro1`, ..., `mass_rate_pro<n_pro>`: Mass source rate at each production point, to be transferred from the other application using [Receiver.md].
16+
- `energy_rate_pro1`, ..., `energy_rate_pro<n_pro>`: Energy source rate at each production point, to be transferred from the other application using [Receiver.md].
17+
18+
`n_inj` is the size of the [!param](/Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics/injection_points) parameter, and
19+
`n_pro` is the size of the [!param](/Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics/production_points) parameter.
20+
21+
If the parameter [!param](/Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics/multi_app)
22+
is provided, then the porous flow app is the main application, and [MultiAppPostprocessorTransfer.md]
23+
objects are created by this object to transfer the post-processors listed above to the sub application;
24+
if the parameter is not provided, then the other application is responsible for creating the transfers.
25+
26+
[PorousFlowPointSourceFromPostprocessor.md] dirac kernels are added for each injection and production point,
27+
using the `mass_rate_*` and `energy_rate_*` post-processors listed above.
28+
29+
!syntax parameters /Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics
30+
31+
!syntax inputs /Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics
32+
33+
!syntax children /Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../source/physics/CoupledInjectionProductionPhysics.md
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//* This file is part of the MOOSE framework
2+
//* https://mooseframework.inl.gov
3+
//*
4+
//* All rights reserved, see COPYRIGHT for full restrictions
5+
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6+
//*
7+
//* Licensed under LGPL 2.1, please see LICENSE for details
8+
//* https://www.gnu.org/licenses/lgpl-2.1.html
9+
10+
#pragma once
11+
12+
#include "PhysicsBase.h"
13+
14+
/**
15+
* Adds objects to perform hydrodynamic coupling at injection and production points.
16+
*/
17+
class CoupledInjectionProductionPhysics : public PhysicsBase
18+
{
19+
public:
20+
static InputParameters validParams();
21+
22+
CoupledInjectionProductionPhysics(const InputParameters & parameters);
23+
24+
protected:
25+
/// Adds a PorousFlowPointSourceFromPostprocessor
26+
void addPPSourceDiracKernel(const Point & point,
27+
const NonlinearVariableName & var,
28+
const PostprocessorName & pp_name);
29+
/// Adds a Receiver
30+
void addReceiverPostprocessor(const PostprocessorName & pp_name);
31+
/// Adds a PointValue
32+
void addPointValuePostprocessor(const VariableName & var,
33+
const Point & point,
34+
const PostprocessorName & pp_name);
35+
/// Adds a MultiAppPostprocessorTransfer
36+
void addPostprocessorTransfer(const PostprocessorName & pp_name, bool from_multi_app);
37+
38+
/// Injection points
39+
const std::vector<Point> & _injection_points;
40+
/// Production points
41+
const std::vector<Point> & _production_points;
42+
43+
/// Injection and production points
44+
std::vector<Point> _points;
45+
/// Label for each point
46+
std::vector<std::string> _labels;
47+
48+
private:
49+
void addDiracKernels() override;
50+
void addPostprocessors() override;
51+
void addTransfers() override;
52+
};

modules/porous_flow/src/base/PorousFlowApp.C

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ PorousFlowApp::registerAll(Factory & f, ActionFactory & af, Syntax & syntax)
5555
Registry::registerObjectsTo(f, {"PorousFlowApp"});
5656
Registry::registerActionsTo(af, {"PorousFlowApp"});
5757

58+
registerSyntax("CoupledInjectionProductionPhysics", "Physics/CoupledInjectionProduction/*");
59+
5860
registerSyntaxTask("PorousFlowUnsaturated", "PorousFlowUnsaturated", "add_user_object");
5961
registerSyntaxTask("PorousFlowUnsaturated", "PorousFlowUnsaturated", "add_kernel");
6062
registerSyntaxTask("PorousFlowUnsaturated", "PorousFlowUnsaturated", "add_material");
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//* This file is part of the MOOSE framework
2+
//* https://mooseframework.inl.gov
3+
//*
4+
//* All rights reserved, see COPYRIGHT for full restrictions
5+
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6+
//*
7+
//* Licensed under LGPL 2.1, please see LICENSE for details
8+
//* https://www.gnu.org/licenses/lgpl-2.1.html
9+
10+
#include "CoupledInjectionProductionPhysics.h"
11+
12+
registerPhysicsBaseTasks("PorousFlowApp", CoupledInjectionProductionPhysics);
13+
registerMooseAction("PorousFlowApp", CoupledInjectionProductionPhysics, "add_dirac_kernel");
14+
registerMooseAction("PorousFlowApp", CoupledInjectionProductionPhysics, "add_postprocessor");
15+
registerMooseAction("PorousFlowApp", CoupledInjectionProductionPhysics, "add_transfer");
16+
17+
InputParameters
18+
CoupledInjectionProductionPhysics::validParams()
19+
{
20+
InputParameters params = PhysicsBase::validParams();
21+
22+
params.addRequiredParam<std::vector<Point>>("injection_points", "List of injection points [m]");
23+
params.addRequiredParam<std::vector<Point>>("production_points", "List of production points [m]");
24+
params.addParam<MultiAppName>("multi_app", "MultiApp to transfer to and from");
25+
26+
params.addClassDescription(
27+
"Adds objects to perform hydrodynamic coupling at injection and production points.");
28+
29+
return params;
30+
}
31+
32+
CoupledInjectionProductionPhysics::CoupledInjectionProductionPhysics(
33+
const InputParameters & parameters)
34+
: PhysicsBase(parameters),
35+
_injection_points(getParam<std::vector<Point>>("injection_points")),
36+
_production_points(getParam<std::vector<Point>>("production_points"))
37+
{
38+
_points = _injection_points;
39+
_points.insert(_points.end(), _production_points.begin(), _production_points.end());
40+
41+
for (const auto i : index_range(_injection_points))
42+
_labels.push_back("inj" + std::to_string(i + 1));
43+
for (const auto i : index_range(_production_points))
44+
_labels.push_back("pro" + std::to_string(i + 1));
45+
}
46+
47+
void
48+
CoupledInjectionProductionPhysics::addDiracKernels()
49+
{
50+
for (const auto i : index_range(_points))
51+
{
52+
addPPSourceDiracKernel(_points[i], "porepressure", "mass_rate_" + _labels[i]);
53+
addPPSourceDiracKernel(_points[i], "temperature", "energy_rate_" + _labels[i]);
54+
}
55+
}
56+
57+
void
58+
CoupledInjectionProductionPhysics::addPostprocessors()
59+
{
60+
for (const auto i : index_range(_points))
61+
{
62+
addPointValuePostprocessor("porepressure", _points[i], "p_" + _labels[i]);
63+
addPointValuePostprocessor("temperature", _points[i], "T_" + _labels[i]);
64+
addReceiverPostprocessor("mass_rate_" + _labels[i]);
65+
addReceiverPostprocessor("energy_rate_" + _labels[i]);
66+
}
67+
}
68+
69+
void
70+
CoupledInjectionProductionPhysics::addTransfers()
71+
{
72+
if (isParamValid("multi_app"))
73+
for (const auto i : index_range(_points))
74+
{
75+
addPostprocessorTransfer("p_" + _labels[i], false);
76+
addPostprocessorTransfer("T_" + _labels[i], false);
77+
addPostprocessorTransfer("mass_rate_" + _labels[i], true);
78+
addPostprocessorTransfer("energy_rate_" + _labels[i], true);
79+
}
80+
}
81+
82+
void
83+
CoupledInjectionProductionPhysics::addPPSourceDiracKernel(const Point & point,
84+
const NonlinearVariableName & var,
85+
const PostprocessorName & pp_name)
86+
{
87+
const std::string class_name = "PorousFlowPointSourceFromPostprocessor";
88+
auto params = _factory.getValidParams(class_name);
89+
params.set<NonlinearVariableName>("variable") = var;
90+
params.set<Point>("point") = point;
91+
params.set<PostprocessorName>("mass_flux") = pp_name;
92+
getProblem().addDiracKernel(class_name, "dirac_" + pp_name, params);
93+
}
94+
95+
void
96+
CoupledInjectionProductionPhysics::addReceiverPostprocessor(const PostprocessorName & pp_name)
97+
{
98+
const std::string class_name = "Receiver";
99+
auto params = _factory.getValidParams(class_name);
100+
getProblem().addPostprocessor(class_name, pp_name, params);
101+
}
102+
103+
void
104+
CoupledInjectionProductionPhysics::addPointValuePostprocessor(const VariableName & var,
105+
const Point & point,
106+
const PostprocessorName & pp_name)
107+
{
108+
const std::string class_name = "PointValue";
109+
auto params = _factory.getValidParams(class_name);
110+
params.set<VariableName>("variable") = var;
111+
params.set<Point>("point") = point;
112+
params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
113+
getProblem().addPostprocessor(class_name, pp_name, params);
114+
}
115+
116+
void
117+
CoupledInjectionProductionPhysics::addPostprocessorTransfer(const PostprocessorName & pp_name,
118+
bool from_multi_app)
119+
{
120+
const std::string class_name = "MultiAppPostprocessorTransfer";
121+
auto params = _factory.getValidParams(class_name);
122+
if (from_multi_app)
123+
params.set<MultiAppName>("from_multi_app") = getParam<MultiAppName>("multi_app");
124+
else
125+
params.set<MultiAppName>("to_multi_app") = getParam<MultiAppName>("multi_app");
126+
params.set<PostprocessorName>("from_postprocessor") = pp_name;
127+
params.set<PostprocessorName>("to_postprocessor") = pp_name;
128+
params.set<MooseEnum>("reduction_type") = "average";
129+
params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
130+
getProblem().addTransfer(class_name, pp_name + "_transfer", params);
131+
}
Binary file not shown.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
gravity_vector = '0 0 0'
2+
initial_p = 1e5
3+
initial_T = 300
4+
5+
porosity = 0.8
6+
perm = 1e-8 # permeability
7+
rho_matrix = 1000.0
8+
cp_matrix = 500.0
9+
k_matrix = 5.0
10+
11+
inj_point1 = '0.5 0.5 0.5'
12+
pro_point1 = '3.5 1.5 1.5'
13+
14+
[GlobalParams]
15+
PorousFlowDictator = dictator
16+
gravity = ${gravity_vector}
17+
[]
18+
19+
[Mesh]
20+
type = GeneratedMesh
21+
dim = 3
22+
xmax = 4.0
23+
ymax = 3.0
24+
zmax = 2.0
25+
nx = 4
26+
ny = 3
27+
nz = 2
28+
[]
29+
30+
[PorousFlowFullySaturated]
31+
coupling_type = ThermoHydro
32+
porepressure = porepressure
33+
temperature = temperature
34+
fp = fp
35+
pressure_unit = Pa
36+
stabilization = full
37+
[]
38+
39+
[FluidProperties]
40+
[fp]
41+
type = IdealGasFluidProperties
42+
[]
43+
[]
44+
45+
[Variables]
46+
[porepressure]
47+
initial_condition = ${initial_p}
48+
[]
49+
[temperature]
50+
initial_condition = ${initial_T}
51+
scaling = 1e-6
52+
[]
53+
[]
54+
55+
[Materials]
56+
[porosity_mat]
57+
type = PorousFlowPorosityConst
58+
porosity = ${porosity}
59+
[]
60+
[permeability_mat]
61+
type = PorousFlowPermeabilityConst
62+
permeability = '${perm} ${perm} ${perm} ${perm} ${perm} ${perm} ${perm} ${perm} ${perm}'
63+
[]
64+
[matrix_energy_mat]
65+
type = PorousFlowMatrixInternalEnergy
66+
density = ${rho_matrix}
67+
specific_heat_capacity = ${cp_matrix}
68+
[]
69+
[thermal_conductivity_mat]
70+
type = PorousFlowThermalConductivityIdeal
71+
dry_thermal_conductivity = '${k_matrix} 0 0 0 ${k_matrix} 0 0 0 ${k_matrix}'
72+
[]
73+
[]
74+
75+
[Executioner]
76+
type = Transient
77+
78+
end_time = 5.0
79+
dt = 1.0
80+
81+
solve_type = NEWTON
82+
line_search = none
83+
nl_max_its = 20
84+
nl_abs_tol = 1e-5
85+
nl_rel_tol = 1e-5
86+
l_tol = 1e-3
87+
l_max_its = 10
88+
petsc_options_iname = '-pc_type'
89+
petsc_options_value = 'lu'
90+
automatic_scaling = true
91+
[]
92+
93+
[MultiApps]
94+
[sub]
95+
type = TransientMultiApp
96+
app_type = PorousFlowApp
97+
input_files = sub.i
98+
execute_on = 'INITIAL TIMESTEP_END'
99+
[]
100+
[]
101+
102+
[Physics]
103+
[CoupledInjectionProduction]
104+
[inj_prod]
105+
injection_points = '${inj_point1}'
106+
production_points = '${pro_point1}'
107+
multi_app = sub
108+
[]
109+
[]
110+
[]
111+
112+
[Outputs]
113+
exodus = true
114+
[]
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
e_source = 1e5
2+
mass_rate_inj1 = 0.5
3+
energy_rate_inj1 = ${fparse mass_rate_inj1 * e_source}
4+
mass_rate_pro1 = -0.5
5+
energy_rate_pro1 = ${fparse mass_rate_pro1 * e_source}
6+
7+
[Mesh]
8+
type = GeneratedMesh
9+
dim = 1
10+
nx = 1
11+
[]
12+
13+
[Postprocessors]
14+
[mass_rate_inj1]
15+
type = ConstantPostprocessor
16+
value = ${mass_rate_inj1}
17+
[]
18+
[energy_rate_inj1]
19+
type = ConstantPostprocessor
20+
value = ${energy_rate_inj1}
21+
[]
22+
[p_inj1]
23+
type = Receiver
24+
[]
25+
[T_inj1]
26+
type = Receiver
27+
[]
28+
29+
[mass_rate_pro1]
30+
type = ConstantPostprocessor
31+
value = ${mass_rate_pro1}
32+
[]
33+
[energy_rate_pro1]
34+
type = ConstantPostprocessor
35+
value = ${energy_rate_pro1}
36+
[]
37+
[p_pro1]
38+
type = Receiver
39+
[]
40+
[T_pro1]
41+
type = Receiver
42+
[]
43+
[]
44+
45+
[Problem]
46+
solve = false
47+
[]
48+
49+
[Executioner]
50+
type = Transient
51+
end_time = 5.0
52+
dt = 1.0
53+
[]

0 commit comments

Comments
 (0)