A teaching-oriented Python laboratory for solving partial differential equations with classical finite differences.
This repository connects the mathematical derivation of finite-difference schemes with readable implementations, reproducible examples, error metrics, automated tests, and visual results.
| 🚀 Quick Start Install and run a first example. |
🧭 Roadmap How the project is organized. |
📐 Methods PDEs, schemes, and conventions. |
🎥 Results Figures and animations. |
| 📊 Metrics How accuracy is measured. |
🧪 Tests Numerical verification. |
🎓 Teaching Classroom and study uses. |
🧑🔬 Team People and support. |
A guided bridge between finite-difference theory, implementation, verification, and visualization
Finite differences are often the first place where students see partial differential equations become algorithms. The idea is simple:
derivatives -> differences between neighboring grid values
PDE model -> algebraic equations on a mesh
solution -> arrays that can be measured, plotted, and tested
The purpose of this project is not to hide that process behind a black box. The purpose is to make each step visible:
| Step | What students can inspect |
|---|---|
| 📄 Mathematical model | The PDE, boundary conditions, and exact benchmark solution. |
| 📐 Discretization | The finite-difference stencil used in space and time. |
| 💻 Implementation | Matrix/vector formulations and node-wise stencil formulations. |
| 📊 Verification | Error metrics against exact solutions. |
| 🎥 Visualization | Static plots and transient animations. |
| 🧪 Testing | Automated checks that guard against regressions and unstable mistakes. |
The code is intentionally explicit. It is designed for lectures, guided labs, reports, and independent study.
Each example follows the same path: model, mesh, stencil, solver, metrics, figures, and tests
Each example follows the same computational story:
flowchart LR
PDE["PDE model"] --> Mesh["Spatial and temporal mesh"]
Mesh --> Stencil["Finite-difference stencil"]
Stencil --> Solver["Discrete solver"]
Solver --> Exact["Exact-solution comparison"]
Exact --> Metrics["Error metrics"]
Exact --> Figures["Figures and animations"]
Metrics --> Tests["Automated tests"]
Figures --> Gallery["Results gallery"]
The repository currently includes five equation families:
| Equation | Main phenomenon | Example file |
|---|---|---|
| Poisson | Steady potentials and elliptic boundary-value problems. | Examples/CFDM_Poisson_examples.py |
| Diffusion | Smoothing, heat conduction, and gradient-driven transport. | Examples/CFDM_Diffusion_examples.py |
| Wave | Oscillatory propagation and second-order time dynamics. | Examples/CFDM_Wave_examples.py |
| Advection | Transport by a prescribed velocity field. | Examples/CFDM_Advection_examples.py |
| Advection-Diffusion | Transport combined with smoothing. | Examples/CFDM_Advection_Diffusion_examples.py |
The labels describe how the same finite-difference idea is organized in code
All methods in this repository are finite-difference methods. The labels used in the examples describe how the discrete equations are solved or organized.
For Poisson, the examples use the traditional labels:
| Label | Meaning | Computational idea |
|---|---|---|
FD |
Finite-difference matrix formulation | Assemble the linear system and solve it directly. |
GS |
Gauss-Seidel formulation | Sweep through the grid using Gauss-Seidel updates. |
For Diffusion, Wave, Advection, and Advection-Diffusion, the examples use implementation labels:
| Label | Meaning | Computational idea |
|---|---|---|
Matrix |
Matrix/vector formulation | Apply the stencil through an operator matrix or vectorized update. |
Stencil |
Node-wise stencil formulation | Evaluate the same stencil directly by sweeping over nodes. |
This distinction is important. In transient examples, both formulations are finite-difference implementations; the time-integration scheme is stated separately, for example Explicit, Crank-Nicolson, or the centered wave update.
Solvers, examples, shared tools, tests, assets, and results live in separate places
Classical Finite Differences/
├── CFDM/
│ ├── Poisson.py
│ ├── Diffusion.py
│ ├── Wave.py
│ ├── Advection.py
│ └── Advection_Diffusion.py
├── Common/
│ ├── Metrics.py
│ ├── Graphs.py
│ ├── ExampleTools.py
│ └── TimeIntegrators/
├── Examples/
│ ├── CFDM_Poisson_examples.py
│ ├── CFDM_Diffusion_examples.py
│ ├── CFDM_Wave_examples.py
│ ├── CFDM_Advection_examples.py
│ └── CFDM_Advection_Diffusion_examples.py
├── Results/
├── Tests/
├── assets/
├── requirements.txt
├── CITATION.cff
├── LICENSE
└── README.md
| Directory | Purpose |
|---|---|
CFDM/ |
Numerical solvers for each PDE family. |
Common/ |
Shared tools for metrics, plotting, output formatting, and auxiliary time integrators. |
Examples/ |
Complete executable workflows for each equation. |
Results/ |
Versionable figures and animations generated by the examples. |
Tests/ |
Automated tests for accuracy, consistency, rectangular grids, warnings, and implementation agreement. |
assets/ |
Images used by the README and teaching presentation. |
Clone the project, install the dependencies, and run a first Poisson example
git clone https://github.com/gstinoco/Classical_Finite_Differences.git
cd Classical_Finite_DifferencesA virtual environment or Conda environment is recommended.
pip install -r requirements.txtDependencies:
numpy
matplotlib
opencv-python
pytest
python Examples/CFDM_Poisson_examples.pyThis prints error tables and writes figures under:
Results/Poisson/
Each script builds the benchmark, runs the solver, prints metrics, and writes visual results
Each example file can be executed directly:
| Equation | Command |
|---|---|
| 🧲 Poisson | python Examples/CFDM_Poisson_examples.py |
| 💧 Diffusion | python Examples/CFDM_Diffusion_examples.py |
| 🌊 Wave | python Examples/CFDM_Wave_examples.py |
| 💨 Advection | python Examples/CFDM_Advection_examples.py |
| 🔀 Advection-Diffusion | python Examples/CFDM_Advection_Diffusion_examples.py |
Examples can also be called from Python to control cost, suppress file output, or reuse arrays in a notebook:
from Examples import CFDM_Diffusion_examples as diffusion_examples
diffusion_examples.main(
show=False,
save_path=None,
nodes_1d=21,
nodes_2d=21,
time_steps=200,
)Common parameters:
| Parameter | Meaning |
|---|---|
show |
Opens interactive plot windows when set to True. |
save_path |
Output directory; if None, figures are not saved. |
nodes_1d |
Number of spatial nodes for one-dimensional examples. |
nodes_2d |
Number of nodes per spatial direction for two-dimensional examples. |
time_steps |
Number of time levels for transient examples. |
The README uses curated assets while links point to the full reproducible outputs in Results/
The Results/ directory is part of the teaching material. It provides a visual reference for the methods and a reproducible gallery of outputs.
| Stationary Example |
|---|
Poisson/2D_FD.png
|
| Diffusion | Wave |
|---|---|
Diffusion/2D_Stencil.gif
|
Wave/2D_Stencil.gif
|
| Advection | Advection-Diffusion |
Advection/2D_Matrix_LaxWendroff.gif
|
Advection_Diffusion/2D_Stencil_CN.gif
|
Representative outputs:
| Family | Example output |
|---|---|
| Poisson | Results/Poisson/2D_FD.png |
| Diffusion | Results/Diffusion/2D_Stencil.gif |
| Wave | Results/Wave/2D_Stencil.gif |
| Advection | Results/Advection/2D_Matrix_LaxWendroff.gif |
| Advection-Diffusion | Results/Advection_Diffusion/2D_Stencil_CN.gif |
Naming convention:
Results/<Equation>/<Dimension>_<Formulation>_<Method>.<ext>
Examples:
1D_FD.png
1D_GS_Neumann_2.png
2D_Matrix_FTBS.gif
2D_Stencil_CN.gif
Poisson problems are stationary boundary-value problems that appear in electrostatics, gravitation, pressure projection, potential theory, and steady-state modeling.
Project convention:
Delta phi = -f
Available solvers:
| Case | FD | GS |
|---|---|---|
| 1D Dirichlet Poisson | Poisson1D |
Poisson1D_iter |
| 2D Dirichlet Poisson | Poisson2D |
Poisson2D_iter |
| 1D Neumann variant 1 | Poisson1D_Neumann_1 |
Poisson1D_Neumann_1_iter |
| 1D Neumann variant 2 | Poisson1D_Neumann_2 |
Poisson1D_Neumann_2_iter |
| 1D Neumann variant 3 | Poisson1D_Neumann_3 |
Poisson1D_Neumann_3_iter |
The Neumann variants compare different finite-difference approximations for the derivative condition at the left boundary. The examples keep a Dirichlet condition at the right boundary.
Diffusion models smoothing, heat conduction, concentration spreading, and gradient-driven transport.
Typical forms:
u_t = nu u_xx
u_t = nu Delta u
Available solvers:
| Case | Matrix | Stencil |
|---|---|---|
| 1D diffusion | Diffusion1D |
Diffusion1D_iter |
| 2D diffusion | Diffusion2D |
Diffusion2D_iter |
The 2D solver can run with an explicit update or with a Crank-Nicolson-type option:
implicit=True
lam=0.5The wave equation models propagation with finite speed, including vibrations, signals, and oscillatory fields.
Typical forms:
u_tt = c^2 u_xx
u_tt = c^2 Delta u
Available solvers:
| Case | Matrix | Stencil |
|---|---|---|
| 1D wave equation | Wave1D |
Wave1D_iter |
| 2D wave equation | Wave2D |
Wave2D_iter |
The implemented scheme uses centered finite differences in time and space. The first two time levels are initialized from the exact benchmark solution used by the examples.
Advection describes transport by velocity: a profile moves through the domain while the numerical method attempts to preserve its shape.
Typical forms:
u_t + a u_x = 0
u_t + a u_x + b u_y = 0
Available solvers:
| Case | Matrix | Stencil |
|---|---|---|
| 1D advection | Advection1D |
Advection1D_iter |
| 2D advection | Advection2D |
Advection_2D_iter |
Implemented schemes:
| Scheme | Teaching role |
|---|---|
FTCS |
Centered spatial difference; useful for discussion, but unstable for pure advection in standard settings. |
FTBS |
Upwind scheme for positive velocities. |
FTFS |
Upwind scheme for negative velocities. |
LaxWendroff |
Second-order method for smooth transport under appropriate CFL conditions. |
Advection-Diffusion combines transport by velocity with diffusion-driven smoothing.
Typical forms:
u_t + a u_x = nu u_xx
u_t + a u_x + b u_y = nu Delta u
Available solvers:
| Case | Matrix | Stencil |
|---|---|---|
| 1D advection-diffusion | AdvectionDiffusion1D |
AdvectionDiffusion1D_iter |
| 2D advection-diffusion | AdvectionDiffusion2D |
AdvectionDiffusion2D_iter |
Example labels:
| Label | Meaning |
|---|---|
Explicit Matrix |
Explicit time stepping with matrix/vector finite-difference implementation. |
Explicit Stencil |
Explicit time stepping with node-wise stencil implementation. |
Crank-Nicolson Matrix |
Crank-Nicolson-type update with matrix/vector implementation. |
Crank-Nicolson Stencil |
Crank-Nicolson-type update with node-wise stencil implementation. |
The examples impose boundary values from the exact solution whenever possible. This makes verification direct because the numerical solution can be compared point by point against a known reference.
| Topic | Convention |
|---|---|
| Dirichlet boundaries | Boundary values are assigned from the exact solution. |
| Neumann boundaries | Poisson 1D includes three derivative-stencil variants. |
| Positive advection velocity | The upwind direction corresponds to FTBS. |
| Negative advection velocity | The upwind direction corresponds to FTFS. |
| Transient examples | Parameters are chosen to keep the demonstrated cases within a stable working range. |
Some schemes are included because they are pedagogically useful even when they are not the best production choice. For example, unstable or conditionally stable methods are valuable for showing why discretization decisions matter.
All examples report the same metrics so methods and equations can be discussed side by side
The examples print a common table of metrics so different methods can be compared using the same language.
Let u_ex be the exact solution and u_ap the numerical approximation.
| Metric | Formula | Interpretation |
|---|---|---|
MAE |
mean(abs(u_ex - u_ap)) |
Average absolute error, in the same units as the solution. |
MSE |
mean((u_ex - u_ap)^2) |
Squared error average; penalizes large errors more strongly. |
RMSE |
sqrt(MSE) |
Root mean squared error, again in solution units. |
MAPE |
mean(abs((u_ex - u_ap)/u_ex))*100 |
Percentage error; interpret carefully near exact zeros. |
R^2 |
1 - SS_res/SS_tot |
Agreement with the variation of the exact solution. |
For transient examples, the metrics are computed over the full space-time solution arrays, not only at the final time.
Tests protect accuracy, consistency, rectangular meshes, stability choices, and warning-free execution
Run the full test suite with:
python -W error::RuntimeWarning -m pytest TestsThe warning policy is intentional. Runtime warnings such as overflow, invalid values, or division by zero often reveal unstable parameters, indexing mistakes, or boundary-condition errors.
You can also check syntax and import-time correctness with:
python -m compileall CFDM Common Examples TestsCurrent tests cover:
| Test focus | Why it matters |
|---|---|
| 🎯 Accuracy | Confirms that examples solve the intended benchmark problem. |
| Checks that paired formulations agree numerically. | |
| 📏 Rectangular meshes | Helps detect swapped axes and hidden square-grid assumptions. |
| 🚦 CFL-aware cases | Guards against accidental unstable parameter choices. |
| Catches numerical failures before they become silent bad results. |
Start with stationary problems, then move through increasingly rich transient models
| Step | What to study |
|---|---|
| 1️⃣ | Start with Examples/CFDM_Poisson_examples.py to study stationary boundary-value problems. |
| 2️⃣ | Move to Examples/CFDM_Diffusion_examples.py to see how a solution evolves in time. |
| 3️⃣ | Explore Examples/CFDM_Wave_examples.py to compare oscillatory propagation with diffusive smoothing. |
| 4️⃣ | Continue with Examples/CFDM_Advection_examples.py to study transport, upwinding, and method choice. |
| 5️⃣ | Finish with Examples/CFDM_Advection_Diffusion_examples.py to combine transport and diffusion. |
| 6️⃣ | Open the corresponding files in CFDM/ and compare FD/GS for Poisson with Matrix/Stencil for transient equations. |
| 7️⃣ | Inspect Common/Metrics.py, Common/Graphs.py, and Common/ExampleTools.py to see how verification and visualization are shared. |
| 8️⃣ | Modify a benchmark solution or mesh size, then run the tests again. |
The examples are explicit enough to read in class and reproducible enough to use in assignments
This project can support lectures, laboratory sessions, workshops, homework discussions, and self-study.
| Teaching activity | How the repository helps |
|---|---|
| Derive a finite-difference scheme | Students can compare the derived stencil with the implementation in CFDM/. |
| Compare formulations | Poisson shows FD versus GS; transient equations show Matrix versus Stencil. |
| Discuss stability | Changing mesh sizes or time steps reveals why numerical parameters matter. |
| Practice verification | Exact solutions, common metrics, and tests make numerical accuracy measurable. |
| Build reports | The generated figures and tables can be used directly as reproducible evidence. |
The code is written to be read, compared, executed, and safely extended
| Convention | Purpose |
|---|---|
| 📃 Complete institutional headers | Preserve authorship, context, funding, and revision history. |
| 📑 Complete public docstrings | Make numerical assumptions, arguments, and return values explicit. |
| 💬 Descriptive inline comments | Support line-by-line guided reading. |
| Make scripts easy to run from the terminal when direct execution is meaningful. | |
| 🏷️ Accurate output labels | Use FD/GS for Poisson and Matrix/Stencil for transient equations. |
| 🔒 Local planning files | Keep private review notes out of version control with names such as *.local.*. |
Faculty and students building readable, reproducible teaching material for classical finite differences
| Photo | Student | Institution | Contact |
|---|---|---|---|
|
Gabriela Pedraza-Jiménez |
|
|
|
Eli Chagolla-Inzunza |
|
|
| Photo | Student | Institution | Contact |
|---|---|---|---|
|
Jorge L. González-Figueroa |
|
|
|
Christopher N. Magaña-Barocio |
|
|
| Photo | Student | Institution | Contact |
|---|---|---|---|
|
Maria Goretti Fraga-Lopez |
|
|
Collaboration that helps keep the examples, documentation, and computational tools useful for teaching
If this repository supports a course, workshop, thesis, report, publication, or derived implementation, please cite it as academic software. Citation metadata is provided in CITATION.cff, which GitHub and other tools can use to generate additional formats.
The citation below lists the main software authors. The broader research team shown above may be acknowledged when their participation is relevant to a specific course, report, or derived project.
Recommended citation:
Tinoco Guerrero, G., Domínguez Mota, F. J., Guzmán Torres, J. A., & Árias Rojas, H. (2026).
Classical Finite Differences [Software].
Universidad Michoacana de San Nicolás de Hidalgo and SIIIA MATH: Soluciones en Ingeniería.
https://github.com/gstinoco/Classical_Finite_Differences
BibTeX:
@software{tinoco_guerrero_2026_classical_finite_differences,
author = {Tinoco Guerrero, Gerardo and Domínguez Mota, Francisco Javier and Guzmán Torres, José Alberto and Árias Rojas, Heriberto},
title = {Classical Finite Differences},
year = {2026},
publisher = {Universidad Michoacana de San Nicolás de Hidalgo and SIIIA MATH: Soluciones en Ingeniería},
type = {Software},
url = {https://github.com/gstinoco/Classical_Finite_Differences},
license = {MIT}
}This project is distributed under the MIT License. See LICENSE for the full license text.








