Replay a problem

This demo is based on the Flow Around A Cylinder demo, and demonstrates how one can compute any PPField from a stored solution, given that the dependencies of the field are either saved to disk or computable from the fields saved to disk.

This can be very useful when one needs additional information to the one specified at the time of the solve.

The source code for this demo can be found in Replay.py.

We start by importing from Flow Around A Cylinder:

import sys
# Add FlowAroundCylinder problem as example problem
sys.path.insert(0, path.join(path.dirname(path.realpath(__file__)),'../../../demo/documented/FlowAroundCylinder'))
from FlowAroundCylinder import FlowAroundCylinder

We then import cbcflow

from cbcflow import *

Note that we for this demo does not need to import from dolfin.

Play

We start by defining the play-routine, that is, a normal solve. We use the IPCS_Stable scheme and save the results to Results.

def play():
    # First solve the problem
    problem = FlowAroundCylinder({"refinement_level": 3})
    scheme = IPCS_Stable()

For this we simply store the velocity at every second timestep, and the pressure at every third timestep. We plot the velocity, and we send keyword mode=color so the plot will show the velocity magnitude:

postprocessor = NSPostProcessor({"casedir": "Results"})

postprocessor.add_fields([
    Velocity({"save": True, "stride_timestep": 2, "plot": True, "plot_args": {"mode": "color"}}),
    Pressure({"save": True, "stride_timestep": 3}),
])

We then solve the problem:

solver = NSSolver(problem, scheme, postprocessor)
solver.solve()

Replay

When the solve has been performed, we might want to compute some more derived fields. We start by creating a new postprocessor instance. This instance must point to the same case directory as the original solve:

def replay():
    # Create postprocessor pointing to the same casedir
    postprocessor = NSPostProcessor({"casedir": "Results"})

We then define some new fields to store, and adds them to the postprocessor

# Add new fields to compute
postprocessor.add_fields([
    Stress({"save": True}),
    StreamFunction({"save": True, "plot": True}),
    L2norm("Velocity", {"save": True, "plot": True}),
])

The StreamFunction and L2norm of Velocity only depend on the velocity, and we expect this to be computed at the same timesteps we computed the velocity in the original solve.

The Stress, however, depends on both the Velocity and the Pressure. Since the velocity was saved at every second timestep, and the pressure was only saved every third timestep, we expect this to be computed at timesteps 0, 6, 12, ... .

We then initiate a NSReplay instance with the postprocessor-instance as argument, and call its replay-function to execute the replay routine:

# Replay
replayer = NSReplay(postprocessor)
replayer.replay()