Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help



Complete PDE Examples

Topic: advanced.pde.examples

Three complete, real-world examples demonstrating MathHook's PDE solving capabilities across heat, wave, and Laplace equations. Each example includes full problem setup, mathematical formulation, MathHook implementation, and physical interpretation.

Mathematical Definition

Example 1: Heat Diffusion

Example 2: Wave Propagation

Example 3: Electrostatic Potential

Complete PDE Examples

Three complete, real-world examples demonstrating MathHook's PDE solving capabilities.

Example 1: Heat Diffusion in Steel Rod

Physical Problem: A 1-meter steel rod is initially heated to 100°C. Both ends are plunged into ice water (0°C). How does temperature evolve?

Complete Solution

STEP 1: Define Variables

Temperature , position (0 to 1 meter), time

STEP 2: Create PDE

Heat equation:

STEP 3: Material Properties

Steel: m²/s

STEP 4: Boundary Conditions

  • (left end in ice water)
  • (right end in ice water)

STEP 5: Initial Condition

(uniform initial temperature)

STEP 6: Solve

Using HeatEquationSolver

STEP 7: Examine Solution

Solution structure shows eigenvalues and exponential decay modes.

Physical Interpretation:

  • Eigenvalues determine spatial modes
  • Higher modes decay faster (∝ )
  • Temperature → 0°C as (boundary temperature)

Example 2: Vibrating Guitar String

Physical Problem: An E4 guitar string (0.65 m) is plucked 5 mm at the center and released. Describe the vibration.

Complete Solution

STEP 1: Define Variables

Displacement , position along string, time

STEP 2: Create PDE

Wave equation:

STEP 3: Physical Parameters

Steel E string: N, kg/m

Wave speed: m/s

STEP 4: Boundary Conditions

  • (left end fixed)
  • (right end fixed, m)

STEP 5: Initial Conditions

  • Initial position: triangular pluck at center (5 mm displacement)
  • Initial velocity: released from rest ()

STEP 6: Solve

Using WaveEquationSolver

STEP 7: Analyze Musical Properties

Musical Harmonics:

  • Fundamental: Hz (close to E4 = 329.63 Hz)
  • Overtones:
    • Hz (octave)
    • Hz (octave + fifth)
    • Hz (two octaves)

Standing Wave Nodes:

  • Mode 1: nodes at m
  • Mode 2: nodes at m
  • Mode 3: nodes at m

Example 3: Electrostatic Potential in Rectangular Plate

Physical Problem: A 10 cm × 5 cm conducting plate has bottom/sides grounded (0 V) and top edge at 100 V. Find the potential distribution.

Complete Solution

STEP 1: Define Variables

Electrostatic potential , horizontal position , vertical position

STEP 2: Create PDE

Laplace equation:

STEP 3: Boundary Conditions

  • V (left edge grounded)
  • V (right edge grounded, m)
  • V (bottom edge grounded)
  • V (top edge at fixed potential, m)

STEP 4: Solve

Using LaplaceEquationSolver

STEP 5: Examine Solution

Solution structure shows:

  • X-direction eigenvalues:
  • Hyperbolic sine functions in -direction
  • Smooth variation from 0 V to 100 V

Physical Interpretation:

  • Potential varies smoothly from 0 V (bottom/sides) to 100 V (top)
  • No local maxima/minima inside (maximum principle)
  • Electric field points from high to low potential
  • Field strongest near top edge (steepest gradient)

Estimated potential at center (5 cm, 2.5 cm): V (halfway between 0 V and 100 V)

Common Pitfalls

Pitfall 1: Expecting Numerical Coefficients

❌ WRONG: Coefficients are symbolic

#![allow(unused)]
fn main() {
for coeff in result.coefficients {
    let numerical_value = coeff.evaluate()?;  // ERROR: Can't evaluate A_1
}
}

✅ CORRECT: Acknowledge symbolic nature

#![allow(unused)]
fn main() {
for (n, coeff) in result.coefficients.iter().enumerate() {
    println!("Coefficient A_{} (symbolic): {}", n + 1, coeff);
}
}

Pitfall 2: Using Non-Standard Variable Names

❌ MAY NOT CLASSIFY:

