Skip to content
Merged
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
39 changes: 39 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Evan Gress
name: Bug report
description: A calculation gives a wrong answer, or something crashes.
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thanks for reporting! For wrong numbers, a reference value (textbook,
standard, or hand calculation) helps us fix it fast.
- type: textarea
id: what
attributes:
label: What happened?
description: Include the full error message if there was one.
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Code to reproduce
description: The smallest snippet that shows the problem.
render: python
placeholder: |
from fpc import Fluids
Fluids().colebrook_friction_factor(reynolds=1e5, relative_roughness=1e-4)
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected result and its source
description: What should the answer be, and where does that value come from?
- type: input
id: version
attributes:
label: Environment
description: Operating system, Python version (`uv run python --version`), and commit or version.
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Evan Gress
blank_issues_enabled: true
39 changes: 39 additions & 0 deletions .github/ISSUE_TEMPLATE/new_domain.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Evan Gress
name: New domain or method request
description: Propose a new engineering class or new calculations for an existing one.
labels: [enhancement, new-domain]
body:
- type: input
id: domain
attributes:
label: Domain or class
description: A new domain (e.g. "Acoustics") or an existing class (e.g. "Fluids").
validations:
required: true
- type: textarea
id: methods
attributes:
label: Calculations to include
description: One line per method, with the formula if you know it.
placeholder: |
- sound_pressure_level(pressure) -> dB, Lp = 20 log10(p / 20 uPa)
- add_decibels(levels) -> combined level
validations:
required: true
- type: textarea
id: references
attributes:
label: References
description: Textbooks, standards, or papers the formulas come from, so they can be verified.
- type: textarea
id: who
attributes:
label: Who would use this?
description: The kind of engineer or student, and the problem it helps them solve.
- type: checkboxes
id: contribute
attributes:
label: Contributing
options:
- label: I'd like to implement this myself (see the checklist in CONTRIBUTOR.md).
30 changes: 30 additions & 0 deletions .github/ISSUE_TEMPLATE/new_example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Evan Gress
name: New worked example
description: Suggest a realistic problem for the examples/ folder.
labels: [example]
body:
- type: textarea
id: question
attributes:
label: The engineering question
description: Phrase it the way it comes up at work, with real-looking numbers.
placeholder: "We need to move 12 L/s of water up 15 m through 120 m of steel pipe. Which pipe size and pump?"
validations:
required: true
- type: textarea
id: approach
attributes:
label: Approach
description: The steps and formulas a good answer would walk through.
- type: textarea
id: python
attributes:
label: Python ideas it would teach
description: e.g. root finding, pandas groupby, Pint conversions, optimization, plotting.
- type: checkboxes
id: contribute
attributes:
label: Contributing
options:
- label: I'd like to write this example myself.
63 changes: 39 additions & 24 deletions .github/make_social_preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
import numpy as np

# --- Palette (kept in one place so it is easy to retheme) -----------------
BG = "#0d1b2a" # deep navy background
PANEL = "#152538" # slightly lighter panel for the plot
CYAN = "#4cc9f0" # primary accent
MAGENTA = "#f72585" # secondary accent
TEXT = "#e6edf3" # near-white body text
BG = "#0d1b2a" # deep navy background
PANEL = "#152538" # slightly lighter panel for the plot
CYAN = "#4cc9f0" # primary accent
MAGENTA = "#f72585" # secondary accent
TEXT = "#e6edf3" # near-white body text
SUBTLE = "#8b97a7" # muted captions

# 16in x 8in at 80 dpi -> 1280 x 640 px, exactly what GitHub wants.
Expand All @@ -40,22 +40,37 @@
canvas.add_patch(plt.Rectangle((0.04, 0.905), 0.075, 0.012, color=CYAN, lw=0))

# Title block: project name, one-line value prop, two-line description.
canvas.text(0.04, 0.74, "First Principles Code",
fontsize=46, color=TEXT, weight="bold")
canvas.text(0.04, 0.65, "Open-source Python for engineers",
fontsize=22, color=CYAN, weight="semibold")
canvas.text(0.04, 0.51,
"A teaching template that replaces MATLAB & Maplesoft\n"
"with NumPy, SciPy, matplotlib, and Pint.",
fontsize=18, color=SUBTLE, linespacing=1.4)
canvas.text(0.04, 0.74, "First Principles Code", fontsize=46, color=TEXT, weight="bold")
canvas.text(
0.04, 0.65, "Open-source Python for engineers", fontsize=22, color=CYAN, weight="semibold"
)
canvas.text(
0.04,
0.51,
"A teaching template that replaces MATLAB & Maplesoft\n"
"with NumPy, SciPy, matplotlib, and Pint.",
fontsize=18,
color=SUBTLE,
linespacing=1.4,
)

