The Weight Sits on Top and She Still Rights Herself — Metacentric Height and the Free Surface Effect
GM is the margin the waterplane inertia buys you. A single free surface in a tank can take the whole margin away.
The centre of gravity of a container ship sits several metres above the centroid of her submerged volume. The heavy end is on top, and she still stands up by herself. Meanwhile a barge whose centre of gravity is below the buoyancy centre can roll over. Up versus down settles nothing. This post is about the quantity that actually decides the case — the metacentric height — where it comes from, and why liquid in a tank can erase it completely.
The centre of gravity is above the centre of buoyancy#
Symbols first. is the keel, is the centre of gravity, is the centre of buoyancy — the centroid of the submerged volume. Archimedes only fixed the magnitude: buoyancy equals the weight of the displaced water, and its line of action passes through the centroid of that displaced volume.
Upright, and share the same vertical line. Weight and buoyancy are equal and opposite, so the moment is zero. In that state it makes no difference whether is high or low. Stability is not defined by the state at rest. It is defined by what appears when you tip the body slightly.
Heel her, and things change. is the centroid of the submerged shape, so when the shape changes, moves with it. rotates with the ship but stays put inside it. The two verticals separate and a lever arm appears. That arm is the righting arm , and the righting moment is for a displacement .
Heel her and the submerged shape changes#
Tip her yourself in the simulation below. Change the beam, the draft and the height of the centre of gravity, then press release at 15 deg and watch whether she comes back.
(green) is dragged toward the low side, and the gap that opens against the vertical through (yellow) is . The purple is where the buoyancy line crosses the ship's centreline. Push the KG slider above 7.33 m and drops below : instead of returning, she lies over at a fixed angle and stays there.
— the waterplane inertia is the whole story#
At a small heel the change in the submerged shape reduces to two wedges: one that emerges on the high side and one that immerses on the low side. Their volumes are equal, because the displacement cannot change, and they are separated horizontally. That transfer of volume is what moves .
Take a strip of the waterplane (the section the free surface cuts through the hull) at a distance from the centreline. It contributes a volume change and a moment . Summing over the waterplane gives a second moment of area.
is the second moment of the waterplane about the centreline and is the displaced volume. For a rectangular section of beam , per unit length and , so
The beam enters cubed, then the in the denominator cancels one power and leaves a square. Widen the hull by 20% and grows by 44%. That is why a canoe is twitchy and a raft is not. The verdict itself is one line.
is the height of the buoyancy centre and the height of the centre of gravity. means she rights herself, means she goes over. For a barge with beam m and draft m, m and m, so m. If is 6.6 m, the whole margin is 0.733 m.
The angle where betrays you#
is a slope at . At small angles holds well. The interesting question is when it stops holding.
Geometry sets that point, because stays constant only while the waterplane stays the same. The barge above has 4 m of freeboard, so the deck edge goes under at , that is 26.6 degrees. From there the waterplane stops widening and starts to shrink. collapses and the curve rolls over.
Press hold heel in the simulation and drag past 30 degrees: the solid green curve (the exact value) peels away from the dashed purple line (). The heel where the two disagree in sign is the angle of vanishing stability.
Liquid in a tank takes the whole of GM#
Now put a tank of liquid inside the hull. Ballast tanks, fuel tanks, cargo tanks, a car deck flooded with firefighting water — all the same problem.
The weight of the liquid does not change when she heels. It only moves. And that movement drags toward the low side. The bookkeeping is identical to : the free surface inside the tank is a waterplane too, and heeling swaps two wedges across it.
is the second moment of the tank's free surface, the density of the liquid inside and that of the water outside. The loss is not subtracted from the hull; it is treated as a virtual rise of by that amount. How much liquid the tank holds does not appear in the formula. Unless the tank is pressed full so there is no free surface at all, or completely empty, 20 cm of liquid costs exactly what 2 m of it costs.
Move the bulkhead slider below.
Yellow is the liquid. Its surface stays horizontal no matter what the hull does. At n = 1, release her and she never returns — she settles at an angle of loll. Add one bulkhead and the red loss bar drops to a quarter, and she stands up again.
One bulkhead cuts the loss to a quarter#
Divide a tank of width into compartments and each is wide, with of them.
The loss falls as , not : the cube on the width beats the single power on the count. One 12 m tank in the barge above gives m⁴ against m³/m, so m. The 0.733 m of was gone long before that. A single centreline bulkhead brings the loss down to 0.549 m and she stands again.
That is what the longitudinal bulkhead down the middle of a tanker is for. The cargo does not change and neither does the height of the centre of gravity. Only the width of each free surface is halved.
The GZ curve and the vanishing angle, in Python#
is a single tangent slope. At large angles it is quicker to cut the submerged polygon directly and take its centroid. Represent the hull section as a polygon, bisect for the waterline height that makes the submerged area equal the displaced area, and compute the centroid of what is left.
import math
def poly_area_centroid(poly):
a = cx = cy = 0.0
n = len(poly)
for i in range(n):
x0, y0 = poly[i]
x1, y1 = poly[(i + 1) % n]
cr = x0 * y1 - x1 * y0
a += cr
cx += (x0 + x1) * cr
cy += (y0 + y1) * cr
a *= 0.5
if abs(a) < 1e-14:
return 0.0, 0.0, 0.0
return a, cx / (6 * a), cy / (6 * a)
def clip_below(poly, phi, h):
"""keep the part of the polygon whose earth-frame height is below h"""
def f(p):
return p[1] * math.cos(phi) - p[0] * math.sin(phi) - h
out = []
n = len(poly)
for i in range(n):
p, q = poly[i], poly[(i + 1) % n]
fp, fq = f(p), f(q)
if fp <= 0.0:
out.append(p)
if (fp < 0.0) != (fq < 0.0):
t = fp / (fp - fq)
out.append((p[0] + t * (q[0] - p[0]), p[1] + t * (q[1] - p[1])))
return out
def waterline_offset(poly, phi, area0):
"""bisect for the waterline height that submerges exactly area0"""
lo, hi = -60.0, 60.0
for _ in range(80):
mid = 0.5 * (lo + hi)
a, _, _ = poly_area_centroid(clip_below(poly, phi, mid))
if a < area0:
lo = mid
else:
hi = mid
return 0.5 * (lo + hi)
def righting_arm(beam, depth, draft, kg, phi):
hull = [(-beam / 2, 0.0), (beam / 2, 0.0), (beam / 2, depth), (-beam / 2, depth)]
h = waterline_offset(hull, phi, beam * draft)
_, xb, yb = poly_area_centroid(clip_below(hull, phi, h))
return xb * math.cos(phi) + (yb - kg) * math.sin(phi), xb, yb
def gz_curve(beam, depth, draft, kg, deg_max=70, step=1):
return [(d, righting_arm(beam, depth, draft, kg, math.radians(d))[0])
for d in range(0, deg_max + 1, step)]
BEAM, DEPTH, DRAFT = 16.0, 8.0, 4.0
KG = 6.6
KB = DRAFT / 2
BM = BEAM ** 2 / (12 * DRAFT)
GM = KB + BM - KG
print(f"KB={KB:.3f} m BM=B^2/12T={BM:.3f} m KM={KB+BM:.3f} m KG={KG:.3f} m GM={GM:.3f} m")
print(f"deck edge immerses at phi = {math.degrees(math.atan(2*(DEPTH-DRAFT)/BEAM)):.1f} deg")
print()
print(" phi[deg] GZ[m] GM*sin(phi)[m] error[%]")
for d, gz in gz_curve(BEAM, DEPTH, DRAFT, KG, 60, 5):
lin = GM * math.sin(math.radians(d))
err = f"{100 * (lin - gz) / gz:8.1f}" if abs(gz) > 0.01 else " -"
print(f" {d:5.1f} {gz:7.4f} {lin:11.4f} {err}")
curve = gz_curve(BEAM, DEPTH, DRAFT, KG, 70, 1)
dmax, gzmax = max(curve, key=lambda t: t[1])
vanish = next((d for d, g in curve if d > 5 and g <= 0.0), None)
print()
print(f"max GZ = {gzmax:.3f} m at {dmax} deg, vanishing stability at {vanish} deg")KB=2.000 m BM=B^2/12T=5.333 m KM=7.333 m KG=6.600 m GM=0.733 m
deck edge immerses at phi = 26.6 deg
phi[deg] GZ[m] GM*sin(phi)[m] error[%]
0.0 0.0000 0.0000 -
5.0 0.0657 0.0639 -2.7
10.0 0.1417 0.1273 -10.2
15.0 0.2394 0.1898 -20.7
20.0 0.3716 0.2508 -32.5
25.0 0.5550 0.3099 -44.2
30.0 0.7207 0.3667 -49.1
35.0 0.6823 0.4206 -38.4
40.0 0.5196 0.4714 -9.3
45.0 0.2828 0.5185 83.3
50.0 0.0001 0.5618 -
55.0 -0.3116 0.6007 -292.8
60.0 -0.6406 0.6351 -199.1
max GZ = 0.727 m at 31 deg, vanishing stability at 51 degAt 5 degrees the error is 2.7%. At 30 degrees delivers barely half the true , because the waterplane keeps widening until the deck goes under and the real righting arm outruns the linear estimate. Past 45 degrees the sign of the error flips and the linear estimate starts lying in the dangerous direction: at 50 degrees the true is zero while still promises 0.56 m.
The free surface loss can be checked without cutting any polygon. Below deck immersion the sides are vertical, and the righting arm has a closed form. The loss is a virtual rise, so subtract from and feed that in.
import math
BEAM, DRAFT, KG = 16.0, 4.0, 6.6
NABLA = BEAM * DRAFT
BM = BEAM ** 2 / (12 * DRAFT)
GM = DRAFT / 2 + BM - KG
def free_surface_loss(rho_f, rho, b, n, nabla):
"""free surface loss [m] for a tank of width b split by n bulkheads"""
i_free = n * (b / n) ** 3 / 12
return rho_f * i_free / (rho * nabla)
def wall_sided_gz(gm, bm, phi):
"""righting arm while the sides are still vertical, before deck immersion"""
return (gm + 0.5 * bm * math.tan(phi) ** 2) * math.sin(phi)
print(" tanks i[m^4] dGM[m] GM_eff[m] GZ(20deg)[m]")
for n in (1, 2, 3, 4):
d_gm = free_surface_loss(1000.0, 1025.0, 12.0, n, NABLA)
gz20 = wall_sided_gz(GM - d_gm, BM, math.radians(20))
print(f" {n:4d} {n*(12.0/n)**3/12:7.1f} {d_gm:7.3f} {GM-d_gm:8.3f} {gz20:11.3f}") tanks i[m^4] dGM[m] GM_eff[m] GZ(20deg)[m]
1 144.0 2.195 -1.462 -0.379
2 36.0 0.549 0.185 0.184
3 16.0 0.244 0.489 0.288
4 9.0 0.137 0.596 0.325One bulkhead takes from 144 to 36, exactly a quarter. The righting arm at 20 degrees flips sign, from −0.379 m to +0.184 m. The closed form used here, , agrees with the polygon calculation as long as the deck stays dry: with no loss at all it gives 0.3716 m at 20 degrees, the same number as the table above.
Before you float a hull in a 6-DOF VOF run#
The moment you solve a floating body with CFD, every one of these numbers becomes a check on the solver.
First, work out by hand before you set the initial draft. Capture the free surface with VOF (comparing interface capturing schemes) and attach 6-DOF rigid body motion (quaternion-based rigid body FEM) and she will roll on her own. If the period of that damped free decay, with the roll radius of gyration, disagrees with the hand value, suspect the grid or the inertia you typed in.
Second, grid resolution eats directly. is an -weighted integral over the waterplane, so the cells near the sides contribute the most. If the free surface smears over two or three cells, the effective waterplane width blurs and the righting moment is underpredicted. Refining locally around the waterline is the cheap fix.
Third, if you run with the tanks filled, the free surface loss appears by itself — together with sloshing. When the liquid runs out of phase with the hull motion the result can be worse or better than the quasi-static . This is also where implicit treatments of the free surface earn their keep (Casulli–Zanolli's nested Newton). The hand calculation still holds there. It is just no longer the answer — it is the baseline you use to distrust the result.
Related
Share if you found it helpful.