Skip to content

CorrectorNet Architecture

The CorrectorNet is a U-Net convolutional neural network that maps a 101-channel ocean state to a 101-channel additive correction field. It is designed to be computationally efficient while capturing multi-scale spatial structures in ocean dynamics.

U-Net Architecture

The network follows the classic encoder-decoder U-Net design with skip connections:

Input (B, 101, H, W)

    ┌───▼──── ResBlock (101 → 256) ────────────────────────┐
    │                                                       │
    │   Down (256 → 512)                                    │
    │        │                                               │
    │   Down (512 → 1024)                                   │
    │        │                                               │
    │   Down (1024 → 2048)  ← bottleneck                    │
    │        │                                               │
    │   Up (2048+1024 → 1024) ──── skip from Down2 ──────   │
    │        │                                               │
    │   Up (1024+512 → 512) ────── skip from Down1 ──────   │
    │        │                                               │
    │   Up (512+256 → 256) ─────── skip from inc ────────   │
    │        │                                               │
    └────────▼───────────────────────────────────────────────┘

    Conv2d (256 → 101, kernel=1)  ← zero-initialized

   Output (B, 101, H, W)

Channel Dimensions

StageModuleInput ChannelsOutput Channels
Input101
Encoder 1inc (ResBlock)101256
Encoder 2down1 (Down)256512
Encoder 3down2 (Down)5121024
Bottleneckdown3 (Down)10242048
Decoder 1up1 (Up)2048 + 1024 (skip)1024
Decoder 2up2 (Up)1024 + 512 (skip)512
Decoder 3up3 (Up)512 + 256 (skip)256
Outputoutc (Conv2d 1×1)256101

Building Blocks

ResBlock

The ResBlock is a residual convolutional block with two 3×3 convolutions:

x ──┬── Conv2d(3×3, in→mid) ── BatchNorm ── ReLU ── Conv2d(3×3, mid→out) ── BatchNorm ── [+ shortcut] ── ReLU ──→ out

    └── [1×1 Conv + BatchNorm if in_channels ≠ out_channels, else identity]
ResBlock(x)=ReLU(BN(Conv3×3(ReLU(BN(Conv3×3(x)))))+shortcut(x))

The shortcut connection is an identity when in_channels == out_channels, and a 1×1 convolution followed by batch normalization when they differ. This design ensures smooth gradient flow and makes training stable even at depth.

Down (Down-sampling)

python
class Down(nn.Module):
    def __init__(self, in_channels, out_channels):
        self.maxpool_conv = nn.Sequential(
            nn.MaxPool2d(2),
            ResBlock(in_channels, out_channels),
        )

Each Down block halves the spatial resolution via 2×2 max pooling, then applies a ResBlock that doubles the channel dimension. The spatial dimension at the bottleneck is H/8×W/8.

Up (Up-sampling)

python
class Up(nn.Module):
    def __init__(self, in_channels, out_channels, bilinear=True):
        if bilinear:
            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
            self.conv = ResBlock(in_channels, out_channels, in_channels // 2)
        else:
            self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2)
            self.conv = ResBlock(in_channels, out_channels)

Each Up block doubles the spatial resolution (via bilinear interpolation by default) and halves the channel dimension. The upsampled feature map is concatenated with the corresponding encoder skip connection along the channel axis. Padding is applied as needed to handle odd spatial dimensions. The default setting uses bilinear interpolation (bilinear=True), which is more memory-efficient and avoids checkerboard artifacts common with transposed convolutions.

Zero-Initialized Output

A critical design choice: the final 1×1 output convolution is zero-initialized:

python
self.outc = nn.Conv2d(hidden_dim, out_channels, kernel_size=1)
nn.init.constant_(self.outc.weight, 0.0)
nn.init.constant_(self.outc.bias, 0.0)

This ensures that at initialization, the CorrectorNet outputs exactly zero. The initial correction is the identity — the physics model runs unchanged. The network then gradually learns to produce non-zero corrections as training progresses. This trick, originally from the diffusion model literature, prevents the network from disrupting the physics solution early in training and leads to more stable convergence.

Input Channel Breakdown

The 101 input channels correspond to 12 prognostic fields as follows:

#FieldDescriptionVertical LevelsChannels
1uBaroclinic zonal velocity1616
2ubBarotropic zonal velocity1616
3vBaroclinic meridional velocity1616
4vbBarotropic meridional velocity1616
5tTemperature1616
6sSalinity1616
7elSea surface height1
8uaDepth-averaged zonal velocity1
9uabBarotropic depth-avg. zonal vel.1
10vaDepth-averaged meridional velocity1
11vabBarotropic depth-avg. meridional vel.1
Total101

The constant SUPERVISED_KB = 16 determines how many vertical levels are supervised and thus how many channels each 3D field contributes. The dimension transform for 3D fields is:

RH×W×Kpermute(0,3,1,2)RK×H×W

SyncBatchNorm for DDP

For distributed data-parallel training, the network uses SyncBatchNorm to synchronize batch statistics across all GPUs:

python
model = nn.SyncBatchNorm.convert_sync_batchnorm(model)

This is critical when training on 8 GPUs with a per-GPU batch size that might be small (e.g., 1-4). Without synchronized batch statistics, the batch norm layers would see insufficient samples and produce noisy estimates, degrading training stability.

Computational Cost

For a typical grid size of H×W360×240:

MetricApproximate Value
Parameters~18 million
FLOPs (forward pass)~100 GFLOPs per 360×240 input
GPU memory (inference)~200 MB
GPU memory (training with gradients)~600 MB per GPU
Forward pass latency~5 ms on A100

The U-Net architecture is deliberately lightweight. The physics core (POM) is the dominant computational cost, not the neural corrector. The CorrectorNet overhead is approximately 1-2% of the total per-step computation.

Design Rationale

Several design choices merit explanation:

  1. U-Net over alternatives: U-Nets are well-suited for spatial field transformations because the skip connections preserve fine-grained spatial information that would otherwise be lost in the bottleneck. Pure convolutional networks without skip connections or pure MLPs would struggle to capture the multi-scale spatial structures in ocean dynamics.

  2. Symmetric encoder-decoder: The CorrectorNet uses a fully symmetric channel progression (10125651210242048 and back). This ensures the network can represent corrections that are spatially localized (through the encoder path) while maintaining global context (through the decoder path).

  3. No temporal modeling: The CorrectorNet operates purely on instantaneous spatial snapshots — it has no recurrent state, no attention over time, and no memory of previous states. This is intentional: the physics core handles temporal integration. The network's job is only to provide per-timestep spatial corrections.

Released under the MIT License.