diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a0cd7e37..b2c47b70b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ Changes are grouped as follows - `Fixed` for any bug fixes. - `Security` in case of vulnerabilities. +## [7.63.11] - 2024-10-24 +### Added +- Added support for simulation tasks in data workflows. + ## [7.63.10] - 2024-10-22 ### Fixed - The Not() filter now only accepts a single filter (and no longer silently ignores the rest). diff --git a/cognite/client/_version.py b/cognite/client/_version.py index cdbba3160..6da48b639 100644 --- a/cognite/client/_version.py +++ b/cognite/client/_version.py @@ -1,4 +1,4 @@ from __future__ import annotations -__version__ = "7.63.10" +__version__ = "7.63.11" __api_subversion__ = "20230101" diff --git a/cognite/client/data_classes/__init__.py b/cognite/client/data_classes/__init__.py index fadaae74a..29231efca 100644 --- a/cognite/client/data_classes/__init__.py +++ b/cognite/client/data_classes/__init__.py @@ -291,6 +291,8 @@ DynamicTaskParameters, FunctionTaskOutput, FunctionTaskParameters, + SimulationTaskOutput, + SimulationTaskParameters, SubworkflowTaskParameters, TransformationTaskOutput, TransformationTaskParameters, @@ -562,10 +564,12 @@ "WorkflowVersionList", "FunctionTaskParameters", "TransformationTaskParameters", + "SimulationTaskParameters", "CDFTaskParameters", "DynamicTaskParameters", "SubworkflowTaskParameters", "FunctionTaskOutput", + "SimulationTaskOutput", "TransformationTaskOutput", "CDFTaskOutput", "DynamicTaskOutput", diff --git a/cognite/client/data_classes/workflows.py b/cognite/client/data_classes/workflows.py index 1373e07df..f1e4cd8de 100644 --- a/cognite/client/data_classes/workflows.py +++ b/cognite/client/data_classes/workflows.py @@ -112,7 +112,7 @@ def as_write(self) -> WorkflowUpsertList: return WorkflowUpsertList([workflow.as_write() for workflow in self.data]) -ValidTaskType = Literal["function", "transformation", "cdf", "dynamic", "subworkflow"] +ValidTaskType = Literal["function", "transformation", "cdf", "dynamic", "subworkflow", "simulator"] class WorkflowTaskParameters(CogniteObject, ABC): @@ -140,6 +140,8 @@ def load_parameters(cls, data: dict) -> WorkflowTaskParameters: return SubworkflowTaskParameters._load(parameters) elif type_ == "subworkflow" and "workflowExternalId" in parameters["subworkflow"]: return SubworkflowReferenceParameters._load(parameters) + elif type_ == "simulator": + return SimulationTaskParameters._load(parameters) else: raise ValueError(f"Unknown task type: {type_}. Expected {ValidTaskType}") @@ -219,6 +221,48 @@ def dump(self, camel_case: bool = True) -> dict[str, Any]: return output +class SimulationTaskParameters(WorkflowTaskParameters): + """ + The simulation parameters are used to specify the simulation routine to be executed. + + Args: + routine_external_id (str): The external ID of the simulation routine to be executed. + run_time (int | None): Reference timestamp used for data pre-processing and data sampling. + inputs (list[dict[str, Any]] | None): List of input overrides + """ + + task_type = "simulator" + + def __init__( + self, + routine_external_id: str, + run_time: int | None = None, + inputs: list[dict[str, Any]] | None = None, + ) -> None: + self.routine_external_id = routine_external_id + self.run_time = run_time + self.inputs = inputs + + @classmethod + def _load(cls, resource: dict, cognite_client: CogniteClient | None = None) -> SimulationTaskParameters: + simulation: dict[str, Any] = resource["simulator"] + + return cls( + routine_external_id=simulation["routineExternalId"], + run_time=simulation.get("runTime"), + inputs=simulation.get("inputs"), + ) + + def dump(self, camel_case: bool = True) -> dict[str, Any]: + simulation = { + "routineExternalId" if camel_case else "routine_external_id": self.routine_external_id, + "runTime" if camel_case else "run_time": self.run_time, + "inputs": self.inputs, + } + + return {"simulator": simulation} + + class TransformationTaskParameters(WorkflowTaskParameters): """ The transformation parameters are used to specify the transformation to be called. @@ -521,6 +565,8 @@ def load_output(cls, data: dict) -> WorkflowTaskOutput: return DynamicTaskOutput.load(data) elif task_type == "subworkflow": return SubworkflowTaskOutput.load(data) + elif task_type == "simulator": + return SimulationTaskOutput.load(data) else: raise ValueError(f"Unknown task type: {task_type}") @@ -560,6 +606,50 @@ def dump(self, camel_case: bool = True) -> dict[str, Any]: } +class SimulationTaskOutput(WorkflowTaskOutput): + """ + The class represent the output of Simulation execution. + + Args: + run_id (int | None): The run id of the simulation execution in the SimInt API. + logs (list[dict[str, Any]] | None): Logs from the simulation execution. + status_message (str | None): Status of the current simulation execution. + outputs (list[dict[str, Any]] | None): Outputs results from the simulation execution + """ + + task_type: ClassVar[str] = "simulator" + + def __init__( + self, + run_id: int | None, + logs: list[dict[str, Any]] | None, + status_message: str | None, + outputs: list[dict[str, Any]] | None, + ) -> None: + self.run_id = run_id + self.logs = logs + self.status_message = status_message + self.outputs = outputs + + @classmethod + def load(cls, data: dict[str, Any]) -> SimulationTaskOutput: + output = data["output"] + return cls( + run_id=output.get("runId"), + logs=output.get("logs"), + status_message=output.get("statusMessage"), + outputs=output.get("outputs"), + ) + + def dump(self, camel_case: bool = True) -> dict[str, Any]: + return { + "runId" if camel_case else "run_id": self.run_id, + "logs": self.logs, + "statusMessage" if camel_case else "status_message": self.status_message, + "outputs": self.outputs, + } + + class TransformationTaskOutput(WorkflowTaskOutput): """ The transformation output is used to specify the output of a transformation task. diff --git a/pyproject.toml b/pyproject.toml index 7a4aeffeb..ce5eba3f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "cognite-sdk" -version = "7.63.10" +version = "7.63.11" description = "Cognite Python SDK" readme = "README.md" documentation = "https://cognite-sdk-python.readthedocs-hosted.com" diff --git a/tests/data/simulators/ShowerMixer.dwxmz b/tests/data/simulators/ShowerMixer.dwxmz new file mode 100644 index 000000000..b9c934835 Binary files /dev/null and b/tests/data/simulators/ShowerMixer.dwxmz differ diff --git a/tests/data/simulators/__init__.py b/tests/data/simulators/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/data/simulators/seed.py b/tests/data/simulators/seed.py new file mode 100644 index 000000000..2de2f000b --- /dev/null +++ b/tests/data/simulators/seed.py @@ -0,0 +1,740 @@ +simulator = { + "name": "DWSIM", + "externalId": "integration_tests_workflow", + "fileExtensionTypes": ["dwxmz"], + "modelTypes": [{"name": "Steady State", "key": "SteadyState"}], + "stepFields": [ + { + "stepType": "get/set", + "fields": [ + { + "name": "objectName", + "label": "Simulation Object Name", + "info": "Enter the name of the DWSIM object, i.e. Feed", + }, + { + "name": "objectProperty", + "label": "Simulation Object Property", + "info": "Enter the property of the DWSIM object, i.e. Temperature", + }, + ], + }, + { + "stepType": "command", + "fields": [ + { + "name": "command", + "label": "Command", + "info": "Select a command", + "options": [{"label": "Solve Flowsheet", "value": "Solve"}], + } + ], + }, + ], + "unitQuantities": [ + { + "name": "area", + "label": "Area", + "units": [{"label": "m2", "name": "m2"}, {"label": "cm2", "name": "cm2"}, {"label": "ft2", "name": "ft2"}], + }, + { + "name": "head", + "label": "Head", + "units": [{"label": "m", "name": "m"}, {"label": "ft", "name": "ft"}, {"label": "cm", "name": "cm"}], + }, + { + "name": "mass", + "label": "Mass", + "units": [{"label": "kg", "name": "kg"}, {"label": "g", "name": "g"}, {"label": "lb", "name": "lb"}], + }, + { + "name": "time", + "label": "Time", + "units": [{"label": "s", "name": "s"}, {"label": "min.", "name": "min."}, {"label": "h", "name": "h"}], + }, + { + "name": "accel", + "label": "Acceleration", + "units": [ + {"label": "m/s2", "name": "m/s2"}, + {"label": "cm/s2", "name": "cm/s2"}, + {"label": "ft/s2", "name": "ft/s2"}, + ], + }, + { + "name": "force", + "label": "Force", + "units": [ + {"label": "N", "name": "N"}, + {"label": "dyn", "name": "dyn"}, + {"label": "kgf", "name": "kgf"}, + {"label": "lbf", "name": "lbf"}, + ], + }, + { + "name": "deltaP", + "label": "Delta P", + "units": [ + {"label": "Pa", "name": "Pa"}, + {"label": "atm", "name": "atm"}, + {"label": "lbf/ft2", "name": "lbf/ft2"}, + {"label": "kgf/cm2", "name": "kgf/cm2"}, + {"label": "kgf/cm2_g", "name": "kgf/cm2_g"}, + {"label": "kPa", "name": "kPa"}, + {"label": "bar", "name": "bar"}, + {"label": "barg", "name": "barg"}, + {"label": "ftH2O", "name": "ftH2O"}, + {"label": "inH2O", "name": "inH2O"}, + {"label": "inHg", "name": "inHg"}, + {"label": "mbar", "name": "mbar"}, + {"label": "mH2O", "name": "mH2O"}, + {"label": "mmH2O", "name": "mmH2O"}, + {"label": "mmHg", "name": "mmHg"}, + {"label": "MPa", "name": "MPa"}, + {"label": "psi", "name": "psi"}, + {"label": "psig", "name": "psig"}, + ], + }, + { + "name": "deltaT", + "label": "Delta T", + "units": [ + {"label": "C.", "name": "C."}, + {"label": "K.", "name": "K."}, + {"label": "F.", "name": "F."}, + {"label": "R.", "name": "R."}, + ], + }, + { + "name": "volume", + "label": "Volume", + "units": [ + {"label": "m3", "name": "m3"}, + {"label": "cm3", "name": "cm3"}, + {"label": "L", "name": "L"}, + {"label": "ft3", "name": "ft3"}, + {"label": "bbl", "name": "bbl"}, + {"label": "gal[US]", "name": "gal[US]"}, + {"label": "gal[UK]", "name": "gal[UK]"}, + ], + }, + { + "name": "density", + "label": "Density", + "units": [ + {"label": "kg/m3", "name": "kg/m3"}, + {"label": "g/cm3", "name": "g/cm3"}, + {"label": "lbm/ft3", "name": "lbm/ft3"}, + ], + }, + { + "name": "entropy", + "label": "Entropy", + "units": [ + {"label": "kJ/[kg.K]", "name": "kJ/[kg.K]"}, + {"label": "cal/[g.C]", "name": "cal/[g.C]"}, + {"label": "BTU/[lbm.R]", "name": "BTU/[lbm.R]"}, + ], + }, + { + "name": "diameter", + "label": "Diameter", + "units": [{"label": "mm", "name": "mm"}, {"label": "in", "name": "in"}], + }, + { + "name": "distance", + "label": "Distance", + "units": [{"label": "m", "name": "m"}, {"label": "ft", "name": "ft"}, {"label": "cm", "name": "cm"}], + }, + { + "name": "enthalpy", + "label": "Enthalpy", + "units": [ + {"label": "kJ/kg", "name": "kJ/kg"}, + {"label": "cal/g", "name": "cal/g"}, + {"label": "BTU/lbm", "name": "BTU/lbm"}, + {"label": "kcal/kg", "name": "kcal/kg"}, + ], + }, + { + "name": "heatflow", + "label": "Heat Flow", + "units": [ + {"label": "kW", "name": "kW"}, + {"label": "kcal/h", "name": "kcal/h"}, + {"label": "BTU/h", "name": "BTU/h"}, + {"label": "BTU/s", "name": "BTU/s"}, + {"label": "cal/s", "name": "cal/s"}, + {"label": "HP", "name": "HP"}, + {"label": "kJ/h", "name": "kJ/h"}, + {"label": "kJ/d", "name": "kJ/d"}, + {"label": "MW", "name": "MW"}, + {"label": "W", "name": "W"}, + {"label": "BTU/d", "name": "BTU/d"}, + {"label": "MMBTU/d", "name": "MMBTU/d"}, + {"label": "MMBTU/h", "name": "MMBTU/h"}, + {"label": "kcal/s", "name": "kcal/s"}, + {"label": "kcal/h", "name": "kcal/h"}, + {"label": "kcal/d", "name": "kcal/d"}, + ], + }, + { + "name": "massflow", + "label": "Mass Flow", + "units": [ + {"label": "g/s", "name": "g/s"}, + {"label": "lbm/h", "name": "lbm/h"}, + {"label": "kg/s", "name": "kg/s"}, + {"label": "kg/h", "name": "kg/h"}, + {"label": "kg/d", "name": "kg/d"}, + {"label": "kg/min", "name": "kg/min"}, + {"label": "lb/min", "name": "lb/min"}, + {"label": "lb/s", "name": "lb/s"}, + {"label": "lb/h", "name": "lb/h"}, + {"label": "lb/d", "name": "lb/d"}, + {"label": "Mg/s", "name": "Mg/s"}, + {"label": "Mg/h", "name": "Mg/h"}, + {"label": "Mg/d", "name": "Mg/d"}, + ], + }, + { + "name": "pressure", + "label": "Pressure", + "units": [ + {"label": "Pa", "name": "Pa"}, + {"label": "atm", "name": "atm"}, + {"label": "kgf/cm2", "name": "kgf/cm2"}, + {"label": "kgf/cm2g", "name": "kgf/cm2g"}, + {"label": "lbf/ft2", "name": "lbf/ft2"}, + {"label": "kPa", "name": "kPa"}, + {"label": "kPag", "name": "kPag"}, + {"label": "bar", "name": "bar"}, + {"label": "barg", "name": "barg"}, + {"label": "ftH2O", "name": "ftH2O"}, + {"label": "inH2O", "name": "inH2O"}, + {"label": "inHg", "name": "inHg"}, + {"label": "mbar", "name": "mbar"}, + {"label": "mH2O", "name": "mH2O"}, + {"label": "mmH2O", "name": "mmH2O"}, + {"label": "mmHg", "name": "mmHg"}, + {"label": "MPa", "name": "MPa"}, + {"label": "psi", "name": "psi"}, + {"label": "psig", "name": "psig"}, + ], + }, + { + "name": "spec_vol", + "label": "Specific Volume", + "units": [ + {"label": "m3/kg", "name": "m3/kg"}, + {"label": "cm3/g", "name": "cm3/g"}, + {"label": "ft3/lbm", "name": "ft3/lbm"}, + ], + }, + { + "name": "velocity", + "label": "Velocity", + "units": [ + {"label": "m/s", "name": "m/s"}, + {"label": "cm/s", "name": "cm/s"}, + {"label": "mm/s", "name": "mm/s"}, + {"label": "km/h", "name": "km/h"}, + {"label": "ft/h", "name": "ft/h"}, + {"label": "ft/min", "name": "ft/min"}, + {"label": "ft/s", "name": "ft/s"}, + {"label": "in/s", "name": "in/s"}, + ], + }, + { + "name": "mass_conc", + "label": "Mass Concentration", + "units": [ + {"label": "kg/m3", "name": "kg/m3"}, + {"label": "g/L", "name": "g/L"}, + {"label": "g/cm3", "name": "g/cm3"}, + {"label": "g/mL", "name": "g/mL"}, + {"label": "lbm/ft3", "name": "lbm/ft3"}, + ], + }, + { + "name": "molarflow", + "label": "Molar Flow", + "units": [ + {"label": "mol/s", "name": "mol/s"}, + {"label": "lbmol/h", "name": "lbmol/h"}, + {"label": "mol/h", "name": "mol/h"}, + {"label": "mol/d", "name": "mol/d"}, + {"label": "kmol/s", "name": "kmol/s"}, + {"label": "kmol/h", "name": "kmol/h"}, + {"label": "kmol/d", "name": "kmol/d"}, + {"label": "m3/d @ BR", "name": "m3/d @ BR"}, + {"label": "m3/d @ NC", "name": "m3/d @ NC"}, + {"label": "m3/d @ CNTP", "name": "m3/d @ CNTP"}, + {"label": "m3/d @ SC", "name": "m3/d @ SC"}, + {"label": "m3/d @ 0 C, 1 atm", "name": "m3/d @ 0 C, 1 atm"}, + {"label": "m3/d @ 15.56 C, 1 atm", "name": "m3/d @ 15.56 C, 1 atm"}, + {"label": "m3/d @ 20 C, 1 atm", "name": "m3/d @ 20 C, 1 atm"}, + {"label": "ft3/d @ 60 f, 14.7 psia", "name": "ft3/d @ 60 f, 14.7 psia"}, + {"label": "ft3/d @ 0 C, 1 atm", "name": "ft3/d @ 0 C, 1 atm"}, + {"label": "MMSCFD", "name": "MMSCFD"}, + {"label": "SCFD", "name": "SCFD"}, + {"label": "SCFM", "name": "SCFM"}, + {"label": "Mm3/d @ BR", "name": "Mm3/d @ BR"}, + {"label": "Mm3/d @ SC", "name": "Mm3/d @ SC"}, + {"label": "Mm3/d @ NC", "name": "Mm3/d @ NC"}, + ], + }, + { + "name": "reac_rate", + "label": "Reaction Rate", + "units": [ + {"label": "kmol/[m3.s]", "name": "kmol/[m3.s]"}, + {"label": "kmol/[m3.min.]", "name": "kmol/[m3.min.]"}, + {"label": "kmol/[m3.h]", "name": "kmol/[m3.h]"}, + {"label": "mol/[m3.s]", "name": "mol/[m3.s]"}, + {"label": "mol/[m3.min.]", "name": "mol/[m3.min.]"}, + {"label": "mol/[m3.h]", "name": "mol/[m3.h]"}, + {"label": "mol/[L.s]", "name": "mol/[L.s]"}, + {"label": "mol/[L.min.]", "name": "mol/[L.min.]"}, + {"label": "mol/[L.h]", "name": "mol/[L.h]"}, + {"label": "mol/[cm3.s]", "name": "mol/[cm3.s]"}, + {"label": "mol/[cm3.min.]", "name": "mol/[cm3.min.]"}, + {"label": "mol/[cm3.h]", "name": "mol/[cm3.h]"}, + {"label": "lbmol/[ft3.h]", "name": "lbmol/[ft3.h]"}, + ], + }, + { + "name": "viscosity", + "label": "Viscosity", + "units": [ + {"label": "kg/[m.s]", "name": "kg/[m.s]"}, + {"label": "Pa.s", "name": "Pa.s"}, + {"label": "cP", "name": "cP"}, + {"label": "lbm/[ft.h]", "name": "lbm/[ft.h]"}, + ], + }, + { + "name": "molar_conc", + "label": "Molar Concentration", + "units": [ + {"label": "kmol/m3", "name": "kmol/m3"}, + {"label": "mol/m3", "name": "mol/m3"}, + {"label": "mol/L", "name": "mol/L"}, + {"label": "mol/cm3", "name": "mol/cm3"}, + {"label": "mol/mL", "name": "mol/mL"}, + {"label": "lbmol/ft3", "name": "lbmol/ft3"}, + ], + }, + { + "name": "conductance", + "label": "Conductance", + "units": [ + {"label": "[kg/s]/[Pa^0.5]", "name": "[kg/s]/[Pa^0.5]"}, + {"label": "[lbm/h]/[psi^0.5]", "name": "[lbm/h]/[psi^0.5]"}, + {"label": "[kg/h]/[atm^0.5]", "name": "[kg/h]/[atm^0.5]"}, + {"label": "[kg/h]/[bar^0.5]", "name": "[kg/h]/[bar^0.5]"}, + {"label": "[kg/h]/[[kgf/cm2]^0.5]", "name": "[kg/h]/[[kgf/cm2]^0.5]"}, + ], + }, + { + "name": "diffusivity", + "label": "Diffusivity", + "units": [ + {"label": "m2/s", "name": "m2/s"}, + {"label": "cSt", "name": "cSt"}, + {"label": "ft2/s", "name": "ft2/s"}, + {"label": "mm2/s", "name": "mm2/s"}, + {"label": "cm2/s", "name": "cm2/s"}, + ], + }, + { + "name": "temperature", + "label": "Temperature", + "units": [ + {"label": "K", "name": "K"}, + {"label": "R", "name": "R"}, + {"label": "C", "name": "C"}, + {"label": "F", "name": "F"}, + ], + }, + { + "name": "molar_volume", + "label": "Molar Volume", + "units": [ + {"label": "m3/kmol", "name": "m3/kmol"}, + {"label": "cm3/mmol", "name": "cm3/mmol"}, + {"label": "ft3/lbmol", "name": "ft3/lbmol"}, + ], + }, + { + "name": "speedOfSound", + "label": "Speed of Sound", + "units": [ + {"label": "m/s", "name": "m/s"}, + {"label": "cm/s", "name": "cm/s"}, + {"label": "mm/s", "name": "mm/s"}, + {"label": "km/h", "name": "km/h"}, + {"label": "ft/h", "name": "ft/h"}, + {"label": "ft/min", "name": "ft/min"}, + {"label": "ft/s", "name": "ft/s"}, + {"label": "in/s", "name": "in/s"}, + ], + }, + { + "name": "foulingfactor", + "label": "Fouling Factor", + "units": [ + {"label": "K.m2/W", "name": "K.m2/W"}, + {"label": "C.cm2.s/cal", "name": "C.cm2.s/cal"}, + {"label": "ft2.h.F/BTU", "name": "ft2.h.F/BTU"}, + ], + }, + { + "name": "molar_entropy", + "label": "Molar Entropy", + "units": [ + {"label": "kJ/[kmol.K]", "name": "kJ/[kmol.K]"}, + {"label": "cal/[mol.C]", "name": "cal/[mol.C]"}, + {"label": "BTU/[lbmol.R]", "name": "BTU/[lbmol.R]"}, + ], + }, + { + "name": "cakeresistance", + "label": "Cake Resistance", + "units": [ + {"label": "m/kg", "name": "m/kg"}, + {"label": "ft/lbm", "name": "ft/lbm"}, + {"label": "cm/g", "name": "cm/g"}, + ], + }, + { + "name": "heatCapacityCp", + "label": "Cp", + "units": [ + {"label": "kJ/[kg.K]", "name": "kJ/[kg.K]"}, + {"label": "cal/[g.C]", "name": "cal/[g.C]"}, + {"label": "BTU/[lbm.R]", "name": "BTU/[lbm.R]"}, + ], + }, + { + "name": "molar_enthalpy", + "label": "Molar Enthalpy", + "units": [ + {"label": "kJ/kmol", "name": "kJ/kmol"}, + {"label": "cal/mol", "name": "cal/mol"}, + {"label": "BTU/lbmol", "name": "BTU/lbmol"}, + {"label": "J/mol", "name": "J/mol"}, + ], + }, + { + "name": "surfaceTension", + "label": "Surface Tension", + "units": [ + {"label": "N/m", "name": "N/m"}, + {"label": "dyn/cm", "name": "dyn/cm"}, + {"label": "lbf/in", "name": "lbf/in"}, + ], + }, + { + "name": "volumetricFlow", + "label": "Volumetric Flow", + "units": [ + {"label": "m3/s", "name": "m3/s"}, + {"label": "ft3/s", "name": "ft3/s"}, + {"label": "cm3/s", "name": "cm3/s"}, + {"label": "m3/h", "name": "m3/h"}, + {"label": "m3/d", "name": "m3/d"}, + {"label": "bbl/h", "name": "bbl/h"}, + {"label": "bbl/d", "name": "bbl/d"}, + {"label": "ft3/min", "name": "ft3/min"}, + {"label": "ft3/d", "name": "ft3/d"}, + {"label": "gal[UK]/h", "name": "gal[UK]/h"}, + {"label": "gal[UK]/min", "name": "gal[UK]/min"}, + {"label": "gal[UK]/s", "name": "gal[UK]/s"}, + {"label": "gal[US]/h", "name": "gal[US]/h"}, + {"label": "gal[US]/min", "name": "gal[US]/min"}, + {"label": "gal[US]/s", "name": "gal[US]/s"}, + {"label": "L/h", "name": "L/h"}, + {"label": "L/min", "name": "L/min"}, + {"label": "L/s", "name": "L/s"}, + ], + }, + { + "name": "compressibility", + "label": "Compressibility", + "units": [ + {"label": "1/Pa", "name": "1/Pa"}, + {"label": "1/atm", "name": "1/atm"}, + {"label": "1/kPa", "name": "1/kPa"}, + {"label": "1/bar", "name": "1/bar"}, + {"label": "1/MPa", "name": "1/MPa"}, + {"label": "1/psi", "name": "1/psi"}, + ], + }, + { + "name": "molecularWeight", + "label": "Molecular Weight", + "units": [ + {"label": "kg/kmol", "name": "kg/kmol"}, + {"label": "g/mol", "name": "g/mol"}, + {"label": "lbm/lbmol", "name": "lbm/lbmol"}, + ], + }, + { + "name": "mediumresistance", + "label": "Medium Resistance", + "units": [ + {"label": "m-1", "name": "m-1"}, + {"label": "cm-1", "name": "cm-1"}, + {"label": "ft-1", "name": "ft-1"}, + ], + }, + { + "name": "heat_transf_coeff", + "label": "Heat Transfer Coefficient", + "units": [ + {"label": "W/[m2.K]", "name": "W/[m2.K]"}, + {"label": "cal/[cm2.s.C]", "name": "cal/[cm2.s.C]"}, + {"label": "BTU/[ft2.h.R]", "name": "BTU/[ft2.h.R]"}, + ], + }, + { + "name": "reac_rate_heterog", + "label": "Reaction Rate Heterogeneous", + "units": [ + {"label": "kmol/[kg.s]", "name": "kmol/[kg.s]"}, + {"label": "kmol/[kg.min.]", "name": "kmol/[kg.min.]"}, + {"label": "kmol/[kg.h]", "name": "kmol/[kg.h]"}, + {"label": "mol/[kg.s]", "name": "mol/[kg.s]"}, + {"label": "mol/[kg.min.]", "name": "mol/[kg.min.]"}, + {"label": "mol/[kg.h]", "name": "mol/[kg.h]"}, + {"label": "lbmol/[lbm.h]", "name": "lbmol/[lbm.h]"}, + ], + }, + { + "name": "cinematic_viscosity", + "label": "Kinematic Viscosity", + "units": [ + {"label": "m2/s", "name": "m2/s"}, + {"label": "cSt", "name": "cSt"}, + {"label": "ft2/s", "name": "ft2/s"}, + {"label": "mm2/s", "name": "mm2/s"}, + {"label": "cm2/s", "name": "cm2/s"}, + ], + }, + { + "name": "thermalConductivity", + "label": "Thermal Conductivity", + "units": [ + {"label": "W/[m.K]", "name": "W/[m.K]"}, + {"label": "cal/[cm.s.C]", "name": "cal/[cm.s.C]"}, + {"label": "BTU/[ft.h.R]", "name": "BTU/[ft.h.R]"}, + ], + }, + { + "name": "jouleThomsonCoefficient", + "label": "Joule Thomson Coefficient", + "units": [ + {"label": "K/Pa", "name": "K/Pa"}, + {"label": "F/psi", "name": "F/psi"}, + {"label": "C/atm", "name": "C/atm"}, + ], + }, + ], +} + + +simulator_integration = { + "externalId": "integration_tests_workflow_connector", + "simulatorExternalId": "integration_tests_workflow", + "heartbeat": 1706396950969, + "dataSetId": 97552494921583, + "connectorVersion": "1.0.0", + "simulatorVersion": "1.0.0", + "licenseStatus": "AVAILABLE", + "licenseLastCheckedTime": 0, + "connectorStatus": "IDLE", + "connectorStatusUpdatedTime": 0, +} + + +simulator_model = { + "externalId": "integration_tests_workflow_model", + "simulatorExternalId": "integration_tests_workflow", + "name": "Test Simulator Model", + "description": "Test Simulator Model Desc", + "dataSetId": 97552494921583, + "labels": [{"externalId": "simconfig-labels-PROSPER"}], + "type": "SteadyState", +} + +simulator_model_revision = { + "externalId": "integration_tests_workflow_model_revision", + "modelExternalId": "integration_tests_workflow_model", + "description": "test sim model revision description", + "fileId": 00000000000000, +} + +simulator_routine = { + "externalId": "integration_tests_workflow_routine", + "modelExternalId": "integration_tests_workflow_model", + "simulatorIntegrationExternalId": "integration_tests_workflow_connector", + "name": "Routine test", + "description": "test", +} + +simulator_routine_revision = { + "externalId": "integration_tests_workflow_routine_revision", + "routineExternalId": "integration_tests_workflow_routine", + "configuration": { + "schedule": {"enabled": True, "cronExpression": "*/10 * * * *"}, + "dataSampling": {"enabled": True, "validationWindow": None, "samplingWindow": 15, "granularity": 1}, + "logicalCheck": [], + "steadyStateDetection": [], + "inputs": [ + { + "name": "Cold Water Temperature - Constant", + "referenceId": "CWTC", + "value": 10, + "valueType": "DOUBLE", + "unit": {"name": "C", "quantity": "temperature"}, + "saveTimeseriesExternalId": "DWSIM-INPUT-constinput-CWTC-ShowerMixer-AI", + }, + { + "name": "Cold Water Pressure - Constant", + "referenceId": "CWPC", + "value": 3.6, + "valueType": "DOUBLE", + "unit": {"name": "bar", "quantity": "pressure"}, + "saveTimeseriesExternalId": "DWSIM-INPUT-constinput-CWPC-ShowerMixer", + }, + { + "name": "Cold Water Volumetric Flow - Constant", + "referenceId": "CWVFC", + "value": 0.37, + "valueType": "DOUBLE", + "unit": {"name": "m3/h", "quantity": "volumetricFlow"}, + "saveTimeseriesExternalId": "DWSIM-INPUT-constinput-CWVFC-ShowerMixer-AI", + }, + { + "name": "Hot Water Temperature - Constant", + "referenceId": "HWTC", + "value": 69, + "valueType": "DOUBLE", + "unit": {"name": "C", "quantity": "temperature"}, + "saveTimeseriesExternalId": "DWSIM-INPUT-constinput-HWTC-ShowerMixer-AI", + }, + { + "name": "Hot Water Pressure - Constant", + "referenceId": "HWPC", + "value": 2.8, + "valueType": "DOUBLE", + "unit": {"name": "bar", "quantity": "pressure"}, + "saveTimeseriesExternalId": "DWSIM-INPUT-constinput-HWPC-ShowerMixer-AI", + }, + { + "name": "Hot Water Volumetric Flow - Constant", + "referenceId": "HWVFC", + "value": 0.19, + "valueType": "DOUBLE", + "unit": {"name": "m3/h", "quantity": "volumetricFlow"}, + "saveTimeseriesExternalId": "DWSIM-INPUT-constinput-HWVFC-ShowerMixer-AI", + }, + ], + "outputs": [ + { + "name": "Shower Temperature", + "referenceId": "ST", + "unit": {"name": "C", "quantity": "temperature"}, + "valueType": "DOUBLE", + "saveTimeseriesExternalId": "DWSIM-OUTPUT-const_input-ST-ShowerMixer-AI", + }, + { + "name": "Shower Pressure", + "referenceId": "SP", + "unit": {"name": "bar", "quantity": "pressure"}, + "valueType": "DOUBLE", + "saveTimeseriesExternalId": "DWSIM-OUTPUT-const_input-SP-ShowerMixer-AI", + }, + { + "name": "Shower Volumetric Flow", + "referenceId": "SVF", + "unit": {"name": "m3/h", "quantity": "volumetricFlow"}, + "valueType": "DOUBLE", + "saveTimeseriesExternalId": "DWSIM-OUTPUT-const_input-SVF-ShowerMixer-AI", + }, + ], + }, + "script": [ + { + "order": 1, + "description": "Set Inputs", + "steps": [ + { + "order": 1, + "stepType": "Set", + "arguments": {"referenceId": "CWTC", "objectName": "Cold water", "objectProperty": "Temperature"}, + }, + { + "order": 2, + "stepType": "Set", + "arguments": {"referenceId": "CWPC", "objectName": "Cold water", "objectProperty": "Pressure"}, + }, + { + "order": 3, + "stepType": "Set", + "arguments": { + "referenceId": "CWVFC", + "objectName": "Cold water", + "objectProperty": "Volumetric Flow", + }, + }, + { + "order": 4, + "stepType": "Set", + "arguments": {"referenceId": "HWTC", "objectName": "Hot water", "objectProperty": "Temperature"}, + }, + { + "order": 5, + "stepType": "Set", + "arguments": {"referenceId": "HWPC", "objectName": "Hot water", "objectProperty": "Pressure"}, + }, + { + "order": 6, + "stepType": "Set", + "arguments": { + "referenceId": "HWVFC", + "objectName": "Hot water", + "objectProperty": "Volumetric Flow", + }, + }, + ], + }, + { + "order": 2, + "description": "Solve the flowsheet", + "steps": [{"order": 1, "stepType": "Command", "arguments": {"command": "Solve"}}], + }, + { + "order": 3, + "description": "Set simulation outputs", + "steps": [ + { + "order": 1, + "stepType": "Get", + "arguments": {"referenceId": "ST", "objectName": "Shower", "objectProperty": "Temperature"}, + }, + { + "order": 2, + "stepType": "Get", + "arguments": {"referenceId": "SP", "objectName": "Shower", "objectProperty": "Pressure"}, + }, + { + "order": 3, + "stepType": "Get", + "arguments": {"referenceId": "SVF", "objectName": "Shower", "objectProperty": "Volumetric Flow"}, + }, + ], + }, + ], +} diff --git a/tests/tests_integration/test_api/test_data_workflows.py b/tests/tests_integration/test_api/test_data_workflows.py index 6ec8ecce9..e3df1f4da 100644 --- a/tests/tests_integration/test_api/test_data_workflows.py +++ b/tests/tests_integration/test_api/test_data_workflows.py @@ -9,6 +9,7 @@ from cognite.client.data_classes.workflows import ( CDFTaskParameters, FunctionTaskParameters, + SimulationTaskParameters, SubworkflowTaskParameters, TransformationTaskParameters, Workflow, @@ -26,6 +27,62 @@ ) from cognite.client.exceptions import CogniteAPIError from cognite.client.utils._text import random_string +from tests.data.simulators.seed import ( + simulator, + simulator_integration, + simulator_model, + simulator_model_revision, + simulator_routine, + simulator_routine_revision, +) + + +@pytest.fixture +def add_simulator_resoures(cognite_client: CogniteClient) -> None: + simulator_external_id = "integration_tests_workflow" + simulator_model_file_external_id = "ShowerMixer_simulator_model_file" + + file = cognite_client.files.upload( + path="tests/data/simulators/ShowerMixer.dwxmz", + external_id=simulator_model_file_external_id, + name="ShowerMixer.dwxmz", + data_set_id=97552494921583, + ) + + resources = [ + {"url": f"/api/v1/projects/{cognite_client.config.project}/simulators", "seed": simulator}, + { + "url": f"/api/v1/projects/{cognite_client.config.project}/simulators/integrations", + "seed": simulator_integration, + }, + {"url": f"/api/v1/projects/{cognite_client.config.project}/simulators/models", "seed": simulator_model}, + { + "url": f"/api/v1/projects/{cognite_client.config.project}/simulators/models/revisions", + "seed": {**simulator_model_revision, "fileId": file.id}, + }, + {"url": f"/api/v1/projects/{cognite_client.config.project}/simulators/routines", "seed": simulator_routine}, + { + "url": f"/api/v1/projects/{cognite_client.config.project}/simulators/routines/revisions", + "seed": simulator_routine_revision, + }, + ] + + for resource in resources: + cognite_client.post( + resource["url"], + json={"items": [resource["seed"]]}, + headers={"cdf-version": "alpha"}, + ) + + yield None + + cognite_client.post( + f"/api/v1/projects/{cognite_client.config.project}/simulators/delete", + json={"items": [{"externalId": simulator_external_id}]}, + headers={"cdf-version": "alpha"}, + ) + + cognite_client.files.delete(external_id=simulator_model_file_external_id) @pytest.fixture @@ -540,3 +597,34 @@ def test_trigger_run_history( ) # it would take too long to wait for the trigger to run, so we just check that the history is not None assert history is not None + + +class TestSimIntInWorkflows: + @pytest.mark.usefixtures("add_simulator_resoures") + def test_create_and_run_simint_workflow( + self, + cognite_client: CogniteClient, + ): + workflow_id = "integration_test-workflow_for_simulator_integration" + + version = WorkflowVersionUpsert( + workflow_external_id=workflow_id, + version="1", + workflow_definition=WorkflowDefinitionUpsert( + tasks=[ + WorkflowTask( + external_id=f"{workflow_id}-1-task1", + parameters=SimulationTaskParameters( + routine_external_id="integration_tests_workflow", + ), + ) + ], + description=None, + ), + ) + + res = cognite_client.workflows.versions.upsert(version) + assert res.workflow_external_id == workflow_id + assert res.workflow_definition.tasks[0].type == "simulator" + assert len(res.workflow_definition.tasks) > 0 + cognite_client.workflows.versions.delete(workflow_version_id=(workflow_id, "1"))