Пример #1
0
def calc_p(p, uvwf, rho, dt, dxyz, obst):
    """
    Calculating the Pressure.
    """
    # -------------------------------------------------------------------------
    # Fetch the resolution
    rc = p.val.shape
    # Create linear system
    A_p, b_p = create_matrix(p, zeros(rc), dt/rho, dxyz, obst, 'n')

    # Compute the source for the pressure.  Important: don't send "obst"
    # as a parameter here, because you don't want to take it into
    # account at this stage.  After velocity corrections, you should.
    b_p = vol_balance(uvwf, dxyz, zeros(rc))

    print('Maximum volume error before correction: %12.5e' % abs(b_p).max())
    print('Volume imbalance before correction    : %12.5e' % b_p.sum())

    # Solve for pressure
    res = bicgstab(A_p, reshape(b_p, prod(rc)), tol=TOL)
    p.val[:] = reshape(res[0], rc)

    print("res[1] = ", res[1])

    # Anchor it to values around zero (the absolute value of pressure
    # correction can get really volatile.  Although it is in prinicple not
    # important for incompressible flows, it is ugly for post-processing.
    p.val[:] = p.val[:] - p.val.mean()

    # Set to zero in obstacle (it can get strange
    # values during the iterative solution procedure)
    if obst.any() != 0:
        p.val[:] = obst_zero_val(p.pos, p.val, obst)

    # Finally adjust the boundary values
    p = adj_n_bnds(p)

    return  # end of function
def main(show_plot=True):
    """
    Docstring.
    """

    # =========================================================================
    #
    # Define problem
    #
    # =========================================================================

    xn = nodes(0, 1, 64, 1.0 / 256, 1.0 / 256)
    yn = nodes(0, 1, 64, 1.0 / 256, 1.0 / 256)
    zn = nodes(0, 0.1, 5)

    # Cell dimensions
    nx, ny, nz, dx, dy, dz, rc, ru, rv, rw = cartesian_grid(xn, yn, zn)

    # Set physical properties
    grashof = 1.4105E+06
    prandtl = 0.7058
    rho = zeros(rc)
    mu = zeros(rc)
    kappa = zeros(rc)
    cap = zeros(rc)
    rho[:, :, :] = 1.0
    mu[:, :, :] = 1.0 / sqrt(grashof)
    kappa[:, :, :] = 1.0 / (prandtl * sqrt(grashof))
    cap[:, :, :] = 1.0

    # Time-stepping parameters
    dt = 0.02  # time step
    ndt = 1000  # number of time steps

    # Create unknowns; names, positions and sizes
    uc = create_unknown('cell-u-vel', C, rc, DIRICHLET)
    vc = create_unknown('cell-v-vel', C, rc, DIRICHLET)
    wc = create_unknown('cell-w-vel', C, rc, DIRICHLET)
    uf = create_unknown('face-u-vel', X, ru, DIRICHLET)
    vf = create_unknown('face-v-vel', Y, rv, DIRICHLET)
    wf = create_unknown('face-w-vel', Z, rw, DIRICHLET)
    t = create_unknown('temperature', C, rc, NEUMANN)
    p = create_unknown('pressure', C, rc, NEUMANN)
    p_tot = zeros(rc)

    # This is a new test
    t.bnd[W].typ[:] = DIRICHLET
    t.bnd[W].val[:] = -0.5

    t.bnd[E].typ[:] = DIRICHLET
    t.bnd[E].val[:] = +0.5

    for j in (B, T):
        uc.bnd[j].typ[:] = NEUMANN
        vc.bnd[j].typ[:] = NEUMANN
        wc.bnd[j].typ[:] = NEUMANN

    obst = zeros(rc)

    # =========================================================================
    #
    # Solution algorithm
    #
    # =========================================================================

    # -----------
    #
    # Time loop
    #
    # -----------
    for ts in range(1, ndt + 1):

        print_time_step(ts)

        # ------------------
        # Store old values
        # ------------------
        t.old[:] = t.val[:]
        uc.old[:] = uc.val[:]
        vc.old[:] = vc.val[:]
        wc.old[:] = wc.val[:]

        # ------------------------
        # Temperature (enthalpy)
        # ------------------------
        calc_t(t, (uf, vf, wf), (rho * cap), kappa, dt, (dx, dy, dz), obst)

        # -----------------------
        # Momentum conservation
        # -----------------------
        ef = zeros(rc), t.val, zeros(rc)

        calc_uvw((uc, vc, wc), (uf, vf, wf), rho, mu, p_tot, ef, dt,
                 (dx, dy, dz), obst)

        # ----------
        # Pressure
        # ----------
        calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst)

        p_tot = p_tot + p.val

        # ---------------------
        # Velocity correction
        # ---------------------
        corr_uvw((uc, vc, wc), p, rho, dt, (dx, dy, dz), obst)
        corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst)

        # Compute volume balance for checking
        err = vol_balance((uf, vf, wf), (dx, dy, dz), obst)
        print('Maximum volume error after correction: %12.5e' % abs(err).max())

        # Check the CFL number too
        cfl = cfl_max((uc, vc, wc), dt, (dx, dy, dz))
        print('Maximum CFL number: %12.5e' % cfl)

        # =====================================================================
        #
        # Visualisation
        #
        # =====================================================================
        if show_plot:
            if ts % 20 == 0:
                plot_isolines(t.val, (uc, vc, wc), (xn, yn, zn), Z)
