CASM  1.1.0
A Clusters Approach to Statistical Mechanics
ConfigEnumStrain.cc
Go to the documentation of this file.
2 
3 #include <algorithm>
4 
10 #include "casm/misc/CASM_math.hh"
11 #include "casm/misc/algorithm.hh"
13 
14 namespace CASM {
15 
16 namespace {
17 
18 // Increment past any values outside ellipsoid defined by shape_factor
19 // matrix (if trim_corners==true)
20 void advance_past_corners(EigenCounter<Eigen::VectorXd> &counter,
21  Eigen::MatrixXd shape_factor) {
22  while (counter.valid() &&
23  double(counter().transpose() * shape_factor * counter()) > 1.0 + TOL) {
24  ++counter;
25  }
26 }
27 
28 } // namespace
29 
31  ConfigEnumStrainParams const &params)
32  : ConfigEnumStrain(initial_state, params.wedges, params.min_val,
33  params.max_val, params.inc_val, params.dof,
34  params.auto_range, params.trim_corners) {}
35 
37  ConfigEnumInput const &initial_state,
38  std::vector<SymRepTools_v2::SubWedge> const &wedges,
39  Eigen::VectorXd min_val, Eigen::VectorXd max_val, Eigen::VectorXd inc_val,
40  DoFKey const &strain_key, bool auto_range, bool trim_corners)
41  : m_strain_key(strain_key),
42  m_trim_corners(trim_corners),
43  m_current(initial_state.configuration()),
44  m_equiv_ind(0),
45  m_wedges(wedges),
46  m_shape_factor(
47  Eigen::MatrixXd::Identity(min_val.size(), min_val.size())) {
48  // Check there are wedges to counter over
49  if (m_wedges.size() == 0) return;
50 
51  // Check for dimensional mismatches
52  if (min_val.size() != m_wedges[0].trans_mat().cols() ||
53  min_val.size() != inc_val.size() || min_val.size() != max_val.size()) {
54  std::stringstream msg;
55  msg << "Error in ConfigEnumStrain: dimension mismatch";
56  throw std::runtime_error(msg.str());
57  }
58 
59  // Check for very small inc_val that would cause problems. Currently it is
60  // hard-coded that there should not be >1e4 points along a dimension
61  for (int d = 0; d < inc_val.size(); ++d) {
62  if (inc_val(d) == 0. || (max_val(d) - min_val(d)) / inc_val(d) > 1e4) {
63  std::stringstream msg;
64  msg << "Error in ConfigEnumStrain: Increment along dimension " << d + 1
65  << " is too small: " << inc_val(d);
66  throw std::runtime_error(msg.str());
67  }
68  }
69 
70  // If auto_range==true, set min_val[i]=-max_val[i], for strain components, i,
71  // with multiplicity==1. Typically, set to true if using symmetry adapted axes
72  if (auto_range) {
73  int d = 0;
74  for (auto const &irrep_wedge : m_wedges[0].irrep_wedges()) {
75  for (int i = 0; i < irrep_wedge.axes.cols(); ++i) {
76  if (irrep_wedge.mult[i] == 1) {
77  min_val(d) = -max_val(d);
78  }
79  d++;
80  }
81  }
82  }
83 
84  // If trim_corners==true, set shape_factor matrix to exclude grid points
85  // that lie outside an ellipsoid defined by most extreme min_val/max_val
86  // Excluded if:
87  // m_counter().transpose() * m_shape_factor * m_counter() > 1.0 + TOL
88  if (m_trim_corners) {
89  int dim = min_val.size();
90  for (int d = 0; d < dim; ++d) {
91  double mag = max(abs(min_val(d)), abs(max_val(d)));
92  m_shape_factor(d, d) = 1. / (mag * mag);
93  }
94  }
95 
96  // Find first valid config
97  m_counter = EigenCounter<Eigen::VectorXd>(min_val, max_val, inc_val);
98  m_counter.reset();
99  if (m_trim_corners) advance_past_corners(m_counter, m_shape_factor);
100 
103  m_strain_key, m_wedges[m_equiv_ind].trans_mat() * m_counter());
104  this->_initialize(&m_current);
105 
106  if (!m_counter.valid()) {
107  this->_invalidate();
108  }
109 
110  m_current.set_source(this->source(step()));
111 }
112 
113 // Implements _increment
115  ++m_counter;
116  if (m_trim_corners) advance_past_corners(m_counter, m_shape_factor);
117 
118  // Move to next part of wedge if necessary
119  if (!m_counter.valid() && m_equiv_ind + 1 < m_wedges.size()) {
120  m_counter.reset();
121  ++m_equiv_ind;
122 
123  if (m_trim_corners) advance_past_corners(m_counter, m_shape_factor);
124  }
125 
126  if (m_counter.valid()) {
128  m_strain_key, m_wedges[m_equiv_ind].trans_mat() * m_counter());
129 
130  _increment_step();
131  } else {
132  _invalidate();
133  }
134 
135  m_current.set_source(this->source(step()));
136  return;
137 }
138 
139 std::string ConfigEnumStrain::name() const { return enumerator_name; }
140 
141 const std::string ConfigEnumStrain::enumerator_name = "ConfigEnumStrain";
142 
144 
146  return m_counter();
147 }
148 
149 } // namespace CASM
void set_global_dof(DoFKey const &_key, Eigen::Ref< const Eigen::VectorXd > const &_val)
Set global continuous DoF values.
Definition: ConfigDoF.cc:99
static const std::string enumerator_name
std::string name() const override
Derived enumerators must implement name, via ENUM_MEMBERS.
Eigen::VectorXd normal_coordinate() const
EigenCounter< Eigen::VectorXd > m_counter
Eigen::MatrixXd m_shape_factor
ConfigEnumStrain(ConfigEnumInput const &initial_state, ConfigEnumStrainParams const &params)
void increment() override
Implements increment over all strain states.
std::vector< SymRepTools_v2::SubWedge > m_wedges
const ConfigDoF & configdof() const
const Access the DoF
A Counter allows looping over many incrementing variables in one loop.
Definition: Counter.hh:109
virtual jsonParser source(step_type step) const
Definition: Enumerator.hh:129
void _invalidate()
Call if enumeration complete.
Definition: Enumerator.hh:159
void _increment_step()
Increment current step value.
Definition: Enumerator.hh:153
step_type step() const
Increments with each enumerated object.
Definition: Enumerator.hh:115
IdentitySymRepBuilder Identity()
std::vector< IrrepWedge > irrep_wedges(SymGroup const &head_group, SymGroupRepID id, Eigen::Ref< const Eigen::MatrixXd > const &_subspace)
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::MatrixXd MatrixXd
void reset_properties(ConfigType &config)
Definition: Calculable.cc:147
const double TOL
Definition: definitions.hh:30
std::string DoFKey
Definition: DoFDecl.hh:7
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Eigen::VectorXd VectorXd
T max(const T &A, const T &B)
Definition: CASM_math.hh:95