# 2D channel with time-dependent boundary conditions¶

Here we extend the 2D channel example by adding constant and time dependent boundary conditions.

We begin by defining the domain and solver as before:

```
from thetis import *
lx = 40e3
ly = 2e3
nx = 25
ny = 2
mesh2d = RectangleMesh(nx, ny, lx, ly)
P1_2d = FunctionSpace(mesh2d, 'CG', 1)
bathymetry_2d = Function(P1_2d, name='Bathymetry')
depth = 20.0
bathymetry_2d.assign(depth)
# total duration in seconds
t_end = 12 * 3600
# export interval in seconds
t_export = 300.0
solver_obj = solver2d.FlowSolver2d(mesh2d, bathymetry_2d)
options = solver_obj.options
options.simulation_export_time = t_export
options.simulation_end_time = t_end
options.swe_timestepper_type = 'CrankNicolson'
options.timestep = 50.0
```

We will force the model with a constant volume flux at the right boundary
(x=40 km) and impose a tidal volume flux on the left boundary (x=0 km).
Note that we have increased `t_end`

and `t_export`

to better illustrate
tidal dynamics.

Boundary condtitions are defined for each external boundary using their ID.
In this example we are using a
`RectangleMesh()`

which assigns IDs 1, 2, 3,
and 4 for the four sides of the rectangle:

```
left_bnd_id = 1
right_bnd_id = 2
```

At each boundary we need to define the external value of the prognostic
variables, i.e. in this case the water elevation and velocity.
The value should be either a Firedrake `Constant`

or
`Function`

(in case the boundary condition is not uniform in space).

We store the boundary conditions in a dictionary:

```
swe_bnd = {}
in_flux = 1e3
swe_bnd[right_bnd_id] = {'elev': Constant(0.0),
'flux': Constant(-in_flux)}
```

Above we set the water elevation to zero and prescribe a constant volume flux.
The volume flux is defined as outward normal flux, i.e. a negative value stands
for flow into the domain.
Alternatively we could also prescribe the normal velocity (with key `'un'`

)
or the 2D velocity vector (`'uv'`

).
For all supported boundary conditions, see module `shallowwater_eq`

.

In order to set time-dependent boundary conditions we first define a python function that evaluates the time dependent variable:

```
def timedep_flux(simulation_time):
"""Time-dependent flux function"""
tide_amp = -2e3
tide_t = 12 * 3600.
flux = tide_amp*sin(2 * pi * simulation_time / tide_t) + in_flux
return flux
```

We then create a Constant object with the initial value, and assign it to the left boundary:

```
tide_flux_const = Constant(timedep_flux(0))
swe_bnd[left_bnd_id] = {'flux': tide_flux_const}
```

Boundary conditions are now complete, and we assign them to the solver object:

```
solver_obj.bnd_functions['shallow_water'] = swe_bnd
```

Note that if boundary conditions are not assigned for some boundaries (the lateral boundaries 3 and 4 in this case), Thetis assumes impermeable land conditions.

The only missing piece is to add a mechanism that re-evaluates the boundary
condition as the simulation progresses.
For this purpose we use the optional `update_forcings`

argument of the
`iterate()`

method.
`update_forcings`

is a python function that updates all time dependent
`Constant`

s or
`Function`

s used to force the model.
In this case we only need to update `tide_flux_const`

:

```
def update_forcings(t_new):
"""Callback function that updates all time dependent forcing fields"""
tide_flux_const.assign(timedep_flux(t_new))
```

and finally pass this callback to the time iterator:

```
solver_obj.iterate(update_forcings=update_forcings)
```

This tutorial can be dowloaded as a Python script here.