NetCDF

Descrição

De acordo com a página do NetCDF, NetCDF (Network Common Data Form) é um conjunto de bibliotecas e formatos de dados independentes de máquina que suportam a criação, acesso e compartilhamento de dados científicos orientados a arrays. É também um padrão comunitário para compartilhamento de dados científicos.

Versões Disponíveis

  • netcdf/c/4.6.3 (default)

  • netcdf/fortran/4.4.5 (default)

Carregando Módulos

# Para C
module load netcdf/c/4.6.3

# Para Fortran
module load netcdf/fortran/4.4.5

# Para ambos
module load netcdf/c/4.6.3
module load netcdf/fortran/4.4.5

Compilação com NetCDF

C

compile_netcdf_c.sh
#!/bin/bash
#SBATCH -J compile_netcdf_c
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 00:10:00
#SBATCH --mem=2G

export INPUT="read_write.c"
export OUTPUT="read_write"

module load netcdf/c/4.6.3

job-nanny gcc -o read_write read_write.c -lnetcdf

Fortran

compile_netcdf_fortran.sh
#!/bin/bash
#SBATCH -J compile_netcdf_fortran
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 00:10:00
#SBATCH --mem=2G

export INPUT="read_write.f90"
export OUTPUT="read_write"

module load netcdf/fortran/4.4.5

job-nanny gfortran -o read_write read_write.f90 -lnetcdff

Exemplo de Código C

write_netcdf.c
#include <netcdf.h>
#include <stdio.h>
#include <stdlib.h>

#define NDIMS 2
#define NX 6
#define NY 12

int main() {
    int ncid, x_dimid, y_dimid, varid;
    int dimids[NDIMS];
    int data[NX][NY];
    int retval;

    // Criar dados
    for (int i = 0; i < NX; i++)
        for (int j = 0; j < NY; j++)
            data[i][j] = i * NY + j;

    // Criar arquivo
    if ((retval = nc_create("simple.nc", NC_CLOBBER, &ncid)))
        return retval;

    // Definir dimensões
    if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid)))
        return retval;
    if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid)))
        return retval;

    // Definir variável
    dimids[0] = x_dimid;
    dimids[1] = y_dimid;
    if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS,
                             dimids, &varid)))
        return retval;

    // Sair do modo de definição
    if ((retval = nc_enddef(ncid)))
        return retval;

    // Escrever dados
    if ((retval = nc_put_var_int(ncid, varid, &data[0][0])))
        return retval;

    // Fechar arquivo
    if ((retval = nc_close(ncid)))
        return retval;

    printf("Arquivo simple.nc criado com sucesso!\n");
    return 0;
}

Exemplo de Código Fortran

write_netcdf.f90
program write_netcdf
  use netcdf
  implicit none

  integer :: ncid, x_dimid, y_dimid, varid
  integer, parameter :: NX = 6, NY = 12
  integer :: data(NX, NY)
  integer :: i, j

  ! Criar dados
  do i = 1, NX
    do j = 1, NY
      data(i,j) = (i-1)*NY + (j-1)
    end do
  end do

  ! Criar arquivo
  call check( nf90_create("simple_f.nc", NF90_CLOBBER, ncid) )

  ! Definir dimensões
  call check( nf90_def_dim(ncid, "x", NX, x_dimid) )
  call check( nf90_def_dim(ncid, "y", NY, y_dimid) )

  ! Definir variável
  call check( nf90_def_var(ncid, "data", NF90_INT, &
                           (/ x_dimid, y_dimid /), varid) )

  ! Sair do modo de definição
  call check( nf90_enddef(ncid) )

  ! Escrever dados
  call check( nf90_put_var(ncid, varid, data) )

  ! Fechar arquivo
  call check( nf90_close(ncid) )

  print *, "Arquivo simple_f.nc criado com sucesso!"

contains
  subroutine check(status)
    integer, intent(in) :: status
    if (status /= nf90_noerr) then
      print *, trim(nf90_strerror(status))
      stop
    end if
  end subroutine check
end program write_netcdf

Script para Processamento em Lote

submit_netcdf_process.sh
#!/bin/bash
#SBATCH -J netcdf_process
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 04:00:00
#SBATCH --mem=8G

export INPUT="dados/*.nc"
export OUTPUT="processados/"

module load netcdf/c/4.6.3
module load netcdf4-python

mkdir -p processados

cat > process_netcdf.py << 'EOF'
import netCDF4 as nc
import numpy as np
import glob
import os

# Processar todos os arquivos .nc
for arquivo in glob.glob('dados/*.nc'):
    print(f"Processando {arquivo}...")

    # Abrir arquivo
    ds = nc.Dataset(arquivo, 'r')

    # Ler variáveis
    for var_name in ds.variables:
        var = ds.variables[var_name]

        # Calcular estatísticas
        data = var[:]
        if data.size > 0:
            media = np.mean(data)
            desvio = np.std(data)
            minimo = np.min(data)
            maximo = np.max(data)

            print(f"  {var_name}: média={media:.3f}, "
                  f"desvio={desvio:.3f}, min={minimo:.3f}, max={maximo:.3f}")

    # Salvar resultados
    nome_base = os.path.basename(arquivo)
    with open(f"processados/{nome_base}.txt", 'w') as f:
        f.write(f"Análise de {arquivo}\n")
        for var_name in ds.variables:
            var = ds.variables[var_name]
            data = var[:]
            if data.size > 0:
                f.write(f"{var_name}: {np.mean(data):.6f} "
                       f"{np.std(data):.6f}\n")

    ds.close()
EOF

python3 process_netcdf.py

Ferramentas de Linha de Comando

O NetCDF inclui utilitários de linha de comando úteis:

# Informações sobre o arquivo
ncdump -h arquivo.nc

# Extrair dados em formato texto
ncdump arquivo.nc > arquivo.cdl

# Comparar arquivos
ncdiff -v var arquivo1.nc arquivo2.nc diff.nc

# Juntar arquivos no tempo
ncrcat arquivo1.nc arquivo2.nc arquivo3.nc saida.nc

Job Array para Processamento Paralelo

submit_netcdf_array.sh
#!/bin/bash
#SBATCH -J netcdf_array
#SBATCH --array=1-20
#SBATCH -N 1
#SBATCH -n 1
#SBATCH -t 02:00:00
#SBATCH --mem=4G

ARQUIVOS=($(ls dados/*.nc))
ARQUIVO=${ARQUIVOS[$SLURM_ARRAY_TASK_ID-1]}

export INPUT="$ARQUIVO"
export OUTPUT="saida_${SLURM_ARRAY_TASK_ID}/"

module load netcdf/c/4.6.3

mkdir -p saida_${SLURM_ARRAY_TASK_ID}
cd saida_${SLURM_ARRAY_TASK_ID}

# Extrair metadados
ncdump -h ../$ARQUIVO > metadados.txt

# Extrair variáveis específicas
ncdump -v temperatura ../$ARQUIVO > temperatura.txt

Referências

Ver também