Exemple #1
0
        /// <summary>
        /// Returns the ADM params vector, but the substrate dependent parameters
        /// are returned as normal means, not weighted means
        /// </summary>
        /// <param name="mySubstrates"></param>
        /// <returns></returns>
        public double[] getParams(substrates mySubstrates)
        {
            double[] Q = new double[mySubstrates.getNumSubstrates()];

            for (int isubstrate = 0; isubstrate < mySubstrates.getNumSubstrates(); isubstrate++)
            {
                Q[isubstrate] = 1;
            }

            return(getParams(0, Q, math.sum(Q), mySubstrates)); // , true
        }
Exemple #2
0
        /// <summary>
        /// Calc u prime for substrate feed of all substrates saved in sensors at the
        /// current time
        /// </summary>
        /// <param name="mySensors"></param>
        /// <param name="mySubstrates"></param>
        /// <returns>|| u'(t) ||_2^2, where u is the vector of substrate feeds</returns>
        private double calcudot(biogas.sensors mySensors, biogas.substrates mySubstrates)
        {
            double t2 = mySensors.getCurrentTime();

            if (t2 < 0) // no recorded value yet in no sensor
            {
                return(0);
            }

            double t1 = mySensors.getPreviousTime();

            double[] Q1, Q2;

            // TODO
            // wenn init substrate feed nicht gegeben ist, dann ist am anfang der simulation
            // Q2 = Q1
            // aktuell berechne ich in MATLAb noch init_substrate feed und addiere das am ende
            // zu udot hinzu, sollte erstmal ok sein
            mySensors.getMeasurementsAt("Q", "Q", t1, mySubstrates, out Q1);

            mySensors.getMeasurementsAt("Q", "Q", t2, mySubstrates, out Q2);

            //

            double udot = 0;

            for (int isubstrate = 0; isubstrate < mySubstrates.getNumSubstrates(); isubstrate++)
            {
                double u1 = Q1[isubstrate];
                double u2 = Q2[isubstrate];

                double udot1 = calcudot(t1, t2, u1, u2);

                udot += udot1 * udot1;
            }

            return(udot);
        }
Exemple #3
0
        /// <summary>
        /// Measure TS content inside a digester
        ///
        /// type 7
        /// </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 the digester
        /// first values are Q for substrates, then pumped sludge going into digester
        /// dimension: always number of substrates + number of digesters
        /// </param>
        /// <param name="par">not used</param>
        /// <returns></returns>
        override protected physValue[] doMeasurement(double[] x, biogas.plant myPlant,
                                                     biogas.substrates mySubstrates, biogas.sensors mySensors,
                                                     double[] Q, params double[] par)
        {
            // TODO
            // so erweitern, dass auch TS in Fermenter Input gemessen werden kann
            // evtl. substrate_sensor nutzen, kann aber auch direkt über mySubstrates gemessen werden

            physValue[] values = new physValue[1];

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

            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 = 0;

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

                        if (TS_digester < double.Epsilon) // vermutlich wurde noch nicht gemessen?
                        {
                            TS_digester = 11;
                        }
                    }
                    catch // TODO: wann passiert das??, sollte eigentlich nicht passieren
                    {
                        TS_digester = 11;
                    }

                    substrates_or_sludge.addSubstrate(
                        new biogas.sludge(mySubstrates, math.ones(n_substrate), TS_digester));

                    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]);
                }
            }



            if (id.EndsWith("3")) // out sensor
            {
                // calc TS inside digester due to the substrates or the sludge if digester is not fed
                values[0] = biogas.digester.calcTS(x, substrates_or_sludge, Q_s_or_s.ToArray());
            }
            else if (id.EndsWith("2")) // in sensor
            {
                // TODO
                // ändern, da momentan entweder substrate oder sludge genommen wird und nicht beides
                // selbe Problem wie bei OLR_sensor denke ich
                substrates_or_sludge.get_weighted_mean_of(Q_s_or_s.ToArray(), "TS", out values[0]);

                values[0].Symbol = "TS";
            }
            else
            {
                throw new exception(String.Format("id of TS sensor not valid: {0}", id));
            }

            //

            values[0].Label = "total solids";

            return(values);
        }
Exemple #4
0
        static void Main(string[] args)
        {
            physValue COD = biogas.chemistry.calcTOC("Xch");

            //physValueBounded mol_mass= new physValueBounded("Sac");

            //double a= 1;

            //physValueBounded c= a* mol_mass;

            fitness_params myparams = new fitness_params("fitness_params_geiger.xml");

            myparams.set_params_of("manurebonus", true);

            //double[] state= new double[37];

            //physValueBounded fostac= biogas.ADMstate.calcFOSTACOfADMstate(state);

            //physValue C;
            //physValue H;

            //physValue Hh2= biogas.chemistry.Hh2;

            //biogas.chemistry.get_CHONS_of("Sac_", out C, out H);

            //physValue ThODch= biogas.chemistry.calcTheoreticalOxygenDemand("Xch");

            //biogas.substrate.createMe();

            //double[] a= biogas.ADMstate.getDefaultADMstate(33);

            //double[] b= biogas.ADMstate.getDefaultADMstate(33);

            //a[33]= 10;
            //b[33]= 15;

            //double[,] c= new double[a.Length, 2];

            //for (int ii= 0; ii < a.Length; ii++)
            //{
            //  c[ii, 0]= a[ii];
            //  c[ii, 1]= b[ii];
            //}

            //double[] d= biogas.ADMstate.mixADMstreams(c);

            //biogas.substrate mySubstrate= new biogas.substrate("manure_cattle_1.xml");

            //mySubstrate.print();

            //mySubstrate= new biogas.substrate("wheat_silage_3.xml");

            //mySubstrate.print();

            substrates mySubstrates = new biogas.substrates("substrate_geiger.xml");

            mySubstrates.print();
            //mySubstrates.saveAsXML("test.xml");

            plant myPlant = new biogas.plant("plant_geiger.xml");
            //myPlant.saveAsXML("test_plant.xml");

            //double[] Q= {1,2,3,4,5,6,7};

            //myPlant.myDigesters.get("main").AD_Model.getParams(Q, mySubstrates);

            digester myDigester = myPlant.myDigesters.get(1);

            myDigester.calcHeatLossDueToRadiation(new physValue(40, "°C"));

            double[] Q           = { 15, 20, 0, 0, 0, 0, 0, 0, 0, 0 };
            double   QdigesterIn = 35;

            double[] ADMparams = myDigester.AD_Model.getParams(0, Q, QdigesterIn, mySubstrates);

            //double[] x= biogas.ADMstate.getDefaultADMstate();

//      double[] x= { 0.00890042014469482,
//0.00393026902393572,
//0.0898975418574202,
//0.0105303688871217,
//0.0188083338344299,
//0.0891872294599488,
//4.06518710070508,
//1.48197701713060e-06,
//0.0463395911897687,
//0.0137825768581825,
//0.231507824368968,
//3.42633334388719,
//8.90655977614532,
//0.129429796425159,
//0.0457772931408461,
//0.0271093313710146,
//3.81638964565446,
//0.988123176978798,
//0.410214653254316,
//0.633820130695941,
//0.537171143510719,
//1.81695029971744,
//0.992459517922010,
//8.07171990003056,
//19.9716874568380,
//0.000997039324889569,
//0.0155655622013352,
//0.0104958374141159,
//0.0187566838733815,
//0.0889172491178123,
//4.05462904506225,
//0.152623707143880,
//0.00590111878589172,
//8.13313521280990e-05,
//0.465153466604388,
//0.506049932143382,
//0.971284730099898
////8.05130545875131e-05,
////0.460473427139200,
////0.500958421870263,
////0.961512362064050
// };

            double[] x = { 0.00719913836418267,
                           0.00322799288019040,
                           0.0546025712168657,
                           0.0115793536955362,
                           0.0229074890746752,
                           0.0600482037552511,
                           0.463364086785563,
                           7.72721521995682e-08,
                           0.0469910866922296,
                           0.0479055807768373,
                           0.154317294840363,
                           -1.35975859128971e-47,
                           21.5301936374036,
                           0.750446550594154,
                           0.161739337648583,
                           0.0603411370260300,
                           4.96860324952978,
                           0.832215069627251,
                           0.222662822346057,
                           0.629071151058018,
                           0.547835241984119,
                           2.00168204821595,
                           1.05831074978528,
                           29.5159593610614,
                           1.79228974953266,
                           1.27233772322647e-52,
                           1.77592375955463e-55,
                           0.0115411203828431,
                           0.0228383440861995,
                           0.0598411508360539,
                           0.462166407598810,
                           0.2406363011183078,
                           0.00374878408176311,
                           4.31650348109949e-06,
                           0.476514182736779,
                           0.487815404290303,
                           0.964333903530564 };



            //biogas.sensors mySensors=
            //  new biogas.sensors(new biogas.VFA_TAC_sensor("1"));

            //physValue VFA_TAC= mySensors.getCurrentMeasurement("VFA_TAC_1", 2);

            //VFA_TAC= mySensors.measure(0, "VFA_TAC_1", 1, x);

            //VFA_TAC= mySensors.measure(2, "VFA_TAC_1", 1, x);

            biogas.sensors mySensors =
                new biogas.sensors(new biogas.TS_sensor("postdigester_3"));

            biogas.sensor_array mySensorArray = new biogas.sensor_array("Q");

            for (int isubstrate = 0; isubstrate < mySubstrates.getNumSubstrates(); isubstrate++)
            {
                mySensorArray.addSensor(new biogas.Q_sensor(mySubstrates.getID(isubstrate + 1)));
            }

            mySensorArray.addSensor(new biogas.Q_sensor("postdigester_digester"));

            mySensors.addSensorArray(mySensorArray);

            mySensors.addSensor(new biogas.substrate_sensor("cost"));

            mySensors.addSensor(new biogas.pumpEnergy_sensor("postdigester_digester"));

            mySensors.addSensor(new biogas.total_biogas_sensor("", myPlant));

            //physValue VFA_TACs= mySensors.measure(0, "VS_1", 1, new double[]{1,2}, mySubstrates);

            double[,] substrate_network = { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } };

            double[,] plant_network = { { 0, 1, 0 }, { 1, 0, 1 } };

            double TS;

            //mySensors.measure(0, "TS_digester_3", 1, x,
            //          myPlant, mySubstrates, mySensors,
            //          substrate_network, plant_network, "digester", out TS);


            mySensors.measure(0, "substrate_cost", 0, mySubstrates, out TS);
            mySensors.measure(1, "substrate_cost", 0, mySubstrates, out TS);
            mySensors.measure(2, "substrate_cost", 0, mySubstrates, out TS);

            double energy;

            double[] pump = { 5 };

            mySensors.measure(0, "pumpEnergy_postdigester_digester", 0, myPlant, 10, pump, out energy);

            double[] data;

            mySensors.getMeasurementStream("substrate_cost", out data);

            double[] u = new double[6];
            u[0] = 10;
            u[1] = 100;
            u[2] = 100;
            u[3] = 20;
            u[4] = 200;
            u[5] = 200;

            mySensors.measureVec(0, "total_biogas_", 0, myPlant, u, "threshold", 5);

            physValue Qgas_h2;
            physValue Qgas_ch4;
            physValue Qgas_co2;

            physValue T = new physValue("T", 41.4, "°C");

            biogas.ADMstate.calcBiogasOfADMstate(x, new physValue(3000, "m^3"),
                                                 T, out Qgas_h2, out Qgas_ch4, out Qgas_co2);

            double ph = biogas.ADMstate.calcPHOfADMstate(x);

            substrate mySubstrate = mySubstrates.get("swinemanure");

            biogas.ADMstate.calcADMstream(mySubstrate, 30);

            double mypH = mySubstrate.get_param_of("pH");
        }
