Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Python Plugin Instances in User-Defined Plant Component #5264

Open
bonnema opened this issue Oct 1, 2024 · 1 comment
Open

Allow Python Plugin Instances in User-Defined Plant Component #5264

bonnema opened this issue Oct 1, 2024 · 1 comment

Comments

@bonnema
Copy link
Contributor

bonnema commented Oct 1, 2024

Enhancement Request

Modify the user-defined plant component to accept a Python Plugin Instance for the plantInitializationProgramCallingManager as well as the plantSimulationProgramCallingManager. Additionally, if a Python Plugin Instance is specified, do not construct any default Energy Management System objects.

Detailed Description

Currently, the user-defined plant component only allows an Energy Management System Program Calling Manager for the plantInitializationProgramCallingManager and the plantSimulationProgramCallingManager. It also default constructs a number of Energy Management System actuators in addition to a two Energy Management System programs.

However, this does not allow a Python Plugin to be used to model the user-defined plant component. While the importance of these defaults and generating a running model is recognized, it would be beneficial to be able to bypass this functionality.

Possible Implementation

Overload the setPlantInitializationProgramCallingManager and setPlantSimulationProgramCallingManager methods to accept a Python Plugin Instance. If the setPlantInitializationProgramCallingManager method is used with a Python Plugin Instance, do not default construct a Plant Initialization Energy Management System Program or these actuators:

  • designVolumeFlowRateActuator
  • minimumMassFlowRateActuator
  • maximumMassFlowRateActuator
  • minimumLoadingCapacityActuator
  • maximumLoadingCapacityActuator
  • optimalLoadingCapacityActuator

Similarly, if the setPlantSimulationProgramCallingManager method is used with a Python Plugin Instance, do not default construct a Plant Simulation Energy Management System Program or these actuators:

  • outletTemperatureActuator
  • massFlowRateActuator

It is important to keep these split, sometimes it is convenient to keep one program in Python and the other in ERL.

@bonnema bonnema added Enhancement Request Triage Issue needs to be assessed and labeled, further information on reported might be needed labels Oct 1, 2024
@DavidGoldwasser DavidGoldwasser removed the Triage Issue needs to be assessed and labeled, further information on reported might be needed label Oct 16, 2024
@jmarrec
Copy link
Collaborator

jmarrec commented Oct 30, 2024

That's all done in the Ctor:

