Exemple #1
0
 private void AddWells()
 {
     foreach (var _well in dbEntities.wells.ToList())
     {
         WellData well = new WellData
         {
             Data = new wells_measurements()
             {
                 well_id = _well.well_id
             },
             Name     = _well.name,
             a        = new double[] { (double)_well.a1, (double)_well.a2, (double)_well.a3 },
             b        = new double[] { (double)_well.b1, (double)_well.b2, (double)_well.b3 },
             Shtutzer = dbEntities.shtutzers.First(x => x.well_id == _well.well_id)
         };
         wells.Add(well);
         nodes.First(x => x.Id == _well.gather_point_id).wells.Add(@well);
     }
 }
Exemple #2
0
        public void CalcShtutzer(WellData well)
        {
            if (well.Shtutzer.d_sht_current <= 0)
            {
                well.Gl = 0;
                well.Gg = 0;
                return;
            }
            float G = (well.Data.cond_output + well.Data.gas_output);

            well.Gl = well.Data.cond_output * (1 - well.Shtutzer.d_sht_current * 1.5);
            well.Gg = (float)(G - well.Gl);
            //G = 24;
            //well.Shtutzer.d_sht_current = 0.116f;
            //well.Data.wellhead_T = 328.87f;
            //well.Data.wellhead_P = 4132733.47f;
            //double R = 8.314/well.Shtutzer.M;
            //double S1 = Math.PI*well.Shtutzer.d1*well.Shtutzer.d1/4;
            //double V1 = G/(well.Shtutzer.ro*S1);
            //double Cpg = well.Shtutzer.k * R/(well.Shtutzer.k - 1);
            //double T1z = well.Data.wellhead_T + V1*V1/(2*Cpg);
            //double P1z = well.Data.wellhead_P * Math.Pow(T1z/well.Data.wellhead_T, well.Shtutzer.k/(well.Shtutzer.k - 1));
            //double phi = (well.Shtutzer.ro_l - well.Shtutzer.ro)/(well.Shtutzer.ro_l - well.Shtutzer.ro_g);
            //double betag = phi;
            //double Q1 = G/well.Shtutzer.ro;
            //double Qg1 = betag*Q1;
            //double Gg1 = Qg1*well.Shtutzer.ro_g;
            //double Gl1 = G - Gg1;
            //double akr = Math.Sqrt(2*well.Shtutzer.k*R*T1z/(well.Shtutzer.k + 1));
            //double Pshz = P1z -
            //			  (1 - well.Shtutzer.d_sht_current*well.Shtutzer.d_sht_current/well.Shtutzer.d1/well.Shtutzer.d1)*
            //			  well.Shtutzer.ro*V1*V1/4;
            //double rk = 2/(well.Shtutzer.k + 1);
            //double cd = well.Shtutzer.k/(well.Shtutzer.k - 1);
            //double betakrg = Math.Pow(rk, cd);
            //double f1 = Math.Sqrt(2*well.Shtutzer.k/(well.Shtutzer.k + 1))*
            //			Math.Pow((well.Shtutzer.k + 1)/2, 1/(well.Shtutzer.k - 1));
            //double Gkrg = f1*Pshz/Math.Sqrt(R*T1z)*Math.PI*well.Shtutzer.d_sht_current*well.Shtutzer.d_sht_current/4;
            //if (G > Gkrg) G = Gkrg;
            //double Gch = G/Gkrg;
            //double c = 1/((1 - betakrg)*betakrg);
            //double Psh = Pshz*(0.5 + Math.Sqrt(0.25 - Gch*Gch/c));
            //double q = Gch;
            //double f2 = Math.Sqrt((well.Shtutzer.k + 1)/(well.Shtutzer.k - 1))*
            //			Math.Pow((well.Shtutzer.k + 1)/2, 1/(well.Shtutzer.k + 1));
            //double P2sh = Pshz*
            //			  Math.Pow(q/(f2*Math.Pow((1 - Psh/Pshz), (well.Shtutzer.k - 1)/(2*well.Shtutzer.k))), well.Shtutzer.k);
            //double eP = 0.1; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            //while (Math.Abs(P2sh - Psh)/well.Data.wellhead_P >= eP)
            //{
            //	Psh = P2sh;
            //	P2sh = Pshz*Math.Pow(q/(f2*Math.Pow((1 - Psh/Pshz), (well.Shtutzer.k - 1)/(2*well.Shtutzer.k))), well.Shtutzer.k);
            //}
            //double betakrgks = 0.4 + 10*(betakrg - 0.4)*(betag - 0.9);
            //double xch = (betag - 0.9)*10;
            //double y = 0;
            //if (xch <= 0.5)
            //	y = 0.278*xch;
            //else
            //{
            //	double x1 = 2*(xch - 0.5);
            //	y = 0.139 - 0.283*x1 + 1.44*x1*x1;
            //}
            //double Gkrgks = Gkrg*(0.706*y + 0.294);
            //if (G > Gkrgks)
            //{

            //}
            //else
            //{
            //	double pi = P2sh/Pshz;
            //	double lyash =
            //		Math.Sqrt((well.Shtutzer.k + 1)/(well.Shtutzer.k - 1)*(1 - Math.Pow(pi, (well.Shtutzer.k - 1)/well.Shtutzer.k)));
            //	double Vsh = lyash*akr;
            //	double Tsh = T1z*(1 - (well.Shtutzer.k - 1)/(well.Shtutzer.k + 1)*lyash*lyash);
            //	double Rosh = Pshz*Math.Pow(pi, 1/well.Shtutzer.k)/(R*T1z);
            //	double P2z = Pshz -
            //				 Math.Pow(
            //					 well.Shtutzer.d2*well.Shtutzer.d2/well.Shtutzer.d_sht_current/well.Shtutzer.d_sht_current - 1, 2)*Rosh*
            //				 Vsh*Vsh/2;
            //	double ro2 = Rosh;
            //	double V2 = G*4/(ro2*Math.PI*well.Shtutzer.d2*well.Shtutzer.d2);
            //	double lya2 = V2/akr;
            //	double P2 = P2z*
            //				Math.Pow(1 - (well.Shtutzer.k - 1)/(well.Shtutzer.k + 1)*lya2*lya2,
            //					well.Shtutzer.k/(well.Shtutzer.k - 1));
            //	double T2 = T1z*(1 - (well.Shtutzer.k - 1)/(well.Shtutzer.k + 1)*lya2*lya2);
            //	ro2 = P2/(well.Shtutzer.z*R*T2);
            //	double eRO = 0.001;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            //	while (Math.Abs(ro2 - Rosh)/Rosh >= eRO)
            //	{
            //		Rosh = ro2;
            //		V2 = G * 4 / (ro2 * Math.PI * well.Shtutzer.d2 * well.Shtutzer.d2);
            //		lya2 = V2/akr;
            //		P2 = P2z * Math.Pow(1 - (well.Shtutzer.k - 1) / (well.Shtutzer.k + 1) * lya2 * lya2,
            //					well.Shtutzer.k / (well.Shtutzer.k - 1));
            //		T2 = T1z * (1 - (well.Shtutzer.k - 1) / (well.Shtutzer.k + 1) * lya2 * lya2);
            //		ro2 = P2/(R*T2*well.Shtutzer.z);
            //	}
            //	double betag2 = (well.Shtutzer.ro_l - ro2) / (well.Shtutzer.ro_l - well.Shtutzer.ro_g);//!!!!!!!!!!!!!!!!!!!!!!
            //	double Q2 = G/ro2;
            //	double Qg2 = betag2*Q2;
            //	double Ql2 = (1 - betag2)*Q2;
            //	double Gg2 = Qg2 * well.Shtutzer.ro_g;////////////////ROg2
            //	double Gl2 = G - Gg2;
            //	double T2rv = (Cpg*Gg1 + well.Shtutzer.C_l*Gl1)/(Cpg*Gg2 + well.Shtutzer.C_l*Gl2)*well.Data.wellhead_T +
            //				  well.Shtutzer.D/(Cpg*Gg2 + well.Shtutzer.C_l*Gl2)*(well.Data.wellhead_P*Gg1 - P2*Gg2) +
            //				  1.1*(V1*V1 - V2*V2)*G/(2*(Cpg*Gg2 + well.Shtutzer.C_l*Gl2));
            //	double T2zam = well.Data.wellhead_T +
            //				   well.Shtutzer.D*Gg1*(well.Data.wellhead_P - P2)/(Cpg*Gg1 + well.Shtutzer.C_l*Gl1) +
            //				   1.1*(V1*V1 - V2*V2)*G/(2*(Cpg*Gg1 + well.Shtutzer.C_l*Gl1));
            //	well.Data.inlet_T = (float)(0.5*T2zam + 0.5*T2rv);
            //	well.Data.inlet_P = (float) P2;
            //	well.Gg = (float) Gg2;
            //	well.Gl = (float) Gl2;

            //}
        }
        public void CalcShtutzer(WellData well)
        {
            if (well.Shtutzer.d_sht_current <= 0)
            {
                well.Gl = 0;
                well.Gg = 0;
                return;
            }
            float G = (well.Data.cond_output + well.Data.gas_output);
            well.Gl = well.Data.cond_output * (1 - well.Shtutzer.d_sht_current*1.5);
            well.Gg = (float)(G - well.Gl);
            //G = 24;
            //well.Shtutzer.d_sht_current = 0.116f;
            //well.Data.wellhead_T = 328.87f;
            //well.Data.wellhead_P = 4132733.47f;
            //double R = 8.314/well.Shtutzer.M;
            //double S1 = Math.PI*well.Shtutzer.d1*well.Shtutzer.d1/4;
            //double V1 = G/(well.Shtutzer.ro*S1);
            //double Cpg = well.Shtutzer.k * R/(well.Shtutzer.k - 1);
            //double T1z = well.Data.wellhead_T + V1*V1/(2*Cpg);
            //double P1z = well.Data.wellhead_P * Math.Pow(T1z/well.Data.wellhead_T, well.Shtutzer.k/(well.Shtutzer.k - 1));
            //double phi = (well.Shtutzer.ro_l - well.Shtutzer.ro)/(well.Shtutzer.ro_l - well.Shtutzer.ro_g);
            //double betag = phi;
            //double Q1 = G/well.Shtutzer.ro;
            //double Qg1 = betag*Q1;
            //double Gg1 = Qg1*well.Shtutzer.ro_g;
            //double Gl1 = G - Gg1;
            //double akr = Math.Sqrt(2*well.Shtutzer.k*R*T1z/(well.Shtutzer.k + 1));
            //double Pshz = P1z -
            //			  (1 - well.Shtutzer.d_sht_current*well.Shtutzer.d_sht_current/well.Shtutzer.d1/well.Shtutzer.d1)*
            //			  well.Shtutzer.ro*V1*V1/4;
            //double rk = 2/(well.Shtutzer.k + 1);
            //double cd = well.Shtutzer.k/(well.Shtutzer.k - 1);
            //double betakrg = Math.Pow(rk, cd);
            //double f1 = Math.Sqrt(2*well.Shtutzer.k/(well.Shtutzer.k + 1))*
            //			Math.Pow((well.Shtutzer.k + 1)/2, 1/(well.Shtutzer.k - 1));
            //double Gkrg = f1*Pshz/Math.Sqrt(R*T1z)*Math.PI*well.Shtutzer.d_sht_current*well.Shtutzer.d_sht_current/4;
            //if (G > Gkrg) G = Gkrg;
            //double Gch = G/Gkrg;
            //double c = 1/((1 - betakrg)*betakrg);
            //double Psh = Pshz*(0.5 + Math.Sqrt(0.25 - Gch*Gch/c));
            //double q = Gch;
            //double f2 = Math.Sqrt((well.Shtutzer.k + 1)/(well.Shtutzer.k - 1))*
            //			Math.Pow((well.Shtutzer.k + 1)/2, 1/(well.Shtutzer.k + 1));
            //double P2sh = Pshz*
            //			  Math.Pow(q/(f2*Math.Pow((1 - Psh/Pshz), (well.Shtutzer.k - 1)/(2*well.Shtutzer.k))), well.Shtutzer.k);
            //double eP = 0.1; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            //while (Math.Abs(P2sh - Psh)/well.Data.wellhead_P >= eP)
            //{
            //	Psh = P2sh;
            //	P2sh = Pshz*Math.Pow(q/(f2*Math.Pow((1 - Psh/Pshz), (well.Shtutzer.k - 1)/(2*well.Shtutzer.k))), well.Shtutzer.k);
            //}
            //double betakrgks = 0.4 + 10*(betakrg - 0.4)*(betag - 0.9);
            //double xch = (betag - 0.9)*10;
            //double y = 0;
            //if (xch <= 0.5)
            //	y = 0.278*xch;
            //else
            //{
            //	double x1 = 2*(xch - 0.5);
            //	y = 0.139 - 0.283*x1 + 1.44*x1*x1;
            //}
            //double Gkrgks = Gkrg*(0.706*y + 0.294);
            //if (G > Gkrgks)
            //{

            //}
            //else
            //{
            //	double pi = P2sh/Pshz;
            //	double lyash =
            //		Math.Sqrt((well.Shtutzer.k + 1)/(well.Shtutzer.k - 1)*(1 - Math.Pow(pi, (well.Shtutzer.k - 1)/well.Shtutzer.k)));
            //	double Vsh = lyash*akr;
            //	double Tsh = T1z*(1 - (well.Shtutzer.k - 1)/(well.Shtutzer.k + 1)*lyash*lyash);
            //	double Rosh = Pshz*Math.Pow(pi, 1/well.Shtutzer.k)/(R*T1z);
            //	double P2z = Pshz -
            //				 Math.Pow(
            //					 well.Shtutzer.d2*well.Shtutzer.d2/well.Shtutzer.d_sht_current/well.Shtutzer.d_sht_current - 1, 2)*Rosh*
            //				 Vsh*Vsh/2;
            //	double ro2 = Rosh;
            //	double V2 = G*4/(ro2*Math.PI*well.Shtutzer.d2*well.Shtutzer.d2);
            //	double lya2 = V2/akr;
            //	double P2 = P2z*
            //				Math.Pow(1 - (well.Shtutzer.k - 1)/(well.Shtutzer.k + 1)*lya2*lya2,
            //					well.Shtutzer.k/(well.Shtutzer.k - 1));
            //	double T2 = T1z*(1 - (well.Shtutzer.k - 1)/(well.Shtutzer.k + 1)*lya2*lya2);
            //	ro2 = P2/(well.Shtutzer.z*R*T2);
            //	double eRO = 0.001;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            //	while (Math.Abs(ro2 - Rosh)/Rosh >= eRO)
            //	{
            //		Rosh = ro2;
            //		V2 = G * 4 / (ro2 * Math.PI * well.Shtutzer.d2 * well.Shtutzer.d2);
            //		lya2 = V2/akr;
            //		P2 = P2z * Math.Pow(1 - (well.Shtutzer.k - 1) / (well.Shtutzer.k + 1) * lya2 * lya2,
            //					well.Shtutzer.k / (well.Shtutzer.k - 1));
            //		T2 = T1z * (1 - (well.Shtutzer.k - 1) / (well.Shtutzer.k + 1) * lya2 * lya2);
            //		ro2 = P2/(R*T2*well.Shtutzer.z);
            //	}
            //	double betag2 = (well.Shtutzer.ro_l - ro2) / (well.Shtutzer.ro_l - well.Shtutzer.ro_g);//!!!!!!!!!!!!!!!!!!!!!!
            //	double Q2 = G/ro2;
            //	double Qg2 = betag2*Q2;
            //	double Ql2 = (1 - betag2)*Q2;
            //	double Gg2 = Qg2 * well.Shtutzer.ro_g;////////////////ROg2
            //	double Gl2 = G - Gg2;
            //	double T2rv = (Cpg*Gg1 + well.Shtutzer.C_l*Gl1)/(Cpg*Gg2 + well.Shtutzer.C_l*Gl2)*well.Data.wellhead_T +
            //				  well.Shtutzer.D/(Cpg*Gg2 + well.Shtutzer.C_l*Gl2)*(well.Data.wellhead_P*Gg1 - P2*Gg2) +
            //				  1.1*(V1*V1 - V2*V2)*G/(2*(Cpg*Gg2 + well.Shtutzer.C_l*Gl2));
            //	double T2zam = well.Data.wellhead_T +
            //				   well.Shtutzer.D*Gg1*(well.Data.wellhead_P - P2)/(Cpg*Gg1 + well.Shtutzer.C_l*Gl1) +
            //				   1.1*(V1*V1 - V2*V2)*G/(2*(Cpg*Gg1 + well.Shtutzer.C_l*Gl1));
            //	well.Data.inlet_T = (float)(0.5*T2zam + 0.5*T2rv);
            //	well.Data.inlet_P = (float) P2;
            //	well.Gg = (float) Gg2;
            //	well.Gl = (float) Gl2;

            //}
        }
