// -------------------------------------------------------------------------------------
        //                            !!! PROTECTED METHODS !!!
        // -------------------------------------------------------------------------------------

        /// <summary>
        /// here it is defined what is measured in the sensor and in which position
        ///
        /// not type 0
        /// </summary>
        /// <param name="u">biogas stream: dimension: BioGas.n_gases</param>
        /// <param name="par">not used</param>
        /// <returns>
        /// measured biogas values
        /// first n_gases values are biogas in m^3/d
        /// next n_gases values are biogas concentrations in %
        /// </returns>
        /// <exception cref="exception">u.Length &lt; _n_gases</exception>
        /// <exception cref="exception">u is empty</exception>
        override protected physValue[] doMeasurement(double[] u, params double[] par)
        {
            physValue[] QgasP = new physValue[(int)BioGas.n_gases];

            // is already checked for in calcPercentualBiogasComposition
            //if (u.Length != (int)BioGas.n_gases)
            //  throw new exception(String.Format(
            //          "u is not of correct dimension: {0} != {1}!",
            //          u.Length, (int)BioGas.n_gases));

            BioGas.calcPercentualBiogasComposition(u, out QgasP);

            physValue[] values = new physValue[dimension];

            for (int ivalue = 0; ivalue < values.Length; ivalue++)
            {
                if (ivalue < (int)BioGas.n_gases)
                {
                    values[ivalue] = new physValue(BioGas.symGases[ivalue], u[ivalue], "m^3/d",
                                                   BioGas.labelGases[ivalue]);
                }
                else
                {
                    values[ivalue] = QgasP[ivalue - (int)BioGas.n_gases];
                }
            }

            return(values);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="myPlant"></param>
        /// <param name="u">contains (h2, ch4, co2)_digester_1, (h2, ch4, co2)_digester_2</param>
        /// <param name="gas2bhkwsplittype">fiftyfifty, one2one, threshold</param>
        /// <param name="par"></param>
        /// <returns></returns>
        override protected physValue[] doMeasurement(biogas.plant myPlant,
                                                     double[] u, string gas2bhkwsplittype,
                                                     params double[] par)
        {
            // contains:
            // total biogas production [m³/d]
            // total biogas production splitted into components [m³d]
            // biogas for each chp splitted into components
            // biogas excess [m³/d]
            physValue[] values = new physValue[dimension];

            // TODO
            //Console.WriteLine(dimension);

            int n_digester = myPlant.getNumDigesters();
            int n_chp      = myPlant.getNumCHPs();
            int n_gases    = (int)BioGas.n_gases;

            // u contains (h2, ch4, co2)_digester_1, (h2, ch4, co2)_digester_2, ...

            // TODO - scheint mir ok zu sein, kann das nicht erkennen.
            // ch4 must be the second element due to implementation below
            //
            // ch4 is the second element
            int index_ch4 = BioGas.pos_ch4 - 1;

            // total biogas in m^3/d (h2, ch4, co2)
            double[] biogas_total = BioGas.merge_streams(u, n_digester);

            // total biogas production in m³/d, sum of biogas_total
            double total_biogas_total;

            // percentual biogas prdocution on the plant (h2 %, ch4 %, co2 %)
            double[] biogas_total_perc = BioGas.calcRelContent(biogas_total, out total_biogas_total);

            //

            double[] gas_out = new double[n_gases * n_chp];

            //

            switch (gas2bhkwsplittype)
            {
            case "fiftyfifty":

                gas_out = math.repmat(math.rdivide(biogas_total, n_chp), n_chp);

                break;

            case "one2one":

                if (n_chp == n_digester)
                {
                    gas_out = u;
                }
                else
                {
                    throw new exception(String.Format("n_chp != n_digester: {0} != {1}!",
                                                      n_chp, n_digester));
                }

                break;

            case "threshold":

                double gas_max;

                for (int ichp = 0; ichp < n_chp; ichp++)
                {
                    if (biogas_total[index_ch4] > 0)
                    {
                        // in gas_max is the maximal amount of methane in m^3/d which
                        // can be handled by the indexed bhkw
                        myPlant.getCHP(ichp + 1).getMaxMethaneConsumption(out gas_max);

                        // available methane content
                        double methan = Math.Min(biogas_total[index_ch4], gas_max);

                        for (int igas = 0; igas < n_gases; igas++)
                        {
                            // get the fraction out of the biogas
                            gas_out[igas + ichp * n_gases] =
                                methan / biogas_total[index_ch4] * biogas_total[igas];
                        }

                        // decrease biogas amount
                        for (int igas = 0; igas < n_gases; igas++)
                        {
                            biogas_total[igas] -= gas_out[igas + ichp * n_gases];
                        }
                    }
                    else
                    {
                        break;
                    }
                }

                //

                break;

            default:
                throw new exception(String.Format(
                                        "Unknown gas2bhkwsplittype: {0}!", id_suffix));
            }

            // too much biogas produced [m^3/d], sum of the three parts
            double gas_excess = Math.Max(total_biogas_total - math.sum(gas_out), 0);

            //

            values[0] = new physValue("biogas_t", total_biogas_total, "m^3/d", "total biogas");

            //

            physValue[] values_rel = BioGas.convert(biogas_total_perc);

            for (int igas = 0; igas < n_gases; igas++)
            {
                values[igas + 1] = values_rel[igas];
            }

            //

            for (int igas = 0; igas < n_gases; igas++)
            {
                for (int ichp = 0; ichp < n_chp; ichp++)
                {
                    values[igas + ichp * n_gases + 1 + n_gases] =
                        new physValue(BioGas.symGases[igas] + "_" + myPlant.getCHPID(ichp + 1),
                                      gas_out[igas + ichp * n_gases], "m^3/d",
                                      BioGas.labelGases[igas]);
                }
            }

            values[values.Length - 1] = new physValue("biogas_excess", gas_excess, "m^3/d", "excess biogas");

            //

            return(values);
        }