smdogroup / funtofem

Adaptable framework for aerothermoelastic analysis and adjoint-based gradient evaluation
Apache License 2.0
26 stars 24 forks source link

Who owns the model? The interface? Or the driver? Both? #169

Closed jfkiviaho closed 1 year ago

jfkiviaho commented 1 year ago

Hi,

I've been working on a new solver interface for FUNtoFEM, and I was a little bit confused about ownership and use of the Model object in the SolverInterface and FUNtoFEMDriver classes.

As I understand it now, a SolverInterface must have access to the Model object in its constructor. This is so that it can, for example, call initialize_aero_nodes for a given Body object in the Model and thus set the sizes of the data structures in that Body object before the driver calls initialize_variables on that Body object and creates those data structures. Otherwise, you end up with data structures of the default size zero, which isn't very helpful.

But that fact---that a SolverInterface must have access to the Model in its constructor---wasn't obvious to me at first. There isn't a model parameter in the constructor for the SolverInterface base class. And most of the member functions that make up the interface of the SolverInterface class, functions like initialize, include parameters scenario and bodies. That gave me the first impression that SolverInterface doesn't need its own "reference" to the Model, because the driver will just pass in the Scenario object or Body list from its own "reference" to the Model. And indeed that is how things work for the most part. Returning to the example of initialize, the driver calls _initialize_forward(scenario, self.model.bodies) which propagates the Body list from self.model, the driver's own "reference" to the Model, through to SolverInterface.initialize via the bodies parameter.

So my conclusion is that SolverInterface doesn't actually need its own access to Model for the most part, except crucially in its constructor when it needs to initialize the nodes in the Model's Body objects. That's a little confusing. But I understand it could be difficult to disentangle. I don't really have any prescriptions. But I thought it might be useful to log this in Issues in case anyone finds themselves similarly confused in the future.

--Jan

sean-engelstad commented 1 year ago

Yeah, there is some overlap in providing data from the model class to the SolverInterface class, with the FUNtoFEMmodel in the constructor and the Scenario and Body classes through the initialize, iterate, methods, etc. Also, a better name for the initialize method would probably be initialize_forward as it is the forward analysis version of initialize_adjoint.

Many of the objects in FUNtoFEM need the model in the constructor including all of the SolverInterface classes (as of yet). The Fun3dInterface, for example, needs to know each of the bodies during its construction since it reads in the aero mesh through FUN3D and stores the coordinates in each Body. On the other hand, the TacsSteadyInterface needs the model in the constructor so that it can initialize the ScenarioData metadata class for each Scenario, holding adjoints, functions, and TACS states. Finally, the FUNtoFEMnlbgs driver needs the model so that it can loop over each scenario calling the appropriate analyses from each solver, and telling it which bodies to include in the analysis.

sean-engelstad commented 1 year ago

I'm going to close this issue if that's ok. I gave it the question label so people can search for it later under the question labels section. I have another issue that I intend for people to see in the future after it is closed as well. I wonder what is the best way to ensure that.