Exemple #4
0
        private void CalcNode(Node node)
        {
            if (node.wells.Count != 0)
            {
                WellData firstWell = null;
                double   TG = 0, PG = 0, G = 0;
                for (int i = 0; i < node.wells.Count(); i++)                 //выполняем расчет G для всех скважин
                {
                    node.wells[i].G = new double[5];
                    node.wells[i].P = new double[5];
                    if (node.wells[i].Gkr == 0)
                    {
                        continue;
                    }
                    if (firstWell == null)                     //если скважина первая, то считаем для нее давление
                    {
                        firstWell          = node.wells[i];
                        node.wells[i].P[0] = beta_kr * node.wells[i].Pkr;
                        node.wells[i].G[0] = Math.Sqrt(node.wells[i].a[2])
                                             * node.wells[i].Gkr;
                        for (int m = 1; m < 5; m++)
                        {
                            node.wells[i].P[m] = (m * 0.25 * (1 - beta_kr) + beta_kr) * node.wells[i].Pkr;
                            node.wells[i].G[m] = Math.Sqrt(node.wells[i].a[0] * Math.Pow(m * 0.25, 2) + node.wells[i].a[1] * m * 0.25 + node.wells[i].a[2])
                                                 * node.wells[i].Gkr;
                        }
                    }
                    else
                    {
                        for (int m = 0; m < 5; m++)
                        {
                            node.wells[i].G[m] = Math.Sqrt(node.wells[i].a[0] * Math.Pow(m * 0.25, 2) + node.wells[i].a[1] * m * 0.25 + node.wells[i].a[2])
                                                 * node.wells[i].Gkr;
                        }
                    }
                }
                //считаем в узле сбора
                node.P_ = new double[5];
                node.G_ = new double[5];
                node.T_ = new double[5];

                if (firstWell == null)
                {
                    node.T = 0;
                    node.P = 0;
                    return;
                }

                for (int i = 0; i < 5; i++)
                {
                    double big_unkown_coef = 300;
                    node.P_[i] = firstWell.P[i] - K_p * big_unkown_coef * firstWell.G[i];
                    for (int j = 0; j < node.wells.Count(); j++)
                    {
                        TG += node.wells[j].Data.inlet_T * node.wells[j].G[i];
                    }
                    node.G_[i] = node.wells.Sum(x => x.G[i]);
                    if (node.G_[i] == 0)
                    {
                        node.T_[i] = 0;
                    }
                    else
                    {
                        node.T_[i] = TG / node.G_[i];
                    }
                    TG = 0;
                }

                node.a = GetParabolCoefs(new[] { node.P_[0], node.P_[1], node.P_[2] }, new[] { node.G_[0], node.G_[1], node.G_[2] });
                node.b = GetParabolCoefs(new[] { node.P_[2], node.P_[3], node.P_[4] }, new[] { node.G_[2], node.G_[3], node.G_[4] });

                //считаем давление в остальных скважинах

                for (int j = 1; j < node.wells.Count(); j++)                 //выполняем расчет для первой скважины
                {
                    for (int m = 1; m < 5; m++)
                    {
                        double big_unkown_coef = 300;
                        node.wells[j].P[m] = firstWell.P[m] + K_p * big_unkown_coef * firstWell.G[m];
                    }
                }
            }
            else
            {
                if (node.Name == "K336")
                {
                    string f = "";
                }
                var _pipes = _graph.pipes.Where(x => x.EndNode == node).ToList();
                if (_pipes.Count == 0)
                {
                    node.P_ = new double[5];
                    node.G_ = new double[5];
                    node.a  = new double[5];
                    node.b  = new double[5];
                    node.P  = 0;
                    node.T  = 0;
                    node.G  = 0;
                }
                else
                {
                    foreach (var pipe in _pipes)
                    {
                        CalcPipe(pipe);
                    }
                    for (int i = 0; i < 5; i++)
                    {
                        if (node.G_[i] == 0)
                        {
                            node.T_[i] = 0;
                            node.P_[i] = 0;
                        }
                        else
                        {
                            node.T_[i] /= node.G_[i];
                            node.P_[i] /= node.G_[i];
                        }
                    }
                    if (node.P_.Max(x => x) == 0)
                    {
                        node.a = new double[5];
                        node.b = new double[5];
                    }
                    else
                    {
                        node.a = GetParabolCoefs(new[] { node.P_[0], node.P_[1], node.P_[2] }, new[] { node.G_[0], node.G_[1], node.G_[2] });
                        node.b = GetParabolCoefs(new[] { node.P_[2], node.P_[3], node.P_[4] }, new[] { node.G_[2], node.G_[3], node.G_[4] });
                    }
                }
            }
        }
