janhardo

900 Reputation

13 Badges

11 years, 302 days
B. Ed math

MaplePrimes Activity


These are replies submitted by janhardo


 

 

 

 

restart;
with(plots):

# ============================================================
# NONLINEAR WAVE EQUATION SOLVED AS COUPLED ODEs
# ============================================================
#
# ORIGINAL PDE: ∂²u/∂t² = c²(λ(H + ∂u/∂x)) · ∂²u/∂x²
#
# AFTER SPATIAL DISCRETIZATION (FINITE DIFFERENCES):
# We obtain a SYSTEM of COUPLED ORDINARY DIFFERENTIAL EQUATIONS (ODEs):
#
# For each internal point i = 1, 2, ..., Nx-1:
#
#   d²u_i/dt² = c²(λ(H + (u_{i+1}-u_{i-1})/(2Δx))) · (u_{i+1}-2u_i+u_{i-1})/Δx²
#
# This is a system of (Nx-1) coupled, nonlinear ODEs.
# ============================================================

# ============================================================
# STEP 1: PHYSICAL SYSTEM PARAMETERS
# ============================================================
L := 0.04;                         # Length of the rod [m] (4 cm)
A0 := 12*L/2*10^(-6);              # Initial amplitude [m] (~2.4e-7 m)
Nx := 100;                         # Number of spatial points (creates 99 ODEs)
dx := L/Nx;                        # Spatial step size [m]
x_vals := [seq(i*dx, i=0..Nx)];    # Positions along the rod [m]

printf("========================================\n");
printf("     COUPLED ODEs FROM WAVE EQUATION\n");
printf("========================================\n\n");
printf("STEP 1: SYSTEM PARAMETERS\n");
printf("  Rod length L = %.4f m (%.1f cm)\n", L, L*100);
printf("  Initial amplitude A0 = %.2e m\n", A0);
printf("  Number of spatial points Nx+1 = %d\n", Nx+1);
printf("  Number of COUPLED ODEs = %d (for internal points)\n", Nx-1);
printf("  Spatial step dx = %.2e m\n\n", dx);

# ============================================================
# STEP 2: MATERIAL MODEL (PIECEWISE FUNCTIONS)
# ============================================================
# c_sq(H) = squared speed of sound [m²/s²]
c_sq := proc(H)
    if H < 700 then
        return -3143*H + 1.99e7;      # Region 1: decreasing speed
    elif H < 1000 then
        return 7333*H + 1.257e7;      # Region 2: increasing speed
    else
        return 1.99e7;                # Region 3: constant speed
    end if;
end proc:

# lambda(H) = helper function for inverse relation
lambda := proc(H)
    if H < 1000 then
        return (3/250000000)*H;
    else
        return 3/250000;
    end if;
end proc:

printf("STEP 2: MATERIAL MODEL\n");
printf("  c²(H) = piecewise function:\n");
printf("    H < 700:   c² = -3143·H + 1.99e7\n");
printf("    700 ≤ H < 1000: c² = 7333·H + 1.257e7\n");
printf("    H ≥ 1000:  c² = 1.99e7 (constant)\n");
printf("  λ(H) = 3/250000000 * H for H < 1000\n\n");

# ============================================================
# STEP 3: NUMERICAL PARAMETERS
# ============================================================
c_max := sqrt(1.99e7);              # Maximum wave speed [m/s]
dt := 0.5 * dx / c_max;             # Time step (CFL = 0.5 for stability)
f0 := sqrt(c_sq(650))/(2*L);        # Resonance frequency [Hz]
T0 := 1/f0;                         # Period [s]
Nt := 1500;                         # Number of time steps

printf("STEP 3: NUMERICAL PARAMETERS\n");
printf("  Maximum wave speed c_max = %.1f m/s\n", c_max);
printf("  Resonance frequency f0 = %.1f Hz (ultrasonic!)\n", f0);
printf("  Period T0 = %.2e s\n", T0);
printf("  Time step dt = %.2e s\n", dt);
printf("  Number of time steps Nt = %d\n", Nt);
printf("  CFL number = %.3f (must be < 1 for stability)\n\n", c_max*dt/dx);

# ============================================================
# STEP 4: INITIALIZE THE SOLUTION (Three time layers)
# ============================================================
# We need three arrays for the time integration:
#   u_old = solution at time t - dt
#   u_curr = solution at time t
#   u_new = solution at time t + dt

u_old := Array(0..Nx);
u_curr := Array(0..Nx);
u_new := Array(0..Nx);

# INITIAL CONDITION: u(x,0) = A0·cos(πx/L)
# This is the FIRST HARMONIC vibration mode
for i from 0 to Nx do
    u_curr[i] := A0 * cos(Pi * x_vals[i+1] / L);
    u_old[i] := u_curr[i];         # Initial velocity = 0 => u_old = u_curr
end do:

printf("STEP 4: INITIAL CONDITION\n");
printf("  u(x,0) = A0·cos(πx/L)\n");
printf("  ∂u/∂t(x,0) = 0\n");
printf("  This creates the first harmonic vibration mode.\n");
printf("  The rod is maximally stretched at the middle (x = %.2f m).\n\n", L/2);

# Display the initial values for the first few points (educational)
printf("  Initial values for the first 5 points (i=0 to 4):\n");
for i from 0 to 4 do
    printf("    u[%d](0) = %.2e m at x = %.4f m\n", i, u_curr[i], x_vals[i+1]);
end do;
printf("    ...\n\n");

# ============================================================
# STEP 5: BOUNDARY CONDITIONS (Neumann - Free Ends)
# ============================================================
# Neumann: ∂u/∂x = 0 at both ends
# This means: u[0] = u[1] and u[Nx] = u[Nx-1]
# Physically: The ends are FREE (no force)
apply_bc := proc()
    u_new[0] := u_new[1];
    u_new[Nx] := u_new[Nx-1];
end proc:

printf("STEP 5: BOUNDARY CONDITIONS\n");
printf("  Neumann: ∂u/∂x = 0 at x = 0 and x = L\n");
printf("  This means: u(t) = u(t) and u_%d(t) = u_%d(t)\n", Nx, Nx-1);
printf("  Physically: The ends are FREE (can move without force).\n");
printf("  Waves reflect at the ends WITHOUT sign reversal.\n\n");

# ============================================================
# STEP 6: THE COUPLED ODE SYSTEM - EXPLANATION
# ============================================================
printf("STEP 6: THE COUPLED ODE SYSTEM\n");
printf("  After spatial discretization, we get %d coupled ODEs:\n\n", Nx-1);

for i from 1 to 3 do
    printf("  ODE %d: d²u_%d/dt² = c²(λ(H + (u_%d-u_%d)/(2dx))) · (u_%d-2u_%d+u_%d)/dx²\n",
           i, i, i+1, i-1, i+1, i, i-1);
end do;
printf("  ...\n");
for i from Nx-3 to Nx-1 do
    printf("  ODE %d: d²u_%d/dt² = c²(λ(H + (u_%d-u_%d)/(2dx))) · (u_%d-2u_%d+u_%d)/dx²\n",
           i, i, i+1, i-1, i+1, i, i-1);
end do;
printf("\n  Each ODE connects point i with its neighbors i-1 and i+1.\n");
printf("  This is why they are called COUPLED ODEs.\n\n");

