# -*- coding: utf-8 -*-
"""Flash Config parser.
:copyright: Copyright (c) 2021 RadiaSoft LLC. All Rights Reserved.
:license: http://www.apache.org/licenses/LICENSE-2.0.html
"""
from pykern import pkio
from pykern.pkcollections import PKDict
from pykern.pkdebug import pkdc, pkdp, pkdlog
import inspect
import re
def _fields(templates, values):
# template: [field template, label template]
# values: values to insert into the field/label templates
return {t[0].format(v): t[1].format(v.upper()) for v in values for t in templates}
def _sim_fields(schema, model_name, fields):
# any model field may be overtaken by the main simulation Config
n = "Simulation_SimulationMain_flashApp"
res = []
for f in fields:
if n in schema.model and f in schema.model[n]:
res.append(f"{n}.{f}")
else:
res.append(f"{model_name}.{f}")
return res
[docs]
class SpecializedViews:
# POSIT: FLASH field names are unique so flat list is ok
_LABELS = PKDict(
LimitedSlopeBeta="Limited Slope Beta",
RiemannSolver="Riemann Solver",
UnitSystem="System of Units",
allowDtSTSDominate="allowDtSTSDominate",
cfl="Courant Factor",
charLimiting="Characteristic Limiting",
cvisc="Artificial Viscosity Constant",
diff_eleFlCoef="Flux Limiter Coefficient",
diff_eleXlBoundaryType="X Left Boundary",
diff_eleXrBoundaryType="X Right Boundary",
diff_eleYlBoundaryType="Y Left Boundary",
diff_eleYrBoundaryType="Y Right Boundary",
diff_eleZlBoundaryType="Z Left Boundary",
diff_eleZrBoundaryType="Z Right Boundary",
diff_thetaImplct="Implicitness Factor",
diff_useEleCond="Use Ele Conduction",
dt_diff_factor="Timestep Factor",
dtinit="Initial Timestep [s]",
dtmax="Maximum Timestep",
dtmin="Minimum Timestep",
ed_crossSectionFunctionType_1="Cross Section Function Type",
ed_gaussianCenterMajor_1="Major Gaussian Center",
ed_gaussianCenterMinor_1="Minor Gaussian Center",
ed_gaussianExponent_1="Gaussian Exponent",
ed_gaussianRadiusMajor_1="Major Gaussian Radius",
ed_gaussianRadiusMinor_1="Minor Gaussian Radius",
ed_gradOrder="Gradient Order",
ed_gridType_1="Type of Beam Grid",
ed_laser3Din2D="3D Ray Tracing",
ed_laser3Din2DwedgeAngle="Wedge Angle",
ed_laserIOMaxNumberOfPositions="Max Ray Positions",
ed_laserIOMaxNumberOfRays="Max Rays",
ed_lensSemiAxisMajor_1="Lens Semi Axis Major",
ed_lensX_1="Lens X",
ed_lensY_1="Lens Y",
ed_lensZ_1="Lens Z",
ed_maxRayCount="Max Ray Count",
ed_numberOfBeams="Number of Beams",
ed_numberOfPulses="Number of Pulses",
ed_numberOfRays_1="Number of Rays",
ed_numberOfSections_1="Number of Sections",
ed_power_1_1="Laser Pulse Section 1",
ed_power_1_2="Laser Pulse Section 2",
ed_power_1_3="Laser Pulse Section 3",
ed_power_1_4="Laser Pulse Section 4",
ed_pulseNumber_1="Pulse Number",
ed_semiAxisMajorTorsionAngle_1="Major Semiaxis Torsion Angle",
ed_semiAxisMajorTorsionAxis_1="Major Semiaxis Torsion Axis",
ed_targetSemiAxisMajor_1="Major Target Semiaxis",
ed_targetSemiAxisMinor_1="Minor Target Semiaxis",
ed_targetX_1="X Target",
ed_targetY_1="Y Target",
ed_targetZ_1="Z Target",
ed_time_1_1="Laser Pulse Section 1",
ed_time_1_2="Laser Pulse Section 2",
ed_time_1_3="Laser Pulse Section 3",
ed_time_1_4="Laser Pulse Section 4",
ed_useLaserIO="Use Laser IO",
ed_wavelength_1="Wavelength",
entropy="Entropy Fix",
eosMode="Eos Mode",
eosModeInit="Initial Eos Mode",
fl_b="Flame Width",
fl_epsilon_0="Lower Sharpening Factor",
fl_epsilon_1="Upper Sharpening Factor",
fl_fsConstFlameSpeed="Constant Flame Speed",
fl_kpp_fact="Prefactor Adjustment",
flame_deltae="Flame Delta e",
gconst="Acceleration Constant",
gdirec="Direction of Acceleration",
geometry="Grid Geometry",
grav_boundary_type="Boundary Condition",
lrefine_max="Maximum Refinement Level",
lrefine_min="Minimum Refinement Level",
nend="Maximum Number of Timesteps",
order="Order",
plotFileIntervalTime="Plot File Interval Time [s]",
refine_var_count="Refine Variable Count",
rt_dtFactor="Time Step Coefficient",
rt_mgdBounds_1="Boundary 1",
rt_mgdBounds_2="Boundary 2",
rt_mgdBounds_3="Boundary 3",
rt_mgdBounds_4="Boundary 4",
rt_mgdBounds_5="Boundary 5",
rt_mgdBounds_6="Boundary 6",
rt_mgdBounds_7="Boundary 7",
rt_mgdFlCoef="MGD Flux Limiter Coefficient",
rt_mgdFlMode="MGD Glux Limiter Mode",
rt_mgdNumGroups="Number of Groups",
rt_mgdXlBoundaryType="X MGD Left Boundary",
rt_mgdXrBoundaryType="X MGD Right Boundary",
rt_mgdYlBoundaryType="Y MGD Left Boundary",
rt_mgdYrBoundaryType="Y MGD Right Boundary",
rt_mgdZlBoundaryType="Z MGD Left Boundary",
rt_mgdZrBoundaryType="Z MGD Right Boundary",
rt_useMGD="Use Multigroup Radiation Diffusion",
shockDetect="Use Strong Compressive Shock Detection",
slopeLimiter="Slope Limiter",
sumyi_burned="Burned sumyi",
sumyi_unburned="Unburned sumyi",
threadHydroBlockList="Block List Threading",
threadHydroWithinBlock="Within Block Threading",
tmax="Maximum Simulation Time [s]",
updateHydroFluxes="Update Hydro Fluxes",
useDiffuse="Use Diffusive Effects",
useEnergyDeposition="Use Energy Deposition",
useFlame="Use Flame",
useGravity="Use Gravity",
useHydro="Use Hydro Calculation",
useRadTrans="Use Radiative Transfer",
use_cma_advection="Use CMA Advection",
use_cma_flattening="Use CMA Flattening",
ye_burned="Burned ye",
ye_unburned="Unburned ye",
**_fields(
[
["{}l_boundary_type", "{} Lower Boundary Type"],
["{}r_boundary_type", "{} Upper Boundary Type"],
["{}min", "{} Minimum"],
["{}max", "{} Maximum"],
["nblock{}", "Blocks in {}"],
],
["x", "y", "z"],
),
**_fields(
[
["refine_var_{}", "Name Variable {}"],
["refine_cutoff_{}", "Refine Variable {}"],
["derefine_cutoff_{}", "Derefine Variable {}"],
],
[str(v) for v in range(1, 7)],
),
)
_VIEW_FUNC_PREFIX = "_view_"
def __init__(self):
self._view_fns = PKDict()
for n, o in inspect.getmembers(self):
if n.startswith(self._VIEW_FUNC_PREFIX) and inspect.ismethod(o):
self._view_fns[n[len(self._VIEW_FUNC_PREFIX) :]] = o
[docs]
def update_schema(self, schema):
self._update_labels(schema)
self._update_views(schema)
return schema
def _assert_model_view_fields_exist(self, name, view, schema):
"""Check that model fields in view exist in models"""
def flatten(to_flatten):
def flatten_column(to_flatten):
if isinstance(to_flatten[0], str):
return flatten(to_flatten[1])
res = []
for f in to_flatten:
res += flatten_column(f)
return res
res = []
for f in to_flatten:
if isinstance(f, str):
res.append(f)
continue
assert isinstance(f, list), "uknown type f={f}"
res += flatten_column(f)
return res
for f in flatten(view.get("basic", []) + view.get("advanced", [])):
if "." not in f:
f = f"{name}.{f}"
p = f.split(".")
assert (
p[0] in schema.model
), f"model name={p[0]} does not exist in known models={schema.model.keys()}"
assert (
p[1] in schema.model[p[0]]
), f"field={p[1]} name={p[0]} does not exist in model={schema.model[p[0]]}"
def _get_species_list(self, schema):
res = []
for f in schema.model.Multispecies_MultispeciesMain:
m = re.search(r"eos_(.*)EosType", f)
if m:
res.append(m.group(1))
return res
def _update_labels(self, schema):
labels = self._LABELS.copy()
self._update_sim_labels(schema, labels)
self._update_multispecies_labels(schema, labels)
for m in schema.model.values():
for f in m:
if f not in labels:
continue
info = m[f]
if len(info) == 3:
info.append(f)
elif info[3]:
info[3] = "{} {}".format(f, info[3])
else:
info[3] = f
info[0] = labels[f]
def _update_multispecies_labels(self, schema, labels):
if "Multispecies_MultispeciesMain" not in schema.model:
return
for s in self._get_species_list(schema):
for f, label in {
"ms_{}A": "Number of protons and neutrons in nucleus",
"ms_{}Z": "Atomic number",
"ms_{}ZMin": "Minimum allowed average ionization",
"eos_{}EosType": "EOS type to use for MTMMMT EOS",
"eos_{}SubType": "EOS subtype to use for MTMMMT EOS",
"ms_{}Gamma": "Ratio of heat capacities",
"eos_{}TableFile": "Tabulated EOS file name",
"op_{}Absorb": "Absorption",
"op_{}Emiss": "Emission",
"op_{}Trans": "Transport",
}.items():
labels[f.format(s)] = f"{s.title()} {label}"
def _update_sim_labels(self, schema, labels):
# TODO(pjm): use constant for flashApp model
# special case for main simulation labels - use full description as label
for f, info in schema.model.Simulation_SimulationMain_flashApp.items():
if len(info) > 3:
labels[f] = info[3]
info[3] = ""
def _update_views(self, schema):
for n, f in self._view_fns.items():
if n not in schema.view:
continue
v = f(schema)
if v:
self._assert_model_view_fields_exist(n, v, schema)
schema.view[n].update(v)
def _view_Driver_DriverMain(self, schema):
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4p2.py?submit=rp_Driver.txt
v = PKDict(
title="Simulation Driver",
advanced=[
[
"Driver",
[
"dr_abortPause",
"dr_dtMinBelowAction",
"dr_dtMinContinue",
"dr_numPosdefVars",
"dr_posdefDtFactor",
"dr_posdefVar_1",
"dr_posdefVar_2",
"dr_posdefVar_3",
"dr_posdefVar_4",
"dr_printTStepLoc",
"dr_shortenLastStepBeforeTMax",
"dr_tstepSlowStartFactor",
"dr_usePosdefComputeDt",
],
],
[
"Drift",
[
"drift_break_inst",
"drift_trunc_mantissa",
"drift_tuples",
"drift_verbose_inst",
],
],
[
"Time",
[
"wall_clock_time_limit",
"tinitial",
],
],
[
"Timestep",
[
"tstep_change_factor",
"nbegin",
"nend",
"useSTS",
"useSTSforDiffusion",
"nuSTS",
"nstepTotalSTS",
],
],
[
"Thread",
[
"threadBlockListBuild",
"threadDriverBlockList",
"threadDriverWithinBlock",
"threadRayTraceBuild",
"threadWithinBlockBuild",
],
],
[
"Redshift",
[
"zInitial",
"zFinal",
],
],
[
"Other",
[
"meshCopyCount",
"sweepOrder",
],
],
],
basic=[
"tmax",
"dtinit",
"nend",
"allowDtSTSDominate",
],
)
if "IO_IOMain" in schema.model:
v.basic.append("IO_IOMain.plotFileIntervalTime")
return v
def _view_physics_Diffuse_DiffuseMain(self, schema):
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4p2.py?submit=rp_Diffuse.txt
v = PKDict(
title="Diffusive Effects",
basic=[
"diff_eleFlMode",
"diff_eleFlCoef",
"dt_diff_factor",
[
[
"X",
[
"diff_eleXlBoundaryType",
"diff_eleXrBoundaryType",
],
],
[
"Y",
[
"diff_eleYlBoundaryType",
"diff_eleYrBoundaryType",
],
],
[
"Z",
[
"diff_eleZlBoundaryType",
"diff_eleZrBoundaryType",
],
],
],
],
)
if "physics_Diffuse_DiffuseMain_Unsplit" in schema.model:
v.basic.insert(3, "physics_Diffuse_DiffuseMain_Unsplit.diff_thetaImplct")
if "physics_Diffuse_DiffuseMain" in schema.model:
v.basic.insert(0, "physics_Diffuse_DiffuseMain.diff_useEleCond")
v.basic.insert(0, "physics_Diffuse_DiffuseMain.useDiffuse")
return v
def _view_physics_Gravity_GravityMain(self, schema):
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4p2.py?submit=rp_Gravity.txt
v = PKDict(
basic=[
"useGravity",
],
)
if "physics_Gravity" in schema.model:
# Flash docs seem to be wrong. useGravity does not exist in
# physics/Gravity. Just physics/Gravity/GravityMain
v.basic.insert(1, "physics_Gravity.grav_boundary_type")
if "physics_Gravity_GravityMain_Constant" in schema.model:
v.basic.extend(
[
"physics_Gravity_GravityMain_Constant.gconst",
"physics_Gravity_GravityMain_Constant.gdirec",
]
)
return v
def _view_Grid_GridMain(self, schema):
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4p2.py?submit=rp_Grid.txt
v = PKDict(
title="Grid",
basic=[
[
"Main",
[
"geometry",
"eosModeInit",
"eosMode",
[
[
"X",
[
"xl_boundary_type",
"xr_boundary_type",
"xmin",
"xmax",
],
],
[
"Y",
[
"yl_boundary_type",
"yr_boundary_type",
"ymin",
"ymax",
],
],
[
"Z",
[
"zl_boundary_type",
"zr_boundary_type",
"zmin",
"zmax",
],
],
],
],
],
],
)
if "Grid_GridMain_paramesh" in schema.model:
v.basic.append(
[
"Paramesh",
[
"Grid_GridMain_paramesh.nblockx",
"Grid_GridMain_paramesh.nblocky",
"Grid_GridMain_paramesh.nblockz",
"Grid_GridMain_paramesh.lrefine_min",
"Grid_GridMain_paramesh.lrefine_max",
"Grid_GridMain_paramesh.refine_var_count",
[
[
"Name",
[
# TODO(pjm): this should apply to all view fields
# fields may be defined on main flash app module
*_sim_fields(
schema,
"Grid_GridMain_paramesh",
[
"refine_var_1",
"refine_var_2",
"refine_var_3",
"refine_var_4",
],
),
],
],
[
"Refine Cutoff",
[
"Grid_GridMain_paramesh.refine_cutoff_1",
"Grid_GridMain_paramesh.refine_cutoff_2",
"Grid_GridMain_paramesh.refine_cutoff_3",
"Grid_GridMain_paramesh.refine_cutoff_4",
],
],
[
"Derefine Cutoff",
[
"Grid_GridMain_paramesh.derefine_cutoff_1",
"Grid_GridMain_paramesh.derefine_cutoff_2",
"Grid_GridMain_paramesh.derefine_cutoff_3",
"Grid_GridMain_paramesh.derefine_cutoff_4",
],
],
],
],
],
)
return v
def _view_physics_Hydro_HydroMain(self, schema):
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4p2.py?submit=rp_Hydro.txt
v = PKDict(
title="Hydrodynamics",
basic=[
"useHydro",
"cfl",
],
fieldsPerTab=10,
)
if "physics_Hydro_HydroMain_unsplit" in schema.model:
v.basic.extend(
[
"physics_Hydro_HydroMain_unsplit.order",
"physics_Hydro_HydroMain_unsplit.slopeLimiter",
"physics_Hydro_HydroMain_unsplit.LimitedSlopeBeta",
"physics_Hydro_HydroMain_unsplit.charLimiting",
"physics_Hydro_HydroMain_unsplit.cvisc",
"physics_Hydro_HydroMain_unsplit.RiemannSolver",
"physics_Hydro_HydroMain_unsplit.entropy",
"physics_Hydro_HydroMain_unsplit.shockDetect",
]
)
return v
def _view_physics_materialProperties_Opacity_OpacityMain_Multispecies(self, schema):
v = PKDict(title="Material Properties", basic=[])
if "physics_materialProperties_Opacity_OpacityMain" in schema.model:
v.basic.append("physics_materialProperties_Opacity_OpacityMain.useOpacity")
if "physics_materialProperties_Conductivity_ConductivityMain" in schema.model:
v.basic.append(
"physics_materialProperties_Conductivity_ConductivityMain.useConductivity"
)
if (
"physics_materialProperties_MagneticResistivity_MagneticResistivityMain"
in schema.model
):
v.basic.append(
"physics_materialProperties_MagneticResistivity_MagneticResistivityMain.useMagneticResistivity"
)
v.basic.append([])
for s in self._get_species_list(schema):
v.basic[-1].append(
[
s.title(),
[
f"physics_materialProperties_Opacity_OpacityMain_Multispecies.op_{s}Absorb",
f"physics_materialProperties_Opacity_OpacityMain_Multispecies.op_{s}Emiss",
f"physics_materialProperties_Opacity_OpacityMain_Multispecies.op_{s}Trans",
],
],
)
return v
def _view_Multispecies_MultispeciesMain(self, schema):
v = PKDict(
title="Multispecies",
basic=[
[],
],
)
for s in self._get_species_list(schema):
v.basic[-1].append(
[
s.title(),
[
f"ms_{s}A",
f"ms_{s}Z",
f"ms_{s}ZMin",
f"eos_{s}EosType",
f"eos_{s}SubType",
f"eos_{s}TableFile",
],
],
)
return v
def _view_physics_RadTrans_RadTransMain_MGD(self, schema):
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4.py?submit=rp_RadTrans.txt
v = PKDict(
title="Radiative Transfer",
basic=[
[
"Main",
[
"rt_useMGD",
"rt_mgdFlMode",
"rt_mgdFlCoef",
[
[
"X",
[
"rt_mgdXlBoundaryType",
"rt_mgdXrBoundaryType",
],
],
[
"Y",
[
"rt_mgdYlBoundaryType",
"rt_mgdYrBoundaryType",
],
],
[
"Z",
[
"rt_mgdZlBoundaryType",
"rt_mgdZrBoundaryType",
],
],
],
],
],
[
"MGD Groups",
[
"rt_mgdNumGroups",
"rt_mgdBounds_1",
"rt_mgdBounds_2",
"rt_mgdBounds_3",
"rt_mgdBounds_4",
"rt_mgdBounds_5",
"rt_mgdBounds_6",
"rt_mgdBounds_7",
],
],
],
)
if "physics_RadTrans_RadTransMain" in schema.model:
v.basic[0][1].insert(0, "physics_RadTrans_RadTransMain.rt_dtFactor")
v.basic[0][1].insert(0, "physics_RadTrans_RadTransMain.useRadTrans")
return v
def _view_physics_sourceTerms_EnergyDeposition_EnergyDepositionMain_Laser(
self, schema
):
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4p22.py?submit=rp_EnergyDeposition.txt
v = PKDict(
title="Energy Deposition - Laser",
basic=[
[
"Bulk",
[
"useEnergyDeposition",
"ed_maxRayCount",
"ed_gradOrder",
"ed_laser3Din2D",
"ed_laser3Din2DwedgeAngle",
"physics_sourceTerms_EnergyDeposition_EnergyDepositionMain_Laser_LaserIO.ed_useLaserIO",
"physics_sourceTerms_EnergyDeposition_EnergyDepositionMain_Laser_LaserIO.ed_laserIOMaxNumberOfPositions",
"physics_sourceTerms_EnergyDeposition_EnergyDepositionMain_Laser_LaserIO.ed_laserIOMaxNumberOfRays",
],
],
[
"Pulse 1",
[
"ed_numberOfPulses",
"ed_numberOfSections_1",
[
[
"Time",
[
"ed_time_1_1",
"ed_time_1_2",
"ed_time_1_3",
"ed_time_1_4",
],
],
[
"Power",
[
"ed_power_1_1",
"ed_power_1_2",
"ed_power_1_3",
"ed_power_1_4",
],
],
],
],
],
[
"Beam 1",
[
[
[
"X",
[
"ed_lensX_1",
"ed_targetX_1",
],
],
[
"Y",
[
"ed_lensY_1",
"ed_targetY_1",
],
],
[
"Z",
[
"ed_lensZ_1",
"ed_targetZ_1",
],
],
],
"ed_numberOfBeams",
"ed_lensSemiAxisMajor_1",
"ed_crossSectionFunctionType_1",
"ed_numberOfRays_1",
"ed_pulseNumber_1",
"ed_wavelength_1",
"ed_gridType_1",
"ed_gridnRadialTics_1",
"ed_gaussianExponent_1",
[
[
"Major",
[
"ed_gaussianRadiusMajor_1",
"ed_gaussianCenterMajor_1",
"ed_targetSemiAxisMajor_1",
"ed_semiAxisMajorTorsionAngle_1",
"ed_semiAxisMajorTorsionAxis_1",
],
],
[
"Minor",
[
"ed_gaussianRadiusMinor_1",
"ed_gaussianCenterMinor_1",
"ed_targetSemiAxisMinor_1",
],
],
],
],
],
],
)
return v
def _view_physics_sourceTerms_Flame_FlameMain(self, schema):
# TODO(e-carlin): add _LABELS for things
# http://flash.uchicago.edu/site/flashcode/user_support/rpDoc_4p2.py?submit=rp_Flame.txt
v = PKDict(
basic=[
"useFlame",
"fl_epsilon_0",
"fl_epsilon_1",
"fl_kpp_fact",
"fl_b",
],
)
if "physics_sourceTerms_Flame_FlameEffects_EIP" in schema.model:
v.basic.extend(
[
[
[
"Unburned",
[
"physics_sourceTerms_Flame_FlameEffects_EIP.ye_unburned",
"physics_sourceTerms_Flame_FlameEffects_EIP.sumyi_unburned",
],
],
[
"Burned",
[
"physics_sourceTerms_Flame_FlameEffects_EIP.ye_burned",
"physics_sourceTerms_Flame_FlameEffects_EIP.sumyi_burned",
],
],
],
"physics_sourceTerms_Flame_FlameEffects_EIP.flame_deltae",
]
)
if "physics_sourceTerms_Flame_FlameSpeed_Constant" in schema.model:
v.basic.append(
"physics_sourceTerms_Flame_FlameSpeed_Constant.fl_fsConstFlameSpeed"
)
return v
def _view_Simulation_SimulationMain_flashApp(self, schema):
res = PKDict(
title="FLASH Simulation",
basic=schema.view.Simulation_SimulationMain_flashApp.advanced,
advanced=schema.view.Simulation_SimulationMain_flashApp.advanced,
)
if "sim_condWall" in schema.model.Simulation_SimulationMain_flashApp:
# TODO(pjm): special views for cap laser, instead look for common species fields
res.basic = [
"sim_condWall",
"sim_peakField",
"sim_period",
"sim_zminWall",
[
[
"Fill",
[
"sim_eosFill",
"sim_rhoFill",
"sim_teleFill",
"sim_tionFill",
"sim_tradFill",
],
],
[
"Wall",
[
"sim_eosWall",
"sim_rhoWall",
"sim_teleWall",
"sim_tionWall",
"sim_tradWall",
],
],
],
]
return res