<jupyter_start><jupyter_text>.NET Initialization MiniSim is a .net dll and as such we need to import the pythonnet module (clr) and load the .net DLL into the Python kernel. Afterwards we can import the .net namespaces as Python modules.<jupyter_code>import clr
clr.AddReference(r"..\bin\MiniSim.Core")

import MiniSim.Core.Expressions as expr
import MiniSim.Core.Flowsheeting as fl
import MiniSim.Core.Numerics as num
from MiniSim.Core.UnitsOfMeasure import Unit, SI, METRIC, PhysicalDimension
import MiniSim.Core.ModelLibrary as lib
import MiniSim.Core.PropertyDatabase as chemsep
from MiniSim.Core.Reporting import Generator, StringBuilderLogger
import MiniSim.Core.Thermodynamics as thermo
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = (16,8)
plt.rcParams['grid.color'] = 'k'<jupyter_output><empty_output><jupyter_text>General Objects Instantiation<jupyter_code>Database = chemsep.ChemSepAdapter()
logger = StringBuilderLogger();
reporter = Generator(logger)

Database.ListComponents("benzen")<jupyter_output><empty_output><jupyter_text>Definition of the Thermo-System When an instance of the ThermodynamicSystem class is created, we can define the base method (NRTL. UNIQUAC or SRK). This will set the internal states accordingly. Alternatively the equilibrium approach could be chosen explicitly with the respective data classes. We then add three compontents from the ChemSep Database, Benzene, Toluene and P-Xylene. Use the ListComponents(string) method to find suitable components, and then use the exact spelling to select it from the databank.<jupyter_code>sys= thermo.ThermodynamicSystem("Test2","NRTL", "default")
sys.AddComponent(Database.FindComponent("Benzene"))
sys.AddComponent(Database.FindComponent("Toluene"))
sys.AddComponent(Database.FindComponent("P-xylene"))
Database.FillBIPs(sys)

sys.VariableFactory.SetOutputDimension(PhysicalDimension.Pressure, METRIC.mbar)<jupyter_output><empty_output><jupyter_text>Flowsheet Definition First we create the feed stream S01. For this stream, we specify the temperature and pressure, as well as the total molar flow and the molar composition. If ALL molar fractions are specified, the summation closure equation is not added to the equation system. In that case, the composition must add up to exactly one. In this example, we initialize the molar fraction of P-xylene, which means that it is still a free variable, and as such the closure will be added to the equation system.We need to define our own unit of measure for the molar flow, but because Pythonnet does not support .net operator overlading, we have to use a helper function that creates an aggregate unit: kmol/h<jupyter_code>kmolh=Unit.Make([SI.kmol],[SI.h])
print(kmolh)
S01 = (fl.MaterialStream("S01", sys)
    .Specify("T",50, METRIC.C)
    .Specify("P",1, METRIC.bar)
    .Specify("n",10.0, kmolh)
    .Specify("x[Benzene]",0.5)
    .Specify("x[Toluene]",0.1)
    .Init("x[P-xylene]",0.4)
    .InitializeFromMolarFractions()
    .FlashPT())

S02 = fl.MaterialStream("S02",sys)
S03 = fl.MaterialStream("S03",sys)<jupyter_output><empty_output><jupyter_text>Once the stream objects are created, we can instantiate the Flash object. We need to connect the In, Vap and Liq port to their respective streams. For a Flash, we need two additional degrees of freedom, chosen from temperature T, pressure P, vapor fraction VF or heat duty Q.<jupyter_code>flash = (lib.Flash("Flash",sys)
    .Connect("In", S01)
    .Connect("Vap", S02)
    .Connect("Liq", S03)
    .Specify("P", 1, METRIC.bar)
    .Specify("VF",0.5)
    .Initialize())<jupyter_output><empty_output><jupyter_text>Now that all the objects are created we can assemble them in a flowsheet.<jupyter_code>flowsheet= (fl.Flowsheet("Flow")
    .AddMaterialStreams(S01,S02,S03)
    .AddUnit(flash))<jupyter_output><empty_output><jupyter_text>Problem Solving using Newton-Raphson First, we create an instance of the solver class, which requires an instance of any ILogger-implementing class. Then we call the Solve method and pass either a flowsheet or an equation system. The equation system is solved using the Newton-Raphson method.Finally we use the Reporter object to write a textual summary of the flowsheet.<jupyter_code>presolver=  num.BasicNewtonSolver(logger)
presolver.Solve(flowsheet)

reporter.Report(flowsheet, 4, False)
print(logger.Flush())<jupyter_output>Iter Step Length     Infeasibility   Damping Notes
0    0               7816,8          1       
1    25253,7         2038,62         0,739200282809472 
2    5078,88         0,0920979       1       
3    678,222         0,00135012      1       
4    7,01157         2,38145E-05     1       
5    0,0425876       8,6519E-09      1       
Problem NLAES was solved. Constraint violation is below tolerance (5 iter, 53,42 ms, NV = 98, NZ = 347, NZ% = 3,61%)

Report for flowsheet Flow
================================================

Material Streams

System                    Test2      

Property                  Unit                S01          S02          S03

Temperature               °C              50.0000     106.4570     106.4570
Pressure                  mbar          1000.0000    1000.0000    1000.0000
Vapor Fraction            mol/mol          0.0000       1.0000       0.0000
Specific Enthalpy         kJ/kmol     -33624.2220    8757.1804  -24413.0090
Phase    [...]<jupyter_text>Equation Analyis When we want to view the actual equations used in the model, we have to create an EquationSystem explicitly.<jupyter_code>from IPython.display import display, Markdown, Latex
eq= num.AlgebraicSystem("Review")
flowsheet.CreateEquations(eq)
eqtab=""
eqtab+="|Model|Class|Group|Equation<img width=500/>|Residual|\n"
eqtab+="|:----|:----|:----|:------|---|\n"
for e in eq.Equations:
    eqtab+="|"+e.ModelName+"|"+e.ModelClass+"|"+e.Group+"|"+e.Pretty()+"|"+str(e.Residual())+"\n"
display(Markdown(eqtab))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1041041041041041, 'fraction_numerical': 0.04287620954287621, 'mean_word_length': 3.9463696369636962, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '114962', 'license': 'MIT', 'n_tokens_mistral': 2030, 'n_tokens_neox': 1824, 'n_words': 586, 'path': 'doc/SimpleFlash.ipynb', 'repo_name': 'Nukleon84/MiniSim', 'size': '5994'}