Introduction
The Hydrogeology module of code_saturne is a numerical model for groundwater flow and solute transport in continuous porous media. The flow part is based on the Richards equation, derived from the Darcy law and the conservation of the mass of water in the soil. The transport part is based on the the classical advection-diffusion equation of tracers, slightly modified to take into account the specificities of groundwater transport.
This module can be used to simulate transfers of water and solutes in several saturated and/or unsaturated porous media. The flow part can be steady or unsteady, with isotropic or anisotropic soil permeabilities and allows for any type of soil water retention model thanks to a user-defined model. Two classical models are predefined: the saturated model and the van Genuchten-Mualen model. The transport part considers dispersion, sorption and radioactive decay in the case of a radioactive tracer. The sorption between soil and water phases is modeled by the classical Kd approach model. Additionaly solute precipitation/dissolution phenomena can also be taken into account by an instantaneous model.
Physical concepts and equations are presented in the theory guide
The groundwater flow module (GWF) relies on CDO vertex-based or CDO vertex+cell-based discretization schemes. Here is listed a set of references useful for the reader willing to get a better understanding of the mathematical concepts underpinning CDO schemes.
To set-up a GWF computation, one has to update the cs_user_parameters.c file and edit the function cs_user_model at least in simple cases. In more complex cases, editing cs_user_finalize_setup should be necessary.
Activate the GWF module
The first step is to activate the CDO module in the function cs_user_model (please refer to Activation of CDO/HHO schemes).
Then, one has to activate the groundwater flow (GWF) module in the function cs_user_model. The function to call is cs_gwf_activate.
There are three parameters:
- The main hydraulic model to consider (i.e. which equations have to be solved). Please refer to cs_gwf_model_type_t. There are currently two models available :
- An optional flag to specify a physical phenomena to take into account or to specify a numerical treatment to apply. If no option is needed, then simply set 0. Here are listed the available option flags:
- An optional flag to specify the activation of automatic postprocessing for quantities of interest related to groundwater flows. Set 0 if no additional postprocessing is requested. Here are listed the available options:
Remark: If a CS_GWF_MODEL_SATURATED_SINGLE_PHASE is set at the activation step, then one expects that all soil models are defined by the type CS_GWF_SOIL_SATURATED
Examples of activation of the GWF module
Example 1: Activate the GWF model with a fully saturated single-phase flow model and no other option.
{
option_flag, post_flag);
}
unsigned short int cs_flag_t
Definition: cs_defs.h:321
cs_gwf_t * cs_gwf_activate(cs_gwf_model_type_t model, cs_flag_t option_flag, cs_flag_t post_flag)
Initialize the module dedicated to groundwater flows.
Definition: cs_gwf.c:3276
@ CS_GWF_MODEL_SATURATED_SINGLE_PHASE
Single phase (liquid phase) modelling in a porous media.
Definition: cs_gwf_param.h:129
Example 2: Second example: Activate the GWF model with an unsaturated single-phase flow model without any additional option.
0,
#define CS_GWF_POST_PERMEABILITY
Activate the post-processing of the permeability field.
Definition: cs_gwf_param.h:80
@ CS_GWF_MODEL_UNSATURATED_SINGLE_PHASE
Single phase (liquid phase) modelling in a porous media.
Definition: cs_gwf_param.h:143
Example 3: Activate the GWF model with an unsaturated single-phase flow model. Moreover, one takes into account the gravity effect and the postprocessing of the soil permeability as well as the Darcy flux across domain boundaries.
{
}
#define CS_GWF_POST_DARCY_FLUX_BALANCE
Compute the overall balance at the different boundaries of the Darcy flux.
Definition: cs_gwf_param.h:81
@ CS_GWF_GRAVITATION
Definition: cs_gwf_param.h:192
Soils
The second step is to add at least one new soil. The add of soil(s) should be done before adding tracers inside the function cs_user_model and after having activated the GWF module. Two functions are available to add a new soil:
- cs_gwf_add_iso_soil when the soil is modelled by an isotropic absolute (or intrinsic) permeability
- cs_gwf_add_aniso_soil when the soil is modelled by an anisotropic absolute (or intrinsic) permeability (i.e. one has to specific a 3x3 tensor)
These two functions have a similar set of parameters:
- The name of the volume zone associated to this soil (to add a volume, one can either use the GUI or use cs_volume_zone_define inside cs_user_zones ; see Simple volume zone example for more details)
- The value of the bulk mass density of the soil. This is only useful when a tracer is considered. If there is no tracer, one can set
1
for instance.
- The value of the absolute permeability. In case of an isotropic soil, this is a scalar and in case of an anisotropic soil, one expects a tensor.
- The value of the soil porosity (which is equivalent to the saturated moisture or the max. liquid saturation in single-phase flows)
- The type of soil model. There are two predefined soil models and one user-defined soil model
Examples of settings for a predefined soil model
Case of a saturated model
The saturated model is the simplest model.
Example 1: A saturated soils defined by an isotropic permeability on all the computational domain.
{
const double iso_val = 1e-10;
const double theta_s = 0.85;
}
double cs_real_t
Floating-point value.
Definition: cs_defs.h:319
cs_gwf_soil_t * cs_gwf_add_iso_soil(const char *z_name, double density, double k_abs, double porosity, cs_gwf_soil_model_t model)
Create and add a new cs_gwf_soil_t structure. An initialization by default of all members is performe...
Definition: cs_gwf.c:3748
@ CS_GWF_SOIL_SATURATED
Definition: cs_gwf_param.h:259
Example 2: Two saturated soils defined by an anisotropic (saturated) permeability
{
double aniso_val1[3][3] = {{1e-3, 0, 0},
{ 0, 1, 0},
{ 0, 0, 1e-1}};
double aniso_val2[3][3] = {{1e-5, 0, 0},
{ 0, 1, 0},
{ 0, 0, 1e-2}};
const double theta_s = 1;
const double bulk_density = 1.0;
}
cs_gwf_soil_t * cs_gwf_add_aniso_soil(const char *z_name, double density, double k_abs[3][3], double porosity, cs_gwf_soil_model_t model)
Create and add a new cs_gwf_soil_t structure. An initialization by default of all members is performe...
Definition: cs_gwf.c:3800
Case of a Van Genuchten-Mualen model
Soils which behave according to a Van Genuchten-Mualen model are specified in two steps: a call to cs_gwf_add_iso_soil and then a call to cs_gwf_soil_set_genuchten_param to specifiy the parameters associated to this model.
Example 3: Soil relying on a Van Genuchten-Mualen and considering a isotropic permeability
{
1800,
3e-1,
0.9,
0.078,
0.036,
1.56,
0.5);
}
@ CS_GWF_SOIL_GENUCHTEN
Definition: cs_gwf_param.h:258
void cs_gwf_soil_set_genuchten_param(cs_gwf_soil_t *soil, double theta_r, double alpha, double n, double L)
Set a soil defined by a Van Genuchten-Mualen model.
Definition: cs_gwf_soil.c:859
Example of settings for a user-defined soil
If the predefined models are not sufficient, it is possible to add a user-defined soil. In this case, the add of the new soil is made as follows
- Define a structure to get an access to the parameters defining the soil model
- Add a new soil (cs_gwf_add_iso_soil or cs_gwf_add_aniso_soil )
- Call cs_gwf_soil_set_user to specify the structure to use, the function to update quantities related to the hydraulic model and if needed a function to free the structure storing the soil parameters.
These three steps are performed inside the function cs_user_model
Here is a complete example of a user-defined soil model (called hereafter Tracy since it has been designed by F. T. Tracy in this article).
Define a structure to store the model parameters
Example of the structure used to handle the soil model parameters
typedef struct {
double L;
double h_s;
double h_r;
double theta_r;
double theta_s;
} cs_tracy_param_t;
Add a user-defined soil
cs_gwf_soil_t *s =
1.0,
1.15741e-4,
0.45,
cs_tracy_param_t *tp = NULL;
tp->L = 200;
tp->h_s = 0.;
tp->h_r = -100;
tp->theta_r = 0.15;
tp,
tracy_update,
tracy_free_param);
#define BFT_MALLOC(_ptr, _ni, _type)
Allocate memory for _ni elements of type _type.
Definition: bft_mem.h:62
@ CS_GWF_SOIL_USER
Definition: cs_gwf_param.h:260
void cs_gwf_soil_set_user(cs_gwf_soil_t *soil, void *param, cs_gwf_soil_update_t *update_func, cs_gwf_soil_free_param_t *free_param_func)
Set a soil defined by a user-defined model.
Definition: cs_gwf_soil.c:902
with the two requested functions (defined for instance as a static function in the file cs_user_parameters.c). These functions have to fullfill the prototype defined in cs_gwf_soil_update_t (for the update of the soil properties) and in cs_gwf_soil_free_param_t (for the free of the soil parameter structure).
Here is an example of how to update soil properties (function called tracy_update)
static void
cs_gwf_soil_t *soil)
{
const cs_tracy_param_t *sp = (cs_tracy_param_t *)soil->model_param;
const double delta_m = soil->porosity - sp->theta_r;
const double k_s = soil->abs_permeability[0][0];
cs_real_t *permeability = hc->permeability_field->val;
cs_real_t *moisture = hc->moisture_field->val;
cs_real_t *capacity = hc->capacity_field->val;
const cs_real_t k_r = (
h - sp->h_r)/(sp->h_s - sp->h_r);
permeability[c_id] = k_s * k_r;
moisture[c_id] = sp->theta_r + k_r * delta_m;
capacity[c_id] = delta_m /(sp->h_s - sp->h_r);
}
}
#define CS_UNUSED(x)
Definition: cs_defs.h:495
int cs_lnum_t
local mesh entity id
Definition: cs_defs.h:313
@ h
Definition: cs_field_pointer.h:91
Definition: cs_cdo_connect.h:61
Definition: cs_cdo_quantities.h:137
Structure to handle the modelling of a single-phase flows in a porous media considered as saturated o...
Definition: cs_gwf_priv.h:198
cs_real_t * head_in_law
Definition: cs_gwf_priv.h:287
const cs_lnum_t * elt_ids
Definition: cs_zone.h:65
cs_lnum_t n_elts
Definition: cs_zone.h:64
and an example of how to free the soil parameter structure (function called tracy_free_param)
static void
tracy_free_param(void **p_soil_param)
{
cs_tracy_param_t *sp = (cs_tracy_param_t *)(*p_soil_param);
*p_soil_param = NULL;
}
#define BFT_FREE(_ptr)
Free allocated memory.
Definition: bft_mem.h:101
Further settings (initial and boundary conditions)
In this example, we also give some highlights on how this soil structure can be used to further set the problem for instance to specify the initial and boundary conditions. This step is made in the function cs_user_finalize_setup
cs_tracy_param_t *tp = soil->model_param;
"left",
get_bc,
soil);
"right",
&(tp->h_r));
NULL,
get_ic,
tp);
cs_equation_param_t * cs_equation_param_by_name(const char *eqname)
Return the cs_equation_param_t structure associated to a cs_equation_t structure based on the equatio...
Definition: cs_equation.c:570
cs_xdef_t * cs_equation_add_ic_by_analytic(cs_equation_param_t *eqp, const char *z_name, cs_analytic_func_t *analytic, void *input)
Define the initial condition for the unknown related to this equation. This definition applies to a v...
Definition: cs_equation_param.c:2391
cs_xdef_t * cs_equation_add_bc_by_analytic(cs_equation_param_t *eqp, const cs_param_bc_type_t bc_type, const char *z_name, cs_analytic_func_t *analytic, void *input)
Define and initialize a new structure to set a boundary condition related to the given equation param...
Definition: cs_equation_param.c:2765
cs_xdef_t * cs_equation_add_bc_by_value(cs_equation_param_t *eqp, const cs_param_bc_type_t bc_type, const char *z_name, cs_real_t *values)
Define and initialize a new structure to set a boundary condition related to the given equation struc...
Definition: cs_equation_param.c:2524
cs_gwf_soil_t * cs_gwf_soil_by_name(const char *name)
Retrieve a soil structure from its name.
Definition: cs_gwf_soil.c:276
@ CS_PARAM_BC_DIRICHLET
Definition: cs_param_types.h:478
Set of parameters to handle an unsteady convection-diffusion-reaction equation with term sources.
Definition: cs_equation_param.h:192
where the two functions used to define either the boundary condition (called "get_bc") in the example or the initial condition (called "get_ic") in the example follow a predefined prototype (see cs_analytic_func_t)
Here are collected two examples of such functions:
static void
bool dense_output,
void *input,
{
const cs_gwf_soil_t *soil = input;
assert(soil != NULL);
const cs_tracy_param_t *tp = soil->model_param;
assert(tp != NULL);
const double overL = 1./tp->L;
const double dtheta = soil->porosity - tp->theta_r;
const double td =
-5 * tp->L * tp->L * dtheta /( 6 * tp->h_r * soil->abs_permeability[0][0] );
const double alpha = 6 - 5*time/td;
const double xll = (xyz[3*id] - tp->L)*overL,
beta = xll*xll;
}
}
@ p
Definition: cs_field_pointer.h:67
double precision, dimension(ncharm), save alpha
Definition: cpincl.f90:99
double precision, dimension(ncharm), save beta
Definition: cpincl.f90:99
static void
bool dense_output,
void *input,
{
cs_tracy_param_t *tp = input;
assert(input != NULL);
const double one6 = 1./6;
const double x = xyz[3*id], xll = (x - tp->L)/tp->L;
retval[r_id] = tp->h_r*(1-one6*xll*xll);
}
}
Tracers
The third step (which is not mandatory) is to add tracer(s). There are several ways to add a tracer or a set of tracers. All tracers will be advected by the Darcy flux arising from the Richards equation. There are currently two main models available which is specified with a parameter when adding a tracer:
- a standard model (the default one) which can be upgraded with the following tag:
- a user-defined model which is automatically associated to the tag CS_GWF_TRACER_USER
According to the type of tracer at stake, the following functions can be used to add tracers:
Predefined tracers
Here is a simple example for a standard tracer which can be added in the function cs_user_model
{
model,
"Tracer_01",
"C");
NULL,
0.,
1., 0.,
1e-4);
}
cs_gwf_tracer_t * cs_gwf_add_tracer(cs_gwf_tracer_model_t tr_model, const char *eq_name, const char *var_name)
Add a new equation related to the groundwater flow module.
Definition: cs_gwf.c:3855
cs_flag_t cs_gwf_tracer_model_t
Definition: cs_gwf_param.h:272
void cs_gwf_tracer_set_soil_param(cs_gwf_tracer_t *tracer, const char *soil_name, double wmd, double alpha_l, double alpha_t, double distrib_coef)
Set the main parameters corresponding to a default modelling of a tracer transport equation for a spe...
Definition: cs_gwf_tracer.c:2213
Set of parameters describing a tracer structure.
Here is another example for a radioactive tracer taking into account precipitation effects. The two types of definition can be mixed in the same setting.
{
model,
"Tracer",
"C",
0.01);
NULL,
0.,
1., 0.,
1e-4);
NULL,
1e-4);
}
cs_gwf_tracer_t * cs_gwf_add_radioactive_tracer(cs_gwf_tracer_model_t tr_model, const char *eq_name, const char *var_name, double lambda)
Add a new equation related to the groundwater flow module.
Definition: cs_gwf.c:3921
@ CS_GWF_TRACER_PRECIPITATION
Add the precipitation phenomena to the default tracer equation.
Definition: cs_gwf_param.h:321
void cs_gwf_tracer_set_precip_param(cs_gwf_tracer_t *tracer, const char *soil_name, double conc_l_star)
For a specified soil set the parameters corresponding to a precipitation modelling of a tracer transp...
Definition: cs_gwf_tracer.c:2276
Remark: Get a tracer structure.
{
}
cs_gwf_tracer_t * cs_gwf_tracer_by_name(const char *eq_name)
Retrieve the pointer to the cs_gwf_tracer_t structure associated to the name given as parameter.
Definition: cs_gwf_tracer.c:2014
Decay chain
A decay chain is a set of radioactive tracer equations which are linked. This link is expressed through a source term which is automatically defined. The order in the chain corresponds to the order in which the array of variables is given. According to the type of unit used to express the quantity of tracer in the soil (Becquerel or mole), the source term is modified.
The two possibilities for the unit associated to a tracer is:
Here is a complete example to define the physical parameters associated to a decay chain
{
int n_tracers = 3;
const char *species_names[3] = {"grandfather", "father", "son"};
double decay_rates[3] = {1e-3, 1e-5, 1e-4};
"my_decay_chain",
species_names,
models,
decay_rates);
const char *soil_names[2] = {"soil1", "soil2"};
const double kd_values[2][3] = {{1e-3, 5e-3, 4e-5},
{1e-3, 1e-3, 1e-5}};
for (int is = 0; is < 2; is++)
soil_names[is],
0.,
1., 0.,
kd_values[is][i]);
NULL,
1e-4);
}
}
cs_gwf_tracer_decay_chain_t * cs_gwf_add_decay_chain(int n_tracers, cs_gwf_tracer_unit_t unit, const char *chain_name, const char *var_names[], cs_gwf_tracer_model_t models[], double lambda_vals[])
Add a set of tracer equations corresponding to a radioactive decay chain in the groundwater flow modu...
Definition: cs_gwf.c:4040
@ CS_GWF_TRACER_UNIT_MOLE
Definition: cs_gwf_param.h:105
Definition: cs_gwf_tracer.h:162
cs_gwf_tracer_t ** tracers
Definition: cs_gwf_tracer.h:173
int n_tracers
Definition: cs_gwf_tracer.h:167
It is possible to retrieve the structure associated to a decay chain in another user-defined function such as cs_user_parameters thanks to its name and perform additional settings as follows:
{
assert(tdc != NULL);
for (
int it = 0; it < tdc->
n_tracers; it++) {
}
}
static void cs_equation_set_param(cs_equation_param_t *eqp, cs_equation_key_t key, const char *keyval)
Set a parameter attached to a keyname in a cs_equation_param_t structure.
Definition: cs_equation_param.h:1710
@ CS_EQKEY_SLES_VERBOSITY
Definition: cs_equation_param.h:1244
cs_equation_param_t * cs_gwf_tracer_decay_chain_get_equation_param(cs_gwf_tracer_decay_chain_t *tdc, int id)
Retrieve the equation parameters for the tracer at the position "id" in the decay chain structure....
Definition: cs_gwf_tracer.c:3358
cs_gwf_tracer_decay_chain_t * cs_gwf_tracer_decay_chain_by_name(const char *chain_name)
Retrieve the decay chain structure associated to the name given as parameter. If not found,...
Definition: cs_gwf_tracer.c:3258
User-defined tracers
To be done.
Automatic postprocessings
It is possible to activate or add an automatic post-processing of several quantities of interest related to groundwater flows. Here are available flags to activate through the usage of cs_gwf_set_post_options
false);
void cs_gwf_set_post_options(cs_flag_t post_flag, bool reset)
Set the flag dedicated to the post-processing of the GWF module.
Definition: cs_gwf.c:3677
#define CS_GWF_POST_DARCY_FLUX_AT_BOUNDARY
Define a field at boundary faces for the Darcy flux and activate the post-processing.
Definition: cs_gwf_param.h:83
#define CS_GWF_POST_DARCY_FLUX_DIVERGENCE
Compute in each control volume (vertices or cells w.r.t the space scheme) the divergence of the Darcy...
Definition: cs_gwf_param.h:82
Helper functions
Helper functions for soils
Get a soil structure from its name.
There is a similar which retrieve the soil structure from its id (see cs_gwf_soil_by_id).
Helper functions for tracers
Get a tracer structure from its name.