Skip to content

Commit 6e38c00

Browse files
committed
update
1 parent 3750e86 commit 6e38c00

13 files changed

Lines changed: 392 additions & 422 deletions

File tree

SuPyMode/_version.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
commit_id: COMMIT_ID
2929
__commit_id__: COMMIT_ID
3030

31-
__version__ = version = "2.1.6"
32-
__version_tuple__ = version_tuple = (2, 1, 6)
31+
__version__ = version = "2.2.0"
32+
__version_tuple__ = version_tuple = (2, 2, 0)
3333

34-
__commit_id__ = commit_id = "g88eeb5109"
34+
__commit_id__ = commit_id = "ge15358cc2"

SuPyMode/cpp/eigensolver/eigensolver.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "eigensolver.h"
22

3+
34
void EigenSolver::initialize(
45
const ModelParameters &model_parameters,
56
const pybind11::array_t<double> &finit_difference_triplets_py,
@@ -18,6 +19,8 @@ void EigenSolver::initialize(
1819

1920
this->generate_mode_set();
2021

22+
this->compute_laplacian();
23+
2124
}
2225

2326

@@ -159,8 +162,10 @@ void EigenSolver::populate_sorted_supermodes(size_t slice, Eigen::MatrixXd &eige
159162
}
160163
}
161164

162-
void EigenSolver::loop_over_itr(double alpha)
165+
void EigenSolver::loop_over_itr(const double guess_index, bool auto_label)
163166
{
167+
double alpha = this->index_to_eigenvalue(guess_index);
168+
164169
if (this->model_parameters.debug_mode > 0)
165170
std::cout << "Starting iterative eigenvalue computation with extrapolation order: " << this->extrapolation_order << ", alpha: " << alpha << std::endl;
166171

@@ -212,6 +217,24 @@ void EigenSolver::loop_over_itr(double alpha)
212217
this->normalize_mode_field();
213218

214219
this->arrange_mode_field();
220+
221+
for (SuperMode& supermode: sorted_supermodes) {
222+
supermode.mode_number = this->mode_number++;
223+
supermode.solver_number = this->solver_number;
224+
}
225+
226+
size_t index = 0;
227+
if (auto_label)
228+
for (SuperMode& supermode: sorted_supermodes) {
229+
supermode.label = mode_labeler.get(supermode.boundaries, index);
230+
++index;
231+
}
232+
else
233+
for (SuperMode& supermode: sorted_supermodes) {
234+
supermode.label = "mode_" + std::to_string(supermode.mode_number);
235+
}
236+
237+
this->solver_number++;
215238
}
216239

217240
void EigenSolver::sort_mode_per_last_propagation_constant()

SuPyMode/cpp/eigensolver/eigensolver.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "../utils/progress_bar.h"
1212
#include "../utils/numpy_interface.h"
1313
#include "boundaries/boundaries.h"
14+
#include "model_parameters/model_parameters.h"
15+
#include "mode_labeler.h"
16+
1417
#include <iostream>
1518

1619
class EigenSolver
@@ -39,6 +42,7 @@ class EigenSolver
3942
Eigen::VectorXd previous_eigen_values;
4043

4144
std::vector<double> alpha_vector;
45+
ModeLabeler mode_labeler;
4246

4347
public:
4448
Eigen::SparseMatrix<double, Eigen::ColMajor> laplacian_matrix;
@@ -49,11 +53,13 @@ class EigenSolver
4953
double k_taper;
5054

5155
EigenSolver(
56+
ModelParameters &model_parameters,
5257
const size_t max_iteration,
5358
const double tolerance,
5459
const size_t accuracy,
5560
const size_t extrapolation_order)
56-
: max_iteration(max_iteration),
61+
: model_parameters(model_parameters),
62+
max_iteration(max_iteration),
5763
tolerance(tolerance),
5864
accuracy(accuracy),
5965
extrapolation_order(extrapolation_order)
@@ -105,7 +111,7 @@ class EigenSolver
105111
* \param alpha The alpha parameter for the eigenvalue problem.
106112
* \return A tuple containing the eigenvalues and eigenvectors.
107113
*/
108-
SuperMode &get_sorted_mode(size_t mode_number){ return sorted_supermodes[mode_number]; }
114+
SuperMode &get_sorted_mode(const size_t mode_number) { return sorted_supermodes[mode_number]; }
109115

110116
/**
111117
* \brief Generates the mode set based on the model parameters.
@@ -151,7 +157,7 @@ class EigenSolver
151157
* \param extrapolation_order The order of extrapolation for the eigenvalue problem.
152158
* \param alpha The alpha parameter for the eigenvalue problem.
153159
*/
154-
void loop_over_itr(double alpha = 0);
160+
void loop_over_itr(double guess_index, bool auto_label);
155161

156162
/**
157163
* \brief Sorts the modes based on the last propagation constant.

SuPyMode/cpp/eigensolver/interface.cpp

Lines changed: 19 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ PYBIND11_MODULE(interface_eigensolver, module)
3939
- Mode sorting and selection
4040
)pbdoc"
4141
)
42-
.def(pybind11::init<const size_t, const double, const size_t, const size_t>(),
42+
.def(pybind11::init<ModelParameters&, const size_t, const double, const size_t, const size_t>(),
43+
pybind11::arg("model_parameters"),
4344
pybind11::arg("max_iteration") = 10'000,
4445
pybind11::arg("tolerance") = 1e-8,
4546
pybind11::arg("accuracy") = 2,
@@ -62,6 +63,17 @@ PYBIND11_MODULE(interface_eigensolver, module)
6263
Order of Richardson extrapolation for iterative eigenvalue computation (e.g., 1, 2, 3)
6364
)pbdoc"
6465
)
66+
.def_readonly(
67+
"model_parameters",
68+
&EigenSolver::model_parameters,
69+
R"pbdoc(
70+
Model parameters for the eigenvalue solver.
71+
72+
This parameter provides access to the model parameters used in the
73+
eigenvalue solver, including grid spacing, mesh size, and other
74+
relevant physical and numerical parameters.
75+
)pbdoc"
76+
)
6577
.def_readonly(
6678
"accuracy",
6779
&EigenSolver::accuracy,
@@ -175,7 +187,7 @@ PYBIND11_MODULE(interface_eigensolver, module)
175187
The mode index corresponding to the given eigenvalue.
176188
)pbdoc"
177189
)
178-
.def("_cpp_set_boundaries",
190+
.def("set_boundaries",
179191
&EigenSolver::setup_boundaries,
180192
pybind11::arg("left"),
181193
pybind11::arg("right"),
@@ -205,7 +217,7 @@ PYBIND11_MODULE(interface_eigensolver, module)
205217
If boundary conditions are not recognized.
206218
)pbdoc"
207219
)
208-
.def("_cpp_initialize",
220+
.def("initialize",
209221
&EigenSolver::initialize,
210222
pybind11::arg("model_parameters"),
211223
pybind11::arg("finit_matrix"),
@@ -237,7 +249,8 @@ PYBIND11_MODULE(interface_eigensolver, module)
237249
.def(
238250
"loop_over_itr",
239251
&EigenSolver::loop_over_itr,
240-
pybind11::arg("alpha"),
252+
pybind11::arg("guess_index"),
253+
pybind11::arg("auto_label") = true,
241254
R"pbdoc(
242255
Perform iterative eigenvalue computation with extrapolation.
243256
@@ -274,38 +287,7 @@ PYBIND11_MODULE(interface_eigensolver, module)
274287
)pbdoc"
275288
)
276289
.def(
277-
"_cpp_compute_laplacian",
278-
&EigenSolver::compute_laplacian,
279-
R"pbdoc(
280-
Compute the Laplacian operator matrix for the finite difference grid.
281-
282-
This method constructs the discrete Laplacian operator used in the
283-
wave equation eigenvalue problem. The Laplacian is computed using
284-
finite difference approximations on the computational grid.
285-
286-
The method handles:
287-
- Grid spacing variations
288-
- Boundary condition implementation
289-
- Coordinate system transformations (cylindrical)
290-
291-
Returns
292-
-------
293-
None
294-
The computed Laplacian is stored internally and used by the
295-
eigenvalue solver.
296-
297-
Notes
298-
-----
299-
This method should be called before solving for eigenvalues.
300-
The Laplacian matrix is typically sparse and stored efficiently
301-
using appropriate data structures.
302-
303-
The finite difference stencil used depends on the accuracy order
304-
specified in the model parameters, with higher orders providing
305-
better accuracy at the cost of increased computational complexity.
306-
)pbdoc"
307-
)
308-
.def("_cpp_reset_solver",
290+
"reset_solver",
309291
&EigenSolver::reset_solver,
310292
R"pbdoc(
311293
Reset the eigenvalue solver to its initial state.
@@ -326,7 +308,7 @@ PYBIND11_MODULE(interface_eigensolver, module)
326308
)pbdoc"
327309
)
328310
.def(
329-
"_cpp_get_mode",
311+
"get_sorted_mode",
330312
&EigenSolver::get_sorted_mode,
331313
R"pbdoc(
332314
Retrieve computed and sorted eigenmodes.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <vector>
5+
#include <tuple>
6+
#include <array>
7+
#include <utility>
8+
#include <stdexcept>
9+
10+
// Uses your existing types
11+
// enum class BoundaryCondition { Zero, Symmetric, AntiSymmetric };
12+
// class Boundaries { public: BoundaryCondition left, right, top, bottom; ... };
13+
14+
class ModeLabeler {
15+
public:
16+
ModeLabeler() = default;
17+
18+
std::string get(const Boundaries& boundaries, const size_t mode_number) const
19+
{
20+
const BoundaryCondition x_parity = get_parity(boundaries.left, boundaries.right);
21+
const BoundaryCondition y_parity = get_parity(boundaries.top, boundaries.bottom);
22+
23+
const std::vector<ModeTuple> filtered_modes = get_filtered_mode_list(x_parity, y_parity);
24+
25+
if (mode_number >= filtered_modes.size()) {
26+
throw std::out_of_range(
27+
"Mode number " + std::to_string(mode_number) +
28+
" exceeds available modes. Max allowed: " +
29+
(filtered_modes.empty() ? std::string("none") : std::to_string(filtered_modes.size() - 1))
30+
);
31+
}
32+
33+
const auto& [azimuthal, radial, sub_label] = filtered_modes[mode_number];
34+
return "LP" + std::to_string(azimuthal) + std::to_string(radial) + sub_label;
35+
}
36+
37+
private:
38+
using ModeTuple = std::tuple<int, int, std::string>;
39+
40+
struct ModeEntry {
41+
int azimuthal;
42+
int radial;
43+
std::string sub_label;
44+
BoundaryCondition x_parity;
45+
BoundaryCondition y_parity;
46+
};
47+
48+
private:
49+
static BoundaryCondition get_parity(
50+
const BoundaryCondition boundary_1,
51+
const BoundaryCondition boundary_2
52+
) {
53+
if (boundary_1 == BoundaryCondition::Symmetric || boundary_2 == BoundaryCondition::Symmetric)
54+
return BoundaryCondition::Symmetric;
55+
56+
if (boundary_1 == BoundaryCondition::AntiSymmetric || boundary_2 == BoundaryCondition::AntiSymmetric)
57+
return BoundaryCondition::AntiSymmetric;
58+
59+
return BoundaryCondition::Zero;
60+
}
61+
62+
static const std::vector<std::pair<int, int>>& get_azimuthal_radial_pairs()
63+
{
64+
static const std::vector<std::pair<int, int>> pairs = {
65+
{0, 1}, {1, 1}, {2, 1}, {0, 2}, {3, 1}, {1, 2}, {4, 1},
66+
{2, 2}, {0, 3}, {5, 1}, {3, 2}, {1, 3}, {6, 1},
67+
};
68+
return pairs;
69+
}
70+
71+
static const std::vector<ModeEntry>& get_mode_catalog()
72+
{
73+
static const std::vector<ModeEntry> catalog = []() {
74+
std::vector<ModeEntry> entries;
75+
entries.reserve(64);
76+
77+
for (const auto& [azimuthal, radial] : get_azimuthal_radial_pairs())
78+
{
79+
std::vector<std::array<BoundaryCondition, 2>> parities;
80+
std::vector<std::string> sublabels;
81+
82+
if (azimuthal == 0) {
83+
parities = { {BoundaryCondition::Symmetric, BoundaryCondition::Symmetric} };
84+
sublabels = { "" };
85+
}
86+
else if (azimuthal % 2 == 1) {
87+
parities = {
88+
{BoundaryCondition::AntiSymmetric, BoundaryCondition::Symmetric},
89+
{BoundaryCondition::Symmetric, BoundaryCondition::AntiSymmetric},
90+
};
91+
sublabels = { "_a", "_b" };
92+
}
93+
else {
94+
parities = {
95+
{BoundaryCondition::Symmetric, BoundaryCondition::Symmetric},
96+
{BoundaryCondition::AntiSymmetric, BoundaryCondition::AntiSymmetric},
97+
};
98+
sublabels = { "_a", "_b" };
99+
}
100+
101+
for (size_t i = 0; i < parities.size(); ++i)
102+
{
103+
ModeEntry entry;
104+
entry.azimuthal = azimuthal;
105+
entry.radial = radial;
106+
entry.sub_label = sublabels[i];
107+
entry.x_parity = parities[i][0];
108+
entry.y_parity = parities[i][1];
109+
entries.push_back(std::move(entry));
110+
}
111+
}
112+
113+
return entries;
114+
}();
115+
116+
return catalog;
117+
}
118+
119+
static std::vector<ModeTuple> get_filtered_mode_list(
120+
const BoundaryCondition x_parity,
121+
const BoundaryCondition y_parity
122+
) {
123+
const auto& catalog = get_mode_catalog();
124+
125+
std::vector<ModeTuple> filtered_modes;
126+
filtered_modes.reserve(catalog.size());
127+
128+
for (const ModeEntry& entry : catalog)
129+
{
130+
const bool x_ok = (x_parity == BoundaryCondition::Zero) || (x_parity == entry.x_parity);
131+
const bool y_ok = (y_parity == BoundaryCondition::Zero) || (y_parity == entry.y_parity);
132+
133+
if (x_ok && y_ok)
134+
filtered_modes.emplace_back(entry.azimuthal, entry.radial, entry.sub_label);
135+
}
136+
137+
return filtered_modes;
138+
}
139+
};

SuPyMode/cpp/supermode/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ add_library("${NAME}" STATIC "${NAME}.cpp")
77

88
target_include_directories("${NAME}" PUBLIC "${CMAKE_SOURCE_DIR}/extern/eigen")
99

10-
target_link_libraries("${NAME}" PRIVATE pybind11::module model_parameters)
10+
target_link_libraries("${NAME}" PRIVATE pybind11::module model_parameters boundaries)
1111

1212
# Create a Python module, if needed.
1313
pybind11_add_module("interface_${NAME}" MODULE interface.cpp)

0 commit comments

Comments
 (0)