Exemple #5
0
        /// <summary>
        /// measures the density of the substrate feed of a given digester
        ///
        /// type 7
        ///
        /// TODO: mySensors wird hier eigentlich nicht benötigt
        /// wenn mySensors gelöscht wird, dann ist das keine type 7 funktion mehr, OK
        ///
        /// </summary>
        /// <param name="x">ADM state vector</param>
        /// <param name="myPlant"></param>
        /// <param name="mySubstrates"></param>
        /// <param name="mySensors"></param>
        /// <param name="Q">
        /// substrate feed and recirculation sludge going into the digester
        /// first values are Q for substrates, then pumped sludge going into digester
        /// dimension: always number of substrates + number of digesters
        /// </param>
        /// <param name="par">not used</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];

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

            double Qsum = math.sum(Q);

            // das ist feed in fermenter
            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];
            }

            //

            physValue rhoSubstrate;

            // wenn fermenter nicht mit substraten gefüttert wird
            if (math.sum(Qsubstrates) == 0)
            {
                rhoSubstrate = new physValue(0, "kg/d");
            }
            else
            {
                mySubstrates.get_weighted_sum_of(Qsubstrates, "rho", out rhoSubstrate);
                rhoSubstrate = rhoSubstrate.convertUnit("kg/d");
            }

            //

            physValue rhoSludge = new physValue("rho", 1000, "kg/m^3");

            for (int isubstrate = n_substrate; isubstrate < Q.Length; isubstrate++)
            {
                rhoSubstrate += rhoSludge * new physValue(Q[isubstrate], "m^3/d");
            }

            //

            if (Qsum != 0)
            {
                values[0] = rhoSubstrate / new physValue(Qsum, "m^3/d");
            }
            else
            {
                values[0] = new physValue(0, "kg/m^3");
            }

            //

            values[0].Symbol = "rho";

            //

            return(values);
        }
