Flow simulation in 1D

| main | Tutorials | Functions | website |

This is a simple example on how to use the msim functions to solve the groundwater flow equations for 1D domains

Contents

Problem Description

The domain a 10 km line. The left boundary is a specified constant head and the right side is a specified flux. In addition we assume uniform recharge. First we specify some generic simulation options into a struct variable

opt.dim = 1; %This is the dimension of the problem
opt.el_order = 'linear'; %This is the element order. The other option is 'quadratic'
opt.assemblemode = 'vect';%other options are 'nested' and 'serial'. However you should always use 'vect' or leave empty

Mesh Generation

Next we define the 1D mesh. The mesh generation for this problem is trivial and there is no need to use Gmsh

L = 10000; %m domain Length
% Discretize the domain into 5 m segments
p = [0:5:L]';
Np = size(p, 1); %Number of nodes

To Define the mesh we use a structure variable with 2 rows. The first row corresponds to the zero dimension elements (e.g. points) and the second row to 1D elements (lines). Each row has the field elem with 1 or more rows depending on the number of elements. Each row of elem has 2 fields. id and type. id are the ids f the elements and type is the type pf the elements. Here we have only one type of elements

MSH(1,1).elem(1,1).id = [1:Np]';
MSH(1,1).elem(1,1).type = 'point';
MSH(2,1).elem(1,1).id = [(1:Np-1)' (2:Np)'];
MSH(2,1).elem(1,1).type = 'line';

Boundary Conditions - fluxes

The fluxes are divided into two categories. Those that are applied on elements and those that are applied on nodes. To account for the element fluxes we define the following structure:

FLUX(1,1).id = (1:length(MSH(2,1).elem(1,1).id))';
FLUX(1,1).val = 2e-5 * ones(length(FLUX(1,1).id), 1);
FLUX(1,1).dim = 1;% This is the dimension of the elements
FLUX(1,1).el_type = 'line'; %ths is unnecessary for 1D problems
FLUX(1,1).el_order = 'linear';
FLUX(1,1).id_el = 1; %This is the index in the Mesh.elem field
FLUX(1,1).assemblemode = 'vect';

Next we will defined 2 point sources which extract water from the domain (e.g. wells). Let's assume that the sources are are located at x = 403 and 825 m. However, since the mesh has been created before the definition of the point sources we will assing the fluxes to the nearets node.

[~, id1] = min(abs(403 - p));
[~, id2] = min(abs(825 - p));
FLUX_point = [[id1;id2] [-0.05; -0.05]];

Last we will assign the flux boundary at the right side of the domain

FLUX_point = [FLUX_point; Np -0.01];

Boundary Conditions - Constant head

This is a simple matrix where the first column is the id of the node and the second column is the specified value

CH = [1 30];

Assemble the matrices

Before assembling the matrices we need to define a hydraulic conductivity. We will define the hydraulic conductivity as random variable.

K = normrnd(50, 10, 100, 1);
x = linspace(0, L, 100)';
Knd = interp1q(x, K, p);
Tnd = Knd *1;

Assemble the left hand side matrix

[Kglo, H] = Assemble_LHS(p, MSH(2,1).elem(1,1).id, Tnd, CH, [], opt);

Assemble the right hand side matrix

F_rch= Assemble_RHS(length(H), p, MSH, FLUX);

The Assemble RHS function essentially distributes the element fluxes to the mesh nodes. Now we have to add the point fluxes to the output of the RHS assemble

F_rch(FLUX_point(:, 1), 1) = F_rch(FLUX_point(:, 1), 1) + FLUX_point(:, 2);

Solve

Now we can solve the problem by invoking the following function and plot the results

Head = solve_system(Kglo, H, F_rch);
plot(p, Head)

| main | Tutorials | Functions | website |