Пример #1
0
        /// <summary>
        /// Print state values to a string, to be displayed on a console
        /// </summary>
        /// <param name="x">state vector</param>
        /// <param name="digester_id"></param>
        /// <param name="myPlant"></param>
        /// <returns></returns>
        public static string print(double[] x, string digester_id, plant myPlant)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("  pH= " + calcPHOfADMstate(x).ToString("0.00") + "\t\t\t");
            sb.Append("NH4= " + calcNH4p(x, digester_id, myPlant, "g/l").printValue() + "\n");

            sb.Append("  VFA/TA= " + calcFOSTACOfADMstate(x).printValue() + "\t\t\t");
            sb.Append("TA= " + calcTACOfADMstate(x, "gCaCO3eq/l").printValue() + "\t\t\t");
            sb.Append("VFA= " + calcVFAOfADMstate(x, "gHAceq/l").printValue() + "\n");

            sb.Append("  Sac= " + calcFromADMstate(x, "Sac", "g/l").printValue() + "\t\t\t");
            sb.Append("Sbu= " + calcFromADMstate(x, "Sbu", "g/l").printValue() + "\t\t\t");
            sb.Append("Spro= " + calcFromADMstate(x, "Spro", "g/l").printValue() + "\t\t\t");
            sb.Append("Sva= " + calcFromADMstate(x, "Sva", "g/l").printValue() + "\n");

            physValue T = myPlant.getDigesterByID(digester_id).get_params_of("T");
            physValue V = myPlant.getDigesterByID(digester_id).get_params_of("Vliq");

            physValue qgas_h2, qgas_ch4, qgas_co2, qgas;

            calcBiogasOfADMstate(x, V, T, out qgas_h2, out qgas_ch4, out qgas_co2, out qgas);

            sb.Append("  Qch4= " + qgas_ch4.printValue("0.000") + "\t\t");
            sb.Append("Qco2= " + qgas_co2.printValue("0.000") + "\t\t");
            sb.Append("Qh2= " + qgas_h2.printValue("0.0000") + "\t\t");
            sb.Append("Qgas= " + qgas.printValue("0.00") + "\n");

            return(sb.ToString());
        }
Пример #2
0
        /// <summary>
        /// Print state values to a string, to be displayed on a console
        /// </summary>
        /// <param name="x"></param>
        /// <param name="digester_id"></param>
        /// <param name="myPlant"></param>
        /// <param name="pH"></param>
        /// <param name="NH4"></param>
        /// <param name="VFATA"></param>
        /// <param name="VFA"></param>
        /// <param name="TA"></param>
        /// <param name="Sac"></param>
        /// <param name="Sbu"></param>
        /// <param name="Spro"></param>
        /// <param name="Sva"></param>
        /// <param name="gas_h2"></param>
        /// <param name="gas_ch4"></param>
        /// <param name="gas_co2"></param>
        /// <param name="gas"></param>
        /// <returns></returns>
        public static string printAndReturn(double[] x, string digester_id, plant myPlant,
                                            out double pH, out double NH4, out double VFATA, out double VFA, out double TA,
                                            out double Sac, out double Sbu, out double Spro, out double Sva, out double gas_h2,
                                            out double gas_ch4, out double gas_co2, out double gas)
        {
            pH  = calcPHOfADMstate(x);
            NH4 = calcNH4p(x, digester_id, myPlant, "g/l").Value;

            VFATA = calcFOSTACOfADMstate(x).Value;
            TA    = calcTACOfADMstate(x, "gCaCO3eq/l").Value;
            VFA   = calcVFAOfADMstate(x, "gHAceq/l").Value;

            Sac  = calcFromADMstate(x, "Sac", "g/l").Value;
            Sbu  = calcFromADMstate(x, "Sbu", "g/l").Value;
            Spro = calcFromADMstate(x, "Spro", "g/l").Value;
            Sva  = calcFromADMstate(x, "Sva", "g/l").Value;

            physValue T = myPlant.getDigesterByID(digester_id).get_params_of("T");
            physValue V = myPlant.getDigesterByID(digester_id).get_params_of("Vliq");

            physValue qgas_h2, qgas_ch4, qgas_co2, qgas;

            calcBiogasOfADMstate(x, V, T, out qgas_h2, out qgas_ch4, out qgas_co2, out qgas);

            gas_h2  = qgas_h2.Value;
            gas_ch4 = qgas_ch4.Value;
            gas_co2 = qgas_co2.Value;
            gas     = qgas.Value;

            return(print(x, digester_id, myPlant));
        }
