Пример #1
0
        /// <summary>
        /// Calculation method for the CMixerExample110 unit operation.
        /// </summary>
        /// <remarks>
        /// A mixer unit operation combined the material flows from two inlet ports into the flow of a single outlet port.
        /// In order to do this calculation, the mixer unit obtains flow information from each inlet port,
        /// the adds the flows to obtain the flow of the outlet port. In the case of the mixer below, it is assumed that the
        /// components are the same in each material object and that the components are listed in the same order.
        /// After the combined flow is calculated at the values set to the outlet port, along with the
        /// enthalpy of the stream calculated from an energy balance and the pressure determined from
        /// the inlet pressures, the outlet stream can be flahsed to determine equilibrium conditions.
        /// The last task is releasing any duplicate material objects obtained.
        /// </remarks>
        /// <example>
        /// <para>An example of how to calculate a unit operation. This method obtains material objects
        /// from each of ports using the <seealso cref = "CapeOpen.CPortCollection"/> class. The <seealso cref = "CapeOpen.ICapeThermoMaterial"/>
        /// interface is used to obtain the names using the CompIds() method, flows of each of the
        /// components present in the material object and overall pressure obtained using the
        /// <seealso cref = "CapeOpen.ICapeThermoMaterial.GetOverallProp"/> method. The enthaply of
        /// each phase in the inlet materials is calculated using <seealso cref = "CapeOpen.ICapeThermoPropertyRoutine.CalcSinglePhaseProp"/>
        /// method. The inlet enthalpy was multiplied by the phase flow (phase fraction * overall flow)
        /// which was summed to determine the outlet stream enthalpy.
        /// The output pressure from the lower of the two streams' pressure and pressure drop parameter.
        /// Lastly, the results of the
        /// calculations are applied to the output material object using the <seealso cref = "CapeOpen.ICapeThermoMaterial.SetOverallProp"/>
        /// method. The last method of the calculate method is to call the material's
        /// <seealso cref = "CapeOpen.ICapeThermoEquilibriumRoutine.CalcEquilibrium"/> method.</para>
        /// <para>
        /// A calculation report is generated by this method that is made avalable through the
        /// <seealso cref = "CapeOpen.ICapeUnitReport.ProduceReport"/> method.
        /// </para>
        /// <para>
        /// In this case, the inlet materials need to be released. This is accomplished using the
        /// <seealso cref = "System.Runtime.InteropServices.Marshal.ReleaseComObject"/> method.
        /// Using this method to release the outlet material object would result in an null object reference error.
        /// </para>
        /// <para>
        /// The method also documents use of the <seealso cref = "CapeOpen.CCapeObject.throwException"/> method to provide
        /// CAPE-OPEN compliant error handling.
        /// </para>
        /// <code>
        /// public override void Calculate()
        /// {
        ///    this.calcReport = String.Empty;
        ///    // Log a message using the simulation context (pop-up message commented out.
        ///    if (this.SimulationContext != null)
        ///        (this.SimulationContext as CapeOpen.ICapeDiagnostic).LogMessage("Starting Mixer Calculation");
        ///    this.calcReport = String.Concat(this.calcReport, "Starting Mixer Calculation", System.Environment.NewLine);
        ///    // Get the material Object from Port 0.
        ///    CapeOpen.ICapeThermoMaterial in1 = null;
        ///    CapeOpen.ICapeThermoMaterial in2 = null;
        ///    CapeOpen.ICapeThermoMaterial output = null;
        ///    CapeOpen.ICapeThermoMaterial temp = null;
        ///    Object comps = null;
        ///    Object forms = null;
        ///    Object names = null;
        ///    Object bTemp = null;
        ///    Object molWts = null;
        ///    Object casNos = null;
        ///    string[] compIds1 = null;
        ///    string[] compIds2 = null;
        ///    string[] compIds3 = null;
        ///    try
        ///    {
        ///        temp = (this.Ports[0].connectedObject as CapeOpen.ICapeThermoMaterial);
        ///        in1 = temp.CreateMaterial() as CapeOpen.ICapeThermoMaterial;
        ///        //in1.CopyFromMaterial(temp);
        ///        if (temp.GetType().IsCOMObject) System.Runtime.InteropServices.Marshal.ReleaseComObject(temp);
        ///        (in1 as CapeOpen.ICapeThermoCompounds).GetCompoundList(ref comps, ref forms, ref names, ref bTemp, ref molWts, ref casNos);
        ///        compIds1 = comps as string[];
        ///        temp = this.Ports[1].connectedObject as CapeOpen.ICapeThermoMaterial;
        ///        in2 = temp.CreateMaterial() as CapeOpen.ICapeThermoMaterial;
        ///        //in2.CopyFromMaterial(temp);
        ///        if (temp.GetType().IsCOMObject) System.Runtime.InteropServices.Marshal.ReleaseComObject(temp);
        ///        (in2 as CapeOpen.ICapeThermoCompounds).GetCompoundList(ref comps, ref forms, ref names, ref bTemp, ref molWts, ref casNos);
        ///        compIds2 = comps as string[];
        ///        output = this.Ports[2].connectedObject as CapeOpen.ICapeThermoMaterial;
        ///        (output as CapeOpen.ICapeThermoCompounds).GetCompoundList(ref comps, ref forms, ref names, ref bTemp, ref molWts, ref casNos);
        ///        compIds3 = comps as string[];
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.1.", p_Ex);
        ///        this.calcReport = String.Concat(this.calcReport, "Material object does not support CAPE-OPEN Thermodynamics 1.1.", System.Environment.NewLine);
        ///        this.throwException(ex as CapeOpen.ECapeUser);
        ///    }
        ///    int l1 = 0;
        ///    int l2 = 0;
        ///    int l3 = 0;
        ///    l1 = compIds1.Length;
        ///    l2 = compIds2.Length;
        ///    l3 = compIds3.Length;
        ///    if (l1 != l2)
        ///    {
        ///        this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
        ///        throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
        ///    }
        ///    if (l1 != l3)
        ///    {
        ///        this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
        ///        throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not match outlet material.");
        ///    }
        ///    for (int i = 0; i &lt; l3; i++)
        ///    {
        ///        if ((String.Compare(compIds1[i], compIds2[i])) != 0)
        ///        {
        ///            this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
        ///            throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
        ///        }
        ///
        ///        if (String.Compare(compIds1[i], compIds3[i]) != 0)
        ///        {
        ///            this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
        ///            throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not mAtch outlet material.");
        ///        }
        ///    }
        ///
        ///    double[] press1 = null;
        ///    double[] press2 = null;
        ///    double[] flow1 = null;
        ///    double[] flow2 = null;
        ///    double[] flow3 = new double[l3];
        ///    string[] props = { "enthalpy" };
        ///    string[] overall = { "Overall" };
        ///    double[] enthalpy = { 0 };
        ///    Object obj = null;
        ///    Object obj1 = null;
        ///    Object obj2 = null;
        ///    Object obj3 = null;
        ///    string[] phases = null;
        ///    CapeOpen.ICapeThermoEquilibriumRoutine eqRoutine;
        ///    try
        ///    {
        ///        in1.GetOverallProp("flow", "mole", ref obj);
        ///        flow1 = obj as double[];
        ///        double totalFlow = 0;
        ///        foreach (double flow in flow1)
        ///        {
        ///            totalFlow = totalFlow + flow;
        ///        }
        ///        in1.GetOverallProp("pressure", "", ref obj);
        ///        press1 = obj as double[];
        ///        CapeOpen.ICapeThermoPropertyRoutine p_Calc = in1 as CapeOpen.ICapeThermoPropertyRoutine;
        ///        CapeOpen.ICapeThermoPhases phaseList = in1 as CapeOpen.ICapeThermoPhases;
        ///        phaseList.GetPhaseList(ref obj1, ref obj2, ref obj3);
        ///        phases = obj1 as string[];
        ///        foreach (String phase in phases)
        ///        {
        ///            p_Calc.CalcSinglePhaseProp(props, phase);
        ///            in1.GetSinglePhaseProp("enthalpy", phase, "mole", ref obj);
        ///            double[] enth = obj as double[];
        ///            in1.GetSinglePhaseProp("phaseFraction", phase, "mole", ref obj);
        ///            double[] fract = obj as double[];
        ///            enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
        ///        }
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.ECapeUser user = in1 as CapeOpen.ECapeUser;
        ///        this.calcReport = string.Concat(this.calcReport, user.description, System.Environment.NewLine);
        ///        this.throwException(user);
        ///    }
        ///    try
        ///    {
        ///        in2.GetOverallProp("flow", "mole", ref obj);
        ///        flow2 = obj as double[];
        ///        double totalFlow = 0;
        ///        foreach (double flow in flow2)
        ///        {
        ///            totalFlow = totalFlow + flow;
        ///        }
        ///        in2.GetOverallProp("pressure", "", ref obj);
        ///        press2 = obj as double[];
        ///        CapeOpen.ICapeThermoPropertyRoutine p_Calc = in2 as CapeOpen.ICapeThermoPropertyRoutine;
        ///        CapeOpen.ICapeThermoPhases phaseList = in2 as CapeOpen.ICapeThermoPhases;
        ///        phaseList.GetPhaseList(ref obj1, ref obj2, ref obj3);
        ///        foreach (String phase in phases)
        ///        {
        ///            p_Calc.CalcSinglePhaseProp(props, phase);
        ///            in2.GetSinglePhaseProp("enthalpy", phase, "mole", ref obj);
        ///            double[] enth = obj as double[];
        ///            in2.GetSinglePhaseProp("phaseFraction", phase, "mole", ref obj);
        ///            double[] fract = obj as double[];
        ///            enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
        ///        }
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.ECapeUser user = in2 as CapeOpen.ECapeUser;
        ///        this.calcReport = string.Concat(this.calcReport, user.description, System.Environment.NewLine);
        ///        this.throwException(user);
        ///    }
        ///    for (int i = 0; i &lt; l3; i++)
        ///    {
        ///        flow3[i] = flow1[i] + flow2[i];
        ///    }
        ///    try
        ///    {
        ///        output.SetOverallProp("flow", "mole", flow3);
        ///        double[] press = new double[1];
        ///        press[0] = press1[0];
        ///        if (press1[0] > press2[0]) press[0] = press2[0];
        ///        double pressdrop = (this.Parameters[0] as CapeOpen.CRealParameter).SIValue;
        ///        press[0] = press[0] - pressdrop;
        ///        output.SetOverallProp("pressure", "", press);
        ///        output.GetOverallProp("totalFlow", "mole", ref obj);
        ///        double[] totalFlow = obj as double[];
        ///        enthalpy[0] = enthalpy[0] / totalFlow[0];
        ///        output.SetOverallProp("enthalpy", "mole", enthalpy);
        ///        this.calcReport = string.Concat(this.calcReport, "The outlet pressure is: ", press[0].ToString(), "Pa", System.Environment.NewLine);
        ///        int[] status = { 0, 0 };
        ///        output.SetPresentPhases(phases, status);
        ///        this.calcReport = string.Concat(this.calcReport, "The outlet ethalpy is: ", enthalpy[0].ToString(), "J/Mole", System.Environment.NewLine);
        ///        eqRoutine = output as CapeOpen.ICapeThermoEquilibriumRoutine;
        ///        string[] spec1 = { "pressure", String.Empty, "Overall" };
        ///        string[] spec2 = { "enthalpy", String.Empty, "Overall" };
        ///        eqRoutine.CalcEquilibrium(spec1, spec2, "unspecified");
        ///        this.calcReport = string.Concat(this.calcReport, "Calculated pressure-enthalpy flash", System.Environment.NewLine);
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.ECapeUser user = output as CapeOpen.ECapeUser;
        ///        this.calcReport = string.Concat(this.calcReport, user.description, System.Environment.NewLine);
        ///        this.throwException(user);
        ///    }
        ///
        ///    if (in1.GetType().IsCOMObject) System.Runtime.InteropServices.Marshal.ReleaseComObject(in1);
        ///    if (in2.GetType().IsCOMObject) System.Runtime.InteropServices.Marshal.ReleaseComObject(in2);
        ///    // Log the end of the calculation.
        ///    if (this.SimulationContext != null)
        ///        (this.SimulationContext as CapeOpen.ICapeDiagnostic).LogMessage("Ending Mixer Calculation");
        ///    this.calcReport = string.Concat(this.calcReport, "Ending Mixer Calculation");
        ///    //(this.SimulationContext as CapeOpen.ICapeDiagnostic).PopUpMessage("Ending Mixer Calculation");
        /// }
        /// </code>
        /// </example>
        /// <seealso cref="CapeOpen.ICapeThermoMaterial"/>
        /// <seealso cref="CapeOpen.ICapeThermoCompounds"/>
        /// <seealso cref="CapeOpen.ICapeThermoPhases"/>
        /// <seealso cref="CapeOpen.ICapeThermoPropertyRoutine"/>
        /// <seealso cref="CapeOpen.ICapeThermoEquilibriumRoutine"/>
        /// <seealso cref="CapeOpen.COMExceptionHandler"/>
        public override void Calculate()
        {
            this.calcReport = String.Empty;
            // Log a message using the simulation context (pop-up message commented out.
            if (this.SimulationContext != null)
            {
                (this.SimulationContext as CapeOpen.ICapeDiagnostic).LogMessage("Starting Mixer Calculation");
            }
            this.calcReport = String.Concat(this.calcReport, "Starting Mixer Calculation", System.Environment.NewLine);
            // Get the material Object from Port 0.
            CapeOpen.ICapeThermoMaterial in1    = null;
            CapeOpen.ICapeThermoMaterial in2    = null;
            CapeOpen.ICapeThermoMaterial output = null;
            object temp   = null;
            Object comps  = null;
            Object forms  = null;
            Object names  = null;
            Object bTemp  = null;
            Object molWts = null;
            Object casNos = null;

            string[] compIds1 = null;
            string[] compIds2 = null;
            string[] compIds3 = null;
            try
            {
                temp = this.Ports[0].connectedObject;
                in1  = (temp as CapeOpen.ICapeThermoMaterial).CreateMaterial() as CapeOpen.ICapeThermoMaterial;
                in1.CopyFromMaterial(ref temp);
                if (temp.GetType().IsCOMObject)
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(temp);
                }
                (in1 as CapeOpen.ICapeThermoCompounds).GetCompoundList(ref comps, ref forms, ref names, ref bTemp, ref molWts, ref casNos);
                compIds1 = comps as string[];
                temp     = this.Ports[1].connectedObject as CapeOpen.ICapeThermoMaterial;
                in2      = (temp as CapeOpen.ICapeThermoMaterial).CreateMaterial() as CapeOpen.ICapeThermoMaterial;
                in2.CopyFromMaterial(ref temp);
                if (temp.GetType().IsCOMObject)
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(temp);
                }
                (in2 as CapeOpen.ICapeThermoCompounds).GetCompoundList(ref comps, ref forms, ref names, ref bTemp, ref molWts, ref casNos);
                compIds2 = comps as string[];
                output   = this.Ports[2].connectedObject as CapeOpen.ICapeThermoMaterial;
                (output as CapeOpen.ICapeThermoCompounds).GetCompoundList(ref comps, ref forms, ref names, ref bTemp, ref molWts, ref casNos);
                compIds3 = comps as string[];
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.1.", p_Ex);
                this.calcReport = String.Concat(this.calcReport, "Material object does not support CAPE-OPEN Thermodynamics 1.1.", System.Environment.NewLine);
                this.throwException(ex as CapeOpen.ECapeUser);
            }
            int l1 = 0;
            int l2 = 0;
            int l3 = 0;

            l1 = compIds1.Length;
            l2 = compIds2.Length;
            l3 = compIds3.Length;
            if (l1 != l2)
            {
                this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
                throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
            }
            if (l1 != l3)
            {
                this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
                throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not match outlet material.");
            }
            for (int i = 0; i < l3; i++)
            {
                if ((String.Compare(compIds1[i], compIds2[i])) != 0)
                {
                    this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
                    throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
                }

                if (String.Compare(compIds1[i], compIds3[i]) != 0)
                {
                    this.calcReport = string.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
                    throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not mAtch outlet material.");
                }
            }

            double[] press1   = null;
            double[] press2   = null;
            double[] flow1    = null;
            double[] flow2    = null;
            double[] flow3    = new double[l3];
            string[] props    = { "enthalpy" };
            string[] overall  = { "Overall" };
            double[] enthalpy = { 0 };
            Object   obj      = null;
            Object   obj1     = null;
            Object   obj2     = null;
            Object   obj3     = null;

            string[] phases = null;
            CapeOpen.ICapeThermoEquilibriumRoutine eqRoutine;
            try
            {
                in1.GetOverallProp("flow", "mole", ref obj);
                flow1 = obj as double[];
                double totalFlow = 0;
                foreach (double flow in flow1)
                {
                    totalFlow = totalFlow + flow;
                }
                in1.GetOverallProp("pressure", "", ref obj);
                press1 = obj as double[];
                CapeOpen.ICapeThermoPropertyRoutine p_Calc    = in1 as CapeOpen.ICapeThermoPropertyRoutine;
                CapeOpen.ICapeThermoPhases          phaseList = in1 as CapeOpen.ICapeThermoPhases;
                phaseList.GetPhaseList(ref obj1, ref obj2, ref obj3);
                phases = obj1 as string[];
                foreach (String phase in phases)
                {
                    p_Calc.CalcSinglePhaseProp(props, phase);
                    in1.GetSinglePhaseProp("enthalpy", phase, "mole", ref obj);
                    double[] enth = obj as double[];
                    in1.GetSinglePhaseProp("phaseFraction", phase, "mole", ref obj);
                    double[] fract = obj as double[];
                    enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
                }
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.ECapeUser user = in1 as CapeOpen.ECapeUser;
                this.calcReport = string.Concat(this.calcReport, user.description, System.Environment.NewLine);
                this.throwException(user);
            }
            try
            {
                in2.GetOverallProp("flow", "mole", ref obj);
                flow2 = obj as double[];
                double totalFlow = 0;
                foreach (double flow in flow2)
                {
                    totalFlow = totalFlow + flow;
                }
                in2.GetOverallProp("pressure", "", ref obj);
                press2 = obj as double[];
                CapeOpen.ICapeThermoPropertyRoutine p_Calc    = in2 as CapeOpen.ICapeThermoPropertyRoutine;
                CapeOpen.ICapeThermoPhases          phaseList = in2 as CapeOpen.ICapeThermoPhases;
                phaseList.GetPhaseList(ref obj1, ref obj2, ref obj3);
                foreach (String phase in phases)
                {
                    p_Calc.CalcSinglePhaseProp(props, phase);
                    in2.GetSinglePhaseProp("enthalpy", phase, "mole", ref obj);
                    double[] enth = obj as double[];
                    in2.GetSinglePhaseProp("phaseFraction", phase, "mole", ref obj);
                    double[] fract = obj as double[];
                    enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
                }
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.ECapeUser user = in2 as CapeOpen.ECapeUser;
                this.calcReport = string.Concat(this.calcReport, user.description, System.Environment.NewLine);
                this.throwException(user);
            }
            for (int i = 0; i < l3; i++)
            {
                flow3[i] = flow1[i] + flow2[i];
            }
            try
            {
                output.SetOverallProp("flow", "mole", flow3);
                double[] press = new double[1];
                press[0] = press1[0];
                if (press1[0] > press2[0])
                {
                    press[0] = press2[0];
                }
                double pressdrop = (this.Parameters[0] as CapeOpen.CRealParameter).SIValue;
                press[0] = press[0] - pressdrop;
                output.SetOverallProp("pressure", "", press);
                output.GetOverallProp("totalFlow", "mole", ref obj);
                double[] totalFlow = obj as double[];
                enthalpy[0] = enthalpy[0] / totalFlow[0];
                output.SetOverallProp("enthalpy", "mole", enthalpy);
                this.calcReport = string.Concat(this.calcReport, "The outlet pressure is: ", press[0].ToString(), "Pa", System.Environment.NewLine);
                int[] status = { 0, 0 };
                output.SetPresentPhases(phases, status);
                this.calcReport = string.Concat(this.calcReport, "The outlet ethalpy is: ", enthalpy[0].ToString(), "J/Mole", System.Environment.NewLine);
                eqRoutine       = output as CapeOpen.ICapeThermoEquilibriumRoutine;
                string[] spec1 = { "pressure", String.Empty, "Overall" };
                string[] spec2 = { "enthalpy", String.Empty, "Overall" };
                eqRoutine.CalcEquilibrium(spec1, spec2, "unspecified");
                this.calcReport = string.Concat(this.calcReport, "Calculated pressure-enthalpy flash", System.Environment.NewLine);
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.ECapeUser user = output as CapeOpen.ECapeUser;
                this.calcReport = string.Concat(this.calcReport, user.description, System.Environment.NewLine);
                this.throwException(user);
            }

            if (in1.GetType().IsCOMObject)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(in1);
            }
            if (in2.GetType().IsCOMObject)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(in2);
            }
            // Log the end of the calculation.
            if (this.SimulationContext != null)
            {
                (this.SimulationContext as CapeOpen.ICapeDiagnostic).LogMessage("Ending Mixer Calculation");
            }
            this.calcReport = string.Concat(this.calcReport, "Ending Mixer Calculation");
            //(this.SimulationContext as CapeOpen.ICapeDiagnostic).PopUpMessage("Ending Mixer Calculation");
        }
