예제 #1
0
        /// <summary>
        /// Measure NH4 content inside a digester
        /// 1st measurement is Snh4 in g/l
        /// 2nd : Snh4 + NH4 in Xc in g/l
        ///
        /// type 5
        /// </summary>
        /// <param name="myPlant"></param>
        /// <param name="x">ADM state vector</param>
        /// <param name="param">not used - but OK</param>
        /// <param name="par">not used</param>
        /// <returns></returns>
        override protected physValue[] doMeasurement(biogas.plant myPlant, double[] x,
                                                     string param, params double[] par)
        {
            physValue[] values = new physValue[dimension];

            // hier wird umrechnungsfaktor 18 genutzt, deshalb nur ammonium und nicht
            // ammonium nitrogen
            values[0] = ADMstate.calcFromADMstate(x, "Snh4", "g/l");

            //
            // -2 wegen _2 bzw. _3
            string digester_id = id.Substring(("Snh4_").Length, id.Length - 2 - ("Snh4_").Length);

            // kmol N/m^3
            double NH4 = ADMstate.calcNH4(x, digester_id, myPlant);

            //
            // erstmal Snh4 nennen, damit convertUnit funktioniert
            // TODO - könnte es auch N nennen, dann wird allerdings nur mit 14 als
            // umrechnungsfaktor gerechnet und nicht wie jetzt mit 18. Vorsicht
            // bei vergleich mit Ntot, TKN und Norg, dort wird nur mit 14 gerechnet.
            // da ich die Größe ammonium nitrogen nenne, wird umrechnungsfaktor 14 genutzt
            values[1]        = new physValue("N", NH4, "mol/l", "total ammonium nitrogen");
            values[1]        = values[1].convertUnit("g/l");
            values[1].Symbol = "NH4";

            return(values);
        }
예제 #2
0
        /// <summary>
        /// calc methane yield [m^3 CH4 / kgVS]
        ///
        /// http://www.bioconverter.com/technology/primer.htm#Methane%20Yield%20%28m3%20CH4%20/%20kg%20VS%20added%29
        ///
        /// if methane yield is high, everything is ok, if it is too low
        /// maybe decrease substrate feed, digester could be overburdened
        ///
        /// </summary>
        /// <param name="x">ADM state vector</param>
        /// <param name="pQ">Q   : m^3/d  : total feed into the digester</param>
        /// <param name="pVS">VS  : % TS   : volatile solids content of feed</param>
        /// <param name="pTS">TS  : % FM   : total solids content of feed</param>
        /// <param name="prho">rho : kg/m^3 : density of feed</param>
        /// <returns></returns>
        public physValue calcCH4Yield(double[] x, physValue pQ, physValue pVS,
                                      physValue pTS, physValue prho)
        {
            physValue Qgas_h2, Qgas_ch4;

            ADMstate.calcBiogasOfADMstate(x, Vliq, T, out Qgas_h2, out Qgas_ch4);

            physValue Q   = pQ.convertUnit("m^3/d");
            physValue VS  = pVS.convertUnit("% TS");
            physValue TS  = pTS.convertUnit("% FM");
            physValue rho = prho.convertUnit("kg/m^3");

            VS = substrate.convertFrom_TS_To_FM(VS, TS);

            // VS [% FM] * [100 % / % FM] * m^3/d * kg/m^3 = VS kg/d
            physValue VS_kg = VS.convertUnit("100 %") * Q * rho;

            if (VS_kg.Value == 0)
            {
                return(new physValue(0, "m^3/kg"));
            }

            // m^3/d / kgVS/d= m^3/kgVS
            // Einheit ist: m^3/kg
            physValue CH4Yield = Qgas_ch4 / VS_kg;

            return(CH4Yield);
        }
예제 #3
0
        // -------------------------------------------------------------------------------------
        //                            !!! PROTECTED METHODS !!!
        // -------------------------------------------------------------------------------------

        /// <summary>
        /// measures Q of ADM stream in m^3/d
        ///
        /// type 0
        /// </summary>
        /// <param name="x">ADM state vector (dimension: dim_stream)</param>
        /// <param name="par">not used</param>
        /// <returns>flow in m^3/d</returns>
        override protected physValue[] doMeasurement(double[] x, params double[] par)
        {
            physValue[] values = new physValue[1];

            values[0] = ADMstate.calcQOfADMstate(x);

            return(values);
        }
예제 #4
0
        // -------------------------------------------------------------------------------------
        //                            !!! PROTECTED METHODS !!!
        // -------------------------------------------------------------------------------------

        /// <summary>
        /// Measures volatile fatty acid concentration in digester
        ///
        /// type 0
        /// </summary>
        /// <param name="x">ADM state vector</param>
        /// <param name="par">not used</param>
        /// <returns>volatile fatty acid concentration in gHAceq/l</returns>
        override protected physValue[] doMeasurement(double[] x, params double[] par)
        {
            physValue[] values = new physValue[1];

            values[0] = ADMstate.calcVFAOfADMstate(x, "gHAceq/l");

            values[0].Symbol = "Svfa";

            return(values);
        }
