From c14ae0790e04b7f3d6261ea536464d7665f7fefe Mon Sep 17 00:00:00 2001 From: jeremiah Date: Fri, 24 Apr 2026 15:02:28 -0700 Subject: [PATCH 1/2] fix fails_required_occ_init --- src/casm/configuration/occ_events/OccEventCounter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/casm/configuration/occ_events/OccEventCounter.cc b/src/casm/configuration/occ_events/OccEventCounter.cc index 95f0d76..b941173 100644 --- a/src/casm/configuration/occ_events/OccEventCounter.cc +++ b/src/casm/configuration/occ_events/OccEventCounter.cc @@ -254,7 +254,7 @@ class OccInitCounter : public SingleStepBase { /// \brief Check if initial occupation satisifies /// required occupation (required_occ_init) bool fails_required_occ_init() const { - if (!data()->params.required_init_atom_count.has_value()) { + if (!data()->params.required_occ_init.has_value()) { return false; } std::vector const &occ_init = data()->occ_init_counter(); From ab8ceedb4b2d83b4da867e0d1f3175412ac84018 Mon Sep 17 00:00:00 2001 From: jeremiah Date: Fri, 24 Apr 2026 22:49:10 -0700 Subject: [PATCH 2/2] add n_required_sublattices option --- .../configuration/occ_events/OccEventCounter.hh | 1 + python/libcasm/occ_events/_methods.py | 11 +++++++++-- .../configuration/occ_events/OccEventCounter.cc | 14 ++++++++++++-- .../occ_events/io/json/OccEventCounter_json_io.cc | 2 ++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/casm/configuration/occ_events/OccEventCounter.hh b/include/casm/configuration/occ_events/OccEventCounter.hh index b9e0672..61e46de 100644 --- a/include/casm/configuration/occ_events/OccEventCounter.hh +++ b/include/casm/configuration/occ_events/OccEventCounter.hh @@ -67,6 +67,7 @@ struct OccEventCounterParameters { std::optional required_cluster_size; std::optional> excluded_sublattices; std::optional> required_sublattices; + std::optional n_required_sublattices; /// \brief Optional customizeable filter to skip or allow events /// based on the cluster. Return true to allow, diff --git a/python/libcasm/occ_events/_methods.py b/python/libcasm/occ_events/_methods.py index f5a424d..174dcc2 100644 --- a/python/libcasm/occ_events/_methods.py +++ b/python/libcasm/occ_events/_methods.py @@ -180,8 +180,15 @@ def make_canonical_prim_periodic_occevents( Filter by sublattice, using sublattice indices: - - "excluded_sublattices": Optional[list[int]] = None - - "required_sublattices": Optional[list[int]] = None + - "excluded_sublattices": Optional[list[int]] = None, Do not include + events that contain any of these sublattices. + - "required_sublattices": Optional[list[int]] = None, Only include + events that contain these sublattices. Events may contain additional + sublattices not specified in `required_sublattices`. + - "n_required_sublattices": Optional[int] = None, Set how many + sublattices from `required_sublattices` the event must contain. + The default is that the event must contain every sublattice in + `required_sublattices`. Filter by occupation, using occupation variable on each cluster site: diff --git a/src/casm/configuration/occ_events/OccEventCounter.cc b/src/casm/configuration/occ_events/OccEventCounter.cc index b941173..0383031 100644 --- a/src/casm/configuration/occ_events/OccEventCounter.cc +++ b/src/casm/configuration/occ_events/OccEventCounter.cc @@ -121,7 +121,7 @@ class PrototypeClusterCounter : public SingleStepBase { return false; } - /// \brief Check if cluster does not include any + /// \brief Check if cluster includes sufficient number of /// required sublattice (required_sublattices) bool fails_required_sublattices() const { if (!data()->params.required_sublattices.has_value()) { @@ -137,10 +137,20 @@ class PrototypeClusterCounter : public SingleStepBase { if (it != has_sublattice.end()) { it->second = true; } + } + // require at least n_required_sublattices matches + // of sublattices in required_sublattices + int misses_remaining = 0; // default must match all (no misses) + if (data()->params.n_required_sublattices.has_value()) { + int n_required_sublattices = *data()->params.n_required_sublattices; + misses_remaining = + static_cast(has_sublattice.size()) - n_required_sublattices; } for (auto const &pair : has_sublattice) { if (pair.second == false) { - return true; + if (--misses_remaining < 0) { + return true; + } } } return false; diff --git a/src/casm/configuration/occ_events/io/json/OccEventCounter_json_io.cc b/src/casm/configuration/occ_events/io/json/OccEventCounter_json_io.cc index e8262d8..1c7ac64 100644 --- a/src/casm/configuration/occ_events/io/json/OccEventCounter_json_io.cc +++ b/src/casm/configuration/occ_events/io/json/OccEventCounter_json_io.cc @@ -75,6 +75,7 @@ jsonParser &to_json(occ_events::OccEventCounterParameters const ¶ms, _to_json(params.required_cluster_size, "required_cluster_size"); _to_json(params.excluded_sublattices, "excluded_sublattices"); _to_json(params.required_sublattices, "required_sublattices"); + _to_json(params.n_required_sublattices, "n_required_sublattices"); _to_json(params.required_occ_init, "required_occ_init"); @@ -141,6 +142,7 @@ void parse(InputParser &parser) { parser.optional(params.required_cluster_size, "required_cluster_size"); parser.optional(params.excluded_sublattices, "excluded_sublattices"); parser.optional(params.required_sublattices, "required_sublattices"); + parser.optional(params.n_required_sublattices, "n_required_sublattices"); parser.optional(params.required_occ_init, "required_occ_init");