Julia Fundamentals

Core Julia programming concepts for scientific computing

Learning Objectives

By the end of this guide, you should be able to:

  • [ ] Create and manipulate arrays using Julia's syntax
  • [ ] Perform mathematical and statistical operations
  • [ ] Use control flow and functions effectively
  • [ ] Apply multiple dispatch patterns
  • [ ] Work with units, measurements, and DataFrames

Arrays, Math & Astrophysical Data

Julia's array and math syntax is similar to MATLAB and Python (NumPy), but with 1-based indexing! This section covers array creation, indexing, math, statistics, and data operations specifically useful for MERA.jl.

Arrays and Indexing (1-based!)

Note: Julia arrays are 1-based (first element is at index 1, not 0). Slicing is inclusive. Broadcasting uses the dot (.) syntax.

TaskJulia CodeNotes
Row vector, col vector[1 2 3], [1; 2; 3]2D shapes (1,3), (3,1)
1D vector, matrix[1, 2, 3], [1 2; 3 4]
Zeros, ones, identityzeros(2,2), ones(2,2), I
Range, linspace, logspace1:2:9, range(0,1,length=10), exp10.(range(log10(1), log10(100), length=5))
Reshape, flattenreshape(A, 3,4), vec(A)
Indexing/slicingA[2:4, 1:2], A[end, 1:end-1]Inclusive ranges
Boolean indexingA[A .> 0]Broadcast comparison

✅ Try This (8-12 minutes)

Exercise: Complete "Working with Arrays" from Julia Academy Link: https://juliaacademy.com/p/intro-to-julia (Section 3) Goal: Master Julia's array syntax, indexing, and operations Time: 8-12 minutes

Interactive Practice: Follow "Julia Arrays Tutorial" Link: https://docs.julialang.org/en/v1/manual/arrays/ Focus: Broadcasting, slicing, multidimensional arrays

Scientific Computing: Work through "Think Julia" Chapter 10 Link: https://benlauwens.github.io/ThinkJulia.jl/latest/book.html Goal: Arrays in scientific computing context

📖 Why This Matters

Foundation for all computation: Arrays are the fundamental data structure in scientific computing. Mastering Julia's array syntax and 1-based indexing is crucial for working with simulation data, observational datasets, and numerical computations in MERA.jl.

Linear Algebra & Math

Julia's LinearAlgebra standard library provides efficient matrix and vector operations. Use using LinearAlgebra to access advanced features.

TaskJulia CodePackage
Matrix multiplyA * B[base]
Elemwise multiplyA .* B[base]
Dot productdot(a, b), a ⋅ bLinearAlgebra
Norm, inv, detnorm(A), inv(A), det(A)LinearAlgebra
Eigenvaluesvals, vecs = eigen(A)LinearAlgebra
SVDU, S, V = svd(A)LinearAlgebra
Choleskycholesky(A)LinearAlgebra
QR factorizationQ, R = qr(A)LinearAlgebra
Solve Ax = bA \ b[base]
FFTfft(x), ifft(X)FFTW

Statistics & Distributions

Julia's Statistics and Distributions packages provide a rich set of statistical tools. Use using Statistics, Distributions to access these functions.

TaskJulia CodePackage
Basic statsmean(x), std(x), var(x)Statistics
Quantilesquantile(x, [0.25,0.5,0.75])Statistics
Correlation/covariancecor(x, y), cov(x, y)Statistics
Histogramfit(Histogram, x, nbins=10)StatsBase
ECDFecdf(x)StatsBase
Statistical testsOneSampleTTest(x), KSTest(x,y)HypothesisTests
Fit distributionsfit(Normal, x), fit(Gamma, x)Distributions
Sample from distributionrand(Normal(0,1), 100)Distributions
Curve fitting (nonlinear)@. model(x, p) = p[1]*exp(-p[2]*x)<br>fit = curve_fit(model, xdata, ydata, p0)LsqFit
Linear regressionfit(LinearModel, @formula(y ~ x), df)GLM
Polynomial fitpolyfit(x, y, deg)Polynomials

Units, Measurements & Astronomy

Julia supports physical units, error propagation, and astronomy-specific calculations via dedicated packages. Use using Unitful, Measurements, AstroLib as needed.

