Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 102 additions & 14 deletions Common/DataDrivenConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,10 +786,13 @@ class Config_FGM(Config):
__generate_extra_interpolated_burnerflames:bool = True # Generate extra interpolated burner-stabilized flamelets
__generate_equilibrium:bool = DefaultSettings_FGM.include_equilibrium # Generate chemical equilibrium data
__generate_counterflames:bool = DefaultSettings_FGM.include_counterflames # Generate counter-flow diffusion flamelets.
__counterflow_fixed_strain:bool = DefaultSettings_FGM.counterflow_fixed_strain # Fixed-strain mode for counterflow flames.
__counterflow_strain_rate:float = DefaultSettings_FGM.counterflow_strain_rate # Global strain rate [1/s] for fixed-strain mode.

__flamelet_types:list[str] = [FlameletSolverOptions[0]]

__write_MATLAB_files:bool = False # Write TableGenerator compatible flamelet files.
__save_mole_fractions:bool = False # Save mole fractions (X-) in flamelet CSV files.

gas:ct.Solution = None # Cantera solution object.
__species_in_mixture:list[str] = None # Species names in mixture.
Expand Down Expand Up @@ -859,6 +862,9 @@ def __init__(self, load_file:str=None):
self.__dict__ = loaded_config.__dict__.copy()
print("Loaded configuration file with name " + loaded_config.GetConfigName())
else:
# Initialize __flamelet_types as an instance variable (not shared class variable)
self._Config_FGM__flamelet_types = [FlameletSolverOptions[0]]

self.SetAlphaExpo(DefaultSettings_FGM.init_learning_rate_expo)
self.SetLRDecay(DefaultSettings_FGM.learning_rate_decay)
self.SetBatchExpo(DefaultSettings_FGM.batch_size_exponent)
Expand Down Expand Up @@ -964,7 +970,10 @@ def PrintBanner(self):
if self.__generate_equilibrium:
print("-Chemical equilibrium data")
if self.__generate_counterflames:
print("-Counter-flow diffusion flamelet data")
if self.__counterflow_fixed_strain:
print("-Counter-flow diffusion flamelet data (fixed strain rate: %.1f 1/s)" % self.__counterflow_strain_rate)
else:
print("-Counter-flow diffusion flamelet data (ramp to extinction)")
print("")

print("Flamelet manifold data characteristics: ")
Expand Down Expand Up @@ -1495,36 +1504,36 @@ def includeFlameletType(self, flamelet_type:str="FREEFLAME"):

if flamelet_type not in FlameletSolverOptions:
raise Exception("%s is not recognized as a viable flamelet type" % flamelet_type)

if flamelet_type not in self.__flamelet_types:
self.__flamelet_types.append(flamelet_type)

return

def setFlameletTypes(self, flamelet_types:list[str]):
self.__flamelet_types = flamelet_types.copy()
self.__checkFlameletTypes()
return

def __checkFlameletTypes(self):
self.__generate_burnerflames = "BURNERFLAME" in self.__flamelet_types
self.__generate_freeflames = "FREEFLAME" in self.__flamelet_types
self.__generate_counterflames = "COUNTERFLAME" in self.__flamelet_types
self.__generate_equilibrium = "EQUILIBRIUM" in self.__flamelet_types
self.__generate_extra_interpolated_burnerflames = "BURNERFLAME_INT" in self.__flamelet_types
return

def excludeFlameletType(self, flamelet_type:str):
if flamelet_type not in FlameletSolverOptions:
raise Exception("%s is not recognized as a viable flamelet type" % flamelet_type)

if flamelet_type in self.__flamelet_types:
self.__flamelet_types.remove(flamelet_type)

self.__checkFlameletTypes()
if len(self.__flamelet_types) == 0:
raise Exception("At least one flamelet type should be included in the manifold")
# Allow empty list temporarily during configuration setup
# Validation will happen when the config is actually used

return