Пример #3
0
        /// <summary>
        /// type 7
        ///
        /// called in ADMstate_stoichiometry.cs -> measure_type7
        /// </summary>
        /// <param name="x">ADM state vector - not used</param>
        /// <param name="myPlant"></param>
        /// <param name="mySubstrates">not yet used</param>
        /// <param name="mySensors">used to get TS inside digester</param>
        /// <param name="Q">not used</param>
        /// <param name="par">not used</param>
        /// <returns>measured values</returns>
        override protected physValue[] doMeasurement(double[] x, biogas.plant myPlant,
                                                     biogas.substrates mySubstrates,
                                                     biogas.sensors mySensors,
                                                     double[] Q, params double[] par)
        {
            // 1st Pel in kWh/d for mixing digester
            // 2nd Pdissipated in kWh/d for mixing digester, dissipated in digester
            physValue[] values = new physValue[dimension];

            //

            digester myDigester = myPlant.getDigesterByID(id_suffix);

            // calc stirrer(s) power for digester in kWh/d
            values[0] = myDigester.calcStirrerPower(mySensors);

            // calc stirrer(s) power dissipated to digester in kWh/d
            values[1] = myDigester.calcStirrerDissipation(mySensors);

            values[0].Label = "electrical energy of stirrer";
            values[1].Label = "thermal energy dissipated by stirrer";

            //

            return(values);
        }
        /// <summary>
        /// type 7
        ///
        /// called in ADMstate_stoichiometry.cs
        ///
        /// unterschied zu typ 7 ist, dass Q hier nur aus Substraten besteht und nicht
        /// aus zusätzlichem sludge, da sludge nicht aufgewärmt werden muss,
        /// nein ist jetzt ein Typ 7 sensor, sludge wird ignoriert
        /// </summary>
        /// <param name="x">not used</param>
        /// <param name="myPlant"></param>
        /// <param name="mySubstrates"></param>
        /// <param name="mySensors"></param>
        /// <param name="Q">zufuhr aller substrate in fermenter (nicht in Anlage),
        /// da heatConsumption_sensor am fermenter angebracht ist</param>
        /// <param name="par">not used</param>
        /// <returns>measured values</returns>
        override protected physValue[] doMeasurement(double[] x, biogas.plant myPlant,
                                                     biogas.substrates mySubstrates,
                                                     biogas.sensors mySensors,
                                                     double[] Q, params double[] par)
        {
            // wegen 4 siehe oben
            // 1. Ptherm kWh/d for heating substrates
            // 2. Ptherm kWh/d loss due to radiation
            // 3. Ptherm kWh/d produced by microbiology
            // 4. Ptherm kWh/d produced by stirrer dissipation
            physValue[] values = new physValue[dimension];

            // TODO - rufe hier calcThermalEnergyBalance auf von digester_energy.cs
            // benötigt als weiteren Parameter allerdings mySensors

            digester myDigester = myPlant.getDigesterByID(id_suffix);

            // Q ist nur das was in fermenter rein geht
            // bspw. gäbe es bei einem nicht gefütterten aber beheiztem fermenter
            // keine substrate welche aufgeheizt werden müssten
            //myDigester.heatInputSubstrates(Q, mySubstrates, out values[0]);

            myDigester.calcThermalEnergyBalance(Q, mySubstrates, myPlant.Tout, mySensors,
                                                out values[0], out values[1], out values[2], out values[3]);

            //

            values[0].Label = "thermal energy to heat substrates";
            values[1].Label = "thermal energy loss due to radiation";
            values[2].Label = "thermal energy produced by microorganisms";
            values[3].Label = "thermal energy dissipated by stirrer";

            //physValue P_radiation_loss_kW;
            // because in heating first power in kW is calculated, it does not
            // make the code faster to not have power in kW as parameter
            //myPlant.compensateHeatLossDueToRadiation(id_suffix,
            //        out P_radiation_loss_kW, out values[1]);

            //

            return(values);
        }
