Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# CoupledInjectionProduction

This [Physics](syntax/Physics/index.md) object adds dirac kernels for mass and energy
sources at injection and production points within a porous matrix, where the sources
are provided by post-processor values transferred from another application.

This object creates the following post-processors:

- `p_inj1`, ..., `p_inj<n_inj>`: Pressure at each injection point, via [PointValue.md].
- `T_inj1`, ..., `T_inj<n_inj>`: Temperature at each injection point, via [PointValue.md].
- `p_pro1`, ..., `p_pro<n_pro>`: Pressure at each production point, via [PointValue.md].
- `T_pro1`, ..., `T_pro<n_pro>`: Temperature at each production point, via [PointValue.md].
- `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].
- `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].
- `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].
- `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].

`n_inj` is the size of the [!param](/Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics/injection_points) parameter, and
`n_pro` is the size of the [!param](/Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics/production_points) parameter.

If the parameter [!param](/Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics/multi_app)
is provided, then the porous flow app is the main application, and [MultiAppPostprocessorTransfer.md]
objects are created by this object to transfer the post-processors listed above to the sub application;
if the parameter is not provided, then the other application is responsible for creating the transfers.

[PorousFlowPointSourceFromPostprocessor.md] dirac kernels are added for each injection and production point,
using the `mass_rate_*` and `energy_rate_*` post-processors listed above.

!syntax parameters /Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics

!syntax inputs /Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics

!syntax children /Physics/CoupledInjectionProduction/CoupledInjectionProductionPhysics
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//* This file is part of the MOOSE framework
//* https://mooseframework.inl.gov
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "PhysicsBase.h"

/**
* Adds objects to perform hydrodynamic coupling at injection and production points.
*/
class CoupledInjectionProductionPhysics : public PhysicsBase
{
public:
static InputParameters validParams();

CoupledInjectionProductionPhysics(const InputParameters & parameters);

protected:
/// Adds a PorousFlowPointSourceFromPostprocessor
void addPPSourceDiracKernel(const Point & point,
const NonlinearVariableName & var,
const PostprocessorName & pp_name);
/// Adds a Receiver
void addReceiverPostprocessor(const PostprocessorName & pp_name);
/// Adds a PointValue
void addPointValuePostprocessor(const VariableName & var,
const Point & point,
const PostprocessorName & pp_name);
/// Adds a MultiAppPostprocessorTransfer
void addPostprocessorTransfer(const PostprocessorName & pp_name, bool from_multi_app);

/// Injection points
const std::vector<Point> & _injection_points;
/// Production points
const std::vector<Point> & _production_points;

/// Injection and production points
std::vector<Point> _points;
/// Label for each point
std::vector<std::string> _labels;

private:
void addDiracKernels() override;
void addPostprocessors() override;
void addTransfers() override;
};
2 changes: 2 additions & 0 deletions modules/porous_flow/src/base/PorousFlowApp.C
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ PorousFlowApp::registerAll(Factory & f, ActionFactory & af, Syntax & syntax)
Registry::registerObjectsTo(f, {"PorousFlowApp"});
Registry::registerActionsTo(af, {"PorousFlowApp"});

registerSyntax("CoupledInjectionProductionPhysics", "Physics/CoupledInjectionProduction/*");

registerSyntaxTask("PorousFlowUnsaturated", "PorousFlowUnsaturated", "add_user_object");
registerSyntaxTask("PorousFlowUnsaturated", "PorousFlowUnsaturated", "add_kernel");
registerSyntaxTask("PorousFlowUnsaturated", "PorousFlowUnsaturated", "add_material");
Expand Down
131 changes: 131 additions & 0 deletions modules/porous_flow/src/physics/CoupledInjectionProductionPhysics.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//* This file is part of the MOOSE framework
//* https://mooseframework.inl.gov
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "CoupledInjectionProductionPhysics.h"

registerPhysicsBaseTasks("PorousFlowApp", CoupledInjectionProductionPhysics);
registerMooseAction("PorousFlowApp", CoupledInjectionProductionPhysics, "add_dirac_kernel");
registerMooseAction("PorousFlowApp", CoupledInjectionProductionPhysics, "add_postprocessor");
registerMooseAction("PorousFlowApp", CoupledInjectionProductionPhysics, "add_transfer");