# Feature ribbon and repo URL near the bottom.
canvas.text(0.04, 0.18,
"dynamics · statics · vibration · controls"
" · Pint units · solve_ivp · curve_fit · pytest",
fontsize=14, color=SUBTLE)
canvas.text(0.04, 0.10, "github.com/evangress/first-principles-code",
fontsize=14, color=CYAN, weight="medium")
canvas.text(
0.04,
0.18,
"dynamics · statics · vibration · controls"
" · Pint units · solve_ivp · curve_fit · pytest",
fontsize=14,
color=SUBTLE,
)
canvas.text(
0.04,
0.10,
"github.com/evangress/first-principles-code",
fontsize=14,
color=CYAN,
weight="medium",
)

# --- Inset plot: damped free-vibration "simulate -> fit" hero --------------
plot = fig.add_axes((0.60, 0.22, 0.36, 0.58))
Expand All @@ -66,12 +81,13 @@
mass, stiffness, damping = 2.0, 800.0, 8.0
omega_n = np.sqrt(stiffness / mass)
zeta = damping / (2 * np.sqrt(stiffness * mass))
omega_d = omega_n * np.sqrt(1 - zeta ** 2)
omega_d = omega_n * np.sqrt(1 - zeta**2)
displacement_mm = 10.0 * np.exp(-zeta * omega_n * time) * np.cos(omega_d * time)

plot.plot(time, displacement_mm, color=CYAN, lw=2.5, label="simulate")
plot.plot(time, displacement_mm, color=MAGENTA, lw=1.4, ls="--", alpha=0.85,
label="fit recovers params")
plot.plot(
time, displacement_mm, color=MAGENTA, lw=1.4, ls="--", alpha=0.85, label="fit recovers params"
)

plot.set_title("simulate → fit", color=TEXT, loc="left", fontsize=14, pad=10)
plot.set_xlabel("time [s]", color=SUBTLE, fontsize=12)
Expand All @@ -80,8 +96,7 @@
for spine in plot.spines.values():
spine.set_color(SUBTLE)
plot.grid(True, color="#2a3a52", alpha=0.5)
plot.legend(loc="upper right", facecolor=PANEL, edgecolor=SUBTLE,
labelcolor=TEXT, fontsize=11)
plot.legend(loc="upper right", facecolor=PANEL, edgecolor=SUBTLE, labelcolor=TEXT, fontsize=11)

# --- Save -------------------------------------------------------------------
output_path = Path(__file__).resolve().parent / "social-preview.png"
Expand Down
60 changes: 60 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Evan Gress
#
# Builds the documentation site (mkdocs + mkdocstrings) on every pull request
# so broken links or docstrings fail early, and publishes it to GitHub Pages
# on every push to main.
#
# One-time repository setup: Settings -> Pages -> Source: "GitHub Actions".

name: docs

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
build:
name: build site
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true

- name: Install Python 3.14
run: uv python install 3.14

- name: Build (strict - warnings are errors)
env:
NO_MKDOCS_2_WARNING: "1"
run: uv run --group docs mkdocs build --strict

- name: Upload site for Pages
if: github.event_name == 'push'
uses: actions/upload-pages-artifact@v3
with:
path: site

deploy:
name: deploy to GitHub Pages
if: github.event_name == 'push'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
16 changes: 14 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Evan Gress
#
# Runs the pytest suite on every push to main and on every pull request.
# Runs lint, format check, type check, and the pytest suite on every push to
# main and on every pull request.
# Uses uv (the same tool the project develops with) so CI matches local dev.

name: tests
Expand All @@ -14,7 +15,7 @@ on:

jobs:
pytest:
name: pytest (Python 3.14)
name: checks + pytest (Python 3.14)
runs-on: ubuntu-latest
steps:
- name: Check out the repository
Expand All @@ -32,5 +33,16 @@ jobs:
- name: Sync dependencies (incl. dev group)
run: uv sync --all-groups

- name: Lint (ruff)
run: uv run ruff check .

- name: Check formatting (ruff format)
run: uv run ruff format --check .

- name: Type check (mypy)
run: uv run mypy

# --all-groups above installed the notebook tools, so this also
# executes every notebook and runs every example script.
- name: Run pytest
run: uv run pytest
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,10 @@ displacement.png
*.png
# ...but keep the committed GitHub social-preview card
!.github/social-preview.png

# PyCharm / JetBrains per-user settings
.idea/

# Figures and tables written by the example scripts and template
examples/output/
templates/output/
10 changes: 0 additions & 10 deletions .idea/.gitignore

This file was deleted.

10 changes: 0 additions & 10 deletions .idea/first-principles-code.iml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/inspectionProfiles/profiles_settings.xml

This file was deleted.

7 changes: 0 additions & 7 deletions .idea/misc.xml

This file was deleted.

8 changes: 0 additions & 8 deletions .idea/modules.xml

This file was deleted.

7 changes: 0 additions & 7 deletions .idea/pyProjectModel.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

Loading
Loading