#![allow(unused)]
fn main() {
let r = symbol!(r);         // Radial
let theta = symbol!(theta); // Angular
}

✅ USE STANDARD NAMES:

#![allow(unused)]
fn main() {
let x = symbol!(x);
let y = symbol!(y);
let t = symbol!(t);
}

Pitfall 3: Non-Homogeneous BCs Without Transformation

❌ UNSUPPORTED DIRECTLY:

#![allow(unused)]
fn main() {
let bc = BoundaryCondition::dirichlet(expr!(50), ...);  // Non-zero
}

✅ TRANSFORM FIRST:

  1. Find steady-state satisfying BCs
  2. Solve for with homogeneous BCs
  3. Add back:

Summary

Three complete examples demonstrate:

  1. ✅ Heat equation: Thermal diffusion in steel
  2. ✅ Wave equation: Musical string vibrations
  3. ✅ Laplace equation: Electrostatic potential

All examples show:

  • Correct eigenvalue computation
  • Proper solution structure
  • Physical interpretation
  • Symbolic coefficient limitation

Next steps: Use these patterns for your own PDE problems, keeping limitations in mind (Dirichlet BCs only, symbolic coefficients).

Examples

Heat Diffusion in Steel Rod - Complete Implementation

1-meter steel rod cooling from 100°C with ice water at ends. Full implementation with error handling.

Rust
#![allow(unused)]
fn main() {
use mathhook::prelude::*;

fn solve_cooling_rod() -> Result<(), Box<dyn std::error::Error>> {
    // Define Variables
    let u = symbol!(u);
    let x = symbol!(x);
    let t = symbol!(t);

    // Create PDE
    let equation = expr!(u);
    let pde = Pde::new(equation, u, vec![x.clone(), t.clone()]);

    // Material Properties
    let alpha = expr!(0.000013);  // Steel thermal diffusivity

    // Boundary Conditions
    let bc_left = BoundaryCondition::dirichlet(
        expr!(0),
        BoundaryLocation::Simple {
            variable: x.clone(),
            value: expr!(0),
        },
    );
    let bc_right = BoundaryCondition::dirichlet(
        expr!(0),
        BoundaryLocation::Simple {
            variable: x,
            value: expr!(1),
        },
    );

    // Initial Condition
    let ic = InitialCondition::value(expr!(100));

    // Solve
    let solver = HeatEquationSolver::new();
    let result = solver.solve_heat_equation_1d(
        &pde,
        &alpha,
        &[bc_left, bc_right],
        &ic,
    )?;

    // Examine Solution
    println!("Heat Equation Solution for Cooling Steel Rod");
    println!("Solution structure: {}", result.solution);
    println!("Eigenvalues: {:?}", result.eigenvalues.iter().take(5).collect::<Vec<_>>());
    println!("Fourier coefficients: {:?}", result.coefficients.iter().take(5).collect::<Vec<_>>());

    Ok(())
}

}
Python
from mathhook import symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, HeatEquationSolver

def solve_cooling_rod():
    # Define Variables
    u = symbol('u')
    x = symbol('x')
    t = symbol('t')

    # Create PDE
    equation = expr(u)
    pde = Pde(equation, u, [x, t])

    # Material Properties
    alpha = expr(0.000013)

    # Boundary Conditions
    bc_left = BoundaryCondition.dirichlet(
        expr(0),
        BoundaryLocation.simple(variable=x, value=expr(0))
    )
    bc_right = BoundaryCondition.dirichlet(
        expr(0),
        BoundaryLocation.simple(variable=x, value=expr(1))
    )

    # Initial Condition
    ic = InitialCondition.value(expr(100))

    # Solve
    solver = HeatEquationSolver()
    result = solver.solve_heat_equation_1d(pde, alpha, [bc_left, bc_right], ic)

    print(f"Solution: {result.solution}")
    print(f"Eigenvalues: {result.eigenvalues[:5]}")
    print(f"Coefficients: {result.coefficients[:5]}")

JavaScript
const { symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, HeatEquationSolver } = require('mathhook');