# ============================================================
# STEP 7: SOLVING THE COUPLED ODEs USING FINITE DIFFERENCES
# ============================================================
# We use an explicit time integration scheme:
#   u_new[i] = 2*u_curr[i] - u_old[i] + dt² · (d²u_i/dt²)
#
# This comes from the central difference approximation:
#   d²u_i/dt² ≈ (u_new[i] - 2*u_curr[i] + u_old[i]) / dt²

printf("STEP 7: SOLVING THE COUPLED ODEs\n");
printf("  Using explicit time integration (central differences):\n");
printf("    u_new[i] = 2*u_curr[i] - u_old[i] + dt² · (d²u_i/dt²)\n\n");
printf("  Starting numerical integration...\n\n");

# Storage indices for visualization
save_indices := [42, 106, 211, 317, 422];
solutions := table();

# TIME INTEGRATION LOOP
for n from 1 to Nt do
    
    # --------------------------------------------------------
    # COMPUTE ALL COUPLED ODEs
    # Each iteration of this loop computes ONE ODE for point i
    # The ODEs are COUPLED because u_new[i] depends on u_curr[i-1] and u_curr[i+1]
    # --------------------------------------------------------
    for i from 1 to Nx-1 do
        
        # ----- COUPLING TERM 1: LOCAL STRAIN (∂u/∂x) -----
        # This connects u_i with its neighbors u_{i-1} and u_{i+1}
        du_dx := (u_curr[i+1] - u_curr[i-1]) / (2 * dx);
        
        # ----- MATERIAL PARAMETER H DEPENDS ON STRAIN -----
        H_total := 650 + du_dx;
        
        # ----- SQUARED SPEED OF SOUND c² -----
        if H_total < 700 then
            c2 := -3143*H_total + 1.99e7;
        elif H_total < 1000 then
            c2 := 7333*H_total + 1.257e7;
        else
            c2 := 1.99e7;
        end if;
        
        # ----- COUPLING TERM 2: SECOND DERIVATIVE (∂²u/∂x²) -----
        # This also connects u_i with its neighbors u_{i-1} and u_{i+1}
        u_xx := (u_curr[i+1] - 2*u_curr[i] + u_curr[i-1]) / dx^2;
        
        # ----- THE COUPLED ODE FOR POINT i -----
        # d²u_i/dt² = c² · u_xx
        # Discretized in time:
        u_new[i] := 2*u_curr[i] - u_old[i] + dt^2 * c2 * u_xx;
        
    end do;
    # --------------------------------------------------------
    # END OF COUPLED ODE COMPUTATION
    # --------------------------------------------------------
    
    # Apply boundary conditions (coupling the end points)
    apply_bc();
    
    # Store solutions for visualization
    for idx from 1 to 5 do
        if n = save_indices[idx] then
            solutions[n] := copy(u_new);
            printf("  Stored: t = %.3f T0 (time step %d/%d)\n", n*dt/T0, n, Nt);
        end if;
    end do;
    
    # Shift time layers for next iteration
    for i from 0 to Nx do
        u_old[i] := u_curr[i];
        u_curr[i] := u_new[i];
    end do;
    
    # Progress indicator
    if n mod 500 = 0 then
        printf("  Progress: %d/%d (%.0f%%)\n", n, Nt, 100*n/Nt);
    end if;
end do:

printf("\nSimulation completed!\n\n");

# ============================================================
# STEP 8: VISUALIZATION OF THE COUPLED ODE SOLUTION
# ============================================================
printf("STEP 8: VISUALIZATION\n");
printf("  Generating plots of the solution u_i(t)...\n");

colors := ["red", "blue", "green", "magenta", "black"];
plot_list := [];

for idx from 1 to 5 do
    n_idx := save_indices[idx];
    t_val := evalf(n_idx * dt / T0, 3);
    points := [seq([x_vals[i+1], solutions[n_idx][i]], i=0..Nx)];
    p := plot(points,
              labels=["x [m]", "u(x,t) [m]"],
              title=sprintf("Wave at t = %.3f T", t_val),
              color=colors[idx],
              legend=sprintf("t = %.3f T", t_val),
              thickness=2);
    plot_list := [op(plot_list), p];
end do:

display(plot_list, title="Solution of the Coupled ODE System", size=[800,500]);
printf("  Plot shows the wave at 5 different times.\n\n");

# ============================================================
# STEP 9: ANIMATION OF THE COUPLED ODE SOLUTION
# ============================================================
printf("STEP 9: ANIMATION\n");
printf("  Generating animation of the moving wave...\n");

animation_frames := [];
t_labels := [0.1, 0.25, 0.5, 0.75, 1.0];
explanation := [
    "t = 0.10 T: Wave begins moving right.\nThe wave deforms because c² depends on strain.",
    "t = 0.25 T: Wave approaches the right end.\nAmplitude changes due to nonlinearity.",
    "t = 0.50 T: Wave reaches the end and reflects.\n∂u/∂x=0 at the end (free boundary).",
    "t = 0.75 T: Wave moves back left.\nWave shape is mirrored.",
    "t = 1.00 T: Wave returns to initial condition.\nOne complete period completed."
];

for idx from 1 to 5 do
    n_idx := save_indices[idx];
    t_val := evalf(n_idx * dt / T0, 3);
    points := [seq([x_vals[i+1], solutions[n_idx][i]], i=0..Nx)];
    
    p := plot(points,
              labels=["x [m]", "u(x,t) [m]"],
              title=sprintf("Longitudinal wave at t = %.2f T", t_labels[idx]),
              color="blue",
              thickness=3,
              view=[0..L, -A0*2..A0*2]);
    
    text := plots:-textplot([0.02, A0*1.5, explanation[idx]],
                            font=["Arial", 10],
                            color="darkred",
                            align="LEFT");
    
    animation_frames := [op(animation_frames), display(p, text)];
end do:

# Repeat frames for smooth animation
smooth_frames := [];
for rep from 1 to 4 do
    for idx from 1 to 5 do
        smooth_frames := [op(smooth_frames), animation_frames[idx]];
    end do;
end do:

display(smooth_frames, insequence=true, size=[800,600]);
printf("  Animation started! (%d frames)\n\n", nops(smooth_frames));

# ============================================================
# STEP 10: SUMMARY FOR THE STUDENT
# ============================================================
printf("========================================\n");
printf("              SUMMARY\n");
printf("========================================\n\n");
printf("WHAT IS A COUPLED ODE SYSTEM?\n");
printf("  • We have %d unknown functions u_i(t), i = 1..%d\n", Nx-1, Nx-1);
printf("  • Each ODE connects u_i with its neighbors u_{i-1} and u_{i+1}\n");
printf("  • This is why they are called COUPLED ODEs\n\n");
printf("WHERE ARE THE ODEs IN THE CODE?\n");
printf("  • Inside the main time loop (for n from 1 to Nt)\n");
printf("  • In the inner loop (for i from 1 to Nx-1)\n");
printf("  • Each iteration computes ONE ODE for point i\n\n");
printf("WHAT DOES EACH ODE DO?\n");
printf("  • Computes d²u_i/dt² = c² · (u_{i+1}-2u_i+u_{i-1})/dx²\n");
printf("  • Updates u_new[i] = 2*u_curr[i] - u_old[i] + dt² · (d²u_i/dt²)\n\n");
printf("ANSWER TO THE ORIGINAL QUESTION:\n");
printf("  Q: Can pdsolve handle c²(λ(H + ∂u/∂x))?\n");
printf("  A: NO, pdsolve CANNOT handle this nonlinear PDE.\n");
printf("  SOLUTION: Convert to COUPLED ODEs and use finite differences.\n");
printf("========================================\n");

