ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
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/algorithm/string.hpp>
34#include <boost/optional.hpp>
35
36#include <algorithm>
37#include <functional>
38#include <iomanip>
39#include <iterator>
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 {
56 return std::vector<std::string>{value};
57 }
58
59 template <typename T, typename = std::enable_if_t<!std::is_arithmetic_v<T>>>
60 std::vector<std::string> operator()(T const &) const {
61 throw std::runtime_error("Cannot convert " + Utils::demangle<T>());
62 }
63
64 template <typename T, typename = std::enable_if_t<std::is_same_v<T, int>>>
65 auto operator()(T const &value) const {
66 return operator()(to_str(value));
67 }
68
69 auto operator()(double const &value) const {
70 return operator()(to_str(value));
71 }
72
73 auto operator()(std::vector<std::string> const &values) const {
74 return values;
75 }
76
77 auto operator()(std::vector<Variant> const &values) const {
78 std::vector<std::string> values_str;
79 for (auto const &v : values) {
80 values_str.emplace_back(boost::apply_visitor(*this, v).front());
81 }
82 return values_str;
83 }
84
85 template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
86 auto operator()(std::vector<T> const &values) const {
87 std::vector<std::string> values_str;
88 for (auto const &v : values) {
89 values_str.emplace_back(to_str(v));
90 }
91 return values_str;
92 }
93
94private:
95 std::string to_str(int const value) const { return std::to_string(value); }
96
97 std::string to_str(double const value) const {
98 std::ostringstream serializer;
99 serializer << std::scientific << std::setprecision(17);
100 serializer << value;
101 return serializer.str();
102 }
103};
104
106 : public boost::static_visitor<std::unordered_map<std::string, Variant>> {
107 auto operator()(std::unordered_map<std::string, Variant> const &obj) const {
108 return obj;
109 }
110
111 template <typename T>
112 auto operator()(std::unordered_map<T, Variant> const &obj) const {
113 // handle the case of the empty dict, which can have any key type
114 return (obj.empty()) ? result_type{} : invalid(obj);
115 }
116
117 template <typename T> auto operator()(T const &obj) const {
118 return invalid(obj);
119 }
120
121private:
122 template <typename T> auto invalid(T const &obj) const {
123 return get_value<result_type>(obj);
124 }
125};
126
127std::string serialize_parameters(Variant const &pack) {
128 auto const parameters = boost::apply_visitor(GetParameterList(), pack);
129 if (parameters.empty()) {
130 throw std::invalid_argument(
131 "ScaFaCoS methods require at least 1 parameter");
132 }
133 auto const visitor = ConvertToStringVector();
134 std::string method_params = "";
135 for (auto const &kv : parameters) {
136 method_params += "," + kv.first;
137 for (auto const &value : boost::apply_visitor(visitor, kv.second)) {
138 method_params += "," + value;
139 }
140 }
141 return method_params.substr(1);
142}
143
144template <typename T>
145boost::optional<Variant> string_to_number(std::string const &s) {
146 auto deserializer = std::istringstream(s);
147 T result;
148 deserializer >> result;
149 if (deserializer.fail() or not deserializer.eof()) {
150 return {};
151 }
152 return Variant{result};
153}
154
155std::unordered_map<std::string, Variant>
156deserialize_parameters(std::string const &parameters) {
157 /*
158 * ScaFaCoS parameters are serialized to a comma-separated string.
159 * Key-value pairs can be split with a look ahead: when the next
160 * item is a string, it is a parameter name and the current list
161 * of arithmetic values belong to the current parameter name.
162 * The only exception is string-valued parameters; in that case
163 * the current list of arithmetic values is empty.
164 */
165 auto const numbers = std::string("-0123456789");
166 std::unordered_map<std::string, Variant> method_params{};
167 std::vector<std::string> flat_array;
168 // Clang 10 false positive: https://github.com/boostorg/algorithm/issues/63
169 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
170 boost::split(flat_array, parameters, boost::is_any_of(","));
171 for (auto it = flat_array.begin(); it != flat_array.end();) {
172 auto const parameter_name = *it;
173 auto parameter_list = std::vector<Variant>{};
174 for (++it; it != flat_array.end(); ++it) {
175 if ((numbers.find(it->front()) == std::string::npos) and
176 not parameter_list.empty()) {
177 break;
178 }
179 auto result = Variant{*it};
180 if (auto converted = string_to_number<int>(*it)) {
181 result = Variant{*converted};
182 } else if (auto converted = string_to_number<double>(*it)) {
183 result = Variant{*converted};
184 }
185 parameter_list.emplace_back(result);
186 }
187 assert(not parameter_list.empty());
188 if (parameter_list.size() == 1ul) {
189 method_params[parameter_name] = parameter_list.front();
190 } else {
191 method_params[parameter_name] = Variant{std::move(parameter_list)};
192 }
193 }
194 return method_params;
195}
196
197} // namespace Scafacos
198} // namespace ScriptInterface
199
200#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:156
std::string serialize_parameters(Variant const &pack)
Flatten a parameter map.
Definition scafacos.cpp:127
boost::optional< Variant > string_to_number(std::string const &s)
Definition scafacos.cpp:145
std::vector< std::string > available_methods()
Fetch list of methods compiled in ScaFaCoS.
Definition scafacos.cpp:49
PackedVariant pack(const Variant &v)
Transform a Variant to a PackedVariant.
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:80
static std::vector< std::string > available_methods()
auto operator()(std::vector< T > const &values) const
Definition scafacos.cpp:86
auto operator()(std::vector< Variant > const &values) const
Definition scafacos.cpp:77
auto operator()(double const &value) const
Definition scafacos.cpp:69
auto operator()(std::string const &value) const
Definition scafacos.cpp:55
auto operator()(std::vector< std::string > const &values) const
Definition scafacos.cpp:73
std::vector< std::string > operator()(T const &) const
Definition scafacos.cpp:60
auto operator()(std::unordered_map< std::string, Variant > const &obj) const
Definition scafacos.cpp:107
auto operator()(std::unordered_map< T, Variant > const &obj) const
Definition scafacos.cpp:112