diff --git a/src/core/lb/LBWalberla.cpp b/src/core/lb/LBWalberla.cpp index 17641c39b7..f31634f448 100644 --- a/src/core/lb/LBWalberla.cpp +++ b/src/core/lb/LBWalberla.cpp @@ -38,6 +38,7 @@ #include #include +#include namespace LB { @@ -128,7 +129,9 @@ void LBWalberla::update_collision_model(LBWalberlaBase &lb, LBWalberlaParams ¶ms, double kT, unsigned int seed) { auto const &system = ::System::get_system(); - if (auto le_protocol = system.lees_edwards->get_protocol()) { + auto le_protocol = system.lees_edwards->get_protocol(); + if (le_protocol and + not std::holds_alternative(*le_protocol)) { if (kT != 0.) { throw std::runtime_error( "Lees-Edwards LB doesn't support thermalization"); diff --git a/src/script_interface/lees_edwards/LeesEdwards.hpp b/src/script_interface/lees_edwards/LeesEdwards.hpp index 3d8d91182e..6efe545222 100644 --- a/src/script_interface/lees_edwards/LeesEdwards.hpp +++ b/src/script_interface/lees_edwards/LeesEdwards.hpp @@ -45,15 +45,16 @@ class LeesEdwards : public AutoParameters { add_parameters( {{"protocol", [this](Variant const &value) { + auto &system = get_system(); if (is_none(value)) { - auto const &system = get_system(); - context()->parallel_try_catch([&system]() { + context()->parallel_try_catch([&]() { auto constexpr invalid_dir = LeesEdwardsBC::invalid_dir; system.lb.lebc_sanity_checks(invalid_dir, invalid_dir); }); m_protocol = nullptr; system.box_geo->set_lees_edwards_bc(LeesEdwardsBC{}); m_lees_edwards->unset_protocol(); + system.on_lees_edwards_change(); return; } context()->parallel_try_catch([this]() { @@ -67,8 +68,15 @@ class LeesEdwards : public AutoParameters { "activation via set_boundary_conditions()"); } }); - m_protocol = get_value>(value); - m_lees_edwards->set_protocol(m_protocol->protocol()); + auto const protocol = get_value>(value); + context()->parallel_try_catch([&]() { + try { + set_protocol(protocol); + } catch (...) { + set_protocol(m_protocol); + throw; + } + }); }, [this]() { if (m_protocol) @@ -89,13 +97,13 @@ class LeesEdwards : public AutoParameters { VariantMap const ¶ms) override { if (name == "set_boundary_conditions") { context()->parallel_try_catch([this, ¶ms]() { - auto const protocol = params.at("protocol"); - if (is_none(protocol)) { - do_set_parameter("protocol", protocol); + auto const variant = params.at("protocol"); + if (is_none(variant)) { + do_set_parameter("protocol", variant); return; } // check input arguments - m_protocol = get_value>(protocol); + auto const protocol = get_value>(variant); auto const shear_direction = get_shear_axis(params, "shear_direction"); auto const shear_plane_normal = get_shear_axis(params, "shear_plane_normal"); @@ -106,10 +114,18 @@ class LeesEdwards : public AutoParameters { auto &system = get_system(); system.lb.lebc_sanity_checks(shear_direction, shear_plane_normal); // update box geometry and cell structure - system.box_geo->set_lees_edwards_bc( - LeesEdwardsBC{0., 0., shear_direction, shear_plane_normal}); - m_lees_edwards->set_protocol(m_protocol->protocol()); - system.on_lees_edwards_change(); + auto const old_shear_direction = get_lebc().shear_direction; + auto const old_shear_plane_normal = get_lebc().shear_plane_normal; + try { + system.box_geo->set_lees_edwards_bc( + LeesEdwardsBC{0., 0., shear_direction, shear_plane_normal}); + set_protocol(protocol); + } catch (...) { + system.box_geo->set_lees_edwards_bc(LeesEdwardsBC{ + 0., 0., old_shear_direction, old_shear_plane_normal}); + set_protocol(m_protocol); + throw; + } }); } return {}; @@ -159,6 +175,18 @@ class LeesEdwards : public AutoParameters { } m_params.reset(); } + + void set_protocol(std::shared_ptr const &protocol) { + auto &system = get_system(); + if (protocol) { + m_lees_edwards->set_protocol(protocol->protocol()); + } else { + system.box_geo->set_lees_edwards_bc(LeesEdwardsBC{}); + m_lees_edwards->unset_protocol(); + } + system.on_lees_edwards_change(); + m_protocol = protocol; + } }; } // namespace LeesEdwards diff --git a/testsuite/python/integrator_exceptions.py b/testsuite/python/integrator_exceptions.py index 6e11c04c36..77953f8487 100644 --- a/testsuite/python/integrator_exceptions.py +++ b/testsuite/python/integrator_exceptions.py @@ -170,7 +170,8 @@ def test_npt_integrator(self): shear_direction="x", shear_plane_normal="y", protocol=protocol) self.system.integrator.run(0) with self.assertRaisesRegex(Exception, self.msg + 'The NpT integrator cannot use Lees-Edwards'): - self.system.lees_edwards.protocol = espressomd.lees_edwards.Off() + self.system.lees_edwards.protocol = espressomd.lees_edwards.LinearShear( + shear_velocity=0., initial_pos_offset=0., time_0=0.) self.system.integrator.run(0) self.system.lees_edwards.protocol = None self.system.integrator.run(0) diff --git a/testsuite/python/lb_lees_edwards.py b/testsuite/python/lb_lees_edwards.py index 0bbc0da08e..d86530c385 100644 --- a/testsuite/python/lb_lees_edwards.py +++ b/testsuite/python/lb_lees_edwards.py @@ -41,9 +41,13 @@ def __init__(self, **kwargs): def __enter__(self): self.lbf = espressomd.lb.LBFluidWalberla( - agrid=1., density=1., kinematic_viscosity=1., tau=system.time_step, **self.kwargs) + agrid=1., density=1., kinematic_viscosity=1., + tau=system.time_step, **self.kwargs) system.lb = self.lbf - system.thermostat.set_lb(LB_fluid=self.lbf, gamma=1.0) + thmst_kwargs = {} + if "seed" in self.kwargs: + thmst_kwargs["seed"] = self.kwargs["seed"] + system.thermostat.set_lb(LB_fluid=self.lbf, gamma=1.0, **thmst_kwargs) return self.lbf def __exit__(self, exc_type, exc_value, exc_traceback): @@ -299,15 +303,17 @@ def test_lebc_mismatch(self): """ Check that MD LEbc and LB LEbc always agree. """ - err_msg = "MD and LB Lees-Edwards boundary conditions disagree" + err_msg = "Lees-Edwards LB only supports shear_plane_normal=\"y\"" # MD and LB LEbc must match - with self.assertRaisesRegex(RuntimeError, err_msg): + with self.assertRaisesRegex(ValueError, err_msg): with LBContextManager() as lbf: LEContextManager('y', 'x', 1.).initialize() + system.lees_edwards.protocol = None with LBContextManager() as lbf: LEContextManager('x', 'y', 1.).initialize() # when a LB actor with LEbc is active, the MD LEbc shear directions # are immutable + err_msg = "MD and LB Lees-Edwards boundary conditions disagree" with LEContextManager('x', 'y', 1.): with LBContextManager() as lbf: with self.assertRaisesRegex(RuntimeError, err_msg): @@ -320,7 +326,7 @@ def test_lebc_mismatch(self): self.assertEqual(system.lees_edwards.shear_plane_normal, "y") # when de-activating and later re-activating a LB actor with LEbc, # the MD LEbc must have the same shear directions - with self.assertRaisesRegex(Exception, err_msg): + with self.assertRaisesRegex(RuntimeError, err_msg): with LEContextManager('z', 'y', 1.): system.lb = lbf self.assertIsNone(system.lb) @@ -348,7 +354,7 @@ def test_lebc_mismatch(self): self.assertIsNone(system.lb) with self.assertRaisesRegex(RuntimeError, "Lees-Edwards LB doesn't support thermalization"): with LBContextManager(kT=1., seed=42) as lbf: - LEContextManager('x', 'y', 1.) + LEContextManager('x', 'y', 1.).initialize() self.assertIsNone(system.lb) with self.assertRaisesRegex(ValueError, "Lees-Edwards sweep is implemented for a ghost layer of thickness 1"):