0.4e-1

 

0.2400000000e-6

 

100

 

0.4000000000e-3

 

[0., 0.4000000000e-3, 0.8000000000e-3, 0.1200000000e-2, 0.1600000000e-2, 0.2000000000e-2, 0.2400000000e-2, 0.2800000000e-2, 0.3200000000e-2, 0.3600000000e-2, 0.4000000000e-2, 0.4400000000e-2, 0.4800000000e-2, 0.5200000000e-2, 0.5600000000e-2, 0.6000000000e-2, 0.6400000000e-2, 0.6800000000e-2, 0.7200000000e-2, 0.7600000000e-2, 0.8000000000e-2, 0.8400000000e-2, 0.8800000000e-2, 0.9200000000e-2, 0.9600000000e-2, 0.1000000000e-1, 0.1040000000e-1, 0.1080000000e-1, 0.1120000000e-1, 0.1160000000e-1, 0.1200000000e-1, 0.1240000000e-1, 0.1280000000e-1, 0.1320000000e-1, 0.1360000000e-1, 0.1400000000e-1, 0.1440000000e-1, 0.1480000000e-1, 0.1520000000e-1, 0.1560000000e-1, 0.1600000000e-1, 0.1640000000e-1, 0.1680000000e-1, 0.1720000000e-1, 0.1760000000e-1, 0.1800000000e-1, 0.1840000000e-1, 0.1880000000e-1, 0.1920000000e-1, 0.1960000000e-1, 0.2000000000e-1, 0.2040000000e-1, 0.2080000000e-1, 0.2120000000e-1, 0.2160000000e-1, 0.2200000000e-1, 0.2240000000e-1, 0.2280000000e-1, 0.2320000000e-1, 0.2360000000e-1, 0.2400000000e-1, 0.2440000000e-1, 0.2480000000e-1, 0.2520000000e-1, 0.2560000000e-1, 0.2600000000e-1, 0.2640000000e-1, 0.2680000000e-1, 0.2720000000e-1, 0.2760000000e-1, 0.2800000000e-1, 0.2840000000e-1, 0.2880000000e-1, 0.2920000000e-1, 0.2960000000e-1, 0.3000000000e-1, 0.3040000000e-1, 0.3080000000e-1, 0.3120000000e-1, 0.3160000000e-1, 0.3200000000e-1, 0.3240000000e-1, 0.3280000000e-1, 0.3320000000e-1, 0.3360000000e-1, 0.3400000000e-1, 0.3440000000e-1, 0.3480000000e-1, 0.3520000000e-1, 0.3560000000e-1, 0.3600000000e-1, 0.3640000000e-1, 0.3680000000e-1, 0.3720000000e-1, 0.3760000000e-1, 0.3800000000e-1, 0.3840000000e-1, 0.3880000000e-1, 0.3920000000e-1, 0.3960000000e-1, 0.4000000000e-1]

 

========================================
     COUPLED ODEs FROM WAVE EQUATION
========================================

STEP 1: SYSTEM PARAMETERS
  Rod length L = 0.0400 m (4.0 cm)
  Initial amplitude A0 = 2.40e-07 m
  Number of spatial points Nx+1 = 101
  Number of COUPLED ODEs = 99 (for internal points)
  Spatial step dx = 4.00e-04 m

STEP 2: MATERIAL MODEL
  c²(H) = piecewise function:
    H < 700:   c² = -3143·H + 1.99e7
    700 ≤ H < 1000: c² = 7333·H + 1.257e7
    H ≥ 1000:  c² = 1.99e7 (constant)
  λ(H) = 3/250000000 * H for H < 1000

 

 

4460.941605

 

0.4483358396e-7

 

52822.00360

 

0.1893150452e-4

 

1500

 

STEP 3: NUMERICAL PARAMETERS
  Maximum wave speed c_max = 4460.9 m/s
  Resonance frequency f0 = 52822.0 Hz (ultrasonic!)
  Period T0 = 1.89e-05 s
  Time step dt = 4.48e-08 s
  Number of time steps Nt = 1500
  CFL number = 0.500 (must be < 1 for stability)

 

 

`Array(0..100, {(1) = 0, (2) = 0, (3) = 0, (4) = 0, (5) = 0, (6) = 0, (7) = 0, (8) = 0, (9) = 0, (10) = 0, (11) = 0, (12) = 0, (13) = 0, (14) = 0, (15) = 0, (16) = 0, (17) = 0, (18) = 0, (19) = 0, (20) = 0, (21) = 0, (22) = 0, (23) = 0, (24) = 0, (25) = 0, (26) = 0, (27) = 0, (28) = 0, (29) = 0, (30) = 0, (31) = 0, (32) = 0, (33) = 0, (34) = 0, (35) = 0, (36) = 0, (37) = 0, (38) = 0, (39) = 0, (40) = 0, (41) = 0, (42) = 0, (43) = 0, (44) = 0, (45) = 0, (46) = 0, (47) = 0, (48) = 0, (49) = 0, (50) = 0, (51) = 0, (52) = 0, (53) = 0, (54) = 0, (55) = 0, (56) = 0, (57) = 0, (58) = 0, (59) = 0, (60) = 0, (61) = 0, (62) = 0, (63) = 0, (64) = 0, (65) = 0, (66) = 0, (67) = 0, (68) = 0, (69) = 0, (70) = 0, (71) = 0, (72) = 0, (73) = 0, (74) = 0, (75) = 0, (76) = 0, (77) = 0, (78) = 0, (79) = 0, (80) = 0, (81) = 0, (82) = 0, (83) = 0, (84) = 0, (85) = 0, (86) = 0, (87) = 0, (88) = 0, (89) = 0, (90) = 0, (91) = 0, (92) = 0, (93) = 0, (94) = 0, (95) = 0, (96) = 0, (97) = 0, (98) = 0, (99) = 0, (100) = 0})`

 

`Array(0..100, {(1) = 0, (2) = 0, (3) = 0, (4) = 0, (5) = 0, (6) = 0, (7) = 0, (8) = 0, (9) = 0, (10) = 0, (11) = 0, (12) = 0, (13) = 0, (14) = 0, (15) = 0, (16) = 0, (17) = 0, (18) = 0, (19) = 0, (20) = 0, (21) = 0, (22) = 0, (23) = 0, (24) = 0, (25) = 0, (26) = 0, (27) = 0, (28) = 0, (29) = 0, (30) = 0, (31) = 0, (32) = 0, (33) = 0, (34) = 0, (35) = 0, (36) = 0, (37) = 0, (38) = 0, (39) = 0, (40) = 0, (41) = 0, (42) = 0, (43) = 0, (44) = 0, (45) = 0, (46) = 0, (47) = 0, (48) = 0, (49) = 0, (50) = 0, (51) = 0, (52) = 0, (53) = 0, (54) = 0, (55) = 0, (56) = 0, (57) = 0, (58) = 0, (59) = 0, (60) = 0, (61) = 0, (62) = 0, (63) = 0, (64) = 0, (65) = 0, (66) = 0, (67) = 0, (68) = 0, (69) = 0, (70) = 0, (71) = 0, (72) = 0, (73) = 0, (74) = 0, (75) = 0, (76) = 0, (77) = 0, (78) = 0, (79) = 0, (80) = 0, (81) = 0, (82) = 0, (83) = 0, (84) = 0, (85) = 0, (86) = 0, (87) = 0, (88) = 0, (89) = 0, (90) = 0, (91) = 0, (92) = 0, (93) = 0, (94) = 0, (95) = 0, (96) = 0, (97) = 0, (98) = 0, (99) = 0, (100) = 0})`

 