def getFlameletTypes(self):
Expand All @@ -1539,7 +1548,10 @@ def RunFreeFlames(self, input:bool=DefaultSettings_FGM.include_freeflames):

"""
self.__generate_freeflames = input
self.includeFlameletType("FREEFLAME")
if input:
self.includeFlameletType("FREEFLAME")
else:
self.excludeFlameletType("FREEFLAME")
return
def RunBurnerFlames(self, input:bool=DefaultSettings_FGM.include_burnerflames):
"""
Expand All @@ -1550,7 +1562,10 @@ def RunBurnerFlames(self, input:bool=DefaultSettings_FGM.include_burnerflames):

"""
self.__generate_burnerflames = input
self.includeFlameletType("BURNERFLAME")
if input:
self.includeFlameletType("BURNERFLAME")
else:
self.excludeFlameletType("BURNERFLAME")
return

def RunEquilibrium(self, input:bool=DefaultSettings_FGM.include_equilibrium):
Expand All @@ -1562,7 +1577,10 @@ def RunEquilibrium(self, input:bool=DefaultSettings_FGM.include_equilibrium):

"""
self.__generate_equilibrium = input
self.includeFlameletType("EQUILIBRIUM")
if input:
self.includeFlameletType("EQUILIBRIUM")
else:
self.excludeFlameletType("EQUILIBRIUM")
return

def RunCounterFlames(self, input:bool=DefaultSettings_FGM.include_counterflames):
Expand All @@ -1574,7 +1592,10 @@ def RunCounterFlames(self, input:bool=DefaultSettings_FGM.include_counterflames)

"""
self.__generate_counterflames = input
self.includeFlameletType("COUNTERFLAME")
if input:
self.includeFlameletType("COUNTERFLAME")
else:
self.excludeFlameletType("COUNTERFLAME")
return

def RunExtraInterpolatedBurnerFlames(self, input:bool=True):
Expand All @@ -1586,7 +1607,10 @@ def RunExtraInterpolatedBurnerFlames(self, input:bool=True):

"""
self.__generate_extra_interpolated_burnerflames = input
self.includeFlameletType("INT_BURNERFLAME")
if input:
self.includeFlameletType("INT_BURNERFLAME")
else:
self.excludeFlameletType("INT_BURNERFLAME")
return

def GenerateFreeFlames(self):
Expand Down Expand Up @@ -1625,6 +1649,70 @@ def GenerateCounterFlames(self):
"""
return self.__generate_counterflames

def SetCounterFlowFixedStrain(self, fixed:bool=True):
"""
Select fixed-strain-rate mode for counter-flow diffusion flames.

When True, one flame is solved per temperature level at the strain rate
set by SetCounterFlowStrainRate. When False (default), the existing
ramp-to-extinction behaviour is used.

:param fixed: enable fixed-strain mode.
:type fixed: bool
"""
self.__counterflow_fixed_strain = fixed
return

def GetCounterFlowFixedStrain(self) -> bool:
"""
Whether fixed-strain mode is enabled for counter-flow flames.

:return: fixed-strain mode is active.
:rtype: bool
"""
return self.__counterflow_fixed_strain

def SetCounterFlowStrainRate(self, strain_rate:float):
"""
Set the global strain rate used in fixed-strain counter-flow flame mode.

:param strain_rate: global strain rate in 1/s.
:type strain_rate: float
:raises Exception: if strain_rate is not strictly positive.
"""
if strain_rate <= 0:
raise Exception("Counter-flow strain rate must be strictly positive.")
self.__counterflow_strain_rate = strain_rate
return

def GetCounterFlowStrainRate(self) -> float:
"""
Return the global strain rate used in fixed-strain counter-flow flame mode.

:return: global strain rate [1/s].
:rtype: float
"""
return self.__counterflow_strain_rate

def SetSaveMoleFractions(self, save_mole_fractions:bool):
"""
Enable or disable saving mole fractions (X-species) in flamelet CSV files.

