helics 3.7.0
Loading...
Searching...
No Matches
Inputs.hpp
1/*
2Copyright (c) 2017-2026,
3Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Energy
4Innovation LLC. See the top-level NOTICE for additional details. All rights reserved.
5SPDX-License-Identifier: BSD-3-Clause
6*/
7#pragma once
8
9#include "Federate.hpp"
11#include "helicsTypes.hpp"
12
13#include <memory>
14#include <string>
15#include <utility>
16#include <vector>
17
18namespace units {
19class precise_unit;
20} // namespace units
21
22namespace helics {
23
24class ValueFederate;
25enum MultiInputHandlingMethod : uint16_t {
27 VECTORIZE_OPERATION = HELICS_MULTI_INPUT_VECTORIZE_OPERATION,
31 DIFF_OPERATION = HELICS_MULTI_INPUT_DIFF_OPERATION,
34 AVERAGE_OPERATION = HELICS_MULTI_INPUT_AVERAGE_OPERATION
35};
36
38class HELICS_CXX_EXPORT Input: public Interface {
39 protected:
40 ValueFederate* fed = nullptr;
41 private:
42 int referenceIndex{-1};
43 void* dataReference{nullptr};
44
45 DataType targetType{DataType::HELICS_UNKNOWN};
46 DataType injectionType{
47 DataType::HELICS_UNKNOWN};
48 bool changeDetectionEnabled{false};
49 bool hasUpdate{false};
50 bool disableAssign{false};
51 bool useThreshold{false};
52 bool multiUnits{false};
53 MultiInputHandlingMethod inputVectorOp{
54 MultiInputHandlingMethod::NO_OP};
55 int32_t prevInputCount{0};
56 size_t customTypeHash{0U};
57 defV lastValue{invalidDouble};
58 std::shared_ptr<units::precise_unit> outputUnits;
59 std::shared_ptr<units::precise_unit> inputUnits;
60 std::vector<std::pair<DataType, std::shared_ptr<units::precise_unit>>>
61 sourceTypes;
62 std::string givenTarget;
63 double delta{-1.0};
64 double threshold{0.0};
65 // this needs to match the defV type
66 std::variant<std::function<void(const double&, Time)>,
67 std::function<void(const int64_t&, Time)>,
68 std::function<void(const std::string&, Time)>,
69 std::function<void(const std::complex<double>&, Time)>,
70 std::function<void(const std::vector<double>&, Time)>,
71 std::function<void(const std::vector<std::complex<double>>&, Time)>,
72 std::function<void(const NamedPoint&, Time)>,
73 std::function<void(const bool&, Time)>,
74 std::function<void(const Time&, Time)>>
75 value_callback;
76 public:
78 Input() = default;
80 Input(ValueFederate* valueFed,
82 std::string_view actName,
83 std::string_view unitsOut = {});
84
85 Input(ValueFederate* valueFed,
86 std::string_view key,
87 std::string_view defaultType = "def",
88 std::string_view units = {});
89
90 template<class FedPtr>
91 Input(FedPtr& valueFed,
92 std::string_view key,
93 std::string_view defaultType = "def",
94 std::string_view units = {}): Input(std::addressof(*valueFed), key, defaultType, units)
95 {
96 static_assert(
97 std::is_base_of<ValueFederate, std::remove_reference_t<decltype(*valueFed)>>::value,
98 "first argument must be a pointer to a ValueFederate");
99 }
100
101 Input(InterfaceVisibility locality,
102 ValueFederate* valueFed,
103 std::string_view key,
104 std::string_view defaultType = "def",
105 std::string_view units = {});
106
107 template<class FedPtr>
108 Input(InterfaceVisibility locality,
109 FedPtr& valueFed,
110 std::string_view key,
111 std::string_view defaultType = "def",
112 std::string_view units = {}):
113 Input(locality, std::addressof(*valueFed), key, defaultType, units)
114 {
115 static_assert(
116 std::is_base_of<ValueFederate, std::remove_reference_t<decltype(*valueFed)>>::value,
117 "first argument must be a pointer to a ValueFederate");
118 }
119
120 Input(ValueFederate* valueFed,
121 std::string_view key,
122 DataType defType,
123 std::string_view units = {}): Input(valueFed, key, typeNameStringRef(defType), units)
124 {
125 }
126
127 template<class FedPtr>
128 Input(FedPtr& valueFed, std::string_view key, DataType defType, std::string_view units = {}):
129 Input(valueFed, key, typeNameStringRef(defType), units)
130 {
131 }
132
133 Input(InterfaceVisibility locality,
134 ValueFederate* valueFed,
135 std::string_view key,
136 std::string_view units = {}): Input(locality, valueFed, key, "def", units)
137 {
138 }
139
140 template<class FedPtr>
141 Input(InterfaceVisibility locality,
142 FedPtr& valueFed,
143 std::string_view key,
144 std::string_view units = {}): Input(locality, valueFed, key, "def", units)
145 {
146 }
147
148 Input(InterfaceVisibility locality,
149 ValueFederate* valueFed,
150 std::string_view key,
151 DataType defType,
152 std::string_view units = {}):
153 Input(locality, valueFed, key, typeNameStringRef(defType), units)
154 {
155 }
156
157 template<class FedPtr>
158 Input(InterfaceVisibility locality,
159 FedPtr& valueFed,
160 std::string_view key,
161 DataType defType,
162 std::string_view units = {}):
163 Input(locality, valueFed, key, typeNameStringRef(defType), units)
164 {
165 }
166
170 Time getLastUpdate() const;
171
177 void registerNotificationCallback(std::function<void(Time)> callback);
178
180 const std::string& getPublicationType() const
181 {
182 return ((injectionType == DataType::HELICS_UNKNOWN) ||
183 (injectionType == DataType::HELICS_CUSTOM)) ?
184 getInjectionType() :
185 typeNameStringRef(injectionType);
186 }
188 const std::string& getType() const { return getExtractionType(); }
190 const std::string& getUnits() const { return getExtractionUnits(); }
192 void addPublication(std::string_view target);
194 void addTarget(std::string_view target) { addPublication(target); }
200 bool checkUpdate(bool assumeUpdate = false);
201
203 void clearUpdate();
206 bool isUpdated();
214 bool isUpdated() const;
215
216 virtual void setOption(int32_t option, int32_t value = 1) override;
217 virtual int32_t getOption(int32_t option) const override;
223 template<class X>
224 void setInputNotificationCallback(std::function<void(const X&, Time)> callback)
225 {
226 static_assert(
227 helicsType<X>() != DataType::HELICS_CUSTOM,
228 "callback type must be a primary helics type one of \"double, int64_t, named_point, bool, Time "
229 "std::vector<double>, std::vector<std::complex<double>>, std::complex<double>\"");
230 value_callback = std::move(callback);
231 registerCallback();
232 }
233
234 private:
235 template<class X>
236 void setDefault_impl(std::integral_constant<int, 0> /*V*/, X&& val)
237 {
239 lastValue = make_valid(std::forward<X>(val));
240 }
241
242 template<class X>
243 void setDefault_impl(std::integral_constant<int, 1> /*V*/, X&& val)
244 {
245 lastValue = make_valid(std::forward<X>(val));
246 }
247
248 template<class X>
249 void setDefault_impl(std::integral_constant<int, 2> /*V*/, X&& val)
250 {
251 auto res = ValueConverter<remove_cv_ref<X>>::convert(std::forward<X>(val));
252 lastValue = std::string(res.to_string());
253 setDefaultBytes(res);
254 }
255
257 void registerCallback();
258
259 public:
262 template<class X>
263 void setDefault(X&& val)
264 {
265 setDefault_impl<X>(typeCategory<X>(), std::forward<X>(val));
266 }
267
268 void setDefaultBytes(data_view val);
272 void setMinimumChange(double deltaV) noexcept
273 {
274 // this first check enables change detection if it was disabled via negative delta
275 if (delta < 0.0) {
276 changeDetectionEnabled = true;
277 }
278 delta = deltaV;
279 // the second checks if we should disable from negative delta
280 if (delta < 0.0) {
281 changeDetectionEnabled = false;
282 }
283 }
287 void enableChangeDetection(bool enabled = true) noexcept { changeDetectionEnabled = enabled; }
288
289 private:
291 void handleCallback(Time time);
292 template<class X>
293 void getValue_impl(std::integral_constant<int, primaryType> /*V*/, X& out);
294
296 void getValue_impl(std::integral_constant<int, primaryType> /*V*/, char& out)
297 {
298 out = getValueChar();
299 }
300
302 void getValue_impl(std::integral_constant<int, convertibleType> /*V*/, char& out)
303 {
304 out = getValueChar();
305 }
306
307 template<class X>
308 void getValue_impl(std::integral_constant<int, convertibleType> /*V*/, X& out)
309 {
310 std::conditional_t<std::is_integral<X>::value,
311 std::conditional_t<std::is_same<X, char>::value, char, int64_t>,
312 double>
313 gval;
314 getValue_impl(std::integral_constant<int, primaryType>(), gval);
315 out = static_cast<X>(gval);
316 }
317
318 template<class X>
319 void getValue_impl(std::integral_constant<int, nonConvertibleType> /*V*/, X& out)
320 {
321 ValueConverter<X>::interpret(getBytes(), out);
322 }
323
324 template<class X>
325 X getValue_impl(std::integral_constant<int, primaryType> /*V*/)
326 {
327 X val; // NOLINT
328 getValue_impl(std::integral_constant<int, primaryType>(), val);
329 return val;
330 }
331
332 template<class X>
333 X getValue_impl(std::integral_constant<int, convertibleType> /*V*/)
334 {
335 std::conditional_t<std::is_integral<X>::value,
336 std::conditional_t<std::is_same<X, char>::value, char, int64_t>,
337 double>
338 gval;
339 getValue_impl(std::integral_constant<int, primaryType>(), gval);
340 return static_cast<X>(gval);
341 }
342
343 template<class X>
344 X getValue_impl(std::integral_constant<int, nonConvertibleType> /*V*/)
345 {
346 return ValueConverter<X>::interpret(getBytes());
347 }
348
349 public:
351 int getValue(double* data, int maxsize);
353 int getComplexValue(double* data, int maxsize);
355 int getValue(char* str, int maxsize);
359 template<class X>
360 void getValue(X& out)
361 {
362 getValue_impl<X>(typeCategory<X>(), out);
363 }
366 template<class X>
367 auto getValue()
368 {
369 return getValue_impl<remove_cv_ref<X>>(typeCategory<X>());
370 }
371
372 template<class X>
373 const X& getValueRef();
375 double getDouble() { return getValue_impl<double>(std::integral_constant<int, primaryType>()); }
377 const std::string& getString() { return getValueRef<std::string>(); }
378
380 data_view getBytes();
382 size_t getByteCount();
384 size_t getStringSize();
386 size_t getVectorSize();
387
389 DataType getHelicsType() const { return targetType; }
390
392 DataType getHelicsInjectionType() const { return injectionType; }
393
394 MultiInputHandlingMethod getMultiInputMode() const { return inputVectorOp; }
395
396 bool vectorDataProcess(const std::vector<std::shared_ptr<const SmallBuffer>>& dataV);
397
398 const std::string& getTarget() const
399 {
400 return (!givenTarget.empty()) ? givenTarget : getSourceTargets();
401 }
402
403 virtual const std::string& getDisplayName() const override
404 {
405 return (mName.empty()) ? getTarget() : getName();
406 }
407
408 private:
410 void loadSourceInformation();
412 char getValueChar();
414 bool allowDirectFederateUpdate() const
415 {
416 return hasUpdate && !changeDetectionEnabled &&
417 inputVectorOp == MultiInputHandlingMethod::NO_OP;
418 }
419 data_view checkAndGetFedUpdate();
420 void forceCoreDataUpdate();
421 friend class ValueFederateManager;
422};
423
425HELICS_CXX_EXPORT double
426 doubleExtractAndConvert(const data_view& dv,
427 const std::shared_ptr<units::precise_unit>& inputUnits,
428 const std::shared_ptr<units::precise_unit>& outputUnits);
429
430HELICS_CXX_EXPORT void
431 integerExtractAndConvert(defV& store,
432 const data_view& dv,
433 const std::shared_ptr<units::precise_unit>& inputUnits,
434 const std::shared_ptr<units::precise_unit>& outputUnits);
435
436template<class X>
437void Input::getValue_impl(std::integral_constant<int, primaryType> /*V*/, X& out)
438{
439 auto dv = checkAndGetFedUpdate();
440 if (!dv.empty()) {
441 if (injectionType == DataType::HELICS_UNKNOWN) {
442 loadSourceInformation();
443 }
444
445 if (injectionType == helics::DataType::HELICS_DOUBLE) {
446 defV val = doubleExtractAndConvert(dv, inputUnits, outputUnits);
447 valueExtract(val, out);
448 } else if (injectionType == helics::DataType::HELICS_INT) {
449 defV val;
450 integerExtractAndConvert(val, dv, inputUnits, outputUnits);
451 valueExtract(val, out);
452 } else {
453 valueExtract(dv, injectionType, out);
454 }
455 if (changeDetectionEnabled) {
456 if (changeDetected(lastValue, out, delta)) {
457 lastValue = make_valid(out);
458 } else {
459 valueExtract(lastValue, out);
460 }
461 } else {
462 lastValue = make_valid(out);
463 }
464 } else {
465 valueExtract(lastValue, out);
466 }
467 hasUpdate = false;
468}
469
470template<class X>
471inline const X& getValueRefImpl(defV& val)
472{
473 valueConvert(val, helicsType<X>());
474 return std::get<X>(val);
475}
476
477template<>
478inline const std::string& getValueRefImpl(defV& val)
479{
480 // don't convert a named point to a string
481 if ((val.index() == named_point_loc)) {
482 return std::get<NamedPoint>(val).name;
483 }
484 valueConvert(val, DataType::HELICS_STRING);
485 return std::get<std::string>(val);
486}
487
488HELICS_CXX_EXPORT bool checkForNeededCoreRetrieval(std::size_t currentIndex,
489 DataType injectionType,
490 DataType conversion);
491
492template<class X>
493const X& Input::getValueRef()
494{
495 static_assert(std::is_same<typeCategory<X>, std::integral_constant<int, primaryType>>::value,
496 "calling getValue By ref must be with a primary type");
497 auto dv = checkAndGetFedUpdate();
498 if (!dv.empty()) {
499 if (injectionType == DataType::HELICS_UNKNOWN) {
500 loadSourceInformation();
501 }
502
503 if (changeDetectionEnabled) {
504 X out;
505 if (injectionType == helics::DataType::HELICS_DOUBLE) {
506 defV val = doubleExtractAndConvert(dv, inputUnits, outputUnits);
507 valueExtract(val, out);
508 } else if (injectionType == helics::DataType::HELICS_INT) {
509 defV val;
510 integerExtractAndConvert(val, dv, inputUnits, outputUnits);
511 valueExtract(val, out);
512 } else {
513 valueExtract(dv, injectionType, out);
514 }
515 if (changeDetected(lastValue, out, delta)) {
516 lastValue = make_valid(std::move(out));
517 }
518 } else {
519 valueExtract(dv, injectionType, lastValue);
520 }
521 } else {
522 if (checkForNeededCoreRetrieval(lastValue.index(),
523 injectionType,
524 helicsType<remove_cv_ref<X>>())) {
525 forceCoreDataUpdate();
526 }
527 }
528
529 hasUpdate = false;
530 return getValueRefImpl<remove_cv_ref<X>>(lastValue);
531}
532} // namespace helics
naming a set of types that are interchangeable and recognizable inside the HELICS application API and...
Definition Inputs.hpp:38
const std::string & getUnits() const
Definition Inputs.hpp:190
void addTarget(std::string_view target)
Definition Inputs.hpp:194
const std::string & getType() const
Definition Inputs.hpp:188
void setMinimumChange(double deltaV) noexcept
Definition Inputs.hpp:272
const std::string & getString()
Definition Inputs.hpp:377
void setDefault(X &&val)
Definition Inputs.hpp:263
auto getValue()
Definition Inputs.hpp:367
void enableChangeDetection(bool enabled=true) noexcept
Definition Inputs.hpp:287
void getValue(X &out)
Definition Inputs.hpp:360
const std::string & getPublicationType() const
Definition Inputs.hpp:180
virtual const std::string & getDisplayName() const override
Definition Inputs.hpp:403
DataType getHelicsType() const
Definition Inputs.hpp:389
Input()=default
DataType getHelicsInjectionType() const
Definition Inputs.hpp:392
void setInputNotificationCallback(std::function< void(const X &, Time)> callback)
Definition Inputs.hpp:224
double getDouble()
Definition Inputs.hpp:375
Definition LocalFederateId.hpp:65
Definition application_api/Federate.hpp:880
Definition application_api/ValueFederate.hpp:28
Definition data_view.hpp:22
@ HELICS_MULTI_INPUT_OR_OPERATION
Definition helics_enums.h:333
@ HELICS_MULTI_INPUT_DIFF_OPERATION
Definition helics_enums.h:338
@ HELICS_MULTI_INPUT_NO_OP
Definition helics_enums.h:326
@ HELICS_MULTI_INPUT_MAX_OPERATION
Definition helics_enums.h:340
@ HELICS_MULTI_INPUT_AND_OPERATION
Definition helics_enums.h:330
@ HELICS_MULTI_INPUT_SUM_OPERATION
Definition helics_enums.h:335
@ HELICS_MULTI_INPUT_VECTORIZE_OPERATION
Definition helics_enums.h:328
@ HELICS_MULTI_INPUT_MIN_OPERATION
Definition helics_enums.h:342
@ HELICS_MULTI_INPUT_AVERAGE_OPERATION
Definition helics_enums.h:344
the main namespace for the helics co-simulation library User functions will be in the helics namespac...
Definition AsyncFedCallInfo.hpp:14
constexpr DataType helicsType()
Definition helicsTypes.hpp:378
DataType
Definition helicsTypes.hpp:273
constexpr double invalidDouble
defined constant for an invalid value as a double
Definition helicsTypes.hpp:499
const std::string & typeNameStringRef(DataType type)
Definition helicsTypes.cpp:64
void valueExtract(const defV &data, std::string &val)
Definition helicsPrimaryTypes.cpp:174
double doubleExtractAndConvert(const data_view &dv, const std::shared_ptr< units::precise_unit > &inputUnits, const std::shared_ptr< units::precise_unit > &outputUnits)
Definition Inputs.cpp:777
int64_t make_valid(bool obj)
Definition HelicsPrimaryTypes.hpp:68
bool changeDetected(const defV &prevValue, const std::string &val, double)
Definition helicsPrimaryTypes.cpp:20
std::conditional_t< helicsType< remove_cv_ref< X > >() !=DataType::HELICS_CUSTOM, std::integral_constant< int, primaryType >, std::conditional_t< isConvertableType< remove_cv_ref< X > >(), std::integral_constant< int, convertibleType >, std::integral_constant< int, nonConvertibleType > > > typeCategory
Definition helicsTypes.hpp:553
TimeRepresentation< count_time< 9 > > Time
Definition helicsTime.hpp:27
std::variant< double, int64_t, std::string, std::complex< double >, std::vector< double >, std::vector< std::complex< double > >, NamedPoint > defV
Definition HelicsPrimaryTypes.hpp:37
STL namespace.