Skip to content

Commit

Permalink
update doc, rename, complex general support
Browse files Browse the repository at this point in the history
Co-authored-by: Marcel Koch <[email protected]>
  • Loading branch information
yhmtsai and MarcelKoch committed May 17, 2024
1 parent 1e12424 commit 3cbb182
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 50 deletions.
2 changes: 1 addition & 1 deletion core/config/config_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace config {

template <>
deferred_factory_parameter<const LinOpFactory>
build_or_get_factory<const LinOpFactory>(const pnode& config,
parse_or_get_factory<const LinOpFactory>(const pnode& config,
const registry& context,
const type_descriptor& td)
{
Expand Down
28 changes: 19 additions & 9 deletions core/config/config_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ inline std::shared_ptr<T> get_stored_obj(const pnode& config,
* the registry by string.
*/
template <typename T>
deferred_factory_parameter<T> build_or_get_factory(const pnode& config,
deferred_factory_parameter<T> parse_or_get_factory(const pnode& config,
const registry& context,
const type_descriptor& td);

Expand All @@ -73,7 +73,7 @@ deferred_factory_parameter<T> build_or_get_factory(const pnode& config,
*/
template <>
deferred_factory_parameter<const LinOpFactory>
build_or_get_factory<const LinOpFactory>(const pnode& config,
parse_or_get_factory<const LinOpFactory>(const pnode& config,
const registry& context,
const type_descriptor& td);

Expand All @@ -82,25 +82,25 @@ build_or_get_factory<const LinOpFactory>(const pnode& config,
*/
template <>
deferred_factory_parameter<const stop::CriterionFactory>
build_or_get_factory<const stop::CriterionFactory>(const pnode& config,
parse_or_get_factory<const stop::CriterionFactory>(const pnode& config,
const registry& context,
const type_descriptor& td);

/**
* give a vector of factory by calling build_or_get_factory.
* give a vector of factory by calling parse_or_get_factory.
*/
template <typename T>
inline std::vector<deferred_factory_parameter<T>> build_or_get_factory_vector(
inline std::vector<deferred_factory_parameter<T>> parse_or_get_factory_vector(
const pnode& config, const registry& context, const type_descriptor& td)
{
std::vector<deferred_factory_parameter<T>> res;
if (config.get_tag() == pnode::tag_t::array) {
for (const auto& it : config.get_array()) {
res.push_back(build_or_get_factory<T>(it, context, td));
res.push_back(parse_or_get_factory<T>(it, context, td));
}
} else {
// only one config can be passed without array
res.push_back(build_or_get_factory<T>(config, context, td));
res.push_back(parse_or_get_factory<T>(config, context, td));
}

return res;
Expand Down Expand Up @@ -156,8 +156,18 @@ get_value(const pnode& config)
if (config.get_tag() == pnode::tag_t::real) {
return static_cast<ValueType>(get_value<real_type>(config));
} else if (config.get_tag() == pnode::tag_t::array) {
return ValueType{get_value<real_type>(config.get(0)),
get_value<real_type>(config.get(1))};
real_type real(0);
real_type imag(0);
if (config.get_array().size() >= 1) {
real = get_value<real_type>(config.get(0));
}
if (config.get_array().size() >= 2) {
imag = get_value<real_type>(config.get(1));
}
GKO_THROW_IF_INVALID(
config.get_array().size() <= 2,
"complex value array expression only accept up to two elements");
return ValueType{real, imag};
}
GKO_INVALID_STATE("Can not get complex value");
}
Expand Down
2 changes: 1 addition & 1 deletion core/config/stop_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ configure_implicit_residual(const pnode& config, const registry& context,

template <>
deferred_factory_parameter<const stop::CriterionFactory>
build_or_get_factory<const stop::CriterionFactory>(const pnode& config,
parse_or_get_factory<const stop::CriterionFactory>(const pnode& config,
const registry& context,
const type_descriptor& td)
{
Expand Down
4 changes: 2 additions & 2 deletions core/solver/cg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ typename Cg<ValueType>::parameters_type Cg<ValueType>::parse(
}
if (auto& obj = config.get("criteria")) {
params.with_criteria(
gko::config::build_or_get_factory_vector<
gko::config::parse_or_get_factory_vector<
const stop::CriterionFactory>(obj, context, td_for_child));
}
if (auto& obj = config.get("preconditioner")) {
params.with_preconditioner(
gko::config::build_or_get_factory<const LinOpFactory>(
gko::config::parse_or_get_factory<const LinOpFactory>(
obj, context, td_for_child));
}
return params;
Expand Down
96 changes: 64 additions & 32 deletions include/ginkgo/core/config/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,74 @@ class pnode;


/**
* parse is the main entry point to create an Ginkgo object based on
* parse is the main entry point to create an Ginkgo LinOpFactory based on
* some file configuration. It reads a configuration stored as a property tree
* and creates the desired type.
*
* General rules for configuration
* 1. all parameter and template usage are according to the class directly. It
* has the same behavior as the class like default setting without specifying
* anything. When the class factory parameters allows `with_<key>(value)`,
* the file configuration will allow `"<key>": value`
* 2. all key will use snake_case including template. For example, ValueType ->
* value_type
* 3. If the value is not bool, integer, or floating point, we will use string
* to represent everything. For example, we will use string to select the
* enum value. `"baseline": "absolute"` will select the absolute baseline in
* ResidualNorm critrion
* 4. `"type"` is the new key to select the class without template type. We also
* prepend the namespace except for gko. For example, we use "solver::Cg" for
* Cg solver. Note. the template type is given by the another entry or from
* the type_descriptor.
* 5. We have supports the following datatype with postfix to indicate their
* size: int32, int64, float32, float64, complex<float32>, complex<float64>.
* note: we have also allow `void` additionally in type_descriptor to specify
* file must contain the value/index type config.
* 6. We use [real, imag] to represent complex values. If it only contains one
* value or none [], we will treat it as a complex number with an imaginary
* part = 0.
* 7. In many cases, the parameter allows array input. If the array only
* contains one object, users can directly provide the object without putting
* it into an array.
* `"criteria": [{...}]` and `"criteria": {...}` are the same.
* 1. The configuration can be used to define factory parameters and class
* template parameters. Any factory parameter that is not defined in the
* configuration will fallback to their default value. Any template parameter
* that is not defined will fallback to the type_descriptor argument
* 2. The new `"type"` key determines which Ginkgo object to create. The value
* for this key is the desired class name with namespaces (except for
* `gko::`, `experimental::`). Any template parameters a class might have are
* left out. Only classes with a factory are supported. For example, the
* configuration `"type": "solver::Cg"` specifies that a Cg solver will be
* created. Note: template parameters can either be given in the
* configuration as separate key-value pairs, or in the type_descriptor.
* 3. Factory and class template parameters can be defined with key-value pairs
* that are derived from the class they are refering to. When a factory has a

Check warning on line 47 in include/ginkgo/core/config/config.hpp

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"refering" should be "referring".
* parameter with the function `with_<key>(value)`, then the configuration
* allows `"<key>": value` to define this parameter. When a class has a
* template parameter `template<typename/type... key> class`, then the
* configuration allows `"<key>": value` to the template parameter. The
* supported values of the template parameter depend on the context. For
* index and value types, these are listed under 4.
* 4. Values for template parameters are represented with strings. The following
* datatypes, with postfix to indicate their size, are supported: int32,
* int64, float32, float64, complex<float32>, complex<float64>.
* 5. All keys use snake_case including template parameters. Factory parameter
* keys are already defined with snake_case in their factories, while class
* template arguments need to be translated, i.e. `ValueType -> value_type`.
* 6. The allowed values for factory parameters depend on the type the parameter
* is stored as. There are three distinct options:
* - POD types (bool, integer, floating point, or enum): Except for enum,
* the value has to be the POD type. For enums, a string value is used to
* represent them. The string has to be one of the possible enum values.
* An example of this type of parameter is the `krylov_dim` parameter for
* the Gmres solver.
* - LinOp (smart) pointers: The value has to be a string. The string is used
* to look up a LinOp object in the registry.
* An example is the `generated_preconditioner` parameter for iterative
* solvers such as Cg.
* - LinOpFactory (smart) pointers: The value can either be a string, or a
* nested configuration. The string has the same behavior as for LinOp
* pointers, i.e. an LinOpFactory object from the registry is taken. The
* nested configuration has to adhere to the general configuration rules
* again. See the examples below for some use-cases.
* An example is the `preconditioner` parameter for iterative solvers
* such as Cg.
* - CriterionFactory (smart) pointers: The value can either be a string, or
* a nested configuration. It has the same behavior as for LinOpFactory.
* - A vector of the types above: The value has to be an array with the
* inner values specified as above.
* 7. Complex values are represented as an 2-element array [real, imag]. If the
* array contains only one value, it will be considered as a complex number
* with an imaginary part = 0. An empy array will be treated as zero.

Check warning on line 84 in include/ginkgo/core/config/config.hpp

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"empy" should be "empty".
* 8. Keys that expect array of objects also accept single object which is
* interpreted as a 1-element array. This means the following configurations
* are equivalent if the key expects an array value: `"<key>": [{object}]`
* and `"<key>": {object}`.
*
* The configuration needs to specify the resulting type by the field:
* All configurations need to specify the resulting type by the field:
* ```
* "type": "some_supported_ginkgo_type"
* ```
* The result will be a deferred_factory_parameter,
* which can be thought of as an intermediate step before a LinOpFactory.
* Providing an Executor through the function `.on(exec)` will then create the
* factory with the parameters as defined in the configuration.
* The result will be a deferred_factory_parameter, which is an intermediate
* step before a LinOpFactory. Providing an Executor through the function
* `.on(exec)` will then create the factory with the parameters as defined in
* the configuration.
*
* Given a configuration that is defined as
* ```
Expand Down Expand Up @@ -126,7 +155,10 @@ class pnode;
* templated type, then the value and/or index type from
* the descriptor will be used. Any definition of the
* value and/or index type within the config will take
* precedence over the descriptor.
* precedence over the descriptor. If `void` is used for
* one or both of the types, then the corresponding type
* has to be defined in the config, otherwise the
* parsing will fail.
*
* @return a deferred_factory_parameter which creates an LinOpFactory after
* `.on(exec)` is called on it.
Expand Down
11 changes: 6 additions & 5 deletions include/ginkgo/core/config/type_descriptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ namespace config {
* This class describes the value and index types to be used when building a
* Ginkgo type from a configuration file.
*
* A type_descriptor is passed to the parse function defines which
* template parameters, in terms of value_type and/or index_type, the created
* object will have. For example, a CG solver created like this:
* A type_descriptor is passed in order to define the parse function defines
* which template parameters, in terms of value_type and/or index_type, the
* created object will have. For example, a CG solver created like this:
* ```
* auto cg = parse(config, context, type_descriptor("float64", "int32"));
* ```
* will have the value type `float64` and the index type `int32`. Any Ginkgo
* object that does not require one of these types will just ignore it. We used
* void type to specify no default type.
* object that does not require one of these types will just ignore it. The
* value `void` can be used to specify that no default type is provided. In this
* case, the configuration has to provide the necessary template types.
*
* If the configuration specifies one of the fields (or both):
* ```
Expand Down

0 comments on commit 3cbb182

Please sign in to comment.