`Array(0..100, {(1) = 0, (2) = 0, (3) = 0, (4) = 0, (5) = 0, (6) = 0, (7) = 0, (8) = 0, (9) = 0, (10) = 0, (11) = 0, (12) = 0, (13) = 0, (14) = 0, (15) = 0, (16) = 0, (17) = 0, (18) = 0, (19) = 0, (20) = 0, (21) = 0, (22) = 0, (23) = 0, (24) = 0, (25) = 0, (26) = 0, (27) = 0, (28) = 0, (29) = 0, (30) = 0, (31) = 0, (32) = 0, (33) = 0, (34) = 0, (35) = 0, (36) = 0, (37) = 0, (38) = 0, (39) = 0, (40) = 0, (41) = 0, (42) = 0, (43) = 0, (44) = 0, (45) = 0, (46) = 0, (47) = 0, (48) = 0, (49) = 0, (50) = 0, (51) = 0, (52) = 0, (53) = 0, (54) = 0, (55) = 0, (56) = 0, (57) = 0, (58) = 0, (59) = 0, (60) = 0, (61) = 0, (62) = 0, (63) = 0, (64) = 0, (65) = 0, (66) = 0, (67) = 0, (68) = 0, (69) = 0, (70) = 0, (71) = 0, (72) = 0, (73) = 0, (74) = 0, (75) = 0, (76) = 0, (77) = 0, (78) = 0, (79) = 0, (80) = 0, (81) = 0, (82) = 0, (83) = 0, (84) = 0, (85) = 0, (86) = 0, (87) = 0, (88) = 0, (89) = 0, (90) = 0, (91) = 0, (92) = 0, (93) = 0, (94) = 0, (95) = 0, (96) = 0, (97) = 0, (98) = 0, (99) = 0, (100) = 0})`

 

STEP 4: INITIAL CONDITION
  u(x,0) = A0·cos(πx/L)
  ∂u/∂t(x,0) = 0
  This creates the first harmonic vibration mode.
  The rod is maximally stretched at the middle (x = 0.02 m).

  Initial values for the first 5 points (i=0 to 4):
    u[0](0) = 2.40e-07 m at x = 0.0000 m
    u[1](0) = 2.40e-07 m at x = 0.0004 m
    u[2](0) = 2.40e-07 m at x = 0.0008 m
    u[3](0) = 2.39e-07 m at x = 0.0012 m
    u[4](0) = 2.38e-07 m at x = 0.0016 m
    ...

 

 

Warning, (in apply_bc) `u_new` is implicitly declared local

 

STEP 5: BOUNDARY CONDITIONS
  Neumann: ∂u/∂x = 0 at x = 0 and x = L
  This means: u(t) = u(t) and u_100(t) = u_99(t)
  Physically: The ends are FREE (can move without force).
  Waves reflect at the ends WITHOUT sign reversal.

STEP 6: THE COUPLED ODE SYSTEM
  After spatial discretization, we get 99 coupled ODEs:

  ODE 1: d²u_1/dt² = c²(λ(H + (u_2-u_0)/(2dx))) · (u_2-2u_1+u_0)/dx²
  ODE 2: d²u_2/dt² = c²(λ(H + (u_3-u_1)/(2dx))) · (u_3-2u_2+u_1)/dx²
  ODE 3: d²u_3/dt² = c²(λ(H + (u_4-u_2)/(2dx))) · (u_4-2u_3+u_2)/dx²
  ...
  ODE 97: d²u_97/dt² = c²(λ(H + (u_98-u_96)/(2dx))) · (u_98-2u_97+u_96)/dx²
  ODE 98: d²u_98/dt² = c²(λ(H + (u_99-u_97)/(2dx))) · (u_99-2u_98+u_97)/dx²
  ODE 99: d²u_99/dt² = c²(λ(H + (u_100-u_98)/(2dx))) · (u_100-2u_99+u_98)/dx²

  Each ODE connects point i with its neighbors i-1 and i+1.
  This is why they are called COUPLED ODEs.

STEP 7: SOLVING THE COUPLED ODEs
  Using explicit time integration (central differences):
    u_new[i] = 2*u_curr[i] - u_old[i] + dt² · (d²u_i/dt²)

  Starting numerical integration...

 

 

[42, 106, 211, 317, 422]

 

table( [ ] )

 

  Stored: t = 0.099 T0 (time step 42/1500)
  Stored: t = 0.251 T0 (time step 106/1500)
  Stored: t = 0.500 T0 (time step 211/1500)
  Stored: t = 0.751 T0 (time step 317/1500)
  Stored: t = 0.999 T0 (time step 422/1500)
  Progress: 500/1500 (33%)
  Progress: 1000/1500 (67%)
  Progress: 1500/1500 (100%)

Simulation completed!

STEP 8: VISUALIZATION
  Generating plots of the solution u_i(t)...

 

["red", "blue", "green", "magenta", "black"]

 

[]

 

 

  Plot shows the wave at 5 different times.

STEP 9: ANIMATION
  Generating animation of the moving wave...

 

[]

 

[.1, .25, .5, .75, 1.0]

 

