public void CalculateProperty(CapeOpenThermoMaterialPropertyType property, CapeOpenPhaseType phase, CapeOpenCalculationType calculationType)
        {
            string[] zType = new string[1];
            zType[0] = CapeOpenThermoMaterialPropertyTypeHelper.Map(property);
            string[] zPhase = new string[1];
            zPhase[0] = CapeOpenPhaseTypeHelper.Map(phase);
            string zCalculationType = CapeOpenCalculationTypeHelper.Map(calculationType);

            //mConnectedObject.CalcProp(CapeOpenThermoMaterialPropertyTypeHelper.Map(property), CapeOpenPhaseTypeHelper.Map(phase), "Mixture");
            if (calculationType != CapeOpenCalculationType.Nothing)
            {
                mConnectedObject.CalcProp(zType, zPhase, zCalculationType);
            }
            else
            {
                mConnectedObject.CalcProp(zType, zPhase, null);
            }
        }
        /// <summary>
        /// Calculate or get property
        /// </summary>
        /// <param name="propName">property name, defined in CO reference</param>
        /// <param name="phases">empty means </param>
        /// <param name="basis"></param>
        /// <param name="calculate"></param>
        /// <returns></returns>
        protected double[] GetPropList(string propName, PropertyBasis basis, Phases[] phases = null, bool calculate = true)
        {
            object value = null;

            try
            {
                // overall don't need calculate
                if (calculate && phases != null && phases.Length != 0)
                {
                    CasterLogger.Debug($"Calculate property {propName} for {phases}");
                    _capeThermoMaterialObject.CalcProp(new[] { propName }, phases, "mixture");
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine("Calculate single phase prop {0} fails. {1}", propName, e.Message);
            }
            if (phases == null || phases.Length == 0) // overall
            {
                CasterLogger.Debug($"Get property {propName} for overall phase");
                value = _capeThermoMaterialObject.GetProp(propName, "Overall", null, "mixture", basis.ToString());
            }
            else if (phases.Length == 1)  // one phase
            {
                CasterLogger.Debug($"Get property {propName} for {phases[0]}");
                value = _capeThermoMaterialObject.GetProp(propName, phases[0].Value, null, "mixture", basis.ToString());
            }
            else if (phases.Length == 2)  // two phases, example: kvalues
            {
                CasterLogger.Debug($"Get property {propName} for {phases[0]} and {phases[1]}");
                string phaseName = null;
                if (phases.Contains(Phases.Vapor) && phases.Contains(Phases.Liquid))
                {
                    phaseName = Phases.Vapor.Value + Phases.Liquid.Value;   // vapor in front
                }
                else
                {
                    phaseName = phases[0].Value + phases[1].Value;
                }
                value = _capeThermoMaterialObject.GetProp(propName, phaseName, null, "mixture", basis.ToString());
            }
            else
            {
                CasterLogger.Error($"Only support overall, 1 phase or 2 phases");
                throw new ArgumentOutOfRangeException($"Only support overall, 1 phase or 2 phases");
            }
            CasterLogger.Debug($"Get property {propName}: {value}");
            return(value as double[]);
        }
Example #3
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");
        }