Exemple #5
0
        private void AddWells()
        {
            foreach (var _well in dbEntities.wells.ToList())
            {
                WellData well = new WellData
                {
                    Data = new wells_measurements() { well_id = _well.well_id },
                    Name = _well.name,
                    a = new double[] { (double)_well.a1, (double)_well.a2, (double)_well.a3 },
                    b = new double[] { (double)_well.b1, (double)_well.b2, (double)_well.b3 },
                    Shtutzer = dbEntities.shtutzers.First(x => x.well_id == _well.well_id)
                };
                wells.Add(well);
                nodes.First(x => x.Id == _well.gather_point_id).wells.Add(@well);

            }
        }
        public double[] Calc(DateTime _optimizationDate)
        {
            optimizationDate = _optimizationDate;
            double maxKGF = graph.wells.Where(s => s.Gg != 0).Max(m => m.Gl/m.Gg),
                min1KGF = graph.wells.Where(s => s.Gg != 0).Min(m => m.Gl / m.Gg),
                min2KGF = graph.wells.Where(z => (z.Gg != 0)&&(z.Gl / z.Gg != min1KGF)).Min(m => m.Gl / m.Gg);

            maxKGFWell = graph.wells.First(z => z.Gl/z.Gg == maxKGF);
            min1KGFWell = graph.wells.First(z => z.Gl / z.Gg == min1KGF);
            min2KGFWell = graph.wells.First(z => z.Gl / z.Gg == min2KGF);

            maxKGFWell.d_sht = maxKGFWell.Shtutzer.d_sht_current;
            min1KGFWell.d_sht = min1KGFWell.Shtutzer.d_sht_current;
            min2KGFWell.d_sht = min2KGFWell.Shtutzer.d_sht_current;

            double eps = 0.001;
            //maxKGFWell.Name = "99999999";
            //Подставить начальные значения dшт
            //foreach (var well in graph.wells)
            //{
            //	well.d_sht = 0.06;
            //	well.Gl = 400;
            //	well.Gg = 1300;
            //}
            //Вычислить по модели штуцера и сети
            //Определить скважину с max КГФ и две с min КГФ

            //Перейти к новому решению для этих скважин
            evaluator.CalcGraph(optimizationDate);
            Psb = graph.endNode.P;
            Gsb = graph.endNode.G;
            double alpha = 1, beta = 0.5, gamma = 2;
            List<double[]> x = new List<double[]>();
            double[] f = new double[n+1];

            //начальные значения x
            x.Add(new []{d_shts[0], d_shts[1], d_shts[2]});
            x.Add(new []{d_shts[0], d_shts[0], d_shts[2]});
            x.Add(new []{d_shts[2], d_shts[3], d_shts[4]});
            x.Add(new[] { d_shts[2], d_shts[3], d_shts[1]});

            int xh_ind; //индекс наибольшего f
            int xg_ind; //индекс второго максимума
            int xl_ind; //индекс наименьшего f

            double[] xr; //отраженная точка
            double[] xe; //точка после растяжения
            double[] xc = new double[n]; //точка после сжатия

            double[] x0 = new double[n]; //центр тяжести

            do
            {
                //Вычисляем F в точках х
                for (int i = 0; i < f.Length; i++)
                {
                    f[i] = F(x[i]);
                }

                x0 = new double[n];

                xh_ind = Array.IndexOf(f, f.Max());
                xg_ind = Array.IndexOf(f, f.Where(y => y != f[xh_ind]).Max());
                xl_ind = Array.IndexOf(f, f.Min());

                for (int i = 0; i < n + 1; i++)
                {
                    if (i != xh_ind)
                        for (int j = 0; j < x0.Length; j++)
                            x0[j] += x[i][j]/n;
                }
                double Fx0 = F(x0);

                double[] x0_ = x0.Select(y => y*(1 + alpha)).ToArray();
                double[] xh_ = x[xh_ind].Select(y => y*alpha).ToArray();
                xr = x0_.Select((y, i) => y - xh_[i]).ToArray();

                if (F(xr) < F(x[xl_ind]))
                {
                    double[] xr_ = xr.Select(y => y*gamma).ToArray();
                    x0_ = x0.Select(y => y*(1 - gamma)).ToArray();
                    xe = xr_.Select((y, i) => y + x0_[i]).ToArray();
                    if (F(xe) < F(x[xl_ind]))
                    {
                        x[xh_ind] = xe;
                        f[xh_ind] = F(xe);
                        if (Сonvergence(eps, f)) return x[xl_ind];
                        continue;
                    }
                    else
                    {
                        x[xh_ind] = xr;
                        f[xh_ind] = F(xr);
                        if (Сonvergence(eps, f)) return x[xl_ind];
                        continue;
                    }
                }
                else
                {
                    if (F(xr) < f[xg_ind])
                    {
                        x[xh_ind] = xr;
                        f[xh_ind] = F(xr);
                        if (Сonvergence(eps, f)) return x[xl_ind];
                        continue;
                    }
                    else
                    {
                        //шаг Е
                        if (F(xr) > f[xh_ind])
                        {
                        }
                        else
                        {
                            x[xh_ind] = xr;
                            f[xh_ind] = F(xr);
                        }
                        double[] xh_beta = x[xh_ind].Select(y => y * beta).ToArray();
                        double[] x0_beta = x0.Select(y => y * (1 - beta)).ToArray();
                        xc = xh_beta.Select((y, i) => y + x0_beta[i]).ToArray();
                    }
                }
                if (F(xc) < f[xh_ind])
                {
                    x[xh_ind] = xc;
                    f[xh_ind] = F(xc);
                    if (Сonvergence(eps, f)) return x[xl_ind];
                }
                else
                {
                    //уменьшаем размер симплекса Ж3
                    for (int i = 0; i < n + 1; i++)
                    {
                        x[i] = x[i].Select((m, j) => (m - x[xl_ind][j])/2).ToArray();
                        f[i] = F(x[i]);
                    }
                    if (Сonvergence(eps, f)) return x[xl_ind];
                }
            }
            while (!Сonvergence(eps, f)) ;

            return x[xh_ind];
        }
        public double[] Run(DateTime _optimizationDate)
        {
            optimizationDate = _optimizationDate;
            double maxKGF = graph.wells.Where(s => s.Gg != 0).Max(m => m.Gl / m.Gg),
                min1KGF = graph.wells.Where(s => s.Gg != 0).Min(m => m.Gl / m.Gg),
                min2KGF = graph.wells.Where(z => (z.Gg != 0) && (z.Gl / z.Gg != min1KGF)).Min(m => m.Gl / m.Gg);

            maxKGFWell = graph.wells.First(z => z.Gl / z.Gg == maxKGF);
            min1KGFWell = graph.wells.First(z => z.Gl / z.Gg == min1KGF);
            min2KGFWell = graph.wells.First(z => z.Gl / z.Gg == min2KGF);

            evaluator.CalcGraph(optimizationDate);
            Psb = graph.endNode.P;
            Gsb = graph.endNode.G;

            return context.Run(0.001, new [] {0.06, 0.12, 0.08});
        }