예제 #5
0
        /// <summary>
        /// Calculates given symbol out of state vector x. The symbol in the state vector
        /// must be measured in the unit of the ADM state vector (as defined in variable
        /// unitsADMstate) and is returned in ToUnit
        ///
        /// </summary>
        /// <param name="x"></param>
        /// <param name="symbol"></param>
        /// <param name="ToUnit"></param>
        /// <returns></returns>
        public static physValueBounded calcFromADMstate(double[] x, string symbol,
                                                        string ToUnit)
        {
            // nicht so gut den defaultUnit von physValue zu holen, da ein anderes AD
            // Model andere Einheiten haben könnte
            //string FromUnit= physValue.getDefaultUnit(symbol);
            // so ist es OK!
            string FromUnit = ADMstate.getUnitOfADMstatevariable(symbol);

            return(calcFromADMstate(x, symbol, FromUnit, ToUnit));
        }
예제 #6
0
        // -------------------------------------------------------------------------------------
        //                            !!! PROTECTED METHODS !!!
        // -------------------------------------------------------------------------------------

        /// <summary>
        /// Calculates hydraulic retention time of the digester measured in days
        ///
        /// type 0 aktuell type 1
        /// </summary>
        /// <param name="x">ADM state vector</param>
        /// <param name="par">volume of the digester in m^3</param>
        /// <returns>measured HRT in days</returns>
        override protected physValue[] doMeasurement(double[] x, params double[] par)
        {
            physValue[] values = new physValue[dimension];

            if (par.Length != 1)
            {
                throw new exception(String.Format(
                                        "Length of params is != 1: {0}!", par.Length));
            }

            double Vliq = par[0];

            values[0] = ADMstate.calcHRTOfADMstate(x, Vliq);

            return(values);
        }
예제 #7
0
        // -------------------------------------------------------------------------------------
        //                            !!! PROTECTED METHODS !!!
        // -------------------------------------------------------------------------------------

        /// <summary>
        /// Calculates the heat energy produced by bacteria inside the digester measured in kWh/d
        ///
        /// nicht type 0 und auch nicht type 1, da x ist vektor aus ADM1 beschreibend die reaktions
        /// raten p oder rho genannt
        /// </summary>
        /// <param name="p">ADM reaction rates vector</param>
        /// <param name="par">volume of the digester in m^3</param>
        /// <returns>measured energy in kWh/d</returns>
        override protected physValue[] doMeasurement(double[] p, params double[] par)
        {
            physValue[] values = new physValue[dimension];

            if (par.Length != 1)
            {
                throw new exception(String.Format(
                                        "Length of params is != 1: {0}!", par.Length));
            }

            double Vliq = par[0];

            values[0] = new physValue("Pprodmic",
                                      ADMstate.calcProdEnergyOfMicroOrganisms(p, Vliq), "kWh/d",
                                      "thermal energy prod. of microorganisms");

            return(values);
        }
예제 #8
0
        /// <summary>
        /// calc methane production rate [m^3/m^3/day]
        ///
        /// http://www.bioconverter.com/technology/primer.htm#Methane%20Production%20Rate
        ///
        /// http://www.bioconverter.com/technology/primer.htm#Methane%20Production%20Rate%20%28m3/m3-day%29
        ///
        /// </summary>
        /// <param name="x">ADM state vector</param>
        /// <returns></returns>
        public physValue calcCH4ProductionRate(double[] x)
        {
            physValue Qgas_h2, Qgas_ch4;

            ADMstate.calcBiogasOfADMstate(x, Vliq, T, out Qgas_h2, out Qgas_ch4);

            Qgas_ch4 = Qgas_ch4.convertUnit("m^3/d");
            _Vliq    = Vliq.convertUnit("m^3");

            if (Vliq.Value == 0)
            {
                return(new physValue(0, "1/d"));
            }

            // m^3/d/m^3= 1/d
            physValue CH4ProductionRate = Qgas_ch4 / Vliq;

            return(CH4ProductionRate);
        }
예제 #9
0
        // -------------------------------------------------------------------------------------
        //                            !!! PROTECTED METHODS !!!
        // -------------------------------------------------------------------------------------

        /// <summary>
        /// Measure ADM stream vector in default units of the model
        ///
        /// is a type 0, because u is the stream vector
        /// </summary>
        /// <param name="u">33 or 34 dim stream vector</param>
        /// <param name="par">not used</param>
        /// <returns>measured ADM stream vector</returns>
        /// <exception cref="exception">u.Length &lt; ADMstate.dim_stream - 1</exception>
        override protected physValue[] doMeasurement(double[] u, params double[] par)
        {
            physValue[] values = new physValue[dimension];

            if (u.Length < ADMstate.dim_stream - 1)
            {
                throw new exception(String.Format(
                                        "u has not the correct dimension! is: {0}, must be at least: {1}!",
                                        u.Length, ADMstate.dim_stream - 1));
            }

            for (int idim = 0; idim < dimension; idim++)
            {
                values[idim] = new physValue(ADMstate.symADMstate[idim], u[idim],
                                             ADMstate.getUnitOfADMstatevariable(idim + 1));
            }

            return(values);
        }
