using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace CApp
{
    public partial class Form1 : Form
    {
        [DllImport(@"ppp.dll", EntryPoint = "initS", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int initS(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "loadSB", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int loadSB(int stream, int btype);

        [DllImport(@"ppp.dll", EntryPoint = "CompCID", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        private static extern int CompCID(int code);

        [DllImport(@"ppp.dll", EntryPoint = "setWm", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int setWm(int stream, double W);

        [DllImport(@"ppp.dll", EntryPoint = "setMP", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int setMP(int stream, int mp, int model, int state);

        [DllImport(@"ppp.dll", EntryPoint = "putCC", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        private static extern int putCC(int stream, int pos, int compcode);

        [DllImport(@"ppp.dll", EntryPoint = "putZ", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int putZ(int stream, int pos, double Zi);

        [DllImport(@"ppp.dll", EntryPoint = "setS", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int setS(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "setOp", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int setOp(int stream, double t, double p);

        [DllImport(@"ppp.dll", EntryPoint = "isSDef", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int isSDef(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "getErrFlag", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern int getErrFlag();

        [DllImport(@"ppp.dll", EntryPoint = "defErrMsg", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern void defErrMsg(int action);

        [DllImport(@"ppp.dll", EntryPoint = "setErrFlag", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern void setErrFlag(int action);

        [DllImport(@"ppp.dll", EntryPoint = "ErrMsg", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr ErrMsg();

        [DllImport(@"ppp.dll", EntryPoint = "getPatm", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double getPatm();

        [DllImport(@"ppp.dll", EntryPoint = "StrLf", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double StrLf(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "StrGD", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double StrGD(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "StrLD", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double StrLD(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "StrGSS", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double StrGSS(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "StrLSS", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double StrLSS(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "StrGJT", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double StrGJT(int stream);

        [DllImport(@"ppp.dll", EntryPoint = "StrLJT", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern double StrLJT(int stream);

        // given a integers (that identifies a quantity ) method returns as ANSI C type the string identifying the selected UM.
        [DllImport(@"ppp.dll", EntryPoint = "getSUMS", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr getSUMS(int unit);

        // given a component code method returns as ANSI C type the string with the name.
        [DllImport(@"ppp.dll", EntryPoint = "CompN", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr CompN(int code);
       
        

        // Use CAS codes to avoid problems with different versions of databases 
        static int METHANE_CAS = 74828;
        static int ETHANE_CAS = 74840; 
        static int PROPANE_CAS = 74986;
        static int ISOBUTANE_CAS = 75285;
        static int NBUTANE_CAS = 106978; 
        static int ISOPENTANE_CAS = 78784; 
        static int NPENTANE_CAS = 109660; 
        static int NHEXANE_CAS = 110543; 

        static int METHANE = CompCID(METHANE_CAS); // get this database code for Methane
        static int ETHANE = CompCID(ETHANE_CAS);
        static int PROPANE = CompCID(PROPANE_CAS);
        static int ISOBUTANE = CompCID(ISOBUTANE_CAS);
        static int NBUTANE = CompCID(NBUTANE_CAS); 
        static int ISOPENTANE = CompCID(ISOPENTANE_CAS);
        static int NPENTANE = CompCID(NPENTANE_CAS);
        static int NHEXANE = CompCID(NHEXANE_CAS);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // initialize names
            NAMEC1.Text = Marshal.PtrToStringAnsi(CompN(METHANE));
            NAMEC2.Text = Marshal.PtrToStringAnsi(CompN(ETHANE));
            NAMEC3.Text = Marshal.PtrToStringAnsi(CompN(PROPANE));
            NAMEC4.Text = Marshal.PtrToStringAnsi(CompN(ISOBUTANE));
            NAMEC5.Text = Marshal.PtrToStringAnsi(CompN(NBUTANE));
            NAMEC6.Text = Marshal.PtrToStringAnsi(CompN(ISOPENTANE));
            NAMEC7.Text = Marshal.PtrToStringAnsi(CompN(NPENTANE));
            NAMEC8.Text = Marshal.PtrToStringAnsi(CompN(NHEXANE));

            // compositions (to some possible numbers for a natural gas)
            MFC1.Text = "0.7";
            MFC2.Text = "0.15";
            MFC3.Text = "0.05";
            MFC4.Text = "0.05";
            MFC5.Text = "0.01";
            MFC6.Text = "0.01";
            MFC7.Text = "0.01";
            MFC8.Text = "0.02";

            // and operating conditions (to some standard cond.)
            double value = 200;
            TEMP.Text = value.ToString();
            value = getPatm();
            PRESS.Text = value.ToString();
            // see Properties operating manual for the codes of different units
            string ums = Marshal.PtrToStringAnsi(getSUMS(17)); // UM temperature
            UMT.Text = ums;
            ums = Marshal.PtrToStringAnsi(getSUMS(15));	// UM pressure
            UMP.Text = ums;
        }

        private void Calculate_Click(object sender, EventArgs e)
        {
            int res, stream;
            double p, t, z, value;
            string ums;

            // define a stream to use for calc's    
            stream = 1;
            initS(stream); // Initialize Stream...
            setWm(stream, 1); // a default value for flow
            setMP(stream, 1, 61, 0); // set Peng Robinson Extended (code = 61) for vapor fugacity 
            setMP(stream, 1, 61, 1); // same model for liquid fugacity
            setMP(stream, 2, 61, 0); // same model for vapor enthalpy 
            setMP(stream, 2, 61, 1); // same model for liquid enthalpy 
            setMP(stream, 3, 61, 0); // same model for vapor entropy 
            setMP(stream, 3, 61, 1); // same model for liquid entropy
            setMP(stream, 4, 61, 0); // same model for vapor volume 
            setMP(stream, 4, 61, 1); // same model for liquid volume 
            putCC(stream, 1, METHANE);
            putCC(stream, 2, ETHANE);
            putCC(stream, 3, PROPANE);
            putCC(stream, 4, ISOBUTANE);
            putCC(stream, 5, NBUTANE);
            putCC(stream, 6, NPENTANE);
            putCC(stream, 8, NHEXANE);
            z = double.Parse(MFC1.Text);
            putZ(stream, 1, z);
            z = double.Parse(MFC2.Text);
            putZ(stream, 2, z);
            z = double.Parse(MFC3.Text);
            putZ(stream, 3, z);
            z = double.Parse(MFC4.Text);
            putZ(stream, 4, z);
            z = double.Parse(MFC5.Text);
            putZ(stream, 5, z);
            z = double.Parse(MFC6.Text);
            putZ(stream, 6, z);
            z = double.Parse(MFC7.Text);
            putZ(stream, 7, z);
            z = double.Parse(MFC8.Text);
            putZ(stream, 8, z);
            setS(stream); // end stream defintion 
            loadSB(stream,0);  // automatically loads all available VLE BIPs from database

            if (isSDef(stream) != 0)
            {
                // stop Error messages
                defErrMsg(0);
           	    // reset Err's flag
                setErrFlag(0);
                // get operating conditions
                t = double.Parse(TEMP.Text);
                p = double.Parse(PRESS.Text);
                // isothermal flash at desired p,t conditions
                res = setOp(stream, t, p);
                if (res == 0) goto err_Renamed;

                // get all properties
                value = 1.0 - StrLf(stream); // convert liquid fraction to vapor fraction...
                R1.Text = value.ToString();
                // gas phase
                value = StrGD(stream);  // get density
                R2.Text = value.ToString();
                // see Properties operating manual for the codes of different units
                ums = Marshal.PtrToStringAnsi(getSUMS(27)); // UM density
                UM2.Text = ums;
                value = StrGSS(stream); // get speed of sound
                R3.Text = value.ToString();
                // see Properties operating manual for the codes of different units
                ums = Marshal.PtrToStringAnsi(getSUMS(38)); // UM velocity
                UM3.Text = ums;
                value = StrGJT(stream); // get Joule Thomson
                R4.Text = value.ToString();
                // see Properties operating manual for the codes of different units
                ums = Marshal.PtrToStringAnsi(getSUMS(52)); // UM Joule Thomson
                UM4.Text = ums;                
                // liquid phase
                value = StrLD(stream);
                R5.Text = value.ToString();
                // see Properties operating manual for the codes of different units
                ums = Marshal.PtrToStringAnsi(getSUMS(27)); // UM density
                UM5.Text = ums;
                value = StrLSS(stream);
                R6.Text = value.ToString();
                // see Properties operating manual for the codes of different units
                ums = Marshal.PtrToStringAnsi(getSUMS(38)); // UM velocity
                UM6.Text = ums;
                value = StrLJT(stream);
                R7.Text = value.ToString();
                // see Properties operating manual for the codes of different units
                ums = Marshal.PtrToStringAnsi(getSUMS(52)); // UM Joule Thomson
		    UM7.Text = ums;

            // show the Err message (if present)
            // (get Err flag, if TRUE there is
            //  an Err message)
            err_Renamed:
                if (getErrFlag() != 0) REPORT.Text = Marshal.PtrToStringAnsi(ErrMsg());
                else REPORT.Text = "No Errors";
            }
        }
    }
}
