8 concept GroupOrParticle = std::is_convertible_v<T, Group> || std::is_convertible_v<T, Particle>;
22 bool is_inside =
false;
23 Selection(
T& item,
int number_total,
int number_inside,
bool item_is_inside);
33 template <GroupOrParticle T>
36 , n_total(number_total)
37 , n_inside(number_inside)
38 , is_inside(item_is_inside)
42 enum class BiasDirection
49 double bias(
double outside_acceptance,
int n_total,
int n_inside,
50 BiasDirection direction);
63 const double outside_acceptance =
65 static BiasDirection getDirection(
bool inside_before,
bool inside_after);
66 template <std::ranges::range Range>
double getNumberInside(Range& range)
const;
69 const std::unique_ptr<Region::RegionBase>
region;
72 RegionSampler(
double outside_acceptance, std::unique_ptr<Region::RegionBase> region);
74 void to_json(
json& j)
const;
76 template <GroupOrParticle T, std::ranges::range Range>
77 std::optional<Selection<T>> select(Range& range,
Random&
random);
79 template <GroupOrParticle T>
double bias(
const Selection<T>& selection);
89 template <std::ranges::range Range>
double RegionSampler::getNumberInside(Range& range)
const 91 if (fixed_number_inside) {
92 return fixed_number_inside.value();
94 return static_cast<double>(std::ranges::count_if(
95 range, [&](
const auto& i) {
return region->inside(i); }));
110 template <GroupOrParticle T, std::ranges::range Range>
113 const auto n_total = std::ranges::distance(range.begin(), range.end());
114 int max_selection_attempts = 10 * n_total;
116 auto it = random.
sample(range.begin(), range.end());
117 if (it == range.end()) {
120 const auto inside = region->inside(*it);
121 if (not inside && outside_acceptance <
random()) {
124 return Selection<T>(*it, n_total, getNumberInside(range), inside);
125 }
while (max_selection_attempts-- > 0);
126 faunus_logger->warn(
"Max selection attempts reached. Increase outside acceptance (p) ?");
140 const auto is_inside_after = region->inside(*(selection.
item));
141 const auto direction = getDirection(selection.is_inside, is_inside_after);
142 return SmarterMonteCarlo::bias(outside_acceptance, selection.n_total, selection.n_inside,
152 using OptionalElement =
153 std::optional<std::reference_wrapper<T>>;
154 std::optional<SmarterMonteCarlo::Selection<T>>
161 void analyseSelection(
int count_inside);
166 void to_json(
json& j)
const;
167 template <std::ranges::range Range> OptionalElement select(Range& mollist,
Random&
random);
170 template <GroupOrParticle T>
186 mean_selected_inside +=
static_cast<double>(selection->is_inside);
188 if (region_sampler.fixed_number_inside) {
192 mean_number_inside +=
static_cast<double>(count_inside);
193 if (mean_number_inside.size() % 100 == 0) {
194 blocks_inside += mean_number_inside.avg();
195 if (blocks_inside.size() % 2 == 0 &&
196 blocks_inside.rsd() < 0.04) {
197 region_sampler.fixed_number_inside =
200 "Regional <N_inside> = {:.1f} converged and settled after {} iterations",
201 region_sampler.fixed_number_inside.value(), mean_number_inside.size());
216 auto bias_energy(0.0);
218 analyseSelection(selection->n_inside);
219 bias_energy = region_sampler.bias(*selection);
221 mean_bias_energy += bias_energy;
227 region_sampler.to_json(j);
228 if (mean_number_inside) {
229 j[
"mean number inside"] = mean_number_inside.avg();
231 if (mean_bias_energy) {
232 j[
"mean bias energy (kT)"] = mean_bias_energy.avg();
234 if (mean_selected_inside) {
235 j[
"selected inside fraction"] = mean_selected_inside.avg();
245 template <GroupOrParticle T>
246 template <std::ranges::range Range>
249 selection = region_sampler.select<
T>(mollist,
random);
251 return *(selection->item);
nlohmann::json json
JSON object.
Definition: json_support.h:10
Particle or groups selection for smart Monte Carlo (SMC) moves.
Definition: smart_montecarlo.h:16
Random random
global instance of Random
Definition: random.cpp:62
Helper class for smart MC moves that preferentially samples within Regions.
Definition: smart_montecarlo.h:60
Random number generator.
Definition: random.h:34
double T
floating point size
Definition: units.h:73
double bias(const Selection< T > &selection)
Definition: smart_montecarlo.h:138
std::optional< double > fixed_number_inside
Optionally give a fixed number inside.
Definition: smart_montecarlo.h:80
Iterator sample(Iterator begin, Iterator end)
Pick random element in iterable range.
Definition: random.h:61
std::unique_ptr< RegionBase > createRegion(const Space &spc, const json &j)
Expects an object where KEY is an arbitrary, user-defined name and the VALUE is another object defini...
Definition: regions.cpp:47
Definition: smart_montecarlo.cpp:4
T * item
Selected group, particle etc.
Definition: smart_montecarlo.h:19
const std::unique_ptr< Region::RegionBase > region
This defines the smart MC region.
Definition: smart_montecarlo.h:69
Placeholder for atoms and molecules.
Definition: space.h:92
std::optional< Selection< T > > select(Range &range, Random &random)
Select a random element from range and perform region check.
Definition: smart_montecarlo.h:111
double bias()
Returns the bias energy.
Definition: smart_montecarlo.h:214
OptionalElement select(Range &mollist, Random &random)
Definition: smart_montecarlo.h:247
Selection(T &item, int number_total, int number_inside, bool item_is_inside)
Definition: smart_montecarlo.h:34
Helper class for constructing smart monte carlo moves.
Definition: smart_montecarlo.h:149