Loading src/csg/impl/levelset_3d.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading src/inputs/geometry.cpp +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 src/inputs/mesh.cpp +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]; Loading @@ -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]; Loading @@ -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]; } Loading @@ -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]; } Loading src/inputs/parser.cpp +12 −2 Original line number Diff line number Diff line // standard includes #include <assert.h> #include <iostream> #include <memory> // subproject includes Loading Loading @@ -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; } Loading src/inputs/solver.cpp +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 Loading
src/csg/impl/levelset_3d.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading
src/inputs/geometry.cpp +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
src/inputs/mesh.cpp +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]; Loading @@ -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]; Loading @@ -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]; } Loading @@ -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]; } Loading
src/inputs/parser.cpp +12 −2 Original line number Diff line number Diff line // standard includes #include <assert.h> #include <iostream> #include <memory> // subproject includes Loading Loading @@ -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; } Loading
src/inputs/solver.cpp +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