Skip to content

Commit

Permalink
defaults (#2448)
Browse files Browse the repository at this point in the history
* Allow specification of default values for inputs in the json and toml configurations

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Minor edits to Config. Options Reference for new `defaults` parameters

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update docs/references/configuration_options_reference.md

Co-authored-by: Ryan Mast <[email protected]>

* Update docs/references/configuration_options_reference.md

Co-authored-by: Ryan Mast <[email protected]>

* Update docs/user-guide/fundamental_topics/interface_configuration.md

Co-authored-by: Ryan Mast <[email protected]>

* Update docs/user-guide/fundamental_topics/interface_configuration.md

Co-authored-by: Ryan Mast <[email protected]>

* Corrected `helicsInputSetDefaultTime()` and `helicsInputSetDefaultNamedPoint()` in Config. Options Reference

* Apply suggestions from code review

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Trevor Hardy <[email protected]>
Co-authored-by: Ryan Mast <[email protected]>
  • Loading branch information
4 people authored Oct 20, 2022
1 parent fa59a5c commit 9b340a2
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 8 deletions.
30 changes: 30 additions & 0 deletions docs/references/configuration_options_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ An example of one publication, subscription, named input, endpoint, and filter i
"subscriptions": [
{
"only_update_on_change": false,
"default": value,
}
],
"inputs": [
Expand All @@ -171,6 +172,7 @@ An example of one publication, subscription, named input, endpoint, and filter i
"multiple_connections_allowed": false
"multi_input_handling_method": "average",
"targets": ["pub1", "pub2"]
"default": 5.5,
}
],
"endpoints": [
Expand Down Expand Up @@ -761,6 +763,34 @@ This option allows the specific numerical definition of "change" when using the

---

### `default`

_API:_ `helicsInputSetDefaultX`
[C++ input](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Input.html#a55056ac9dd2895270f575827dd9951c7)
| [C input](api-reference/C_API.md#input)
| [Python input](https://python.helics.org/api/capi-py.html#helicsInputSetDefault)
| [Julia input](https://julia.helics.org/latest/api/#HELICS.helicsInputSetDefulat-Tuple{HELICS.Input,XXX})

This option allows specifying the default value used when no publication has been received. Each datatype has its own API call such as:

- `helicsInputSetDefaultBoolean()`
- `helicsInputSetDefaultBytes()`
- `helicsInputSetDefaultChar()`
- `helicsInputSetDefaultComplex()`
- `helicsInputSetDefaultComplexVector()`
- `helicsInputSetDefaulDouble()`
- `helicsInputSetDefaultInteger()`
- `helicsInputSetDefaultRaw()`
- `helicsInputSetDefaultString()` (used for JSONs)
- `helicsInputSetDefaultVector()`

Though they are not as obviously named, the following two APIs do provide a means of setting the default value as well:

- `helicsInputSetDefaultTime()` - set the default using a HelicsTime value
- `helicsInputSetDefaultNamedPoint()` -set the default NamedPoint which is a pair of a string and double used for tagged values or set points

---

### `connection_required` | `connectionrequired` | `connectionRequired` [false]

_API:_ `helicsFederateInfoSetFlagOption`
Expand Down
34 changes: 32 additions & 2 deletions docs/user-guide/fundamental_topics/interface_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,25 @@ Below is a sample JSON configuration file with some of the more common options.
"unit":"A",
"global": true,
"only_update_on_change": true,
"tolerance": 0.2
"tolerance": 0.2,
"default":0.91
}
]
],
"inputs": [
{
"key": "ipt2",
"type": "double",
"connection_required": true,
"target": "pub1",
"global": true,
"default":"3.67",
"tags": [
{ "name": "period", "value": "0.7" },
{ "name": "description", "value": "a test input" }
]
}
//specify an input with a target multiple targets could be specified like "targets":["pub1","pub2","pub3"]
],
}
```

Expand All @@ -93,15 +109,29 @@ Below is a sample JSON configuration file with some of the more common options.
- `type` - Data type, such as integer, double, complex.
- `units` - The units can be any sort of unit string, a wide assortment is supported and can be compound units such as m/s^2 and the conversion will convert as long as things are convertible. The unit match is also checked for other types and an error if mismatching units are detected. A warning is also generated if the units are not understood and not matching. The unit checking and conversion is only active if both the publication and subscription specify units. HELICS is able to do some levels of unit conversion, currently only on double type publications but more may be added in the future.
- `only_transmit_on_change` and `tolerance` - Publications will only send a new value out to the federation when the value has changed more than the delta specified by `tolerance`.
- `alias` - an alternate name for the publication must be globally unique for publications
- `tags` - Arbitrary string value pairs that can be applied to interfaces. Tags are available to others through queries but are not transmitted by default. They can be used to store additional information about an interface that might be useful to applications. At some point in the future automated connection routines will make use of them. "tags" are applicable to any interface and can also be used on federates.
- **`subscriptions`** - These are lists of the values being sent to and from the given federate.

- `key` - This string identifies the federation-unique value that this federate wishes to receive. If `global` has been set to `false` in the `publications` JSON configuration file, the name of the value is formatted as `<federate name>/<publication key>`. Both of these strings can be found in the publishing federate's JSON configuration file as the `name` and `key` strings, respectively. If `global` is `true` the string is the publishing federate's `key` value.
- `required` - The message being subscribed to must be provided by some other publisher in the federation.
- `type` - Data type, such as integer, double, complex.
- `units` - Same as with `publications`.
- `global` - Applies to the `key`, same as with `publications`.
- `default` - set the default value to return if no publications have been received
- `only_update_on_change` and `tolerance` - Subscriptions will only consider a new value received when that value has changed more than the delta specified by `tolerance`.

- **`inputs`** - These are lists of the values being sent to and from the given federate.
- `name` - the name of the input.
- `required` - The input must have a valid target
- `type` - Data type, such as integer, double, complex.
- `units` - Same as with `publications`.
- `global` - Applies to the `key`, same as with `publications`.
- `default` - set the default value to return if no publications have been received
- `target` - A key for a publication the input should receive, may be an array such as ["pub1","pub2","pub3"]
- `tags` - name and value pairs defining user tags for the interface
- `only_update_on_change` and `tolerance` - Inputs will only consider a new value received when that value has changed more than the delta specified by `tolerance`.

## API Configuration

Configuring the federate interface with the API is done internal to a user-written simulator. The specific API used will depend on the language the simulator is written in. Native APIs for HELICS are available in [C++](../../doxygen/index.md) and [C](../../references/api-reference/C_API.md). MATLAB, Java, Julia, Nim, and Python all support the C API calls (ex: `helicsFederateEnterExecutionMode()`). Python and Julia also have native APIs (see: [Python (PyHELICS)](https://python.helics.org/api/), [Julia](https://gmlc-tdc.github.io/HELICS.jl/latest/api/)) that wrap the C APIs to better support the conventions of their languages. The [API References](../../references/api-reference/index.md) page contains links to the APIs.
Expand Down
19 changes: 16 additions & 3 deletions src/helics/application_api/ValueFederate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ void ValueFederate::registerValueInterfacesJson(const std::string& jsonString)
subAct->addTarget(name);
}
}
auto defStr = fileops::getOrDefault(sub, "default", emptyStr);
if (!defStr.empty()) {
subAct->setDefault(defStr);
}
loadOptions(this, sub, *subAct);
}
}
Expand All @@ -312,7 +316,10 @@ void ValueFederate::registerValueInterfacesJson(const std::string& jsonString)
inp = &registerInput(name, type, units);
}
}

auto defStr = fileops::getOrDefault(ipt, "default", emptyStr);
if (!defStr.empty()) {
inp->setDefault(defStr);
}
loadOptions(this, ipt, *inp);
}
}
Expand Down Expand Up @@ -386,7 +393,10 @@ void ValueFederate::registerValueInterfacesToml(const std::string& tomlString)
id->addTarget(name);
}
}

auto defStr = fileops::getOrDefault(sub, "default", emptyStr);
if (!defStr.empty()) {
id->setDefault(defStr);
}
loadOptions(this, sub, *id);
}
}
Expand All @@ -412,7 +422,10 @@ void ValueFederate::registerValueInterfacesToml(const std::string& tomlString)
id = &registerInput(name, type, units);
}
}

auto defStr = fileops::getOrDefault(ipt, "default", emptyStr);
if (!defStr.empty()) {
id->setDefault(defStr);
}
loadOptions(this, ipt, *id);
}
}
Expand Down
13 changes: 13 additions & 0 deletions tests/helics/application_api/ValueFederateAdditionalTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,14 @@ TEST(valuefed_json_tests, file_loadb)

EXPECT_EQ(vFed.getTag("description"), "fedb description");
EXPECT_EQ(vFed.getTag("version"), "27");

auto& sub1 = vFed.getInput(0);
vFed.enterInitializingMode();

auto dv = sub1.getDouble();
EXPECT_DOUBLE_EQ(dv, 9.33);
dv = inp2.getDouble();
EXPECT_DOUBLE_EQ(dv, 3.67);
vFed.disconnect();
helics::BrokerFactory::terminateAllBrokers();
helics::CoreFactory::terminateAllCores();
Expand Down Expand Up @@ -662,8 +670,13 @@ TEST(valuefederate, toml_file_loadb)
EXPECT_EQ(std::stod(dval), 0.7);
}

auto& sub1 = vFed.getInput(0);
vFed.enterExecutingMode();

auto dv = sub1.getDouble();
EXPECT_DOUBLE_EQ(dv, 9.33);
dv = inp2.getDouble();
EXPECT_DOUBLE_EQ(dv, 3.67);
EXPECT_EQ(vFed.getTag("description"), "fedb description");
EXPECT_EQ(vFed.getTag("version"), "27");

Expand Down
4 changes: 3 additions & 1 deletion tests/helics/test_files/example_value_fed_testb.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
{
"key": "pub1", // the key of the publication
"connection_required": true, //set to true to make helics issue a warning if the publication is not found
"tolerance": 0.3
"tolerance": 0.3,
"default": "9.33"
},
{
"key": "fedName/pub2", // the name of the publication to subscribe to
Expand All @@ -63,6 +64,7 @@
"connection_required": true,
"target": "pub1",
"global": true,
"default": 3.67,
"tags": [
{ "name": "period", "value": "0.7" },
{ "name": "description", "value": "a test input" }
Expand Down
4 changes: 2 additions & 2 deletions tests/helics/test_files/example_value_fed_testb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ period= 1.0 #the period with which federate may return time
#set required to true to make helics issue a warning if the publication is not found
#example of inline tables (be careful it falls under the most recent [section] or [[table]]
subscriptions=[
{key="pub1", connection_required=true},
{key="pub1", connection_required=true, default=9.33},
# shortcut is a naming shortcut for the publication for later retrieval
{key="valueFed_toml/pub2", alias="pubshortcut", info="this is an information string for use by the application"}
]

inputs=[
{key="ipt2", type="double",flags="connection_optional", target="pub1", global=true,tags=[{name="period",value=0.7},{name="description",value="a test input"}]}
{key="ipt2", type="double",flags="connection_optional", target="pub1",default="3.67", global=true,tags=[{name="period",value=0.7},{name="description",value="a test input"}]}
] #specify an input with a target

#add some descriptive tags to a federate
Expand Down

0 comments on commit 9b340a2

Please sign in to comment.