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(ESPRESSO_SCAFACOS) or defined(ESPRESSO_SCAFACOS_DIPOLES)
23
26
27#include "scafacos.hpp"
28
30
31#include <utils/demangle.hpp>
32
33#include <algorithm>
34#include <functional>
35#include <iomanip>
36#include <iterator>
37#include <optional>
38#include <span>
39#include <sstream>
40#include <stdexcept>
41#include <string>
42#include <type_traits>
43#include <utility>
44#include <variant>
45#include <vector>
46
47namespace ScriptInterface {
48namespace Scafacos {
49
50std::vector<std::string> available_methods() {
52}
53
55 using result_type = std::vector<std::string>;
56
57 auto operator()(std::string const &value) const { return result_type{value}; }
58
59 template <typename T> result_type operator()(T const &value) const {
60 if constexpr (std::is_arithmetic_v<T>) {
61 return operator()(to_str(value));
62 }
63 throw std::runtime_error("Cannot convert " + Utils::demangle<T>());
64 }
65
66 auto operator()(result_type const &values) const { return values; }
67
68 template <typename T, std::size_t N>
69 auto operator()(std::span<T, N> const values) const {
71 for (auto const &v : values) {
72 if constexpr (std::is_same_v<std::remove_cvref_t<T>, Variant>) {
73 values_str.emplace_back(std::visit(*this, v).front());
74 } else {
75 values_str.emplace_back(to_str(v));
76 }
77 }
78 return values_str;
79 }
80
81 template <typename T> auto operator()(std::vector<T> const &values) const {
82 return (*this)(std::span(values.begin(), values.size()));
83 }
84
85 template <typename T, std::size_t N>
87 return (*this)(std::span(values.begin(), N));
88 }
89
90private:
91 template <typename T>
92 requires std::is_arithmetic_v<T>
93 std::string to_str(T const &value) const {
94 std::ostringstream serializer;
95 if constexpr (std::is_floating_point_v<T>) {
96 serializer << std::scientific << std::setprecision(17);
97 }
98 serializer << value;
99 return serializer.str();
100 }
101};
102
104 using result_type = std::unordered_map<std::string, Variant>;
105
106 auto operator()(result_type const &obj) const { return obj; }
107
108 template <typename T>
109 auto operator()(std::unordered_map<T, Variant> const &obj) const {
110 // handle the case of the empty dict, which can have any key type
111 return (obj.empty()) ? result_type{} : invalid(obj);
112 }
113
114 template <typename T> auto operator()(T const &obj) const {
115 return invalid(obj);
116 }
117
118private:
119 template <typename T> auto invalid(T const &obj) const {
121 }
122};
123
124std::string serialize_parameters(Variant const &pack) {
125 auto const parameters = std::visit(GetParameterList(), pack);
126 if (parameters.empty()) {
127 throw std::invalid_argument(
128 "ScaFaCoS methods require at least 1 parameter");
129 }
130 auto const visitor = ConvertToStringVector();
131 std::string method_params = "";
132 for (auto const &[name, values] : parameters) {
133 method_params += "," + name;
134 for (auto const &value : std::visit(visitor, values)) {
135 method_params += "," + value;
136 }
137 }
138 return method_params.substr(1);
139}
140
141template <typename T>
142std::optional<Variant> string_to_number(std::string const &s) {
143 auto deserializer = std::istringstream(s);
144 T result;
145 deserializer >> result;
146 if (deserializer.fail() or not deserializer.eof()) {
147 return {};
148 }
149 return Variant{result};
150}
151
152std::unordered_map<std::string, Variant>
154 /*
155 * ScaFaCoS parameters are serialized to a comma-separated string.
156 * Key-value pairs can be split with a look ahead: when the next
157 * item is a string, it is a parameter name and the current list
158 * of arithmetic values belong to the current parameter name.
159 * The only exception is string-valued parameters; in that case
160 * the current list of arithmetic values is empty.
161 */
162 auto const numbers = std::string("-0123456789");
163 std::unordered_map<std::string, Variant> method_params{};
164 std::vector<std::string> flat_array;
165 std::istringstream buffer;
166 buffer.str(parameters);
167 for (std::string line; std::getline(buffer, line, ',');) {
168 flat_array.emplace_back(line);
169 }
170 for (auto it = flat_array.begin(); it != flat_array.end();) {
171 auto const parameter_name = *it;
172 auto parameter_list = std::vector<Variant>{};
173 for (++it; it != flat_array.end(); ++it) {
174 if ((numbers.find(it->front()) == std::string::npos) and
175 not parameter_list.empty()) {
176 break;
177 }
178 auto result = Variant{*it};
179 if (auto converted = string_to_number<int>(*it)) {
180 result = Variant{*converted};
181 } else if (auto converted = string_to_number<double>(*it)) {
182 result = Variant{*converted};
183 }
184 parameter_list.emplace_back(result);
185 }
186 assert(not parameter_list.empty());
187 if (parameter_list.size() == 1ul) {
189 } else {
191 }
192 }
193 return method_params;
194}
195
196} // namespace Scafacos
197} // namespace ScriptInterface
198
199#endif // ESPRESSO_SCAFACOS or ESPRESSO_SCAFACOS_DIPOLES
ScafacosContextBase provides the public interface of the ScaFaCoS bridge.
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
std::unordered_map< std::string, Variant > deserialize_parameters(std::string const &parameters)
Convert flattened parameters to a map.
Definition scafacos.cpp:153
std::string serialize_parameters(Variant const &pack)
Flatten a parameter map.
Definition scafacos.cpp:124
std::vector< std::string > available_methods()
Fetch list of methods compiled in ScaFaCoS.
Definition scafacos.cpp:50
std::optional< Variant > string_to_number(std::string const &s)
Definition scafacos.cpp:142
PackedVariant pack(const Variant &v)
Transform a Variant to a PackedVariant.
static std::vector< std::string > available_methods()
auto operator()(std::span< T, N > const values) const
Definition scafacos.cpp:69
auto operator()(Utils::Vector< T, N > const &values) const
Definition scafacos.cpp:86
auto operator()(result_type const &values) const
Definition scafacos.cpp:66
result_type operator()(T const &value) const
Definition scafacos.cpp:59
auto operator()(std::string const &value) const
Definition scafacos.cpp:57
auto operator()(std::vector< T > const &values) const
Definition scafacos.cpp:81
std::unordered_map< std::string, Variant > result_type
Definition scafacos.cpp:104
auto operator()(result_type const &obj) const
Definition scafacos.cpp:106
auto operator()(std::unordered_map< T, Variant > const &obj) const
Definition scafacos.cpp:109
Recursive variant implementation.
Definition Variant.hpp:84