Search code examples
openmdao

How to break down a complex model into components + custom "drivers"?


I have a complex model (A) that can easily be written into a single component with inputs and outputs. However, within model A there are repeated calls to two "physical" disciplines A1 and A2. I'd like to separate model A into two sub-components (A1 and A2) and have a code that calls A1 and A2 according to some rules. The question is, should I write this "glue code" as a component that calls other components inside it? or should I write my own "driver" that calls A1 and A2 with my rules? Or must I keep the large model in one single component?

Another similar case is when an (ideally) single component must be evaluated at different cases (input values). How to call it repeatedly? Or make one component that loops inside the compute method? Thanks.


Solution

  • you have several options here, and depending on the details of why you make repeated calls to A1 and A2, which one I recommend would change.

    I almost always recommend breaking larger models up into smaller components, because it makes computing analytic derivatives easier and gives a more modular code base. Assuming you did break A up, what is the character of the repeated calls?

    Are A1 and A2 some kind of analysis that you wish to repeat at multiple different operating points? e.g. multiple load cases or aerodynamic considitions? Maybe you average between them all to compute some final output of A? If so I would recommend writing A1 and A2 as vectorized functions that can take in arrays of input data (each entry of the array represents a different point) and then outputs an array with the computations done on each element. Using numpy arrays this way si both fast and an efficient use of memory in OpenMDAO. This is definitely how I would suggest you handle your last question, about running repeatedly with different inputs. If you can't vectorize the functions, then instead you can stamp out multiple instances of your model (one for each input case), but depending on how many input cases you have this might be less efficient.

    Are you iterating over A1/A2 for some kind of convergence process? If so you should use a solver to handle that kind of looping. GaussSeidel or Newton should do the trick. If your rules are composed of some kind of heuristic iteration to reach convergence, then you could code that into a custom solver, although this would be somewhat difficult for a novice user for sure. If instead your rules amount to some kind of algorithm where you execute A1/A2 in some fixed sequence and call each on a fixed number of times, I come back to my suggestion that you just instantiate multiple copies of A1 and A2 and then connect them together to make the sequence you want for your problem.