pyrds

python implementation of a finitie volume discretization to solve the reaction diffusion equation


Install
pip install pyrds==1.0.1

Documentation

Python implementation of a finite volume discretization to solve the reaction-diffusion-equation on a non-uniforme 1d domain.

Installation

pip install pyrds

Usage

import numpy
from collections import deque
from pyrds import FiniteVolumeDiscretization, lapack_tridiag
from matplotlib import pyplot


if __name__ == '__main__':
    ''' discrete representation of a lake '''
    # bathymetry/morphology of a lake
    bathymetry_z = numpy.linspace(0, 16, 9, endpoint=True)  # [m]
    bathymetry_areas = numpy.array([494199, 440930, 393912, 348221, 301994, 240935, 153063, 69403, 18691])  # [m2]

    # finite volume discretization
    n_volumes = 499
    lake = FiniteVolumeDiscretization(0, 16, n_volumes, bathymetry_z, bathymetry_areas)

    # define time grid with a constant time step
    dt = 1./8.  # [d]
    tgrid = numpy.arange(0, 365+dt/2., dt).tolist()

    ''' initial conditions '''
    n_vars = 2
    state_vars = numpy.hstack((
                                numpy.zeros((n_volumes, 1)),  # [umol m-3]
                                numpy.zeros((n_volumes, 1))   # [umol m-3]
                             )).reshape((n_volumes*n_vars, 1))

    ''' define constant source/sink as well as diffusivity '''
    D = numpy.ones((n_vars, n_volumes+1)) * 0.3
    S = numpy.zeros((n_vars, n_volumes))  # volume sources
    F = numpy.zeros((n_vars, n_volumes+1))  # flux sources
    # Flux of substance 0 from atmosphere
    F[0,0] = 20
    # Flux of substance 1 from sediment
    F[1,-1] = -20*bathymetry_areas[0]/bathymetry_areas[-1]

    ''' precondition the discretization system '''
    lake.precondition(n_vars, dt)

    ''' initialize record '''
    state_record = deque()

    ''' run simulation'''
    for t in tgrid:
        state_vars = lapack_tridiag(*lake.assembleLES_IE(state_vars, D, S, F))
        state_record.append((state_vars, t))

    ''' plot result '''
    record_array = numpy.array([r[:,0] for (r, t) in state_record])
    record_array = record_array.reshape((-1, n_vars, n_volumes))

    substance_A_record = record_array[:,0,:] / 1000. # [uM]
    substance_B_record = record_array[:,1,:] / 1000. # [uM]

    def colormesh(fig, ax, tmesh, zmesh, var, title):
        ax.invert_yaxis()
        ax.set_title(title)
        cbar = ax.imshow(numpy.fliplr(numpy.rot90(var, -1)), vmin=0, aspect='auto', extent=[tgrid[0], tgrid[-1], 0, 16])
        ax.set_ylabel('Depth [m]')
        ax.set_xlabel('Time [d]')
        fig.colorbar(cbar, ax=ax)

    fig = pyplot.figure()
    ax = fig.add_subplot(211)
    colormesh(fig, ax, tgrid, lake.grid.z_centres, substance_A_record, 'Substance A [uM]')
    ax = fig.add_subplot(212)
    colormesh(fig, ax, tgrid, lake.grid.z_centres, substance_B_record, 'Substance B [uM]')
    pyplot.show()