30#include "system/System.hpp"
31#include "thermostat.hpp"
33#ifdef ESPRESSO_WALBERLA
55static auto is_solver_set(std::unique_ptr<Solver::Implementation>
const &ptr) {
56 return ptr !=
nullptr and ptr->solver.has_value();
59static void check_solver(std::unique_ptr<Solver::Implementation>
const &ptr) {
74 std::visit([](
auto &ptr) { ptr->propagate(); }, *impl->solver);
79 std::visit([](
auto &ptr) { ptr->ghost_communication(); }, *impl->solver);
84 std::visit([](
auto &ptr) { ptr->ghost_communication_pdf(); }, *impl->solver);
89 std::visit([](
auto &ptr) { ptr->ghost_communication_vel(); }, *impl->solver);
95 std::visit([&](
auto &ptr) { ptr->sanity_checks(system); }, *impl->solver);
101 std::visit([=](
auto &ptr) { ptr->veto_time_step(time_step); },
108 std::visit([=](
auto &ptr) { ptr->veto_kT(kT); }, *impl->solver);
113 unsigned int shear_plane_normal)
const {
115 auto const callback = [=](
auto &ptr) {
116 ptr->lebc_sanity_checks(shear_direction, shear_plane_normal);
118 std::visit(callback, *impl->solver);
124 auto &solver = *impl->solver;
125 std::visit([](
auto &ptr) { ptr->on_cell_structure_change(); }, solver);
131 std::visit([](
auto const &ptr) { ptr->veto_boxl_change(); }, *impl->solver);
137 std::visit([](
auto &ptr) { ptr->on_boxl_change(); }, *impl->solver);
143 std::visit([](
auto &ptr) { ptr->on_node_grid_change(); }, *impl->solver);
149 std::visit([](
auto &ptr) { ptr->on_timestep_change(); }, *impl->solver);
155 std::visit([](
auto &ptr) { ptr->on_temperature_change(); }, *impl->solver);
161 std::visit([](
auto &ptr) { ptr->on_lees_edwards_change(); }, *impl->solver);
167 std::visit([](
auto &ptr) { ptr->update_collision_model(); }, *impl->solver);
173 return std::visit([](
auto &ptr) {
return ptr->is_gpu(); }, *impl->solver);
178 return std::visit([](
auto &ptr) {
return ptr->get_agrid(); }, *impl->solver);
183 return std::visit([](
auto &ptr) {
return ptr->get_tau(); }, *impl->solver);
188 return std::visit([](
auto &ptr) {
return ptr->get_kT(); }, *impl->solver);
193 return std::visit([](
auto &ptr) {
return ptr->get_pressure_tensor(); },
202 return [&, kernel = ptr->make_lattice_position_checker(
204 return kernel(box_geo.folded_position(pos) * m_conv.
pos_to_lb);
210std::optional<Utils::Vector3d>
218 auto const lb_pos = box_geo.folded_position(pos) * m_conv.
pos_to_lb;
219 return ptr->get_velocity_at_pos(lb_pos,
false);
229 auto const lb_pos = box_geo.folded_position(pos) * m_conv.
pos_to_lb;
230 return ptr->get_density_at_pos(lb_pos,
false);
236 std::vector<Utils::Vector3d>
const &pos)
const {
240 std::vector<Utils::Vector3d> pos_lb;
241 pos_lb.reserve(pos.size());
242 for (
auto const &pos_md : pos) {
243 pos_lb.emplace_back(box_geo.folded_position(pos_md) *
246 return ptr->get_densities_at_pos(pos_lb);
255 auto const res = ptr->get_velocity_at_pos(pos * m_conv.
pos_to_lb,
true);
263 std::vector<Utils::Vector3d>
const &pos)
const {
266 std::vector<Utils::Vector3d> pos_lb;
267 pos_lb.reserve(pos.size());
268 for (
auto const &pos_md : pos) {
269 pos_lb.emplace_back(pos_md * m_conv.
pos_to_lb);
271 auto res = ptr->get_velocities_at_pos(pos_lb);
272 for (
auto &v : res) {
281 std::vector<Utils::Vector3d>
const &forces) {
284 std::vector<Utils::Vector3d> pos_lb;
285 std::vector<Utils::Vector3d> force_lb;
286 pos_lb.reserve(pos.size());
287 force_lb.reserve(pos.size());
288 for (
auto const &pos_md : pos) {
289 pos_lb.emplace_back(pos_md * m_conv.
pos_to_lb);
291 for (
auto const &force_md : forces) {
292 force_lb.emplace_back(force_md * m_conv.
force_to_lb);
294 ptr->add_forces_at_pos(pos_lb, force_lb);
303 if (not ptr->add_force_at_pos(pos * m_conv.
pos_to_lb,
305 throw std::runtime_error(
"Cannot apply force to LB");
313 return std::visit([](
auto const &ptr) {
return ptr->get_momentum(); },
317template <>
void Solver::set<LBNone>(std::shared_ptr<LBNone> lb_instance) {
319 assert(not impl->solver.has_value());
320 impl->solver = lb_instance;
323#ifdef ESPRESSO_WALBERLA
325void Solver::set<LBWalberla>(std::shared_ptr<LBWalberlaBase> lb_fluid,
326 std::shared_ptr<LBWalberlaParams> lb_params) {
328 assert(not impl->solver.has_value());
330 auto lb_instance = std::make_shared<LBWalberla>(lb_fluid, lb_params);
331 lb_instance->sanity_checks(system);
332 auto const &lebc = system.box_geo->lees_edwards_bc();
333 lb_fluid->check_lebc(lebc.shear_direction, lebc.shear_plane_normal);
334 impl->solver = lb_instance;
335 auto const agrid = lb_instance->get_agrid();
336 auto const tau = lb_instance->get_tau();
337 m_conv =
Conversions{1. / agrid, agrid / tau, tau * tau / agrid};
LBWalberlaBase provides the public interface of the LB waLBerla bridge.
Vector implementation and trait types for boost qvm interoperability.
std::shared_ptr< BoxGeometry > box_geo
static auto is_solver_set(std::unique_ptr< Solver::Implementation > const &ptr)
static void check_solver(std::unique_ptr< Solver::Implementation > const &ptr)
void veto_boxl_change() const
void lebc_sanity_checks(unsigned int shear_direction, unsigned int shear_plane_normal) const
Perform LB LEbc parameter checks.
std::vector< double > get_interpolated_densities(std::vector< Utils::Vector3d > const &pos) const
Calculate the interpolated fluid densities in LB units.
void add_force_density(Utils::Vector3d const &pos, Utils::Vector3d const &force_density)
Add a force density to the fluid at the given position.
std::function< bool(Utils::Vector3d const &)> make_lattice_position_checker(bool consider_points_in_halo) const
Make a functor to check if a position is in the local domain.
Utils::Vector3d get_coupling_interpolated_velocity(Utils::Vector3d const &pos) const
Calculate the interpolated fluid velocity in MD units.
void sanity_checks() const
Perform LB parameter and boundary velocity checks.
void on_timestep_change()
void ghost_communication()
Perform a full ghost communication.
void propagate()
Propagate the LB fluid.
void reset()
Remove the LB solver.
std::optional< Utils::Vector3d > get_interpolated_velocity(Utils::Vector3d const &pos) const
Calculate the interpolated fluid velocity in LB units.
bool is_solver_set() const
Return true if a LB solver is active.
void ghost_communication_pdf()
Perform a ghost communication of the PDF field.
double get_tau() const
Get the LB time step.
void on_temperature_change()
std::optional< double > get_interpolated_density(Utils::Vector3d const &pos) const
Calculate the interpolated fluid density in LB units.
void add_forces_at_pos(std::vector< Utils::Vector3d > const &pos, std::vector< Utils::Vector3d > const &forces)
void veto_kT(double kT) const
Check if a thermostat is compatible with the LB temperature.
double get_agrid() const
Get the LB grid spacing.
Utils::VectorXd< 9 > get_pressure_tensor() const
void update_collision_model()
void veto_time_step(double time_step) const
Check if a MD time step is compatible with the LB tau.
void ghost_communication_vel()
Perform a ghost communication of the velocity field.
void on_lees_edwards_change()
void on_node_grid_change()
Utils::Vector3d get_momentum() const
void on_cell_structure_change()
std::vector< Utils::Vector3d > get_coupling_interpolated_velocities(std::vector< Utils::Vector3d > const &pos) const
Calculate the interpolated fluid velocities in MD units.
double get_kT() const
Get the thermal energy parameter of the LB fluid.