Skip to content

Subcase mode distillation#241

Merged
Bruno02468 merged 11 commits into
MystranSolver:devfrom
Bruno02468:subcase_mode_distillation
Jun 1, 2026
Merged

Subcase mode distillation#241
Bruno02468 merged 11 commits into
MystranSolver:devfrom
Bruno02468:subcase_mode_distillation

Conversation

@Bruno02468
Copy link
Copy Markdown
Collaborator

@Bruno02468 Bruno02468 commented May 31, 2026

The subcase/mode distillation!

This one might be a little weird.

The problem

Put simply, MYSTRAN uses the same "internals" for both subcases and modes (as in eigenpairs). That allows for some logical savings when dealing with doing solves and generating output.

SOL 101 decks don't have modes so that doesn't matter. But 103 and 105 decks do. Since they already have modes, they can't have subcases properly: 103 didn't work with them, and 105 only worked with the required two (one static, one eigen).

What I did

This PR aims to fix this limitation in order to make MYSTRAN's subcases more compatible with modern solvers. I'll break down this effort into three parts.

1. Mode/subcase rewiring

The first -- and most crucial step -- was to introduce into MYSTRAN's code a distinct idea of mode, whilst keeping the idea of subcases mostly intact. Several dynamically-allocated data structures were added to store mode-specific information on a per-subcase basis. The changed/new arrays are too many to list them all here, but no existing array's leading dimension changed.

The new EIG_PARAMS_TYPE is also noteworthy: it uses a Fortran 2003 feature (allocatable components in derived types) and is the whole reason this feature was possible (that's why some files were renamed to .f03).

These changes are what allows what comes next.

2. Multi-subcase for SOL 103

With all that groundwork laid down, making SOL 103 work with multiple subcases was easy enough: use all that new wiring to allow for reading, computing, and outputting results for more than one subcase. Most of it was adding one more loop around existing code.

Even though I defined this as a separate step, it was kind of done alongside the previous one, since I needed to actually test all those changes, and 103 was easier than 105.

3. Multi-subcase for SOL 105 with STATSUB

Now for the hard part. Once I got multi-subcase 103 working, I decided to implement that for 105 with that STATSUB card other modern solvers have. You put it inside a modes subcase and it just lets you specify the corresponding static preload case. Bam, buckling solutions with multiple static-eigen subcase pairs. Looks easy, right? No.

3.1. How buckling works

First of all, if you remember what I said way up there in the beginning, MYSTRAN doesn't do both modes and subcases. So how does it even do buckling? It requires two subcases, and one of them is an eigenproblem, it's gonna have modes! What gives?

Without going too much into the details, MYSTRAN deals with it by... sort of running itself twice. On the first go, the static preload subcase is run so you get the data to construct the differential stiffness matrix. It almost looks like a normal MYSTRAN run.

But then, some data that actually needs to persist is put into some temporary files/arrays, and MYSTRAN runs the eigen "subcase" nearly from the top (LINK1), save for the first few steps like decoding the input deck. That means the eigen "subcase" is more like its own run, so it's free to have its own modes-as-subcases.

3.2. What was needed to give us STATSUB?

A lot of things. First, a quick rundown:

  1. Parsing the brand-new STATSUB card in the case control step (new CC_STATSUB subroutine);
  2. Building an index of the relationships between the buckling subcases from the static ones;
  3. Use the new/changed data structures for per-mode state;
  4. Restructuring the LINK1 and LINK4 outer loops;
  5. Reconstructing KGGD from UG and reducing it to KLLD;
  6. Updating the per-pass state lifecycle.

Now, details on some of the more involved items.

3.2.1. Restructuring the LINK1 and LINK4 outer loops?

Yes. MYSTRAN has two "passes" to solve buckling, denoted by LOAD_ISTEP being 1 or 2. Before:

  • LOAD_ISTEP==1 solved the static subcase, and
  • LOAD_ISTEP==2 rebuilt KGGD from the previous step's UG, then solved the eigenproblem.

Now:

  • LOAD_ISTEP==1 loops over all static subcases, storing the UG for each of them.
  • LOAD_ISTEP==2 loops over all buckling subcases, rebuilds & reduces each KGGD from the corresponding UG, and solves the eigenproblems.
3.2.2. Reconstructing KGGD from UG and reducing it to KLLD?

Before, MYSTRAN didn't have to concern itself with multiple UGs. Now it does. To aid us with that, three new subroutines have been introduced:

  • READ_L5A_UG_FOR_SUBCASE: retrieves a stored UG from the .L5A temporary file;
  • BUILD_KGGD_FROM_UG: takes the retrieved UG and builds KGGD via the existing code in EMG;
  • REBUILD_KLLD_FROM_KGGD: does the whole set-reduction step so we can solve the eigenproblem;
3.2.3. Updating the per-pass state lifecycle?

This one was arguably the hardest one. The code doesn't lie: this whole two-pass business was implemented as a hack from the very start. I've lost count of how many memory bugs I fixed back in the v15/v16 days that were 100% about something happening between the two passes that shouldn't (allocation, deallocation, file closing, file deletion, etc.), and this time it was no different.

Several of the new data structures had to have their (de)allocations gated (by way of checking the solution type and current pass if applicable) in LINK1, and the clean-up code in LINK4 had to be changed to accomodate for the multiple buckling cases.


So... did it work?

Yeah, I think so. I added some test cases to the Build_Test_Cases subdirectory, and both multi-subcase 103 and STATSUB-based 105 work with no major hiccups. Of course we'll need to test this thoroughly, but @victorkemp's test suite seems to agree that I haven't introduced any regressions. I even checked for memory errors with valgrind.

Oh, and existing SOL 105 decks are not broken by this. In the absence of a STATSUB card, the previous rules apply: two subcases, one static, one eigen, in that order.

Caveats

MYSTRAN is, in general, still limited in its support for subcases: they can never differ in SPCs and MPCs, for example. Until we "fix" that -- that is, if we ever decide to -- the usefulness of these features might be limited.

I also did not touch the NLSTATIC (106) cases. I mean, it's not even a documented feature. But I'm open to suggestions on how to deal with SOL 106 -- and "don't" is a valid suggestion.


Thanks for reading!

@Bruno02468 Bruno02468 marked this pull request as ready for review June 1, 2026 01:25
@Bruno02468 Bruno02468 merged commit 1a047c9 into MystranSolver:dev Jun 1, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant