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
35 changes: 12 additions & 23 deletions toolchain/mfc/gen_case_constraints_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class PlaybookEntry:
tags: List[str]


LEVEL_EMOJI = {"Beginner": "🟢", "Intermediate": "🟡", "Advanced": "🔴"}


# Curated list of hero examples
PLAYBOOK_EXAMPLES = [
PlaybookEntry(
Expand Down Expand Up @@ -130,41 +133,27 @@ def summarize_case_params(params: Dict[str, Any]) -> Dict[str, Any]:
}


def get_model_name(model_eqns: int | None) -> str:
"""Get human-friendly model name from schema."""
if model_eqns is None:
return "Not specified"
return get_value_label("model_eqns", model_eqns) or "Not specified"


def get_riemann_solver_name(solver: int | None) -> str:
"""Get Riemann solver name from schema."""
if solver is None:
return "Not specified"
return get_value_label("riemann_solver", solver) or "Not specified"


def get_time_stepper_name(stepper: int | None) -> str:
"""Get time stepper name from schema."""
if stepper is None:
def _named(param: str, value: int | None) -> str:
"""Get the name from a schema (i.e. model name, Riemann solver name, time stepper name)."""
if value is None:
return "Not specified"
return get_value_label("time_stepper", stepper) or "Not specified"
return get_value_label(param, value) or "Not specified"


def render_playbook_card(entry: PlaybookEntry, summary: Dict[str, Any]) -> str:
"""Render a single playbook entry as Markdown"""
lines = []

tags_str = " · ".join(entry.tags)
level_emoji = {"Beginner": "🟢", "Intermediate": "🟡", "Advanced": "🔴"}.get(entry.level, "")
level_emoji = LEVEL_EMOJI.get(entry.level, "")

lines.append("<details>")
lines.append(f"<summary><b>{entry.title}</b> {level_emoji} <i>{entry.level}</i> · <code>{entry.case_dir}</code></summary>\n")
lines.append(f"**{entry.description}**\n")
lines.append(f"**Tags:** {tags_str}\n")

lines.append("**Physics Configuration:**\n")
lines.append(f"- **Model:** {get_model_name(summary['model_eqns'])} (`model_eqns = {summary['model_eqns']}`)")
lines.append(f"- **Model:** {_named('model_eqns', summary['model_eqns'])} (`model_eqns = {summary['model_eqns']}`)")

if summary["num_fluids"] is not None:
lines.append(f"- **Number of fluids:** {summary['num_fluids']}")
Expand Down Expand Up @@ -216,11 +205,11 @@ def render_playbook_card(entry: PlaybookEntry, summary: Dict[str, Any]) -> str:
lines.append(f"- **Reconstruction:** MUSCL (order {summary['muscl_order']})")

if summary["riemann_solver"]:
solver_name = get_riemann_solver_name(summary["riemann_solver"])
solver_name = _named("riemann_solver", summary["riemann_solver"])
lines.append(f"- **Riemann solver:** {solver_name} (`riemann_solver = {summary['riemann_solver']}`)")

if summary["time_stepper"]:
stepper_name = get_time_stepper_name(summary["time_stepper"])
stepper_name = _named("time_stepper", summary["time_stepper"])
lines.append(f"- **Time stepping:** {stepper_name}")

# Links
Expand Down Expand Up @@ -264,7 +253,7 @@ def generate_playbook() -> str:
if not level_entries:
continue

level_emoji = {"Beginner": "🟢", "Intermediate": "🟡", "Advanced": "🔴"}.get(level, "")
level_emoji = LEVEL_EMOJI.get(level, "")
lines.append(f"\n### {level_emoji} {level} Examples\n")

for entry in level_entries:
Expand Down
6 changes: 3 additions & 3 deletions toolchain/mfc/sched.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,17 @@ def notify_long_running_threads(progress: rich.progress.Progress, running_tracke
# headless: milestone notifications at 2, 10, 30 minutes
else:
# 2 minutes
if (not holder.notified_2m) and elapsed >= 2 * 60:
if (not holder.notified_2m) and elapsed >= HEADLESS_THRESHOLDS[0][0]:
cons.print(f" {HEADLESS_THRESHOLDS[0][1]} [bold magenta]{case_uuid}[/bold magenta] {case_trace}")
holder.notified_2m = True

# 10 minutes
if (not holder.notified_10m) and elapsed >= 10 * 60:
if (not holder.notified_10m) and elapsed >= HEADLESS_THRESHOLDS[1][0]:
cons.print(f" {HEADLESS_THRESHOLDS[1][1]} [bold magenta]{case_uuid}[/bold magenta] {case_trace}")
holder.notified_10m = True

# 30 minutes
if (not holder.notified_30m) and elapsed >= 30 * 60:
if (not holder.notified_30m) and elapsed >= HEADLESS_THRESHOLDS[2][0]:
cons.print(f" {HEADLESS_THRESHOLDS[2][1]} [bold magenta]{case_uuid}[/bold magenta] {case_trace}")
holder.notified_30m = True

Expand Down
15 changes: 2 additions & 13 deletions toolchain/mfc/user_guide.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,8 @@
"h": "HiPerGator", # Proper capitalization
}

# Display order and colors for organizations
# Display order for organizations
ORG_ORDER = ["ORNL", "LLNL", "ACCESS", "Georgia Tech", "Caltech", "Brown", "DoD", "Florida", "CSCS"]
ORG_COLORS = {
"ORNL": "yellow",
"LLNL": "yellow",
"ACCESS": "yellow",
"Georgia Tech": "yellow",
"Caltech": "yellow",
"Brown": "yellow",
"DoD": "yellow",
"Florida": "yellow",
}


def _parse_modules_file():
Expand Down Expand Up @@ -142,8 +132,7 @@ def _generate_clusters_content():
continue
# Format: " [yellow]ORG:[/yellow] [cyan]slug[/cyan]=Name [cyan]slug2[/cyan]=Name2"
entries = [f"[cyan]{slug}[/cyan]={_get_cluster_short_name(slug, name)}" for slug, name in org_clusters[org]]
color = ORG_COLORS.get(org, "yellow")
cluster_lines.append(f" [{color}]{org}:[/{color}] " + " ".join(entries))
cluster_lines.append(f" [yellow]{org}:[/yellow] " + " ".join(entries))

# Handle "Other" if any
if org_clusters.get("Other"):
Expand Down
Loading