Commit 197ad738 authored by Mark Meredith's avatar Mark Meredith
Browse files

Provide better error messages for parsing inputs files

parent dad725ad
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -131,7 +131,9 @@ double signed_distance_3d(const Cylinder &cyl, double xx, double yy,
double signed_distance_3d(const LinearExtrude &lin_ext, double xx, double yy,
                          double zz) {
  // TODO: support height, center and twist
  double sign_z = (0 <= zz && zz <= lin_ext.height) ? 1.0 : 1.0; // unused zz warning workaround
  double sign_z = (0 <= zz && zz <= lin_ext.height)
                      ? 1.0
                      : 1.0; // unused zz warning workaround
  return sign_z * signed_distance_2d(lin_ext.group, xx, yy);
}

+30 −34
Original line number Diff line number Diff line
#include <iostream>

#include "solver.hpp"
#include "solver_impl.hpp"

namespace solver {

std::optional<solver::GeometrySettings> make_geometry(solver::InputInfo ii) {
solver::GeometrySettings make_geometry(solver::InputInfo ii,
                                       std::vector<InputsMessage> &messages) {
  solver::GeometrySettings geo;

  geo.csg_filename = "";
  if (!ii.count(CSG_FILENAME)) {
    require(CSG_FILENAME);
    return std::nullopt;
  }
    add_missing_msg(CSG_FILENAME, messages, std::vector<std::string>{""});
  } else {
    auto csg_filename = std::get<solver::StringArray>(ii[CSG_FILENAME]);
    if (csg_filename.size() != 1) {
    std::cout << CSG_FILENAME << " should only have 1 element" << std::endl;
    return std::nullopt;
      add_msg(CSG_FILENAME, messages, std::vector<std::string>{""});
    } else {
      geo.csg_filename = csg_filename[0];
    }
  }

  if (!ii.count(PROB_LO)) {
    require(PROB_LO);
    return std::nullopt;
    add_missing_msg(PROB_LO, messages, std::vector<double>{});
  }
  if (!ii.count(PROB_HI)) {
    require(PROB_HI);
    return std::nullopt;
    add_missing_msg(PROB_HI, messages, std::vector<double>{});
  }
  if (!ii.count(PERIODIC)) {
    require(PERIODIC);
    return std::nullopt;
    add_missing_msg(PERIODIC, messages, std::vector<double>{0, 0, 0});
  }
  auto lows = std::get<solver::NumberArray>(ii[PROB_LO]);
  auto highs = std::get<solver::NumberArray>(ii[PROB_HI]);
  auto is_periodic = std::get<solver::NumberArray>(ii[PERIODIC]);
  if (lows.size() != 3) {
    std::cout << "prob_lo needs 3 elements " << std::endl;
    return std::nullopt;
    add_msg(PROB_LO, messages, std::vector<double>{0, 0, 0});
  } else {
    std::get<0>(geo.axes).low = lows[0];
    std::get<1>(geo.axes).low = lows[1];
    std::get<2>(geo.axes).low = lows[2];
  }
  if (highs.size() != 3) {
    std::cout << "prob_hi needs 3 elements " << std::endl;
    return std::nullopt;
    add_msg(PROB_HI, messages, std::vector<double>{0, 0, 0});
  } else {
    std::get<0>(geo.axes).high = highs[0];
    std::get<1>(geo.axes).high = highs[1];
    std::get<2>(geo.axes).high = highs[2];
  }
  if (is_periodic.size() != 3) {
    std::cout << "periodic needs 3 elements " << std::endl;
    return std::nullopt;
  }

  geo.csg_filename = csg_filename[0];
  std::get<0>(geo.axes).high = highs[0];
  std::get<0>(geo.axes).low = lows[0];
    add_msg(PERIODIC, messages, std::vector<double>{0, 0, 0});
  } else {
    std::get<0>(geo.axes).periodic = is_periodic[0];
  std::get<1>(geo.axes).high = highs[1];
  std::get<1>(geo.axes).low = lows[1];
    std::get<1>(geo.axes).periodic = is_periodic[1];
  std::get<2>(geo.axes).high = highs[2];
  std::get<2>(geo.axes).low = lows[2];
    std::get<2>(geo.axes).periodic = is_periodic[2];
  }
  return geo;
}
} // namespace solver
+27 −26
Original line number Diff line number Diff line
#include <iostream>

#include "solver.hpp"
#include "solver_impl.hpp"