function solveCoolingRod() {
    // Define Variables
    const u = symbol('u');
    const x = symbol('x');
    const t = symbol('t');

    // Create PDE
    const equation = expr(u);
    const pde = new Pde(equation, u, [x, t]);

    // Material Properties
    const alpha = expr(0.000013);

    // Boundary Conditions
    const bcLeft = BoundaryCondition.dirichlet(
        expr(0),
        BoundaryLocation.simple({ variable: x, value: expr(0) })
    );
    const bcRight = BoundaryCondition.dirichlet(
        expr(0),
        BoundaryLocation.simple({ variable: x, value: expr(1) })
    );

    // Initial Condition
    const ic = InitialCondition.value(expr(100));

    // Solve
    const solver = new HeatEquationSolver();
    const result = solver.solveHeatEquation1d(pde, alpha, [bcLeft, bcRight], ic);

    console.log(`Solution: ${result.solution}`);
    console.log(`Eigenvalues: ${result.eigenvalues.slice(0, 5)}`);
    console.log(`Coefficients: ${result.coefficients.slice(0, 5)}`);
}

Vibrating Guitar String - Musical Analysis

E4 guitar string with musical frequency analysis and standing wave nodes.

Rust
#![allow(unused)]
fn main() {
use mathhook::prelude::*;

fn solve_vibrating_string() -> Result<(), Box<dyn std::error::Error>> {
    let u = symbol!(u);
    let x = symbol!(x);
    let t = symbol!(t);

    let equation = expr!(u);
    let pde = Pde::new(equation, u, vec![x.clone(), t.clone()]);

    let c = expr!(442);  // Wave speed

    let bc1 = BoundaryCondition::dirichlet(
        expr!(0),
        BoundaryLocation::Simple { variable: x.clone(), value: expr!(0) },
    );
    let bc2 = BoundaryCondition::dirichlet(
        expr!(0),
        BoundaryLocation::Simple { variable: x, value: expr!(0.65) },
    );

    let ic_position = InitialCondition::value(expr!(0.005));
    let ic_velocity = InitialCondition::derivative(expr!(0));

    let solver = WaveEquationSolver::new();
    let result = solver.solve_wave_equation_1d(
        &pde, &c, &[bc1, bc2], &ic_position, &ic_velocity
    )?;

    println!("Wave Equation Solution for Vibrating Guitar String");
    println!("Solution: {}", result.solution);

    // Compute musical frequencies
    let L = 0.65;
    let c_val = 442.0;
    for n in 1..=5 {
        let f_n = (n as f64) * c_val / (2.0 * L);
        println!("f_{} = {:.2} Hz (mode {})", n, f_n, n);
    }

    Ok(())
}

}
Python
from mathhook import symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, WaveEquationSolver

def solve_vibrating_string():
    u = symbol('u')
    x = symbol('x')
    t = symbol('t')

    equation = expr(u)
    pde = Pde(equation, u, [x, t])

    c = expr(442)

    bc1 = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=x, value=expr(0)))
    bc2 = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=x, value=expr(0.65)))

    ic_position = InitialCondition.value(expr(0.005))
    ic_velocity = InitialCondition.derivative(expr(0))

    solver = WaveEquationSolver()
    result = solver.solve_wave_equation_1d(pde, c, [bc1, bc2], ic_position, ic_velocity)

    print(f"Solution: {result.solution}")

    # Musical frequencies
    L = 0.65
    c_val = 442.0
    for n in range(1, 6):
        f_n = n * c_val / (2.0 * L)
        print(f"f_{n} = {f_n:.2f} Hz (mode {n})")

JavaScript
const { symbol, expr, Pde, BoundaryCondition, BoundaryLocation, InitialCondition, WaveEquationSolver } = require('mathhook');

function solveVibratingString() {
    const u = symbol('u');
    const x = symbol('x');
    const t = symbol('t');

    const equation = expr(u);
    const pde = new Pde(equation, u, [x, t]);

    const c = expr(442);

    const bc1 = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: x, value: expr(0) }));
    const bc2 = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: x, value: expr(0.65) }));

    const icPosition = InitialCondition.value(expr(0.005));
    const icVelocity = InitialCondition.derivative(expr(0));

    const solver = new WaveEquationSolver();
    const result = solver.solveWaveEquation1d(pde, c, [bc1, bc2], icPosition, icVelocity);

    console.log(`Solution: ${result.solution}`);

    // Musical frequencies
    const L = 0.65;
    const cVal = 442.0;
    for (let n = 1; n <= 5; n++) {
        const fn = n * cVal / (2.0 * L);
        console.log(`f_${n} = ${fn.toFixed(2)} Hz (mode ${n})`);
    }
}

