예제 #1
0
파일: Initialize.cs 프로젝트: vcer007/CUBOS
        //Method Name: initializeSimulationSinglePhase
        //Objectives: The same as the previous method, but it does not take data as input. It uses internal hard coded sata.
        //Inputs: N/A
        //Outputs: N/A
        public static void initializeSimulationSinglePhase()
        {
            #region Initialize Rectangular grid dimensions
            bool homogeneous = false;
            int  x = 5, y = 1, z = 1;

            int[] inactive_blocks = new int[] { };

            //creates an arrayfor the grid x, y and z dimensions
            int[] grid_dimensions = new int[] { x, y, z };

            //calculates the size of the entire grid "including both active and non-active blocks"
            int size = x * y * z;
            //calculates the size of the active-blocks only
            int size_active = x * y * z - inactive_blocks.Length;

            //use this if the natural ordering excludes inactive blocks
            if (inactive_blocks.Length > 0)
            {
                size = size_active;
            }

            GridBlock[] grid;
            #endregion

            #region Initialize grid
            //The gridding technique used here is for only a single row or a single column
            int[] delta_X = new int[x];
            int[] delta_Y = new int[y];
            int[] delta_Z = new int[z];

            //Homogeneous grid sizing
            if (homogeneous)
            {
                for (int i = 0; i < x; i++)
                {
                    delta_X[i] = 300;
                }
                for (int i = 0; i < y; i++)
                {
                    delta_Y[i] = 350;
                }
                for (int i = 0; i < z; i++)
                {
                    delta_Z[i] = 40;
                }
            }
            //Heterogeneous grid sizing
            else
            {
                //General grid values
                for (int i = 0; i < x; i++)
                {
                    delta_X[i] = 300;
                }
                for (int i = 0; i < y; i++)
                {
                    delta_Y[i] = 500;
                }
                for (int i = 0; i < z; i++)
                {
                    delta_Z[i] = 50;
                }
                //Specific heterogenities
                delta_X = new int[] { 400, 300, 150, 200, 250 };
            }
            #endregion

            #region Initialize Rock properties
            //The gridding technique used here is for the whole grid


            double[] Kx_data              = new double[size];
            double[] Ky_data              = new double[size];
            double[] Kz_data              = new double[size];
            double[] porosity             = new double[size];
            double   compressibility_rock = 0;

            //Homogeneous grid
            if (homogeneous)
            {
                for (int i = 0; i < size; i++)
                {
                    Kx_data[i]           = 270;
                    Ky_data[i]           = 270;
                    porosity[i]          = 0.27;
                    compressibility_rock = 0.000001;
                }
            }
            //Heterogeneous grid
            else
            {
                //General
                for (int i = 0; i < size; i++)
                {
                    Kx_data[i]  = 270;
                    Ky_data[i]  = 270;
                    porosity[i] = 0.27;
                    //compressibility_rock = 0.000001;
                }
                //Specific heterogenities
                Kx_data              = new double[] { 273, 248, 127, 333, 198 };
                Ky_data              = Kx_data;
                porosity             = new double[] { 0.21, 0.17, 0.1, 0.25, 0.13 };
                compressibility_rock = 0;
            }
            #endregion

            #region Initialize PVT

            double FVF       = 1;
            double viscosity = 1.5;

            //For slightly-compressibly fluid
            double compressibility_fluid = 2.5 * Math.Pow(10, -5);

            //For compressible fluid, this data is used for constructing the PVT table
            double[][] g_data = new double[4][];
            g_data[0] = new double[] { 14.7, 264.7, 514.7, 1014.7, 2014.7, 2514.7, 3014.7, 4014.7, 5014.7, 9014.7 };
            g_data[1] = new double[] { 0.166666, 0.012093, 0.006274, 0.003197, 0.001614, 0.001294, 0.00108, 0.000811, 0.0006490, 0.000386 };
            g_data[2] = new double[] { 0.008, 0.0096, 0.0112, 0.014, 0.0189, 0.0208, 0.0228, 0.0268, 0.0309, 0.047 };
            g_data[3] = new double[] { 0.0647, 0.8916, 1.7185, 3.3727, 6.8806, 8.3326, 9.9837, 13.2952, 16.6139, 27.948 };

            PVT pvt = new PVT(g_data: g_data);
            #endregion

            #region  Initialize boundary conditions

            int initial_pressure = 3000;

            double[] boundary_flow_rate           = new double[size];
            double[] boundary_pressure_x          = new double[size];
            double[] boundary_pressure_y          = new double[size];
            double[] boundary_pressure_gradient_x = new double[size];
            double[] boundary_pressure_gradient_y = new double[size];


            //boundary_pressure_x[0] = 4000;
            //boundary_flow_rate[0] = -500;
            //boundary_flow_rate[3] = 200;
            //boundary_pressure_gradient_x[1] = 0.3; boundary_pressure_gradient_x[3] = 0.3;
            //boundary_pressure_y[0] = 4000; boundary_pressure_y[1] = 4000;
            //boundary_pressure_gradient_x[3] = 0.2;
            #endregion

            #region  Initialize wells data
            Well[] wells = new Well[size];
            Well   well;
            for (int i = 0; i < wells.Length; i++)
            {
                if (i == 3)
                {
                    well = new Well();

                    well.type_calculation    = Well.TypeCalculation.Specified_Flow_Rate;
                    well.specified_flow_rate = 400;
                    well.specified_BHP       = 1500;
                    well.skin = 0;
                    well.rw   = 3;
                    well.type = Well.Type.Production;
                    //Add the well to the array
                    wells[i] = well;
                }

                //if (i == 3)
                //{
                //    well = new Well();

                //    well.type_calculation = Well.TypeCalculation.Specified_BHP;
                //    well.specified_BHP = 3500;
                //    well.rw = 3;
                //    well.skin = 0;
                //    well.type = Well.Type.Injection;
                //    //Add the well to the array
                //    wells[i] = well;
                //}
                //if (i == 4)
                //{
                //    well = new Well();

                //    well.type_calculation = Well.TypeCalculation.Specified_Flow_Rate;
                //    well.well_flow_rate = 1000;
                //    well.type = Well.Type.Production;

                //    //Add the well to the array
                //    wells[i] = well;
                //}
            }
            #endregion

            #region run specifications
            TypeDefinitions.Compressibility compressibility = TypeDefinitions.Compressibility.Slightly_Compressible;
            var phase     = Transmissibility.Phase.Water;
            var grid_type = Transmissibility.GridType.Rectangular;

            //For compressible and slightly-compressible fluids, define the values for time steps and total simulation time
            double delta_t  = 5;
            double time_max = 180;

            //For compressible fluid problems
            double convergence_pressure = 0.001;
            #endregion

            #region Initialize
            //#########################################################################################
            //Assign neighbouring blocks "according to the natural ordering procedure"
            grid = RectangularBlockNumbering.assignGridOrdering(grid_dimensions, inactive_blocks, RectangularBlockNumbering.NumberingScheme.Active_Only);

            GridBlock block;

            //Parallel.For(0, grid.Length, (counter) =>
            //{

            //});
            for (int counter = 0; counter < grid.Length; counter++)
            {
                block = grid[counter];

                //#########################################################################################
                //Assign PVT and rock properties

                block.delta_x     = delta_X[block.x]; block.delta_y = delta_Y[block.y]; block.h = delta_Z[counter];
                block.bulk_volume = block.delta_x * block.delta_y * block.h;

                block.Kx = Kx_data[counter]; block.Ky = Ky_data[counter]; block.Kz = Kz_data[counter];

                //To-Do: initialize pressure through hydraulic equilibrium
                block.pressure = initial_pressure;

                if (compressibility == TypeDefinitions.Compressibility.Compressible)
                {
                    block.water_viscosity = pvt.getWaterViscosity(initial_pressure);
                    block.So  = 0; block.Sg = 0; block.Sw = 1;
                    block.Kro = 0; block.Krg = 0; block.Krw = 1;
                    block.Cf  = compressibility_rock; block.C = compressibility_fluid;

                    block.Bw       = pvt.getWaterFVF(initial_pressure);
                    block.porosity = Vp_Calculator.chord_slope_Vp(compressibility_rock, porosity[counter], block.pressure, initial_pressure);
                }
                else if (compressibility == TypeDefinitions.Compressibility.Slightly_Compressible)
                {
                    //For slightly compressibly fluids, viscosity is independent of pressure
                    block.water_viscosity = viscosity;
                    //For a single phase fluid, saturation and relative permeabilities of the fluid is equal to unity
                    block.So  = 0; block.Sg = 0; block.Sw = 1;
                    block.Kro = 0; block.Krg = 0; block.Krw = 1;
                    //For slightly compressible fluids, the values of rock compressibility "Cf" and fluid compressibility C_fluid are used to estimate the new values
                    block.Cf = compressibility_rock; block.C = compressibility_fluid;

                    block.Bw       = PVT.chord_slope_FVF(compressibility_fluid, initial_pressure);
                    block.porosity = Vp_Calculator.chord_slope_Vp(compressibility_rock, porosity[counter], block.pressure, initial_pressure);
                }
                else
                {
                    block.water_viscosity = viscosity; block.Bw = FVF;
                    block.porosity        = porosity[counter];
                    block.So  = 0; block.Sg = 0; block.Sw = 1;
                    block.Kro = 0; block.Krg = 0; block.Krw = 1;
                }

                //#########################################################################################
                //Calculate geometric factors "the part of the transmissibility that is always constant" only once in the initialization process
                var direction_x = Transmissibility.Direction.x;
                var direction_y = Transmissibility.Direction.y;

                if (homogeneous)
                {
                    block.GF_x = Transmissibility.getGeometricFactor(block, grid_type, direction_x);
                    block.GF_y = Transmissibility.getGeometricFactor(block, grid_type, direction_y);
                }

                //#########################################################################################
                //Set boundary conditions

                double boundary_transmissibility = 0;

                block.boundary_flow_rate = boundary_flow_rate[counter];
                if (boundary_pressure_x[counter] != 0)
                {
                    boundary_transmissibility = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_x, phase);
                    block.boundary_pressure_times_transmissibility = boundary_transmissibility * boundary_pressure_x[counter];
                    block.boundary_transmissibility = boundary_transmissibility;
                }
                else if (boundary_pressure_y[counter] != 0)
                {
                    boundary_transmissibility = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_y, phase);
                    block.boundary_pressure_times_transmissibility = boundary_transmissibility * boundary_pressure_y[counter];
                    block.boundary_transmissibility = boundary_transmissibility;
                }

                //boundary pressure gradient is positive for depletion and negative for encroachment
                boundary_transmissibility         = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_x, phase);
                block.boundary_pressure_gradient += boundary_pressure_gradient_x[counter] * block.delta_x / 2 * boundary_transmissibility;

                boundary_transmissibility         = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_y, phase);
                block.boundary_pressure_gradient += boundary_pressure_gradient_y[counter] * block.delta_y / 2 * boundary_transmissibility;


                //#########################################################################################
                //Set well rates
                if (wells[counter] != null)
                {
                    well       = wells[counter];
                    block.type = GridBlock.Type.Well;

                    if (well.type_calculation == Well.TypeCalculation.Specified_Flow_Rate)
                    {
                        block.well_type      = GridBlock.WellType.Specified_Flow_Rate;
                        block.well_flow_rate = well.specified_flow_rate;
                        block.specified_BHP  = well.specified_BHP;

                        block.rw = well.rw;
                        double well_geometric_factor = Well.getGeometricFactor(block);
                        block.well_geometric_factor = well_geometric_factor;
                        block.well_transmissibility = Well.getTransmissibility(block, well_geometric_factor, Well.Phase.Water);
                    }
                    else
                    {
                        block.well_type = GridBlock.WellType.Specified_BHP;
                        block.BHP       = well.specified_BHP;
                        block.rw        = well.rw;
                        block.skin      = well.skin;
                        double well_geometric_factor = Well.getGeometricFactor(block);
                        block.well_geometric_factor = well_geometric_factor;
                        block.well_transmissibility = Well.getTransmissibility(block, well_geometric_factor, Well.Phase.Water);
                    }
                }
            }

            #region calculate the geometric factors of a heterogeneous grid
            if (!homogeneous)
            {
                var direction_x = Transmissibility.Direction.x;
                var direction_y = Transmissibility.Direction.y;
                int x_counter   = 0;
                int y_counter   = 0;
                //int z_counter = 0;

                for (int i = 0; i < grid.Length; i++)
                {
                    block = grid[i];

                    if (x > 1)
                    {
                        x_counter = block.east_counter != -1 ? block.east_counter : block.west_counter;

                        block.GF_x = Transmissibility.getGeometricFactor(block, grid[x_counter], grid_type, direction_x);
                    }
                    if (y > 1)
                    {
                        y_counter = block.north_counter != -1 ? block.north_counter : block.south_counter;

                        block.GF_y = Transmissibility.getGeometricFactor(block, grid[y_counter], grid_type, direction_y);
                    }
                }
            }
            #endregion

            #endregion

            #region Choose Solver
            if (compressibility == TypeDefinitions.Compressibility.Incompressible)
            {
                //SolverSinglePhase.incompressible(grid);
            }
            else if (compressibility == TypeDefinitions.Compressibility.Slightly_Compressible)
            {
                //SolverSinglePhase.slightly_compressible(grid, delta_t, time_max);
            }
            else
            {
                //SolverSinglePhase.compressible(grid, delta_t, time_max, convergence_pressure, output, pvt);
            }
            #endregion
        }