namespace solver {

std::optional<solver::MeshSettings> make_mesh(solver::InputInfo ii) {
solver::MeshSettings make_mesh(solver::InputInfo ii,
                               std::vector<InputsMessage> &messages) {
  solver::MeshSettings mesh;
  auto [mx, my, mz] = mesh.axes;

  if (!ii.count(N_CELL)) {
    require(N_CELL);
    return std::nullopt;
  }
    // NumberArray defaults = std::vector<double> {0};
    add_msg(N_CELL, messages, std::vector<double>{});
  } else {

    auto n_cell = std::get<solver::NumberArray>(ii[N_CELL]);
    if (n_cell.size() != 3) {
    std::cout << N_CELL << " needs 3 elements " << std::endl;
    return std::nullopt;
  }

  auto [mx, my, mz] = mesh.axes;
      add_msg(N_CELL, messages, std::vector<double>{0, 0, 0});
    } else {
      mx.n_cell = n_cell[0];
      my.n_cell = n_cell[1];
      mz.n_cell = n_cell[2];
    }
  }

  auto fabarray_size = std::get<solver::NumberArray>(ii[FABARRAY_TILE_SZ]);
  if (fabarray_size.size() != 3) {
    std::cout << FABARRAY_TILE_SZ << " needs 3 elements " << std::endl;
    add_msg(FABARRAY_TILE_SZ, messages, std::vector<double>{0, 0, 0});
  } else {
    mx.fluid_max_tile_size = fabarray_size[0];
    my.fluid_max_tile_size = fabarray_size[1];
@@ -32,7 +33,7 @@ std::optional<solver::MeshSettings> make_mesh(solver::InputInfo ii) {

  auto part_grid_size = std::get<solver::NumberArray>(ii[PARTICLE_TILE_SZ]);
  if (part_grid_size.size() != 3) {
    std::cout << PARTICLE_TILE_SZ << " needs 3 elements " << std::endl;
    add_msg(PARTICLE_TILE_SZ, messages, std::vector<double>{0, 0, 0});
  } else {
    mx.particle_max_tile_size = part_grid_size[0];
    my.particle_max_tile_size = part_grid_size[1];
@@ -41,19 +42,19 @@ std::optional<solver::MeshSettings> make_mesh(solver::InputInfo ii) {

  auto grid_size_x = std::get<solver::NumberArray>(ii[GRID_SIZE_X]);
  if (grid_size_x.size() != 1) {
    std::cout << GRID_SIZE_X << " is a scalar " << std::endl;
    add_msg(GRID_SIZE_X, messages, std::vector<double>{0});
  } else {
    mx.max_grid_size = grid_size_x[0];
  }
  auto grid_size_y = std::get<solver::NumberArray>(ii[GRID_SIZE_Y]);
  if (grid_size_y.size() != 1) {
    std::cout << GRID_SIZE_Y << " is a scalar " << std::endl;
    add_msg(GRID_SIZE_Y, messages, std::vector<double>{0});
  } else {
    my.max_grid_size = grid_size_y[0];
  }
  auto grid_size_z = std::get<solver::NumberArray>(ii[GRID_SIZE_Z]);
  if (grid_size_z.size() != 1) {
    std::cout << GRID_SIZE_Z << " is a scalar " << std::endl;
    add_msg(GRID_SIZE_Z, messages, std::vector<double>{0});
  } else {
    mz.max_grid_size = grid_size_z[0];
  }
@@ -61,35 +62,35 @@ std::optional<solver::MeshSettings> make_mesh(solver::InputInfo ii) {
  auto particle_grid_size_x =
      std::get<solver::NumberArray>(ii[PARTICLE_GRID_SIZE_X]);
  if (particle_grid_size_x.size() != 1) {
    std::cout << PARTICLE_GRID_SIZE_X << " is a scalar " << std::endl;
    add_msg(PARTICLE_GRID_SIZE_X, messages, std::vector<double>{0});
  } else {
    mx.particle_max_grid_size = particle_grid_size_x[0];
  }
  auto particle_grid_size_y =
      std::get<solver::NumberArray>(ii[PARTICLE_GRID_SIZE_Y]);
  if (particle_grid_size_y.size() != 1) {
    std::cout << PARTICLE_GRID_SIZE_Y << " is a scalar " << std::endl;
    add_msg(PARTICLE_GRID_SIZE_Y, messages, std::vector<double>{0});
  } else {
    my.particle_max_grid_size = particle_grid_size_y[0];
  }
  auto particle_grid_size_z =
      std::get<solver::NumberArray>(ii[PARTICLE_GRID_SIZE_Z]);
  if (particle_grid_size_z.size() != 1) {
    std::cout << PARTICLE_GRID_SIZE_Z << " is a scalar " << std::endl;
    add_msg(PARTICLE_GRID_SIZE_Z, messages, std::vector<double>{0});
  } else {
    mz.particle_max_grid_size = particle_grid_size_z[0];
  }

  auto bf = std::get<solver::NumberArray>(ii[BLOCKING_FACTOR]);
  if (bf.size() != 1) {
    std::cout << BLOCKING_FACTOR << " is a scalar" << std::endl;
    add_msg(BLOCKING_FACTOR, messages, std::vector<double>{0});
  } else {
    mesh.blocking_factor = bf[0];
  }

  auto volfrac = std::get<solver::NumberArray>(ii[SMALL_VOLFRAC]);
  if (volfrac.size() != 1) {
    std::cout << SMALL_VOLFRAC << " is a scalar" << std::endl;
    add_msg(SMALL_VOLFRAC, messages, std::vector<double>{0});
  } else {
    mesh.small_volfrac = volfrac[0];
  }
+12 −2
Original line number Diff line number Diff line
// standard includes
#include <assert.h>
#include <iostream>
#include <memory>

// subproject includes
@@ -136,9 +137,18 @@ template <> struct action<keyval_line> {
std::optional<parser_state> do_parse(std::string str) {
  parser_state st;
  memory_input in(str, "std::cin");

  try {
    if (!parse<grammar, action>(in, st)) {
      return std::nullopt;
    }
  } catch (const parse_error &e) {
    const auto p = e.positions.front();
    std::cerr << e.what() << std::endl
              << in.line_at(p) << std::endl
              << std::string(p.byte_in_line, ' ') << '^' << std::endl;
  }

  return st;
}

+47 −29
Original line number Diff line number Diff line
#include <iostream>
#include <optional>
#include <sstream>

#include "solver.hpp"
#include "solver_impl.hpp"

namespace solver {

void require(std::string key) {
  std::cout << "missing required key:  " << key << std::endl;
}
void add_missing_msg(std::string key, std::vector<InputsMessage> &messages,
                     Array defaults) {
  std::ostringstream oss;

std::optional<solver::SolverSettings> do_make_solver(solver::InputInfo ii) {
  solver::SolverSettings ss;
  auto new_geo = make_geometry(ii);
  if (!new_geo.has_value()) {
    std::cout << "Problem making geometry" << std::endl;
    return std::nullopt;
  oss << key << " is missing; using defaults: ";
  if (auto sarray = std::get_if<StringArray>(&defaults)) {
    for (auto def : *sarray) {
      oss << def << " ";
    }
  } else if (auto narray = std::get_if<NumberArray>(&defaults)) {
    for (auto def : *narray) {
      oss << def << " ";
    }
  }
  messages.push_back(InputsMessage{oss.str()});
}
  auto new_mesh = make_mesh(ii);
  if (!new_mesh.has_value()) {
    std::cout << "Problem making mesh" << std::endl;
    return std::nullopt;

void add_msg(std::string key, std::vector<InputsMessage> &messages,
             Array defaults) {
  std::ostringstream oss;
  std::ostringstream defs;
  int size = 0;

  if (auto sarray = std::get_if<StringArray>(&defaults)) {
    size = sarray->size();
    for (auto def : *sarray) {
      defs << def << " ";
    }
  auto new_time = make_time(ii);
  if (!new_time.has_value()) {
    std::cout << "Problem making time" << std::endl;
    return std::nullopt;
  } else if (auto narray = std::get_if<NumberArray>(&defaults)) {
    size = narray->size();
    for (auto def : *narray) {
      defs << def << " ";
    }
  ss.geometry = new_geo.value();
  ss.time = new_time.value();
  ss.mesh = new_mesh.value();
  return ss;
  }

std::optional<solver::SolverSettings> make_solver(solver::InputInfo ii) {
  auto maybe_state = do_make_solver(ii);
  if (!maybe_state.has_value()) {
    return std::nullopt;
  if (size == 1) {
    oss << key << " should be a scalar; using defaults: ";
  } else {
    oss << key << " should have " << size << " elements; using defaults";
  }
  oss << defs.str();
  messages.push_back(InputsMessage{oss.str()});
}
  return maybe_state.value();

std::pair<solver::SolverSettings, std::vector<InputsMessage>>
make_solver(solver::InputInfo ii) {
  std::vector<InputsMessage> messages;
  solver::SolverSettings ss;
  ss.geometry = make_geometry(ii, messages);
  ss.mesh = make_mesh(ii, messages);
  ss.time = make_time(ii, messages);
  return std::make_pair(ss, messages);
}

std::string serialize(solver::SolverSettings settings) {
Loading