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 mass. The transport part is based on the the classical advection-diffusion equation of tracers, slightly modified to 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 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. The partition between soil and water phases can be modeled by a 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:2975
@ CS_GWF_MODEL_SATURATED_SINGLE_PHASE
Single phase (liquid phase) modelling in a porous media.
Definition: cs_gwf_param.h:113
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:127
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:176
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:3439
@ CS_GWF_SOIL_SATURATED
Definition: cs_gwf_param.h:243
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:3491
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:242
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:744
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:244
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:787
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:493
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:132
Structure to handle the modelling of a single-phase flows in a porous media considered as saturated o...
Definition: cs_gwf_priv.h:161
cs_real_t * head_in_law
Definition: cs_gwf_priv.h:250
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:572
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:2207
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:2568
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:2340
cs_gwf_soil_t * cs_gwf_soil_by_name(const char *name)
Retrieve a soil structure from its name.
Definition: cs_gwf_soil.c:269
@ CS_PARAM_BC_DIRICHLET
Definition: cs_param_types.h:473
Set of parameters to handle an unsteady convection-diffusion-reaction equation with term sources.
Definition: cs_equation_param.h:186
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);
}
}
Tacers
The third step (which is not mandatory) is to add tracer(s) thanks to the function cs_gwf_add_tracer This tracer will be advected by the Darcy flux arising from the Richards equation.
There are currently two models :
- a default model (the predefined one; see cs_gwf_cdo_predef_tracer)
- a user-defined model (see cs_gwf_cdo_user_tracer)
The first parameter in cs_gwf_add_tracer is a flag which can be built with
Predefined tracers
Here is a simple example for a standard tracer which can be added in the function cs_user_model
{
"Tracer",
"C");
NULL,
0.,
1., 0.,
1e-4,
0.01);
}
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:3546
cs_flag_t cs_gwf_tracer_model_t
Definition: cs_gwf_param.h:256
void cs_gwf_tracer_set_main_param(cs_gwf_tracer_t *tracer, const char *soil_name, double wmd, double alpha_l, double alpha_t, double distrib_coef, double reaction_rate)
Set a tracer for a specified soil when the tracer is attached to the default model.
Definition: cs_gwf_tracer.c:1446
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:1272
User-defined tracers
TODO
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:3368
#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.