:param save_mole_fractions: whether to save mole fractions alongside mass fractions.
:type save_mole_fractions: bool
"""
self.__save_mole_fractions = save_mole_fractions
return

def GetSaveMoleFractions(self) -> bool:
"""
Check whether mole fractions (X-species) should be saved in flamelet CSV files.

:return: True if mole fractions should be saved.
:rtype: bool
"""
return self.__save_mole_fractions

def GenerateExtraInterpolatedBurnerFlames(self):
"""
Whether the manifold data contains extra interpolated burner-stabilized flame data.
Expand Down
3 changes: 3 additions & 0 deletions Common/Properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ class DefaultSettings_FGM(DefaultProperties):
include_equilibrium:bool = True
include_counterflames:bool = False

counterflow_fixed_strain:bool = False # False = ramp-to-extinction; True = fixed strain rate
counterflow_strain_rate:float = 56.0 # global strain rate [1/s] for fixed-strain mode

affinity_threshold:float = 0.7
output_file_header:str = "flamelet_data"
boundary_file_header:str = "boundary_data"
Expand Down
70 changes: 61 additions & 9 deletions Data_Generation/DataGenerator_FGM.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class DataGenerator_Cantera(DataGenerator_Base):
__define_equivalence_ratio:bool = not DefaultSettings_FGM.run_mixture_fraction # Define unburnt mixture via the equivalence ratio
__unb_mixture_status:list[float] = []
__flameletSolverDict:Dict[str, FlameletSolver_Cantera]

__run_freeflames:bool = DefaultSettings_FGM.include_freeflames # Run adiabatic flame computations
__run_extra_interpolated_burnerflames:bool = True # Run extra interpolated burner-stabilized flame computations
__run_burnerflames:bool = DefaultSettings_FGM.include_burnerflames # Run burner stabilized flame computations
Expand Down Expand Up @@ -138,17 +138,22 @@ def __SynchronizeSettings(self):
def SetLoglevel(self, loglevel:int=0):
"""Set Cantera solver verbosity level (0=silent)."""
self.__loglevel = loglevel
# Propagate loglevel to all existing flamelet solvers
for solver in self.__flameletSolverDict.values():
solver.setCanteraVerbose(loglevel)
solver.setSolverVerbose(loglevel)

def SetInitialGridLength(self, length:float):
"""Set the initial domain length (in metres) for new flamelet grids."""
self.__initial_grid_length = length

def setRefinementCriteria(self, flamelet_type:str, ratio:float=3, slope:float=0.03, curve:float=0.03, prune:float=0.01):
if flamelet_type not in self.__flameletSolverDict.keys():
raise Exception("%s is included in the available flamelet types" % flamelet_type)
available = list(self.__flameletSolverDict.keys())
raise Exception("%s is NOT included in the available flamelet types. Available: %s" % (flamelet_type, available))
self.__flameletSolverDict[flamelet_type].setGridRefinementCriteria(ratio, slope, curve, prune)
return


def SetMdotDHTarget(self, dH_target:float):
"""Set the target enthalpy step between successive burner-stabilized flamelets.
Expand Down Expand Up @@ -316,6 +321,48 @@ def RunExtraInterpolatedBurnerFlames(self, input:bool=True):
self.__SynchronizeSettings()
return

def SetFreeFlameRefineCriteria(self, **kwargs):
"""Set refinement criteria for free-flame solver using the existing setRefinementCriteria method.

This is a convenience wrapper that calls setRefinementCriteria with flamelet_type="FREEFLAME".

:param ratio: refinement ratio
:type ratio: int, optional
:param slope: refinement slope criterion
:type slope: float, optional
:param curve: refinement curvature criterion
:type curve: float, optional
:param prune: refinement prune criterion
:type prune: float, optional
"""
ratio = kwargs.get('ratio', 2)
slope = kwargs.get('slope', 0.025)
curve = kwargs.get('curve', 0.025)
prune = kwargs.get('prune', 0.01)
self.setRefinementCriteria("FREEFLAME", ratio, slope, curve, prune)
return

def SetBurnerFlameRefineCriteria(self, **kwargs):
"""Set refinement criteria for burner-flame solver using the existing setRefinementCriteria method.