InputParameters
CoupledInjectionProductionPhysics::validParams()
{
InputParameters params = PhysicsBase::validParams();

params.addRequiredParam<std::vector<Point>>("injection_points", "List of injection points [m]");
params.addRequiredParam<std::vector<Point>>("production_points", "List of production points [m]");
params.addParam<MultiAppName>("multi_app", "MultiApp to transfer to and from");

params.addClassDescription(
"Adds objects to perform hydrodynamic coupling at injection and production points.");

return params;
}

CoupledInjectionProductionPhysics::CoupledInjectionProductionPhysics(
const InputParameters & parameters)
: PhysicsBase(parameters),
_injection_points(getParam<std::vector<Point>>("injection_points")),
_production_points(getParam<std::vector<Point>>("production_points"))
{
_points = _injection_points;
_points.insert(_points.end(), _production_points.begin(), _production_points.end());

for (const auto i : index_range(_injection_points))
_labels.push_back("inj" + std::to_string(i + 1));
for (const auto i : index_range(_production_points))
_labels.push_back("pro" + std::to_string(i + 1));
}

void
CoupledInjectionProductionPhysics::addDiracKernels()
{
for (const auto i : index_range(_points))
{
addPPSourceDiracKernel(_points[i], "porepressure", "mass_rate_" + _labels[i]);
addPPSourceDiracKernel(_points[i], "temperature", "energy_rate_" + _labels[i]);
}
}

void
CoupledInjectionProductionPhysics::addPostprocessors()
{
for (const auto i : index_range(_points))
{
addPointValuePostprocessor("porepressure", _points[i], "p_" + _labels[i]);
addPointValuePostprocessor("temperature", _points[i], "T_" + _labels[i]);
addReceiverPostprocessor("mass_rate_" + _labels[i]);
addReceiverPostprocessor("energy_rate_" + _labels[i]);
}
}

void
CoupledInjectionProductionPhysics::addTransfers()
{
if (isParamValid("multi_app"))
for (const auto i : index_range(_points))
{
addPostprocessorTransfer("p_" + _labels[i], false);
addPostprocessorTransfer("T_" + _labels[i], false);
addPostprocessorTransfer("mass_rate_" + _labels[i], true);
addPostprocessorTransfer("energy_rate_" + _labels[i], true);
}
}

void
CoupledInjectionProductionPhysics::addPPSourceDiracKernel(const Point & point,
const NonlinearVariableName & var,
const PostprocessorName & pp_name)
{
const std::string class_name = "PorousFlowPointSourceFromPostprocessor";
auto params = _factory.getValidParams(class_name);
params.set<NonlinearVariableName>("variable") = var;
params.set<Point>("point") = point;
params.set<PostprocessorName>("mass_flux") = pp_name;
getProblem().addDiracKernel(class_name, "dirac_" + pp_name, params);
}

void
CoupledInjectionProductionPhysics::addReceiverPostprocessor(const PostprocessorName & pp_name)
{
const std::string class_name = "Receiver";
auto params = _factory.getValidParams(class_name);
getProblem().addPostprocessor(class_name, pp_name, params);
}

void
CoupledInjectionProductionPhysics::addPointValuePostprocessor(const VariableName & var,
const Point & point,
const PostprocessorName & pp_name)
{
const std::string class_name = "PointValue";
auto params = _factory.getValidParams(class_name);
params.set<VariableName>("variable") = var;
params.set<Point>("point") = point;
params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
getProblem().addPostprocessor(class_name, pp_name, params);
}