Exemple #6
0
        /// <summary>
        /// Create network of sensors, which are inside the simulation model
        /// </summary>
        /// <param name="myPlant"></param>
        /// <param name="mySubstrates"></param>
        /// <param name="plant_network"></param>
        /// <param name="plant_network_max"></param>
        /// <returns>
        /// sensors object containing all sensor and sensor_array objects inside the simulation model
        /// </returns>
        /// <exception cref="exception">Unknown sensor array id</exception>
        public static sensors create_sensor_network(plant myPlant, substrates mySubstrates,
                                                    double[,] plant_network, double[,] plant_network_max)
        {
            sensors mySensors = new sensors();

            for (int idigester = 0; idigester < myPlant.getNumDigesters(); idigester++)
            {
                string digester_id = myPlant.getDigesterID(idigester + 1);

                //

                mySensors.addSensor(new biogas.VFA_TAC_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.aceto_hydro_sensor(digester_id));

                mySensors.addSensor(new biogas.AcVsPro_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.HRT_sensor(digester_id));

                mySensors.addSensor(new biogas.faecal_sensor(digester_id));

                mySensors.addSensor(new biogas.inhibition_sensor(digester_id));

                mySensors.addSensor(new biogas.energyProdMicro_sensor(digester_id));

                mySensors.addSensor(new biogas.biogas_sensor(digester_id));

                mySensors.addSensor(new biogas.VFA_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.VFA_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.VFAmatrix_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.VFAmatrix_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.Sva_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.Sva_sensor(digester_id + "_3"));
                mySensors.addSensor(new biogas.Sbu_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.Sbu_sensor(digester_id + "_3"));
                mySensors.addSensor(new biogas.Spro_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.Spro_sensor(digester_id + "_3"));
                mySensors.addSensor(new biogas.Sac_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.Sac_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.VS_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.VS_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.Q_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.Q_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.NH3_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.NH3_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.NH4_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.NH4_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.Norg_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.Norg_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.TKN_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.TKN_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.Ntot_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.Ntot_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.pH_stream_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.pH_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.biomassAciAce_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.biomassMeth_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.TAC_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.TAC_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.SS_COD_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.SS_COD_sensor(digester_id + "_3"));

                mySensors.addSensor(new biogas.VS_COD_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.VS_COD_sensor(digester_id + "_3"));

                // heating
                mySensors.addSensor(new biogas.heatConsumption_sensor(digester_id));

                // stirrers - all stirrer in the digester
                mySensors.addSensor(new biogas.stirrer_sensor(digester_id));

                //

                mySensors.addSensor(new biogas.TS_sensor(digester_id + "_2")); // TS messung des Fermenterinputs
                mySensors.addSensor(new biogas.TS_sensor(digester_id + "_3")); // TS im fermenter

                mySensors.addSensor(new biogas.OLR_sensor(digester_id));

                // measures density of sludge inside the digester
                mySensors.addSensor(new biogas.density_sensor(digester_id));

                //

                mySensors.addSensor(new biogas.ADMstate_sensor(digester_id));

                mySensors.addSensor(new biogas.ADMstream_sensor(digester_id + "_2"));
                mySensors.addSensor(new biogas.ADMstream_sensor(digester_id + "_3"));

                //

                mySensors.addSensor(new biogas.ADMintvars_sensor(digester_id));

                mySensors.addSensor(new biogas.ADMparams_sensor(digester_id));
            }

            //

            mySensors.addSensor(new biogas.SS_COD_sensor("finalstorage_2"));
            mySensors.addSensor(new biogas.VS_COD_sensor("finalstorage_2"));
            mySensors.addSensor(new biogas.Q_sensor("finalstorage_2"));

            mySensors.addSensor(new biogas.SS_COD_sensor("total_mix_2"));
            mySensors.addSensor(new biogas.VS_COD_sensor("total_mix_2"));
            mySensors.addSensor(new biogas.Q_sensor("total_mix_2"));
            mySensors.addSensor(new biogas.VS_sensor("total_mix_2"));

            mySensors.addSensor(new biogas.substrate_sensor("cost"));

            // fitness sensors

            mySensors.addSensor(new biogas.fitness_sensor());

            mySensors.addSensor(new biogas.AcVsPro_fit_sensor());
            mySensors.addSensor(new biogas.VFA_fit_sensor());
            mySensors.addSensor(new biogas.VFA_TAC_fit_sensor());
            mySensors.addSensor(new biogas.TS_fit_sensor());
            mySensors.addSensor(new biogas.pH_fit_sensor());
            mySensors.addSensor(new biogas.OLR_fit_sensor());
            mySensors.addSensor(new biogas.TAC_fit_sensor());
            mySensors.addSensor(new biogas.HRT_fit_sensor());
            mySensors.addSensor(new biogas.N_fit_sensor());
            mySensors.addSensor(new biogas.CH4_fit_sensor());
            mySensors.addSensor(new biogas.SS_COD_fit_sensor());
            mySensors.addSensor(new biogas.VS_COD_fit_sensor());
            mySensors.addSensor(new biogas.gasexcess_fit_sensor());
            mySensors.addSensor(new biogas.setpoint_fit_sensor());
            mySensors.addSensor(new biogas.manurebonus_sensor());
            mySensors.addSensor(new biogas.udot_sensor());

            //

            mySensors.addSensor(new biogas.total_biogas_sensor("", myPlant));

            //

            mySensors.addSensorArray(new biogas.sensor_array("Q"));

            for (int isubstrate = 0; isubstrate < mySubstrates.getNumSubstrates(); isubstrate++)
            {
                try
                {
                    mySensors.getArray("Q").addSensor(new biogas.Q_sensor(mySubstrates.getID(isubstrate + 1)));
                }
                catch (exception e)
                {
                    Console.WriteLine("Could not add Q_sensor to substrate array!");
                    throw (e);
                }

                mySensors.addSensor(new biogas.substrateparams_sensor(mySubstrates.getID(isubstrate + 1)));
            }

            //


            // nº of Columms -> Inputs to the fermenter
            for (int ifermenterIn = 0; ifermenterIn < myPlant.getNumDigesters() + 1; ifermenterIn++)
            {
                // nº of Rows -> Outputs to the fermenter
                for (int ifermenterOut = 0; ifermenterOut < myPlant.getNumDigesters(); ifermenterOut++)
                {
                    // TODO - es gibt bestimmt auch eine funktion in matlab, welche diese schleife
                    // schon implementiert hat als funktion
                    // Connection condition within fermenters
                    if ((plant_network[ifermenterOut, ifermenterIn] > 0) &&
                        (plant_network_max[ifermenterOut, ifermenterIn] < Double.PositiveInfinity))
                    {
                        //
                        // Fermenter Name for Input
                        String fermenter_id_in = myPlant.getDigesterID(ifermenterIn + 1);
                        // Fermenter Name for Output
                        String fermenter_id_out = myPlant.getDigesterID(ifermenterOut + 1);

                        //

                        mySensors.getArray("Q").addSensor(
                            new biogas.Q_sensor(fermenter_id_out + "_" + fermenter_id_in));
                    }
                }
            }

            //

            for (int ibhkw = 0; ibhkw < myPlant.getNumCHPs(); ibhkw++)
            {
                String bhkw_id = myPlant.getCHPID(ibhkw + 1);

                mySensors.addSensor(new biogas.energyProduction_sensor(bhkw_id));
            }

            //

            mySensors.addSensor(new biogas.energyProdSum_sensor());

            //

            // TODO - könnte man evtl. auch in transportation rein schieben

            for (int ipump = 0; ipump < myPlant.getNumPumps(); ipump++)
            {
                String pump_id = myPlant.getPumpID(ipump + 1);

                mySensors.addSensor(new biogas.pumpEnergy_sensor(pump_id));
            }

            //

            for (int isubstrate_transport = 0;
                 isubstrate_transport < myPlant.getNumSubstrateTransports();
                 isubstrate_transport++)
            {
                String substrate_transport_id = myPlant.getSubstrateTransportID(isubstrate_transport + 1);

                // for liquid substrates
                mySensors.addSensor(new biogas.pumpEnergy_sensor(substrate_transport_id));

                // for non-liquid substrates
                mySensors.addSensor(new biogas.transportEnergy_sensor(substrate_transport_id));
            }

            //



            //

            return(mySensors);
        }
        /// <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);
        }