Induction: magnetic flux and the electromotive force
The voltage induced around a loop computed as the work per charge along the wire, and the magnetic flux through it computed as a surface integral, apart: for a loop moving through a non-uniform field, a turning coil, and a loop at rest beside a changing field, the voltage is minus the rate of change of the flux.
With scripts, this page keeps a record in your browser of whether you completed the lesson. Nothing is stored without them.
With scripts, this place suggests what to do next, with the reason, from the progress saved in your browser. Without them, follow the learning path.
Move a magnet in and out of a coil of wire and a current flows in the wire, though no battery is connected. A bicycle dynamo lights its lamp the same way, and so does every generator of a power station: a coil turns in a magnetic field, and a voltage appears between its ends. A transformer does it with nothing moving at all, by changing the field through a coil.
Faraday found the rule that covers all of these: the voltage around a loop, its electromotive force, is minus the rate at which the magnetic flux through the loop changes. This lesson does not assume the rule. It computes the voltage from the force on the charges in the wire, the Lorentz force of the previous lesson and the induced electric field, integrated around the loop. It computes the flux, separately, by integrating the field over the surface the loop bounds, and differentiates it in time. Then it asks whether the two agree, for a loop that slides through a field that is not uniform, for a coil that turns, and for a loop at rest beside a field that grows. The surprises are in the last case: a loop can have a voltage where the field on its wire is nearly zero, and none where the electric field on it is strong.
Assumptions
Thin wire, flat loops. The loop is a curve without thickness, the edge of a flat rectangle. A real coil has a thickness and many turns; for a coil of several turns the voltage is the sum over the turns.
No current, or a current too small to matter. The voltage is computed for an open loop, or one with a very large resistance. A current in the loop would make a field of its own that opposes the change, which is the content of Lenz’s rule, and changes the flux.
Slow compared with light. The wire moves far slower than light, and the fields change slowly enough that the time light takes to cross the loop does not matter. Then the force per charge on a charge moving with the wire is , with the velocity of the wire there.
Given fields. The magnetic and the induced electric field are given in closed form, not computed from currents. The flux tube of the third example is a model of the field inside and near a long coil, with smooth edges so that its integrals are accurate.
Quadrature and a difference. The integrals are Gauss-Legendre rules, accurate for smooth fields; the rate of change of the flux is a central difference, whose error falls as the square of its step.
Faraday’s law
The electromotive force and the flux
A charge carried along by the wire at the velocity feels the force . The electromotive force of the loop is the work this force does per unit charge on one trip around it,
and it is the voltage a meter would read across a small gap in the loop. The flux is the integral of the magnetic field over the surface that the loop bounds, with the normal that the sense of the loop picks by the right-hand rule:
Faraday’s law, in the form called the flux rule, says
Why it holds: two ways for the flux to change
The flux through a loop changes for two reasons, and each corresponds to one of the two terms of the force.
The loop moves. In a static field a moving loop sweeps out a strip with each piece of its edge, of area per time . A magnetic field has no sources, , so the flux that the loop gains is the flux through those strips,
the motional term. For a rectangle of height moving at along through a field , only the two sides across the motion count, and .
The field changes. A magnetic field that changes in time comes with an electric field that circulates around it: the Maxwell-Faraday equation , which by Stokes’s theorem gives for a loop at rest. In terms of the potentials, and the induced field is .
Neither statement is used to compute anything below. The program integrates the force along the wire and the field over the surface with separate rules, and differentiates the flux numerically; the law is what the comparison tests.
The flux tube
The third example uses a tube of field along , strongest on its axis and falling off with the distance from it over a width , , a smooth model of the field inside a long coil. Its vector potential points around the axis,
and gives the field by . When grows at the rate , the induced electric field is , the same expression with in place of and a minus sign. Outside the tube the magnetic field is nearly zero, yet the electric field falls only as : a loop far from the tube still sits in an induced field.
Code
The loop is a Rectangle; flux integrates the field over it, and emf integrates the force per charge around its edge. The two do not call each other. flux_rate is the central difference of the flux in time.
def emf( loop: Rectangle,*, electric: VectorField |None=None, magnetic: VectorField |None=None, velocity: VectorField |None=None, nodes: int=24,) ->float:"""The EMF around ``loop`` in its sense, in V: the line integral of the force per unit charge E + u x B on a charge carried by the wire, where ``velocity`` gives the velocity u (m/s) of the wire at each of its points. A field that is not given is zero; a wire at rest feels only E. """ points, elements = loop.edge(nodes) force = np.zeros_like(points)if electric isnotNone: force += electric(points)if magnetic isnotNoneand velocity isnotNone: force += np.cross(velocity(points), magnetic(points))returnfloat(np.sum(force * elements))
def flux(magnetic: VectorField, loop: Rectangle, *, nodes: int=24) ->float:"""The flux of ``magnetic`` (a function of the points) through ``loop`` along its normal, by Gauss-Legendre in both directions: in Wb.""" points, weights = loop.surface(nodes)returnfloat(np.sum(weights * (magnetic(points) @ loop.normal)))
def flux_tube_fields( points: ArrayLike, *, strength: float, rate: float, width: float) ->tuple[Array, Array]:"""The induced electric field and the magnetic field (E, B) of a tube of flux along z: B = B0 exp(-r^2 / a^2) z, with B0 = ``strength`` (T) changing at ``rate`` (T/s) and a = ``width`` (m). Both come from the vector potential A = B0 a^2 (1 - exp(-r^2/a^2)) / (2 r) along phi: B = curl A, and the induced field E = -dA/dt, which is -rate a^2 (1 - exp(-r^2/a^2)) / (2 r) along phi. Neither uses Faraday's law. """ points = np.asarray(points, dtype=float) x, y = points[..., 0], points[..., 1] r2 = x**2+ y**2 profile = np.exp(-r2 / width**2)# (1 - exp(-r^2/a^2)) / r^2, which tends to 1/a^2 on the axis safe = np.where(r2 >0.0, r2, 1.0) ratio = np.where(r2 >0.0, -np.expm1(-r2 / width**2) / safe, 1.0/ width**2)# E_phi phi = E_phi / r (-y, x, 0) e_over_r =-0.5* rate * width**2* ratio electric = np.stack([-e_over_r * y, e_over_r * x, np.zeros_like(x)], axis=-1) magnetic = np.stack( [np.zeros_like(x), np.zeros_like(x), strength * profile], axis=-1 )return electric, magnetic
A field along has the profile of a bump in : 0.5 T at its peak, falling off over 5 cm. A rectangular loop of 4 cm along by 6 cm along moves through it at 2 m/s, centred on the peak at the time zero. The EMF is computed from along the wire and compared with minus the rate of change of the flux, with a step of 10 μs, at times across the passage.
PEAK =0.5# TBUMP =0.05# mSPEED =2.0# m/sWIDTH, HEIGHT =0.04, 0.06# mSTEP =1e-5# s, the step of the central differencetimes = np.linspace(-0.06, 0.06, 241) # sFARADAY_TOLERANCE =1e-6# a chosen tolerance, relative to the largest EMF
def moving_loop_run(experiment: Experiment) -> Passage:"""The EMF of the moving loop from u x B along the wire against minus the rate of its flux; record the table of a few times.""" carried = uniform([SPEED, 0.0, 0.0]) fluxes = np.array([flux(bump, loop_at(t)) for t in times]) motional = np.array( [emf(loop_at(t), magnetic=bump, velocity=carried) for t in times] ) from_flux = np.array( [-flux_rate(lambda s: flux(bump, loop_at(s)), t, STEP) for t in times] ) gap =float(np.max(np.abs(motional - from_flux)) / np.max(np.abs(motional)))assert gap < FARADAY_TOLERANCE, "the motional EMF is not -dPhi/dt" shown = [0,60,100,140,180,240, ] # the time zero, where both are zero, is left out experiment.table("moving-loop-run", [ (times[i] *1e3, fluxes[i] *1e3, motional[i] *1e3, from_flux[i] *1e3)for i in shown ], [ ("time", "ms", ".1f"), ("flux", "mWb", ".5f"), ("EMF along the wire", "mV", ".5f"), ("minus the rate of the flux", "mV", ".5f"), ],"The flux through the moving loop, its EMF from the force on the charges ""of the wire, and minus the rate of change of the flux, at a few of the ""computed times, to five decimals.", )return Passage(fluxes, motional, from_flux, gap)
The flux through the moving loop, its EMF from the force on the charges of the wire, and minus the rate of change of the flux, at a few of the computed times, to five decimals.
time (ms)
flux (mWb)
EMF along the wire (mV)
minus the rate of the flux (mV)
-60.0
0.00612
-1.07532
-1.07532
-30.0
0.31139
-26.99926
-26.99926
-10.0
0.98650
-28.36245
-28.36245
10.0
0.98650
28.36245
28.36245
30.0
0.31139
26.99926
26.99926
60.0
0.00612
1.07532
1.07532
def draw_moving_loop(passage: Passage) -> Figure:"""The flux through the passing loop, and its EMF computed both ways.""" fig, (top, bottom) = plt.subplots(2, 1, figsize=(6.4, 4.6), sharex=True) top.plot(times *1e3, passage.fluxes *1e3, color=FIGURE_COLOURS[0]) top.set_ylabel("flux (mWb)") bottom.plot( times *1e3, passage.motional *1e3, color=FIGURE_COLOURS[0], label="EMF along the wire", ) bottom.plot( times[::8] *1e3, passage.from_flux[::8] *1e3,"o", markerfacecolor="none", color=FIGURE_COLOURS[1], label="minus the rate of the flux", ) bottom.axhline(0.0, color=FIGURE_COLOURS[2], linewidth=0.6) bottom.set_xlabel("time (ms)") bottom.set_ylabel("EMF (mV)") bottom.legend(fontsize=8)return fig
Figure 1: simulated A loop passing through a bump of field. Top: the flux through it rises and falls. Bottom: the EMF from the force on the charges of the wire (line) and minus the rate of change of the flux (markers) are one curve, negative while the flux grows and positive while it falls.
Numerically verified (a rigid rectangular loop translated through a static field, a central difference of the stated step): The EMF of a loop moving through a static, non-uniform magnetic field, computed from the force on the charges of the wire, equals minus the rate of change of the flux through the loop. At every one of the 241 times the two agree to 1.1e-07 of the largest EMF, inside the chosen tolerance of 1e-06; what remains is the error of the central difference. The sign is Lenz’s: while the loop enters the field and its flux grows, the EMF is negative, in the sense that would drive a current whose own field opposes the growth. At the time zero the loop is centred on the peak, the flux is largest, and the two sides across the motion sit in equal fields, so the EMF is zero. The data are simulated, and the check is the flux rule.
A coil turning in a uniform field
A coil of 10 cm by 20 cm turns at 50 Hz about its long axis in a uniform field of 0.3 T across the axis: a generator of a single turn. Each point of the wire moves with the velocity . The EMF from the force along the wire is compared over one turn with minus the rate of the flux and with .
def coil_run(experiment: Experiment) ->tuple[float, float]:"""The EMF of the turning coil along the wire against minus the rate of its flux and against B A omega sin(omega t); record the table, return the largest gap and the peak.""" area = COIL["width"] * COIL["height"] spin = np.array([0.0, 0.0, OMEGA])def turning(points):return np.cross(spin, points) coil_emf = np.array( [ emf(rotating_coil(t, **COIL), magnetic=uniform(FIELD), velocity=turning)for t in turn_times ] ) coil_from_flux = np.array( [-flux_rate(lambda s: flux(uniform(FIELD), rotating_coil(s, **COIL)), t, 1e-7 )for t in turn_times ] ) generator = FIELD[0] * area * OMEGA * np.sin(OMEGA * turn_times) peak = FIELD[0] * area * OMEGA coil_gap =float(np.max(np.abs(coil_emf - coil_from_flux)) / peak) formula_gap =float(np.max(np.abs(coil_emf - generator)) / peak) gap =max(coil_gap, formula_gap)assert gap < FARADAY_TOLERANCE, "the coil is not a generator" experiment.table("coil-run", [ ("EMF along the wire", np.max(coil_emf), np.min(coil_emf)), ("minus the rate of the flux", np.max(coil_from_flux), np.min(coil_from_flux), ), ("B A ω sin ωt", peak, -peak), ], [("computed as", "", ""), ("largest", "V", ".5f"), ("smallest", "V", ".5f")],"The largest and smallest EMF of the turning coil over one turn, from the ""force along the wire, from the rate of the flux, and from the generator ""formula, to five decimals.", )return gap, peak
The largest and smallest EMF of the turning coil over one turn, from the force along the wire, from the rate of the flux, and from the generator formula, to five decimals.
computed as
largest (V)
smallest (V)
EMF along the wire
1.88496
-1.88496
minus the rate of the flux
1.88496
-1.88496
B A ω sin ωt
1.88496
-1.88496
Numerically verified (a flat rectangular coil of one turn, a uniform field across its axis, one turn): The EMF of a coil turning in a uniform field, computed from the force on the charges of the moving wire, equals minus the rate of change of its flux and follows . The three agree over the whole turn to 1.8e-10 of the peak of 1.8850 V. The flux is largest when the coil faces the field, and then the EMF is zero: the sides of the coil move along the field, and vanishes. The EMF is largest a quarter of a turn later, when the coil is edge-on to the field, its flux is zero, and the flux changes fastest. A coil of many turns multiplies this by the number of turns, which is how a small generator reaches a useful voltage.
A loop at rest beside a changing field
A tube of field of 2 cm width along grows at 10 T/s. Three square loops lie at rest in the plane across it: one around the tube, one beside it, and one across its edge. Their EMF is the line integral of the induced electric field alone, and is compared with minus the rate of change of their flux.
def tube_run(experiment: Experiment) ->list[tuple[str, float, float, float]]:"""For each loop at rest, the line integral of the induced field against minus the rate of its flux, and the strongest induced field on its wire; record the table, return its rows.""" rows = []for name, loop in loops.items(): induced = emf(loop, electric=tube_electric, nodes=48) change = flux_rate(lambda t, loop=loop: flux(tube_magnetic_at(t), loop, nodes=48), 0.0, 1e-3 ) points, _ = loop.edge(48) strongest =float(np.max(np.linalg.norm(tube_electric(points), axis=-1)))assertabs(induced + change) <= FARADAY_TOLERANCE *abs(RATE * np.pi * TUBE**2) rows.append((name, induced *1e3, -change *1e3, strongest *1e3)) experiment.table("tube-run", rows, [ ("loop", "", ""), ("EMF along the wire", "mV", ".5f"), ("minus the rate of the flux", "mV", ".5f"), ("strongest induced field on the wire", "mV/m", ".2f"), ],"For three loops at rest near a growing tube of field: the EMF from the ""induced electric field along the wire, minus the rate of change of the ""flux through the loop, and the strongest induced field on the wire, to ""the stated decimals.", )return rows
For three loops at rest near a growing tube of field: the EMF from the induced electric field along the wire, minus the rate of change of the flux through the loop, and the strongest induced field on the wire, to the stated decimals.
Figure 2: simulated The induced electric field (arrows) circulates around a growing tube of magnetic field (shaded), and is still strong where the magnetic field has fallen to nothing. The three loops of the table: the large one encloses the tube, the small one beside it encloses almost none of its flux, and the third, off centre, cuts through the tube.
Numerically verified (square loops at rest near a smooth tube of field that grows at a constant rate, induced field from the vector potential): For a loop at rest in a changing magnetic field, the line integral of the induced electric field around the loop equals minus the rate of change of the flux through it, for a loop around the field, beside it, and across its edge. In each row the EMF and minus the rate of the flux agree, to the chosen tolerance of 1e-06 of the rate of the whole flux of the tube, 12.5664 mV. The loop around the tube picks up nearly all of that, though on its wire the magnetic field is practically zero: the EMF counts the flux inside, not the field on the wire. The loop beside the tube sits in an induced field nearly as strong as on the others, as the last column shows, yet its EMF is 0.16 per cent of the first one’s, the share of the flux of the tube that leaks into it. The field pushes the charges forward on one side of that loop and back on the other. The data are simulated, and the check is the flux rule.
Limits
No current. The loops are open, or have no resistance to speak of. A current would add a field of its own, opposing the change, and for a superconducting loop it would keep the flux constant. The lesson computes the EMF, not the current.
Rigid loops. The examples move a loop without changing its shape. A loop that stretches, a sliding bar on rails, follows the same rule, as the first exercise shows; a loop whose material is not a single wire, such as a disc that turns, is where the flux rule needs care.
Given fields, slow changes. The fields are prescribed in closed form. When they change fast enough for light to take a noticeable fraction of a period to cross the loop, the fields become waves, and this description with a single time is no longer exact.
Smooth fields. The field of a real coil drops sharply at its wall, and a quadrature across that wall would converge slowly; the tube of the third example is smooth on purpose.
Self-check. A long coil carries a current that grows, so the field inside it grows. A wire loop goes around the coil, far outside it, where the magnetic field is practically zero. Is there an EMF around the loop?
No. The wire is where the magnetic field is zero, so nothing acts on its charges.
The magnetic field on the wire is nearly zero, but the induced electric field is not: it circulates around the coil and falls only slowly with the distance. That field pushes the charges along the wire.
Yes. The EMF is minus the rate of change of the flux inside the loop, and the loop encloses the growing flux of the coil.
Correct: the loop around the tube in the third example shows it. The force on the charges is the induced electric field, which is there even where the magnetic field is not.
Only if the loop moves, since there is no on a wire at rest.
A loop at rest feels the induced electric field. The motional term is one of two ways for the flux to change, not the only one.
Solution to the self-check
Yes. The flux through the loop is the flux of the coil, and it grows, so the EMF is minus its rate of change, whatever the size or the shape of the loop as long as it goes around the coil once. What pushes the charges is the induced electric field, which circulates around the coil and reaches the wire though the magnetic field there is practically zero.
Exercises
Exercise 1.A bar sliding on rails. Two rails 10 cm apart lie in a uniform field of 0.2 T at right angles to their plane. A bar slides along them at 3 m/s and closes the loop. Compute the EMF from the force on the charges of the moving bar, and compare it with minus the rate of the flux through the growing loop and with .
Hint 1 of 1 for exercise 1
Only the bar moves. The flux is the field times an area that grows by the gap times the speed per unit time.
Solution to exercise 1
def sliding_bar() ->tuple[float, float, float]:"""Exercise 1: the EMF of a bar sliding on rails, from the force on its charges, from minus the rate of the flux, and B L v.""" b_rails = np.array([0.0, 0.0, 0.2]) gap, bar_speed, start =0.1, 3.0, 0.5def rails(t):return Rectangle( [0.0, 0.0, 0.0], [start + bar_speed * t, 0.0, 0.0], [0.0, gap, 0.0] )def bar_only(points):# the bar is the side at the far end; the rest of the loop is at rest moving = np.isclose(points[..., 0], start)return np.where(moving[..., None], [bar_speed, 0.0, 0.0], 0.0) bar_emf = emf(rails(0.0), magnetic=uniform(b_rails), velocity=bar_only) rails_rate =-flux_rate(lambda t: flux(uniform(b_rails), rails(t)), 0.0, 1e-4) blv = b_rails[2] * gap * bar_speedreturn bar_emf, rails_rate, blv
The force on the charges of the bar gives -60.0000 mV, minus the rate of the flux -60.0000 mV, and is 60.0000 mV in size. The sign is negative because the loop runs counterclockwise about the field and its flux grows: a current would flow clockwise, and the field of that current would oppose the growth.
Exercise 2.A generator of many turns. A coil of 200 turns of 5 cm by 8 cm turns at 25 Hz in a field of 0.1 T. What is the peak voltage between its ends?
Hint 1 of 1 for exercise 2
Each turn has the EMF of the second example, and the turns are in series.
Solution to exercise 2
def many_turns() ->tuple[float, float]:"""Exercise 2: the peak EMF of one turn of the coil of 5 cm by 8 cm at 25 Hz in 0.1 T, and of 200 turns in series.""" one_turn =dict(angular_velocity=2* np.pi *25.0, width=0.05, height=0.08) quarter =0.25/25.0# a quarter of a turn, when the EMF is largest single = emf( rotating_coil(quarter, **one_turn), magnetic=uniform([0.1, 0.0, 0.0]), velocity=lambda p: np.cross([0.0, 0.0, one_turn["angular_velocity"]], p), )return single, 200* single
One turn gives 0.0628 V at its peak, a quarter of a turn after it faces the field, so the coil gives 12.566 V, the formula .
Exercise 3.How wide is beside? Move the loop beside the tube of the third example further out, in steps of 1 cm, and compute its EMF. How does it fall, and why does the induced field on the wire fall more slowly?
Hint 1 of 1 for exercise 3
Compare the flux of the tube that reaches the loop with the strength of the induced field at its distance.
Solution to exercise 3
def further_out(experiment: Experiment) ->tuple[list[float], list[float]]:"""Exercise 3: the EMF, the rate of the flux, and the strongest induced field of the square beside the tube, moved out in steps of 1 cm; record the table, return the EMFs and the fields.""" offsets = np.arange(0.04, 0.09, 0.01) beside_emf = [] beside_rate = [] beside_field = []for x0 in offsets: square = Rectangle([x0, -0.02, 0.0], [0.03, 0.0, 0.0], [0.0, 0.03, 0.0]) beside_emf.append(abs(emf(square, electric=tube_electric, nodes=48))) beside_rate.append(abs( flux_rate(lambda t, square=square: flux( tube_magnetic_at(t), square, nodes=48 ),0.0,1e-3, ) ) ) points, _ = square.edge(48) beside_field.append(float(np.max(np.linalg.norm(tube_electric(points), axis=-1))) ) experiment.table("further-out", [ (x0 *100, e *1e3, r *1e3, f *1e3)for x0, e, r, f inzip( offsets, beside_emf, beside_rate, beside_field, strict=True ) ], [ ("near side at", "cm", ".0f"), ("size of the EMF", "mV", ".2e"), ("size of the rate of the flux", "mV", ".2e"), ("strongest field on the wire", "mV/m", ".2f"), ],"The size of the EMF of the small square beside the growing tube, the ""size of the rate of change of its flux, and the strongest induced field ""on its wire, for each distance of its near side from the axis, to three ""significant digits.", )return beside_emf, beside_field
The size of the EMF of the small square beside the growing tube, the size of the rate of change of its flux, and the strongest induced field on its wire, for each distance of its near side from the axis, to three significant digits.
near side at (cm)
size of the EMF (mV)
size of the rate of the flux (mV)
strongest field on the wire (mV/m)
4
2.00e-02
2.00e-02
49.08
5
1.74e-03
1.74e-03
39.92
6
9.46e-05
9.46e-05
33.33
7
3.18e-06
3.18e-06
28.57
8
6.60e-08
6.60e-08
25.00
The EMF and the rate of the flux agree in every row, and fall by orders of magnitude, from 2.0e-02 mV to 6.6e-08 mV, as fast as the tail of the field of the tube that still reaches the square. The induced field on the wire falls only as the inverse of the distance, from 49.1 to 25.0 mV/m. The field on the wire is strong, but around a loop that encloses almost no flux it pushes the charges forward on one side as much as it holds them back on the other.
The experiment writes every figure of this page into results/, as <label>.png, and every number and table of the page, as the page shows it, into results/results.json. Its numbers match this page to the digits shown, and its figure files are the ones the page shows; digits beyond those can differ between machines, because floating-point libraries differ. Change the code of the experiment and run it again to see what changes.