This is a convenience wrapper that calls setRefinementCriteria with flamelet_type="BURNERFLAME".

:param ratio: refinement ratio
:type ratio: int, optional
:param slope: refinement slope criterion
:type slope: float, optional
:param curve: refinement curvature criterion
:type curve: float, optional
:param prune: refinement prune criterion
:type prune: float, optional
"""
ratio = kwargs.get('ratio', 2)
slope = kwargs.get('slope', 0.025)
curve = kwargs.get('curve', 0.025)
prune = kwargs.get('prune', 0.01)
self.setRefinementCriteria("BURNERFLAME", ratio, slope, curve, prune)
return

def SetNpMdotExtra(self, n_extra:int):
"""Set the number of interpolation steps for extra interpolated burner-stabilized flamelets.

Expand All @@ -339,7 +386,7 @@ def SetMixtureValues(self, mixture_values:list[float]):
raise Exception("At least one mixture status value should be provided.")
if any([phi < 0 for phi in mixture_values]):
raise Exception("Mixture values should be strictly positive")

self.__unb_mixture_status = [phi for phi in mixture_values]
return

Expand Down Expand Up @@ -390,7 +437,7 @@ def computePremixedFlameletsFor(self, mix_status:float):

if mix_status < 0:
raise Exception("Mixture status value should be positive.")

correct_order = FlameletSolverDict.keys()
for c in correct_order:
if c in self.__flameletSolverDict.keys() and c != "COUNTERFLAME":
Expand All @@ -399,12 +446,12 @@ def computePremixedFlameletsFor(self, mix_status:float):
flameletSolver.solveForMixtureStatus(mix_status)

return

def computeNonPremixedFlamelets(self):
if "COUNTERFLAME" in self.__flameletSolverDict.keys():
self.__flameletSolverDict["COUNTERFLAME"].solveForMixtureStatus(0)
return

def ComputeFlamelets(self):
"""Generate and store all flamelet data for the current settings.
"""
Expand All @@ -414,9 +461,9 @@ def ComputeFlamelets(self):
for mix_status in self.__unb_mixture_status:
self.computePremixedFlameletsFor(mix_status)
return

def ComputeFlameletData(Config:Config_FGM, run_parallel:bool=False, N_processors:int=2, loglevel:int=0,
free_flame_refine:dict=None, burner_flame_refine:dict=None):
free_flame_refine:dict=None, burner_flame_refine:dict=None, counter_flame_refine:dict=None):
"""Generate flamelet data according to Config_FGM settings either in serial or parallel.

:param Config: Config_FGM class containing manifold and flamelet generation settings.
Expand All @@ -433,6 +480,9 @@ def ComputeFlameletData(Config:Config_FGM, run_parallel:bool=False, N_processors
:param burner_flame_refine: Cantera burner-flame refinement criteria dict with keys ratio, slope, curve, prune.
If None, the DataGenerator_Cantera defaults are used.
:type burner_flame_refine: dict, optional
:param counter_flame_refine: Cantera counter-flow flame refinement criteria dict with keys ratio, slope, curve, prune.
If None, the DataGenerator_Cantera defaults are used.
:type counter_flame_refine: dict, optional
:raises Exception: If number of processors is set to zero when running in parallel.
"""

Expand Down Expand Up @@ -460,6 +510,8 @@ def _make_generator():
F.SetFreeFlameRefineCriteria(**free_flame_refine)
if burner_flame_refine is not None:
F.SetBurnerFlameRefineCriteria(**burner_flame_refine)
if counter_flame_refine is not None:
F.setRefinementCriteria("COUNTERFLAME", **counter_flame_refine)
return F

# Set up Cantera flamelet generator object
Expand Down
Loading
Loading