Your question sounds as if you've just inherited a big legacy system to take care of, and you're looking for a magical design pattern that would make it simple.
Is it all because of inheritance ?
Let's be honest: Any majors system looks complex and difficult to understand at first sight. That's because of the complex matters they are dealing with.
The system has to be decomposed into smaller, understandable parts. But what would be the alternative to inheritance in your case ? Flat calculation sub-routines that write everything down again and again with a lots of parameters to tell the variables and calculation variant to be used ?
Wouldn't this result in even more difficult code where you're never sure that if you change something in one formula you shouldn't also adapt some other formulas elsewhere ? Wouldn't you then end-up posting a question like I've inherited 200K lines of spaghetti code — what now?.
However the code is written, the more classes you have, the more difficult it'll be to understand. That's natural.
Some psychologists even claim that our brain has in average a short term memory capacity of around 7 items, and trying to understand simultaneous interrelation between more items appears difficult. In their opinion the only way to overcome this limitation would be cluster items. And inheritance is just about that: you can handle the derived object as the original object, with just the variations you'd need. So it should be simpler to understand.
What's difficult to master is how all the classes are related. Not only in their static structure, but also how they dynamically interact at run-time.
How is your system designed ?
Reading the code can give you a detailed view, class by class. With a good IDE, it should not be an issue to navigate between related classes and find all the related pieces of code.
But this is not sufficient to get the perspective and the overall understanding of the system:
The worst possible documentation to create for an object-oriented
system is a stand-alone description of the semantics of each method on
a class-by-class basis. This approach tends to generate a great deal
of useless documentation that no one reads or trusts, and fails to
document the more important architectural issues that transcend
individual classes, namely, the collaborations among classes and
objects. - Grady Booch in Object-Oriented Analysis and Design
For example, it's a common practice to define a high-level relationships between abstract classes, to reduce dependencies in derived concrete classes. But this makes it easy to loose sight of these relations when implementing the concrete classes. And it is sometimes difficult to guess the intent behind the abstraction.
Unfortunately, there is no general purpose design pattern to overcome complexity. There is no way round: you have to get a high level understanding of your system first:
- If there is some architectural design document, start with that.
- If not, make some reverse engineering. Start with a class diagram. There are automated tools that can help.
- Then if you're familiar with design patterns, try to identify in the structure some existing design patterns. This will accelerate your understanding of dynamic relationship between classes.
Maybe that with a deeper understanding you'll find that the code is better structured than you thought. And maybe not. And in this case you can come back with additional specific questions, for which we can provide some ideas about specific design patterns for improvement.