<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>TinyComputers.io (Posts about performance optimization)</title><link>https://tinycomputers.io/</link><description></description><atom:link href="https://tinycomputers.io/categories/performance-optimization.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Original site content © 2022–2026 Tiny Machines Workshop, LLC, except where otherwise noted. Some rights reserved.</copyright><lastBuildDate>Sat, 26 Sep 2026 18:52:26 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Optimizing Scientific Simulations: JAX-Powered Ballistic Calculations</title><link>https://tinycomputers.io/posts/optimizing-scientific-simulations-jax-powered-ballistic-calculations.html?utm_source=feed&amp;utm_medium=rss&amp;utm_campaign=rss</link><dc:creator>A.C. Jokela</dc:creator><description>&lt;div class="audio-widget"&gt;
&lt;div class="audio-widget-header"&gt;
&lt;span class="audio-widget-icon"&gt;🎧&lt;/span&gt;
&lt;span class="audio-widget-label"&gt;Listen to this article&lt;/span&gt;
&lt;/div&gt;
&lt;audio controls preload="metadata"&gt;
&lt;source src="https://tinycomputers.io/optimizing-scientific-simulations-jax-powered-ballistic-calculations_tts.mp3" type="audio/mpeg"&gt;
&lt;/source&gt;&lt;/audio&gt;
&lt;div class="audio-widget-footer"&gt;23 min · AI-generated narration&lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Introduction to Projectile Simulation and Modern Python Tools&lt;/h3&gt;
&lt;p&gt;Accurate simulation of projectile motion is a cornerstone of engineering, ballistics, and numerous scientific fields. Advanced simulations empower engineers and researchers to design better projectiles, optimize firing solutions, and visualize real-world outcomes before physical testing. In the modern age, computational power and flexible programming tools have transformed the landscape: what once required specialized software or labor-intensive calculations can now be accomplished interactively and at scale, right from within a Python environment.&lt;/p&gt;
&lt;p&gt;If you’ve explored our previous article on the fundamental physics governing projectile motion (including forces, air resistance, and drag models), you’re already equipped with the core theoretical background. Now it’s time to bridge theory and application.&lt;/p&gt;
&lt;p&gt;This post is a hands-on guide to building a complete, end-to-end simulation of projectile trajectories in Python, harnessing &lt;a href="https://go.tinymachines.io/pA4xzt"&gt;JAX&lt;/a&gt;, a state-of-the-art computational library. JAX brings together automatic differentiation, just-in-time (JIT) compilation, and accelerated linear algebra, enabling lightning-fast simulation of complex scientific systems. The focus will be less on the physics itself (already well covered) and more on translating those equations into robust, performant code.&lt;/p&gt;
&lt;p&gt;You’ll see how to set up the necessary equations, efficiently solve them using modern ODE integration tools, and visualize the results, all while leveraging JAX’s unique features for speed and scalability. Whether you’re a ballistics enthusiast, an engineer, or a scientific Python user eager to level up, this walk-through will arm you with tools and practices that apply far beyond just projectile simulation.&lt;/p&gt;
&lt;p&gt;Let’s dive in and see how modern Python changes the game for scientific simulation!&lt;/p&gt;
&lt;h3&gt;Overview: Problem Setup and Simulation Goals&lt;/h3&gt;
&lt;p&gt;In this section, we set the stage for our ballistic simulation, clarifying what we’re modeling, why it matters, and the practical outcomes we seek to extract from the code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is being simulated?&lt;/strong&gt;&lt;br&gt;
The core objective is to simulate the flight of a projectile (in this case, a typical 5.56 mm round) fired from a set initial height and velocity. The code models its motion under the influence of gravity and aerodynamic drag, capturing the trajectory as it travels horizontally towards a target positioned at a specific range, say, 500 meters. The simulation starts at the muzzle of the firearm, positioned at a given height above the ground, and traces the projectile’s path through the air until it either impacts the ground or reaches beyond the target.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why simulate?&lt;/strong&gt;&lt;br&gt;
Such simulations are invaluable for answering “what-if” questions in projectile design and use: what if I change the muzzle velocity? How does a heavier or lighter round perform? At what angle should I aim to hit a given target at a certain distance? This approach enables users to tweak parameters and instantly gauge the impact, eliminating guesswork and excessive field testing. For both professionals and enthusiasts, it’s a chance to iterate on design and tactics within minutes, not months.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are the desired outputs?&lt;/strong&gt;&lt;br&gt;
Our main outputs include:
- The full trajectory curve of the projectile (height vs. range)
- The precise launch angle required to hit a specified target distance
- Visualizations to help interpret and communicate simulation results&lt;/p&gt;
&lt;p&gt;Together, these outputs empower informed decision-making and deeper insight into ballistic performance, all driven by robust computational modeling.&lt;/p&gt;
&lt;p&gt;It appears that JAX (a core library for this simulation) is not available in the current environment, which prevents execution of the code involving JAX.&lt;/p&gt;
&lt;p&gt;However, I will proceed with a detailed narrative for this section, focusing on key implementation concepts, code structure, and modularity, backed with illustrative (but non-executable) code snippets:&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Building the ODE System in Python&lt;/h3&gt;
&lt;p&gt;A robust simulation relies on clear formulation and modular code. Here’s how we set up the ordinary differential equation (ODE) problem for projectile motion in Python:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;State Vector Choice&lt;/strong&gt;&lt;br&gt;
To simulate projectile motion, we track both position and velocity in two dimensions:
- Horizontal position (&lt;code&gt;x&lt;/code&gt;)
- Vertical position (&lt;code&gt;z&lt;/code&gt;)
- Horizontal velocity (&lt;code&gt;vx&lt;/code&gt;)
- Vertical velocity (&lt;code&gt;vz&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;So, our state vector is:&lt;br&gt;
&lt;code&gt;y = [x, z, vx, vz]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This compact representation allows for versatile modeling and easy extension (e.g., adding wind, spin, or more dimensions).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constructing the System of Differential Equations&lt;/strong&gt;&lt;br&gt;
Projectile motion is governed by Newton’s laws, capturing how forces (gravity, drag) influence velocity, and how velocity updates position:
- &lt;code&gt;dx/dt = vx&lt;/code&gt;
- &lt;code&gt;dz/dt = vz&lt;/code&gt;
- &lt;code&gt;dvx/dt = -drag_x / m&lt;/code&gt;
- &lt;code&gt;dvz/dt = gravity - drag_z / m&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Drag is a velocity-dependent force that always acts opposite to the direction of movement. The code calculates its magnitude and then decomposes it into x and z components.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Separating the ODE Right-Hand Side (RHS) Functionally&lt;/strong&gt;&lt;br&gt;
The core computation is wrapped in a RHS function, responsible for calculating derivatives:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="n"&gt;v_mag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vz&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1e-9&lt;/span&gt;    &lt;span class="c1"&gt;# Avoid division by zero&lt;/span&gt;
    &lt;span class="n"&gt;Cd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drag_cd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                      &lt;span class="c1"&gt;# Drag coefficient (customizable)&lt;/span&gt;
    &lt;span class="n"&gt;Fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rho_air&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Cd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="c1"&gt;# Aerodynamic drag force&lt;/span&gt;
    &lt;span class="n"&gt;ax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vx&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# Acceleration x&lt;/span&gt;
    &lt;span class="n"&gt;az&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vz&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;# Acceleration z&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;az&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This separation maximizes code clarity and makes performance optimizations easy (e.g., JIT compilation with JAX).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why Structure and Modularity Matter&lt;/strong&gt;&lt;br&gt;
By separating concerns (parameter setup, force models, ODE integration), you gain:
- &lt;strong&gt;Readability:&lt;/strong&gt; Each function’s purpose is clear.
- &lt;strong&gt;Testability:&lt;/strong&gt; Swap in new force or drag models to study their effect.
- &lt;strong&gt;Maintainability:&lt;/strong&gt; Code updates or physics tweaks are low-risk and contained.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Design for Expandability&lt;/strong&gt;&lt;br&gt;
A key design goal is to enable future enhancements, such as switching from a G1 drag model to a different ballistic curve, adding wind, or including non-standard forces. By passing the drag model as a function (e.g., &lt;code&gt;drag_cd = drag_cd_g1&lt;/code&gt;), you decouple physics from solver techniques.&lt;/p&gt;
&lt;p&gt;This modularity allows for rapid experimentation and testing of new models, making the simulation adaptable to various scenarios.&lt;/p&gt;
&lt;h3&gt;Setting Up the Simulation Environment&lt;/h3&gt;
&lt;p&gt;Projectile simulations are driven by several key configuration parameters that define the initial state and environment for the projectile's flight. These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;muzzle_velocity_mps&lt;/strong&gt;: The speed at which the projectile leaves the barrel. This directly affects how far and fast the projectile travels.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mass_kg&lt;/strong&gt;: The projectile's mass, which influences its response to drag and gravity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;muzzle_height_m&lt;/strong&gt;: The starting height above the ground. Raising the muzzle allows for a longer flight before ground impact.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;diameter_m&lt;/strong&gt; and &lt;strong&gt;air_density_kgpm3&lt;/strong&gt;: Both impact the aerodynamic drag force.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gravity_mps2&lt;/strong&gt;: The acceleration due to gravity (usually -9.80665 m/s²).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;max_time_s&lt;/strong&gt; and &lt;strong&gt;samples&lt;/strong&gt;: Define the time span and resolution for the simulation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;target_distance_m&lt;/strong&gt;: The distance to the desired target.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's best practice to set these values programmatically (using configuration dictionaries) because this approach allows for rapid adjustments, parameter sweeps, and reproducible simulations. For example, you might configure different scenarios (e.g., low velocity, high muzzle, heavy projectile) to test how changes affect trajectory and impact point.&lt;/p&gt;
&lt;p&gt;As shown in the sample table, adjusting parameters such as muzzle velocity, launch height, or projectile mass enables "what-if" analysis:&lt;br&gt;
- Lower velocity reduces range.
- Higher muzzle increases airtime and distance.
- Heavier rounds resist drag differently.&lt;/p&gt;
&lt;p&gt;This programmatic approach streamlines experimentation, ensuring that each simulation is consistent, transparent, and easily adaptable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. JAX: Accelerating Simulation and ODE Solving&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In recent years, JAX has emerged as one of the most powerful tools for scientific computing in Python. Built by Google, JAX combines the familiarity of NumPy-like syntax with transformative features for high-performance computation, making it perfectly suited to both machine learning and advanced simulation tasks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Introduction to JAX: Core Features&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At its core, JAX offers three key capabilities:
- &lt;strong&gt;Automatic Differentiation (Autograd):&lt;/strong&gt; JAX can compute gradients of code written in pure Python/Numpy-style, enabling optimization and sensitivity analysis in scientific models.
- &lt;strong&gt;XLA Compilation:&lt;/strong&gt; JAX code can be compiled just-in-time (JIT) to machine code using Google’s Accelerated Linear Algebra (XLA) backend, resulting in massive speed-ups on CPUs, GPUs, or TPUs.
- &lt;strong&gt;Pure Functions:&lt;/strong&gt; JAX enforces a functional programming style: all operations are stateless and side-effect free. This aids reproducibility, parallelism, and debugging.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why JAX is a Good Fit for Physical Simulation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Physical simulations, like the projectile ODE system here, often demand:
- Repeated evaluation of similar update steps (for integration)
- Fast turnaround for parameter studies and sweeps
- Clear-code with minimal coupling and side effects&lt;/p&gt;
&lt;p&gt;JAX’s stateless, vectorized, and parallelizable design makes it a natural fit. Its speed ups mean you can experiment more freely, running larger simulations or sampling the parameter space for optimization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How &lt;code&gt;@jit&lt;/code&gt; Compilation Speeds Up Simulation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JAX’s &lt;code&gt;@jit&lt;/code&gt; decorator is a “just-in-time” compilation wrapper. By applying &lt;code&gt;@jit&lt;/code&gt; to your functions (such as the ODE right-hand side), JAX traces the code, compiles it to efficient machine code, and caches it for future use. For functions called thousands or millions of times (like those updating a projectile’s state at each integration step), this can yield &lt;em&gt;orders of magnitude&lt;/em&gt; speed-up over standard Python or NumPy.&lt;/p&gt;
&lt;p&gt;Example usage from the code:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jax&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jit&lt;/span&gt;

&lt;span class="nd"&gt;@jit&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# ... derivative computation ...&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dydt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first call to &lt;code&gt;rhs&lt;/code&gt; incurs compilation overhead, but future calls run at compiled speed. This is particularly valuable inside ODE solvers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using JAX’s &lt;code&gt;odeint&lt;/code&gt;: Syntax, Advantages, and Hardware Acceleration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While SciPy provides &lt;code&gt;scipy.integrate.odeint&lt;/code&gt; for ordinary differential equations, JAX brings its own &lt;code&gt;jax.experimental.ode.odeint&lt;/code&gt;, designed for stateless, compiled, and differentiable integration.&lt;/p&gt;
&lt;p&gt;Syntax example:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jax.experimental.ode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;odeint&lt;/span&gt;
&lt;span class="n"&gt;traj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;odeint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tgrid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;
- &lt;strong&gt;Statelessness:&lt;/strong&gt; JAX expects pure functions, which eliminates hard-to-find bugs from global state mutations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hardware Acceleration:&lt;/strong&gt; Integrations can transparently run on GPU/TPU if available.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Differentiability:&lt;/strong&gt; Enables sensitivity analysis, parameter optimization, or training.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Seamless Integration:&lt;/strong&gt; Because both your physics (ODE) code and simulation harness share the same JAX design, everything from drag models to scoring functions can be compiled and differentiated.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Contrasting with SciPy’s ODE Solvers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While SciPy’s &lt;code&gt;odeint&lt;/code&gt; is a powerful and widely used tool, it has limitations in terms of performance and flexibility compared to JAX. Here’s a quick comparison:&lt;/p&gt;
&lt;table border="1" style="width: 100%;" class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr style="text-align: right;"&gt;
      &lt;th&gt;Feature&lt;/th&gt;
      &lt;th&gt;SciPy (odeint)&lt;/th&gt;
      &lt;th&gt;JAX (odeint)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Backend&lt;/td&gt;
      &lt;td&gt;Python/Fortran, CPU&lt;/td&gt;
      &lt;td&gt;Compiled (XLA), GPU/TPU&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Stateful?&lt;/td&gt;
      &lt;td&gt;Yes (more impurities)&lt;/td&gt;
      &lt;td&gt;Pure functional&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Differentiable?&lt;/td&gt;
      &lt;td&gt;No (not natively)&lt;/td&gt;
      &lt;td&gt;Yes (via Autograd)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Performance&lt;/td&gt;
      &lt;td&gt;Good (CPU only)&lt;/td&gt;
      &lt;td&gt;Very high (GPU/CPU)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Debugging support&lt;/td&gt;
      &lt;td&gt;Easier, familiar&lt;/td&gt;
      &lt;td&gt;Trickier; pure code&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Tips, Pitfalls, and Debugging When Porting ODEs to JAX&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use only JAX-aware APIs:&lt;/strong&gt; Replace NumPy (and math functions) with their &lt;code&gt;jax.numpy&lt;/code&gt; equivalents (&lt;code&gt;jnp&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Function purity:&lt;/strong&gt; Avoid side effects: no printing, mutation, or global state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch for unsupported types:&lt;/strong&gt; JAX functions operate on arrays, not lists or native Python scalars.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Initial compilation time:&lt;/strong&gt; The first JIT invocation is slow due to compilation overhead; don’t mistake this for actual simulation speed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; Use the function &lt;em&gt;without&lt;/em&gt; &lt;code&gt;@jit&lt;/code&gt; for initial debugging. Once it works, add &lt;code&gt;@jit&lt;/code&gt; for speed. JAX’s error messages are improving, but complex bugs are best isolated in un-jitted code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gradual Migration:&lt;/strong&gt; If moving existing NumPy/SciPy code to JAX, port functions step by step, testing thoroughly at each stage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;JAX rewards this functional, stateless approach with unparalleled speed, scalability, and extendability. For physical simulation projects (where thousands of ODE solves may be required), JAX is a technological force-multiplier: pushing boundaries for researchers, engineers, and anyone seeking both scientific rigor and computational speed.&lt;/p&gt;
&lt;h3&gt;Numerical Simulation of Projectile Motion&lt;/h3&gt;
&lt;p&gt;The simulation of projectile motion involves several key steps, each of which is crucial for achieving accurate and reliable results. Below, we outline the process, including the mathematical formulation, numerical integration, and root-finding techniques.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating a Time Grid and Handling Step Size&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To integrate the equations of motion, we first discretize time into a grid. The time grid's resolution (number of samples) affects both accuracy and computational cost. In the example code, a trajectory is simulated for up to 4 seconds with 2000 sample points. This yields time steps small enough to resolve rapid changes in motion (such as during the initial phase of flight) without introducing significant numerical error or wasteful oversampling.&lt;/p&gt;
&lt;p&gt;Carefully choosing maximum simulation time and the number of points is crucial; a short simulation might end before the projectile lands, while too long or too fine a grid wastes computation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generating the Trajectory with JAX’s ODE Solver&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The simulation leverages JAX’s &lt;code&gt;odeint&lt;/code&gt; (a high-performance ODE integrator), which takes the system’s right-hand side (RHS) function, initial conditions, and the time grid. At each step, it updates the projectile’s state vector &lt;code&gt;[x, z, vx, vz]&lt;/code&gt;, considering drag, gravity, and velocity. The result is a trajectory array detailing the evolution of the projectile's position and velocity throughout its flight.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using Root-Finding (Bisection Method) to Hit a Specified Distance&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For a specified target distance, we need to determine the precise launch angle that will cause the projectile to land at the target. This is a root-finding problem: find the angle where &lt;code&gt;height_at_target(angle)&lt;/code&gt; equals ground level. The bisection method is preferred here: it’s robust, doesn’t require derivatives, and is simple to implement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start with low and high angle bounds.&lt;/li&gt;
&lt;li&gt;Iteratively bisect the interval, checking if the projectile overshoots or falls short at the target distance.&lt;/li&gt;
&lt;li&gt;Shrink the interval toward the angle whose trajectory lands closest to the desired point.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Numerical Interpolation for Accurate Landing Position&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even with fine time resolution, the discrete trajectory samples may bracket the exact target distance without matching it precisely. Simple linear interpolation between the two samples closest to the desired distance estimates the projectile’s true elevation at the target. This provides a continuous, high-accuracy solution without excessive oversampling.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Practical Considerations: Numerical Stability and Accuracy vs. Speed&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stability:&lt;/strong&gt; Too large a time step risks instability (e.g., oscillating or diverging solutions). It's always wise to verify convergence by slightly varying sample count.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed vs. Accuracy:&lt;/strong&gt; Finer grids increase computational cost, but with tools like JAX and just-in-time compiling, you can afford higher resolution without significant slowdowns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reproducibility:&lt;/strong&gt; Always document or fix the random seeds, simulation duration, and grid size for consistent results.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example: Numerical Solution in Action&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let’s demonstrate these principles by implementing the full integration, root-finding, and interpolation steps for a simple projectile simulation. &lt;/p&gt;
&lt;p&gt;Here is the projectile's computed trajectory and the determined launch angle for a 500 m target:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://tinycomputers.io/images/0bf49bf00-1223-4046-94b3-6577b3fe3797.png" style="width: 640px; box-shadow: 0 30px 40px rgba(0,0,0,.1); float: right; padding: 20px 20px 20px 20px;"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Analysis and Interpretation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time grid and integration step:&lt;/strong&gt; The simulation used 2000 time samples over 4 seconds, achieving enough resolution to ensure accuracy without overloading computation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trajectory generation:&lt;/strong&gt; The ODE integrator (&lt;code&gt;odeint&lt;/code&gt;) produced an array representing the projectile's flight path, accounting for both gravity and drag at each instant.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Root-finding:&lt;/strong&gt; The bisection method iteratively determined the precise hold-over angle needed to strike the target. In this case, the solver found a solution of approximately 0.136 degrees.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Numerical interpolation:&lt;/strong&gt; To accurately determine where the projectile crosses the target distance, the height was linearly interpolated between the two closest trajectory points.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practical tradeoff:&lt;/strong&gt; This workflow offers excellent reproducibility, efficient computation, and a reliable approach for balancing speed and accuracy. It can be easily adapted for parameter sweeps or “what-if” analyses in both ballistics and related domains.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Conclusion: The Power of JAX for Scientific Simulation&lt;/h3&gt;
&lt;p&gt;Over the course of this article, we walked through an end-to-end approach for simulating projectile motion using Python and modern computational techniques. We started by constructing the mathematical model, defining state vectors that track position and velocity while accounting for the effects of gravity and drag. By formulating the system as an ordinary differential equation (ODE), we created a robust foundation suitable for simulation, experimentation, and extension.&lt;/p&gt;
&lt;p&gt;We then discussed how to structure simulation code for clarity and extensibility, using configuration dictionaries for initial conditions and modular functions for dynamics and drag. The heart of the technical implementation leveraged JAX’s powerful features: just-in-time compilation (&lt;code&gt;@jit&lt;/code&gt;) and its high-performance, stateless &lt;code&gt;odeint&lt;/code&gt; integrator. This brings significant speed-ups, enables seamless experimentation through rapid parameter sweeps, and offers the added benefit of differentiability for optimization and machine learning applications.&lt;/p&gt;
&lt;p&gt;One of JAX’s greatest strengths is how it enables true exploratory numerical simulation. By harnessing hardware acceleration (CPU, GPU, TPU), researchers and engineers can quickly run many simulations, test out “what-if” questions, and iterate on their models, all from a single, flexible codebase. JAX’s functional purity ensures that results are reproducible and code remains maintainable, even as complexity increases.&lt;/p&gt;
&lt;p&gt;Looking ahead, this simulation framework can be further expanded in various directions:
- &lt;strong&gt;Batch simulations:&lt;/strong&gt; Run large sets of parameter combinations in parallel, enabling Monte Carlo analysis or uncertainty quantification.
- &lt;strong&gt;Stochastic effects:&lt;/strong&gt; Incorporate randomness (e.g., wind gusts, environmental fluctuation) for more realistic or robust predictions.
- &lt;strong&gt;Optimization:&lt;/strong&gt; Use automatic differentiation with JAX to tune system parameters for specific performance goals: maximizing range, minimizing dispersion, or matching experimental data.
- &lt;strong&gt;Higher dimensions:&lt;/strong&gt; Expand from 2D to full 3D trajectories or add additional physics (e.g., spin drift, Coriolis force).&lt;/p&gt;
&lt;p&gt;This modern, JAX-powered workflow not only accelerates traditional ballistics work but also positions researchers to innovate rapidly in research, engineering, and even interactive applications. The principles and techniques described here generalize to many fields whenever clear models, efficiency, and the freedom to explore “what if” truly matter.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# First, let's import JAX and related libraries.&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jax.numpy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jnp&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jax&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jit&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jax.experimental.ode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;odeint&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;numpy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;matplotlib.pyplot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;plt&lt;/span&gt;

&lt;span class="c1"&gt;# CONFIGURATION&lt;/span&gt;
&lt;span class="n"&gt;CONFIG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'target_distance_m'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;500.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     
    &lt;span class="s1"&gt;'muzzle_height_m'&lt;/span&gt;  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      
    &lt;span class="s1"&gt;'muzzle_velocity_mps'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;920.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
    &lt;span class="s1"&gt;'mass_kg'&lt;/span&gt;          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.00402&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
    &lt;span class="s1"&gt;'diameter_m'&lt;/span&gt;       &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.00570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
    &lt;span class="s1"&gt;'air_density_kgpm3'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.225&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'gravity_mps2'&lt;/span&gt;     &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;9.80665&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'drag_family'&lt;/span&gt;      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'G1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'max_time_s'&lt;/span&gt;       &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'samples'&lt;/span&gt;          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Derived quantities&lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'gravity_mps2'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;rho_air&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'air_density_kgpm3'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'mass_kg'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'diameter_m'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;v0_muzzle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'muzzle_velocity_mps'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# G1 drag table (Mach → Cd)&lt;/span&gt;
&lt;span class="n"&gt;_g1_mach&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;1.45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;1.90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;3.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;4.80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;5.00&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;_g1_cd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="mf"&gt;0.127&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.132&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.138&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.144&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.151&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.159&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.166&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.173&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.181&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.188&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.195&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.202&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;0.209&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.216&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.223&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.230&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.238&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.245&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.252&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.340&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.380&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.394&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;0.370&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.340&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.304&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.290&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.270&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.260&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.230&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;0.200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.195&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.185&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.175&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.170&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.165&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.155&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.147&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.144&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;0.141&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.138&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.135&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.132&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.130&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nd"&gt;@jit&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;drag_cd_g1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;mach&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;343.0&lt;/span&gt;
    &lt;span class="n"&gt;Cd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jnp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mach&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_g1_mach&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_g1_cd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_g1_cd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_g1_cd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Cd&lt;/span&gt;

&lt;span class="n"&gt;drag_cd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drag_cd_g1&lt;/span&gt;

&lt;span class="c1"&gt;# ODE RHS&lt;/span&gt;
&lt;span class="nd"&gt;@jit&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="n"&gt;v_mag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jnp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vz&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1e-9&lt;/span&gt;
    &lt;span class="n"&gt;Cd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drag_cd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rho_air&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Cd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;ax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vx&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;az&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fd&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vz&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;v_mag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jnp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;vx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;az&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Shooting trajectory&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;shoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle_rad&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;vx0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v0_muzzle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle_rad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vz0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v0_muzzle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle_rad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;y0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'muzzle_height_m'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;vx0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vz0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;tgrid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'max_time_s'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'samples'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;traj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;odeint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tgrid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;traj&lt;/span&gt;

&lt;span class="c1"&gt;# Height at target function for bisection method&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;height_at_target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;traj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;traj&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;traj&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;searchsorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'target_distance_m'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1e3&lt;/span&gt;
    &lt;span class="n"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;z0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;z1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;z0&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;z0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'target_distance_m'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Find solution angle&lt;/span&gt;
&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deg2rad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deg2rad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;height_at_target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;
&lt;span class="n"&gt;angle_solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"Launch angle needed (G1 drag): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rad2deg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle_solution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;.3f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Plot final trajectory&lt;/span&gt;
&lt;span class="n"&gt;traj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle_solution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;traj&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;traj&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'target_distance_m'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Projectile trajectory'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;axvline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'target_distance_m'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'gray'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'target_distance_m'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; m"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;axhline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'k'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"5.56 mm (G1 drag) - hold-over &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rad2deg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle_solution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;.2f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Range (m)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Height (m)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>auto-differentiation</category><category>ballistics</category><category>bisection method</category><category>code modularity</category><category>drag modeling</category><category>exploratory analysis</category><category>hardware acceleration</category><category>jax</category><category>just-in-time compilation</category><category>matplotlib</category><category>numerical integration</category><category>ode solver</category><category>parameter sweep</category><category>performance optimization</category><category>projectile simulation</category><category>python</category><category>root-finding</category><category>scientific computing</category><category>simulation</category><category>simulation visualization</category><category>trajectory analysis</category><category>trajectory plotting</category><guid>https://tinycomputers.io/posts/optimizing-scientific-simulations-jax-powered-ballistic-calculations.html</guid><pubDate>Thu, 15 May 2025 20:53:31 GMT</pubDate></item><item><title>Unlocking Insights into Your Amazon S3 Buckets with S3STAT</title><link>https://tinycomputers.io/posts/unlocking-insights-into-your-amazon-s3-buckets-with-s3stat.html?utm_source=feed&amp;utm_medium=rss&amp;utm_campaign=rss</link><dc:creator>A.C. Jokela</dc:creator><description>&lt;div class="audio-widget"&gt;
&lt;div class="audio-widget-header"&gt;
&lt;span class="audio-widget-icon"&gt;🎧&lt;/span&gt;
&lt;span class="audio-widget-label"&gt;Listen to this article&lt;/span&gt;
&lt;/div&gt;
&lt;audio controls preload="metadata"&gt;
&lt;source src="https://tinycomputers.io/unlocking-insights-into-your-amazon-s3-buckets-with-s3stat_tts.mp3" type="audio/mpeg"&gt;
&lt;/source&gt;&lt;/audio&gt;
&lt;div class="audio-widget-footer"&gt;10 min · AI-generated narration&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src="https://tinycomputers.io/images/s3stat0.png" style="zoom: 50%; text-align: left; float: left; padding: 50px;" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;S3STAT is a powerful tool designed to analyze Amazon S3 bucket usage patterns, providing valuable insights into traffic patterns, error rates, and geographic distribution. Its primary purpose is to help users optimize their S3 bucket performance, improve security, and reduce costs. By utilizing S3STAT, users can gain a deeper understanding of how their S3 buckets are being accessed and utilized, allowing them to make informed decisions about their cloud storage infrastructure. The benefits of using S3STAT are numerous, including the ability to identify and troubleshoot issues quickly, optimize content delivery for global audiences, and detect potential security threats. Overall, S3STAT is an essential tool for anyone looking to unlock the full potential of their Amazon S3 buckets and ensure they are running efficiently and effectively. With its robust features and ease of use, S3STAT has become a go-to solution for many organizations seeking to optimize their cloud storage operations.&lt;/p&gt;
&lt;p&gt;Getting started with S3STAT is a straightforward and easy process, requiring minimal effort and technical expertise. The setup process is well-documented by S3STAT, with clear and concise instructions that guide users through each step, ensuring a seamless experience. Additionally, S3STAT requires only minimal permissions to function, making it a secure and low-risk addition to any Amazon S3 infrastructure. Overall, the ease of use for getting started with S3STAT is one of its most significant advantages, allowing users to quickly and easily begin analyzing their S3 bucket usage patterns and gaining valuable insights into their cloud storage operations.&lt;/p&gt;
&lt;p&gt;S3STAT provides a comprehensive range of reports that offer in-depth insights into Amazon S3 bucket usage patterns. The reports include detailed information on traffic patterns and bandwidth usage, allowing users to understand how their S3 buckets are being accessed and utilized over time. This information can be used to identify peak usage periods, optimize content delivery, and reduce costs by optimizing storage and data transfer. Additionally, S3STAT reports provide error rates and access denied messages, enabling users to quickly identify and troubleshoot issues with their S3 buckets, such as permissions problems or corrupted files.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://tinycomputers.io/images/s3stat1.png" style="zoom: 50%; text-align: left; float: left; padding: 50px;" loading="lazy"&gt;&lt;/p&gt;
&lt;p&gt;The geographic distribution report provides a detailed breakdown of where traffic is coming from, allowing users to understand their global reach and optimize content delivery for different regions. The user agent analysis report provides information on the types of devices and browsers being used to access S3 buckets, enabling users to tailor their content and optimize their applications for specific platforms. By analyzing these reports, users can gain a deeper understanding of their S3 bucket usage patterns and make informed decisions about how to optimize their cloud storage infrastructure.&lt;/p&gt;
&lt;p&gt;For example, by analyzing traffic patterns and bandwidth usage, a user may discover that their S3 bucket is experiencing high levels of traffic during certain hours of the day, and adjust their content delivery strategy accordingly. Similarly, by examining error rates and access denied messages, a user may identify a permissions issue that is preventing users from accessing certain files, and take corrective action to resolve the problem. By leveraging the insights provided by S3STAT reports, users can optimize their S3 bucket performance, improve security, and reduce costs, ultimately leading to more efficient and effective cloud storage operations. Furthermore, the detailed information provided by S3STAT reports enables users to refine their strategies over time, making data-driven decisions that drive business success.&lt;/p&gt;
&lt;p&gt;S3STAT provides a detailed analysis of traffic patterns, allowing users to gain a deeper understanding of how their Amazon S3 buckets are being accessed and utilized. One key aspect of this analysis is the breakdown of request types, including GET, PUT, DELETE, and other operations. By examining these request types, users can identify trends and patterns in how their S3 buckets are being used, such as whether they are primarily being used for storing and retrieving files, or if they are being used for more complex operations like data processing and analysis.&lt;/p&gt;
&lt;p&gt;In addition to request types, S3STAT also provides detailed information on data transfer volumes and bandwidth usage. This information can be used to identify peak usage periods, optimize content delivery, and reduce costs by optimizing storage and data transfer. For example, if a user notices that their S3 bucket is experiencing high levels of traffic during certain hours of the day, they may be able to adjust their content delivery strategy to take advantage of lower-cost storage options during off-peak hours.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://tinycomputers.io/images/s3stat2.png" style="zoom: 50%; text-align: left; float: left; padding: 50px;" loading="lazy"&gt;
S3STAT also provides time of day and day of week analysis, allowing users to understand how their S3 bucket usage patterns vary over time. This information can be used to optimize S3 bucket performance and reduce costs by identifying opportunities to cache frequently accessed content, use Content Delivery Networks (CDNs) to distribute content more efficiently, or adjust storage class and retention policies to match changing usage patterns. For instance, if a user notices that their S3 bucket is experiencing high levels of traffic on weekdays but low levels of traffic on weekends, they may be able to adjust their storage class and retention policies to take advantage of lower-cost options during periods of low usage.&lt;/p&gt;
&lt;p&gt;By analyzing this data, users can optimize their S3 bucket performance and reduce costs in a variety of ways. For example, they may be able to identify opportunities to use Amazon S3's Infrequent Access storage class, which provides a lower-cost storage option for data that is not frequently accessed. They may also be able to use Amazon S3's lifecycle policies to automatically transition data to lower-cost storage classes or delete it after a certain period of time. Additionally, users can use this data to optimize their content delivery strategy, such as by using CDNs to distribute content more efficiently or caching frequently accessed content to reduce the number of requests made to their S3 bucket.&lt;/p&gt;
&lt;p&gt;Furthermore, analyzing traffic patterns with S3STAT can also help users identify potential security risks and take proactive measures to mitigate them. For instance, if a user notices unusual patterns of access or high levels of traffic from unknown sources, they may be able to take steps to secure their S3 bucket and prevent unauthorized access. By leveraging the detailed insights provided by S3STAT, users can optimize their S3 bucket performance, reduce costs, and improve security, ultimately leading to more efficient and effective cloud storage operations. With this level of visibility and control, users can make data-driven decisions that drive business success and ensure the long-term health and security of their Amazon S3 infrastructure.&lt;/p&gt;
&lt;p&gt;S3STAT provides valuable geographic insights into where your Amazon S3 traffic is coming from, allowing you to understand your global reach and optimize content delivery for different regions. By analyzing the geographic distribution of your S3 traffic, you can identify areas with high demand and adjust your content delivery strategy accordingly. For example, if you notice that a significant portion of your traffic is coming from Europe, you may want to consider using Amazon S3's European data centers or partnering with a Content Delivery Network (CDN) that has a strong presence in the region. This can help reduce latency and improve the overall user experience for your global audience.&lt;/p&gt;
&lt;p&gt;In addition to geographic analysis, S3STAT also provides error analysis capabilities that help identify issues with S3 requests, including 404 errors, access denied messages, timeouts, and other connection issues. By analyzing this data, you can quickly troubleshoot and resolve problems, reducing downtime and improving the overall reliability of your S3-based applications and services. For example, if you notice a high volume of 404 errors coming from a specific region, you may want to investigate whether there are issues with your DNS configuration or if there are problems with your content being cached incorrectly.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://tinycomputers.io/images/s3stat3.png" style="zoom: 50%; text-align: left; float: left; padding: 50px;" loading="lazy"&gt;
To troubleshoot and resolve problems quickly, you can use S3STAT's error analysis data to identify patterns and trends in your S3 request logs. For instance, you may notice that a particular type of error is occurring frequently during peak hours, indicating a potential issue with your application's scalability or performance under load. By using this data to inform your troubleshooting efforts, you can quickly identify the root cause of problems and take corrective action to prevent them from happening in the future. This can help reduce the mean time to detect (MTTD) and mean time to resolve (MTTR) issues, ultimately leading to improved uptime and increased customer satisfaction.&lt;/p&gt;
&lt;p&gt;S3STAT provides valuable insights into who is accessing your Amazon S3 objects, allowing you to monitor and control access to your sensitive data. By analyzing the access logs, you can identify patterns and trends in user behavior, detect potential security threats, and take proactive measures to prevent unauthorized access.&lt;/p&gt;
&lt;p&gt;With S3STAT, you can use this data to detect potential security threats such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unusual access patterns or locations&lt;/li&gt;
&lt;li&gt;Access attempts from unknown or untrusted IP addresses&lt;/li&gt;
&lt;li&gt;Multiple failed login attempts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also use this data to take proactive measures to prevent unauthorized access, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implementing bucket policies and access control lists (ACLs) to restrict access to sensitive data&lt;/li&gt;
&lt;li&gt;Enabling versioning and object locking to prevent accidental or malicious deletion of objects&lt;/li&gt;
&lt;li&gt;Configuring S3 to send notifications when certain events occur, such as when an object is accessed or modified&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, S3STAT's security insights can help you comply with regulatory requirements and industry standards for data access and security. By monitoring and controlling access to your S3 objects, you can ensure the integrity and confidentiality of your sensitive data and maintain the trust of your customers and stakeholders.&lt;/p&gt;
&lt;p&gt;To maximize your insights with S3STAT, follow these best practices:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Regularly review reports and analyze data&lt;/strong&gt;: Schedule regular reviews of your S3STAT reports to stay on top of trends, patterns, and anomalies in your S3 usage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use data to inform decisions about S3 bucket optimization and performance&lt;/strong&gt;: Use S3STAT's insights to optimize your S3 bucket configuration, such as adjusting storage classes, lifecycle policies, and caching strategies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrate with other AWS services&lt;/strong&gt;: Combine S3STAT data with other AWS services, like CloudWatch and CloudTrail, to gain a more comprehensive understanding of your AWS usage and performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor and adjust&lt;/strong&gt;: Continuously monitor your S3STAT data and adjust your optimization strategies as needed to ensure optimal performance, security, and cost-effectiveness.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By following these best practices, you can unlock the full potential of S3STAT and make data-driven decisions to optimize your Amazon S3 usage, improve performance, and reduce costs. Regular review and analysis of S3STAT data will help you identify areas for improvement and ensure that your S3 buckets are running efficiently and securely.&lt;/p&gt;
&lt;p&gt;S3STAT is a powerful tool that provides unparalleled insights into your Amazon S3 bucket usage patterns. With its ease of use and comprehensive reporting capabilities, S3STAT makes it simple to unlock the full potential of your S3 buckets. By leveraging S3STAT's analytics and monitoring features, you can optimize performance, enhance security, and reduce costs. Whether you're looking to improve data transfer speeds, detect potential security threats, or streamline your storage infrastructure, S3STAT has got you covered. With its ability to provide detailed insights into your S3 usage patterns, S3STAT is an essential tool for any organization looking to get the most out of their Amazon S3 investment. By using S3STAT, you can make data-driven decisions and take your S3 bucket management to the next level, ensuring optimal performance, security, and cost-effectiveness.&lt;/p&gt;</description><category>access control</category><category>amazon s3</category><category>aws services</category><category>bucket management</category><category>cloud computing</category><category>cloud storage</category><category>content delivery</category><category>cost optimization</category><category>data analytics</category><category>data insights</category><category>data transfer</category><category>digital transformation</category><category>error analysis</category><category>geographic analysis</category><category>innovation</category><category>it management</category><category>performance optimization</category><category>s3stat</category><category>security monitoring</category><category>storage infrastructure</category><category>technology</category><category>troubleshooting</category><guid>https://tinycomputers.io/posts/unlocking-insights-into-your-amazon-s3-buckets-with-s3stat.html</guid><pubDate>Tue, 31 Dec 2024 21:12:27 GMT</pubDate></item></channel></rss>