TaskJulia CodePackage
Attach unitsv = 10u"km/s"Unitful
Astronomical unitsd = 1u"pc", t = 1u"yr"UnitfulAstro
Unit conversionuconvert(u"m/s", v)Unitful
Measurement with errora = 3.1 ± 0.2Measurements
Error propagationc = a + b; d = a*bMeasurements
Coordinate conversionradec2gal(ra, dec)AstroLib
Julian datejdcnv(year, month, day)AstroLib

DataFrames & CSV Operations

For tabular data, use DataFrames.jl (like pandas in Python). For CSV I/O, use CSV.jl. Always check for missing data and column types.

TaskJulia ExamplePackage
Create DataFramedf = DataFrame(x=[1,2,3], y=["a","b","c"])DataFrames
Load/save CSVCSV.read("file.csv", DataFrame)<br>CSV.write("out.csv", df)CSV
Quick viewfirst(df, 5), describe(df)DataFrames
Filter rowsfilter(row -> row.x > 1, df)DataFrames
Select columnsselect(df, :x, :y)DataFrames
Group + aggregatecombine(groupby(df, :group), :value => mean)DataFrames
Join tablesinnerjoin(df1, df2, on=:id)DataFrames

Control Flow & Loops

Julia's control flow is similar to Python, but uses end to close blocks. For best performance with arrays, use vectorized/broadcasted operations or type-stable, pre-allocated loops.

Conditionals

if x > 0
    println("positive")
elseif x < 0
    println("negative")
else
    println("zero")
end

For Loops

for i in 1:10
    println(i)
end

# Loop over arrays
for x in arr
    println(x)
end

While Loops

i = 1
while i <= 10
    println(i)
    i += 1
end

Performance Tips for Loops

  • Prefer vectorized or broadcasted operations: y = sin.(x)
  • For custom loops, pre-allocate output arrays: result = similar(x)
  • Use concrete types and avoid changing array types inside loops
  • Use @inbounds to skip bounds checking (safe if you know indices are valid)
  • Avoid global variables in loops; wrap code in functions for speed

Example (fast, 1D):

function square_all!(y, x)
    @inbounds for i in eachindex(x)
        y[i] = x[i]^2
    end
end
y = similar(x)
square_all!(y, x)

Nested Loops for Multi-Dimensional Arrays (Performance)

For best performance with multi-dimensional arrays, use nested loops with @inbounds and access elements in column-major order (first index fastest in Julia). This avoids temporary allocations and leverages Julia's memory layout.

Example (2D array, fill with sum of indices):

function fill_sum!(A)
    @inbounds for j in axes(A,2)   # columns outer
        for i in axes(A,1)         # rows inner (fastest)
            A[i,j] = i + j
        end
    end
end
A = zeros(1000,1000)
fill_sum!(A)

Why: Julia stores arrays in column-major order (like Fortran/MATLAB), so looping with the first index innermost is cache-friendly and fastest.

Functions & Multiple Dispatch

Learning Objectives for This Section

  • [ ] Write functions using Julia's syntax
  • [ ] Understand and apply multiple dispatch
  • [ ] Use broadcasting effectively
  • [ ] Recognize when to use different function forms

Multiple dispatch is Julia's core paradigm: functions can have different methods for different argument types. Use broadcasting (.) to apply functions elementwise.

# Short function syntax
f(x) = x^2

# Multiple dispatch
area(r::Real) = π * r^2                    # Circle
area(w::Real, h::Real) = w * h             # Rectangle
area(triangle::Triangle) = 0.5 * triangle.base * triangle.height

# Broadcasting
sin.(x)                                    # Apply sin to each element
my_function.(array)                        # Works with any function

✅ Try This (10-15 minutes)

Exercise: Complete "Functions and Multiple Dispatch" from Julia Academy Link: https://juliaacademy.com/p/intro-to-julia (Section 6) Goal: Master Julia's multiple dispatch paradigm Time: 10-15 minutes

Deep Dive: Work through "Julia Manual - Methods" Link: https://docs.julialang.org/en/v1/manual/methods/ Focus: Method definition, dispatch, specialization

Advanced Practice: Explore "Think Julia" Chapter 17 Link: https://benlauwens.github.io/ThinkJulia.jl/latest/book.html Goal: Multiple dispatch in practice, type system

📖 Why This Matters

Julia's superpower: Multiple dispatch allows you to write generic, reusable code that automatically chooses the right method based on argument types. This enables seamless interoperability between packages and makes Julia code both flexible and fast.

Multiple Dispatch (Core Paradigm)

Functions can have many methods, chosen by argument types. This is more general than single-dispatch OOP.