Пример #5
0
        /// <summary>
        /// Measure OLR of a digester
        ///
        /// type 7
        ///
        /// TODO: größtenteils identisch mit TS_sensor, man könnte was zusammen legen
        /// </summary>
        /// <param name="x">ADM state vector</param>
        /// <param name="myPlant"></param>
        /// <param name="mySubstrates">list of substrates</param>
        /// <param name="mySensors"></param>
        /// <param name="Q">
        /// substrate feed and recirculation sludge going into fermenter in m³/d
        /// first values are Q for substrates, then pumped sludge going into digester
        /// dimension: always number of substrates + number of digesters
        /// </param>
        /// <param name="par"></param>
        /// <returns></returns>
        override protected physValue[] doMeasurement(double[] x, biogas.plant myPlant,
                                                     biogas.substrates mySubstrates, biogas.sensors mySensors,
                                                     double[] Q, params double[] par)
        {
            physValue[] values = new physValue[1];

            // TODO: so abändern, dass die aufgerufene methode calcOLR immer
            // feed und sludge übergeben werden. nicht oder

            // number of substrates
            int n_substrate = mySubstrates.getNumSubstrates();

            double Qsum = math.sum(Q);

            if (Q.Length < n_substrate)
            {
                throw new exception(String.Format(
                                        "Q.Length < n_substrate: {0} < {1}!", Q.Length, n_substrate));
            }

            double[] Qsubstrates = new double[n_substrate];

            // volumeflow for substrates
            for (int isubstrate = 0; isubstrate < n_substrate; isubstrate++)
            {
                Qsubstrates[isubstrate] = Q[isubstrate];
            }

            //

            biogas.substrates substrates_or_sludge;

            //
            List <double> Q_s_or_s = new List <double>();

            // if no substrate is going into the fermenter we have to take the
            // TS from the digesters sludge going into this digester to calculate a
            // sludge. If there is substrate going into the digester we ignore
            // recirculation sludge, because the COD content inside the digester is
            // already influenced by the recirculated COD, so a high recirculation leads
            // to a reduction of the COD content inside the digester and then also to a
            // TS content reduction.
            if (math.sum(Qsubstrates) == 0)
            {
                substrates_or_sludge = new biogas.substrates();

                int ifermenter = 0;

                //

                for (int iflux = n_substrate; iflux < Q.Length; iflux++)
                {
                    string digester_id = myPlant.getDigesterID(ifermenter + 1);

                    double TS_digester, VS_digester = 0;

                    try
                    {
                        mySensors.getCurrentMeasurementD("TS_" + digester_id + "_3", out TS_digester);
                        mySensors.getCurrentMeasurementD("VS_" + digester_id + "_3", out VS_digester);

                        // TODO - warum 4, wenn Fermenter abgestürzt ist, dann ist TS < 2
                        // was zu doofen Fehlermeldungen führt mit calcNfE und boundNDF, wenn man
                        // VS unten in biogas.sludge setzt. deshalb hier abfrage
                        if (TS_digester < 4 /*double.Epsilon*/)
                        {
                            TS_digester = 11;
                        }
                        // TODO - herausfinden warum 15
                        if (VS_digester < 20 /*double.Epsilon*/)
                        {
                            VS_digester = 85; // 85 % TS
                        }
                    }
                    catch
                    {
                        TS_digester = 11;
                        VS_digester = 85;
                    }

                    try
                    {
                        substrates_or_sludge.addSubstrate(
                            new biogas.sludge(mySubstrates, math.ones(n_substrate),
                                              TS_digester, VS_digester));
                    }
                    catch (exception e)
                    {
                        LogError.Log_Err(String.Format("OLR_sensor.doMeasurement, VS: {0}, TS: {1}",
                                                       VS_digester, TS_digester), e);
                        throw (e);
                    }

                    ifermenter = ifermenter + 1;
                }

                //

                for (int isubstrate = n_substrate; isubstrate < Q.Length; isubstrate++)
                {
                    Q_s_or_s.Add(Q[isubstrate]);
                }
            }
            else
            {
                substrates_or_sludge = mySubstrates;

                for (int isubstrate = 0; isubstrate < Qsubstrates.Length; isubstrate++)
                {
                    Q_s_or_s.Add(Qsubstrates[isubstrate]);
                }
            }

            //

            digester myDigester = myPlant.getDigesterByID(id_suffix);

            try
            {
                values[0] = myDigester.calcOLR(x, substrates_or_sludge, Q_s_or_s.ToArray(), Qsum);
            }
            catch (exception e)
            {
                LogError.Log_Err("OLR_sensor.doMeasurement2", e);
                throw (e);
            }

            //

            return(values);
        }