Electrostatic Potential in Rectangular Plate

10cm × 5cm plate with grounded sides and fixed potential top edge.

Rust
#![allow(unused)]
fn main() {
use mathhook::prelude::*;

fn solve_electrostatic_potential() -> Result<(), Box<dyn std::error::Error>> {
    let u = symbol!(u);
    let x = symbol!(x);
    let y = symbol!(y);

    let equation = expr!(u);
    let pde = Pde::new(equation, u, vec![x.clone(), y.clone()]);

    let bc_left = BoundaryCondition::dirichlet(expr!(0), BoundaryLocation::Simple { variable: x.clone(), value: expr!(0) });
    let bc_right = BoundaryCondition::dirichlet(expr!(0), BoundaryLocation::Simple { variable: x.clone(), value: expr!(0.1) });
    let bc_bottom = BoundaryCondition::dirichlet(expr!(0), BoundaryLocation::Simple { variable: y.clone(), value: expr!(0) });
    let bc_top = BoundaryCondition::dirichlet(expr!(100), BoundaryLocation::Simple { variable: y, value: expr!(0.05) });

    let solver = LaplaceEquationSolver::new();
    let result = solver.solve_laplace_equation_2d(&pde, &[bc_left, bc_right, bc_bottom, bc_top])?;

    println!("Laplace Equation Solution for Electrostatic Potential");
    println!("Solution: {}", result.solution);
    println!("X-eigenvalues: {:?}", result.x_eigenvalues.iter().take(5).collect::<Vec<_>>());

    Ok(())
}

}
Python
from mathhook import symbol, expr, Pde, BoundaryCondition, BoundaryLocation, LaplaceEquationSolver

def solve_electrostatic_potential():
    u = symbol('u')
    x = symbol('x')
    y = symbol('y')

    equation = expr(u)
    pde = Pde(equation, u, [x, y])

    bc_left = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=x, value=expr(0)))
    bc_right = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=x, value=expr(0.1)))
    bc_bottom = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple(variable=y, value=expr(0)))
    bc_top = BoundaryCondition.dirichlet(expr(100), BoundaryLocation.simple(variable=y, value=expr(0.05)))

    solver = LaplaceEquationSolver()
    result = solver.solve_laplace_equation_2d(pde, [bc_left, bc_right, bc_bottom, bc_top])

    print(f"Solution: {result.solution}")
    print(f"X-eigenvalues: {result.x_eigenvalues[:5]}")

JavaScript
const { symbol, expr, Pde, BoundaryCondition, BoundaryLocation, LaplaceEquationSolver } = require('mathhook');

function solveElectrostaticPotential() {
    const u = symbol('u');
    const x = symbol('x');
    const y = symbol('y');

    const equation = expr(u);
    const pde = new Pde(equation, u, [x, y]);

    const bcLeft = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: x, value: expr(0) }));
    const bcRight = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: x, value: expr(0.1) }));
    const bcBottom = BoundaryCondition.dirichlet(expr(0), BoundaryLocation.simple({ variable: y, value: expr(0) }));
    const bcTop = BoundaryCondition.dirichlet(expr(100), BoundaryLocation.simple({ variable: y, value: expr(0.05) }));

    const solver = new LaplaceEquationSolver();
    const result = solver.solveLaplaceEquation2d(pde, [bcLeft, bcRight, bcBottom, bcTop]);

    console.log(`Solution: ${result.solution}`);
    console.log(`X-eigenvalues: ${result.xEigenvalues.slice(0, 5)}`);
}

Performance

Time Complexity: Varies by example: O(n) for n modes

API Reference

  • Rust: mathhook_core::pde
  • Python: mathhook.pde
  • JavaScript: mathhook.pde

See Also