["t = 0.10 Tâ‚€: Wave begins moving right.
The wave deforms because c² depends on strain.", "t = 0.25 T₀: Wave approaches the right end.
Amplitude changes due to nonlinearity.", "t = 0.50 Tâ‚€: Wave reaches the end and reflects.
&PartialD;u/&PartialD;x=0 at the end (free boundary).", "t = 0.75 Tâ‚€: Wave moves back left.
Wave shape is mirrored.", "t = 1.00 Tâ‚€: Wave returns to initial condition.
One complete period completed."]

 

[]

 

 

  Animation started! (20 frames)

========================================
              SUMMARY
========================================

WHAT IS A COUPLED ODE SYSTEM?
  • We have 99 unknown functions u_i(t), i = 1..99
  • Each ODE connects u_i with its neighbors u_{i-1} and u_{i+1}
  • This is why they are called COUPLED ODEs

WHERE ARE THE ODEs IN THE CODE?
  • Inside the main time loop (for n from 1 to Nt)
  • In the inner loop (for i from 1 to Nx-1)
  • Each iteration computes ONE ODE for point i

WHAT DOES EACH ODE DO?
  • Computes d²u_i/dt² = c² · (u_{i+1}-2u_i+u_{i-1})/dx²
  • Updates u_new[i] = 2*u_curr[i] - u_old[i] + dt² · (d²u_i/dt²)

ANSWER TO THE ORIGINAL QUESTION:
  Q: Can pdsolve handle c²(λ(H + ∂u/∂x))?
  A: NO, pdsolve CANNOT handle this nonlinear PDE.
  SOLUTION: Convert to COUPLED ODEs and use finite differences.
========================================

 

 


 

Download pde_vrgstuk_Can_pdsolve_handle_a_procedure_in_the_pde_mprimesDEFA_18-4-2026.mw

@Rouben Rostamian  
Thanks for the code! It showed me a different way to use the Euler-Lagrange differential equation. for his first derivative 

@Rouben Rostamian  

Amzing work too,

However, I get the impression that it’s not quite as straightforward as in dharr’s code.

Take this as an example:

To further simplify, observe that the fraction (diff(y(x), x))/sqrt(1+(diff(y(x), x))^2) takes values between -1 and 1, and therefore

we may take it to be the sine of some angle theta, as in sin(theta) = (diff(y(x), x))/sqrt(1+(diff(y(x), x))^2), `and`(-(1/2)*Pi <= theta, theta <= (1/2)*Pi), is this trivial ?

@dharr 
Amazing work. 
One thing about the fence length : 100 m  ?

 

The calculation is a bit messy, and I wasn't quite sure which direction to take, but that has changed.

Are isoperimetric solution curves always convex?, yes it seems

It boils down to deriving the differential equation, which appears to be nonlinear.

So I'm going to revise the calculation above.


 

 

 

 

restart;
with(plots):

# STEP 1: λ from length constraint
lambda := evalf(50/Pi);

# STEP 2: Create C values using seq
C_vals := [seq(16.2 + i*0.2, i = 0..14), 19.0];

# Compute F values using seq
F_vals := [seq(evalf(Int(sin(phi)*cos(phi)/sqrt(C_vals[i] + lambda*sin(phi)), phi = -Pi/2 .. Pi/2)), i = 1..nops(C_vals))];

# Find sign change
product_vals := [seq(F_vals[i] * F_vals[i+1], i = 1..nops(F_vals)-1)];
idx := 1;
while idx <= nops(product_vals) and product_vals[idx] >= 0 do
    idx := idx + 1;
end do:

if idx <= nops(product_vals) then
    C_left := C_vals[idx];
    C_right := C_vals[idx+1];
    F_left := F_vals[idx];
    F_right := F_vals[idx+1];
else
    C_left := 16.2;
    C_right := 17.0;
    F_left := evalf(Int(sin(phi)*cos(phi)/sqrt(C_left + lambda*sin(phi)), phi = -Pi/2 .. Pi/2));
    F_right := evalf(Int(sin(phi)*cos(phi)/sqrt(C_right + lambda*sin(phi)), phi = -Pi/2 .. Pi/2));
end if:

# Bisection
a := C_left: b := C_right: fa := F_left: fb := F_right:
for iter from 1 to 25 do
    c := (a + b)/2:
    if c <= lambda + 0.001 then
        c := lambda + 0.01:
    end if:
    fc := evalf(Int(sin(phi)*cos(phi)/sqrt(c + lambda*sin(phi)), phi = -Pi/2 .. Pi/2)):
    if abs(fc) < 1e-10 then
        break:
    end if:
    if fa * fc < 0 then
        b := c: fb := fc:
    else
        a := c: fa := fc:
    end if:
end do:

C_opt := (a + b)/2:
if C_opt <= lambda then
    C_opt := lambda + 0.1;
end if:

printf("C_opt = %.8f\n", C_opt);

# STEP 3: Plot - gebruik x als parameter
x_max := sqrt(2*(C_opt + lambda));
x_vals := [seq(0 + i*x_max/200, i = 0..200)]:

upper_points := []:
for x in x_vals do
    sin_phi := (x^2/2 - C_opt)/lambda;
    if abs(sin_phi) <= 1 then
        phi := arcsin(sin_phi);
        y := evalf(Int(sin(psi)*lambda*cos(psi)/sqrt(2*(C_opt + lambda*sin(psi))), psi = -Pi/2 .. phi));
        upper_points := [op(upper_points), [x, y]];
    end if;
end do:

lower_points := [seq([upper_points[i][1], -upper_points[i][2]], i = 1..nops(upper_points))]:

plot([upper_points, lower_points],
     color = ["red", "blue"],
     scaling = constrained,
     labels = ["x (m)", "y (m)"],
     title = "Optimal fence for the farmer (100 m)");

lambda_final := lambda;
C_final := C_opt;

15.91549430

 

[16.2, 16.4, 16.6, 16.8, 17.0, 17.2, 17.4, 17.6, 17.8, 18.0, 18.2, 18.4, 18.6, 18.8, 19.0, 19.0]

 

[-.1780411788, -.1633715659, -.1524516834, -.1436552975, -.1362602225, -.1298720646, -.1242482103, -.1192272373, -.1146955706, -.1105698760, -.1067869753, -.1032976976, -.1000629409, -0.9705104585e-1, -0.9423598463e-1, -0.9423598463e-1]

 

[0.2908686618e-1, 0.2490627024e-1, 0.2190049193e-1, 0.1957450280e-1, 0.1769639642e-1, 0.1613637159e-1, 0.1481377085e-1, 0.1367483601e-1, 0.1268187502e-1, 0.1180742262e-1, 0.1103084868e-1, 0.1033627141e-1, 0.9711213065e-2, 0.9145700865e-2, 0.8880420799e-2]

 

1

 

C_opt = 16.99999999

 

8.113629803

 

 

15.91549430

 

16.99999999

(1.1)

 

 

 

 

 

restart;
with(plots):

lambda := evalf(50/Pi);
C_opt := 16.85;  # Approximate value from earlier calculation

# Generate points for the fence - volledige cyclus van -Pi/2 tot 3Pi/2
phi_vals := [seq(-Pi/2 + i*2*Pi/400, i = 0 .. 400)]:

upper_points := []:
for phi in phi_vals do
    x_val := sqrt(2*(C_opt + lambda*sin(phi)));
    y_val := evalf(Int(sin(psi)*lambda*cos(psi)/sqrt(2*(C_opt + lambda*sin(psi))), psi = -Pi/2 .. phi));
    upper_points := [op(upper_points), [x_val, y_val]];
end do:

# De onderste punten zijn de negatieve y-waarden (de curve is symmetrisch)
lower_points := [seq([upper_points[i][1], -upper_points[i][2]], i = 1..nops(upper_points))]:

plot([upper_points, lower_points],
     color = ["red", "blue"],
     scaling = constrained,
     labels = ["x (m)", "y (m)"],
     title = "Optimal fence for the farmer (100 m) - volledige cyclus");

15.91549430

 

16.85

 

 

 

 

 

 

 

restart;
with(plots):

lambda := evalf(50/Pi);
C_opt := lambda;

# Als C = λ, then is the curve a circle with:
# Middelpunt: (R, 0) met R = λ
# Straal: R = λ
# De cirkel gaat door de oorsprong (0,0) en door (2R, 0)

R := lambda;
middelpunt_x := R;
middelpunt_y := 0;

# Parametrische equation  cirkle
theta_vals := [seq(Pi + i*Pi/100, i = 0 .. 100)]:  # van π tot 2π voor bovenste helft

cirkel_upper := [seq([middelpunt_x + R*cos(theta), R*sin(theta)], theta in theta_vals)]:
cirkel_lower := [seq([middelpunt_x + R*cos(theta), -R*sin(theta)], theta in theta_vals)]:

plot([cirkel_upper, cirkel_lower],
     color = ["red", "blue"],
     scaling = constrained,
     labels = ["x (m)", "y (m)"],
     title = "Optimale omheining is een cirkel (C = λ)",
     legend = ["Bovenste tak", "Onderste tak"]);

printf("========================================\n");
printf("OPTIMALE SOLUTION:\n");
printf("========================================\n");
printf("λ = %.8f m\n", lambda);
printf("C = %.8f m\n", C_opt);
printf("Straal van de cirkel R = λ = %.8f m\n", R);
printf("Totale lengte = 2πR = %.8f m (klopt!)\n", 2*Pi*R);
printf("========================================\n");

15.91549430

 

15.91549430

 

15.91549430

 

15.91549430

 

0

 

 

========================================
OPTIMALE OPLOSSING:
========================================
λ = 15.91549430 m
C = 15.91549430 m
Straal van de cirkel R = λ = 15.91549430 m
Totale lengte = 2πR = 99.99999996 m (klopt!)
========================================

 

 


 

Download weideproblee_nu_voor_mpromesDEFA_13-4-2026.mw

@dharr Final answer to your question

"Did you mean the cost is to be maximized for a given L?"

Yes. That is exactly what the Dutch problem states.
Janhardo assumed correctly. Your alternative interpretation (fix cost and L, maximize area) is not this problem.

You wrote earlier: "The cost is Int(xy(x)) and the area is Int(y) and the fence length is L. So the cost and L are fixed and the area is to be maximized?"*

That "so" was a leap. The problem never said cost is fixed — it said the price per m² increases linearly, so the total cost (value) is what changes with shape. The farmer chooses the shape to make that total cost as large as possible, given L.

@Alfred_F 
There i smuch more involved in the meadow problem concerning maple :-) 
the Dido code can be found here : Integral and Minimum - MaplePrimes  , so if someone feels the need to investigate this too..

it should be something like this teardrop form 

but this is no smooth curve...so wrong
 

Dido his problem :


 

 

dido his problem
 

 

# Translated and corrected version: one plot that was not visible is now fixed
restart;
with(PDEtools):
with(Physics):
with(DEtools):
with(plots):
Setup(mathematicalnotation = true):
declare(y(x), prime=x);

# ------------------------------------------------------------
# 1. Helper functions (previously used)
# ------------------------------------------------------------
detect_order := proc(eq, y, x)
    local derivs;
    derivs := indets(eq, specfunc(diff));
    if derivs = {} then return 0; end if;
    return max(map(d -> nops([op(d)])-1, derivs));
end proc:

EL_equation := proc(L, y, x)
    local dLdy, dLdyprime;
    dLdy := diff(L, y(x));
    dLdyprime := diff(L, diff(y(x), x));
    return simplify(dLdy - diff(dLdyprime, x));
end proc:

detect_type := proc(L)
    local partials;
    partials := indets(L, 'diff'(anything, anything));
    if partials <> {} and ormap(d -> nops([op(d)]) > 2, partials) then
        return "field theory (PDE)";
    elif nops(indets(L, specfunc(diff))) > 1 then
        return "multiple functions (system)";
    else
        return "classical (1 function, ODE)";
    end if;
end proc:

is_linear := proc(eq, y, x)
    local vars, max_order, k;
    max_order := detect_order(eq, y, x);
    vars := {y(x)} union {seq(diff(y(x), x$k), k=1..max_order)};
    try
        if not type(eq, `=`) then
            eq := eq;
        else
            eq := lhs(eq) - rhs(eq);
        end if;
        return andmap(term -> degree(term, vars) <= 1, [op(eq)]);
    catch:
        return false;
    end try;
end proc:

historical_stage := proc(expr, y, x, source)
    local has_first, has_second, has_x, L_simple, L_brach, L_catenoid, L_beam;
    L_simple   := sqrt(1 + diff(y(x), x)^2);
    L_brach    := sqrt((1 + diff(y(x), x)^2)/y(x));
    L_catenoid := y(x) * sqrt(1 + diff(y(x), x)^2);
    L_beam     := diff(y(x), x$2)^2;
    
    if source = "L" then
        if expr = L_simple then
            return "Pre-Euler (Fermat, 1662) – shortest time / shortest path";
        elif expr = L_brach then
            return "Pre-Euler (Bernoulli, 1696) – brachistochrone / tautochrone";
        elif expr = L_catenoid then
            return "Euler (1744) – minimal surface of revolution (catenoid)";
        elif expr = L_beam then
            return "Post-Euler (19th century) – Euler-Bernoulli beam";
        end if;
        
        has_first := has(expr, diff(y(x), x));
        has_second := has(expr, diff(y(x), x$2));
        has_x := has(expr, x) and not has(expr, diff(y(x), x));
        if has_second then
            return "Post-Euler (19th century) – higher-order Lagrangian";
        elif has_first and has_x then
            return "Lagrange (1755) – L = L(x, y, y')";
        elif has_first then
            return "Euler (1744) – L = L(y, y') autonomous";
        else
            return "Pre-Euler (17th century) – L without y' (static)";
        end if;
    else # source = "EL"
        has_first := has(expr, diff(y(x), x));
        has_second := has(expr, diff(y(x), x$2));
        has_x := has(expr, x);
        if has_second then
            return "Post-Euler – second-order (or higher) ODE";
        elif has_first and has_x then
            return "Lagrange – first-order ODE with explicit x";
        elif has_first then
            return "Euler – first-order autonomous ODE";
        else
            return "Pre-Euler – algebraic equation";
        end if;
    end if;
end proc:

# ------------------------------------------------------------
# 2. Overview table of famous historical examples
# ------------------------------------------------------------
print_famous_examples_overview := proc()
    printf("\n");
    printf("====================================================================================================================================\n");
    printf("|                     FAMOUS HISTORICAL EXAMPLES FROM THE CALCULUS OF VARIATIONS                                                     |\n");
    printf("====================================================================================================================================\n");
    printf("| Historical example                   | Lagrangian L                                | Euler-Lagrange equation                      | ODE type (odeadvisor)          |\n");
    printf("|---------------------------------------|---------------------------------------------|---------------------------------------------|--------------------------------|\n");
    printf("| Fermat (1662) – shortest time/path   | L = sqrt(1+y'^2)                            | y'' = 0                                     | _linear, _second_order, _quadrature |\n");
    printf("| Bernoulli (1696) – brachistochrone   | L = sqrt((1+y'^2)/y)                        | 2y y'' + (y')^2 + 1 = 0                     | _second_order, _missing_x      |\n");
    printf("| Huygens (1673) – tautochrone         | L = sqrt((1+y'^2)/y) (same)                 | 2y y'' + (y')^2 + 1 = 0                     | _second_order, _missing_x      |\n");
    printf("| Euler (1744) – catenoid (min. area)  | L = y * sqrt(1+y'^2)                        | y y'' - (y')^2 - 1 = 0                      | _second_order, _reducible, _missing_x |\n");
    printf("| Lagrange (1755) – explicit x         | L = e^x * (y')^2                            | y'' + y' = 0                                | _linear, _second_order, _exact |\n");
    printf("| Geodesic (Lagrange, 1760) – shortest path| L = sqrt(1+y'^2+y^2)                     | (1+y'^2) y'' - y (1+y'^2) - y (y')^2 = 0?  | _second_order, _nonlinear      |\n");
    printf("| Post-Euler – Euler-Bernoulli beam    | L = (y'')^2                                 | y'''' = 0                                   | _linear, _fourth_order, _quadrature |\n");
    printf("====================================================================================================================================\n");
    printf("Note: The tautochrone has the same Lagrangian as the brachistochrone; the difference lies in the boundary conditions.\n");
    printf("For the geodesic a simple non-flat metric is chosen: L = sqrt(1 + y'^2 + y^2).\n\n");
end proc:

# ------------------------------------------------------------
# 3. Main analysis procedure (with odeadvisor)
# ------------------------------------------------------------
analyze_Lagrangian := proc(L, y, x,
                           { classify_from::string := "L",
                             show_ode::boolean := false,
                             show_timeline::boolean := false })
    local eq, type_prob, order_prob, lin, history, source_expr, ode_type;
    
    if show_timeline then
        print_Lagrangian_timeline();
    end if;
    
    type_prob := detect_type(L);
    eq := EL_equation(L, y, x);
    
    if show_ode then
        printf("Euler-Lagrange equation: %a\n", eq);
    end if;
    
    try
        ode_type := DEtools:-odeadvisor(eq, y(x));
    catch:
        ode_type := "cannot determine (not an ODE or too complex)";
    end try;
    
    if classify_from = "L" then
        source_expr := L;
    else
        source_expr := eq;
    end if;
    
    order_prob := detect_order(eq, y, x);
    lin := is_linear(eq, y, x);
    history := historical_stage(source_expr, y, x, classify_from);
    
    return table([
        "Lagrangian" = L,
        "Problem type" = type_prob,
        "Euler-Lagrange equation" = eq,
        "ODE type (odeadvisor)" = ode_type,
        "Order of ODE" = order_prob,
        "Linear?" = lin,
        "Classification based on" = classify_from,
        "Historical phase" = history
    ]);
end proc:

print_Lagrangian_timeline := proc()
    printf("\n");
    printf("================================================================================\n");
    printf("|                  HISTORICAL TIMELINE OF THE LAGRANGIAN                      |\n");
    printf("================================================================================\n");
    printf("| Period           | Figures                  | Characteristic Lagrangian     |\n");
    printf("|------------------|--------------------------|-------------------------------|\n");
    printf("| Pre-Euler (17th) | Fermat, Bernoulli        | L = sqrt(1+y'^2) (Fermat)     |\n");
    printf("|                  |                          | L = sqrt((1+y'^2)/y) (Bernoulli) |\n");
    printf("| Euler (1744-60)  | Leonhard Euler           | L = L(y, y') autonomous       |\n");
    printf("| Lagrange (1755)  | J.-L. Lagrange           | L = L(x, y, y')               |\n");
    printf("| Post-Euler (19th)| Hamilton, Jacobi, Noether| L with higher derivatives     |\n");
    printf("| Modern           | Einstein, Feynman        | Lagrangian density for fields  |\n");
    printf("================================================================================\n");
    printf("\n Note: The pre-Euler examples of Fermat and Bernoulli are shown here.\n\n");
end proc:

# ------------------------------------------------------------
# 4. START: show overview of famous examples
# ------------------------------------------------------------
print_famous_examples_overview();

# ------------------------------------------------------------
# 5. EXTRA: Isoperimetric Dido problem (max area, fixed arc length)
# ------------------------------------------------------------
printf("\n");
printf("********************************************************************************\n");
printf("*          THE ISOPERIMETRIC PROBLEM OF DIDO (9th century BC)                 *\n");
printf("*   Maximize the area under a curve with given arc length                     *\n");
printf("*   and a straight coastline (the x-axis).                                    *\n");
printf("********************************************************************************\n\n");

# Define the functional with Lagrange multiplier lambda
# We want to maximize: A = ∫ y dx  subject to  ∫ sqrt(1+y'^2) dx = L (fixed)
# The Lagrangian becomes: L = y + λ * sqrt(1 + y'^2)
lambda := 'lambda':   # symbol for the multiplier
L_Dido := y(x) + lambda * sqrt(1 + diff(y(x), x)^2);

printf("Lagrangian with Lagrange multiplier λ: L = y + λ * sqrt(1 + y'^2)\n");

# Euler-Lagrange equation
EL_Dido := EL_equation(L_Dido, y, x);
printf("Euler-Lagrange equation: %a\n", EL_Dido);

# Simplify the equation (it can be reduced to a circle equation)
# Maple can classify the ODE:
try
    ode_type_Dido := DEtools:-odeadvisor(EL_Dido, y(x));
    printf("ODE type (odeadvisor): %a\n", ode_type_Dido);
catch:
    printf("ODE type could not be determined.\n");
end try;

# Solve the ODE (general solution)
sol_general := dsolve(EL_Dido, y(x));
printf("General solution: %a\n", sol_general);

# The solution is a circle: (x - C1)^2 + (y - C2)^2 = λ^2
# We now choose a concrete example: arc length L = 2, coastline from x=-1 to x=1,
# and the curve touches the coast at points (-1,0) and (1,0).
# Then the radius is R = λ, and the centre is (0, R) (circle through (-1,0) and (1,0)).
# Equation: x^2 + (y - R)^2 = R^2  =>  y = R - sqrt(R^2 - x^2)
# Arc length (half circle) = πR = L = 2  => R = 2/π.

L_length := 2;   # given arc length
R := L_length / Pi;
# The optimal curve:
# Correcte definitie van de optimale kromme (halve cirkel op de x-as)
# Correct definition of the optimal curve (semicircle on the x-axis)
y_opt := x -> sqrt(R^2 - x^2);

# Plot of the semicircle
plot_opt := plot(y_opt(x), x=-R..R, color=red, thickness=2, scaling=constrained,
                 title=sprintf("Optimal circular arc for Dido problem (L = %d, R = %.3f)", L_length, evalf(R)),
                 labels=["x", "y"], labeldirections=[horizontal, vertical]):

# Coastline (blue dotted line) from -R to R (endpoints exactly touch the arc)
plot_coast := plot(0, x=-R..R, color=blue, thickness=2, linestyle=dot):

# Display
display([plot_opt, plot_coast], axes=boxed);

# Show the computed area
area := int(y_opt(x), x=-R..R);
printf("Enclosed area = %a (exact) ≈ %a\n", area, evalf(area));

# ------------------------------------------------------------
# 6. Analysis of the Dido problem with the existing procedure
# ------------------------------------------------------------
printf("\n--- Analysis via the general procedure (classification) ---\n");
res_Dido := analyze_Lagrangian(L_Dido, y, x, classify_from="L", show_ode=true, show_timeline=false):
print(res_Dido);

# ------------------------------------------------------------
# 7. Extra example: free closed curve (no coastline)
# ------------------------------------------------------------
printf("\n********************************************************************************\n");
printf("*   Variant: closed curve (no coastline) – the circle as optimal shape        *\n");
printf("********************************************************************************\n");
printf("For a completely closed curve of length L the optimal shape is a circle.\n");
printf("Area = L^2/(4π). For L=2 this gives area = %a.\n", evalf(2^2/(4*Pi)));
printf("This is larger than the area with a coastline (%a), because the coastline restricts freedom.\n", evalf(area));

# ------------------------------------------------------------
# End of code
# ------------------------------------------------------------
printf("\nEnd of demonstration.\n");

y(x)*`will now be displayed as`*y

 

`derivatives with respect to`*x*`of functions of one variable will now be displayed with '`

 