Пример #3
0
def main(show_plot=True):
    """
    Docstring.
    """

    # =========================================================================
    #
    # Define problem
    #
    # =========================================================================

    # Node coordinates
    xn = nodes(0, 10, 300)
    yn = nodes(0, 1, 40, 1 / 500, 1 / 500)
    zn = nodes(0, 3, 3)

    # Cell coordinates
    xc = avg(xn)
    yc = avg(yn)
    zc = avg(zn)

    # Cell dimensions
    nx, ny, nz, dx, dy, dz, rc, ru, rv, rw = cartesian_grid(xn, yn, zn)

    # Set physical properties
    rho = zeros(rc)
    mu = zeros(rc)
    kappa = zeros(rc)
    cap = zeros(rc)
    rho[:, :, :] = 1.
    mu[:, :, :] = 0.1
    kappa[:, :, :] = 0.15
    cap[:, :, :] = 1.0

    # Time-stepping parameters
    dt = 0.003  # time step
    ndt = 1500  # number of time steps

    # Create unknowns; names, positions and sizes
    uf = create_unknown('face-u-vel', X, ru, DIRICHLET)
    vf = create_unknown('face-v-vel', Y, rv, DIRICHLET)
    wf = create_unknown('face-w-vel', Z, rw, DIRICHLET)
    t = create_unknown('temperature', C, rc, NEUMANN)
    p = create_unknown('pressure', C, rc, NEUMANN)

    # Specify boundary conditions
    uf.bnd[W].typ[:1, :, :] = DIRICHLET
    for k in range(0, nz):
        uf.bnd[W].val[:1, :, k] = par(1.0, yn)

    uf.bnd[E].typ[:1, :, :] = OUTLET
    uf.bnd[E].val[:1, :, :] = 1.0

    for j in (B, T):
        uf.bnd[j].typ[:] = NEUMANN
        vf.bnd[j].typ[:] = NEUMANN
        wf.bnd[j].typ[:] = NEUMANN

    t.bnd[W].typ[:1, :, :] = DIRICHLET
    for k in range(0, nz):
        t.bnd[W].val[:1, :, k] = 1.0 - yc

    t.bnd[S].typ[:, :1, :] = DIRICHLET
    t.bnd[S].val[:, :1, :] = +1.0
    t.bnd[N].typ[:, :1, :] = DIRICHLET
    t.bnd[N].val[:, :1, :] = 0.0

    adj_n_bnds(t)
    adj_n_bnds(p)

    # Specify initial conditions
    uf.val[:, :, :] = 1.0
    t.val[:, :, :] = 0

    obst = zeros(rc)

    # =========================================================================
    #
    # Solution algorithm
    #
    # =========================================================================

    # -----------
    #
    # Time loop
    #
    # -----------
    for ts in range(1, ndt + 1):

        print_time_step(ts)

        # ------------------
        # Store old values
        # ------------------
        t.old[:] = t.val[:]
        uf.old[:] = uf.val[:]
        vf.old[:] = vf.val[:]
        wf.old[:] = wf.val[:]

        # ------------------------
        # Temperature (enthalpy)
        # ------------------------
        calc_t(t, (uf, vf, wf), (rho * cap), kappa, dt, (dx, dy, dz), obst)

        # -----------------------
        # Momentum conservation
        # -----------------------
        ef = zeros(ru), 150.0 * avg(Y, t.val), zeros(rw)

        calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, \
                 zeros(rc), ef, dt, (dx, dy, dz), obst)

        # ----------
        # Pressure
        # ----------
        calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst)

        # ---------------------
        # Velocity correction
        # ---------------------
        corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst)

        # Compute volume balance for checking
        err = vol_balance((uf, vf, wf), (dx, dy, dz), obst)
        print('Maximum volume error after correction: %12.5e' % abs(err).max())

        # Check the CFL number too
        cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz))
        print('Maximum CFL number: %12.5e' % cfl)

        # =====================================================================
        #
        # Visualisation
        #
        # =====================================================================
        if show_plot:
            if ts % 150 == 0:
                plot_isolines(t.val, (uf, vf, wf), (xn, yn, zn), Z)
                plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z)
