def test_pyplot(): pp = PostProcessor() pp.add_field(MockScalarField(dict(plot=True))) pp.update_all({}, 0.0, 0) pp.update_all({}, 0.1, 1) pp.update_all({}, 0.6, 2) pp.update_all({}, 1.6, 3)
def test_dolfinplot(mesh): pp = PostProcessor() spacepool = SpacePool(mesh) Q = spacepool.get_space(1, 0) V = spacepool.get_space(1, 1) pp.add_field(MockFunctionField(Q, dict(plot=True))) pp.add_field(MockVectorFunctionField(V, dict(plot=True))) pp.update_all({}, 0.0, 0) pp.update_all({}, 0.1, 1) pp.update_all({}, 0.6, 2) pp.update_all({}, 1.6, 3)
def test_get(): pp = PostProcessor() velocity = MockVelocity() pp.add_field(velocity) # Check that compute is triggered assert velocity.touched == 0 assert pp.get("MockVelocity") == "u" assert velocity.touched == 1 # Check that get doesn't trigger second compute count pp.get("MockVelocity") assert velocity.touched == 1
def test_add_field(): pp = PostProcessor() pp.add_field(SolutionField("foo")) assert "foo" in pp._fields.keys() pp += SolutionField("bar") assert set(["foo", "bar"]) == set(pp._fields.keys()) pp += [SolutionField("a"), SolutionField("b")] assert set(["foo", "bar", "a", "b"]) == set(pp._fields.keys()) pp.add_fields([ MetaField("foo"), MetaField2("foo", "bar"), ]) assert set(["foo", "bar", "a", "b", "MetaField_foo", "MetaField2_foo_bar"]) == set(pp._fields.keys())
def replay(self): "Replay problem with given postprocessor." # Backup play log self.backup_playlog() # Set up for replay replay_plan = self._fetch_history() postprocessors = [] for fieldname, field in self.postproc._fields.items(): if not (field.params.save or field.params.plot): continue # Check timesteps covered by current field keys = self._check_field_coverage(replay_plan, fieldname) # Get the time dependency for the field t_dep = min( [dep[1] for dep in self.postproc._dependencies[fieldname]] + [0]) dep_fields = [] for dep in self.postproc._full_dependencies[fieldname]: if dep[0] in ["t", "timestep"]: continue if dep[0] in dep_fields: continue # Copy dependency and set save/plot to False. If dependency should be # plotted/saved, this field will be added separately. dependency = self.postproc._fields[dep[0]] dependency = copy.copy(dependency) dependency.params.save = False dependency.params.plot = False dependency.params.safe = False dep_fields.append(dependency) added_to_postprocessor = False for i, (ppkeys, ppt_dep, pp) in enumerate(postprocessors): if t_dep == ppt_dep and set(keys) == set(ppkeys): pp.add_fields(dep_fields, exists_reaction="ignore") pp.add_field(field, exists_reaction="replace") added_to_postprocessor = True break else: continue # Create new postprocessor if no suitable postprocessor found if not added_to_postprocessor: pp = PostProcessor(self.postproc.params, self.postproc._timer) pp.add_fields(dep_fields, exists_reaction="ignore") pp.add_field(field, exists_reaction="replace") postprocessors.append([keys, t_dep, pp]) postprocessors = sorted(postprocessors, key=itemgetter(1), reverse=True) t_independent_fields = [] for fieldname in self.postproc._fields: if self.postproc._full_dependencies[fieldname] == []: t_independent_fields.append(fieldname) elif min(t for dep, t in self.postproc._full_dependencies[fieldname]) == 0: t_independent_fields.append(fieldname) # Run replay sorted_keys = sorted(replay_plan.keys()) N = max(sorted_keys) for timestep in sorted_keys: cbc_print("Processing timestep %d of %d. %.3f%% complete." % (timestep, N, 100.0 * (timestep) / N)) # Load solution at this timestep (all available fields) solution = replay_plan[timestep] t = solution.pop("t") # Cycle through postprocessors and update if required for ppkeys, ppt_dep, pp in postprocessors: if timestep in ppkeys: # Add dummy solutions to avoid error when handling dependencies # We know this should work, because it has already been established that # the fields to be computed at this timestep can be computed from stored # solutions. for field in pp._sorted_fields_keys: for dep in reversed(pp._dependencies[field]): if not have_necessary_deps(solution, pp, dep[0]): solution[dep[0]] = lambda: None pp.update_all(solution, t, timestep) # Clear None-objects from solution [ solution.pop(k) for k in solution.keys() if not solution[k] ] # Update solution to avoid re-computing data for fieldname, value in pp._cache[0].items(): if fieldname in t_independent_fields: value = pp._cache[0][fieldname] #solution[fieldname] = lambda value=value: value # Memory leak! solution[fieldname] = MiniCallable(value) self.timer.increment() if self.params.check_memory_frequency != 0 and timestep % self.params.check_memory_frequency == 0: cbc_print('Memory usage is: %s' % MPI.sum(mpi_comm_world(), get_memory_usage())) # Clean up solution: Required to avoid memory leak for some reason... for f, v in solution.items(): if isinstance(v, MiniCallable): v.value = None del v solution.pop(f) for ppkeys, ppt_dep, pp in postprocessors: pp.finalize_all()
def run_splitting_solver(domain, dt, T): # Create cardiac model problem description cell_model = Tentusscher_panfilov_2006_epi_cell() heart = setup_model(cell_model, domain) # Customize and create monodomain solver ps = SplittingSolver.default_parameters() ps["pde_solver"] = "monodomain" ps["apply_stimulus_current_to_pde"] = True # 2nd order splitting scheme ps["theta"] = 0.5 # Use explicit first-order Rush-Larsen scheme for the ODEs ps["ode_solver_choice"] = "CardiacODESolver" ps["CardiacODESolver"]["scheme"] = "RL1" # Crank-Nicolson discretization for PDEs in time: ps["MonodomainSolver"]["theta"] = 0.5 ps["MonodomainSolver"]["linear_solver_type"] = "iterative" ps["MonodomainSolver"]["algorithm"] = "cg" ps["MonodomainSolver"]["preconditioner"] = "petsc_amg" # Create solver solver = SplittingSolver(heart, params=ps) # Extract the solution fields and set the initial conditions (vs_, vs, vur) = solver.solution_fields() vs_.assign(cell_model.initial_conditions()) solutions = solver.solve((0, T), dt) postprocessor = PostProcessor(dict(casedir="test", clean_casedir=True)) postprocessor.store_mesh(heart.domain()) field_params = dict( save=True, save_as=["hdf5", "xdmf"], plot=False, start_timestep=-1, stride_timestep=1 ) postprocessor.add_field(SolutionField("v", field_params)) theta = ps["theta"] # Solve total = Timer("XXX Total cbcbeat solver time") for i, (timestep, (vs_, vs, vur)) in enumerate(solutions): t0, t1 = timestep current_t = t0 + theta*(t1 - t0) postprocessor.update_all({"v": lambda: vur}, current_t, i) print("Solving on %s" % str(timestep)) # Print memory usage (just for the fun of it) print(memory_usage()) total.stop() # Plot result (as sanity check) #plot(vs[0], interactive=True) # Stop timer and list timings if MPI.rank(mpi_comm_world()) == 0: list_timings(TimingClear_keep, [TimingType_wall])