Adding a custom model

If Adding a custom boundary condition is insufficient for your needs, it is also relatively straightforward to implement a custom model. In this case, however, the Discretization class will need to be modified (or the appropriate methods needs to be replaced in an instance of the class). The methods that most likely need to be changed are linear_part(), nonlinear_part(), mass_matrix() and boundaries(), or functions called from any of these functions.

As an example, the 2D nondimensional incompressible Stokes equations of the form

\[\begin{split}\frac{1}{\mathrm{Re}} \nabla^2 u - \nabla p &= 0\\ \nabla \cdot u &= 0\end{split}\]

could be implemented as

def linear_part(self):
    Re = self.get_parameter('Reynolds Number', 1.0)
    return 1 / Re * (self.u_xx() + self.u_yy()
                     + self.v_xx() + self.v_yy()) \
        - (self.p_x() + self.p_y()) \
        + self.div()

def nonlinear_part(self, state):
    atom = numpy.zeros((self.nx, self.ny, self.nz, self.dof, self.dof, 3, 3, 3))
    return atom, atom

We could then add a moving lid to the top using

def boundaries(self, atom):
    boundary_conditions = BoundaryConditions(
        self.nx, self.ny, self.nz, self.dim, self.dof, self.x, self.y, self.z)

    lid_velocity = self.parameters['Lid Velocity']
    boundary_conditions.moving_lid_north(atom, lid_velocity)

    boundary_conditions.no_slip_east(atom)
    boundary_conditions.no_slip_west(atom)

    boundary_conditions.no_slip_south(atom)

    return boundary_conditions.get_forcing()
\[\]