/// <summary> /// Do measurements which depend on substrates. /// /// 3rd type /// /// example sensor: /// substrate_sensor, VS_sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="mySubstrates"></param> /// <returns>first measured value</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue measure(double time, string id, //double deltatime, biogas.substrates mySubstrates) { double[] x = new double[1]; return(measure(time, id, x, mySubstrates)); }
/// <summary> /// Calc mix of substrates for all digesters /// /// TODO: s. auch in funktion unten /// </summary> /// <param name="t">current simulation time in days</param> /// <param name="mySubstrates"></param> /// <param name="myPlant"></param> /// <param name="substrate_network"></param> /// <param name="mySensors"></param> /// <param name="Q">only used if datasource_type == extern</param> /// <param name="dilution_rates">double vector with the wanted dilution rates for each digester. /// Could be given by a dilution rate control. The size of the vector must /// be equal to number of digesters.</param> /// <returns>[34dim stream for digester1; 34dim stream for digester2; ...]</returns> public static double[] calcADMstreamMix(double t, biogas.substrates mySubstrates, biogas.plant myPlant, double[,] substrate_network, biogas.sensors mySensors, double[] Q, //double deltatime, double[] dilution_rates) { double[,] myStreams = new double[biogas.ADMstate._dim_stream, myPlant.getNumDigesters()]; for (int idigester = 0; idigester < myPlant.getNumDigesters(); idigester++) { double Vliq = myPlant.getDigesterParam(idigester + 1, "Vliq"); // D ist < 0, wenn Anlage nicht geregelt wird double D = dilution_rates[idigester]; double Q_new = D * Vliq; myStreams = math.insertColumn(myStreams, calcADMstreamMixForDigester(t, mySubstrates, substrate_network, mySensors, idigester, Q, Q_new), 0, idigester); // measure energy needed to transport substrates biogas.substrate_transport.run(t, mySensors, "substratemix", myPlant.getDigesterID(idigester + 1), myPlant, mySubstrates, substrate_network); } double[] myStream = math.concat(myStreams); return(myStream); }
/// <summary> /// Do measurements which depend on substrates. /// /// 3rd type /// /// example sensor: /// substrate_sensor, VS_sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="x">could be state vector</param> /// <param name="mySubstrates"></param> /// <returns>first measured value</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue measure(double time, string id, //double deltatime, double[] x, biogas.substrates mySubstrates) { physValue[] values = measureVec(time, id, x, mySubstrates); return(values[0]); }
/// <summary> /// calculates ADMstream mix of substrates for each digester /// and measures in the mix of all digesters together the COD SS and VS /// content. /// </summary> /// <param name="t">current simulation time in days</param> /// <param name="mySubstrates"></param> /// <param name="myPlant"></param> /// <param name="substrate_network"></param> /// <param name="mySensors"></param> /// <param name="dilution_rates">double vector with the wanted dilution rates for each digester. /// Could be given by a dilution rate control. The size of the vector must /// be equal to number of digesters.</param> /// <returns></returns> public static double[] calc_measureADMstreamMix(double t, biogas.substrates mySubstrates, biogas.plant myPlant, double[,] substrate_network, biogas.sensors mySensors, //double deltatime, double[] dilution_rates) { double[] mystream = calcADMstreamMix(t, mySubstrates, myPlant, substrate_network, mySensors, dilution_rates); // double[] mixed_stream = mixADMstreams(mystream); // measure COD SS and VS of mixed stream // TODO : evtl. von total_mix in substratemix umbenennen // muss dann auch überall anders gemacht werden. bsp: objectives und // sensors: create_sensor_network mySensors.measure(t, "SS_COD_total_mix_2", mixed_stream); mySensors.measure(t, "VS_COD_total_mix_2", mixed_stream); mySensors.measure(t, "Q_total_mix_2", mixed_stream); // messe VS in Substratzufuhr mySensors.measure(t, "VS_total_mix_2", mixed_stream, mySubstrates); return(mystream); }
/// <summary> /// Check whether given substrate feed Q qualifies for the manure bonus /// </summary> /// <param name="mySubstrates"></param> /// <param name="Q">substrate feed on plant in m³/d</param> /// <returns></returns> public static bool check_manurebonus(biogas.substrates mySubstrates, double[] Q) { double[] A; double b, dist_bonus; return(check_manurebonus(mySubstrates, Q, out A, out b, out dist_bonus)); }
// ------------------------------------------------------------------------------------- // !!! PRIVATE METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// Calculates the volumeflow of each substrate going into the given digester digester_id. /// The substrate flows are returned as a vector. /// /// TODO: ist nicht mehr private /// </summary> /// <param name="t">current simulation time</param> /// <param name="mySubstrates"></param> /// <param name="myPlant"></param> /// <param name="mySensors"></param> /// <param name="substrate_network"></param> /// <param name="digester_id">id of the digester which is fed</param> /// <returns> /// always a vector with as many elements as there are substrates on the plant /// </returns> public static physValue[] getSubstrateMixFlowForFermenter(double t, biogas.substrates mySubstrates, biogas.plant myPlant, sensors mySensors, double[,] substrate_network, string digester_id) { int digester_index = myPlant.getDigesterIndex(digester_id) - 1; // get recorded substrate feeds in m³/d physValue[] Q = mySensors.getMeasurementsAt("Q", "Q", t, mySubstrates); // make the sum over the 2nd dimension, the digesters double[] norm_vec = math.sum(substrate_network, 1); double[] substrate_digester = new double[substrate_network.GetLength(0)]; for (int isubstrate = 0; isubstrate < substrate_network.GetLength(0); isubstrate++) { // what is if norm_vec is 0 for an element // then we have 0/0. if (norm_vec[isubstrate] != 0) { substrate_digester[isubstrate] = substrate_network[isubstrate, digester_index] / norm_vec[isubstrate]; } else { substrate_digester[isubstrate] = 0; } } // this is the amount of each substrate going into the given digester Q = physValue.times(Q, substrate_digester); return(Q); }
/// <summary> /// called by TS sensor, OLR sensor, density sensor and heatConsumption_sensor /// /// type 7 /// </summary> /// <param name="x">stream 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</param> /// <param name="par">some doubles</param> /// <returns>measured values</returns> /// <exception cref="exception">Not implemented</exception> virtual protected physValue[] doMeasurement(double[] x, biogas.plant myPlant, biogas.substrates mySubstrates, biogas.sensors mySensors, double[] Q, params double[] par) { throw new exception("Not implemented!"); }
/// <summary> /// Do measurements which depend on sensors and substrates. /// /// 9th type /// /// example sensor: /// used by manure bonus sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="mySubstrates"></param> /// <param name="par">some doubles</param> /// <returns>measured values</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue[] measureVec(double time, string id, biogas.substrates mySubstrates, params double[] par) { sensor mySensor = get(id); return(mySensor.measure(time, sampling_time, mySubstrates, this, par)); }
/// <summary> /// Do measurements which depend on sensors and substrates. /// /// 9th type /// /// example sensor: /// used by manure bonus sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="mySubstrates"></param> /// <param name="par">some doubles</param> /// <param name="value">first measured value</param> /// <exception cref="exception">Unknown sensor id</exception> public void measure(double time, string id, biogas.substrates mySubstrates, double[] par, out double value) { physValue[] vals = measureVec(time, id, mySubstrates, par); value = vals[0].Value; }
/// <summary> /// Do measurements which depend on substrates. /// /// 3rd type /// /// example sensor: /// substrate_sensor /// </summary> /// <param name="time">current simulation time [days]</param> /// <param name="deltatime">sample time of the sensor [days]</param> /// <param name="mySubstrates"></param> /// <param name="Q">could be stream of substrates [m^3/d]</param> /// <param name="par">some doubles</param> /// <returns>measured values</returns> public physValue[] measure(double time, double deltatime, biogas.substrates mySubstrates, double[] Q, params double[] par) { double[] x = new double[1]; return(measure(time, deltatime, x, mySubstrates, Q, par)); }
/// <summary> /// Do measurements which depend on plant and substrates. /// /// 6th type /// /// example sensor: /// wird von heatConsumption_sensor genutzt /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="Q">could be substrate feed</param> /// <param name="par">some doubles</param> /// <returns>measured values</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue[] measureVec(double time, string id, //double deltatime, biogas.plant myPlant, biogas.substrates mySubstrates, double[] Q, params double[] par) { sensor mySensor = get(id); return(mySensor.measure(time, sampling_time, myPlant, mySubstrates, Q, par)); }
/// <summary> /// Do measurements which depend on plant and substrates. /// /// 6th type /// /// example sensor: /// wird von heatConsumption_sensor genutzt /// /// heatConsumption_sensor benötigt call mit substrate_network, /// damit getSubstrateMixFlowForFermenter /// aufgerufen werden kann, den haben wir direkt hier drüber /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="values">measured values</param> /// <exception cref="exception">Unknown sensor id</exception> public void measureVec(double time, string id, //double deltatime, biogas.plant myPlant, biogas.substrates mySubstrates, out double[] values) { physValue[] vals = measureVec(time, id, myPlant, mySubstrates); values = physValue.getValues(vals); }
// ------------------------------------------------------------------------------------- // !!! PUBLIC METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// Do measurements which depend on plant and substrates and other measurements. /// /// 7th type /// /// example sensors: /// called by TS sensor /// OLR_sensor /// density_sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="x">could be statevector</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="mySensors"></param> /// <param name="Q">could be substrate feed</param> /// <param name="value">first measured value</param> /// <exception cref="exception">Unknown sensor id</exception> public void measure(double time, string id, //double deltatime, double[] x, biogas.plant myPlant, biogas.substrates mySubstrates, biogas.sensors mySensors, double[] Q, out double value) { physValue[] vals = measureVec(time, id, x, myPlant, mySubstrates, mySensors, Q); value = vals[0].Value; }
/// <summary> /// Do measurements which depend on plant and substrates. /// /// 6th type /// /// example sensor: /// wird von heatConsumption_sensor genutzt /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="Q">zufuhr aller substrate in anlage, nicht in fermenter /// TODO: es wäre vermutlich besser wenn es nur in fermenter wäre, /// da heatConsumption_sensor am fermenter angebracht ist</param> /// <returns>measured values</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue[] measureVec(double time, string id, //double deltatime, biogas.plant myPlant, biogas.substrates mySubstrates, double[] Q) { double[] par = new double[1]; return(measureVec(time, id, myPlant, mySubstrates, Q, par)); }
// ------------------------------------------------------------------------------------- // !!! PUBLIC METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// Check whether current substrate feed saved in sensors qualifies for the manure bonus /// /// </summary> /// <param name="mySubstrates"></param> /// <param name="mySensors"></param> /// <returns></returns> public static bool check_manurebonus(biogas.substrates mySubstrates, biogas.sensors mySensors) { double t = mySensors.getCurrentTime(); // get current time // get recorded substrate feeds in m³/d physValue[] Q = mySensors.getMeasurementsAt("Q", "Q", t, mySubstrates); double[] Qdbl = physValue.getValues(Q); return(check_manurebonus(mySubstrates, Qdbl)); }
// ------------------------------------------------------------------------------------- // !!! PUBLIC METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// TODO /// </summary> /// <param name="t">current simulation time in days</param> /// <param name="mySensors"></param> /// <param name="unit_start"></param> /// <param name="unit_destiny"></param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="substrate_network"></param> /// <returns></returns> public static double run(double t, //double deltatime, biogas.sensors mySensors, string unit_start, string unit_destiny, biogas.plant myPlant, biogas.substrates mySubstrates, double[,] substrate_network) { double Q_pump, Q_solids; return(run(t, mySensors, unit_start, unit_destiny, myPlant, mySubstrates, substrate_network, out Q_pump, out Q_solids)); }
/// <summary> /// Do measurements which depend on plant and substrates and other measurements. /// /// 7th type /// /// example sensors: /// called by TS sensor /// OLR_sensor /// density_sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="x">could be statevector</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="mySensors"></param> /// <param name="substrate_network"></param> /// <param name="plant_network"></param> /// <param name="digester_id">digester ID</param> /// <param name="value">first measured value</param> /// <exception cref="exception">Unknown sensor id</exception> public void measure(double time, string id, //double deltatime, double[] x, biogas.plant myPlant, biogas.substrates mySubstrates, biogas.sensors mySensors, double[,] substrate_network, double[,] plant_network, string digester_id, out double value) { physValue[] vals = measureVec(time, id, x, myPlant, mySubstrates, mySensors, substrate_network, plant_network, digester_id); value = vals[0].Value; }
/// <summary> /// Do measurements which depend on plant and substrates. /// /// 6th type /// /// example sensor: /// wird von heatConsumption_sensor genutzt /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="substrate_network"></param> /// <param name="digester_id">ID of digester</param> /// <returns>measured values</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue[] measureVec(double time, string id, //double deltatime, biogas.plant myPlant, biogas.substrates mySubstrates, double[,] substrate_network, string digester_id) { physValue[] Q_digester = getSubstrateMixFlowForFermenter(time, mySubstrates, myPlant, this, substrate_network, digester_id); // values are Q for all substrates double[] Q = physValue.getValues(Q_digester); return(measureVec(time, id, myPlant, mySubstrates, Q)); }
/// <summary> /// Calc mix of substrates for all digesters /// /// Q is gotten out of sensor /// </summary> /// <param name="t">current simulation time in days</param> /// <param name="mySubstrates"></param> /// <param name="myPlant"></param> /// <param name="substrate_network"></param> /// <param name="mySensors"></param> /// <param name="dilution_rates">double vector with the wanted dilution rates for each digester. /// Could be given by a dilution rate control. The size of the vector must /// be equal to number of digesters.</param> /// <returns>a column vector with dimension equal to dim_stream * n_digester</returns> public static double[] calcADMstreamMix(double t, biogas.substrates mySubstrates, biogas.plant myPlant, double[,] substrate_network, biogas.sensors mySensors, //double deltatime, double[] dilution_rates) { double[] Q; mySensors.getMeasurementsAt("Q", "Q", t, mySubstrates, out Q); return(calcADMstreamMix(t, mySubstrates, myPlant, substrate_network, mySensors, Q, dilution_rates)); }
/// <summary> /// Do measurements which depend on plant and substrates. /// /// 6th type /// /// example sensor: /// wird von heatConsumption_sensor genutzt /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <returns>measured values</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue[] measureVec(double time, string id, //double deltatime, biogas.plant myPlant, biogas.substrates mySubstrates) { double[] Q; // TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // id_in_array einführen und durch "Q" ersetzen // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //getCurrentMeasurements("Q", "Q", mySubstrates, out Q); getMeasurementsAt("Q", "Q", time, mySubstrates, out Q); return(measureVec(time, id, myPlant, mySubstrates, Q)); }
/// <summary> /// Do measurements which depend on plant and substrates and other measurements. /// /// 7th type /// /// example sensors: /// called by TS sensor /// OLR_sensor /// density_sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="x">could be statevector</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="mySensors"></param> /// <param name="substrate_network"></param> /// <param name="plant_network"></param> /// <param name="digester_id">ID of digester</param> /// <returns>measured values</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue[] measureVec(double time, string id, //double deltatime, double[] x, biogas.plant myPlant, biogas.substrates mySubstrates, biogas.sensors mySensors, double[,] substrate_network, double[,] plant_network, string digester_id) { physValue[] pQ = getInputVolumeflowForFermenter(time, mySubstrates, myPlant, mySensors, substrate_network, plant_network, digester_id); // first values are Q for substrates, then pumped sludge going into digester double[] Q = physValue.getValues(pQ); return(measureVec(time, id, x, myPlant, mySubstrates, mySensors, Q)); }
/// <summary> /// Do measurements which depend on substrates. /// /// 3rd type /// /// example sensor: /// substrate_sensor, VS_sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="x">could be state vector</param> /// <param name="mySubstrates"></param> /// <returns>measured values</returns> /// <exception cref="exception">Unknown sensor id</exception> public physValue[] measureVec(double time, string id, //double deltatime, double[] x, biogas.substrates mySubstrates) { double[] Q; // TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // id_in_array einführen und durch "Q" ersetzen // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // TODO - getCurrentMeasurements darf nie für substrate Q aufgerufen werden // da zu beginn der simulation alle Qs bereits in den sensor geschrieben werden // und damit current immer das letzte element im sensor ist. //getCurrentMeasurements("Q", "Q", mySubstrates, out Q); getMeasurementsAt("Q", "Q", time, mySubstrates, out Q); return(measureVec(time, id, x, mySubstrates, Q)); }
// ------------------------------------------------------------------------------------- // !!! PUBLIC METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// called by fitness_sensor in MATLAB /// </summary> /// <param name="time">current simulation time in days</param> /// <param name="myPlant"></param> /// <param name="myFitnessParams"></param> /// <param name="mySubstrates"></param> /// <param name="par"></param> public void measure_optim_params(double time, biogas.plant myPlant, biooptim.fitness_params myFitnessParams, biogas.substrates mySubstrates, double par) { // measure substrate costs // Calculation of costs of substrate inflow // € / d double substrate_costs, manurebonus, udot; measure(time, "substrate_cost", mySubstrates, out substrate_costs); // measure whether current substrate feed qualifies for EEG2009 manure bonus measure(time, "manurebonus", mySubstrates, 0, out manurebonus); measure(time, "udot", mySubstrates, 0, out udot); // measure all other fitness sensors measure_type8(time, myPlant, myFitnessParams, par); }
/// <summary> /// Do measurements which depend on substrate and sensors. /// /// 9th type /// /// example sensor: /// used by manurebonus sensor /// </summary> /// <param name="time">current simulation time [days]</param> /// <param name="deltatime">sample time of the sensor [days]</param> /// <param name="mySubstrates"></param> /// <param name="mySensors"></param> /// <param name="par">some doubles</param> /// <returns>measured values</returns> public physValue[] measure(double time, double deltatime, biogas.substrates mySubstrates, biogas.sensors mySensors, params double[] par) { physValue[] values; if (time - getCurrentTime() >= deltatime) { values = doMeasurement(mySubstrates, mySensors, par); addMeasurement(time, values); } else { values = getCurrentMeasurementVector(); } return(values); }
/// <summary> /// Call measure of all type 7 sensors /// /// type 7 /// /// used by OLR, TS and density sensor /// </summary> /// <param name="time">current simulation time in days</param> /// <param name="x">stream vector usually 34 dim.</param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="mySensors"></param> /// <param name="substrate_network"></param> /// <param name="plant_network"></param> /// <param name="digester_id">ID of digester</param> public void measure_type7(double time, //double deltatime, double[] x, biogas.plant myPlant, biogas.substrates mySubstrates, biogas.sensors mySensors, double[,] substrate_network, double[,] plant_network, string digester_id) { double value; foreach (string id in ids_type7) { // TODO weiterhin ein Problem, wenn 1. Dig: dig1 und zweiter digester // dummy_dig1 heißt, hatten wir nicht ohnehin definiert, dass digester // ID keinen Unterstrich haben darf? s. gui_plant??? dann wäre das hier ok. if (id.Contains("_" + digester_id)) { measure(time, id, x, myPlant, mySubstrates, mySensors, substrate_network, plant_network, digester_id, out value); } } }
/// <summary> /// Returns a vector of volumeflows for the given digester digester_id. /// first elements are the feeds for each substrate followed by the flows /// going over each incoming connection to the digester. /// </summary> /// <param name="t">current simulation time</param> /// <param name="mySubstrates"></param> /// <param name="myPlant"></param> /// <param name="mySensors"></param> /// <param name="substrate_network"></param> /// <param name="plant_network"></param> /// <param name="digester_id"></param> /// <returns></returns> private physValue[] getInputVolumeflowForFermenter(double t, biogas.substrates mySubstrates, biogas.plant myPlant, sensors mySensors, double[,] substrate_network, double[,] plant_network, string digester_id) { // get volumeflow of substrates into fermenter as column vector physValue[] Q_digester = getSubstrateMixFlowForFermenter(t, mySubstrates, myPlant, mySensors, substrate_network, digester_id); // get recirculated volumflow of other fermenters into this fermenter as // column vector physValue[] Q_pumped = getPumpedInputFlowForFermenter(t, mySubstrates, myPlant, mySensors, substrate_network, plant_network, digester_id); // concatenate both vectors vertically return(physValue.concat(Q_digester, Q_pumped)); }
// ------------------------------------------------------------------------------------- // !!! PUBLIC METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// get all objectives /// </summary> /// <param name="mySensors"></param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="myFitnessParams"></param> /// <param name="Stability_punishment"></param> /// <param name="energyBalance">cost - benefit [1000 €/d]</param> /// <param name="energyProd_fitness"></param> /// <param name="energyConsumption">total el. energy consumption [kWh/d]</param> /// <param name="energyThConsumptionHeat">thermal energy consumption [kWh/d]</param> /// <param name="energyConsumptionPump">el. energy consumption for pumps [kWh/d]</param> /// <param name="energyConsumptionMixer">el. energy consumption for mixer [kWh/d]</param> /// <param name="energyProdMicro">thermal energy prod. microbiology [kWh/d]</param> /// <param name="moneyEnergy"> /// money I get for selling the produced total energy (el. + therm.) in €/d /// </param> /// <param name="fitness_constraints">sum of fitness functions</param> /// <param name="fitness">fitness vector</param> public static void getObjectives(biogas.sensors mySensors, biogas.plant myPlant, biogas.substrates mySubstrates, fitness_params myFitnessParams, /*out double SS_COD_fitness, out double VS_COD_fitness,*/ /*out double SS_COD_degradationRate, out double VS_COD_degradationRate, */ /*out double CH4_fitness, */ out double Stability_punishment, out double energyBalance, out double energyProd_fitness, out double energyConsumption, out double energyThConsumptionHeat, out double energyConsumptionPump, out double energyConsumptionMixer, out double energyProdMicro, /*out double energyThermProduction, * out double energyProduction,*/out double moneyEnergy, out double fitness_constraints, out double[] fitness) { double pHvalue_fitness, VFA_TAC_fitness, TS_fitness, VFA_fitness, AcVsPro_fitness, TAC_fitness, OLR_fitness, HRT_fitness, N_fitness, biogasExcess_fitness, diff_setpoints, CH4_fitness, SS_COD_fitness, VS_COD_fitness; // // normalized between 0 and 1 mySensors.getCurrentMeasurementD("SS_COD_fit", out SS_COD_fitness); // normalized between 0 and 1 mySensors.getCurrentMeasurementD("VS_COD_fit", out VS_COD_fitness); // fitness > 0 if pH value under or over boundaries // normalized between 0 and 1 mySensors.getCurrentMeasurementD("pH_fit", out pHvalue_fitness); // da mit tukey gearbeitet wird, kann der term auch etwas größer als 1 sein mySensors.getCurrentMeasurementD("VFA_TAC_fit", out VFA_TAC_fitness); // this is the fitness of the TS in the digester // da mit tukey gearbeitet wird, kann der term auch etwas größer als 1 sein mySensors.getCurrentMeasurementD("TS_fit", out TS_fitness); // TODO // Calculation of TS concentration in inflow // gibt es auch schon in Individuum Überprüfung: nonlcon_substrate // braucht hier dann eigentlich nicht mehr gemacht werden // verhältnis von propionic acid to acetic acid // max. grenze bei 1.4, s. PhD für Quellen // hier ist der Kehrwert, also min grenze, hier wird mit tukey gearbeitet mySensors.getCurrentMeasurementD("AcVsPro_fit", out AcVsPro_fitness); // da mit tukey gearbeitet wird, kann der term auch etwas größer als 1 sein mySensors.getCurrentMeasurementD("VFA_fit", out VFA_fitness); // tukey mySensors.getCurrentMeasurementD("TAC_fit", out TAC_fitness); // tukey mySensors.getCurrentMeasurementD("OLR_fit", out OLR_fitness); // da mit tukey gearbeitet wird, kann der term auch etwas größer als 1 sein mySensors.getCurrentMeasurementD("HRT_fit", out HRT_fitness); // sum of Snh4 + Snh3, mit tukey mySensors.getCurrentMeasurementD("N_fit", out N_fitness); // CH4 > 50 % als tukey implementiert mySensors.getCurrentMeasurementD("CH4_fit", out CH4_fitness); // biogasExcess_fitness is lossbiogasExcess / 1000 // measured in tausend € / d mySensors.getCurrentMeasurementD("gasexcess_fit", out biogasExcess_fitness); // TODO // // calculate OLR and HRT of plant // TODO - ich könnte auch faecal_fit_sensor schreiben // faecal bacteria removal capacity // intestinal enterococci // faecal coliforms double etaIE = 0, etaFC = 0; for (int idigester = 0; idigester < myPlant.getNumDigesters(); idigester++) { string digesterID = myPlant.getDigesterID(idigester + 1); etaIE += mySensors.getCurrentMeasurementDind("faecal_" + digesterID, 0); etaFC += mySensors.getCurrentMeasurementDind("faecal_" + digesterID, 1); } if (myPlant.getNumDigesters() > 0) { etaIE /= myPlant.getNumDigesters(); etaFC /= myPlant.getNumDigesters(); } // TODO - als ausgabeargumente definieren - nö double fitness_etaIE, fitness_etaFC; // wird in 100 % gemessen fitness_etaIE = 1.0f - etaIE / 100.0f; fitness_etaFC = 1.0f - etaFC / 100.0f; // TODO // stability //stateIsStable(1:n_fermenter,1)= 0; //for ifermenter= 1:n_fermenter // %digester_id= char( plant.getDigesterID(ifermenter) ); // %% TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // stateIsStable(ifermenter,1)= 1;%... // %getStateIsStable(measurements, digester_id, plant); //end //% d.h instabil? //if any(stateIsStable == 0) // Stability_punishment= 1; //else // Stability_punishment= 0; //end Stability_punishment = 0; // TODO // double mbonus; mySensors.getCurrentMeasurementD("manurebonus", out mbonus); myFitnessParams.manurebonus = Convert.ToBoolean(mbonus); // energyConsumption = getElEnergyConsumption(myPlant, mySensors, out energyConsumptionPump, out energyConsumptionMixer); // double energyThProdMixer; double energyThConsumption = getThermalEnergyConsumption(myPlant, mySensors, out energyThConsumptionHeat, out energyThProdMixer, out energyProdMicro); // TODO: einheiten nicht sauber // costs for heating in €/d // // kosten für heizung werden direkt in geld umgerechnet // wenn thermisch produzierte wärme zum heizen des fermenters benutzt wird, // dann werden hier virtuelle kosten berechnet mit kosten revenueTherm, // welche unten bei sellEnergy wieder als erlös mit dem gleichen Wert // berechnet werden, d.h. +/- das gleiche. // double costs_heating = myPlant.calcCostsForHeating_Total( new physValue(energyThConsumption, "kWh/d"), myPlant.myFinances.revenueTherm.Value, myPlant.myFinances.priceElEnergy.Value); // // total el. energy production in kWh/d double energyProduction = mySensors.getCurrentMeasurementDind("energyProdSum", 0); // total thermal energy production in kWh/d double energyThermProduction = mySensors.getCurrentMeasurementDind("energyProdSum", 1); //energyProduction= getEnergyProduction(myPlant, mySensors, out energyThermProduction); // double energyProductionMax = getMaxElEnergyProduction(myPlant); // measured in 100 % energyProd_fitness = (1 - energyProduction / energyProductionMax); // Calculation of costs of substrate inflow // € / d double substrate_costs; mySensors.getCurrentMeasurementD("substrate_cost", out substrate_costs); // double udot; mySensors.getCurrentMeasurementD("udot", out udot); // // TODO // was ist wenn wir weniger thermische energie im BHKW erzeugen als wir verbrauchen? // dann ist costs_heating (virt. kosten) > moneyEnergy thermisch (verkauf von thermischer Energie) // die differenz muss dann elektrisch erzeugt werden, wird allerdings nicht gemacht. // die differenz wird aktuell alas virtuelle Kosten verbucht (Verlust den man hat da man nicht wärme verkauft) // und nicht als reale kosten (erzeugungskosten: thermische energie erzeugt durch heizung) // um das zu lösen, warum ruft man nicht berechnung von costs_heating nach berechnung // von energyThermProduction auf und übergibt dann differenz zw. energyThConsumption und // energyThermProduction? // // TODO - was ist wenn die produzierte elektrische energie von niemanden abgenommen wird // das ist der fall, wenn nach sollwert gefahren wird, dann wird nur so viel energie bezahlt // wie nach sollwert verlangt wurde, das geht so ab eeg 2012 - direktvermarktung // must be in kWh/d double energyElSold = 0; // electrical energy that would be sold // dann gibt es eine referenz kurve welche angibt wieviel energie verkauft würde wenn sie produziert // würde, hier nur elektrische energie if (mySensors.exist("ref_energy_sold")) { // wichtig, dass man sich die messung zur aktuellen zeit holt, da // ref_energy_sold eine referenz vorgibt double time = mySensors.getCurrentTime(); energyElSold = mySensors.getMeasurementDAt("ref_energy_sold", "", time, 0, false); energyElSold = Math.Min(energyElSold, energyProduction); } else { energyElSold = energyProduction; } // moneyEnergy : €/d moneyEnergy = biogas.gasexcess_fit_sensor.sellEnergy(energyElSold, energyThermProduction, myPlant, myFitnessParams); // € / d // is negative when we make more money as we have to pay energyBalance = energyConsumption * myPlant.myFinances.priceElEnergy.Value + costs_heating - moneyEnergy + substrate_costs; // tausend € / d energyBalance = energyBalance / 1000; // // TODO bool noisy = false; // calc setpoint control error //diff_setpoints = calc_setpoint_errors(mySensors, myPlant, myFitnessParams, noisy); mySensors.getCurrentMeasurementD("setpoint_fit", noisy, out diff_setpoints); // calc total fitness of all the constraints fitness_constraints = calcFitnessConstraints(myFitnessParams, SS_COD_fitness, VS_COD_fitness, /*VS_COD_degradationRate,*/ pHvalue_fitness, VFA_TAC_fitness, TS_fitness, VFA_fitness, AcVsPro_fitness, TAC_fitness, OLR_fitness, HRT_fitness, N_fitness, CH4_fitness, biogasExcess_fitness, Stability_punishment, energyProd_fitness, fitness_etaIE, fitness_etaFC, diff_setpoints); // calc fitness vector fitness = calcFitnessVector(myFitnessParams, energyBalance, fitness_constraints, udot); }
// ------------------------------------------------------------------------------------- // !!! PUBLIC METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// Do measurements which depend on sensors and substrates. /// /// 9th type /// /// example sensor: /// manure bonus sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="mySubstrates"></param> /// <param name="par">some double</param> /// <param name="value">first measured value</param> /// <exception cref="exception">Unknown sensor id</exception> public void measure(double time, string id, biogas.substrates mySubstrates, double par, out double value) { double[] parvec = { par }; measure(time, id, mySubstrates, parvec, out value); }
// ------------------------------------------------------------------------------------- // !!! PUBLIC METHODS !!! // ------------------------------------------------------------------------------------- /// <summary> /// Do measurements which depend on substrates. /// /// 3rd type /// /// example sensor: /// substrate_sensor, VS_sensor /// </summary> /// <param name="time">current simulation time</param> /// <param name="id">id of sensor</param> /// <param name="x">could be state vector</param> /// <param name="mySubstrates"></param> /// <param name="Q">volumeflow of substrates</param> /// <param name="value">measured values as double</param> /// <exception cref="exception">Unknown sensor id</exception> public void measure(double time, string id, //double deltatime, double[] x, biogas.substrates mySubstrates, double[] Q, out double value) { value = measure(time, id, x, mySubstrates, Q).Value; }
/// <summary> /// TODO /// </summary> /// <param name="t">current simulation time in days</param> /// <param name="mySensors"></param> /// <param name="unit_start"></param> /// <param name="unit_destiny"></param> /// <param name="myPlant"></param> /// <param name="mySubstrates"></param> /// <param name="substrate_network"></param> /// <param name="Q_pump">to be pumped amount in m^3/d</param> /// <param name="Q_solids"> /// amount that can not be pumped because TS content is too high /// </param> /// <returns></returns> public static double run(double t, //double deltatime, biogas.sensors mySensors, string unit_start, string unit_destiny, biogas.plant myPlant, biogas.substrates mySubstrates, double[,] substrate_network, out double Q_pump, out double Q_solids) { string substrate_transport_id = getid(unit_start, unit_destiny); // determine rho - default value for digester or storagetank physValue density_liq = new physValue("rho", 1000, "kg/m^3", "density"); physValue density_sol = new physValue("rho", 1000, "kg/m^3", "density"); Q_pump = 0; Q_solids = 0; // if (unit_start == "substratemix") { // get mean rho out of substrates and double[] Q // nutze hier getSubstrateMixFlowForFermenter //double[] Q; // TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // id_in_array einführen und durch "Q" ersetzen // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //mySensors.getCurrentMeasurements("Q", "Q", mySubstrates, out Q); //getMeasurementsAt("Q", "Q", time, mySubstrates, out Q); // unit_destiny here must be a digester_id, because you cannot // pump substratemix directly into final storage tank physValue[] Q_digester = sensors.getSubstrateMixFlowForFermenter(t, mySubstrates, myPlant, mySensors, substrate_network, unit_destiny); // values are Q for all substrates double[] Q = physValue.getValues(Q_digester); // an dieser Stelle muss man heraus finden, welche Elemente // von Q flüssig und welche fest sind, an Hand TS Gehalt bestimmen < 11 % FM biogas.substrates mySubsSol = new biogas.substrates(); biogas.substrates mySubsLiq = new biogas.substrates(); List <double> Q_liq_subs = new List <double>(); List <double> Q_sol_subs = new List <double>(); // for (int iel = 0; iel < Q.Length; iel++) { double TS = mySubstrates.get_param_of(iel + 1, "TS"); if (TS < 11) // liquid substrate (pumpable) { mySubsLiq.addSubstrate(mySubstrates.get(iel + 1)); Q_liq_subs.Add(Q[iel]); } else { mySubsSol.addSubstrate(mySubstrates.get(iel + 1)); Q_sol_subs.Add(Q[iel]); } } if (Q_liq_subs.Count > 0) { double[] Q_liq_s_a = Q_liq_subs.ToArray(); Q_pump = math.sum(Q_liq_s_a); // mySubsLiq.get_weighted_mean_of(Q_liq_s_a, "rho", out density_liq); } if (Q_sol_subs.Count > 0) { double[] Q_sol_s_a = Q_sol_subs.ToArray(); Q_solids = math.sum(Q_sol_s_a); // mySubsSol.get_weighted_mean_of(Q_sol_s_a, "rho", out density_sol); } } else { throw new exception("substrate_transport may only pump the substratemix"); } // measure energy needed to pump stuff // dann als summe raus geben (solids + liquids) double P_kWh_d; // its important that we pass two arguments here // is used in energyPump_sensor to ditinguish between this call // the one from pump.cs double[] parvec = { Q_pump, density_liq.Value }; mySensors.measure(t, "pumpEnergy_" + substrate_transport_id, myPlant, Q_pump, parvec, out P_kWh_d); // double[] parv = { density_sol.Value }; double P_solids; mySensors.measure(t, "transportEnergy_" + substrate_transport_id, myPlant, Q_solids, parv, out P_solids); P_kWh_d += P_solids; // TODO - DEFINE WHAT SHOULD be returned //double[] retvals = { P_kWh_d, Q_pump }; return(P_kWh_d);// retvals; }