# Example: area for different shapes
area(r::Real) = π * r^2              # Circle
area(w::Real, h::Real) = w * h       # Rectangle
struct Triangle; base; height; end
area(t::Triangle) = 0.5 * t.base * t.height

area(2.0)                # Circle
area(3.0, 4.0)           # Rectangle
area(Triangle(3, 4))     # Triangle

Functional Programming

Functions are first-class: pass them as arguments, return them, use anonymous functions.

map(sin, 0:0.1:π)                # Apply sin to each element
filter(isodd, 1:10)               # Keep only odd numbers
reduce(+, 1:100)                  # Sum all numbers
f = x -> x^2 + 1                  # Anonymous function
g(x) = x^2 + 1                    # Named function

Minimal Object Orientation

Julia uses structs for data, but methods are defined outside structs (no classes). Inheritance is limited to abstract types.

abstract type Shape end
struct Circle <: Shape; r; end
struct Rectangle <: Shape; w; h; end
area(s::Shape) = error("not implemented")
area(c::Circle) = π * c.r^2
area(r::Rectangle) = r.w * r.h

shapes = [Circle(1), Rectangle(2,3)]
areas = area.(shapes)   # Broadcasting over array of shapes

Note: There is no method overloading by object (no obj.method()), but you can use do blocks and closures for encapsulation.

Essential One-Liners & Common Patterns

Handy Julia idioms for scientific computing. Try these in the REPL or a notebook.

# Create and manipulate arrays
A = rand(3, 3)                           # 3×3 random matrix
B = A .+ 1                               # Add 1 to each element
C = A * B                                # Matrix multiplication
x = A \ rand(3)                          # Solve linear system

# Statistics and fitting
data = randn(1000)                       # 1000 random samples
μ = mean(data)                           # Sample mean
dist = fit(Normal, data)                 # Fit normal distribution
samples = rand(dist, 100)                # Generate new samples

# Units and measurements
d = 10u"km"                              # Distance with units  
t = 2u"hr"                               # Time with units
v = d/t                                  # Velocity (automatic units)
measurement = 5.0 ± 0.1                  # Value with uncertainty

# File I/O
@save "results.jld2" A B x               # Save multiple variables
@load "results.jld2" A B x               # Load them back
df = CSV.read("data.csv", DataFrame)     # Read CSV file

# Plotting
using CairoMakie
scatter(1:10, rand(10))                  # Quick scatter plot
lines!(1:10, sin.(1:10))                 # Add line to same plot

# Performance and profiling
@btime sort(rand(1000))                  # Benchmark operation
@showprogress for i in 1:10^6 end       # Progress bar

✅ Check Your Understanding - Julia Fundamentals

Before moving on, you should now be able to:

  • [ ] Create and manipulate arrays with 1-based indexing
  • [ ] Use broadcasting (.) for element-wise operations
  • [ ] Write functions and understand multiple dispatch
  • [ ] Work with control flow (loops, conditionals)
  • [ ] Handle DataFrames and CSV files
  • [ ] Apply units and error propagation
  • [ ] Use basic statistical and mathematical functions

🚀 Hands-on Validation (25-30 minutes)

Comprehensive Project: Complete the "Scientific Computing with Julia" workshop Link: https://github.com/mitmath/julia-mit (Problem sets) Goal: Apply all Julia fundamentals in scientific computing context Time: 25-30 minutes

Multiple Dispatch Challenge: Work through "Type System" examples Link: https://docs.julialang.org/en/v1/manual/types/ Focus: Create custom types and methods for scientific data

Performance Validation: Complete "Think Julia" exercises Link: https://benlauwens.github.io/ThinkJulia.jl/latest/book.html (Exercise sections) Goal: Demonstrate efficient Julia programming patterns

🚀 What's Next?

Continue your Julia journey:

  • Need better performance?Performance & Debugging Guide - Learn optimization techniques
  • Want more resources?Additional Resources - Community, tutorials, and references
  • Ready for real projects? → Apply these fundamentals to your scientific computing tasks
  • Working with MERA.jl? → These patterns apply directly to astrophysical simulation analysis

Expected next reading time: 30-60 minutes depending on your focus

📖 Key Takeaways

Julia's core strengths:

  • Multiple dispatch enables elegant, extensible code
  • 1-based indexing matches mathematical notation
  • Broadcasting makes element-wise operations intuitive
  • Type system enables both flexibility and performance
  • Package ecosystem provides specialized tools for every domain