diff --git a/include/bout/options.hxx b/include/bout/options.hxx index bf1704100f..e790b405b5 100644 --- a/include/bout/options.hxx +++ b/include/bout/options.hxx @@ -194,9 +194,9 @@ public: static void cleanup(); /// The type used to store values - using ValueType = - bout::utils::variant, Matrix, Tensor>; + using ValueType = bout::utils::variant, Array, + Matrix, Tensor>; /// The type used to store attributes /// Extends the variant class so that cast operator can be implemented @@ -874,6 +874,8 @@ void Options::assign<>(FieldPerp val, std::string source); template <> void Options::assign<>(Array val, std::string source); template <> +void Options::assign<>(Array val, std::string source); +template <> void Options::assign<>(Matrix val, std::string source); template <> void Options::assign<>(Tensor val, std::string source); @@ -902,6 +904,8 @@ FieldPerp Options::as(const FieldPerp& similar_to) const; template <> Array Options::as>(const Array& similar_to) const; template <> +Array Options::as>(const Array& similar_to) const; +template <> Matrix Options::as>(const Matrix& similar_to) const; template <> Tensor Options::as>(const Tensor& similar_to) const; diff --git a/include/bout/utils.hxx b/include/bout/utils.hxx index 126fd15d37..7549244c1b 100644 --- a/include/bout/utils.hxx +++ b/include/bout/utils.hxx @@ -543,8 +543,8 @@ std::string toString(const T& val) { /// where the type may be std::string. inline std::string toString(const std::string& val) { return val; } -template <> -inline std::string toString<>(const Array& UNUSED(val)) { +template +inline std::string toString(const Array& UNUSED(val)) { return ""; } diff --git a/src/mesh/data/gridfromfile.cxx b/src/mesh/data/gridfromfile.cxx index aa66b145c7..2e23ce8eb8 100644 --- a/src/mesh/data/gridfromfile.cxx +++ b/src/mesh/data/gridfromfile.cxx @@ -138,7 +138,10 @@ struct GetDimensions { std::vector operator()(MAYBE_UNUSED(int value)) { return {1}; } std::vector operator()(MAYBE_UNUSED(BoutReal value)) { return {1}; } std::vector operator()(MAYBE_UNUSED(const std::string& value)) { return {1}; } - std::vector operator()(const Array& array) { return {array.size()}; } + template + std::vector operator()(const Array& array) { + return {array.size()}; + } std::vector operator()(const Matrix& array) { const auto shape = array.shape(); return {std::get<0>(shape), std::get<1>(shape)}; @@ -471,13 +474,30 @@ void GridFile::readField(Mesh* m, const std::string& name, int UNUSED(ys), int U } } -bool GridFile::get(MAYBE_UNUSED(Mesh* m), MAYBE_UNUSED(std::vector& var), - MAYBE_UNUSED(const std::string& name), MAYBE_UNUSED(int len), - MAYBE_UNUSED(int offset), - MAYBE_UNUSED(GridDataSource::Direction dir)) { +bool GridFile::get(Mesh* UNUSED(m), std::vector& var, const std::string& name, + int len, int offset, GridDataSource::Direction UNUSED(dir)) { TRACE("GridFile::get(vector)"); - return false; + if (not data.isSet(name)) { + return false; + } + + const auto full_var = data[name].as>(); + + // Check size + if (full_var.size() < len + offset) { + throw BoutException("{} has length {}. Expected {} elements + {} offset", name, + full_var.size(), len, offset); + } + + // Ensure that output variable has the correct size + var.resize(len); + + const auto* it = std::begin(full_var); + std::advance(it, offset); + std::copy_n(it, len, std::begin(var)); + + return true; } bool GridFile::get(Mesh* UNUSED(m), std::vector& var, const std::string& name, diff --git a/src/mesh/impls/bout/boutmesh.cxx b/src/mesh/impls/bout/boutmesh.cxx index 956aba0f79..9f9780c70f 100644 --- a/src/mesh/impls/bout/boutmesh.cxx +++ b/src/mesh/impls/bout/boutmesh.cxx @@ -2118,6 +2118,35 @@ void BoutMesh::topology() { add_target(ny_inner - 1, 0, nx); } + // Additional limiters + // Each limiter needs 3 indices: A Y index, start and end X indices + int limiter_count = 0; + Mesh::get(limiter_count, "limiter_count", 0); + if (limiter_count > 0) { + std::vector limiter_yinds, limiter_xstarts, limiter_xends; + if (!source->get(this, limiter_yinds, "limiter_yinds", limiter_count)) { + throw BoutException("Couldn't read limiter_yinds vector of length {} from mesh", + limiter_count); + } + if (!source->get(this, limiter_xstarts, "limiter_xstarts", limiter_count)) { + throw BoutException("Couldn't read limiter_xstarts vector of length {} from mesh", + limiter_count); + } + if (!source->get(this, limiter_xends, "limiter_xends", limiter_count)) { + throw BoutException("Couldn't read limiter_xend vector of length {} from mesh", + limiter_count); + } + + for (int i = 0; i < limiter_count; ++i) { + int yind = limiter_yinds[i]; + int xstart = limiter_xstarts[i]; + int xend = limiter_xends[i]; + output_info.write("Adding a limiter between y={} and {}. X indices {} to {}\n", + yind, yind + 1, xstart, xend); + add_target(yind, xstart, xend); + } + } + if ((ixseps_inner > 0) && (((PE_YIND * MYSUB > jyseps1_1) && (PE_YIND * MYSUB <= jyseps2_1)) || ((PE_YIND * MYSUB > jyseps1_2) && (PE_YIND * MYSUB <= jyseps2_2)))) { diff --git a/src/sys/options.cxx b/src/sys/options.cxx index 8b49b1f3f1..1c50db5896 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -288,6 +288,10 @@ void Options::assign<>(Array val, std::string source) { _set_no_check(std::move(val), std::move(source)); } template <> +void Options::assign<>(Array val, std::string source) { + _set_no_check(std::move(val), std::move(source)); +} +template <> void Options::assign<>(Matrix val, std::string source) { _set_no_check(std::move(val), std::move(source)); } @@ -723,6 +727,32 @@ Array Options::as>(const Array& similar_to) return result; } +template <> +Array Options::as>(const Array& similar_to) const { + if (is_section) { + throw BoutException(_("Option {:s} has no value"), full_name); + } + + Array result = bout::utils::visit( + ConvertContainer>{ + fmt::format(_("Value for option {:s} cannot be converted to an Array"), + full_name), + similar_to}, + value); + + // Mark this option as used + value_used = true; + + output_info << _("\tOption ") << full_name << " = Array"; + if (hasAttribute("source")) { + // Specify the source of the setting + output_info << " (" << bout::utils::variantToString(attributes.at("source")) << ")"; + } + output_info << endl; + + return result; +} + template <> Matrix Options::as>(const Matrix& similar_to) const { if (is_section) { diff --git a/src/sys/options/options_netcdf.cxx b/src/sys/options/options_netcdf.cxx index eda2b0bfbd..fb6efd6567 100644 --- a/src/sys/options/options_netcdf.cxx +++ b/src/sys/options/options_netcdf.cxx @@ -88,6 +88,10 @@ void readGroup(const std::string& filename, const NcGroup& group, Options& resul Array value(static_cast(dims[0].getSize())); var.getVar(value.begin()); result[var_name] = value; + } else if (var_type == ncInt or var_type == ncShort) { + Array value(static_cast(dims[0].getSize())); + var.getVar(value.begin()); + result[var_name] = value; } else if ((var_type == ncString) or (var_type == ncChar)) { std::string value; value.resize(dims[0].getSize());