{"id":663,"date":"2026-08-26T14:12:34","date_gmt":"2026-08-26T14:12:34","guid":{"rendered":"https:\/\/summergeometry.org\/sgi2026\/?p=663"},"modified":"2026-08-26T16:30:34","modified_gmt":"2026-08-26T16:30:34","slug":"vortex-loops-for-jupiters-stripes","status":"publish","type":"post","link":"https:\/\/summergeometry.org\/sgi2026\/vortex-loops-for-jupiters-stripes\/","title":{"rendered":"Vortex Loops for Jupiters&#8217; Stripes"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>Project Members<\/strong>: Aleksa Milovanovi\u0107, Reid Tang<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Mentor<\/strong>: Sadashige Ishida<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Introduction to Fluid Dynamics<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Fluid motion in computer graphics is typically modeled by the incompressible Navier-Stokes equations:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>\u2202<\/mi><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><\/mrow><mrow><mi>\u2202<\/mi><mi>t<\/mi><\/mrow><\/mfrac><mo>+<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>+<\/mo><mfrac><mn>1<\/mn><mi>\u03c1<\/mi><\/mfrac><mo>\u2207<\/mo><mi>p<\/mi><mo>=<\/mo><mover><mi>g<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>+<\/mo><mi>\u03bd<\/mi><mo>\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo separator=\"true\">,<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{\\partial \\vec{u}}{\\partial t} + \\vec{u} \\cdot \\nabla \\vec{u} + \\frac{1}{\\rho} \\nabla p = \\vec{g} + \\nu \\nabla \\cdot \\nabla \\vec{u},<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo>\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u22c5<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>=<\/mo><mn>0<\/mn><mo separator=\"true\">,<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\nabla\\cdot\\vec{u} = 0,<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">where <math><\/math> is the velocity of the fluid, <math><\/math> density, <math><\/math> pressure, <math><\/math> body force and <math><\/math> kinematic viscosity. The first equation (momentum) is Newton&#8217;s second law applied to fluid elements, and the second one constrains the flow to be volume-preserving.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An important concept is <strong>the material derivative<\/strong>, <math><\/math> which measures the rate of change of a quantity following a fluid parcel (Lagrangian) rather than at a fixed point in space (Eulerian).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This allows us to write the momentum equation compactly as<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>D<\/mi><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><\/mrow><mrow><mi>D<\/mi><mi>t<\/mi><\/mrow><\/mfrac><mo>+<\/mo><mfrac><mn>1<\/mn><mi>\u03c1<\/mi><\/mfrac><mo>\u2207<\/mo><mi>p<\/mi><mo>=<\/mo><mover><mi>g<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>+<\/mo><mi>\u03bd<\/mi><mo>\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo separator=\"true\">,<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{D\\vec{u}}{Dt} + \\frac{1}{\\rho}\\nabla p = \\vec{g} + \\nu\\nabla\\cdot\\nabla\\vec{u},<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">and defines advection s.t. <math><\/math> means the quantity is carried by the flow without changing.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Vorticity<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Vorticity<\/strong> is defined as the curl of velocity <math><\/math>, and measures the local rate of rotation of the fluid. For inviscid flow with no body force, taking the curl of the momentum equation gives the vorticity transport equation<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>D<\/mi><mover><mi>\u03c9<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><\/mrow><mrow><mi>D<\/mi><mi>t<\/mi><\/mrow><\/mfrac><mo>=<\/mo><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>\u03c9<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{D\\vec{\\omega}}{Dt} = (\\vec{\\omega}\\cdot\\nabla)\\vec{u}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">where the right-hand side is the vortex-stretching term (as shown in Section 2.1, this term vanishes identically in the 2D setting used throughout this report, so vorticity there is materially conserved exactly, <math><\/math>); it is simply carried by the flow. This makes vorticity important for simulating turbulent and swirl-dominated phenomena, since instead of solving for pressure and velocity everywhere, one only tracks regions where vorticity is concentrated.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The key problem is recovering the velocity field given a vorticity field. In 3D, this is posed as a least-squares problem, i.e. find <math><\/math> minimizing<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo movablelimits=\"false\">\u222d<\/mo><mi>\u2016<\/mi><mo>\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u00d7<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u2212<\/mo><mover><mi>\u03c9<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><msup><mi>\u2016<\/mi><mn>2<\/mn><\/msup><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mi>V<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\iiint \\|\\nabla\\times\\vec{u} &#8211; \\vec{\\omega}\\|^2\\,dV<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">solved via calculus of variations, yielding the Poisson problem <math><\/math>, whose solution is the <strong>Biot-Savart law<\/strong>:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mo movablelimits=\"false\">\u222d<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><msub><mrow><mi mathvariant=\"normal\">\u03a6<\/mi><\/mrow><mn>3<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u2212<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u00d7<\/mo><mover><mi>\u03c9<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo separator=\"true\">,<\/mo><mspace width=\"1em\"><\/mspace><msub><mrow><mi mathvariant=\"normal\">\u03a6<\/mi><\/mrow><mn>3<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><mfrac><mn>1<\/mn><mrow><mn>4<\/mn><mi>\u03c0<\/mi><mi>\u2016<\/mi><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mi>\u2016<\/mi><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">\\vec{u}(\\vec{x}) = \\iiint -\\nabla\\Phi_3(\\vec{x} &#8211; \\vec{p})\\times\\vec{\\omega}(\\vec{p})\\,d\\vec{p}, \\quad \\Phi_3(\\vec{x}) = -\\frac{1}{4\\pi\\|\\vec{x}\\|}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<h5 class=\"wp-block-heading\">Deriving the 2D analogue<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Jupiter&#8217;s bands and jet streams are a 2D phenomenon (a thin shell on the planet&#8217;s surface), so we re-derive the above for a 2D velocity field <math><\/math>, where vorticity reduces to a scalar:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>\u03c9<\/mi><mo>=<\/mo><mfrac><mrow><mi>\u2202<\/mi><mi>v<\/mi><\/mrow><mrow><mi>\u2202<\/mi><mi>x<\/mi><\/mrow><\/mfrac><mo>\u2212<\/mo><mfrac><mrow><mi>\u2202<\/mi><mi>u<\/mi><\/mrow><mrow><mi>\u2202<\/mi><mi>y<\/mi><\/mrow><\/mfrac><mo rspace=\"0em\">=<\/mo><mo lspace=\"0em\" rspace=\"0.2222em\">:<\/mo><msub><mrow><mtext><\/mtext><mi>curl<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\omega = \\frac{\\partial v}{\\partial x} &#8211; \\frac{\\partial u}{\\partial y} =: \\mathrm{curl}_2(\\vec{u})<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">In this 2D setting <math><\/math> points purely out of the plane while <math><\/math> is purely in-plane, so the vortex-stretching term <math><\/math> from Section 2 vanishes identically \u2014 not as an extra assumption, but automatically, because there is no out-of-plane direction left for vorticity to be stretched or tilted into. The vorticity transport equation therefore simplifies exactly to <math><\/math> in 2D, which is what we use throughout.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As in 3D, we seek <math><\/math> minimizing<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo movablelimits=\"false\">\u222c<\/mo><mo fence=\"false\" symmetric=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">(<\/mo><msub><mrow><mtext><\/mtext><mi>curl<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u2212<\/mo><mi>\u03c9<\/mi><msup><mo fence=\"false\" symmetric=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">)<\/mo><mn>2<\/mn><\/msup><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mi>A<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\iint \\big(\\mathrm{curl}_2(\\vec{u}) &#8211; \\omega\\big)^2\\,dA<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Perturbing <math><\/math> and using linearity of <math><\/math>, the stationarity condition <math><\/math> gives, with <math><\/math>,<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo movablelimits=\"false\">\u222c<\/mo><mi>f<\/mi><mspace width=\"0.1667em\"><\/mspace><msub><mrow><mtext><\/mtext><mi>curl<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mi>A<\/mi><mo>=<\/mo><mn>0<\/mn><mtext>&nbsp;<\/mtext><mtext>,&nbsp;for&nbsp;all&nbsp;<\/mtext><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><\/mrow><annotation encoding=\"application\/x-tex\">\\iint  f\\, \\mathrm{curl}_2(\\vec{p})\\,dA = 0 \\ \\text{, for all } \\vec{p}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Unlike 3D, <math><\/math> maps a vector field to a scalar, so its adjoint maps a scalar back to a vector. Integrating by parts term by term (boundary terms vanish as fields decay at infinity),<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo movablelimits=\"false\">\u222c<\/mo><mi>f<\/mi><mspace width=\"0.1667em\"><\/mspace><msub><mrow><mtext><\/mtext><mi>curl<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mi>A<\/mi><mo>=<\/mo><mo movablelimits=\"false\">\u222c<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u22c5<\/mo><msup><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo>\u27c2<\/mo><\/msup><mi>f<\/mi><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mi>A<\/mi><mo separator=\"true\">,<\/mo><mspace width=\"1em\"><\/mspace><msup><mo>\u2207<\/mo><mo>\u27c2<\/mo><\/msup><mi>f<\/mi><mo>\u2261<\/mo><mrow><mo fence=\"true\" form=\"prefix\">(<\/mo><mfrac><mrow><mi>\u2202<\/mi><mi>f<\/mi><\/mrow><mrow><mi>\u2202<\/mi><mi>y<\/mi><\/mrow><\/mfrac><mo separator=\"true\">,<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><mfrac><mrow><mi>\u2202<\/mi><mi>f<\/mi><\/mrow><mrow><mi>\u2202<\/mi><mi>x<\/mi><\/mrow><\/mfrac><mo fence=\"true\" form=\"postfix\">)<\/mo><\/mrow><\/mrow><annotation encoding=\"application\/x-tex\">\\iint f\\,\\mathrm{curl}_2(\\vec{p})\\,dA = \\iint \\vec{p}\\cdot\\nabla^\\perp f\\,dA, \\quad \\nabla^\\perp f \\equiv \\left(\\frac{\\partial f}{\\partial y},-\\frac{\\partial f}{\\partial x}\\right)<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">so that, since this must vanish for all <math><\/math>,<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msup><mo>\u2207<\/mo><mo>\u27c2<\/mo><\/msup><mo fence=\"false\" symmetric=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">(<\/mo><msub><mrow><mtext><\/mtext><mi>curl<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo fence=\"false\" symmetric=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">)<\/mo><mo>=<\/mo><msup><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo>\u27c2<\/mo><\/msup><mi>\u03c9<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\nabla^\\perp\\big(\\mathrm{curl}_2(\\vec{u})\\big) = \\nabla^\\perp\\omega<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The same vector identity used in 3D,<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo>\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u00d7<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u00d7<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>=<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>+<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u22c5<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\nabla\\times\\nabla\\times\\vec{u} = -\\nabla\\cdot\\nabla\\vec{u} + \\nabla(\\nabla\\cdot\\vec{u})<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">restricted to 2D becomes <math><\/math>. With the constraint <math><\/math>, we obtain a Poisson problem:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo>\u2212<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo form=\"prefix\" stretchy=\"false\">\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>=<\/mo><msup><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><mo>\u27c2<\/mo><\/msup><mi>\u03c9<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">-\\nabla\\cdot\\nabla\\vec{u} = \\nabla^\\perp\\omega<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The 2D fundamental solution of the Laplacian is<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mrow><mi mathvariant=\"normal\">\u03a6<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mfrac><mn>1<\/mn><mrow><mn>2<\/mn><mi>\u03c0<\/mi><\/mrow><\/mfrac><mrow><mi>log<\/mi><mo>\u2061<\/mo><\/mrow><mi>\u2016<\/mi><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mi>\u2016<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\Phi_2(\\vec{x}) = \\frac{1}{2\\pi}\\log\\|\\vec{x}\\|<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">satisfying <math><\/math>, verified by the divergence theorem on the unit circle:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mo movablelimits=\"false\">\u222e<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2207<\/mo><msub><mrow><mi mathvariant=\"normal\">\u03a6<\/mi><\/mrow><mn>2<\/mn><\/msub><mo>\u22c5<\/mo><mover><mi>n<\/mi><mo stretchy=\"false\" class=\"tml-xshift\" style=\"math-style:normal;math-depth:0;\">^<\/mo><\/mover><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mi>\u2113<\/mi><mo>=<\/mo><mo movablelimits=\"false\">\u222e<\/mo><mfrac><mn>1<\/mn><mrow><mn>2<\/mn><mi>\u03c0<\/mi><\/mrow><\/mfrac><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mi>\u2113<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><annotation encoding=\"application\/x-tex\">\\oint \\nabla\\Phi_2\\cdot\\hat{n}\\,d\\ell = \\oint \\frac{1}{2\\pi}\\,d\\ell = 1<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The solution to the Poisson problem, via convolution with <math><\/math>:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mo movablelimits=\"false\">\u222c<\/mo><msub><mrow><mi mathvariant=\"normal\">\u03a6<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u2212<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mspace width=\"0.1667em\"><\/mspace><msup><mo>\u2207<\/mo><mo>\u27c2<\/mo><\/msup><mi>\u03c9<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><\/mrow><annotation encoding=\"application\/x-tex\">\\vec{u}(\\vec{x}) = \\iint \\Phi_2(\\vec{x} &#8211; \\vec{p})\\,\\nabla^\\perp\\omega(\\vec{p})\\,d\\vec{p}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Integrating by parts once again (moving <math><\/math> off <math><\/math> onto <math><\/math>) gives the 2D <strong>Biot-Savart law<\/strong> in the form:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mo movablelimits=\"false\">\u222c<\/mo><mi>\u03c9<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mspace width=\"0.1667em\"><\/mspace><msup><mo>\u2207<\/mo><mo>\u27c2<\/mo><\/msup><msub><mrow><mi mathvariant=\"normal\">\u03a6<\/mi><\/mrow><mn>2<\/mn><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u2212<\/mo><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mspace width=\"0.1667em\"><\/mspace><mi>d<\/mi><mover><mi>p<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><\/mrow><annotation encoding=\"application\/x-tex\">\\vec{u}(\\vec{x}) = \\iint \\omega(\\vec{p})\\,\\nabla^\\perp\\Phi_2(\\vec{x}-\\vec{p})\\,d\\vec{p}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Discretizing <math><\/math> as a sum of Dirac deltas collapses the integral to a sum:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mrow><munder><mo movablelimits=\"false\">\u2211<\/mo><mi>i<\/mi><\/munder><\/mrow><mfrac><msub><mrow><mi mathvariant=\"normal\">\u0393<\/mi><\/mrow><mi>i<\/mi><\/msub><mrow><mn>2<\/mn><mi>\u03c0<\/mi><\/mrow><\/mfrac><mfrac><mrow><mo form=\"prefix\" stretchy=\"false\" lspace=\"0em\" rspace=\"0em\">(<\/mo><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u2212<\/mo><msub><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mi>i<\/mi><\/msub><msup><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u27c2<\/mo><\/msup><\/mrow><mrow><mi>\u2016<\/mi><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u2212<\/mo><msub><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mi>i<\/mi><\/msub><msup><mi>\u2016<\/mi><mn>2<\/mn><\/msup><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">\\vec{u}(\\vec{x}) = \\sum_i \\frac{\\Gamma_i}{2\\pi} \\frac{(\\vec{x} &#8211; \\vec{x}_i)^\\perp}{\\|\\vec{x} &#8211; \\vec{x}_i\\|^2}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Since inviscid vorticity is materially conserved, each point vortex simply moves with the velocity induced by all other vortices at its own location (the self-term is excluded), giving the <strong>point vortex dynamics equation<\/strong>:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>d<\/mi><msub><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mi>i<\/mi><\/msub><\/mrow><mrow><mi>d<\/mi><mi>t<\/mi><\/mrow><\/mfrac><mo>=<\/mo><mrow><munder><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>j<\/mi><mo>\u2260<\/mo><mi>i<\/mi><\/mrow><\/munder><\/mrow><mfrac><msub><mrow><mi mathvariant=\"normal\">\u0393<\/mi><\/mrow><mi>j<\/mi><\/msub><mrow><mn>2<\/mn><mi>\u03c0<\/mi><mi>\u2016<\/mi><msub><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mi>i<\/mi><\/msub><mo>\u2212<\/mo><msub><mover><mi>x<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mi>j<\/mi><\/msub><msup><mi>\u2016<\/mi><mn>2<\/mn><\/msup><\/mrow><\/mfrac><mo fence=\"false\" symmetric=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">(<\/mo><mo>\u2212<\/mo><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>y<\/mi><mi>i<\/mi><\/msub><mo>\u2212<\/mo><msub><mi>y<\/mi><mi>j<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo separator=\"true\">,<\/mo><mspace width=\"0.1667em\"><\/mspace><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo>\u2212<\/mo><msub><mi>x<\/mi><mi>j<\/mi><\/msub><mo fence=\"false\" symmetric=\"true\" minsize=\"1.2em\" maxsize=\"1.2em\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{d\\vec{x}_i}{dt} = \\sum_{j\\neq i}\\frac{\\Gamma_j}{2\\pi\\|\\vec{x}_i-\\vec{x}_j\\|^2}\\big(-(y_i-y_j),\\,x_i-x_j\\big)<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">This is the equation we implemented and verified on various examples (e.g. leapfrogging etc.) before extending it to the sphere.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Implementation and Validation in the Plane<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The point vortex dynamics equation above was implemented in Houdini using a custom SOP Solver: each timestep, a VEX wrangle reads the previous frame&#8217;s point cloud (position and circulation <math><\/math> per point), evaluates the Biot\u2013Savart sum, and advances each point&#8217;s position. Before trusting this on any nontrivial configuration, it was validated against two exactly-solvable two-vortex cases: equal circulations <math><\/math>, where both vortices orbit a common, stationary centroid on a circular path, and opposite circulations <math><\/math>, where the pair instead translates together in a straight line at constant speed. Both matched their analytic period\/speed formulas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As a further, qualitative check, a classical four-vortex <strong>leapfrogging<\/strong> configuration (two counter-rotating pairs, arranged so the trailing pair periodically overtakes the leading pair) was simulated and reproduced the expected periodic behavior.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-1024x256.png\" alt=\"\" class=\"wp-image-664\" srcset=\"https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-1024x256.png 1024w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-300x75.png 300w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-768x192.png 768w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-1536x384.png 1536w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-2048x512.png 2048w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-1200x300.png 1200w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/d8cad66881b6ea12bcbccb8bb5b6cb816f8c3031-1980x495.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Trajectories of the four-vortex leapfrogging configuration at three points in the cycle (frames 20, 80, 140). Each mark traces the recent path of one vortex; the pairs periodically exchange places as they orbit and overtake one another.<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">A Vortex-Ring Model of Kelvin\u2013Helmholtz Instability<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To move from the plane to Jupiter&#8217;s spherical atmosphere, the point vortex equation was extended to the unit sphere <math><\/math> by replacing the planar kernel with the spherical Biot\u2013Savart law and integrating positions via the exponential map, <math><\/math>, so that points remain exactly on the sphere regardless of step size. Because <math><\/math> has no boundary, the total vorticity must also integrate to zero, <math><\/math> \u2014 a constraint with no analogue in the plane, enforced here by construction (equal numbers of positive and negative vortices, or an explicit normalization step subtracting the mean circulation from every point).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On this spherical setup, a shear layer was modeled as a vortex sheet: a ring of point vortices along a line of latitude, one sign on each side of the interface, with a small sinusoidal perturbation added to seed the instability. With no additional forcing, mutual induction alone causes the shear layer to roll up into a periodic array of vortices, as expected from classical vortex-sheet theory.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"276\" src=\"https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-1024x276.png\" alt=\"\" class=\"wp-image-665\" srcset=\"https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-1024x276.png 1024w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-300x81.png 300w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-768x207.png 768w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-1536x414.png 1536w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-2048x552.png 2048w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-1200x323.png 1200w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/07e020b756fbba1fa8a57be4e61085367699fae3-1980x533.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">A single vortex-sheet interface at three stages: the initial perturbed line (frame 50), partial roll-up into discrete billows (frame 250), and a more developed, mixed state (frame 450).<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This was then generalized to several alternating-sign rings restricted to a narrower latitude band, approximating Jupiter&#8217;s alternating belt\/zone structure. Passive marker particles (zero circulation, contributing nothing to the velocity field but advected by it) were added and colored with a Jupiter-like palette for visualization.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"276\" src=\"https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-1024x276.png\" alt=\"\" class=\"wp-image-666\" srcset=\"https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-1024x276.png 1024w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-300x81.png 300w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-768x207.png 768w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-1536x414.png 1536w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-2048x552.png 2048w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-1200x323.png 1200w, https:\/\/summergeometry.org\/sgi2026\/wp-content\/uploads\/2026\/08\/6117d0b21adb61f40c877f9e5b9be2bd9bc79cb2-1980x533.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Multi-band configuration (M=3) at frames 20, 250, and 500. Marker particles, seeded uniformly, are progressively advected and mixed along the band-induced shear flow.<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Modeling the Coriolis Effect<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To incorporate planetary rotation, the momentum equation was written in a frame rotating with angular velocity <math><\/math>. Taking the curl and combining terms gives the vorticity equation with a rotational source,<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>D<\/mi><mi>\u03c9<\/mi><\/mrow><mrow><mi>D<\/mi><mi>t<\/mi><\/mrow><\/mfrac><mo>=<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><mn>2<\/mn><mover><mi>u<\/mi><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo>\u22c5<\/mo><mover><mrow><mi mathvariant=\"normal\">\u03a9<\/mi><\/mrow><mo stretchy=\"false\" style=\"transform:scale(0.75) translate(10%, 30%);\">\u2192<\/mo><\/mover><mo separator=\"true\">,<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{D\\omega}{Dt} = -2\\vec{u}\\cdot\\vec{\\Omega},<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">in place of the inviscid <math><\/math> used above. This was implemented by updating each vortex&#8217;s circulation every step, <math><\/math>, so that circulation is no longer materially conserved. This is a first, direct discretization of the effect; a more careful treatment (in particular, its interaction with the <math><\/math> constraint over long integration times) is left for future work.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Discussion and Limitations<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The point-vortex approach reproduces known analytic solutions in the plane, the classical leapfrogging trajectory, and qualitatively correct Kelvin\u2013Helmholtz roll-up on the sphere, both for a single interface and for a multi-band configuration resembling Jupiter&#8217;s belts and zones. The Coriolis implementation here is a direct, unrefined discretization rather than a fully validated one, and the multi-band results are qualitative: parameters such as band spacing, perturbation amplitude, and desingularization radius were chosen for a visually clear roll-up rather than calibrated against a specific analytic growth rate or against Jupiter&#8217;s actual physical parameters. Extending the integrator beyond forward Euler, and validating the Coriolis term against a known conserved quantity, are the natural next steps.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Project Members: Aleksa Milovanovi\u0107, Reid Tang Mentor: Sadashige Ishida Introduction to Fluid Dynamics Fluid motion in computer graphics is typically modeled by the incompressible Navier-Stokes equations: where is the velocity of the fluid, density, pressure, body force and kinematic viscosity. The first equation (momentum) is Newton&#8217;s second law applied to fluid elements, and the second [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[110],"tags":[],"ppma_author":[55,17],"class_list":["post-663","post","type-post","status-publish","format-standard","hentry","category-research"],"authors":[{"term_id":55,"user_id":0,"is_guest":1,"slug":"cap-aleksa-milovanovic","display_name":"aleksa.milovanovic","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/?s=96&d=mm&r=g","author_category":"","first_name":"","last_name":"","user_url":"","job_title":"","description":""},{"term_id":17,"user_id":0,"is_guest":1,"slug":"cap-reidtang","display_name":"reidtang","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/?s=96&d=mm&r=g","author_category":"","first_name":"","last_name":"","user_url":"","job_title":"","description":""}],"_links":{"self":[{"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/posts\/663","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/comments?post=663"}],"version-history":[{"count":5,"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/posts\/663\/revisions"}],"predecessor-version":[{"id":1184,"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/posts\/663\/revisions\/1184"}],"wp:attachment":[{"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/media?parent=663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/categories?post=663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/tags?post=663"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/summergeometry.org\/sgi2026\/wp-json\/wp\/v2\/ppma_author?post=663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}