Пример #2
0
        /// <summary>
        /// Calculation method for the MixerExample unit operation.
        /// </summary>
        /// <remarks>
        /// A mixer unit operation combined the material flows from two inlet ports into the flow of a single outlet port.
        /// In order to do this calculation, the mixer unit obtains flow information from each inlet port,
        /// the adds the flows to obtain the flow of the outlet port. In the case of the mixer below, it is assumed that the
        /// components are the same in each material object and that the components are listed in the same order.
        /// After the combined flow is calculated at the values set to the outlet port, along with the
        /// enthalpy of the stream calculated from an energy balance and the pressure determined from
        /// the inlet pressures, the outlet stream can be flahsed to determine equilibrium conditions.
        /// The last task is releasing any duplicate material objects obtained.
        /// </remarks>
        /// <example>
        /// <para>An example of how to calculate a unit operation. This method obtains material objects
        /// from each of ports using the <see cref = "PortCollection"/> class. The <see cref = "ICapeThermoMaterialObject"/>
        /// interface is used to obtain the names using the CompIds() method, flows of each of the
        /// components present in the material object, overall pressure and overall enthalpy are
        /// obtained using the <see cref = "ICapeThermoMaterialObject.GetProp"/> method. The overall enthalpy of the stram is
        /// calculated using <see cref = "ICapeThermoMaterialObject.CalcProp"/> method. The unit then combines the flows,
        /// calculates the output stream enthalpy, and determines output pressure from the lower of
        /// the two streams' pressure and pressure drop parameter. Lastly, the results of the
        /// calculations are applied to the output material object using the <see cref = "ICapeThermoMaterialObject.SetProp"/>
        /// method. The last method of the calculate method is to call the material's
        /// <see cref = "ICapeThermoMaterialObject.CalcEquilibrium"/> method.</para>
        /// <para>
        /// In this case, the inlet materials need to be released. This is accomplished using the
        /// <see cref = "System.Runtime.InteropServices.Marshal.ReleaseComObject"/> method.
        /// Using this method to release the outlet material object would result in an null object reference error.
        /// </para>
        /// <para>
        /// The method also documents use of the <see cref = "CapeObjectBase.throwException"/> method to provide
        /// CAPE-OPEN compliant error handling.
        /// </para>
        /// <code>
        /// protected override void Calculate()
        /// {
        ///    // Log a message using the simulation context (pop-up message commented out.
        ///    if (this.SimulationContext != null)
        ///        ((ICapeDiagnostic)this.SimulationContext).LogMessage("Starting Mixer Calculation");
        ///    //(CapeOpen.ICapeDiagnostic)(this.SimulationContext).PopUpMessage("Starting Mixer Calculation");
        ///
        ///    // Get the material Object from Port 0.
        ///    ICapeThermoMaterialObject in1 = null;
        ///    ICapeThermoMaterialObject tempMO = null;
        ///    try
        ///    {
        ///        tempMO = (ICapeThermoMaterialObject)this.Ports[0].connectedObject;
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        this.OnUnitOperationEndCalculation("Error - Material object does not support CAPE-OPEN Thermodynamics 1.0.");
        ///        CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
        ///        this.throwException(ex);
        ///    }
        ///
        ///    // Duplicate the port, its an input port, always use a duplicate.
        ///    try
        ///    {
        ///        in1 = (ICapeThermoMaterialObject)tempMO.Duplicate();
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        this.OnUnitOperationEndCalculation("Error - Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.");
        ///        CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
        ///        this.throwException(ex);
        ///    }
        ///    // Arrays for the GetProps and SetProps call for enthaply.
        ///    String[] phases = { "Overall" };
        ///    String[] props = { "enthalpy" };
        ///
        ///    // Declare variables for calculations.
        ///    String[] in1Comps = null;
        ///    double[] in1Flow = null;
        ///    double[] in1Enthalpy = null;
        ///    double[] pressure = null;
        ///    double totalFlow1 = 0;
        ///
        ///    // Exception catching code...
        ///    try
        ///    {
        ///        // Get Strings, must cast to string array data type.
        ///        in1Comps = (String[])in1.ComponentIds;
        ///
        ///        // Get flow. Arguments are the property; phase, in this case, Overall; compound identifications
        ///        // in this case, the null returns the property for all components; calculation type, in this case,
        ///        // null, no calculation type; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
        ///        in1Flow = (double[])in1.GetProp("flow", "Overall", null, null, "mole");
        ///
        ///        // Get pressure. Arguments are the property; phase, in this case, Overall; compound identifications
        ///        // in this case, the null returns the property for all components; calculation type, in this case, the
        ///        // mixture; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
        ///        pressure = (double[])in1.GetProp("Pressure", "Overall", null, "Mixture", null);
        ///
        ///        // The following code adds the individual flows to get the total flow for the stream.
        ///        for (int i = 0; i &lt; in1Flow.Length; i++)
        ///        {
        ///            totalFlow1 = totalFlow1 + in1Flow[i];
        ///        }
        ///
        ///        // Calculates the mixture enthalpy of the stream.
        ///        in1.CalcProp(props, phases, "Mixture");
        ///
        ///        // Get the enthalpy of the stream. Arguments are the property, enthalpy; the phase, overall;
        ///        // a null pointer, required as the overall enthalpy is desired; the calculation type is
        ///        // mixture; and the basis is moles.
        ///        in1Enthalpy = (double[])in1.GetProp("enthalpy", "Overall", null, "Mixture", "mole");
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        // Exception handling, wraps a COM exception, shows the message, and re-throws the excecption.
        ///        if (p_Ex is System.Runtime.InteropServices.COMException)
        ///        {
        ///            System.Runtime.InteropServices.COMException comException = (System.Runtime.InteropServices.COMException)p_Ex;
        ///            p_Ex = CapeOpen.COMExceptionHandler.ExceptionForHRESULT(in1, p_Ex);
        ///        }
        ///        this.throwException(p_Ex);
        ///    }
        ///    IDisposable disp = in1 as IDisposable;
        ///    if (disp != null)
        ///    {
        ///        disp.Dispose();
        ///    }
        ///
        ///
        ///    // Get the material Object from Port 0.
        ///    ICapeThermoMaterialObject in2 = null;
        ///    tempMO = null;
        ///    try
        ///    {
        ///        tempMO = (ICapeThermoMaterialObject)this.Ports[1].connectedObject;
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        this.OnUnitOperationEndCalculation("Error - Material object does not support CAPE-OPEN Thermodynamics 1.0.");
        ///        CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
        ///        this.throwException(ex);
        ///    }
        ///
        ///    // Duplicate the port, its an input port, always use a duplicate.
        ///    try
        ///    {
        ///        in2 = (ICapeThermoMaterialObject)tempMO.Duplicate();
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        this.OnUnitOperationEndCalculation("Error - Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.");
        ///        CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
        ///        this.throwException(ex);
        ///    }
        ///
        ///    // Declare variables.
        ///    String[] in2Comps = null;
        ///    double[] in2Flow = null;
        ///    double[] in2Enthalpy = null;
        ///    double totalFlow2 = 0;
        ///
        ///    // Try block.
        ///    try
        ///    {
        ///        // Get the component identifications.
        ///        in2Comps = in2.ComponentIds;
        ///
        ///        // Get flow. Arguments are the property; phase, in this case, Overall; compound identifications
        ///        // in this case, the null returns the property for all components; calculation type, in this case,
        ///        // null, no calculation type; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
        ///        in2Flow = in2.GetProp("flow", "Overall", null, null, "mole");
        ///
        ///        // Get pressure. Arguments are the property; phase, in this case, Overall; compound identifications
        ///        // in this case, the null returns the property for all components; calculation type, in this case, the
        ///        // mixture; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
        ///        double[] press = in2.GetProp("Pressure", "Overall", null, "Mixture", null);
        ///        if (press[0] &lt; pressure[0]) pressure[0] = press[0];
        ///
        ///        // The following code adds the individual flows to get the total flow for the stream.
        ///        for (int i = 0; i &lt; in2Flow.Length; i++)
        ///        {
        ///            totalFlow2 = totalFlow2 + in2Flow[i];
        ///        }
        ///
        ///        // Calculates the mixture enthalpy of the stream.
        ///        in2.CalcProp(props, phases, "Mixture");
        ///
        ///        // Get the enthalpy of the stream. Arguments are the property, enthalpy; the phase, overall;
        ///        // a null pointer, required as the overall enthalpy is desired; the calculation type is
        ///        // mixture; and the basis is moles.
        ///        in2Enthalpy = in2.GetProp("enthalpy", "Overall", null, "Mixture", "mole");
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        System.Runtime.InteropServices.COMException comException = (System.Runtime.InteropServices.COMException)p_Ex;
        ///        if (comException != null)
        ///        {
        ///            p_Ex = CapeOpen.COMExceptionHandler.ExceptionForHRESULT(in2, p_Ex);
        ///        }
        ///        this.throwException(p_Ex);
        ///    }
        ///    // Release the material object if it is a COM object.
        ///    disp = in2 as IDisposable;
        ///    if (disp != null)
        ///    {
        ///        disp.Dispose();
        ///    }
        ///
        ///
        ///    // Get the outlet material object.
        ///    ICapeThermoMaterialObject outPort = (ICapeThermoMaterialObject)this.Ports[2].connectedObject;
        ///
        ///    // An empty, one-member array to set values in the outlet material stream.
        ///    double[] values = new double[1];
        ///
        ///    // Use energy balanace to calculate the outlet enthalpy.
        ///    values[0] = (in1Enthalpy[0] * totalFlow1 + in2Enthalpy[0] * totalFlow2) / (totalFlow1 + totalFlow2);
        ///    try
        ///    {
        ///        // Set the outlet enthalpy, for the overall phase, with a mixture calculation type
        ///        // to the value calculated above.
        ///        outPort.SetProp("enthalpy", "Overall", null, "Mixture", "mole", values);
        ///
        ///        // Set the outlet pressure to the lower of the to inlet pressures less the value of the
        ///        // pressure drop parameter.
        ///        pressure[0] = pressure[0] - (((RealParameter)(this.Parameters[0])).SIValue);
        ///
        ///        // Set the outlet pressure.
        ///        outPort.SetProp("Pressure", "Overall", null, null, null, pressure);
        ///
        ///        // Resize the value array for the number of components.
        ///        values = new double[in1Comps.Length];
        ///
        ///        // Calculate the individual flow for each component.
        ///        for (int i = 0; i &lt; in1Comps.Length; i++)
        ///        {
        ///            values[i] = in1Flow[i] + in2Flow[i];
        ///        }
        ///        // Set the outlet flow by component. Note, this is for overall phase and mole flows.
        ///        // The component Identifications are used as a check.
        ///        outPort.SetProp("flow", "Overall", in1Comps, null, "mole", values);
        ///
        ///        // Calculate equilibrium using a "pressure-enthalpy" flash type.
        ///        outPort.CalcEquilibrium("PH", null);
        ///
        ///        // Release the material object if it is a COM object.
        ///        if (outPort.GetType().IsCOMObject)
        ///        {
        ///            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(outPort);
        ///        }
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        System.Runtime.InteropServices.COMException comException = (System.Runtime.InteropServices.COMException)p_Ex;
        ///        if (comException != null)
        ///        {
        ///            p_Ex = CapeOpen.COMExceptionHandler.ExceptionForHRESULT(outPort, p_Ex);
        ///        }
        ///        this.throwException(p_Ex);
        ///    }
        ///
        ///    // Log the end of the calculation.
        ///    if (this.SimulationContext != null)
        ///        ((CapeOpen.ICapeDiagnostic)this.SimulationContext).LogMessage("Ending Mixer Calculation");
        ///    //(CapeOpen.ICapeDiagnostic)(this.SimulationContext).PopUpMessage("Ending Mixer Calculation");
        /// }
        ///
        /// </code>
        /// </example>
        /// <see cref="ICapeThermoMaterialObject"/>
        /// <see cref="COMExceptionHandler"/>
        protected override void Calculate()
        {
            // Log a message using the simulation context (pop-up message commented out.
            if (this.SimulationContext != null)
            {
                ((ICapeDiagnostic)this.SimulationContext).LogMessage("Starting Mixer Calculation");
            }
            //(CapeOpen.ICapeDiagnostic>(this.SimulationContext).PopUpMessage("Starting Mixer Calculation");

            // Get the material Object from Port 0.
            ICapeThermoMaterialObject in1    = null;
            ICapeThermoMaterialObject tempMO = null;

            try
            {
                tempMO = (ICapeThermoMaterialObject)this.Ports[0].connectedObject;
            }
            catch (System.Exception p_Ex)
            {
                this.OnUnitOperationEndCalculation("Error - Material object does not support CAPE-OPEN Thermodynamics 1.0.");
                CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
                this.throwException(ex);
            }

            // Duplicate the port, its an input port, always use a duplicate.
            try
            {
                in1 = (ICapeThermoMaterialObject)tempMO.Duplicate();
            }
            catch (System.Exception p_Ex)
            {
                this.OnUnitOperationEndCalculation("Error - Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.");
                CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
                this.throwException(ex);
            }
            // Arrays for the GetProps and SetProps call for enthaply.
            String[] phases = { "Overall" };
            String[] props  = { "enthalpy" };

            // Declare variables for calculations.
            String[] in1Comps    = null;
            double[] in1Flow     = null;
            double[] in1Enthalpy = null;
            double[] pressure    = null;
            double   totalFlow1  = 0;

            // Exception catching code...
            try
            {
                // Get Strings, must cast to string array data type.
                in1Comps = (String[])in1.ComponentIds;

                // Get flow. Arguments are the property; phase, in this case, Overall; compound identifications
                // in this case, the null returns the property for all components; calculation type, in this case,
                // null, no calculation type; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
                in1Flow = (double[])in1.GetProp("flow", "Overall", null, null, "mole");

                // Get pressure. Arguments are the property; phase, in this case, Overall; compound identifications
                // in this case, the null returns the property for all components; calculation type, in this case, the
                // mixture; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
                pressure = (double[])in1.GetProp("Pressure", "Overall", null, "Mixture", null);

                // The following code adds the individual flows to get the total flow for the stream.
                for (int i = 0; i < in1Flow.Length; i++)
                {
                    totalFlow1 = totalFlow1 + in1Flow[i];
                }

                // Calculates the mixture enthalpy of the stream.
                in1.CalcProp(props, phases, "Mixture");

                // Get the enthalpy of the stream. Arguments are the property, enthalpy; the phase, overall;
                // a null pointer, required as the overall enthalpy is desired; the calculation type is
                // mixture; and the basis is moles.
                in1Enthalpy = (double[])in1.GetProp("enthalpy", "Overall", null, "Mixture", "mole");
            }
            catch (System.Exception p_Ex)
            {
                // Exception handling, wraps a COM exception, shows the message, and re-throws the excecption.

                if (p_Ex is System.Runtime.InteropServices.COMException)
                {
                    System.Runtime.InteropServices.COMException comException = (System.Runtime.InteropServices.COMException)p_Ex;
                    p_Ex = CapeOpen.COMExceptionHandler.ExceptionForHRESULT(in1, p_Ex);
                }
                this.throwException(p_Ex);
            }
            IDisposable disp = in1 as IDisposable;

            if (disp != null)
            {
                disp.Dispose();
            }


            // Get the material Object from Port 0.
            ICapeThermoMaterialObject in2 = null;

            tempMO = null;
            try
            {
                tempMO = (ICapeThermoMaterialObject)this.Ports[1].connectedObject;
            }
            catch (System.Exception p_Ex)
            {
                this.OnUnitOperationEndCalculation("Error - Material object does not support CAPE-OPEN Thermodynamics 1.0.");
                CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
                this.throwException(ex);
            }

            // Duplicate the port, its an input port, always use a duplicate.
            try
            {
                in2 = (ICapeThermoMaterialObject)tempMO.Duplicate();
            }
            catch (System.Exception p_Ex)
            {
                this.OnUnitOperationEndCalculation("Error - Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.");
                CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Object connected to Inlet Port 1 does not support CAPE-OPEN Thermodynamics 1.0.", p_Ex);
                this.throwException(ex);
            }

            // Declare variables.
            String[] in2Comps    = null;
            double[] in2Flow     = null;
            double[] in2Enthalpy = null;
            double   totalFlow2  = 0;

            // Try block.
            try
            {
                // Get the component identifications.
                in2Comps = in2.ComponentIds;

                // Get flow. Arguments are the property; phase, in this case, Overall; compound identifications
                // in this case, the null returns the property for all components; calculation type, in this case,
                // null, no calculation type; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
                in2Flow = in2.GetProp("flow", "Overall", null, null, "mole");

                // Get pressure. Arguments are the property; phase, in this case, Overall; compound identifications
                // in this case, the null returns the property for all components; calculation type, in this case, the
                // mixture; and lastly, the basis, moles. Result is cast to a double array, and will contain one value.
                double[] press = in2.GetProp("Pressure", "Overall", null, "Mixture", null);
                if (press[0] < pressure[0])
                {
                    pressure[0] = press[0];
                }

                // The following code adds the individual flows to get the total flow for the stream.
                for (int i = 0; i < in2Flow.Length; i++)
                {
                    totalFlow2 = totalFlow2 + in2Flow[i];
                }

                // Calculates the mixture enthalpy of the stream.
                in2.CalcProp(props, phases, "Mixture");

                // Get the enthalpy of the stream. Arguments are the property, enthalpy; the phase, overall;
                // a null pointer, required as the overall enthalpy is desired; the calculation type is
                // mixture; and the basis is moles.
                in2Enthalpy = in2.GetProp("enthalpy", "Overall", null, "Mixture", "mole");
            }
            catch (System.Exception p_Ex)
            {
                System.Runtime.InteropServices.COMException comException = (System.Runtime.InteropServices.COMException)p_Ex;
                if (comException != null)
                {
                    p_Ex = CapeOpen.COMExceptionHandler.ExceptionForHRESULT(in2, p_Ex);
                }
                this.throwException(p_Ex);
            }
            // Release the material object if it is a COM object.
            disp = in2 as IDisposable;
            if (disp != null)
            {
                disp.Dispose();
            }


            // Get the outlet material object.
            ICapeThermoMaterialObject outPort = (ICapeThermoMaterialObject)this.Ports[2].connectedObject;

            // An empty, one-member array to set values in the outlet material stream.
            double[] values = new double[1];

            // Use energy balanace to calculate the outlet enthalpy.
            values[0] = (in1Enthalpy[0] * totalFlow1 + in2Enthalpy[0] * totalFlow2) / (totalFlow1 + totalFlow2);
            try
            {
                // Set the outlet enthalpy, for the overall phase, with a mixture calculation type
                // to the value calculated above.
                outPort.SetProp("enthalpy", "Overall", null, "Mixture", "mole", values);

                // Set the outlet pressure to the lower of the to inlet pressures less the value of the
                // pressure drop parameter.
                pressure[0] = pressure[0] - (((RealParameter)(this.Parameters[0])).SIValue);

                // Set the outlet pressure.
                outPort.SetProp("Pressure", "Overall", null, null, null, pressure);

                // Resize the value array for the number of components.
                values = new double[in1Comps.Length];

                // Calculate the individual flow for each component.
                for (int i = 0; i < in1Comps.Length; i++)
                {
                    values[i] = in1Flow[i] + in2Flow[i];
                }
                // Set the outlet flow by component. Note, this is for overall phase and mole flows.
                // The component Identifications are used as a check.
                outPort.SetProp("flow", "Overall", in1Comps, null, "mole", values);

                // Calculate equilibrium using a "pressure-enthalpy" flash type.
                outPort.CalcEquilibrium("PH", null);

                // Release the material object if it is a COM object.
                if (outPort.GetType().IsCOMObject)
                {
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(outPort);
                }
            }
            catch (System.Exception p_Ex)
            {
                System.Runtime.InteropServices.COMException comException = (System.Runtime.InteropServices.COMException)p_Ex;
                if (comException != null)
                {
                    p_Ex = CapeOpen.COMExceptionHandler.ExceptionForHRESULT(outPort, p_Ex);
                }
                this.throwException(p_Ex);
            }

            // Log the end of the calculation.
            if (this.SimulationContext != null)
            {
                ((CapeOpen.ICapeDiagnostic) this.SimulationContext).LogMessage("Ending Mixer Calculation");
            }
            //(CapeOpen.ICapeDiagnostic>(this.SimulationContext).PopUpMessage("Ending Mixer Calculation");
        }
