-
Notifications
You must be signed in to change notification settings - Fork 904
[WIP] Power Iteration Method for Numerical Stability Analysis of the Non-Linear System #2570
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 2 commits
4256c98
4d46079
39a2375
b40e595
812331b
748dd9f
0c035c4
60f62eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,7 +73,7 @@ void CSinglezoneDriver::StartSolver() { | |
| Preprocess(TimeIter); | ||
|
|
||
| /*--- Run a time-step iteration of the single-zone problem. ---*/ | ||
|
|
||
| PreRunSpectralRadius(); | ||
| Run(); | ||
|
|
||
| /*--- Perform some postprocessing on the solution before the update ---*/ | ||
|
|
@@ -83,7 +83,7 @@ void CSinglezoneDriver::StartSolver() { | |
| /*--- Update the solution for dual time stepping strategy ---*/ | ||
|
|
||
| Update(); | ||
|
|
||
| PostRunSpectralRadius(); | ||
| /*--- Monitor the computations after each iteration. ---*/ | ||
|
|
||
| Monitor(TimeIter); | ||
|
|
@@ -312,3 +312,83 @@ bool CSinglezoneDriver::Monitor(unsigned long TimeIter){ | |
| bool CSinglezoneDriver::GetTimeConvergence() const{ | ||
| return output_container[ZONE_0]->GetCauchyCorrectedTimeConvergence(config_container[ZONE_0]); | ||
| } | ||
|
|
||
| void CSinglezoneDriver::PreRunSpectralRadius() { | ||
| CGeometry* geometry = geometry_container[ZONE_0][INST_0][MESH_0]; | ||
| CVariable* nodes = nullptr; | ||
|
|
||
| // Get total number of variables | ||
| unsigned long nVarTotal = 0; | ||
| unsigned long nPoint = geometry->GetnPointDomain(); | ||
| for (auto iSol = 0u; iSol < MAX_SOLS; ++iSol) { | ||
| CSolver* solver = solver_container[ZONE_0][INST_0][MESH_0][iSol]; | ||
| if (solver) nVarTotal += solver->GetnVar(); | ||
| } | ||
|
|
||
| unsigned long nTotal = nVarTotal * nPoint; | ||
|
|
||
| // Initialize power iteration vector | ||
| if (v_estimate.empty()) { | ||
| v_estimate.resize(nTotal); | ||
| passivedouble norm = 0.0; | ||
| for (unsigned long i = 0; i < nTotal; i++) { | ||
| v_estimate[i] = static_cast<passivedouble>(rand()) / RAND_MAX; | ||
| norm += v_estimate[i] * v_estimate[i]; | ||
| } | ||
| norm = sqrt(norm); | ||
| for (unsigned long i = 0; i < nTotal; i++) v_estimate[i] /= norm; | ||
|
||
| } | ||
|
|
||
| // Seed derivatives for all solvers | ||
| SeedAllDerivatives(v_estimate, nodes, geometry); | ||
|
||
| if (rank == MASTER_NODE) {std::cout << "seeding done" << endl;}; //see where code fails | ||
| } | ||
|
|
||
| void CSinglezoneDriver::PostRunSpectralRadius() { | ||
| if (rank == MASTER_NODE) {std::cout << "running post spectral function" << endl;}; //see where code fails | ||
|
|
||
| CGeometry* geometry = geometry_container[ZONE_0][INST_0][MESH_0]; | ||
| CVariable* nodes = nullptr; | ||
|
|
||
| // Get total number of variables | ||
| unsigned long nVarTotal = 0; | ||
| unsigned long nPoint = geometry->GetnPointDomain(); | ||
| for (auto iSol = 0u; iSol < MAX_SOLS; ++iSol) { | ||
| CSolver* solver = solver_container[ZONE_0][INST_0][MESH_0][iSol]; | ||
| if (solver) nVarTotal += solver->GetnVar(); | ||
| } | ||
| unsigned long nTotal = nVarTotal * nPoint; | ||
| if (rank == MASTER_NODE) {std::cout <<"extracting tangents" << endl;}; //see where code fails | ||
|
|
||
| // Extract derivatives from all solvers | ||
| vector<passivedouble> w(nTotal); | ||
| GetAllDerivatives(w, nodes, geometry); | ||
| if (rank == MASTER_NODE) {std::cout << "computing eigen" << endl;}; //see where code fails | ||
|
|
||
| // Compute norm and update eigen estimate | ||
| passivedouble rho_new = 0.0; | ||
| for (unsigned long i = 0; i < nTotal; i++) rho_new += w[i] * w[i]; | ||
| rho_new = sqrt(rho_new); | ||
|
|
||
| for (unsigned long i = 0; i < nTotal; i++) v_estimate[i] = w[i] / rho_new; | ||
|
|
||
| // Check convergence | ||
| static passivedouble rho_old = 0.0; | ||
| static int iter = 0; | ||
|
|
||
| int max_iter = 500; | ||
| passivedouble tol = 1e-7; | ||
|
|
||
| if (abs(rho_new - rho_old) < tol || iter >= max_iter) { | ||
| if (rank == MASTER_NODE) { | ||
| std::cout << "Spectral Radius Estimate: " << rho_new << " after " << iter << " iterations." << std::endl; | ||
| } | ||
| // Reset for next analysis if needed | ||
| rho_old = 0.0; | ||
| iter = 0; | ||
| v_estimate.clear(); | ||
| } else { | ||
| rho_old = rho_new; | ||
| iter++; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use su2matrix instead of vector passivedouble so you don't need to deal with the offset variable