Пример #4
0
def main(show_plot=True):
    """
    inlet example
    :param show_plot: show plot or not
    :return: None
    """

    #==========================================================================
    #
    # Define problem
    #
    #==========================================================================

    planes = ('XY', 'XZ', 'YZ')
    tests = array([11, 12, 13, 14, \
                   21, 22, 23, 24, \
                   31, 32, 33, 34, \
                   41, 42, 43, 44])
    TEST = tests[floor(random() * 16)]
    PLANE = planes[floor(random() * 3)]

    # Node coordinates
    xn = nodes(0, 1, 160)
    yn = nodes(0, 1, 160)
    zn = nodes(0, 0.025, 4)

    # Cell coordinates
    xc = avg(xn)
    yc = avg(yn)
    zc = avg(zn)

    # Cell dimensions
    nx, ny, nz, \
    dx, dy, dz, \
    rc, ru, rv, rw = cartesian_grid(xn, yn, zn)

    # Set physical properties
    rho, mu, cap, kappa = properties_for_air(rc)

    # Time-stepping parameters
    dt = 0.15  # time step
    ndt = 200  # number of time steps

    # Create unknowns names, positions and sizes
    uf = create_unknown('face-u-vel', X, ru, DIRICHLET)
    vf = create_unknown('face-v-vel', Y, rv, DIRICHLET)
    wf = create_unknown('face-w-vel', Z, rw, DIRICHLET)
    p = create_unknown('pressure', C, rc, NEUMANN)

    print(TEST)

    # Specify boundary conditions
    if TEST == 11:
        for k in range(0, nz):
            uf.bnd[W].val[0, ny // 4:3 * ny // 4,
                          k] = +par(0.01, yn[ny // 4:3 * ny // 4 + 1])
            uf.bnd[E].typ[0, ny // 4:3 * ny // 4, k] = OUTLET

    elif TEST == 12:  # vertical mirror from 11
        for k in range(0, nz):
            uf.bnd[E].val[0, ny // 4:3 * ny // 4,
                          k] = -par(0.01, yn[ny // 4:3 * ny // 4 + 1])
            uf.bnd[W].typ[0, ny // 4:3 * ny // 4, k] = OUTLET

    elif TEST == 13:  # rotate 11
        for k in range(0, nz):
            vf.bnd[S].val[nx // 4:3 * nx // 4, 0,
                          k] = +par(0.01, xn[nx // 4:3 * nx // 4 + 1])
            vf.bnd[N].typ[nx // 4:3 * nx // 4, 0, k] = OUTLET

    elif TEST == 14:  # horizontal mirror 13
        for k in range(0, nz):
            vf.bnd[N].val[nx // 4:3 * nx // 4, 0,
                          k] = -par(0.01, xn[nx // 4:3 * nx // 4 + 1])
            vf.bnd[S].typ[nx // 4:3 * nx // 4, 0, k] = OUTLET

    elif TEST == 21:  # 2 exits
        for k in range(0, nz):
            uf.bnd[W].val[0, ny // 4:3 * ny // 4,
                          k] = +par(0.01, yn[ny // 4:3 * ny // 4 + 1])
            uf.bnd[E].typ[0, 0:ny // 4, k] = OUTLET
            uf.bnd[E].typ[0, 3 * ny // 4:ny, k] = OUTLET

    elif TEST == 22:  # vertical mirror 21
        for k in range(0, nz):
            uf.bnd[E].val[0, ny // 4:3 * ny // 4,
                          k] = -par(0.01, yn[ny // 4:3 * ny // 4 + 1])
            uf.bnd[W].typ[0, 0:ny // 4, k] = OUTLET
            uf.bnd[W].typ[0, 3 * ny // 4:ny, k] = OUTLET

    elif TEST == 23:  # rotated 21
        for k in range(0, nz):
            vf.bnd[S].val[nx // 4:3 * nx // 4, 0,
                          k] = +par(0.01, xn[nx // 4:3 * nx // 4 + 1])
            vf.bnd[N].typ[:nx // 4, 0, k] = OUTLET
            vf.bnd[N].typ[3 * nx // 4:nx, 0, k] = OUTLET

    elif TEST == 24:  # horizontal mirror of 23
        for k in range(0, nz):
            vf.bnd[N].val[nx // 4:3 * nx // 4, 0,
                          k] = -par(0.01, xn[nx // 4:3 * nx // 4 + 1])
            vf.bnd[S].typ[:nx // 4, 0, k] = OUTLET
            vf.bnd[S].typ[3 * nx // 4:nx, 0, k] = OUTLET

    elif TEST == 31:  # inlet and outlet at the same face
        for k in range(0, nz):
            uf.bnd[W].val[0, 3 * ny // 4:ny,
                          k] = +par(0.01, yn[3 * ny // 4:ny + 1])
            uf.bnd[W].typ[0, :ny // 4, k] = OUTLET

    elif TEST == 32:  # vertical mirror of 31
        for k in range(0, nz):
            uf.bnd[E].val[0, 3 * ny // 4:ny,
                          k] = -par(0.01, yn[3 * ny // 4:ny + 1])
            uf.bnd[E].typ[0, 0:ny // 4, k] = OUTLET

    elif TEST == 33:  # rotated 31
        for k in range(0, nz):
            vf.bnd[S].val[3 * nx // 4:nx, 0,
                          k] = +par(0.01, xn[3 * nx // 4:nx + 1])
            vf.bnd[S].typ[:nx // 4, 0, k] = OUTLET

    elif TEST == 34:  # horizontal mirror of 33
        for k in range(0, nz):
            vf.bnd[N].val[3 * nx // 4:nx, 0,
                          k] = -par(0.01, xn[3 * nx // 4:nx + 1])
            vf.bnd[N].typ[:nx // 4, 0, k] = OUTLET

    elif TEST == 41:  # inlet and outlet at the same face, one more outlet
        for k in range(0, nz):
            uf.bnd[W].val[0, 3 * ny // 4:ny,
                          k] = +par(0.01, yn[3 * ny // 4:ny + 1])
            uf.bnd[W].typ[0, :ny // 8, k] = OUTLET
            uf.bnd[E].typ[0, :ny // 8, k] = OUTLET

    elif TEST == 42:  # vertical mirror of 41
        for k in range(0, nz):
            uf.bnd[E].val[0, 3 * ny // 4:ny,
                          k] = -par(0.01, yn[3 * ny // 4:ny + 1])
            uf.bnd[E].typ[0, :ny // 8, k] = OUTLET
            uf.bnd[W].typ[0, :ny // 8, k] = OUTLET

    elif TEST == 43:  # rotated 41
        for k in range(0, nz):
            vf.bnd[S].val[3 * nx // 4:nx, 0,
                          k] = +par(0.01, xn[3 * nx // 4:nx + 1])
            vf.bnd[S].typ[0:nx // 8, 0, k] = OUTLET
            vf.bnd[N].typ[0:nx // 8, 0, k] = OUTLET

    elif TEST == 44:  # horizontal mirror of 43
        for k in range(0, nz):
            vf.bnd[N].val[3 * ny // 4:nx, 0,
                          k] = -par(0.01, xn[3 * nx // 4:nx + 1])
            vf.bnd[N].typ[:nx // 8, 0, k] = OUTLET
            vf.bnd[S].typ[:nx // 8, 0, k] = OUTLET

    for j in (B, T):
        uf.bnd[j].typ[:] = NEUMANN
        vf.bnd[j].typ[:] = NEUMANN
        wf.bnd[j].typ[:] = NEUMANN

    # Create a cylindrical obstacle in the middle just for kicks
    obst = zeros(rc)
    for k in range(0, nz):
        for j in range(0, ny):
            for i in range(0, nx):
                dist = sqrt((j - ny / 2 + 1)**2 + (i - nx / 2 + 1)**2)
                if dist < ny / 4:
                    obst[i, j, k] = 1

    # =========================================================================
    #
    # Solution algorithm
    #
    # =========================================================================

    # -----------
    #
    # Time loop
    #
    # -----------
    for ts in range(1, ndt + 1):
        print_time_step(ts)

        # ------------------
        # Store old values
        # ------------------
        uf.old[:] = uf.val[:]
        vf.old[:] = vf.val[:]
        wf.old[:] = wf.val[:]

        # -----------------------
        # Momentum conservation
        # -----------------------
        ef = zeros(ru), zeros(rv), zeros(rw)

        calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, zeros(rc), ef, dt,
                 (dx, dy, dz), obst)

        # ----------
        # Pressure
        # ----------
        calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst)

        # ---------------------
        # Velocity correction
        # ---------------------
        corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst)

        # Compute volume balance for checking
        err = vol_balance((uf, vf, wf), (dx, dy, dz), obst)
        print('Maximum volume error after correction: %12.5e' % abs(err).max())

        # Check the CFL number too
        cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz))
        print('Maximum CFL number: %12.5e' % cfl)

    # =========================================================================
    #
    # Visualisation
    #
    # =========================================================================
    if show_plot:
        if ts % 10 == 0:
            plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z)
Пример #5
0
def main(show_plot=True):
    """Example
    """
    #==========================================================================
    #
    # Define problem
    #
    #==========================================================================

    # Node coordinates
    xn = nodes(0, 1, 256)
    yn = nodes(0, 0.125, 32)
    zn = nodes(0, 0.125, 4)

    # Cell coordinates
    xc = avg(xn)
    yc = avg(yn)
    zc = avg(zn)

    # Cell dimensions
    nx, ny, nz, \
    dx, dy, dz, \
    rc, ru, rv, rw = cartesian_grid(xn, yn, zn)

    # Set physical properties
    rho, mu, cap, kappa = properties_for_air(rc)

    # Time-stepping parameters
    dt = 0.002  # time step
    ndt = 5000  # number of time steps

    # Create unknowns; names, positions and sizes
    uf = create_unknown('face-u-vel', X, ru, DIRICHLET)
    vf = create_unknown('face-v-vel', Y, rv, DIRICHLET)
    wf = create_unknown('face-w-vel', Z, rw, DIRICHLET)
    p = create_unknown('pressure', C, rc, NEUMANN)

    # Specify boundary conditions
    uf.bnd[W].typ[:1, :, :] = DIRICHLET
    for k in range(0, nz):
        uf.bnd[W].val[:1, :, k] = par(0.1, yn)

    uf.bnd[E].typ[:1, :, :] = OUTLET

    for j in (B, T):
        uf.bnd[j].typ[:] = NEUMANN
        vf.bnd[j].typ[:] = NEUMANN
        wf.bnd[j].typ[:] = NEUMANN

    adj_n_bnds(p)

    obst = zeros(rc)
    for j in range(0, 24):
        for i in range(64 + j, 64 + 24):
            for k in range(0, nz):
                obst[i, j, k] = 1

    # =========================================================================
    #
    # Solution algorithm
    #
    # =========================================================================

    # -----------
    #
    # Time loop
    #
    # -----------
    for ts in range(1, ndt + 1):

        print_time_step(ts)

        # ------------------
        # Store old values
        # ------------------
        uf.old[:] = uf.val[:]
        vf.old[:] = vf.val[:]
        wf.old[:] = wf.val[:]

        # -----------------------
        # Momentum conservation
        # -----------------------
        ef = zeros(ru), zeros(rv), zeros(rw)

        calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu,  \
                 zeros(rc), ef, dt, (dx, dy, dz), obst)

        # ----------
        # Pressure
        # ----------
        calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst)

        # ---------------------
        # Velocity correction
        # ---------------------
        corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst)

        # Compute volume balance for checking
        err = vol_balance((uf, vf, wf), (dx, dy, dz), obst)
        print('Maximum volume error after correction: %12.5e' % abs(err).max())

        # Check the CFL number too
        cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz))
        print('Maximum CFL number: %12.5e' % cfl)

        # =====================================================================
        #
        # Visualisation
        #
        # =====================================================================
        if show_plot:
            if ts % 20 == 0:
                plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z)
Пример #6
0
def main(show_plot=True):
    """
    Docstring.
    """

    # =========================================================================
    #
    # Define problem
    #
    # =========================================================================

    # Node coordinates
    xn = nodes(0, 1.25, 256)
    yn = nodes(0, 0.125, 32)
    zn = nodes(0, 0.125, 32)

    # Cell coordinates
    xc = avg(xn)
    yc = avg(yn)
    zc = avg(zn)

    # Cell dimensions
    nx, ny, nz, \
    dx, dy, dz, \
    rc, ru, rv, rw = cartesian_grid(xn, yn, zn)

    # Set physical properties
    rho, mu, cap, kappa = properties_for_air(rc)

    # Time-stepping parameters
    dt = 0.005  # time step
    ndt = 2000  # number of time steps

    # Create unknowns; names, positions and sizes
    uc = create_unknown('cell-u-vel', C, rc, DIRICHLET)
    vc = create_unknown('cell-v-vel', C, rc, DIRICHLET)
    wc = create_unknown('cell-w-vel', C, rc, DIRICHLET)
    uf = create_unknown('face-u-vel', X, ru, DIRICHLET)
    vf = create_unknown('face-v-vel', Y, rv, DIRICHLET)
    wf = create_unknown('face-w-vel', Z, rw, DIRICHLET)
    p = create_unknown('pressure', C, rc, NEUMANN)

    # Specify boundary conditions
    uc.bnd[W].typ[:1, :, :] = DIRICHLET
    uc.bnd[W].val[:1, :, :] = 0.1 * outer(par(1.0, yn), par(1.0, zn))

    uc.bnd[E].typ[:1, :, :] = OUTLET

    for j in (B, T):
        uc.bnd[j].typ[:] = NEUMANN
        vc.bnd[j].typ[:] = NEUMANN
        wc.bnd[j].typ[:] = NEUMANN

    adj_n_bnds(p)

    # Create obstacles
    obst = zeros(rc)

    class key:
        """
        Class Docstring.
        """
        ip = -1
        im = -1
        jp = -1
        jm = -1
        kp = -1
        km = -1

    block = (key(), key(), key(), key())

    th = 5
    block[0].im = 3 * nx / 16  # i minus
    block[0].ip = block[0].im + th  # i plus
    block[0].jm = 0  # j minus
    block[0].jp = 3 * ny / 4  # j plus
    block[0].km = 0  # k minus
    block[0].kp = 3 * ny / 4  # k plus

    block[1].im = 5 * nx / 16  # i minus
    block[1].ip = block[1].im + th  # i plus
    block[1].jm = ny / 4  # j minus
    block[1].jp = ny  # j plus
    block[1].km = ny / 4  # k minus
    block[1].kp = ny  # k plus

    block[2].im = 7 * nx / 16  # i minus
    block[2].ip = block[2].im + th  # i plus
    block[2].jm = 0  # j minus
    block[2].jp = 3 * ny / 4  # j plus
    block[2].km = 0  # k minus
    block[2].kp = 3 * ny / 4  # k plus

    block[3].im = 9 * nx / 16  # i minus
    block[3].ip = block[3].im + th  # i plus
    block[3].jm = ny / 4  # j minus
    block[3].jp = ny  # j plus
    block[3].km = ny / 4  # k minus
    block[3].kp = ny  # k plus

    for o in range(0, 4):
        for i in range(floor(block[o].im), floor(block[o].ip)):
            for j in range(floor(block[o].jm), floor(block[o].jp)):
                for k in range(floor(block[o].km), floor(block[o].kp)):
                    obst[i, j, k] = 1

    # =========================================================================
    #
    # Solution algorithm
    #
    # =========================================================================

    # -----------
    #
    # Time loop
    #
    # -----------
    for ts in range(1, ndt + 1):

        print_time_step(ts)

        # ------------------
        # Store old values
        # ------------------
        uc.old[:] = uc.val[:]
        vc.old[:] = vc.val[:]
        wc.old[:] = wc.val[:]

        # -----------------------
        # Momentum conservation
        # -----------------------
        ef = zeros(rc), zeros(rc), zeros(rc)

        calc_uvw((uc, vc, wc), (uf, vf, wf), rho, mu, zeros(rc), ef, dt,
                 (dx, dy, dz), obst)

        # ----------
        # Pressure
        # ----------
        calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst)

        # ---------------------
        # Velocity correction
        # ---------------------
        corr_uvw((uc, vc, wc), p, rho, dt, (dx, dy, dz), obst)
        corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst)

        # Compute volume balance for checking
        err = vol_balance((uf, vf, wf), (dx, dy, dz), obst)
        print('Maximum volume error after correction: %12.5e' % abs(err).max())

        # Check the CFL number too
        cfl = cfl_max((uc, vc, wc), dt, (dx, dy, dz))
        print('Maximum CFL number: %12.5e' % cfl)

        # =====================================================================
        #
        # Visualisation
        #
        # =====================================================================
        if show_plot:
            if ts % 20 == 0:
                plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Y)
                plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Z)