PlantComponentUserDefined::PlantComponentUserDefined(const Model& model) : StraightComponent(PlantComponentUserDefined::iddObjectType(), model) {
OS_ASSERT(getImpl<detail::PlantComponentUserDefined_Impl>());
bool ok = true;
ok = setPlantLoadingMode("MeetsLoadWithNominalCapacityHiOutLimit");
OS_ASSERT(ok);
ok = setPlantLoopFlowRequestMode("NeedsFlowIfLoopOn");
OS_ASSERT(ok);
//setup required Actuators for Plant Connection 1
EnergyManagementSystemActuator dvfrActuator(this->cast<ModelObject>(), "Plant Connection 1", "Design Volume Flow Rate");
dvfrActuator.setName("PCUD_Vdot_Design");
ok = setDesignVolumeFlowRateActuator(dvfrActuator);
OS_ASSERT(ok);
EnergyManagementSystemActuator mmfrActuator(this->cast<ModelObject>(), "Plant Connection 1", "Minimum Mass Flow Rate");
mmfrActuator.setName("PCUD_Mdot_Min");
ok = setMinimumMassFlowRateActuator(mmfrActuator);
OS_ASSERT(ok);
EnergyManagementSystemActuator mxfrActuator(this->cast<ModelObject>(), "Plant Connection 1", "Maximum Mass Flow Rate");
mxfrActuator.setName("PCUD_Mdot_Max");
ok = setMaximumMassFlowRateActuator(mxfrActuator);
OS_ASSERT(ok);
EnergyManagementSystemActuator mlcActuator(this->cast<ModelObject>(), "Plant Connection 1", "Minimum Loading Capacity");
mlcActuator.setName("PCUD_Cap_Min");
ok = setMinimumLoadingCapacityActuator(mlcActuator);
OS_ASSERT(ok);
EnergyManagementSystemActuator mxlcActuator(this->cast<ModelObject>(), "Plant Connection 1", "Maximum Loading Capacity");
mxlcActuator.setName("PCUD_Cap_Max");
ok = setMaximumLoadingCapacityActuator(mxlcActuator);
OS_ASSERT(ok);
EnergyManagementSystemActuator olcActuator(this->cast<ModelObject>(), "Plant Connection 1", "Optimal Loading Capacity");
olcActuator.setName("PCUD_Cap_Opt");
ok = setOptimalLoadingCapacityActuator(olcActuator);
OS_ASSERT(ok);
EnergyManagementSystemActuator otActuator(this->cast<ModelObject>(), "Plant Connection 1", "Outlet Temperature");
otActuator.setName("PCUD_Tout");
ok = setOutletTemperatureActuator(otActuator);
OS_ASSERT(ok);
EnergyManagementSystemActuator mfrActuator(this->cast<ModelObject>(), "Plant Connection 1", "Mass Flow Rate");
mfrActuator.setName("PCUD_Mdot_Request");
ok = setMassFlowRateActuator(mfrActuator);
OS_ASSERT(ok);
//setup Main Program and Manager
/*
EnergyManagementSystemProgram mainProgram(model);
mainProgram.setName("PCUD_MainProgram");
EnergyManagementSystemProgramCallingManager mainProgramCallingManager(model);
mainProgramCallingManager.setName("PCUD_MainProgramCallingManager");
mainProgramCallingManager.setCallingPoint("UserDefinedComponentModel");
mainProgramCallingManager.addProgram(mainProgram);
*/
//setup Init Program and Manager
std::string line;
EnergyManagementSystemProgram initProgram =
createInitProgram(dvfrActuator, mmfrActuator, mxfrActuator, mlcActuator, mxlcActuator, olcActuator, model);
EnergyManagementSystemProgramCallingManager initProgramCallingManager(model);
initProgramCallingManager.setName("PCUD_InitProgramCallingManager");
initProgramCallingManager.setCallingPoint("UserDefinedComponentModel");
initProgramCallingManager.addProgram(initProgram);
//add as children so they delete if object gets removed
ok = setPlantInitializationProgramCallingManager(initProgramCallingManager);
OS_ASSERT(ok);
ok = setPlantInitializationProgram(initProgram);
OS_ASSERT(ok);
//setup Sim Program and Manager
EnergyManagementSystemProgram simProgram = createSimProgram(otActuator, mfrActuator, model);
EnergyManagementSystemProgramCallingManager simProgramCallingManager(model);
simProgramCallingManager.setName("PCUD_SimProgramCallingManager");
simProgramCallingManager.setCallingPoint("UserDefinedComponentModel");
simProgramCallingManager.addProgram(simProgram);
//add as children so they delete if object gets removed
ok = setPlantSimulationProgramCallingManager(simProgramCallingManager);
OS_ASSERT(ok);
ok = setPlantSimulationProgram(simProgram);
OS_ASSERT(ok);
}

So the possible implementation is probably to provide a new ctor:

PlantComponentUserDefined::PlantComponentUserDefined(const PythonPluginInstance& initialiazitionProgram, const PythonPluginInstance& simulationProgram)

or maybe rather add a defaulted arg to the original ctor:

// if initializeEMS is true, actuators are set up, and two pairs of EMS:Program & EMS:ProgramCallingManager are set up for the initialization and simulation programs of the plant connection 1
PlantComponentUserDefined::PlantComponentUserDefined(const Model& model, bool initializeEMS = true);

Side note: I hadn't realized E+ has up to 4 plant connections (and program calling managers for each) while we support only one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants