7. Nonhomogeneous equations: undetermined coefficients and variation of parameters
§13.5 solved ay''+by'+cy=0 completely. This lesson handles the case with a nonzero right side — ay''+by'+cy=g(x) — a nonhomogeneous equation, using two complementary techniques: a quick pattern-matching guess for well-behaved forcing terms, and a fully general fallback method that works no matter how ugly g(x) gets.
The structure of the general solution
If y_h is the general solution to the homogeneous equation ay''+by'+cy=0 (§13.5), and y_p is any one particular solution to ay''+by'+cy=g(x), then the general solution to the nonhomogeneous equation is y=y_h+y_p
Why this works: if L[y]=ay''+by'+cy denotes the left side (a linear operator), then L is additive: L[y_h+y_p]=L[y_h]+L[y_p]=0+g(x)=g(x) — so y_h+y_p solves the full equation. Conversely, any two solutions to the nonhomogeneous equation differ by a solution of the homogeneous equation (subtract them: L[y_1-y_2]=g-g=0), which is exactly why y_h's full two-constant family needs to be added, not just a single homogeneous solution.
The entire problem reduces to finding just one particular solution y_p — everything else is already solved by §13.5.
Undetermined coefficients
For g(x) built from polynomials, exponentials, sines, and cosines (or products of these), guess a particular solution with the same "shape" as g(x), carrying unknown coefficients, then substitute into the equation and solve for those coefficients directly.
| g(x) | Guess for y_p |
|---|---|
| polynomial of degree n | polynomial of degree n |
| e^{kx} | Ae^{kx} |
| \sin(kx) or \cos(kx) | A\cos(kx)+B\sin(kx) (both, even if only one appears in g) |
One caveat: if the guessed form already appears in y_h (the homogeneous solution), it must be multiplied by x (or x^2, if needed again) before substituting — otherwise the guess solves the homogeneous equation and can never match a nonzero g(x) no matter what coefficient is chosen. This situation is called resonance, and it's exactly the same phenomenon behind a physical system driven at its own natural frequency.
Variation of parameters
When g(x) doesn't fit the table — \tan x, \frac1x, or anything without a clean derivative pattern — undetermined coefficients has nothing to guess. Variation of parameters always works instead: given the two independent homogeneous solutions y_1,y_2 from §13.5, seek y_p=u_1(x)y_1+u_2(x)y_2 where u_1,u_2 are now functions, not constants (replacing y_h's constants with functions is exactly the "variation" the method is named for). Solving the resulting system gives:
u_1'=\frac{-y_2\,g(x)}W,\qquad u_2'=\frac{y_1\,g(x)}W,\qquad W=y_1y_2'-y_2y_1'
where W is the Wronskian of y_1,y_2 — a determinant construction directly parallel to §11.5's Jacobian, here testing whether y_1,y_2 are genuinely independent solutions rather than measuring area distortion. Integrating u_1',u_2' and substituting back recovers y_p. This method is strictly more general than undetermined coefficients — it handles every case the table does, plus every case it doesn't — at the cost of needing two integrations instead of algebra.
Doing it in Python
Solving y''-3y'+2y=e^{3x} with undetermined coefficients — a guess of Ae^{3x} is safe here, since e^{3x} doesn't appear in the homogeneous solution (e^x and e^{2x}, from §13.5's own worked example):
import sympy as sp
x, A = sp.symbols('x A')
y_p_guess = A * sp.exp(3*x)
y_p_prime = sp.diff(y_p_guess, x)
y_p_double_prime = sp.diff(y_p_guess, x, 2)
lhs = y_p_double_prime - 3*y_p_prime + 2*y_p_guess
lhs_simplified = sp.simplify(lhs)
print(f"substituting the guess: {lhs_simplified} = exp(3x)")
A_value = sp.solve(sp.Eq(lhs_simplified, sp.exp(3*x)), A)
print(f"A = {A_value}")
y_p = y_p_guess.subs(A, A_value[0])
C1, C2 = sp.symbols('C1 C2')
y_general = C1*sp.exp(x) + C2*sp.exp(2*x) + y_p
print(f"general solution: y = {y_general}")
Confirming the full solution with SymPy's built-in solver:
import sympy as sp
x = sp.Symbol('x')
y = sp.Function('y')
ode = sp.Eq(y(x).diff(x, 2) - 3*y(x).diff(x) + 2*y(x), sp.exp(3*x))
solution = sp.dsolve(ode, y(x))
print(f"sympy's solution: {solution}")
Using variation of parameters (via SymPy, since the by-hand integration gets long) for y''+y=\tan x — a forcing term with no entry in the undetermined-coefficients table at all:
import sympy as sp
x = sp.Symbol('x')
y = sp.Function('y')
ode = sp.Eq(y(x).diff(x, 2) + y(x), sp.tan(x))
solution = sp.dsolve(ode, y(x))
print(f"solution: {solution}")
print("tan(x) has no polynomial/exponential/trig 'shape' to guess --")
print("undetermined coefficients cannot be applied here at all")
Worked example
Solve y''-3y'+2y=e^{3x}.
Homogeneous solution (from §13.5's own worked example, same left side): y_h=C_1e^x+C_2e^{2x}.
Particular solution: guess y_p=Ae^{3x} (safe, since e^{3x} matches neither e^x nor e^{2x} — no resonance).
y_p'=3Ae^{3x},\qquad y_p''=9Ae^{3x}
y_p''-3y_p'+2y_p=9Ae^{3x}-9Ae^{3x}+2Ae^{3x}=2Ae^{3x}
Set equal to e^{3x}: 2A=1\Rightarrow A=\frac12.
y_p=\frac12e^{3x}
General solution:
\boxed{y=C_1e^x+C_2e^{2x}+\frac12e^{3x}}
Sanity check. Differentiate and substitute the full expression back into the original equation — the C_1e^x and C_2e^{2x} terms contribute exactly 0 (they solve the homogeneous equation by construction, from §13.5), leaving only the \frac12e^{3x} term's contribution, which was solved to equal e^{3x} exactly by design. ✓ The coefficient \frac12 being a clean fraction (rather than something messier) is a mild but reassuring sign the algebra went through cleanly.
Your turn
1. Find a particular solution to y''-y=x (guess a linear polynomial, y_p=Ax+B).
2. Explain why y_p=Ae^x would fail as a guess for y''-3y'+2y=e^x (recall the homogeneous solutions from the worked example), and state what the corrected guess should be instead.
3. True or false: variation of parameters can be used even when undetermined coefficients also applies.
Solutions
1. y_p=Ax+B\Rightarrow y_p'=A, y_p''=0.
y_p''-y_p=0-(Ax+B)=-Ax-B
Set equal to x: -A=1\Rightarrow A=-1; -B=0\Rightarrow B=0.
\boxed{y_p=-x}
(Check: y_p''-y_p=0-(-x)=x ✓.)
2. From the worked example, the homogeneous solutions are e^x and e^{2x}. Since e^x already appears in y_h, guessing y_p=Ae^x would substitute into the left side and give exactly 0 (because e^x solves the homogeneous equation), which can never equal the nonzero right side e^x for any choice of A — this is resonance. The corrected guess, per the concept section's caveat, is \boxed{y_p=Axe^x} — multiplying by x to break the overlap with y_h.
3. True. Variation of parameters is the fully general method — it never fails to apply, it's simply more work than undetermined coefficients when the shortcut table happens to cover the specific g(x) in question. Whenever undetermined coefficients works, variation of parameters would (eventually, after more integration) arrive at the identical particular solution; the two methods are not mutually exclusive alternatives so much as a fast path and a universal fallback.
Check yourself in code
Solve y''-3y'+2y=e^{3x} using undetermined coefficients: find A and the general solution.
Print exactly this:
A = [1/2]
general solution: y = C1*exp(x) + C2*exp(2*x) + exp(3*x)/2
import sympy as sp
x, A = sp.symbols('x A')
y_p_guess = A * sp.exp(3*x)
lhs = sp.diff(y_p_guess, x, 2) - 3*sp.diff(y_p_guess, x) + 2*y_p_guess
lhs_simplified = sp.simplify(lhs)
A_value = sp.solve(sp.Eq(lhs_simplified, sp.exp(3*x)), A)
print("A = ...")
y_p = y_p_guess.subs(A, A_value[0])
C1, C2 = sp.symbols('C1 C2')
y_general = C1*sp.exp(x) + C2*sp.exp(2*x) + y_p
print("general solution: y = ...")
import sympy as sp
x, A = sp.symbols('x A')
y_p_guess = A * sp.exp(3*x)
lhs = sp.diff(y_p_guess, x, 2) - 3*sp.diff(y_p_guess, x) + 2*y_p_guess
lhs_simplified = sp.simplify(lhs)
A_value = sp.solve(sp.Eq(lhs_simplified, sp.exp(3*x)), A)
print(f"A = {A_value}")
y_p = y_p_guess.subs(A, A_value[0])
C1, C2 = sp.symbols('C1 C2')
y_general = C1*sp.exp(x) + C2*sp.exp(2*x) + y_p
print(f"general solution: y = {y_general}")
A nonhomogeneous equation's general solution is y_h+y_p — §13.5's full homogeneous family plus any single particular solution — so the entire new problem is finding one y_p. Undetermined coefficients guesses a form matching g(x)'s shape and solves for its coefficients directly (watching for resonance, when the guess overlaps y_h and needs an extra factor of x), while variation of parameters, built on the Wronskian, handles any g(x) at all, at the cost of two integrations instead of algebra.
Next: solving differential equations by an entirely different route — representing the unknown function as a power series (Module 8's machinery) and matching coefficients term by term.