예제 #10
0
        // -------------------------------------------------------------------------------------
        //                            !!! PROTECTED METHODS !!!
        // -------------------------------------------------------------------------------------
        /// <summary>
        /// Measure ADM state vector in default units of the model
        /// 
        /// not type 0, because x is not the stream vector, but the 37 dim state vector
        /// </summary>
        /// <param name="x">37 dim state vector</param>
        /// <param name="par">not used</param>
        /// <returns>measured ADM state vector</returns>
        /// <exception cref="exception">x.Length != ADMstate.dim_state</exception>
        protected override physValue[] doMeasurement(double[] x, params double[] par)
        {
            physValue[] values= new physValue[dimension];

              if (x.Length != ADMstate.dim_state)
              {
            throw new exception(String.Format(
                "x has not the correct dimension! is: {0}, must be: {1}!",
                x.Length, ADMstate.dim_state));
              }

              for (int idim= 0; idim < dimension; idim++)
              {
            values[idim]= new physValue(ADMstate.symADMstate[idim], x[idim],
                                    ADMstate.getUnitOfADMstatevariable(idim + 1));
              }

              return values;
        }
예제 #11
0
        /// <summary>
        /// Measure TKN content inside a digester
        ///
        /// type 5
        /// </summary>
        /// <param name="myPlant"></param>
        /// <param name="x">ADM state vector</param>
        /// <param name="param">not used - but OK</param>
        /// <param name="par">not used</param>
        /// <returns></returns>
        override protected physValue[] doMeasurement(biogas.plant myPlant, double[] x,
                                                     string param, params double[] par)
        {
            physValue[] values = new physValue[1];

            //
            // -2 wegen _2 bzw. _3
            string digester_id = id.Substring(("TKN_").Length, id.Length - 2 - ("TKN_").Length);

            // kmol N/m^3
            double TKN = ADMstate.calcTKN(x, digester_id, myPlant);

            //
            // erstmal N nennen, damit convertUnit funktioniert
            values[0]        = new physValue("N", TKN, "mol/l", "total Kjehldahl nitrogen");
            values[0]        = values[0].convertUnit("g/l");
            values[0].Symbol = "TKN";

            //

            return(values);
        }
예제 #12
0
        /// <summary>
        /// Measure Norg content inside a digester
        ///
        /// type 5
        /// </summary>
        /// <param name="myPlant"></param>
        /// <param name="x">ADM state vector</param>
        /// <param name="param">not used - but OK</param>
        /// <param name="par">not used</param>
        /// <returns></returns>
        override protected physValue[] doMeasurement(biogas.plant myPlant, double[] x,
                                                     string param, params double[] par)
        {
            physValue[] values = new physValue[1];

            //
            // -1 sowieso, -2 wegen _2 bzw. _3
            string digester_id = id.Substring(("Norg_").Length, id.Length - 2 - ("Norg_").Length);

            // kmol N/m^3
            double Norg = ADMstate.calcNorg(x, digester_id, myPlant);

            //
            // erstmal N nennen, damit convertUnit funktioniert
            values[0]        = new physValue("N", Norg, "mol/l", "organic nitrogen");
            values[0]        = values[0].convertUnit("g/l");
            values[0].Symbol = "Norg";

            //

            return(values);
        }
예제 #13
0
        /// <summary>
        /// Measure NH3 content inside a digester
        /// 1st measurement is Snh3 in g/l
        /// 2nd : Snh3 + NH3 in Xc in g/l
        ///
        /// type 5
        /// </summary>
        /// <param name="myPlant"></param>
        /// <param name="x">ADM state vector</param>
        /// <param name="param">not used - but OK</param>
        /// <param name="par">not used</param>
        /// <returns></returns>
        override protected physValue[] doMeasurement(biogas.plant myPlant, double[] x,
                                                     string param, params double[] par)
        {
            physValue[] values = new physValue[dimension];

            // ammonia
            values[0] = ADMstate.calcFromADMstate(x, "Snh3", "g/l");

            //
            // -2 wegen _2 bzw. _3
            string digester_id = id.Substring(("Snh3_").Length, id.Length - 2 - ("Snh3_").Length);

            // kmol N/m^3
            double NH3 = ADMstate.calcNH3(x, digester_id, myPlant);

            //
            // erstmal Snh3 nennen, damit convertUnit funktioniert
            // ammonia nitrogen, umrechnungsfaktor 14
            values[1]        = new physValue("N", NH3, "mol/l", "total ammonia nitrogen");
            values[1]        = values[1].convertUnit("g/l");
            values[1].Symbol = "NH3";

            return(values);
        }