57#ifdef ESPRESSO_WALBERLA_FFT
58 std::shared_ptr<EKFFT>,
60 std::shared_ptr<EKNone>>
63 std::shared_ptr<EKReactions> m_ek_reactions;
64 std::shared_ptr<::EK::EKWalberla> m_ek_instance;
65 std::shared_ptr<::EK::EKWalberla::ek_container_type> m_ek_container;
68 auto get_precision(
decltype(m_poisson_solver)
const &solver)
const {
69 std::optional<bool> result = std::nullopt;
71 [&](
auto const &ptr) {
73 if (ptr
and not std::is_same_v<SolverType, EKNone>) {
85 auto get_precision(std::vector<value_type>
const &
species_list)
const {
86 std::optional<bool> result = std::nullopt;
88 result = get_precision(
species);
94 return m_ek_container->contains(
obj_ptr->get_ekinstance());
97 context()->parallel_try_catch([
this, &
obj_ptr]() {
100 auto const prec_solver = get_precision(m_poisson_solver);
103 throw std::runtime_error(
104 "Cannot mix single and double precision kernels");
109 throw std::runtime_error(
110 "EK species and EK container must have the same tau");
113 m_ek_container->add(
obj_ptr->get_ekinstance());
117 m_ek_container->remove(
obj_ptr->get_ekinstance());
120 struct GetPoissonSolverAsVariant {
121 template <
typename T>
122 auto operator()(std::shared_ptr<T>
const &solver)
const {
128 return std::visit(GetPoissonSolverAsVariant(), m_poisson_solver);
131 struct GetPoissonSolverCoreInstance {
132 template <
typename T>
133 std::shared_ptr<::walberla::PoissonSolver>
134 operator()(std::shared_ptr<T>
const &solver)
const {
135 return solver->get_instance();
139 auto extract_solver(
Variant const &v) {
140 std::optional<
decltype(m_poisson_solver)> solver;
142 if (
auto ptr = std::dynamic_pointer_cast<EKNone>(
so_ptr)) {
143 solver = std::move(ptr);
145#ifdef ESPRESSO_WALBERLA_FFT
146 else if (
auto ptr = std::dynamic_pointer_cast<EKFFT>(
so_ptr)) {
147 solver = std::move(ptr);
150 if (
not solver.has_value()) {
151 context()->parallel_try_catch([]() {
152 throw std::invalid_argument(
"EK solver is of the wrong type");
158 void set_solver(
Variant const &v) {
161 context()->parallel_try_catch([&]() {
165 throw std::runtime_error(
166 "Cannot mix single and double precision kernels");
168 m_ek_container->set_poisson_solver(
handle);
177 [
this]() {
return m_ek_container->get_tau(); }},
178 {
"solver", [
this](
Variant const &v) { set_solver(v); },
179 [
this]() {
return get_solver(); }},
181 [
this]() {
return m_ek_reactions; }},
183 [
this]() {
return m_is_active; }},
185 [
this]() {
return m_ek_container->is_gpu(); }},
194 context()->parallel_try_catch([&]() {
196 throw std::domain_error(
"Parameter 'tau' must be > 0");
198 if (
not params.contains(
"solver")) {
199 throw std::runtime_error(
"Parameter 'solver' is required; use EKNone "
200 "if all species are electrically neutral");
203 m_poisson_solver = extract_solver(params.at(
"solver"));
204 m_ek_container = std::make_shared<::EK::EKWalberla::ek_container_type>(
205 tau, std::visit(GetPoissonSolverCoreInstance{}, m_poisson_solver));
207 m_ek_instance = std::make_shared<::EK::EKWalberla>(
208 m_ek_container, m_ek_reactions->get_handle());
216 if (
method ==
"activate") {
221 if (
method ==
"deactivate") {