Last active
April 25, 2024 19:36
-
-
Save DanWBR/43e261babd7ef96427b806264ae54043 to your computer and use it in GitHub Desktop.
Creates a DWSIM Simulation with a Plug-Flow Reactor + Kinetic Reaction using Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pythoncom | |
pythoncom.CoInitialize() | |
import clr | |
from System.IO import Directory, Path, File | |
from System import String, Environment | |
from System.Collections.Generic import Dictionary | |
dwsimpath = "C:\\Users\\Daniel\\AppData\\Local\\DWSIM8\\" | |
clr.AddReference(dwsimpath + "CapeOpen.dll") | |
clr.AddReference(dwsimpath + "DWSIM.Automation.dll") | |
clr.AddReference(dwsimpath + "DWSIM.Interfaces.dll") | |
clr.AddReference(dwsimpath + "DWSIM.GlobalSettings.dll") | |
clr.AddReference(dwsimpath + "DWSIM.SharedClasses.dll") | |
clr.AddReference(dwsimpath + "DWSIM.Thermodynamics.dll") | |
clr.AddReference(dwsimpath + "DWSIM.UnitOperations.dll") | |
clr.AddReference(dwsimpath + "System.Buffers.dll") | |
clr.AddReference(dwsimpath + "DWSIM.Thermodynamics.ThermoC.dll") | |
from DWSIM.Interfaces.Enums.GraphicObjects import ObjectType | |
from DWSIM.Thermodynamics import Streams, PropertyPackages | |
from DWSIM.UnitOperations import UnitOperations, Reactors | |
from DWSIM.Automation import Automation3 | |
from DWSIM.GlobalSettings import Settings | |
Directory.SetCurrentDirectory(dwsimpath) | |
interf = Automation3() | |
sim = interf.CreateFlowsheet() | |
# add compounds | |
sim.AddCompound("Water") | |
sim.AddCompound("Ethylene glycol") | |
sim.AddCompound("Ethylene oxide") | |
# add kinetic reaction | |
# stoichiometric coefficients | |
comps = Dictionary[str, float]() | |
comps.Add("Ethylene oxide", -1.0); | |
comps.Add("Water", -1.0); | |
comps.Add("Ethylene glycol", 1.0); | |
# direct order coefficients | |
dorders = Dictionary[str, float]() | |
dorders.Add("Ethylene oxide", 1.0); | |
dorders.Add("Water", 0.0); | |
dorders.Add("Ethylene glycol", 0.0); | |
# reverse order coefficients | |
rorders = Dictionary[str, float]({"Ethylene oxide": 0.0, "Water": 0.0, "Ethylene glycol": 0.0}) | |
rorders.Add("Ethylene oxide", 0.0); | |
rorders.Add("Water", 0.0); | |
rorders.Add("Ethylene glycol", 0.0); | |
# create kinetic reaction object | |
# https://dwsim.org/api_help/html/M_DWSIM_FlowsheetBase_FlowsheetBase_CreateKineticReaction.htm | |
# https://github.com/DanWBR/dwsim/blob/1103a3144734b7e1f20071aae98503a5e62daf35/DWSIM.FlowsheetBase/FlowsheetBase.vb#L3646 | |
kr1 = sim.CreateKineticReaction("Ethylene Glycol Production", "Production of Ethylene Glycol from Ethylene Oxide and Water", | |
comps, dorders, rorders, "Ethylene oxide", "Mixture", "Molar Concentration", "kmol/m3", "kmol/[m3.h]", 0.5, 0.0, 0.0, 0.0, "", "") | |
sim.AddReaction(kr1) | |
sim.AddReactionToSet(kr1.ID, "DefaultSet", True, 0) | |
# add objects | |
# https://dwsim.org/api_help/html/M_DWSIM_FlowsheetBase_FlowsheetBase_AddObject.htm | |
m1 = sim.AddObject(ObjectType.MaterialStream, 50, 50, "inlet") | |
m2 = sim.AddObject(ObjectType.MaterialStream, 200, 50, "outlet") | |
e1 = sim.AddObject(ObjectType.EnergyStream, 100, 50, "heat") | |
pfr = sim.AddObject(ObjectType.RCT_PFR, 100, 50, "reactor") | |
# connect streams to PFR | |
# https://dwsim.org/api_help/html/M_DWSIM_Interfaces_ISimulationObject_ConnectFeedMaterialStream.htm | |
pfr.ConnectFeedMaterialStream(m1, 0) | |
# https://dwsim.org/api_help/html/M_DWSIM_Interfaces_ISimulationObject_ConnectProductMaterialStream.htm | |
pfr.ConnectProductMaterialStream(m2, 0) | |
# https://dwsim.org/api_help/html/M_DWSIM_Interfaces_ISimulationObject_ConnectFeedEnergyStream.htm | |
pfr.ConnectFeedEnergyStream(e1, 1) | |
# PFR properties | |
# https://dwsim.org/api_help/html/T_DWSIM_UnitOperations_Reactors_Reactor_PFR.htm | |
pfr.ReactorOperationMode = Reactors.OperationMode.Isothermic | |
pfr.ReactorSizingType = Reactors.Reactor_PFR.SizingType.Length | |
pfr.Volume = 1.0; # m3 | |
pfr.Length = 1.2; # m | |
sim.AutoLayout() | |
# property package | |
# https://github.com/DanWBR/dwsim/blob/1103a3144734b7e1f20071aae98503a5e62daf35/DWSIM.FlowsheetBase/FlowsheetBase.vb#L3801 | |
# https://github.com/DanWBR/dwsim/blob/1103a3144734b7e1f20071aae98503a5e62daf35/DWSIM.FlowsheetBase/FlowsheetBase.vb#L3787 | |
sim.CreateAndAddPropertyPackage("Raoult's Law") | |
m1.SetTemperature(328.2) # K | |
m1.SetMolarFlow(0.0) # will set by compound | |
m1.SetOverallCompoundMolarFlow("Ethylene oxide", 2.39) # mol/s | |
m1.SetOverallCompoundMolarFlow("Water", 9.57) # mol/s | |
# request a calculation | |
errors = interf.CalculateFlowsheet4(sim); | |
print("Reactor Heat Load: {0:.4g} kW".format(pfr.DeltaQ)) | |
for c in pfr.ComponentConversions: | |
if (c.Value > 0): print("{0} conversion: {1:.4g}%".format(c.Key, c.Value * 100.0)) | |
if (len(errors) > 0): | |
for e in errors: | |
print("Error: " + e.ToString()) | |
# reactor profiles (temperature, pressure and concentration) | |
coordinates = [] # volume coordinate in m3 | |
names = [] # compound names | |
values = [] # concentrations in mol/m3 (0 to j, j = number of compounds - 1), temperature in K (j+1), pressure in Pa (j+2) | |
for p in pfr.points: | |
coordinates.append(p[0]) | |
for j in range(1, pfr.ComponentConversions.Count + 3): | |
list1 = [] | |
for p in pfr.points: | |
list1.append(p[j]) | |
values.append(list1) | |
for k in pfr.ComponentConversions.Keys: | |
names.append(k) | |
# save file | |
fileNameToSave = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "pfr.dwxmz") | |
interf.SaveFlowsheet(sim, fileNameToSave, True) | |
# save the pfd to an image and display it | |
clr.AddReference(dwsimpath + "SkiaSharp.dll") | |
clr.AddReference("System.Drawing") | |
from SkiaSharp import SKBitmap, SKImage, SKCanvas, SKEncodedImageFormat | |
from System.IO import MemoryStream | |
from System.Drawing import Image | |
from System.Drawing.Imaging import ImageFormat | |
PFDSurface = sim.GetSurface() | |
bmp = SKBitmap(800, 600) | |
canvas = SKCanvas(bmp) | |
canvas.Scale(1.0) | |
PFDSurface.ZoomAll(bmp.Width, bmp.Height) | |
PFDSurface.UpdateCanvas(canvas) | |
d = SKImage.FromBitmap(bmp).Encode(SKEncodedImageFormat.Png, 100) | |
str = MemoryStream() | |
d.SaveTo(str) | |
image = Image.FromStream(str) | |
imgPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "PFD.png") | |
image.Save(imgPath, ImageFormat.Png) | |
str.Dispose() | |
canvas.Dispose() | |
bmp.Dispose() | |
from PIL import Image | |
im = Image.open(imgPath) | |
im.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment