Fixing frequency-band mode: Adaptive Lanczos#186
Merged
zchlrnr merged 7 commits intoMystranSolver:mainfrom Jan 13, 2026
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Some background
MYSTRAN, when solving eigen problems (SOL 103 or the eigen-step of SOL 105), supports either being told a number of modes ahead of time or receiving a frequency band. When working with a frequency band, it used to run an estimator based on Sylvester's law of inertia using the subroutine
EST_NUM_EIGENS_BANDED.The subroutine's name already indicates the first issue: it works with banded matrices, and ever since we got rid of BANDIT, anything that expects banded matrices can end up using massive amounts of time and memory: a deck with around 7k QUAD elements will require over 24 GB of memory for RFAC. That's one of the reasons why @victorkemp added SuperLU to the eigensolve step (RFAC is also present there).
Even if we brought back resequencing or adapted the subroutine to use sparse subroutines for the tridiagonal factorisation step, it's still inefficient. Bill knew this: he made it so that the eigen estimation subroutine never even runs when there are more DoF in the L-set than the PARAM
EIGESTL, which has a default value of 5000. That's quite small, even for an L-set. If you increaseEIGESTL, you're back to the problem RFAC with 24 GB and days of runtime.All of that means that any eigen problem with over 5k DoF in the L-set, even if now quickly solvable thanks to @victorkemp's great work, will not run the eigen estimator, and thus default to 1 mode. So... frequency-band mode is broken for all but small models.
Why Lanczos?
Lanczos is the eigenvalue extraction method of choice for larger models and more modes, so it's the ideal starting point for a fix. Inverse-power is usually meant to extract just one (the fundamental) mode, and Givens (modified or not) is just not that powerful.
The existing structure
MYSTRAN's Lanczos procedure mainly lives in two modules:
ARPACK_LANCZOS_EIG: contains the ARPACK Lanczos subroutines in F77, the most important beingDSBAND, the "driver" routine.EIG_LANCZOS_ARPACK: called byLINK4, that's where eigen estimation happens, whereDSBANDis called, etc.ARPACK's
DSBANDis where the actual eigensolve happens: the reverse communication loop, the factorisation of KMSM, etc. A key detail is that it requires a number of desired eigenvalues to be supplied from the start.MYSTRAN's
EIG_LANCZOS_ARPACKis responsible for callingDSBANDwith the right parameters, including the number of eigenvalues (henceforth abbreviated toNEV).Making it "adaptive"
The core idea
My idea was to make an adaptive version of MYSTRAN's Lanczos eigensolve procedure. The core of said idea was to start with some
NEV(say, 10), ask Lanczos for that many, and filter for the ones inside the frequency band. Then doubleNEV, run Lanczos again, filter. Deciding when to stop is the hard part.That can be achieved by just a new MYSTRAN routine that calls
DSBANDmore than once, handles reallocation as arrays grow up, theNEV-doubling loop, etcetera. That new routine was born asEIG_LANCZOS_ARPACK_ADAPTIVE.Reusing the factorisation
One of the first things
DSBANDhas to do is factoriseKMSM(K - σM). The "adaptive" subroutine we just saw callsDSBANDrepeatedly with an increasingNEV. That meansKMSMis factorised over and over again, wasting time.So, to make this "adaptive Lanczos" efficient, a new
DSBANDhad to be put together. It's basically the same, except it takes a pre-done factorisation. Those subroutines live in the new moduleDSBAND_PREFAC.fF77 module. It's almost the same asDSBAND, and only the adaptive Lanczos procedure uses it.Why two new modules?
I wanted to ensure this would not break the existing Lanczos procedure. So even though
EIG_LANCZOS_ARPACK_ADAPTIVEcould have bene made into a drop-in replacement forEIG_LANCZOS_ARPACK, I have modifiedLINK4to only call the adaptive one for SOL 103, frequency-band problems.Limitations
There are some drawbacks to this approach:
DSBAND's mode 2, and neither @victorkemp nor I could get it to work on mode 3 (even though it'd make more sense).Giving ARPACK more juice
I have changed some ARPACK defaults. The
PARAMARP_TOL, the tolerance used with ARPACK used to have1e-6as the default, and I changed it to1e-9. I also changedMXITERL's default from50to300-- that's max iterations for Lanczos. The reason for that is these defaults were written with early-2000s computers in mind. The 50-iteration default is particularly abysmal, 300 is alright (and not often reached in practice anyway).I have also changed the Krylov subspace factor. Put simply, Lanczos requires you to specify the size of the Krylov subspace used in the solve, and it's usually a multiple of the number of requested eigenpairs. The minimum that makes mathematical sense is 1. MYSTRAN uses 2 (
EIG_NCVFACL, a constant inMODEL_STUF). Nowadays, 3 is the standard recommendation, so I changedEIG_NCVFACLto 3. The performance impact was minor.These changes have not majorly impacted results or performance for most use cases, but during development, bad defaults masked other issues (such as the MIN4 shell's issues with rigid-body modes in free-free decks because
K6ROTpartially grounds the model).Final remarks
I have done some tests, and this looks sound. I'm not worried about the eigenpairs themselves (they are still calculated the same way). Still, I'd like to see your comments, especially on
DSBAND_PREFAC-- I have little experience with Fortran 77.I hope I got this one right so we can finally say we support frequency-band Lanczos. It's an important feature, so even though we discussed this extensively on Discord, test decks and feedback are more than welcome!