예제 #2
0
파일: Initialize.cs 프로젝트: vcer007/CUBOS
        //Method Name: initializeSimulationSinglePhase
        //Objectives: reads the data from the data object passed to it and assign the values to the blocks after constructing the grid and starting the solver
        //Inputs: a variable of type "SimulatorData" that contains all the simulation data read from the data input file
        //Outpits: N/A
        public static void initializeSimulationSinglePhase(SimulatorData data)
        {
            #region Initialize Rectangular grid dimensions
            bool homogeneous = data.homogeneous;
            int  x = data.x, y = data.y, z = data.z;

            int[] inactive_blocks = data.inactive_blocks;

            //creates an array for the grid x, y and z dimensions
            int[] grid_dimensions = new int[] { x, y, z };

            //calculates the size of the entire grid "including both active and non-active blocks"
            int size = x * y * z;
            //calculates the size of the active-blocks only
            int size_active = x * y * z - inactive_blocks.Length;

            //use this if the natural ordering excludes inactive blocks
            if (data.natural_ordering == SimulatorData.NaturalOrdering.Active_Only)
            {
                size = size_active;
            }

            GridBlock[] grid;
            #endregion

            #region Initialize grid data
            //The gridding technique used here is for only a single row or a single column
            int[] delta_X = new int[x];
            int[] delta_Y = new int[y];
            int[] delta_Z = new int[size];

            double[] depth_top_array = new double[size];
            double   depth_top;

            //Homogeneous grid sizing
            if (homogeneous)
            {
                for (int i = 0; i < x; i++)
                {
                    delta_X[i] = data.delta_X;
                }
                for (int i = 0; i < y; i++)
                {
                    delta_Y[i] = data.delta_Y;
                }
                for (int i = 0; i < size; i++)
                {
                    delta_Z[i] = data.delta_Z;
                }
            }
            //Heterogeneous grid sizing
            else
            {
                delta_X = data.delta_X_array;
                delta_Y = data.delta_Y_array;
                delta_Z = data.delta_Z_array;

                depth_top_array = data.depth_top_array;
            }
            #endregion

            #region Initialize Rock properties
            //The gridding technique used here is for the whole grid

            double[] Kx_data              = new double[size];
            double[] Ky_data              = new double[size];
            double[] Kz_data              = new double[size];
            double[] porosity             = new double[size];
            double   compressibility_rock = 0;

            //Homogeneous grid
            if (homogeneous)
            {
                for (int i = 0; i < size; i++)
                {
                    Kx_data[i]           = data.Kx_data;
                    Ky_data[i]           = data.Ky_data;
                    Kz_data[i]           = data.Kz_data;
                    porosity[i]          = data.porosity;
                    compressibility_rock = data.compressibility_rock;
                }
            }
            //Heterogeneous grid
            else
            {
                Kx_data              = data.Kx_data_array;
                Ky_data              = data.Ky_data_array;
                Kz_data              = data.Kz_data_array;
                porosity             = data.porosity_array;
                compressibility_rock = data.compressibility_rock;
            }
            #endregion

            #region Initialize PVT

            double FVF              = data.FVF;
            double viscosity        = data.viscosity;
            double density          = data.density;
            double molecular_weight = data.molecular_weight;
            double temperature      = data.temperature;

            PVT pvt = new PVT(us_w_d: data.water_data);

            //For slightly-compressibly fluid
            double compressibility_fluid = data.compressibility_fluid;

            //For compressible fluid, this data is used for constructing the PVT table
            double[][] g_data = data.g_data;

            //PVT pvt = new PVT(g_data: g_data);
            #endregion

            #region  Initialize boundary conditions

            double initial_pressure = data.initial_pressure;

            double[] boundary_flow_rate           = data.boundary_flow_rate;
            double[] boundary_pressure_x          = data.boundary_pressure_x;
            double[] boundary_pressure_y          = data.boundary_pressure_y;
            double[] boundary_pressure_gradient_x = data.boundary_pressure_gradient_x;
            double[] boundary_pressure_gradient_y = data.boundary_pressure_gradient_y;

            #endregion

            #region  Initialize wells data
            Well[] wells = data.well_array;
            Well   well;

            #endregion

            #region run specifications
            TypeDefinitions.Compressibility compressibility = data.compressibility;
            var phase     = Transmissibility.Phase.Water;
            var grid_type = data.grid_type;

            //For compressible and slightly-compressible fluids, define the values for time steps and total simulation time
            double delta_t  = data.delta_t;
            double time_max = data.time_max;

            //For compressible fluid problems
            double convergence_pressure = data.convergence_pressure;
            #endregion

            #region Initialize grid
            //#########################################################################################
            //Assign neighbouring blocks "according to the natural ordering procedure"
            //set numbering scheme
            var numbering_scheme = RectangularBlockNumbering.NumberingScheme.Active_Only;
            //contruct the grid
            grid = RectangularBlockNumbering.assignGridOrdering(grid_dimensions, inactive_blocks, numbering_scheme);

            GridBlock block;
            //assign properties to each block in the grid
            for (int counter = 0; counter < grid.Length; counter++)
            {
                block = grid[counter];

                //#########################################################################################
                //Assign PVT and rock properties

                block.delta_x     = delta_X[block.x]; block.delta_y = delta_Y[block.y]; block.h = delta_Z[counter];
                block.depth       = depth_top_array[counter] + block.h * 0.5;
                block.bulk_volume = block.delta_x * block.delta_y * block.h;

                block.Kx = Kx_data[counter]; block.Ky = Ky_data[counter]; block.Kz = Kz_data[counter];

                //To-Do: initialize pressure through hydraulic equilibrium
                block.pressure = initial_pressure;

                if (compressibility == TypeDefinitions.Compressibility.Compressible)
                {
                    block.water_viscosity = pvt.getWaterViscosity(initial_pressure);

                    //For a single phase fluid, saturation and relative permeabilities of the fluid is equal to unity
                    block.So  = 0; block.Sg = 0; block.Sw = 1;
                    block.Kro = 0; block.Krg = 0; block.Krw = 1;
                    //For slightly compressible fluids, the values of rock compressibility "Cf" and fluid compressibility C_fluid are used to estimate the new values
                    block.Cf = compressibility_rock; block.C = compressibility_fluid;

                    const double a             = 5.614583;
                    double       FVF_constants = 14.7 / (60 + 460) * (190 + 460) / 1;
                    double       z_factor      = PVT.calculateZ(738.44, 418.38, initial_pressure, 190, 1);
                    block.Bw            = FVF_constants * z_factor / initial_pressure;
                    density             = PVT.calculateGasDensity(initial_pressure, molecular_weight, z_factor, temperature);
                    block.water_density = density * gamma_c * gravity_c;
                    block.porosity      = Vp_Calculator.chord_slope_Vp(compressibility_rock, porosity[counter], block.pressure, initial_pressure);
                }
                else if (compressibility == TypeDefinitions.Compressibility.Slightly_Compressible)
                {
                    //For slightly compressibly fluids, viscosity is independent of pressure
                    if (viscosity > 0)
                    {
                        block.water_viscosity = viscosity;
                    }
                    else
                    {
                        block.water_viscosity = pvt.getWaterViscosity(initial_pressure);
                    }

                    //For a single phase fluid, saturation and relative permeabilities of the fluid is equal to unity
                    block.So  = 0; block.Sg = 0; block.Sw = 1;
                    block.Kro = 0; block.Krg = 0; block.Krw = 1;
                    //For slightly compressible fluids, the values of rock compressibility "Cf" and fluid compressibility C_fluid are used to estimate the new values
                    block.Cf = compressibility_rock; block.C = compressibility_fluid;

                    block.Bw            = PVT.chord_slope_FVF(compressibility_fluid, 14.7);
                    block.water_density = density * gamma_c * gravity_c;
                    block.porosity      = Vp_Calculator.chord_slope_Vp(compressibility_rock, porosity[counter], block.pressure, initial_pressure);
                }
                else
                {
                    block.water_viscosity = viscosity; block.Bw = FVF; block.water_density = density * gamma_c * gravity_c;
                    block.porosity        = porosity[counter];
                    block.So  = 0; block.Sg = 0; block.Sw = 1;
                    block.Kro = 0; block.Krg = 0; block.Krw = 1;
                }

                //#########################################################################################
                //Calculate geometric factors "the part of the transmissibility that is always constant" only once in the initialization process
                var direction_x = Transmissibility.Direction.x;
                var direction_y = Transmissibility.Direction.y;

                if (homogeneous)
                {
                    block.GF_x = Transmissibility.getGeometricFactor(block, grid_type, direction_x);
                    block.GF_y = Transmissibility.getGeometricFactor(block, grid_type, direction_y);
                }

                //#########################################################################################
                //Set boundary conditions

                double boundary_transmissibility = 0;

                block.boundary_flow_rate = boundary_flow_rate[counter];
                if (boundary_pressure_x[counter] != 0)
                {
                    boundary_transmissibility = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_x, phase);
                    block.boundary_pressure   = boundary_pressure_x[counter];
                    block.boundary_pressure_times_transmissibility = boundary_transmissibility * boundary_pressure_x[counter];
                    block.boundary_transmissibility = boundary_transmissibility;
                }
                else if (boundary_pressure_y[counter] != 0)
                {
                    boundary_transmissibility = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_y, phase);
                    block.boundary_pressure   = boundary_pressure_y[counter];
                    block.boundary_pressure_times_transmissibility = boundary_transmissibility * boundary_pressure_y[counter];
                    block.boundary_transmissibility = boundary_transmissibility;
                }

                //boundary pressure gradient is positive for depletion and negative for encroachment
                boundary_transmissibility         = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_x, phase);
                block.boundary_pressure_gradient += boundary_pressure_gradient_x[counter] * block.delta_x / 2 * boundary_transmissibility;

                boundary_transmissibility         = Transmissibility.getBoundaryTransmissibility(block, grid_type, direction_y, phase);
                block.boundary_pressure_gradient += boundary_pressure_gradient_y[counter] * block.delta_y / 2 * boundary_transmissibility;


                //#########################################################################################
                //Set well rates
                if (wells[counter] != null)
                {
                    well       = wells[counter];
                    block.type = GridBlock.Type.Well;

                    //specified flow rate wells
                    if (well.type_calculation == Well.TypeCalculation.Specified_Flow_Rate)
                    {
                        block.well_type      = GridBlock.WellType.Specified_Flow_Rate;
                        block.well_flow_rate = well.specified_flow_rate;
                        block.specified_BHP  = well.specified_BHP;
                        block.skin           = well.skin;
                        block.rw             = well.rw;
                        double well_geometric_factor = Well.getGeometricFactor(block);
                        block.well_geometric_factor = well_geometric_factor;
                        block.well_transmissibility = Well.getTransmissibility(block, well_geometric_factor, Well.Phase.Water);
                    }
                    //specified BHP wells
                    else
                    {
                        block.well_type = GridBlock.WellType.Specified_BHP;
                        block.BHP       = well.specified_BHP;
                        block.rw        = well.rw;
                        block.skin      = well.skin;
                        double well_geometric_factor = Well.getGeometricFactor(block);
                        block.well_geometric_factor = well_geometric_factor;
                        block.well_transmissibility = Well.getTransmissibility(block, well_geometric_factor, Well.Phase.Water);
                    }
                }
            }

            #region calculate the geometric factors of a heterogeneous grid
            if (!homogeneous)
            {
                var direction_x = Transmissibility.Direction.x;
                var direction_y = Transmissibility.Direction.y;
                int x_counter   = 0;
                int y_counter   = 0;
                //int z_counter = 0;

                for (int i = 0; i < grid.Length; i++)
                {
                    block = grid[i];

                    if (x > 1)
                    {
                        x_counter = block.east_counter != -1 ? block.east_counter : block.west_counter;

                        block.GF_x = x_counter != -1 ? Transmissibility.getGeometricFactor(block, grid[x_counter], grid_type, direction_x) : 0;
                    }
                    if (y > 1)
                    {
                        y_counter = block.north_counter != -1 ? block.north_counter : block.south_counter;

                        block.GF_y = y_counter != -1 ? Transmissibility.getGeometricFactor(block, grid[y_counter], grid_type, direction_y) : 0;
                    }
                }
            }
            #endregion

            #endregion

            #region Output
            SinglePhase.OutPut2D output = new SinglePhase.OutPut2D(grid, grid_dimensions, data.what, data.where, compressibility, data.file_name, data.formatted, data.single_file, inactive_blocks);
            #endregion

            #region Choose Solver
            if (compressibility == TypeDefinitions.Compressibility.Incompressible)
            {
                SolverSinglePhase.incompressible(grid, output);
            }
            else if (compressibility == TypeDefinitions.Compressibility.Slightly_Compressible)
            {
                SolverSinglePhase.slightly_compressible(grid, delta_t, time_max, output, pvt);
            }
            else
            {
                SolverSinglePhase.compressible(grid, delta_t, time_max, convergence_pressure, output, pvt);
            }
            #endregion
        }