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");
107 m_ek_container->add(
obj_ptr->get_ekinstance());
111 m_ek_container->remove(
obj_ptr->get_ekinstance());
114 struct GetPoissonSolverAsVariant {
115 template <
typename T>
116 auto operator()(std::shared_ptr<T>
const &solver)
const {
122 return std::visit(GetPoissonSolverAsVariant(), m_poisson_solver);
125 struct GetPoissonSolverCoreInstance {
126 template <
typename T>
127 std::shared_ptr<::walberla::PoissonSolver>
128 operator()(std::shared_ptr<T>
const &solver)
const {
129 return solver->get_instance();
133 auto extract_solver(
Variant const &v) {
134 std::optional<
decltype(m_poisson_solver)> solver;
136 if (
auto ptr = std::dynamic_pointer_cast<EKNone>(
so_ptr)) {
137 solver = std::move(ptr);
139#ifdef ESPRESSO_WALBERLA_FFT
140 else if (
auto ptr = std::dynamic_pointer_cast<EKFFT>(
so_ptr)) {
141 solver = std::move(ptr);
144 if (
not solver.has_value()) {
145 context()->parallel_try_catch([]() {
146 throw std::invalid_argument(
"EK solver is of the wrong type");
152 void set_solver(
Variant const &v) {
155 context()->parallel_try_catch([&]() {
159 throw std::runtime_error(
160 "Cannot mix single and double precision kernels");
162 m_ek_container->set_poisson_solver(
handle);
171 [
this]() {
return m_ek_container->get_tau(); }},
172 {
"solver", [
this](
Variant const &v) { set_solver(v); },
173 [
this]() {
return get_solver(); }},
175 [
this]() {
return m_ek_reactions; }},
177 [
this]() {
return m_is_active; }},
179 [
this]() {
return m_ek_container->is_gpu(); }},
188 context()->parallel_try_catch([&]() {
190 throw std::domain_error(
"Parameter 'tau' must be > 0");
192 if (
not params.contains(
"solver")) {
193 throw std::runtime_error(
"Parameter 'solver' is required; use EKNone "
194 "if all species are electrically neutral");
197 m_poisson_solver = extract_solver(params.at(
"solver"));
198 m_ek_container = std::make_shared<::EK::EKWalberla::ek_container_type>(
199 tau, std::visit(GetPoissonSolverCoreInstance{}, m_poisson_solver));
201 m_ek_instance = std::make_shared<::EK::EKWalberla>(
202 m_ek_container, m_ek_reactions->get_handle());
210 if (
method ==
"activate") {
215 if (
method ==
"deactivate") {