Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
02d80af
Rename all String()` with `format_as()`
tomchapman Oct 6, 2026
ef70e85
Disable the range formatter for Field types
tomchapman Oct 6, 2026
415a5a6
Use a fmt::formatter for Field2D, Field3D, FieldPerp
tomchapman Oct 6, 2026
b13c455
Replace more `toSring()` calls with `format_as()`
tomchapman Oct 7, 2026
c032889
Move `format_as()` inside namespace `ns` in BOUT_ENUM_CLASS_NS
tomchapman Oct 7, 2026
d77ca70
Replace more `toSring()` calls with `format_as()`
tomchapman Oct 12, 2026
e074c09
Remove `format_as()` for ConductionMethod
tomchapman Oct 12, 2026
dcf4f06
Replace `{:s}` with `{}`
tomchapman Oct 12, 2026
c0cbb88
Replace more `toString()` calls with `format_as()`
tomchapman Oct 12, 2026
d10fc0b
Correct fmt::formatter SFINAE parameter for Field types
tomchapman Oct 12, 2026
bc87893
Delete catch-all `format_as` template from utils.hxx
tomchapman Oct 12, 2026
255b81b
Remove redundant comments
tomchapman Oct 12, 2026
e0d838a
Replace calls to `format_as()` with `fmt::to_string` for types with c…
tomchapman Oct 12, 2026
2a5f3ec
Wrap generic fmt::formatter for Fields in fmt namespace
tomchapman Oct 12, 2026
1db89a8
Replace calls to `format_as()` with `fmt::to_string` for types with c…
tomchapman Oct 12, 2026
dff473e
No need to call `format_as()` with BoutException
tomchapman Oct 13, 2026
17cfc84
Call `fmt::to_string()` or `fmt::format()` not `format_as()`
tomchapman Oct 13, 2026
eaa3a6a
Replace `{:s}` with `{}`
tomchapman Oct 13, 2026
3682624
Remove namespace and qualify class name
tomchapman Oct 13, 2026
7fe4256
Remove `format_as()` functions for std::string and bool types
tomchapman Oct 13, 2026
18e1b25
Minor tidying:
tomchapman Oct 13, 2026
8fb5952
Restore `toString()` for fields
tomchapman Oct 14, 2026
f1ee685
Disable the range formatter for Field types
tomchapman Oct 6, 2026
62f2b3b
Fix signature of `format_as()` for DIFF_METHOD
tomchapman Oct 15, 2026
b36200f
Apply clang-format
tomchapman Oct 15, 2026
bc1e7ec
Add missing header
tomchapman Oct 15, 2026
abc0a66
Remove more `toString()` calls
tomchapman Oct 15, 2026
01ee06c
Restore `toString()` for booleans
tomchapman Oct 15, 2026
8080e6e
Restore original function order
tomchapman Oct 15, 2026
3963b9e
Fix FieldFactoryCreationTest
tomchapman Oct 15, 2026
a568f2e
Replace `toString` with `fmt::to_string` for `operator<<`
tomchapman Oct 16, 2026
7dc1724
Call `fmt::to_string` on enums when using in the argument to EXPECT_EQ.
tomchapman Oct 18, 2026
fca0e8c
Include output_bout_types.hxx in field2d.cxx, field3d.cxx, and fieldp…
tomchapman Oct 18, 2026
6affe3f
Restore use of `toString()` in StringUtilitiesTests
tomchapman Oct 18, 2026
ad7344a
Restore use of `toString()` in OptionsTest
tomchapman Oct 18, 2026
0f85800
Revert replace `toString` with `fmt::to_string` for `operator<<`
tomchapman Oct 18, 2026
eba7b8c
Replace one more `toString` with `fmt::to_string`
tomchapman Oct 19, 2026
e065cdf
Merge remote-tracking branch 'remotes/boutproject/next' into fmt-wrap…
tomchapman Nov 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 42 additions & 44 deletions include/bout/bout_enum_class.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@

#define BOUT_MAKE_FROMSTRING_NAME(enumname) enumname##FromString

/// Create an enum class with toString and <enum name>FromString functions, and an
/// Create an enum class with format_as and <enum name>FromString functions, and an
/// Options::as<enum> overload to read the enum
#define BOUT_ENUM_CLASS(enumname, ...) \
enum class enumname : std::uint8_t { __VA_ARGS__ }; \
\
inline std::string toString(enumname e) { \
inline std::string format_as(enumname e) { \
\
const static std::map<enumname, std::string> toString_map = { \
BOUT_ENUM_CLASS_MAP_ARGS(BOUT_ENUM_CLASS_STR, enumname, __VA_ARGS__)}; \
Expand Down Expand Up @@ -102,51 +102,49 @@
} \
\
inline std::ostream& operator<<(std::ostream& out, const enumname& e) { \
return out << toString(e); \
return out << fmt::to_string(e); \
}

/// Create an enum class with toString and <enum name>FromString functions, and an
/// Create an enum class with format_as and <enum name>FromString functions, and an
/// Options::as<enum> overload to read the enum
#define BOUT_ENUM_CLASS_NS(ns, enumname, ...) \
namespace ns { \
enum class enumname : std::uint8_t { __VA_ARGS__ }; \
} \
\
inline std::string toString(ns::enumname e) { \
\
const static std::map<ns::enumname, std::string> toString_map = { \
BOUT_ENUM_CLASS_MAP_ARGS(BOUT_ENUM_CLASS_STR, ns::enumname, __VA_ARGS__)}; \
auto found = toString_map.find(e); \
if (found == toString_map.end()) { \
throw BoutException("Did not find enum {:d}", static_cast<int>(e)); \
} \
return found->second; \
} \
namespace ns { \
inline enumname BOUT_MAKE_FROMSTRING_NAME(enumname)(const std::string& s) { \
const static std::map<std::string, enumname> fromString_map = { \
BOUT_ENUM_CLASS_MAP_ARGS(BOUT_STR_ENUM_CLASS, enumname, __VA_ARGS__)}; \
auto found = fromString_map.find(s); \
if (found == fromString_map.end()) { \
std::string valid_values{}; \
for (auto const& entry : fromString_map) { \
valid_values += std::string(" ") + entry.first; \
} \
throw BoutException("Did not find enum {:s}. Valid values: {:s}", s, \
valid_values); \
} \
return found->second; \
} \
} \
\
template <> \
inline ns::enumname Options::as<ns::enumname>(const ns::enumname&) const { \
return ns::BOUT_MAKE_FROMSTRING_NAME(enumname)(this->as<std::string>()); \
} \
namespace ns { \
inline std::ostream& operator<<(std::ostream& out, const enumname& e) { \
return out << toString(e); \
} \
#define BOUT_ENUM_CLASS_NS(ns, enumname, ...) \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variadic macro 'BOUT_ENUM_CLASS_NS' used; consider using a 'constexpr' variadic template function [cppcoreguidelines-macro-usage]

#define BOUT_ENUM_CLASS_NS(ns, enumname, ...)                                  \
        ^

namespace ns { \
enum class enumname : std::uint8_t { __VA_ARGS__ }; \
\
inline std::string format_as(const enumname& e) { \
\
const static std::map<enumname, std::string> toString_map = { \
BOUT_ENUM_CLASS_MAP_ARGS(BOUT_ENUM_CLASS_STR, enumname, __VA_ARGS__)}; \
auto found = toString_map.find(e); \
if (found == toString_map.end()) { \
throw BoutException("Did not find enum {:d}", static_cast<int>(e)); \
} \
return found->second; \
} \
\
inline enumname BOUT_MAKE_FROMSTRING_NAME(enumname)(const std::string& s) { \
const static std::map<std::string, enumname> fromString_map = { \
BOUT_ENUM_CLASS_MAP_ARGS(BOUT_STR_ENUM_CLASS, enumname, __VA_ARGS__)}; \
auto found = fromString_map.find(s); \
if (found == fromString_map.end()) { \
std::string valid_values{}; \
for (auto const& entry : fromString_map) { \
valid_values += std::string(" ") + entry.first; \
} \
throw BoutException("Did not find enum {:s}. Valid values: {:s}", s, \
valid_values); \
} \
return found->second; \
} \
\
inline std::ostream& operator<<(std::ostream& out, const enumname& e) { \
return out << fmt::to_string(e); \
} \
} /* end namespace ns */ \
\
template <> \
inline ns::enumname Options::as<ns::enumname>(const ns::enumname&) const { \
return ns::BOUT_MAKE_FROMSTRING_NAME(enumname)(this->as<std::string>()); \
}

#endif // BOUT_ENUM_CLASS_H
27 changes: 9 additions & 18 deletions include/bout/bout_types.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ constexpr CELL_LOC CELL_YLOW = CELL_LOC::ylow;
constexpr CELL_LOC CELL_ZLOW = CELL_LOC::zlow;
constexpr CELL_LOC CELL_VSHIFT = CELL_LOC::vshift;

std::string toString(CELL_LOC location);
std::string format_as(const CELL_LOC& location);
CELL_LOC CELL_LOCFromString(const std::string& location_string);
inline std::string format_as(const CELL_LOC& loc) { return toString(loc); }

/// Differential methods. Both central and upwind
enum class DIFF_METHOD { deflt, u1, u2, c2, w2, w3, c4, u3, fft, split, s2 };
Expand All @@ -67,8 +66,7 @@ constexpr DIFF_METHOD DIFF_FFT = DIFF_METHOD::fft;
constexpr DIFF_METHOD DIFF_SPLIT = DIFF_METHOD::split;
constexpr DIFF_METHOD DIFF_S2 = DIFF_METHOD::s2;

std::string toString(DIFF_METHOD location);
inline std::string format_as(const DIFF_METHOD& method) { return toString(method); }
std::string format_as(const DIFF_METHOD& method);

/// Specify grid region for looping
enum class REGION { all, nobndry, nox, noy, noz };
Expand All @@ -78,8 +76,7 @@ constexpr REGION RGN_NOX = REGION::nox;
constexpr REGION RGN_NOY = REGION::noy;
constexpr REGION RGN_NOZ = REGION::noz;

std::string toString(REGION region);
inline std::string format_as(const REGION& region) { return toString(region); }
std::string format_as(const REGION& region);

/// To identify particular directions (in index space):
/// - X, Y, Z are the coordinate directions
Expand All @@ -90,18 +87,16 @@ inline std::string format_as(const REGION& region) { return toString(region); }
/// field-aligned
enum class DIRECTION { X, Y, Z, YAligned, YOrthogonal };

std::string toString(DIRECTION direction);
inline std::string format_as(const DIRECTION& dir) { return toString(dir); }
std::string format_as(const DIRECTION& dir);

/// Identify kind of a field's y-direction
/// - Standard is the default for the Mesh/Coordinates/ParallelTransform
/// - Aligned indicates that the field has been transformed to field-aligned
/// coordinates
enum class YDirectionType { Standard, Aligned };

std::string toString(YDirectionType d);
std::string format_as(const YDirectionType& d);
YDirectionType YDirectionTypeFromString(const std::string& y_direction_string);
inline std::string format_as(const YDirectionType& d) { return toString(d); }

/// Identify kind of a field's z-direction
/// - Standard is the default
Expand All @@ -110,18 +105,16 @@ inline std::string format_as(const YDirectionType& d) { return toString(d); }
/// Field2D)
enum class ZDirectionType { Standard, Average };

std::string toString(ZDirectionType d);
std::string format_as(const ZDirectionType& d);
ZDirectionType ZDirectionTypeFromString(const std::string& z_direction_string);
inline std::string format_as(const ZDirectionType& d) { return toString(d); }

/// Container for direction types
struct DirectionTypes {
YDirectionType y;
ZDirectionType z;
};

std::string toString(const DirectionTypes& dir);
inline std::string format_as(const DirectionTypes& dir) { return toString(dir); }
std::string format_as(const DirectionTypes& dir);

/// Check whether direction types are compatible, so two fields with attributes
/// d1 and d2 respectively can be added, subtracted, etc.
Expand All @@ -132,14 +125,12 @@ void swap(const DirectionTypes& first, const DirectionTypes& second);
/// To identify valid staggering combinations
enum class STAGGER { None, C2L, L2C };

std::string toString(STAGGER stagger);
inline std::string format_as(const STAGGER& stagger) { return toString(stagger); }
std::string format_as(const STAGGER& stagger);

/// To identify types of derivative method combinations
enum class DERIV { Standard, StandardSecond, StandardFourth, Upwind, Flux };

std::string toString(DERIV deriv);
inline std::string format_as(const DERIV& deriv) { return toString(deriv); }
std::string format_as(const DERIV& deriv);

// A small struct that can be used to wrap a specific enum value, giving
// it a unique type that can be passed as a valid type to templates and
Expand Down
41 changes: 22 additions & 19 deletions include/bout/deriv_store.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#ifndef __DERIV_STORE_HXX__
#define __DERIV_STORE_HXX__

#include "fmt/format.h"
#include <cstddef>
#include <functional>
#include <map>
Expand Down Expand Up @@ -87,7 +88,7 @@ struct DerivativeStore {
STAGGER stagger = STAGGER::None) const {

// Get the key
auto key = getKey(direction, stagger, toString(derivType));
auto key = getKey(direction, stagger, fmt::to_string(derivType));
return isEmpty(key);
}

Expand All @@ -97,7 +98,7 @@ struct DerivativeStore {
STAGGER stagger = STAGGER::None) const {

// Get the key
auto key = getKey(direction, stagger, toString(derivType));
auto key = getKey(direction, stagger, fmt::to_string(derivType));
if (isEmpty(key)) {
return std::set<std::string>{};
} else {
Expand All @@ -112,11 +113,11 @@ struct DerivativeStore {

// Introductory information
output_info << "Available methods for derivative type '";
output_info << toString(derivType);
output_info << fmt::to_string(derivType);
output_info << "' in direction ";
output_info << toString(direction);
output_info << fmt::to_string(direction);
output_info << " ( Staggering : ";
output_info << toString(stagger) << " ) : \n";
output_info << fmt::to_string(stagger) << " ) : \n";

for (const auto& i : getAvailableMethods(derivType, direction, stagger)) {
output_info << "\t" << i << "\n";
Expand Down Expand Up @@ -162,7 +163,8 @@ struct DerivativeStore {
};

// Register this method name in lookup of known methods
registeredMethods[getKey(direction, stagger, toString(derivType))].insert(methodName);
registeredMethods[getKey(direction, stagger, fmt::to_string(derivType))].insert(
methodName);
};

/// Register a function with upwindFunc/fluxFunc interface. Which map is used
Expand Down Expand Up @@ -196,7 +198,8 @@ struct DerivativeStore {
};

// Register this method name in lookup of known methods
registeredMethods[getKey(direction, stagger, toString(derivType))].insert(methodName);
registeredMethods[getKey(direction, stagger, fmt::to_string(derivType))].insert(
methodName);
};

/// Templated versions of the above registration routines.
Expand Down Expand Up @@ -225,7 +228,7 @@ struct DerivativeStore {
DERIV derivType = DERIV::Standard) const {

const auto realName = nameLookup(
name, defaultMethods.at(getKey(direction, stagger, toString(derivType))));
name, defaultMethods.at(getKey(direction, stagger, fmt::to_string(derivType))));
const auto key = getKey(direction, stagger, realName);

const storageType<std::size_t, standardFunc>* theMap = nullptr;
Expand Down Expand Up @@ -269,7 +272,7 @@ struct DerivativeStore {
DERIV derivType = DERIV::Upwind) const {

const auto realName = nameLookup(
name, defaultMethods.at(getKey(direction, stagger, toString(derivType))));
name, defaultMethods.at(getKey(direction, stagger, fmt::to_string(derivType))));
const auto key = getKey(direction, stagger, realName);

const storageType<std::size_t, flowFunc>* theMap = nullptr;
Expand Down Expand Up @@ -331,7 +334,7 @@ struct DerivativeStore {

const auto theDirection = direction.first;
const auto theDerivType = deriv.first;
const auto theDerivTypeString = toString(theDerivType);
const auto theDerivTypeString = fmt::to_string(theDerivType);

// Note both staggered and unstaggered have the same fallback default currently
std::string theDefault{
Expand Down Expand Up @@ -360,7 +363,7 @@ struct DerivativeStore {
defaultMethods[getKey(theDirection, STAGGER::None, theDerivTypeString)] =
theDefault;
output_verbose << "The default method for derivative type " << theDerivTypeString
<< " in direction " << toString(theDirection) << " is "
<< " in direction " << fmt::to_string(theDirection) << " is "
<< theDefault << "\n";

//-------------------------------------------------------------
Expand All @@ -384,16 +387,16 @@ struct DerivativeStore {
defaultMethods[getKey(theDirection, STAGGER::C2L, theDerivTypeString)] =
theDefault;
output_verbose << "The default method for staggered derivative type "
<< theDerivTypeString << " in direction " << toString(theDirection)
<< " is " << theDefault << "\n";
<< theDerivTypeString << " in direction "
<< fmt::to_string(theDirection) << " is " << theDefault << "\n";
}
}
}

/// Provide a method to override/force a specific default method
void forceDefaultMethod(std::string methodName, DERIV deriv, DIRECTION direction,
STAGGER stagger = STAGGER::None) {
const auto key = getKey(direction, stagger, toString(deriv));
const auto key = getKey(direction, stagger, fmt::to_string(deriv));
defaultMethods[key] = uppercase(methodName);
}

Expand Down Expand Up @@ -461,7 +464,7 @@ private:
for (const auto& direction : directions) {
for (const auto& deriv : derivTypes) {
const auto theDirection = direction.first;
const auto theDerivTypeString = toString(deriv.first);
const auto theDerivTypeString = fmt::to_string(deriv.first);
const std::string theDefault{uppercase(initialDefaultMethods[deriv.first])};

//-------------------------------------------------------------
Expand All @@ -482,11 +485,11 @@ private:
std::string getMethodName(std::string name, DIRECTION direction,
STAGGER stagger = STAGGER::None) const {

return name + " (" + toString(direction) + ", " + toString(stagger) + ")";
return name + " (" + fmt::to_string(direction) + ", " + fmt::to_string(stagger) + ")";
};

std::string nameLookup(const std::string name, const std::string defaultName) const {
return name != toString(DIFF_DEFAULT) ? name : defaultName;
return name != fmt::to_string(DIFF_DEFAULT) ? name : defaultName;
}

/// Provides a routine to produce a unique key given information
Expand All @@ -503,8 +506,8 @@ private:
// maps to store the different field types as the signature is
// different.
std::size_t result;
result = std::hash<std::string>{}(toString(direction));
result = result ^ std::hash<std::string>{}(toString(stagger));
result = std::hash<std::string>{}(fmt::to_string(direction));
result = result ^ std::hash<std::string>{}(fmt::to_string(stagger));
result = result ^ std::hash<std::string>{}(key);
return result;
}
Expand Down
Loading
Loading