====================================================================================================================================
|                     FAMOUS HISTORICAL EXAMPLES FROM THE CALCULUS OF VARIATIONS                                                     |
====================================================================================================================================
| Historical example                   | Lagrangian L                                | Euler-Lagrange equation                      | ODE type (odeadvisor)          |
|---------------------------------------|---------------------------------------------|---------------------------------------------|--------------------------------|
| Fermat (1662) – shortest time/path   | L = sqrt(1+y'^2)                            | y'' = 0                                     | _linear, _second_order, _quadrature |
| Bernoulli (1696) – brachistochrone   | L = sqrt((1+y'^2)/y)                        | 2y y'' + (y')^2 + 1 = 0                     | _second_order, _missing_x      |
| Huygens (1673) – tautochrone         | L = sqrt((1+y'^2)/y) (same)                 | 2y y'' + (y')^2 + 1 = 0                     | _second_order, _missing_x      |
| Euler (1744) – catenoid (min. area)  | L = y * sqrt(1+y'^2)                        | y y'' - (y')^2 - 1 = 0                      | _second_order, _reducible, _missing_x |
| Lagrange (1755) – explicit x         | L = e^x * (y')^2                            | y'' + y' = 0                                | _linear, _second_order, _exact |
| Geodesic (Lagrange, 1760) – shortest path| L = sqrt(1+y'^2+y^2)                     | (1+y'^2) y'' - y (1+y'^2) - y (y')^2 = 0?  | _second_order, _nonlinear      |
| Post-Euler – Euler-Bernoulli beam    | L = (y'')^2                                 | y'''' = 0                                   | _linear, _fourth_order, _quadrature |
====================================================================================================================================
Note: The tautochrone has the same Lagrangian as the brachistochrone; the difference lies in the boundary conditions.
For the geodesic a simple non-flat metric is chosen: L = sqrt(1 + y'^2 + y^2).


********************************************************************************
*          THE ISOPERIMETRIC PROBLEM OF DIDO (9th century BC)                 *
*   Maximize the area under a curve with given arc length                     *
*   and a straight coastline (the x-axis).                                    *
********************************************************************************

 

 

y(x)+lambda*(1+(diff(y(x), x))^2)^(1/2)

 

Lagrangian with Lagrange multiplier λ: L = y + λ * sqrt(1 + y'^2)

 

((diff(y(x), x))^2*(1+(diff(y(x), x))^2)^(1/2)-lambda*(diff(diff(y(x), x), x))+(1+(diff(y(x), x))^2)^(1/2))/(1+(diff(y(x), x))^2)^(3/2)

 

Euler-Lagrange equation: (diff(y(x),x)^2*(1+diff(y(x),x)^2)^(1/2)-lambda*diff(diff(y(x),x),x)+(1+diff(y(x),x)^2)^(1/2))/(1+diff(y(x),x)^2)^(3/2)

 

[[_2nd_order, _missing_x], [_2nd_order, _exact, _nonlinear]]

 

ODE type (odeadvisor): [[_2nd_order, _missing_x], [_2nd_order, _exact, _nonlinear]]

 

y(x) = -(lambda+x+c__1)*(lambda-x-c__1)/(-c__1^2-2*c__1*x+lambda^2-x^2)^(1/2)+c__2, y(x) = (lambda+x+c__1)*(lambda-x-c__1)/(-c__1^2-2*c__1*x+lambda^2-x^2)^(1/2)+c__2

 

General solution: y(x) = -(lambda+x+c__1)*(lambda-x-c__1)/(-c__1^2-2*c__1*x+lambda^2-x^2)^(1/2)+c__2

 

2

 

2/Pi

 

proc (x) options operator, arrow; sqrt(Physics:-`^`(R, 2)-Physics:-`^`(x, 2)) end proc

 

 

2/Pi

 

Enclosed area = 2/Pi (exact) ≈ .6366197722

--- Analysis via the general procedure (classification) ---
Euler-Lagrange equation: (diff(y(x),x)^2*(1+diff(y(x),x)^2)^(1/2)-lambda*diff(diff(y(x),x),x)+(1+diff(y(x),x)^2)^(1/2))/(1+diff(y(x),x)^2)^(3/2)

 

res_Dido

 


********************************************************************************
*   Variant: closed curve (no coastline) – the circle as optimal shape        *
********************************************************************************
For a completely closed curve of length L the optimal shape is a circle.
Area = L^2/(4π). For L=2 this gives area = .3183098861.
This is larger than the area with a coastline (.6366197722), because the coastline restricts freedom.

End of demonstration.

 

 


 

Download dido_zijn_problem_opgelost_variatierekeneing_9-4-2026.mw

@Jean-Michel 

In the physics package, you can use arrow vectors or index tensor ( vector in cartesian coordinaties works not as a tensor notation as it seems : see example ) 

Arrow vectors are used for standard vector calculations, and index tensors  are used for tensor calculations.

As far as I can tell, these notation for vector  in the physics package are also different from the vector notations in the vector calculus package.

overrzicht_vectornotaties_voor_paketten_in_maple_mprimes_6-4-2026.mw

 

with(Physics):

# --- METHOD 1: Physics[Vectors] ---
with(Vectors):
A := 2*_i + 3*_j - _k;
B := _i - 2*_j + 4*_k;

# Dot product: just use .
A . B;  # Gives -8

# --- METHOD 2: Physics with indices ---
# No with(Vectors) needed!
A[mu] := (2, 3, -1);   # Components of A
B[mu] := (1, -2, 4);   # Components of B

# Dot product via Einstein summation
g_[mu, nu] * A[~mu] * B[~nu];


                     A := 2 _i + 3 _j - _k

                     B := _i - 2 _j + 4 _k

                               -8

                       A[mu] := 2, 3, -1

                       B[mu] := 1, -2, 4

               Physics:-g_[mu, nu] A[~mu] B[~nu]

 

A := [1,2];
type(A, Vector);          # false

B := Vector([1,2]);
type(B, Vector);          # true

C := <1,2>;
type(C, Vector);          # true

 Jean-Michel 70
Try describing what you're looking for, but it gets tricky when your brain isn't working at its best.

@acer 
Thanks , the cube with ribs do it better.
Note: I wonder what's always wrong with this MaplePrimes website, i could not upload the code ? : has it its own server ?, i think so, because you can run only one url  per server ?

Further the transformation code for the rotation is hidden , so it answering not the initial question.

 

 

 

 

restart;
P := proc(phi)
local Cube, c, V, axes_lines, x_label, y_label, z_label;
uses plots, plottools;

    # Wireframe cube (only lines)
    Cube := cuboid([-1,-1,-1], [1,1,1], style=line, color=black, thickness=2);

    # Draw the coordinate axes ourselves (arrows from -3.5 to 3.5)
    axes_lines :=
        arrow([-3.5,0,0], [3.5,0,0], color=blue, width=0.05, thickness=1),  # x-axis
        arrow([0,-3.5,0], [0,3.5,0], color=blue, width=0.05, thickness=1),  # y-axis
        arrow([0,0,-3.5], [0,0,3.5], color=blue, width=0.05, thickness=1);  # z-axis

    # Labels at the ends of the axes
    x_label := textplot3d([3.7, 0, 0, "x"], font=[Times,bold,20], color=blue);
    y_label := textplot3d([0, 3.7, 0, "y"], font=[Times,bold,20], color=blue);
    z_label := textplot3d([0, 0, 3.7, "z"], font=[Times,bold,20], color=blue);

    # Rotation axis along the x-axis (red arrow)
    c := [-2,0,0], [2,0,0];
    V := arrow([c], color=red, width=0.1, thickness=2);

    # Combine everything and rotate
    display(
        rotate(Cube, phi, [c]),
        axes_lines,
        x_label, y_label, z_label,
        V,
        axes=none,                    # turn off default axes
        scaling=constrained,
        orientation=[40,80],
        view=[-3.7..3.7, -3.7..3.7, -3.7..3.7]
    );
end proc:

plots:-animate(P, [phi], phi=0..2*Pi, frames=90, size=[800,800]);

 

 


 

Download kubus_via_plottottools_met_ribben_DEF_2-4-2026.mw

 




 

@Kitonum 
Which rotation is the cube performing now?

@sand15 

with(Student[LinearAlgebra]):

# Rotation matrix for Euler angles (Z-X-Z) with angles psi, theta, phi
R := RotationMatrix(psi, theta, phi, 'Euler');

Spacefilling curve for a cube with  rotation around x-axis seems to be not possible?

1 2 3 4 5 6 7 Last Page 1 of 85