void
CoupledInjectionProductionPhysics::addPostprocessorTransfer(const PostprocessorName & pp_name,
bool from_multi_app)
{
const std::string class_name = "MultiAppPostprocessorTransfer";
auto params = _factory.getValidParams(class_name);
if (from_multi_app)
params.set<MultiAppName>("from_multi_app") = getParam<MultiAppName>("multi_app");
else
params.set<MultiAppName>("to_multi_app") = getParam<MultiAppName>("multi_app");
params.set<PostprocessorName>("from_postprocessor") = pp_name;
params.set<PostprocessorName>("to_postprocessor") = pp_name;
params.set<MooseEnum>("reduction_type") = "average";
params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
getProblem().addTransfer(class_name, pp_name + "_transfer", params);
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
gravity_vector = '0 0 0'
initial_p = 1e5
initial_T = 300

porosity = 0.8
perm = 1e-8 # permeability
rho_matrix = 1000.0
cp_matrix = 500.0
k_matrix = 5.0

inj_point1 = '0.5 0.5 0.5'
pro_point1 = '3.5 1.5 1.5'

[GlobalParams]
PorousFlowDictator = dictator
gravity = ${gravity_vector}
[]

[Mesh]
type = GeneratedMesh
dim = 3
xmax = 4.0
ymax = 3.0
zmax = 2.0
nx = 4
ny = 3
nz = 2
[]

[PorousFlowFullySaturated]
coupling_type = ThermoHydro
porepressure = porepressure
temperature = temperature
fp = fp
pressure_unit = Pa
stabilization = full
[]

[FluidProperties]
[fp]
type = IdealGasFluidProperties
[]
[]

[Variables]
[porepressure]
initial_condition = ${initial_p}
[]
[temperature]
initial_condition = ${initial_T}
scaling = 1e-6
[]
[]

[Materials]
[porosity_mat]
type = PorousFlowPorosityConst
porosity = ${porosity}
[]
[permeability_mat]
type = PorousFlowPermeabilityConst
permeability = '${perm} ${perm} ${perm} ${perm} ${perm} ${perm} ${perm} ${perm} ${perm}'
[]
[matrix_energy_mat]
type = PorousFlowMatrixInternalEnergy
density = ${rho_matrix}
specific_heat_capacity = ${cp_matrix}
[]
[thermal_conductivity_mat]
type = PorousFlowThermalConductivityIdeal
dry_thermal_conductivity = '${k_matrix} 0 0 0 ${k_matrix} 0 0 0 ${k_matrix}'
[]
[]

[Executioner]
type = Transient

end_time = 5.0
dt = 1.0

solve_type = NEWTON
line_search = none
nl_max_its = 20
nl_abs_tol = 1e-5
nl_rel_tol = 1e-5
l_tol = 1e-3
l_max_its = 10
petsc_options_iname = '-pc_type'
petsc_options_value = 'lu'
automatic_scaling = true
[]

[MultiApps]
[sub]
type = TransientMultiApp
app_type = PorousFlowApp
input_files = sub.i
execute_on = 'INITIAL TIMESTEP_END'
[]
[]

[Physics]
[CoupledInjectionProduction]
[inj_prod]
injection_points = '${inj_point1}'
production_points = '${pro_point1}'
multi_app = sub
[]
[]
[]

[Outputs]
exodus = true
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
e_source = 1e5
mass_rate_inj1 = 0.5
energy_rate_inj1 = ${fparse mass_rate_inj1 * e_source}
mass_rate_pro1 = -0.5
energy_rate_pro1 = ${fparse mass_rate_pro1 * e_source}

[Mesh]
type = GeneratedMesh
dim = 1
nx = 1
[]

[Postprocessors]
[mass_rate_inj1]
type = ConstantPostprocessor
value = ${mass_rate_inj1}
[]
[energy_rate_inj1]
type = ConstantPostprocessor
value = ${energy_rate_inj1}
[]
[p_inj1]
type = Receiver
[]
[T_inj1]
type = Receiver
[]

[mass_rate_pro1]
type = ConstantPostprocessor
value = ${mass_rate_pro1}
[]
[energy_rate_pro1]
type = ConstantPostprocessor
value = ${energy_rate_pro1}
[]
[p_pro1]
type = Receiver
[]
[T_pro1]
type = Receiver
[]
[]

[Problem]
solve = false
[]

[Executioner]
type = Transient
end_time = 5.0
dt = 1.0
[]
Loading