Пример #3
0
        /// <summary>
        /// Calculation method for the CMixerExample110 unit operation.
        /// </summary>
        /// <remarks>
        /// A mixer unit operation combined the material flows from two inlet ports into the flow of a single outlet port.
        /// In order to do this calculation, the mixer unit obtains flow information from each inlet port,
        /// the adds the flows to obtain the flow of the outlet port. In the case of the mixer below, it is assumed that the
        /// components are the same in each material object and that the components are listed in the same order.
        /// After the combined flow is calculated at the values set to the outlet port, along with the
        /// enthalpy of the stream calculated from an energy balance and the pressure determined from
        /// the inlet pressures, the outlet stream can be flahsed to determine equilibrium conditions.
        /// The last task is releasing any duplicate material objects obtained.
        /// </remarks>
        /// <example>
        /// <para>An example of how to calculate a unit operation. This method obtains material objects
        /// from each of ports using the <see cref = "PortCollection"/> class. The <see cref = "ICapeThermoMaterial"/>
        /// interface is used to obtain the names using the CompIds() method, flows of each of the
        /// components present in the material object and overall pressure obtained using the
        /// <see cref = "ICapeThermoMaterial.GetOverallProp"/> method. The enthaply of
        /// each phase in the inlet materials is calculated using <see cref = "ICapeThermoPropertyRoutine.CalcSinglePhaseProp"/>
        /// method. The inlet enthalpy was multiplied by the phase flow (phase fraction * overall flow)
        /// which was summed to determine the outlet stream enthalpy.
        /// The output pressure from the lower of the two streams' pressure and pressure drop parameter.
        /// Lastly, the results of the
        /// calculations are applied to the output material object using the <see cref = "ICapeThermoMaterial.SetOverallProp"/>
        /// method. The last method of the calculate method is to call the material's
        /// <see cref = "ICapeThermoEquilibriumRoutine.CalcEquilibrium"/> method.</para>
        /// <para>
        /// A calculation report is generated by this method that is made avalable through the
        /// <see cref = "MixerExample110.ProduceReport"/> method.
        /// </para>
        /// <para>
        /// In this case, the inlet materials need to be released. This is accomplished using the
        /// <see cref = "System.Runtime.InteropServices.Marshal.ReleaseComObject"/> method.
        /// Using this method to release the outlet material object would result in an null object reference error.
        /// </para>
        /// <para>
        /// The method also documents use of the <see cref = "CapeObjectBase.throwException"/> method to provide
        /// CAPE-OPEN compliant error handling.
        /// </para>
        /// <code>
        ///protected override void Calculate()
        ///{
        ///    this.calcReport = String.Empty;
        ///    // Log a message using the simulation context (pop-up message commented out.
        ///    if (this.SimulationContext is CapeOpen.ICapeDiagnostic)
        ///        ((CapeOpen.ICapeDiagnostic)this.SimulationContext).LogMessage("Starting Mixer Calculation");
        ///    this.calcReport = String.Concat(this.calcReport, "Starting Mixer Calculation", System.Environment.NewLine);
        ///    // Get the material Object from Port 0.
        ///    ICapeThermoMaterial in1 = null;
        ///    ICapeThermoMaterial in2 = null;
        ///    ICapeThermoMaterial outlet = null;
        ///    ICapeThermoMaterial temp = null;
        ///    String[] compIds1 = null;
        ///    String[] compIds2 = null;
        ///    String[] compIds3 = null;
        ///    String[] forms = null;
        ///    String[] names = null;
        ///    double[] bTemps = null;
        ///    double[] molWts = null;
        ///    String[] casNos = null;
        ///    try
        ///    {
        ///        temp = (ICapeThermoMaterial)this.Ports[0].connectedObject;
        ///        in1 = (ICapeThermoMaterial)temp.CreateMaterial();
        ///        in1.CopyFromMaterial(temp);
        ///        if (temp.GetType().IsCOMObject) System.Runtime.InteropServices.Marshal.ReleaseComObject(temp);
        ///        ((CapeOpen.ICapeThermoCompounds)in1).GetCompoundList(ref compIds1, ref forms, ref names, ref bTemps, ref molWts, ref casNos);
        ///        temp = (ICapeThermoMaterial)this.Ports[1].connectedObject;
        ///        in2 = (ICapeThermoMaterial)temp.CreateMaterial();
        ///        in2.CopyFromMaterial(temp);
        ///        if (temp.GetType().IsCOMObject) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(temp);
        ///        ((CapeOpen.ICapeThermoCompounds)in2).GetCompoundList(ref compIds2, ref forms, ref names, ref bTemps, ref molWts, ref casNos);
        ///        outlet = (ICapeThermoMaterial)this.Ports[2].connectedObject;
        ///        ((CapeOpen.ICapeThermoCompounds)outlet).GetCompoundList(ref compIds3, ref forms, ref names, ref bTemps, ref molWts, ref casNos);
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.1.", p_Ex);
        ///        this.calcReport = String.Concat(this.calcReport, "Material object does not support CAPE-OPEN Thermodynamics 1.1.", System.Environment.NewLine);
        ///        this.throwException(ex);
        ///    }
        ///    int l1 = compIds1.Length;
        ///    int l2 = compIds2.Length;
        ///    int l3 = compIds3.Length;
        ///    if (l1 != l2)
        ///    {
        ///        this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
        ///        throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
        ///    }
        ///    if (l1 != l3)
        ///    {
        ///        this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
        ///        throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not match outlet material.");
        ///    }
        ///    for (int i = 0; i &lt; l3; i++)
        ///    {
        ///        if ((String.Compare(compIds1[i], compIds2[i])) != 0)
        ///        {
        ///            this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
        ///            throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
        ///        }
        ///
        ///        if (String.Compare(compIds1[i], compIds3[i]) != 0)
        ///        {
        ///            this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
        ///            throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not mAtch outlet material.");
        ///        }
        ///    }
        ///
        ///    double[] flow1 = null;
        ///    double[] flow2 = null;
        ///    double[] press1 = null;
        ///    double[] press2 = null;
        ///    double[] flow3 = new double[l3];
        ///    String[] props = { "enthalpy" };
        ///    String[] overall = { "Overall" };
        ///    double[] enthalpy = { 0 };
        ///    String[] phases = null;
        ///    CapeOpen.ICapeThermoEquilibriumRoutine eqRoutine;
        ///    string[] strArr1 = null;
        ///    string[] strArr2 = null;
        ///    try
        ///    {
        ///
        ///        in1.GetOverallProp("flow", "mole", ref flow1);
        ///        double totalFlow = 0;
        ///        foreach (double flow in flow1)
        ///        {
        ///            totalFlow = totalFlow + flow;
        ///        }
        ///        in1.GetOverallProp("pressure", "", ref press1);
        ///        CapeOpen.ICapeThermoPropertyRoutine p_Calc = (CapeOpen.ICapeThermoPropertyRoutine)in1;
        ///        CapeOpen.ICapeThermoPhases phaseList = (CapeOpen.ICapeThermoPhases)in1;
        ///        phaseList.GetPhaseList(ref phases, ref strArr1, ref strArr2);
        ///        foreach (String phase in phases)
        ///        {
        ///            p_Calc.CalcSinglePhaseProp(props, phase);
        ///            double[] enth = null;
        ///            in1.GetSinglePhaseProp("enthalpy", phase, "mole", ref enth);
        ///            double[] fract = null;
        ///            in1.GetSinglePhaseProp("phaseFraction", phase, "mole", ref fract);
        ///            enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
        ///        }
        ///        IDisposable disp = in1 as IDisposable;
        ///        if (disp != null)
        ///        {
        ///            disp.Dispose();
        ///        }
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.ECapeUser user = (CapeOpen.ECapeUser)in1;
        ///        this.calcReport = String.Concat(this.calcReport, user.description, System.Environment.NewLine);
        ///        this.throwException(p_Ex);
        ///    }
        ///    try
        ///    {
        ///        in2.GetOverallProp("flow", "mole", ref flow2);
        ///        double totalFlow = 0;
        ///        foreach (double flow in flow2)
        ///        {
        ///            totalFlow = totalFlow + flow;
        ///        }
        ///        in2.GetOverallProp("pressure", "", ref press2);
        ///        CapeOpen.ICapeThermoPropertyRoutine p_Calc = (CapeOpen.ICapeThermoPropertyRoutine)in2;
        ///        CapeOpen.ICapeThermoPhases phaseList = (CapeOpen.ICapeThermoPhases)in2;
        ///        phaseList.GetPhaseList(ref phases, ref strArr1, ref strArr2);
        ///        foreach (String phase in phases)
        ///        {
        ///            p_Calc.CalcSinglePhaseProp(props, phase);
        ///            double[] enth = null;
        ///            in2.GetSinglePhaseProp("enthalpy", phase, "mole", ref enth);
        ///            double[] fract = null;
        ///            in2.GetSinglePhaseProp("phaseFraction", phase, "mole", ref fract);
        ///            enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
        ///        }
        ///        IDisposable disp = in2 as IDisposable;
        ///        if (disp != null)
        ///        {
        ///            disp.Dispose();
        ///        }
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.ECapeUser user = (CapeOpen.ECapeUser)in2;
        ///        this.calcReport = String.Concat(this.calcReport, user.description, System.Environment.NewLine);
        ///        this.throwException(p_Ex);
        ///    }
        ///    for (int i = 0; i &lt; l3; i++)
        ///    {
        ///        flow3[i] = flow1[i] + flow2[i];
        ///    }
        ///    try
        ///    {
        ///        outlet.SetOverallProp("flow", "mole", flow3);
        ///        double[] press = new double[1];
        ///        press[0] = press1[0];
        ///        if (press1[0] &gt; press2[0]) press[0] = press2[0];
        ///        double pressdrop = ((CapeOpen.RealParameter)this.Parameters[0]).SIValue;
        ///        press[0] = press[0] - pressdrop;
        ///        outlet.SetOverallProp("pressure", "", press);
        ///        double[] totalFlow = null;
        ///        outlet.GetOverallProp("totalFlow", "mole", ref totalFlow);
        ///        enthalpy[0] = enthalpy[0] / totalFlow[0];
        ///        outlet.SetOverallProp("enthalpy", "mole", enthalpy);
        ///        this.calcReport = String.Concat(this.calcReport, "The outlet pressure is: ", press[0].ToString(), "Pa", System.Environment.NewLine);
        ///        CapePhaseStatus[] status = { CapePhaseStatus.CAPE_ATEQUILIBRIUM, CapePhaseStatus.CAPE_ATEQUILIBRIUM };
        ///        outlet.SetPresentPhases(phases, status);
        ///        this.calcReport = String.Concat(this.calcReport, "The outlet ethalpy is: ", enthalpy[0].ToString(), "J/Mole", System.Environment.NewLine);
        ///        eqRoutine = (CapeOpen.ICapeThermoEquilibriumRoutine)outlet;
        ///        String[] spec1 = { "pressure", String.Empty, "Overall" };
        ///        String[] spec2 = { "enthalpy", String.Empty, "Overall" };
        ///        eqRoutine.CalcEquilibrium(spec1, spec2, "unspecified");
        ///        this.calcReport = String.Concat(this.calcReport, "Calculated pressure-enthalpy flash", System.Environment.NewLine);
        ///    }
        ///    catch (System.Exception p_Ex)
        ///    {
        ///        CapeOpen.ECapeUser user = (CapeOpen.ECapeUser)outlet;
        ///        this.calcReport = String.Concat(this.calcReport, user.description, System.Environment.NewLine);
        ///        this.throwException(p_Ex);
        ///    }
        ///    // Log the end of the calculation.
        ///    this.calcReport = String.Concat(this.calcReport, "Ending Mixer Calculation");
        ///    if (this.SimulationContext is CapeOpen.ICapeDiagnostic)
        ///        ((CapeOpen.ICapeDiagnostic)this.SimulationContext).LogMessage("Ending Mixer Calculation");
        ///}
        /// </code>
        /// </example>
        /// <see cref="ICapeThermoMaterial"/>
        /// <see cref="ICapeThermoCompounds"/>
        /// <see cref="ICapeThermoPhases"/>
        /// <see cref="ICapeThermoPropertyRoutine"/>
        /// <see cref="ICapeThermoEquilibriumRoutine"/>
        /// <see cref="COMExceptionHandler"/>
        protected override void Calculate()
        {
            this.calcReport = String.Empty;
            // Log a message using the simulation context (pop-up message commented out.
            if (this.SimulationContext is CapeOpen.ICapeDiagnostic)
            {
                ((CapeOpen.ICapeDiagnostic) this.SimulationContext).LogMessage("Starting Mixer Calculation");
            }
            this.calcReport = String.Concat(this.calcReport, "Starting Mixer Calculation", System.Environment.NewLine);
            // Get the material Object from Port 0.
            ICapeThermoMaterial in1    = null;
            ICapeThermoMaterial in2    = null;
            ICapeThermoMaterial outlet = null;
            ICapeThermoMaterial temp   = null;

            String[] compIds1 = null;
            String[] compIds2 = null;
            String[] compIds3 = null;
            String[] forms    = null;
            String[] names    = null;
            double[] bTemps   = null;
            double[] molWts   = null;
            String[] casNos   = null;
            try
            {
                temp = (ICapeThermoMaterial)this.Ports[0].connectedObject;
                in1  = (ICapeThermoMaterial)temp.CreateMaterial();
                in1.CopyFromMaterial(temp);
                if (temp.GetType().IsCOMObject)
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(temp);
                }
                ((CapeOpen.ICapeThermoCompounds)in1).GetCompoundList(ref compIds1, ref forms, ref names, ref bTemps, ref molWts, ref casNos);
                temp = (ICapeThermoMaterial)this.Ports[1].connectedObject;
                in2  = (ICapeThermoMaterial)temp.CreateMaterial();
                in2.CopyFromMaterial(temp);
                if (temp.GetType().IsCOMObject)
                {
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(temp);
                }
                ((CapeOpen.ICapeThermoCompounds)in2).GetCompoundList(ref compIds2, ref forms, ref names, ref bTemps, ref molWts, ref casNos);
                outlet = (ICapeThermoMaterial)this.Ports[2].connectedObject;
                ((CapeOpen.ICapeThermoCompounds)outlet).GetCompoundList(ref compIds3, ref forms, ref names, ref bTemps, ref molWts, ref casNos);
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.CapeInvalidOperationException ex = new CapeOpen.CapeInvalidOperationException("Material object does not support CAPE-OPEN Thermodynamics 1.1.", p_Ex);
                this.calcReport = String.Concat(this.calcReport, "Material object does not support CAPE-OPEN Thermodynamics 1.1.", System.Environment.NewLine);
                this.throwException(ex);
            }
            int l1 = compIds1.Length;
            int l2 = compIds2.Length;
            int l3 = compIds3.Length;

            if (l1 != l2)
            {
                this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
                throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
            }
            if (l1 != l3)
            {
                this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
                throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not match outlet material.");
            }
            for (int i = 0; i < l3; i++)
            {
                if ((String.Compare(compIds1[i], compIds2[i])) != 0)
                {
                    this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials do not match.", System.Environment.NewLine);
                    throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials do not match.");
                }

                if (String.Compare(compIds1[i], compIds3[i]) != 0)
                {
                    this.calcReport = String.Concat(this.calcReport, "Compounds in imlet materials does not match outlet material.", System.Environment.NewLine);
                    throw new CapeOpen.CapeInvalidOperationException("Compounds in imlet materials does not mAtch outlet material.");
                }
            }

            double[] flow1    = null;
            double[] flow2    = null;
            double[] press1   = null;
            double[] press2   = null;
            double[] flow3    = new double[l3];
            String[] props    = { "enthalpy" };
            String[] overall  = { "Overall" };
            double[] enthalpy = { 0 };
            String[] phases   = null;
            CapeOpen.ICapeThermoEquilibriumRoutine eqRoutine;
            string[] strArr1 = null;
            string[] strArr2 = null;
            try
            {
                in1.GetOverallProp("flow", "mole", ref flow1);
                double totalFlow = 0;
                foreach (double flow in flow1)
                {
                    totalFlow = totalFlow + flow;
                }
                in1.GetOverallProp("pressure", "", ref press1);
                CapeOpen.ICapeThermoPropertyRoutine p_Calc    = (CapeOpen.ICapeThermoPropertyRoutine)in1;
                CapeOpen.ICapeThermoPhases          phaseList = (CapeOpen.ICapeThermoPhases)in1;
                phaseList.GetPhaseList(ref phases, ref strArr1, ref strArr2);
                foreach (String phase in phases)
                {
                    p_Calc.CalcSinglePhaseProp(props, phase);
                    double[] enth = null;
                    in1.GetSinglePhaseProp("enthalpy", phase, "mole", ref enth);
                    double[] fract = null;
                    in1.GetSinglePhaseProp("phaseFraction", phase, "mole", ref fract);
                    enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
                }
                IDisposable disp = in1 as IDisposable;
                if (disp != null)
                {
                    disp.Dispose();
                }
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.ECapeUser user = (CapeOpen.ECapeUser)in1;
                this.calcReport = String.Concat(this.calcReport, user.description, System.Environment.NewLine);
                this.throwException(p_Ex);
            }
            try
            {
                in2.GetOverallProp("flow", "mole", ref flow2);
                double totalFlow = 0;
                foreach (double flow in flow2)
                {
                    totalFlow = totalFlow + flow;
                }
                in2.GetOverallProp("pressure", "", ref press2);
                CapeOpen.ICapeThermoPropertyRoutine p_Calc    = (CapeOpen.ICapeThermoPropertyRoutine)in2;
                CapeOpen.ICapeThermoPhases          phaseList = (CapeOpen.ICapeThermoPhases)in2;
                phaseList.GetPhaseList(ref phases, ref strArr1, ref strArr2);
                foreach (String phase in phases)
                {
                    p_Calc.CalcSinglePhaseProp(props, phase);
                    double[] enth = null;
                    in2.GetSinglePhaseProp("enthalpy", phase, "mole", ref enth);
                    double[] fract = null;
                    in2.GetSinglePhaseProp("phaseFraction", phase, "mole", ref fract);
                    enthalpy[0] = enthalpy[0] + totalFlow * fract[0] * enth[0];
                }
                IDisposable disp = in2 as IDisposable;
                if (disp != null)
                {
                    disp.Dispose();
                }
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.ECapeUser user = (CapeOpen.ECapeUser)in2;
                this.calcReport = String.Concat(this.calcReport, user.description, System.Environment.NewLine);
                this.throwException(p_Ex);
            }
            for (int i = 0; i < l3; i++)
            {
                flow3[i] = flow1[i] + flow2[i];
            }
            try
            {
                outlet.SetOverallProp("flow", "mole", flow3);
                double[] press = new double[1];
                press[0] = press1[0];
                if (press1[0] > press2[0])
                {
                    press[0] = press2[0];
                }
                double pressdrop = ((CapeOpen.RealParameter) this.Parameters[0]).SIValue;
                press[0] = press[0] - pressdrop;
                outlet.SetOverallProp("pressure", "", press);
                double[] totalFlow = null;
                outlet.GetOverallProp("totalFlow", "mole", ref totalFlow);
                enthalpy[0] = enthalpy[0] / totalFlow[0];
                outlet.SetOverallProp("enthalpy", "mole", enthalpy);
                this.calcReport = String.Concat(this.calcReport, "The outlet pressure is: ", press[0].ToString(), "Pa", System.Environment.NewLine);
                CapePhaseStatus[] status = { CapePhaseStatus.CAPE_ATEQUILIBRIUM, CapePhaseStatus.CAPE_ATEQUILIBRIUM };
                outlet.SetPresentPhases(phases, status);
                this.calcReport = String.Concat(this.calcReport, "The outlet ethalpy is: ", enthalpy[0].ToString(), "J/Mole", System.Environment.NewLine);
                eqRoutine       = (CapeOpen.ICapeThermoEquilibriumRoutine)outlet;
                String[] spec1 = { "pressure", String.Empty, "Overall" };
                String[] spec2 = { "enthalpy", String.Empty, "Overall" };
                eqRoutine.CalcEquilibrium(spec1, spec2, "unspecified");
                this.calcReport = String.Concat(this.calcReport, "Calculated pressure-enthalpy flash", System.Environment.NewLine);
            }
            catch (System.Exception p_Ex)
            {
                CapeOpen.ECapeUser user = (CapeOpen.ECapeUser)outlet;
                this.calcReport = String.Concat(this.calcReport, user.description, System.Environment.NewLine);
                this.throwException(p_Ex);
            }
            // Log the end of the calculation.
            this.calcReport = String.Concat(this.calcReport, "Ending Mixer Calculation");
            if (this.SimulationContext is CapeOpen.ICapeDiagnostic)
            {
                ((CapeOpen.ICapeDiagnostic) this.SimulationContext).LogMessage("Ending Mixer Calculation");
            }
        }