151 using data_t =
typename G::data_t;
152 using value_t =
typename G::scalar_t;
153 using data_index_t = std::array<long, static_cast<std::size_t>(nda::get_rank<data_t>)>;
154 using data_sym_func_t = std::function<std::tuple<data_index_t, nda::operation>(data_index_t
const &)>;
155 using data_init_func_t = std::function<value_t(data_index_t
const &)>;
158 using mesh_index_t =
typename G::mesh_t::index_t;
162 static constexpr size_t target_rank = G::target_rank;
163 using target_index_t = std::array<long, static_cast<std::size_t>(target_rank)>;
166 nda::sym_grp<data_sym_func_t, data_t> data_sym_grp;
169 data_sym_func_t to_data_symmetry(F
const &f, G
const &g)
const {
171 auto fp = [f, m = g.mesh()](data_index_t
const &x) -> std::tuple<data_index_t, nda::operation> {
175 if constexpr (target_rank == 0) {
177 if constexpr (mesh_rank == 1) {
178 auto [new_mesh_index, op] = f(m.to_index(x[0]));
179 xp[0] = m.to_data_index(new_mesh_index);
183 auto [new_mesh_index, op] = f(m.to_index(to_tuple(x)));
184 xp = to_array(m.to_data_index(new_mesh_index));
191 target_index_t target_index;
192 for (
auto i : range(target_rank)) target_index[i] = x[i + mesh_rank];
194 if constexpr (mesh_rank == 1) {
196 auto [new_mesh_index, new_target_index, op] = f(m.to_index(x[0]), target_index);
199 xp[0] = m.to_data_index(new_mesh_index);
200 for (
auto i : range(target_rank)) xp[i + mesh_rank] = new_target_index[i];
206 auto [new_mesh_index, new_target_index, op] = f(m.to_index(to_tuple<mesh_rank>(x)), target_index);
209 auto new_mesh_arr = to_array(m.to_data_index(new_mesh_index));
210 for (
auto i : range(mesh_rank)) xp[i] = new_mesh_arr[i];
211 for (
auto i : range(target_rank)) xp[i + mesh_rank] = new_target_index[i];
222 std::vector<data_sym_func_t> to_data_symmetry_list(G
const &g, std::vector<F>
const &sym_list)
const {
223 std::vector<data_sym_func_t> data_sym_list;
224 for (
auto f : sym_list) data_sym_list.push_back(to_data_symmetry(f, g));
225 return data_sym_list;
229 template <
typename H> data_init_func_t to_data_init_func(G
const &g, H
const &h)
const {
231 auto hp = [h, m = g.mesh()](data_index_t
const &x) {
232 if constexpr (target_rank == 0) {
234 if constexpr (mesh_rank == 1) {
235 return h(m.to_index(x[0]));
238 return h(m.to_index(to_tuple(x)));
243 target_index_t target_index;
244 for (
auto i : range(target_rank)) target_index[i] = x[i + mesh_rank];
246 if constexpr (mesh_rank == 1) {
247 return h(m.to_index(x[0]), target_index);
250 return h(m.to_index(to_tuple<mesh_rank>(x)), target_index);
264 [[nodiscard]] nda::sym_grp<data_sym_func_t, data_t>
const &
get_data_sym_grp()
const {
return data_sym_grp; }
271 [[nodiscard]]
long num_classes()
const {
return data_sym_grp.num_classes(); }
279 [[nodiscard]] std::vector<value_t>
get_representative_data(G
const &g)
const {
return data_sym_grp.get_representative_data(g.data()); }
302 sym_grp(G
const &g, std::vector<F>
const &sym_list,
long const max_length = 0)
303 : data_sym_grp{g.
data(), to_data_symmetry_list(g, sym_list), max_length} {};
316 template <
typename H>
317 void init(G &g, H
const &h,
bool parallel =
false) const
320 data_sym_grp.init(g.data(), to_data_init_func(g, h), parallel);
332 std::tuple<double, mesh_index_t, target_index_t>
symmetrize(G &g)
const {
333 auto const &[max_diff, max_index] = data_sym_grp.symmetrize(g.data());
334 auto const m = g.mesh();
336 if constexpr (target_rank == 0) {
338 if constexpr (mesh_rank == 1) {
339 return {max_diff, m.to_index(max_index[0]), {}};
342 return {max_diff, m.to_index(to_tuple(max_index)), {}};
348 target_index_t target_index;
349 for (
auto i : range(target_rank)) target_index[i] = max_index[i + mesh_rank];
351 if constexpr (mesh_rank == 1) {
352 return {max_diff, m.to_index(max_index[0]), target_index};
355 return {max_diff, m.to_index(to_tuple<mesh_rank>(max_index)), target_index};