New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create reactive fluid transport material model #5245
Create reactive fluid transport material model #5245
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! I have looked through your PR and had some smaller comments, and I also think it would be good if you could reorder the functions. Usually, all material models have the same order of the functions (for example, the last 4 are always evaluate(), declare_parameters(), parse_parameters(), and create_additional_named_outputs()). Have a look at the other melt material models for the right order.
Maybe it would also be good if someone else could have a look (just to comment on if the general idea of this makes sense since it duplicates some code).
// the melt (fluid) fraction at any point is thus equal to the | ||
// porosity, which is determined by the assigned initial porosity, | ||
// fluid boundary conditions, and fluid transport through the model. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure that this is true. If there is bound water, the total fluid fraction would not equal the porosity.
The free fluid fraction is equal to the porosity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I've modified the documentation and code accordingly.
tests/reactive_fluid_transport.prm
Outdated
@@ -0,0 +1,155 @@ | |||
# This is a 1D test case for an insoluble fluid moving upwards in a | |||
# narrow channel through porous coupled two-phase flow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tester says: "test reactive_fluid_transport.prm is missing a folder with reference data"
tests/reactive_fluid_transport.prm
Outdated
# This is a 1D test case for an insoluble fluid moving upwards in a | ||
# narrow channel through porous coupled two-phase flow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be more correct
# This is a 1D test case for an insoluble fluid moving upwards in a | |
# narrow channel through porous coupled two-phase flow. | |
# This is a 1D test case for a fluid moving upwards in a narrow channel | |
#through porous coupled two-phase flow without reacting with the solid rock. |
tests/reactive_fluid_transport.prm
Outdated
# We use a custom material model that implements the layers with | ||
# different solubility. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is outdated
tests/reactive_fluid_transport.prm
Outdated
set Reference fluid viscosity = 10 | ||
set Reference permeability = 2.5e-6 | ||
set Exponential fluid weakening factor = 0 | ||
set Fluid reaction time scale for operator splitting = 5e4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But operator splitting is not used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, removed
3d5b8ae
to
1fdafa8
Compare
@jdannberg - Thanks for the initial comments and suggestions, which I've addressed aside from the reordering the functions. I'll do the reordering next, finish the test case, and then add in a structure for specifying what reaction model to use. After that, a look from a second reviewer would be ideal. |
@jdannberg @ryanstoner1 @danieldouglas92 - The functions have been re-ordered, a switch case is available for implementing different reaction schemes (current option is no reaction) and the test results have been added. It is probably ready for another round of reviews? @bobmyhill - Would you be willing to take a look? |
/rebuild |
Topics for discussion when reviewing:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@naliboff Some comments about settling on the semantics. Take them of leave them. Perhaps we can discuss some when we talk. Also, it might be good to go over how to best make this extensible if new users have their own reaction formulation.
case no_reaction: | ||
{ | ||
// A fluid-rock reaction model where no reactions occur. | ||
// The melt (fluid) fraction at any point is equal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps specify this to make a bit more transparent?
// The melt (fluid) fraction at any point is equal | |
// The melt (fluid) fraction (volume percent) at any point is equal |
// Modify the viscosity from the base model based on the presence of fluid. | ||
const unsigned int porosity_idx = this->introspection().compositional_index_for_name("porosity"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Modify the viscosity from the base model based on the presence of fluid. | |
const unsigned int porosity_idx = this->introspection().compositional_index_for_name("porosity"); | |
const unsigned int porosity_idx = this->introspection().compositional_index_for_name("porosity"); | |
// Modify the viscosity from the base model based on the presence of fluid. | |
const double phi_0 = 0.05; | ||
porosity = std::max(porosity,1e-8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment could be nice here.
{ | ||
prm.declare_entry("Base model","visco plastic", | ||
Patterns::Selection(MaterialModel::get_valid_model_names_pattern<dim>()), | ||
"The name of a material model that will be modified by the " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"The name of a material model that will be modified by the " | |
"The name of a material model incorporating the " |
Clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I talked to @jdannberg and the general approach makes sense. Go ahead and address the comments.
0147f46
to
4a69158
Compare
4a69158
to
5e5bd1c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! The structure looks good now, but I think the implementation requires some changes. Most importantly, think about if you actually want no reactions, a zero solubility, or both.
@@ -0,0 +1,8 @@ | |||
New: There is now a new material ('reactive fluid | |||
transport') that is designed to advect fluids and | |||
compute luid release and absorption based on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compute luid release and absorption based on | |
compute fluid release and absorption based on |
@@ -0,0 +1,8 @@ | |||
New: There is now a new material ('reactive fluid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New: There is now a new material ('reactive fluid | |
New: There is now a new material model ('reactive fluid |
transport') that is designed to advect fluids and | ||
compute luid release and absorption based on | ||
different models for fluid-rock interaction. The | ||
that properties of the solid are taken from a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that properties of the solid are taken from a | |
properties of the solid are taken from a |
double fluid_reaction_time_scale; | ||
|
||
/** | ||
* Enumeration for selecting which type of scheme to use for reactions between. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Enumeration for selecting which type of scheme to use for reactions between. | |
* Enumeration for selecting which type of scheme to use for reactions between |
{ | ||
// A fluid-rock reaction model where no reactions occur. | ||
// The melt (fluid) fraction (volume percent) at any point is | ||
// equal to the sume of the bound fluid content and porosity, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// equal to the sume of the bound fluid content and porosity, | |
// equal to the sum of the bound fluid content and porosity, |
*/ | ||
enum ReactionScheme | ||
{ | ||
no_reaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above
"computed. If the model does not use operator splitting, this parameter is not used. " | ||
"Units: yr or s, depending on the ``Use years " | ||
"in output instead of seconds'' parameter."); | ||
prm.declare_entry ("Fluid solid reaction scheme", "no reaction", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would prefer this with a dash
prm.declare_entry ("Fluid solid reaction scheme", "no reaction", | |
prm.declare_entry ("Fluid-solid reaction scheme", "no reaction", |
|
||
|
||
Postprocessing: | ||
Compositions min/max/mass: -5.788e-07/0.11/5159 // 0/0/0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure this is working as intended? Shouldn't the fluid be released, i.e. the porosity should increase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, good catch! The initial assignment of values (porosity, bound_fluid) was reversed.
for (unsigned int q=0; q<out.n_evaluation_points(); ++q) | ||
for (unsigned int c=0; c<in.composition[q].size(); ++c) | ||
{ | ||
double porosity_change = eq_free_fluid_fractions[q] - in.composition[q][porosity_idx]; | ||
// do not allow negative porosity | ||
if (in.composition[q][porosity_idx] + porosity_change < 0) | ||
porosity_change = -in.composition[q][porosity_idx]; | ||
|
||
if (c == bound_fluid_idx && this->get_timestep_number() > 0) | ||
reaction_rate_out->reaction_rates[q][c] = - porosity_change / fluid_reaction_time_scale; | ||
else if (c == porosity_idx && this->get_timestep_number() > 0) | ||
reaction_rate_out->reaction_rates[q][c] = porosity_change / fluid_reaction_time_scale; | ||
else | ||
reaction_rate_out->reaction_rates[q][c] = 0.0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only works if you use operator splitting in your model. So (1), please document that, and (2) change your test to actually use operator splitting (because at the moment, it does not test this implementation because it does not use the reaction rates).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on what part of the code needs additional documentation for the operator splitting? There is some documentation at the top on this above the following if statement (if (this->get_parameters().use_operator_splitting && reaction_rate_out != nullptr)
), but happy to more in an additional location.
The test has been updated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just having the assert is fine!
set End time = 1e1 | ||
|
||
|
||
set Use operator splitting = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to use operator splitting for your reactions to work.
bc91b01
to
2d54a9f
Compare
2d54a9f
to
ce8be6f
Compare
60310f6
to
71a5a05
Compare
@jdannberg - Thanks for the thorough review! I've hopefully addressed most of the comments, and I think this is ready for another review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only have a few minor comments, otherwise this looks good!
* model is thus assuming that the bound water fraction is a | ||
* volume fraction (i.e., since porosity is always a volume | ||
* fraction). This latter assumption also requires the selected | ||
* base model is incompressible, as otherwise the advection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* base model is incompressible, as otherwise the advection | |
* base model to be incompressible, as otherwise the advection |
# there is no need to use operator splitting. | ||
set Use operator splitting = false | ||
|
||
# Mellt transport is turned on to ensure it works |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Mellt transport is turned on to ensure it works | |
# Melt transport is turned on to ensure it works |
set Reference fluid viscosity = 10 | ||
set Reference permeability = 2.5e-6 | ||
set Exponential fluid weakening factor = 0 | ||
set Fluid-solid reaction scheme = zero solubility |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be no reaction?
You switch the operator splitting off, so technically, this should give you the correct result, but I find it to be confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see it actually does not work because
Exception 'ExcMessage("The Fluid-reaction scheme zero solubility must be used with operator splitting.")'
:-)
@@ -0,0 +1,161 @@ | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remove this empty line?
# This model tests the reactive fluid transport material | ||
# 'no reaction' scenario to ensure that there is no reaction | ||
# between the fluid and solid phases. The values of | ||
# porosity (0) and the bound fluid (0.01) are initially | ||
# spatially uniform. The absence of reactions between | ||
# the two phases and near zero velocities (free-slip on | ||
# all sides) produces no change in their values through time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very similar to the zero solubility test below. Can you include the other test here with
include $ASPECT_SOURCE_DIR/tests/reactive_fluid_transport_zero_solubility.prm
and the only list the parameters that are different? This way you do not have to duplicate everything.
Compositions min/max/mass: 0.01/0.01/4e+04 // 0/0/0 | ||
Melt fraction min/total/max: 0.01, 4e+04, 0.01 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shows nicely that it worked!
for (unsigned int q=0; q<out.n_evaluation_points(); ++q) | ||
for (unsigned int c=0; c<in.composition[q].size(); ++c) | ||
{ | ||
double porosity_change = eq_free_fluid_fractions[q] - in.composition[q][porosity_idx]; | ||
// do not allow negative porosity | ||
if (in.composition[q][porosity_idx] + porosity_change < 0) | ||
porosity_change = -in.composition[q][porosity_idx]; | ||
|
||
if (c == bound_fluid_idx && this->get_timestep_number() > 0) | ||
reaction_rate_out->reaction_rates[q][c] = - porosity_change / fluid_reaction_time_scale; | ||
else if (c == porosity_idx && this->get_timestep_number() > 0) | ||
reaction_rate_out->reaction_rates[q][c] = porosity_change / fluid_reaction_time_scale; | ||
else | ||
reaction_rate_out->reaction_rates[q][c] = 0.0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just having the assert is fine!
{ | ||
AssertThrow(fluid_reaction_time_scale >= this->get_parameters().reaction_time_step, | ||
ExcMessage("The reaction time step " + Utilities::to_string(this->get_parameters().reaction_time_step) | ||
+ " in the operator splitting scheme is too large to compute melting rates! " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+ " in the operator splitting scheme is too large to compute melting rates! " | |
+ " in the operator splitting scheme is too large to compute fluid release rates! " |
AssertThrow(fluid_reaction_time_scale >= this->get_parameters().reaction_time_step, | ||
ExcMessage("The reaction time step " + Utilities::to_string(this->get_parameters().reaction_time_step) | ||
+ " in the operator splitting scheme is too large to compute melting rates! " | ||
"You have to choose it in such a way that it is smaller than the 'Melting time scale for " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"You have to choose it in such a way that it is smaller than the 'Melting time scale for " | |
"You have to choose it in such a way that it is smaller than the 'Fluid reaction time scale for " |
AssertThrow(this->get_material_model().is_compressible() == false, | ||
ExcMessage("The Fluid-reaction scheme zero solubility must be used with an incompressible base model.")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not work well for all models, since at this point we have not parsed the parameters from the base model. So if the base model has a compressibility that depends on an input parameter, at this point in the code we will not know about it. It would be better to move this after parsing the parameters from the base model or ito the initialize() function.
@jdannberg - Thanks for the last round of edits! I addressed all of the comments, but there is still a bug I am tracking down so not ready to merge yet. |
@jdannberg - I think this is ready to merged! |
This looks good to me now! The only other comment I have is that this also does not create the additional material model outputs the base model has (which I fixed for the prescribed viscosity and depth dependent model here #5547). But that could be addressed in a follow-up PR. And sorry this took me so long to look at! |
A draft material model, which composites on top of existing material models for solid deformation to also simulate reactive fluid transport. This is based on the contribution from #5214 and discussions with @jdannberg, @danieldouglas92, and @ryanstoner1.
The material is a work in progress and the PR was created to facilitate discussion. At present, the only option is to simulate non-reactive (insoluble) fluid flow, but the idea is to maintain a flexible structure and allow users to use add additional petrologic models of varying complexity.
For new features/models or changes of existing features: