From b77b8ee74671c2b9b133b6498b511ec78084552f Mon Sep 17 00:00:00 2001 From: Richard West Date: Wed, 8 Jun 2022 22:51:42 -0400 Subject: [PATCH] [Python/examples] Suggestions from code review. - don't make it look like unit tests - print some output - keep under 88 characters - always create one solution, then save it in several formats --- .../examples/onedim/flame_initial_guess.py | 142 ++++++++++-------- 1 file changed, 76 insertions(+), 66 deletions(-) diff --git a/interfaces/cython/cantera/examples/onedim/flame_initial_guess.py b/interfaces/cython/cantera/examples/onedim/flame_initial_guess.py index 280c2467e2..600f46c57f 100644 --- a/interfaces/cython/cantera/examples/onedim/flame_initial_guess.py +++ b/interfaces/cython/cantera/examples/onedim/flame_initial_guess.py @@ -32,113 +32,123 @@ # and may not be suitable for a publication-quality flame speed calculation refine_criteria = {"ratio": 3, "slope": 0.1, "curve": 0.2} f.set_refine_criteria(**refine_criteria) - -# Try to speed things up by loading the solution -yaml_filepath = os.path.join(data_directory, "flame.yaml") -try: - f.restore(yaml_filepath, name="solution", loglevel=0) -except: - print("Couldn't load yaml solution, so starting from scratch") - f.solve(loglevel=1, auto=True) -print("mixture-averaged flame speed = {:7f} m/s\n".format(f.velocity[0])) +def describe(flame): + "Print a short description of the flame, with a few properties." + print(f"Flame speed = {flame.velocity[0] * 100 :.2f} cm/s") + print(f"Maximum temperature = {flame.T.max() :.0f} K") + # Find the location of the peak OH mole fraction + oh_index = flame.gas.species_index("OH") + grid_index = flame.X[oh_index].argmax() + oh_peak = flame.grid[grid_index] + print(f"Peak OH mole fraction location = {oh_peak * 100 :.2f} cm") + print(f"Solved with {flame.grid.size} grid points") -def compare_flames(f1, f2): - """ - Compare two flame solutions f1 and f2 and check that they're the same. - Expects the grids to be exactly the same, as if you have restored - the solution. - """ - assert np.allclose(f1.grid, f2.grid), "Grid is different" - assert np.allclose(f1.T, f2.T), "Temperature profile is different" - assert np.allclose(f1.X[f.gas.species_index("CH4")], f2.X[f2.gas.species_index("CH4")] ), "Methane profile is different" +describe(f) -print("Save YAML and restore solution") +# Save the flame in a few different formats +print("Save YAML") yaml_filepath = os.path.join(data_directory, "flame.yaml") f.save(yaml_filepath, name="solution", description="Initial methane flame") + +print("Save CSV") +csv_filepath = os.path.join(data_directory, "flame.csv") +f.write_csv(csv_filepath) + +print("Save HDF") +hdf_filepath = os.path.join(data_directory, "flame.h5") +f.write_hdf( + hdf_filepath, + group="flame", + mode="w", + quiet=False, + description=("Initial methane flame"), +) + + +print("\nRestore solution from YAML") gas.TPX = Tin, p, reactants f2 = ct.FreeFlame(gas, width=width) f2.restore(yaml_filepath, name="solution", loglevel=0) -compare_flames(f, f2) +describe(f2) -print("Save HDF and restore solution") -hdf_filepath = os.path.join(data_directory, "flame.h5") -f.write_hdf(hdf_filepath, group="flame", mode="w", quiet=False, - description=("Initial methane flame")) +print("\nRestore solution from HDF") gas.TPX = Tin, p, reactants f2 = ct.FreeFlame(gas, width=width) f2.read_hdf(hdf_filepath, group="flame") -compare_flames(f, f2) +describe(f2) - -print("Save CSV then load initial guess via Pandas and SolutionArray") -# In Cantera v2.6.0 passing set_initial_guess a Pandas DataFrame crashes so you -# must use this work-around to create a SolutionArray from your DataFrame -# and then pass the SolutionArray to the set_initial_guess method. +print("\nLoad initial guess from CSV file directly") csv_filepath = os.path.join(data_directory, "flame.csv") f.write_csv(csv_filepath) -df = pd.read_csv(csv_filepath) -arr2 = ct.SolutionArray(gas) -arr2.from_pandas(df) -gas.TPX = Tin, p, reactants # must set the gas T back to the inlet before making new flame +gas.TPX = Tin, p, reactants # set the gas T back to the inlet before making new flame f2 = ct.FreeFlame(gas, width=width) -f2.set_initial_guess(data=arr2) -compare_flames(f, f2) +f2.set_initial_guess(data=csv_filepath) +describe(f2) -print("Save CSV then load initial guess via Pandas") +print("\nLoad initial guess from CSV file via Pandas") csv_filepath = os.path.join(data_directory, "flame.csv") f.write_csv(csv_filepath) df = pd.read_csv(csv_filepath) -gas.TPX = Tin, p, reactants # must set the gas T back to the inlet before making new flame +gas.TPX = Tin, p, reactants # set the gas T back to the inlet before making new flame f2 = ct.FreeFlame(gas, width=width) f2.set_initial_guess(data=df) -compare_flames(f, f2) +describe(f2) -print("Save CSV and load initial guess directly") -# This one fails -csv_filepath = os.path.join(data_directory, "flame.csv") -f.write_csv(csv_filepath) -gas.TPX = Tin, p, reactants # must set the gas T back to the inlet before making new flame + +print("\nLoad initial guess from CSV file via Pandas and SolutionArray") +# In Cantera v2.6.0 passing set_initial_guess a Pandas DataFrame crashed so you +# must use this work-around to create a SolutionArray from your DataFrame +# and then pass the SolutionArray to the set_initial_guess method. +df = pd.read_csv(csv_filepath) +arr2 = ct.SolutionArray(gas) +arr2.from_pandas(df) +gas.TPX = Tin, p, reactants +# set the gas T back to the inlet before making new flame f2 = ct.FreeFlame(gas, width=width) -f2.set_initial_guess(data=csv_filepath) -compare_flames(f, f2) +f2.set_initial_guess(data=arr2) +describe(f2) -print("Save CSV then load initial guess via Pandas, with modifications") -csv_filepath = os.path.join(data_directory, "flame.csv") -f.write_csv(csv_filepath) + +print("\nLoad initial guess from CSV file via Pandas, with modifications.") df = pd.read_csv(csv_filepath) -print("Modify the Pandas dataframe, removing half the grid points") -df_pruned = df[::2] # remove half of the grid points -gas.TPX = Tin, p, reactants # must set the gas T back to the inlet before making new flame +print("\nModify the Pandas dataframe, removing half the grid points") +df_pruned = df[::2] # remove half of the grid points +gas.TPX = Tin, p, reactants # set the gas T back to the inlet before making new flame f2 = ct.FreeFlame(gas, width=width) f2.set_refine_criteria(**refine_criteria) f2.set_initial_guess(data=df_pruned) f2.solve() -# We wouldn't expect the flame solutions to be exactly the same, so we just check a few other properties -assert np.isclose(f.velocity[0], f2.velocity[0], 1e-2 ), "Flame speeds not within 1%" -assert np.allclose(f.X.max(axis=1), f2.X.max(axis=1), rtol=0.2, atol=1e-20), "Max mole fractions not within 20%" - -print("Modify the Pandas dataframe, removing half the grid points and all but the first 20 species") -df_pruned = df.iloc[::2,:24] -gas.TPX = Tin, p, reactants # must set the gas T back to the inlet before making new flame +# We wouldn't expect the flame solutions to be exactly the same +describe(f2) + +print( + "\nModify the Pandas dataframe, removing half the grid points " + "and all but the first 20 species" +) +df_pruned = df.iloc[::2, :24] +gas.TPX = Tin, p, reactants # set the gas T back to the inlet before making new flame f2 = ct.FreeFlame(gas, width=width) f2.set_refine_criteria(**refine_criteria) f2.set_initial_guess(data=df_pruned) f2.solve() -# We wouldn't expect the flame solutions to be exactly the same, so we just check a few other properties -assert np.isclose(f.velocity[0], f2.velocity[0], 1e-2 ), "Flame speeds not within 1%" -assert np.allclose(f.X.max(axis=1), f2.X.max(axis=1), rtol=0.2, atol=1e-20), "Max mole fractions not within 20%" +# We wouldn't expect the flame solutions to be exactly the same +describe(f2) -print("Modify the Pandas dataframe, removing half the grid points, and raise the T by 50 K") +print( + "\nModify the Pandas dataframe, removing half the grid points, " + "and raise the T by 50 K" +) df_pruned = df.iloc[::2] -gas.TPX = Tin + 50, p, reactants # must set the gas T back to the (new) inlet before making new flame +# set the gas T back to the (new) inlet before making new flame +gas.TPX = (Tin + 50, p, reactants) f2 = ct.FreeFlame(gas, width=width) f2.set_refine_criteria(**refine_criteria) f2.set_initial_guess(data=df_pruned) f2.solve() # We expect thees flames to be different because we raised the temperature. -assert f2.velocity[0] / f.velocity[0] > 1.1, "Flame speed hasn't increased by more than 10%" +describe(f2) -print("All done") +print("\nAll done")