Using Math to Predict Cycling Performance
By Tom Norton
April 10th, 2026

On the 4th of July this year, I'm doing the bike leg of a relay sprint triathlon at the Geneva Triathlon. Looking at last year's results, third place on the bike split was tantalisingly close to what I reckoned I could do in 'peak' shape. So, in a bid to add a dose of reality to my hubris, I figured it would be appropriate to more accurately answer the following questions: Knowing the course ahead of time, what power do I actually need to hold on which parts of the course to beat that time, and thus, is it actually possible?
Turns out this isn't a simple calculation. The course has a climb at the start, a long flat section, some rolling terrain, and a couple of moderate descents. How hard you push on the climb versus the flat changes your total time in non-obvious ways. And it all depends on your weight, your bike, your aerodynamic position, the wind, and a dozen other variables.
I couldn't find a free tool that let me upload the GPX, tweak all the physics parameters, and instantly see what happens when I change my power on different sections. The closest thing is Best Bike Split. It's a paid SaaS at around $19/month, and the free tier doesn't give you course-specific pacing. So I built one.
The Problem with "Eyeballing It"
It's not so hard for an experienced cyclist to estimate individual sections and the power they can/should hold on them. But when you add it all up, the interactions become complex. For example, if I push 20 watts harder on the climb, I might save 30 seconds there, but that extra effort could cost me 30 seconds on the flat later due to fatigue. Or, if I hold back on the climb to save energy for the flat, I might lose more time on the climb than I gain on the flat. The combinations quickly grow beyond what (at least speaking for my limited self) can fit in one's head.
The only way to know for sure is to model the entire course with all the physics involved.
How the math works
The fundamental cycling power equation is well-known. Your power output has to overcome four forces: aerodynamic drag, rolling resistance, gravity, and drivetrain friction. At a given power, on a given gradient, there's exactly one steady-state speed that balances the equation.
At steady state, the power equation looks like this:
P_effective = P_aero + P_rolling + P_gravity
Where:
P_effective = P_rider × (1 - drivetrain_loss) P_aero = 0.5 × CdA × air_density × v_air² × v_ground P_rolling = Crr × m × g × v_ground P_gravity = m × g × sin(slope) × v_ground
- P_rider is your pedalling power (watts)
- CdA is your drag coefficient times frontal area (m²) — this is your aerodynamic "signature"
- v_air is your speed relative to the air (ground speed + headwind)
- Crr is the rolling resistance coefficient of your tyres
- m is the total mass of you + bike + kit (kg)
- g is gravity (9.81 m/s²)
- sin(slope) is derived from the road gradient
The key insight: v_air appears as a squared term inside P_aero, but it also depends on v_ground, which is what we're solving for. This makes the equation implicit — speed is on both sides. You can't isolate it algebraically.
Instead, the calculator uses Newton-Raphson iteration to find the speed where power in equals power out. Starting from an initial guess, it iteratively refines:
v_next = v - f(v) / f'(v)
Where f(v) = P_total(v) - P_effective is the power residual at speed v, and f'(v) is its derivative. Within 10-20 iterations, this converges to a solution accurate to 0.001 watts.
By hand? Miserable. In a spreadsheet? Possible but fragile. Being the incidentally lazy person that I am, I wanted a tool where i can just drag sliders around after uploading the GPX, and see the results.
How It Works
The calculator does a few things:
1. GPX Parsing & Gradient-Aware Splitting
When you upload a GPX file, it extracts the lat/lon/elevation data, smooths the elevation to reduce GPS noise, then splits the route into sections based on actual terrain changes, not equal distances. This is important. If you split a route into 8 equal chunks, a 7% climb that happens to start halfway through a chunk gets averaged with the surrounding flat into a meaningless "3.5%" section. The gradient-aware algorithm detects where the terrain actually changes and creates sections that reflect reality. This was actually the tricky bit to get right - how should I split a given elevation profile into sections that are "flat enough" vs "climby enough"? I ended up with a heuristic that looks for sustained gradient changes above a certain threshold, while also enforcing a minimum section length to avoid over-splitting.
2. Physics Simulation
For each section, given your power, weight, CdA (aerodynamic drag), rolling resistance, and conditions, the Newton-Raphson solver finds the speed. Distance divided by speed gives time. Sum all sections and you have your estimated finish time.
3. Reverse Solving
This is the bit I find most useful. Instead of "given this power, what's my time?", you can ask "given this target time, what power do I need?" The tool binary-searches for the wattage that produces exactly your target time. When I set 35 minutes as my goal and uploaded the Geneva course, it told me I needed 247w uniform. That's a very concrete training target.
4. Per-Section Strategy
This came from a friend's feedback: "Can I simulate pushing hard on the first climb, recovering on the descent, and pushing again on the flat?" Yes. You can click any power value in the course breakdown and override it. Lock the descent at 200w (recovery), push the climb to 310w, and see how the total time changes. The solver adapts too, telling you what the remaining sections need if some are locked.
What I Learned About the Physics
A few things surprised me while building this:
Aerodynamics matter more than power on flat roads. Going from hoods (CdA ~0.32) to drops (CdA ~0.30) saves more time on a flat 20km course than adding 10 watts. If you're doing a time trial, getting low is literally free speed.
Extra watts on a steep descent are almost worthless. At 60+ km/h downhill, you're fighting cubic air resistance. An extra 50 watts might gain you 2 seconds over a 2km descent. Spend those watts on the climb instead, where you're going slow and every watt translates directly to speed.
The Newton-Raphson solver is surprisingly tricky on descents. When gravity is assisting you, the power equation flips and the solver can diverge. I had to implement a smarter initial velocity guess and clamp the step size to prevent it oscillating to nonsense values.
Wind changes everything non-linearly. A 15 km/h headwind on a flat course costs you far more time than a 15 km/h tailwind saves. This comes from the drag equation:
P_aero = 0.5 × CdA × air_density × (v_ground + v_wind)² × v_ground
If you're riding at 36 km/h (10 m/s) into a 15 km/h headwind (4.2 m/s), your air speed is 14.2 m/s, making drag proportional to 14.2² = 201. With a tailwind, your air speed drops to 5.8 m/s, making drag proportional to 5.8² = 34. The headwind case has 6x the aerodynamic drag of the tailwind case. They don't cancel out at all.
The FTP Helper
Most cyclists know their FTP (Functional Threshold Power), the power they can sustain for about an hour. But how does that translate to race power for different durations?
The tool includes presets based on standard power-duration curves:
- All-out (<1h): 105% FTP climbing, 95% flat
- Hard (1-2h): 95% climbing, 88% flat
- Steady (2-4h): 88% climbing, 82% flat
- Endurance (4h+): 80% climbing, 75% flat
Climb power is higher because at low speed there's less aero drag, so more of your effort goes into moving forward. On flats, aero drag dominates and you need to be more conservative to sustain the effort.
Enter your FTP, pick a race intensity, and the sliders set themselves. It's a starting point, and then you can fine-tune.
The Tech
It's built with Next.js, TypeScript, and Tailwind, running entirely client-side. No server, no accounts, no data leaves your browser. The GPX file is parsed in the browser using the DOMParser API, and all the physics runs in JavaScript.
How it compares to the paid tools
The obvious comparison is Best Bike Split. They lead the market for triathlon and time-trial pacing and work with a lot of WorldTour teams. Their pipeline is more sophisticated than mine. Road-surface detection, live weather forecasts, Garmin and Wahoo head-unit integration, an AI race assistant, analytics to compare planned vs. actual power. All polished. All behind a subscription.
The subscription is around $19/month or $119/year. If you race a lot, or if you want your bike computer to beep at you with live power targets on race day, that price is fair.
Here's how mine stacks up.
Shared with BBS: full course-specific physics (CdA, Crr, gradient, air density, drivetrain loss, headwind), GPX upload, goal-time solving, per-section power strategy.
Missing from mine: live weather, road surface detection, head-unit integration, FIT export, multi-plan comparison, race analytics.
One subtle difference worth noting. When you set a target time, my solver picks a single uniform wattage. BBS's optimiser prefers a variable-power plan that pushes harder on climbs and eases on descents. In practice that saves a small amount of time over constant power. You can approximate it here by clicking into the course breakdown and overriding individual sections. Automating it is on my list.
Bottom line: if you're training casually or just trying to answer "can I actually do this?" for a specific course, this tool gets you most of the way there. If you need the full race-day ecosystem with weather and device sync, pay for BBS.
A couple of other free alternatives exist. sport-calculator.com has an Ironman-specific version. TrainerDay published a BBS-style calculator aimed at casual riders. Worth knowing they're there.
Back to the Race
So, can I beat last year's 3rd place? After uploading the Geneva course and plugging in my current FTP, the calculator says I need to average about 250w, holding around 280w on the climb and 240w on the flats. My current FTP puts that right at the edge of "hard but sustainable" for the ~35 minute effort.
Three months of structured training, a clean chain, and a good aero tuck should get me there. Or at least give me a very precise understanding of exactly how far off I am.
Here's hoping I don't blow up on the day!