Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
scafacos.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "config/config.hpp"
21
22#if defined(SCAFACOS) or defined(SCAFACOS_DIPOLES)
23
26
27#include "scafacos.hpp"
28
30
31#include <utils/demangle.hpp>
32
33#include <boost/variant.hpp>
34
35#include <algorithm>
36#include <functional>
37#include <iomanip>
38#include <iterator>
39#include <optional>
40#include <sstream>
41#include <stdexcept>
42#include <string>
43#include <utility>
44#include <vector>
45
46namespace ScriptInterface {
47namespace Scafacos {
48
49std::vector<std::string> available_methods() {
51}
52
54 : public boost::static_visitor<std::vector<std::string>> {
55 auto operator()(std::string const &value) const { return result_type{value}; }
56
57 template <typename T, typename = std::enable_if_t<!std::is_arithmetic_v<T>>>
58 result_type operator()(T const &) const {
59 throw std::runtime_error("Cannot convert " + Utils::demangle<T>());
60 }
61
62 template <typename T, typename = std::enable_if_t<std::is_same_v<T, int>>>
63 auto operator()(T const &value) const {
64 return operator()(to_str(value));
65 }
66
67 auto operator()(double const &value) const {
68 return operator()(to_str(value));
69 }
70
71 auto operator()(result_type const &values) const { return values; }
72
73 auto operator()(std::vector<Variant> const &values) const {
74 result_type values_str;
75 for (auto const &v : values) {
76 values_str.emplace_back(boost::apply_visitor(*this, v).front());
77 }
78 return values_str;
79 }
80
81 template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
82 auto operator()(std::vector<T> const &values) const {
83 result_type values_str;
84 for (auto const &v : values) {
85 values_str.emplace_back(to_str(v));
86 }
87 return values_str;
88 }
89
90private:
91 std::string to_str(int const value) const { return std::to_string(value); }
92
93 std::string to_str(double const value) const {
94 std::ostringstream serializer;
95 serializer << std::scientific << std::setprecision(17);
96 serializer << value;
97 return serializer.str();
98 }
99};
100
102 : public boost::static_visitor<std::unordered_map<std::string, Variant>> {
103 auto operator()(result_type const &obj) const { return obj; }
104
105 template <typename T>
106 auto operator()(std::unordered_map<T, Variant> const &obj) const {
107 // handle the case of the empty dict, which can have any key type
108 return (obj.empty()) ? result_type{} : invalid(obj);
109 }
110
111 template <typename T> auto operator()(T const &obj) const {
112 return invalid(obj);
113 }
114
115private:
116 template <typename T> auto invalid(T const &obj) const {
118 }
119};
120
121std::string serialize_parameters(Variant const &pack) {
122 auto const parameters = boost::apply_visitor(GetParameterList(), pack);
123 if (parameters.empty()) {
124 throw std::invalid_argument(
125 "ScaFaCoS methods require at least 1 parameter");
126 }
127 auto const visitor = ConvertToStringVector();
128 std::string method_params = "";
129 for (auto const &kv : parameters) {
130 method_params += "," + kv.first;
131 for (auto const &value : boost::apply_visitor(visitor, kv.second)) {
132 method_params += "," + value;
133 }
134 }
135 return method_params.substr(1);
136}
137
138template <typename T>
139std::optional<Variant> string_to_number(std::string const &s) {
140 auto deserializer = std::istringstream(s);
141 T result;
142 deserializer >> result;
143 if (deserializer.fail() or not deserializer.eof()) {
144 return {};
145 }
146 return Variant{result};
147}
148
149std::unordered_map<std::string, Variant>
151 /*
152 * ScaFaCoS parameters are serialized to a comma-separated string.
153 * Key-value pairs can be split with a look ahead: when the next
154 * item is a string, it is a parameter name and the current list
155 * of arithmetic values belong to the current parameter name.
156 * The only exception is string-valued parameters; in that case
157 * the current list of arithmetic values is empty.
158 */
159 auto const numbers = std::string("-0123456789");
160 std::unordered_map<std::string, Variant> method_params{};
161 std::vector<std::string> flat_array;
162 std::istringstream buffer;
163 buffer.str(parameters);
164 for (std::string line; std::getline(buffer, line, ',');) {
165 flat_array.emplace_back(line);
166 }
167 for (auto it = flat_array.begin(); it != flat_array.end();) {
168 auto const parameter_name = *it;
169 auto parameter_list = std::vector<Variant>{};
170 for (++it; it != flat_array.end(); ++it) {
171 if ((numbers.find(it->front()) == std::string::npos) and
172 not parameter_list.empty()) {
173 break;
174 }
175 auto result = Variant{*it};
176 if (auto converted = string_to_number<int>(*it)) {
177 result = Variant{*converted};
178 } else if (auto converted = string_to_number<double>(*it)) {
179 result = Variant{*converted};
180 }
181 parameter_list.emplace_back(result);
182 }
183 assert(not parameter_list.empty());
184 if (parameter_list.size() == 1ul) {
186 } else {
188 }
189 }
190 return method_params;
191}
192
193} // namespace Scafacos
194} // namespace ScriptInterface
195
196#endif // SCAFACOS or SCAFACOS_DIPOLES
ScafacosContextBase provides the public interface of the ScaFaCoS bridge.
This file contains the defaults for ESPResSo.
std::unordered_map< std::string, Variant > deserialize_parameters(std::string const &parameters)
Convert flattened parameters to a map.
Definition scafacos.cpp:150
std::string serialize_parameters(Variant const &pack)
Flatten a parameter map.
Definition scafacos.cpp:121
std::vector< std::string > available_methods()
Fetch list of methods compiled in ScaFaCoS.
Definition scafacos.cpp:49
std::optional< Variant > string_to_number(std::string const &s)
Definition scafacos.cpp:139
PackedVariant pack(const Variant &v)
Transform a Variant to a PackedVariant.
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
boost::make_recursive_variant< None, bool, int, std::size_t, double, std::string, ObjectRef, Utils::Vector3b, Utils::Vector3i, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d, std::vector< int >, std::vector< double >, std::vector< boost::recursive_variant_ >, std::unordered_map< int, boost::recursive_variant_ >, std::unordered_map< std::string, boost::recursive_variant_ > >::type Variant
Possible types for parameters.
Definition Variant.hpp:67
static std::vector< std::string > available_methods()
auto operator()(std::vector< T > const &values) const
Definition scafacos.cpp:82
auto operator()(std::vector< Variant > const &values) const
Definition scafacos.cpp:73
auto operator()(result_type const &values) const
Definition scafacos.cpp:71
auto operator()(double const &value) const
Definition scafacos.cpp:67
result_type operator()(T const &) const
Definition scafacos.cpp:58
auto operator()(std::string const &value) const
Definition scafacos.cpp:55
auto operator()(result_type const &obj) const
Definition scafacos.cpp:103
auto operator()(std::unordered_map< T, Variant > const &obj) const
Definition scafacos.cpp:106