Exemple #1
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>
        /// Adds the digester myDigester to the list.
        /// </summary>
        /// <param name="myDigester"></param>
        public void addDigester(digester myDigester)
        {
            myDigesters.addDigester(myDigester);

            substrate_transport mySubstrateTransport = new substrate_transport("substratemix", myDigester.id);

            myTransportation.addSubstrateTransport(mySubstrateTransport);
        }
        /// <summary>
        /// Deletes the by 1-based index specified digester from the list.
        /// </summary>
        /// <param name="index">digester index</param>
        /// <exception cref="exception">Invalid digester index</exception>
        public void deleteDigester(int index)
        {
            digester myDigester = getDigester(index);

            myTransportation.deleteSubstrateTransport("substratemix_" + myDigester.id);

            myDigesters.deleteDigester(index);
        }
        /// <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);
        }
        /// <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);
        }