Skip to content

File atm_io.cpp

File List > components > emulator_comps > eatm > src > impl > atm_io.cpp

Go to the documentation of this file

#include "atm_io.hpp"
#include "../../../common/src/emulator_io.hpp"
#include <cmath>

namespace emulator {
namespace impl {

// Physical constants (currently unused but kept for reference)
// static constexpr double RDAIR = 287.04;   // Dry air gas constant [J/K/kg]
// static constexpr double STEBOL = 5.67e-8; // Stefan-Boltzmann [W/m2/K4]

bool read_atm_initial_conditions(const std::string &filename,
                                 int num_global_cols, int num_local_cols,
                                 const std::vector<int> &col_gids,
                                 const std::vector<double> &lat,
                                 AtmFieldManager &fields,
                                 const std::vector<std::string> &required_vars,
                                 Logger &logger, bool is_root) {
  (void)lat; // Currently unused

  if (is_root) {
    logger.info("Reading IC from: " + filename);
  }

  // Open the IC file
  int ncid = EmulatorIO::open_file(filename);
  if (is_root && ncid < 0) {
    logger.warn("Failed to open IC file: " + filename);
    return false;
  }

  // Check grid dimensions (typically 180 lat x 360 lon = 64800)
  int nlat = EmulatorIO::get_dim_size(ncid, "latitude");
  int nlon = EmulatorIO::get_dim_size(ncid, "longitude");

  if (is_root) {
    logger.info("IC file grid: " + std::to_string(nlat) + " x " +
                std::to_string(nlon) + " = " + std::to_string(nlat * nlon) +
                " vs expected " + std::to_string(num_global_cols));
  }

  if (nlat * nlon != num_global_cols) {
    logger.error("Grid mismatch! Cannot read IC.");
    EmulatorIO::close_file(ncid);
    return false;
  }

  // Buffer to store global data before distribution
  std::map<std::string, std::vector<double>> global_buffers;

  for (const auto &var_name : required_vars) {
    // Ensure field exists in manager (dynamic creation if needed)
    fields.register_dynamic_field(var_name);

    // Allocate global buffer for reading
    global_buffers[var_name] = std::vector<double>(num_global_cols, 0.0);

    // Try to read from file (3D slice at time 0)
    if (EmulatorIO::read_var_3d_slice(
            ncid, var_name, global_buffers[var_name].data(), nlon, nlat, 0)) {
      if (is_root) {
        logger.info("Read " + var_name);
      }
    } else {
      // Handle missing variables with defaults
      if (var_name == "global_mean_co2") {
        std::fill(global_buffers[var_name].begin(),
                  global_buffers[var_name].end(), 415e-6);
        if (is_root) {
          logger.info("Set default " + var_name + " = 415e-6");
        }
      } else if (var_name == "HGTsfc") {
        std::fill(global_buffers[var_name].begin(),
                  global_buffers[var_name].end(), 0.0);
        if (is_root) {
          logger.info("Set default " + var_name + " = 0.0");
        }
      } else if (var_name == "DSWRFtoa") {
        std::fill(global_buffers[var_name].begin(),
                  global_buffers[var_name].end(), 1361.0);
        if (is_root) {
          logger.info("Set default " + var_name + " = 1361.0");
        }
      } else {
        if (is_root) {
          logger.warn("Failed to read " + var_name + ", using zeros.");
        }
      }
    }
  }

  EmulatorIO::close_file(ncid);

  // Distribute to local partition based on col_gids
  for (const auto &var_name : required_vars) {
    std::vector<double> *local_ptr = fields.get_field_ptr(var_name);
    const auto &global_buf = global_buffers[var_name];

    if (local_ptr) {
      for (int i = 0; i < num_local_cols; ++i) {
        int global_idx = col_gids[i] - 1; // 1-based to 0-based
        if (global_idx >= 0 && global_idx < num_global_cols) {
          (*local_ptr)[i] = global_buf[global_idx];
        }
      }
    }
  }

  if (is_root) {
    logger.info("IC generic read complete.");
  }

  return true;
}

} // namespace impl
} // namespace emulator