diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..344b91d --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +*.txt +*.err +*.rat +*.tsl +*.wel +*.out +*.log +*.exe* +*.dll* +*.htm* +*.obj +*.pch* +*.dep +*.idb +*.pdb +*.pyc +*.rst +*.ncb +*.suo +*.user +*.orig +blue-sky +*.dblite +.debug +.release +*.os +*.obj +*.png +*.csv +callgrind* +tags diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3a7974a --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2009, The BS Eagle Project. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the BS Eagle Project nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/README b/README new file mode 100644 index 0000000..2c751c8 --- /dev/null +++ b/README @@ -0,0 +1,30 @@ +BS Eagle black-oil simulator + +The BS Eagle Project (bs-eagle) is an open source black-oil simulator. +The main goal of this project is to provide a free access to the state +of the art oil simulation software to study new methods of oil's +simulation. + +The project based on a BlueSky integration platform and +has a modular architecture and open to modifications and extensions. + +Current available plugins are: + - linear solvers (gmres, cgs, tfqmr, bicgstab, csr_ilu_prec) + - data storages (hdf5) + - grids (ijk, eclipse) + - wells (full implicit black oil model) + - jacobian's fillers + - array arithmetics + +To build bs-eagle you need: + 1. BlueSky kernel + 2. Python 2.5 + 3. SCons (or MS Visual Studio 2005) + 4. Boost library, recomended version is 1.39 + 5. Loki library, recomended version 0.1.6 + 6. HDF5 library, recomnded version 1.8.3 + 6.1. SZIP, recomnded version 2.1 + 6.2. ZLIB, recomnded version 1.2 + +Example of BlueSky BuildSystem script placed at +examples/scons_env.custom and examples/scons_vars.custom. diff --git a/SConscript b/SConscript new file mode 100644 index 0000000..10a2238 --- /dev/null +++ b/SConscript @@ -0,0 +1,9 @@ +SConscript ("bs_bos_core_base/SConscript.bs") +SConscript ("bs_matrix/SConscript.bs") +SConscript ("bs_base_linear_solvers/SConscript.bs") +SConscript ("bs_csr_ilu_prec/SConscript.bs") +SConscript ("bs_bos_core_data_storage/SConscript.bs") +SConscript ("bs_mesh/SConscript.bs") +SConscript ("bs_scal/SConscript.bs") +SConscript ("bs_pvt/SConscript.bs") +SConscript ("bs_bos_core/SConscript.bs") diff --git a/all.sln b/all.sln new file mode 100644 index 0000000..46703df --- /dev/null +++ b/all.sln @@ -0,0 +1,295 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_bos_core", "bs_bos_core\bs_bos_core.vcproj", "{B096BE31-726C-42A6-AFB0-C6BADE241F0D}" + ProjectSection(ProjectDependencies) = postProject + {6179CF48-524A-4031-993A-FD353AD2A74F} = {6179CF48-524A-4031-993A-FD353AD2A74F} + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652} = {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652} + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} = {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} + {952339F0-0C05-440C-8168-A8C2C463D3AE} = {952339F0-0C05-440C-8168-A8C2C463D3AE} + {CE770FDD-686B-48FB-9DFA-B660196BEF89} = {CE770FDD-686B-48FB-9DFA-B660196BEF89} + {0EE477D9-9766-4B63-A50F-6778116CF649} = {0EE477D9-9766-4B63-A50F-6778116CF649} + {578A43D7-0338-4ED0-A455-666FDA782085} = {578A43D7-0338-4ED0-A455-666FDA782085} + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C} = {AAF02BD1-4A63-428B-8FC3-275C2ED1337C} + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81} = {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81} + {25D48348-7171-4ED5-8AE9-166C23CAC051} = {25D48348-7171-4ED5-8AE9-166C23CAC051} + {E7322907-2C9C-4570-A99E-A2F3E56A3D57} = {E7322907-2C9C-4570-A99E-A2F3E56A3D57} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blue-sky", "..\..\kernel\blue-sky.vcproj", "{7C235C2A-609A-49B4-A89B-AC23530F0F89}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bspy_loader", "..\..\python\bspy_loader\bspy_loader.vcproj", "{5FC52CB5-D666-4608-A354-81E3B5DE6035}" + ProjectSection(ProjectDependencies) = postProject + {7C235C2A-609A-49B4-A89B-AC23530F0F89} = {7C235C2A-609A-49B4-A89B-AC23530F0F89} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_matrix", "bs_matrix\bs_matrix.vcproj", "{AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}" + ProjectSection(ProjectDependencies) = postProject + {578A43D7-0338-4ED0-A455-666FDA782085} = {578A43D7-0338-4ED0-A455-666FDA782085} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_base_linear_solvers", "bs_base_linear_solvers\bs_base_linear_solvers.vcproj", "{0EE477D9-9766-4B63-A50F-6778116CF649}" + ProjectSection(ProjectDependencies) = postProject + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} = {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_bos_core_base", "bs_bos_core_base\bs_bos_core_base.vcproj", "{578A43D7-0338-4ED0-A455-666FDA782085}" + ProjectSection(ProjectDependencies) = postProject + {5FC52CB5-D666-4608-A354-81E3B5DE6035} = {5FC52CB5-D666-4608-A354-81E3B5DE6035} + {7C235C2A-609A-49B4-A89B-AC23530F0F89} = {7C235C2A-609A-49B4-A89B-AC23530F0F89} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_amg_solver", "..\bs_amg_solver\bs_amg_solver.vcproj", "{952339F0-0C05-440C-8168-A8C2C463D3AE}" + ProjectSection(ProjectDependencies) = postProject + {0EE477D9-9766-4B63-A50F-6778116CF649} = {0EE477D9-9766-4B63-A50F-6778116CF649} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_cpr_prec", "..\bs_cpr_prec\bs_cpr_prec.vcproj", "{25D48348-7171-4ED5-8AE9-166C23CAC051}" + ProjectSection(ProjectDependencies) = postProject + {952339F0-0C05-440C-8168-A8C2C463D3AE} = {952339F0-0C05-440C-8168-A8C2C463D3AE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_csr_ilu_prec", "bs_csr_ilu_prec\bs_csr_ilu_prec.vcproj", "{AAF02BD1-4A63-428B-8FC3-275C2ED1337C}" + ProjectSection(ProjectDependencies) = postProject + {0EE477D9-9766-4B63-A50F-6778116CF649} = {0EE477D9-9766-4B63-A50F-6778116CF649} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_mesh", "bs_mesh\bs_mesh.vcproj", "{CE770FDD-686B-48FB-9DFA-B660196BEF89}" + ProjectSection(ProjectDependencies) = postProject + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81} = {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_bos_core_data_storage", "bs_bos_core_data_storage\bs_bos_core_data_storage.vcproj", "{3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}" + ProjectSection(ProjectDependencies) = postProject + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} = {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} + {578A43D7-0338-4ED0-A455-666FDA782085} = {578A43D7-0338-4ED0-A455-666FDA782085} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_pvt", "bs_pvt\bs_pvt.vcproj", "{32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}" + ProjectSection(ProjectDependencies) = postProject + {6179CF48-524A-4031-993A-FD353AD2A74F} = {6179CF48-524A-4031-993A-FD353AD2A74F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_scal", "bs_scal\bs_scal.vcproj", "{6179CF48-524A-4031-993A-FD353AD2A74F}" + ProjectSection(ProjectDependencies) = postProject + {578A43D7-0338-4ED0-A455-666FDA782085} = {578A43D7-0338-4ED0-A455-666FDA782085} + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} = {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_mswell", "..\bs_mswell\bs_mswell\bs_mswell.vcproj", "{F73A1821-6C19-451F-A1DF-D4A4862D5E1F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_hdf5_storage", "..\bs_hdf5_storage\bs_hdf5_storage.vcproj", "{E7322907-2C9C-4570-A99E-A2F3E56A3D57}" + ProjectSection(ProjectDependencies) = postProject + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} = {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs_mesh_mpfa", "..\bs_mesh_mpfa\bs_mesh_mpfa.vcproj", "{9A036071-A4DB-4609-9B59-727AA3D49B24}" + ProjectSection(ProjectDependencies) = postProject + {CE770FDD-686B-48FB-9DFA-B660196BEF89} = {CE770FDD-686B-48FB-9DFA-B660196BEF89} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_HDF5|Win32 = Debug_HDF5|Win32 + Debug_MPI|Win32 = Debug_MPI|Win32 + Debug|Win32 = Debug|Win32 + Release_HDF5|Win32 = Release_HDF5|Win32 + release_with_debug|Win32 = release_with_debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Debug_HDF5|Win32.ActiveCfg = Debug_HDF5|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Debug_HDF5|Win32.Build.0 = Debug_HDF5|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Debug_MPI|Win32.ActiveCfg = Debug_MPI|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Debug_MPI|Win32.Build.0 = Debug_MPI|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Debug|Win32.Build.0 = Debug|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Release_HDF5|Win32.ActiveCfg = Release_HDF5|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Release_HDF5|Win32.Build.0 = Release_HDF5|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.release_with_debug|Win32.Build.0 = Release|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Release|Win32.ActiveCfg = Release|Win32 + {B096BE31-726C-42A6-AFB0-C6BADE241F0D}.Release|Win32.Build.0 = Release|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Debug|Win32.ActiveCfg = Debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Debug|Win32.Build.0 = Debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Release_HDF5|Win32.Build.0 = Release|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.release_with_debug|Win32.ActiveCfg = release_with_debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.release_with_debug|Win32.Build.0 = release_with_debug|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Release|Win32.ActiveCfg = Release|Win32 + {7C235C2A-609A-49B4-A89B-AC23530F0F89}.Release|Win32.Build.0 = Release|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Debug|Win32.ActiveCfg = Debug|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Debug|Win32.Build.0 = Debug|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Release_HDF5|Win32.Build.0 = Release|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.release_with_debug|Win32.Build.0 = Release|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Release|Win32.ActiveCfg = Release|Win32 + {5FC52CB5-D666-4608-A354-81E3B5DE6035}.Release|Win32.Build.0 = Release|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Debug|Win32.ActiveCfg = Debug|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Debug|Win32.Build.0 = Debug|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Release_HDF5|Win32.Build.0 = Release|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.release_with_debug|Win32.Build.0 = Release|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Release|Win32.ActiveCfg = Release|Win32 + {AAB3AFFB-CBD4-4367-BFA2-76C656498E6D}.Release|Win32.Build.0 = Release|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Debug|Win32.ActiveCfg = Debug|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Debug|Win32.Build.0 = Debug|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Release_HDF5|Win32.Build.0 = Release|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.release_with_debug|Win32.Build.0 = Release|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Release|Win32.ActiveCfg = Release|Win32 + {0EE477D9-9766-4B63-A50F-6778116CF649}.Release|Win32.Build.0 = Release|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Debug|Win32.ActiveCfg = Debug|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Debug|Win32.Build.0 = Debug|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Release_HDF5|Win32.Build.0 = Release|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.release_with_debug|Win32.Build.0 = Release|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Release|Win32.ActiveCfg = Release|Win32 + {578A43D7-0338-4ED0-A455-666FDA782085}.Release|Win32.Build.0 = Release|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Debug|Win32.ActiveCfg = Debug|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Debug|Win32.Build.0 = Debug|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Release_HDF5|Win32.Build.0 = Release|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.release_with_debug|Win32.Build.0 = Release|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Release|Win32.ActiveCfg = Release|Win32 + {952339F0-0C05-440C-8168-A8C2C463D3AE}.Release|Win32.Build.0 = Release|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Debug|Win32.ActiveCfg = Debug|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Debug|Win32.Build.0 = Debug|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Release_HDF5|Win32.Build.0 = Release|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.release_with_debug|Win32.Build.0 = Release|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Release|Win32.ActiveCfg = Release|Win32 + {25D48348-7171-4ED5-8AE9-166C23CAC051}.Release|Win32.Build.0 = Release|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Debug|Win32.ActiveCfg = Debug|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Debug|Win32.Build.0 = Debug|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Release_HDF5|Win32.Build.0 = Release|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.release_with_debug|Win32.Build.0 = Release|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Release|Win32.ActiveCfg = Release|Win32 + {AAF02BD1-4A63-428B-8FC3-275C2ED1337C}.Release|Win32.Build.0 = Release|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Debug|Win32.ActiveCfg = Debug|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Debug|Win32.Build.0 = Debug|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Release_HDF5|Win32.Build.0 = Release|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.release_with_debug|Win32.Build.0 = Release|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Release|Win32.ActiveCfg = Release|Win32 + {CE770FDD-686B-48FB-9DFA-B660196BEF89}.Release|Win32.Build.0 = Release|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Debug|Win32.ActiveCfg = Debug|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Debug|Win32.Build.0 = Debug|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Release_HDF5|Win32.Build.0 = Release|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.release_with_debug|Win32.Build.0 = Release|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Release|Win32.ActiveCfg = Release|Win32 + {3DF8BD9D-CAEF-4081-A1C2-B624E0959A81}.Release|Win32.Build.0 = Release|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Debug|Win32.ActiveCfg = Debug|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Debug|Win32.Build.0 = Debug|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Release_HDF5|Win32.Build.0 = Release|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.release_with_debug|Win32.Build.0 = Release|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Release|Win32.ActiveCfg = Release|Win32 + {32C5BEFC-9E7D-4341-ACD4-DDDCFEB77652}.Release|Win32.Build.0 = Release|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Debug|Win32.ActiveCfg = Debug|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Debug|Win32.Build.0 = Debug|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Release_HDF5|Win32.Build.0 = Release|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.release_with_debug|Win32.Build.0 = Release|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Release|Win32.ActiveCfg = Release|Win32 + {6179CF48-524A-4031-993A-FD353AD2A74F}.Release|Win32.Build.0 = Release|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Debug|Win32.ActiveCfg = Debug|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Debug|Win32.Build.0 = Debug|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.release_with_debug|Win32.Build.0 = Release|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Release|Win32.ActiveCfg = Release|Win32 + {F73A1821-6C19-451F-A1DF-D4A4862D5E1F}.Release|Win32.Build.0 = Release|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Debug|Win32.ActiveCfg = Debug|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Debug|Win32.Build.0 = Debug|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Release_HDF5|Win32.Build.0 = Release|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.release_with_debug|Win32.Build.0 = Release|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Release|Win32.ActiveCfg = Release|Win32 + {E7322907-2C9C-4570-A99E-A2F3E56A3D57}.Release|Win32.Build.0 = Release|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Debug_HDF5|Win32.ActiveCfg = Debug|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Debug_HDF5|Win32.Build.0 = Debug|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Debug_MPI|Win32.ActiveCfg = Debug|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Debug_MPI|Win32.Build.0 = Debug|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Debug|Win32.ActiveCfg = Debug|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Debug|Win32.Build.0 = Debug|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Release_HDF5|Win32.ActiveCfg = Release|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Release_HDF5|Win32.Build.0 = Release|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.release_with_debug|Win32.ActiveCfg = Release|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.release_with_debug|Win32.Build.0 = Release|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Release|Win32.ActiveCfg = Release|Win32 + {9A036071-A4DB-4609-9B59-727AA3D49B24}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/bs_base_linear_solvers/SConscript.bs b/bs_base_linear_solvers/SConscript.bs new file mode 100644 index 0000000..5e1e9a0 --- /dev/null +++ b/bs_base_linear_solvers/SConscript.bs @@ -0,0 +1,28 @@ +import os +Import ("*") + +lib_name = "bs_base_linear_solvers" +tar_name = "bs_base_linear_solvers" + +env = custom_env.Clone () +env.Append (CPPPATH = ["include", + includes["bs_bos_core_base"], + includes["bs_matrix"] + ] + includes["kernel"]) + +libs = ["blue_sky", "bs_bos_core_base", "bs_matrix"] + +if (build_kind == "debug") : + env.AppendUnique (LIBS = list_suffix (libs, "_d")) + lib_name += "_d" +elif (build_kind == "release") : + env.AppendUnique (LIBS = libs) + +bs_base_linear_solvers = env.SharedLibrary (target = os.path.join (tar_exe_plugin_dir, lib_name), source = files (["."]).sources) + +env.Alias (tar_name, bs_base_linear_solvers) +Export ("bs_base_linear_solvers") + +if (env["install"] == 1) : + inst_tar = env.Install ("$plugins_prefix", bs_base_linear_solvers) + env.Alias (tar_name, inst_tar) diff --git a/bs_base_linear_solvers/bs_base_linear_solvers.vcproj b/bs_base_linear_solvers/bs_base_linear_solvers.vcproj new file mode 100644 index 0000000..d064b69 --- /dev/null +++ b/bs_base_linear_solvers/bs_base_linear_solvers.vcproj @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bs_base_linear_solvers/include/bs_base_linear_solvers_stdafx.h b/bs_base_linear_solvers/include/bs_base_linear_solvers_stdafx.h new file mode 100644 index 0000000..05f41ea --- /dev/null +++ b/bs_base_linear_solvers/include/bs_base_linear_solvers_stdafx.h @@ -0,0 +1,87 @@ +/** +* \file stdafx.h +* \brief precompiled header +* \author Sergey Miryanov +* */ +#ifndef BS_BASE_LINEAR_SOLVERS_PRECOMPILED_HEADERS_H_ +#define BS_BASE_LINEAR_SOLVERS_PRECOMPILED_HEADERS_H_ + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#ifndef UNIX +#include +#else +#include +#endif + +#include + +#include + +#include "bs_common.h" +#include BS_FORCE_PLUGIN_IMPORT () +#include "smart_ptr.h" +#include "bs_kernel.h" +#include "bs_link.h" +#include "bs_object_base.h" +#include "bs_tree.h" +#include "bs_exception.h" +#include "bs_prop_base.h" +#include BS_STOP_PLUGIN_IMPORT () + +#ifdef BSPY_EXPORTING_PLUGIN +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include BS_FORCE_PLUGIN_IMPORT () +#include "bs_plugin_common.h" +#include "py_bs_object_base.h" +#include "py_bs_command.h" +#include "py_bs_tree.h" +#include BS_STOP_PLUGIN_IMPORT () +#endif + +#include BS_FORCE_PLUGIN_IMPORT () +#include "force_inline.h" +#include "bs_assert.h" +#include "bos_report.h" + +#include "aligned_allocator.h" +#include "strategies.h" + +#include "omp_tools.h" +#include "mv_tools.h" + +#include "py_bcsr_matrix.h" +#include "write_time_to_log.h" +#include "dummy_base.h" +#include "named_pbase_access.h" +#include "throw_exception.h" +#include BS_STOP_PLUGIN_IMPORT () + +#endif // #ifndef BS_BASE_LINEAR_SOLVERS_PRECOMPILED_HEADERS_H_ diff --git a/bs_base_linear_solvers/include/cgs.h b/bs_base_linear_solvers/include/cgs.h new file mode 100644 index 0000000..523519c --- /dev/null +++ b/bs_base_linear_solvers/include/cgs.h @@ -0,0 +1,82 @@ +/** + * \file cgs.h + * \brief CGS linear solver + * \author SalimgareevaEM + * \date + * */ +#ifndef BS_CGS_LINEAR_SOLVER_H_ +#define BS_CGS_LINEAR_SOLVER_H_ + +#include "linear_solvers.h" + +namespace blue_sky + { + /** + * @brief CGS linear solver + */ + template + class BS_API_PLUGIN cgs_solver : public linear_solver_base + { + + //----------------------------------------- + // TYPES + //----------------------------------------- + public: + typedef typename strategy_t::matrix_t matrix_t; ///< short name to matrix type + typedef typename strategy_t::item_array_t item_array_t; ///< short name to array type + typedef typename strategy_t::item_t item_t; ///< short name to array item type + typedef typename strategy_t::index_t index_t; ///< short name to matrix's index type + typedef typename strategy_t::rhs_item_t rhs_item_t; ///< short name for type of rhs + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; ///< short name for rhs array type + + + typedef typename strategy_t::matrix_array_t matrix_array_t; ///< short name to matrix array type + + typedef typename strategy_t::index_array_t index_array_t; + + typedef linear_solver_base this_t; ///< typedef to this type + typedef linear_solver_base base_t; ///< typedef to this type. in child classes used as a short name of base class + typedef smart_ptr sp_this_t; ///< short name to smart pointer to this class + typedef smart_ptr sp_prop_t; ///< short name to smart pointer to properties holder class + + typedef smart_ptr sp_matrix_t; ///< short name to smart pointer on matrix_t + + typedef bcsr_matrix bcsr_matrix_t; ///< short name for used matrix + typedef smart_ptr sp_bcsr_matrix_t; ///< short name for smart_pointer on used matrix + + //----------------------------------------- + // METHODS + //----------------------------------------- + public: + //! destructor + virtual ~cgs_solver (); + + //! solve + virtual int solve (matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &sol); + + virtual int solve_prec (matrix_t *matrix, item_array_t &rhs, item_array_t &sol); + + //! setup + virtual int setup (matrix_t *matrix); + + //template + //int init_by_matrix (const mx_t *mx); + + template + int + templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &sol); + + private: + //----------------------------------------- + // VARIABLES + //----------------------------------------- + public: + + public: + BLUE_SKY_TYPE_DECL (cgs_solver); + }; + + } // namespace blue_sky + +#endif // #ifndef BS_CGS_LINEAR_SOLVER_H_ + diff --git a/bs_base_linear_solvers/include/lin_solv_macro.h b/bs_base_linear_solvers/include/lin_solv_macro.h new file mode 100644 index 0000000..2659790 --- /dev/null +++ b/bs_base_linear_solvers/include/lin_solv_macro.h @@ -0,0 +1,169 @@ +/** + * \file lin_solv_macro.h + * \brief + * \author + * \date + * */ +#ifndef BS_LIN_SOLV_MACRO_H_ +#define BS_LIN_SOLV_MACRO_H_ + +namespace blue_sky + { + /** + * @brief sum vector + * + * @param A -- first vector + * @param B -- second vector + * @param alpha -- first scalar + * @param beta -- second scalar + * @param RES -- result vector + * @param I -- index + * @param N -- vector length + + * + * @return nothing + */ + #define SUM_VECTOR(A,B,alpha,beta,RES,I,N) \ + for ((I) = 0; (I) < (N); ++(I)) \ + (RES)[(I)] = alpha*(A)[(I)] + beta*(B)[(I)]; + + template + inline void sum_vector (vector_t &x, typename vector_t::value_type alpha, vector_t &y, typename vector_t::value_type beta, vector_t &res) + { + //int i = 0, cnt = (int)a.size (); + + #ifdef GMRES_SOLVER2_SOLVE_PARALLEL + #pragma omp parallel for + #endif + BS_ASSERT (x.size ()); + BS_ASSERT (y.size ()); + BS_ASSERT (res.size ()); + BS_ASSERT (x.size () == y.size ()); + BS_ASSERT (x.size () == res.size ()); + + size_t i = 0, cnt = x.size (); + + for (i = 0; i < cnt; ++i) + { + res[i] = alpha * x[i] + beta * y[i]; + } + } + + + + + /** + * @brief scale vector + * + * @param A -- vector + * @param T -- scale factor + * @param I -- index + * @param N -- vector length + * + * @return nothing + */ + #define SCALE_VECTOR(A,T,I,N) \ + for ((I) = 0; (I) < (N); ++(I)) \ + (A)[(I)] *= (T); + + // if we got performance decrease we have to specify macroses for seq and mpi separately + // used only in gmres_solver2 + template + inline void scale_vector (vector_t &a, typename vector_t::value_type t) + { + int i = 0, cnt = (int)a.size (); + + #ifdef GMRES_SOLVER2_SOLVE_PARALLEL + #pragma omp parallel for + #endif + for (i = 0; i < cnt; ++i) + { + a[i] *= t; + } + } + + /** + * @brief AXPY (X = X + T * Y) + * + * @param X -- vector + * @param T -- scale factor + * @param Y -- vector + * @param I -- index + * @param N -- vectors length + * + * @return nothing + */ + #define AXPY(X,T,Y,I,N) \ + for ((I) = 0; (I) < (N); ++(I)) \ + (X)[(I)] += (T) * (Y)[(I)]; + + // if we get performance decrease we have to specify macroses for seq and mpi separately + // used only in gmres_solver2 + template + inline void axpy (vector_t &x, const vector_t &y, typename vector_t::value_type t) + { + BS_ASSERT (x.size () == y.size ()); + BS_ASSERT (x.size ()); + + size_t i = 0, cnt = x.size (); + const size_t unroll_factor = 8; + size_t cnt2 = cnt - (cnt % unroll_factor); + + #ifdef GMRES_SOLVER2_SOLVE_PARALLEL + #pragma omp parallel for + #endif + for (i = 0; i < cnt2; i += unroll_factor) + { + x[i] += t * y[i]; + x[i + 1] += t * y[i + 1]; + x[i + 2] += t * y[i + 2]; + x[i + 3] += t * y[i + 3]; + x[i + 4] += t * y[i + 4]; + x[i + 5] += t * y[i + 5]; + x[i + 6] += t * y[i + 6]; + x[i + 7] += t * y[i + 7]; + } + for (; i < cnt; ++i) + { + x[i] += t * y[i]; + } + } + + /** + * @brief AXPY_AYPX // X = Z + P * (X + T * Y) + * + * @param X -- vector + * @param T -- scale factor + * @param Y -- vector + * @param P -- scale factor + * @param Z -- vector + * @param I -- index + * @param N -- vectors length + * + * @return nothing + */ + #define AXPY_AYPX(X,T,Y,P,Z,I,N) \ + for ((I) = 0; (I) < (N); ++(I)) \ + (X)[(I)] = (Z)[(I)] + (P) * ((X)[(I)] + (T) * (Y)[(I)]); + + template inline void + axpy_aypx (vector_t &x, typename vector_t::value_type t, const vector_t &y, typename vector_t::value_type p, const vector_t &z) + { + BS_ASSERT (x.size ()); + BS_ASSERT (y.size ()); + BS_ASSERT (z.size ()); + BS_ASSERT (x.size () == y.size ()); + BS_ASSERT (x.size () == z.size ()); + + size_t i = 0, cnt = x.size (); + + for (i = 0; i < cnt; ++i) + { + x[i] = z[i] + p * (x[i] + t * y[i]); + } + } + + } // end namespace + +#endif // #ifndef BS_LIN_SOLV_MACRO_H_ + diff --git a/bs_base_linear_solvers/include/linear_solvers.h b/bs_base_linear_solvers/include/linear_solvers.h new file mode 100644 index 0000000..c355beb --- /dev/null +++ b/bs_base_linear_solvers/include/linear_solvers.h @@ -0,0 +1,443 @@ +#ifndef LIN_SOLVER__H +#define LIN_SOLVER__H +/*! +* \file linear_solvers.h +* \brief linear solvers declaration +* \author Borschuk Oleg +* \date 2006-07-26 +*/ + +#include BS_FORCE_PLUGIN_IMPORT () +#include "bcsr_matrix.h" +#include "named_pbase_access.h" +#include "bos_report.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + /** + * \brief properties for linear solvers + */ + class BS_API_PLUGIN linear_solver_prop : public named_pbase + { + typedef property_base base_t; ///< short name for base class + + public: + typedef double fp_type_t; ///< short name for used floating point type + + //----------------------------------------- + // METHODS + //----------------------------------------- + public: + //! destructor + virtual ~linear_solver_prop (); + + //! set maximum number of iterations + int set_max_iters (int n_iters); + + //! set tolerance + void set_tolerance (fp_type_t new_tol) + { + if (new_tol > 10e-16) + set_param(FP_TOLERANCE,(fp_type_t)new_tol); + } + + //! set tolerance + void set_matbal_tolerance (fp_type_t new_tol) + { + if (new_tol > 10e-16) + set_param(FP_MATBAL_TOLERANCE,(fp_type_t)new_tol); + } + + //! set number of iters + void set_iters (int n_iters) + { + set_param(I_ITERS,n_iters); + } + + //! set successively converged flag + void set_success (int success) + { + set_param(I_SUCCESS,success); + } + + //! set final resid + void set_final_resid (fp_type_t final_resid) + { + set_param(FP_FINAL_RESID,(fp_type_t)final_resid); + } + + //! set relative factor + void set_relative_factor (fp_type_t relative_factor) + { + set_param(FP_RELATIVE_FACTOR,(fp_type_t)relative_factor); + } + + //! return != 0 if method successfully converged + int check_convergence () const + { + return get_int(I_SUCCESS); + } + + //! return number of iteration + int get_iters () const + { + return get_int(I_ITERS); + } + + //! return relative residual denominator + fp_type_t get_relative_factor () const + { + return get_float(FP_RELATIVE_FACTOR); + } + + //! return maximum allowed number of iterations + int get_max_iters () const + { + return get_int(I_MAX_ITERS); + } + + //! return tolerance + fp_type_t get_tolerance () const + { + return get_float(FP_TOLERANCE); + } + + //! get successively converged flag + int get_success () const + { + return get_int(I_SUCCESS); + } + + //! get final resid + fp_type_t get_final_resid () const + { + return get_float(FP_FINAL_RESID); + } + + //----------------------------------------- + // VARIABLES + //----------------------------------------- + public: + PROP_BASE_IDX_DECL_BEGIN(linear_solver_prop,property_base) + FP_RELATIVE_FACTOR, //!< Parameter index: denominator for resid array to get relative residual + FP_TOLERANCE, //!< Parameter index: tolerance + FP_MATBAL_TOLERANCE, + FP_FINAL_RESID, // + FP_TOTAL, + I_ITERS, //!< Parameter index: number of iteration spend for convergence + I_MAX_ITERS, //!< Parameter index: maximum number of iteration + I_SUCCESS, //!< Parameter index: != 0 if successively converged + I_TOTAL, + LS_TOTAL, + PROP_BASE_IDX_DECL_END + + public: + BLUE_SKY_TYPE_DECL (linear_solver_prop); + PBASE_ACCESS_MS(linear_solver_prop) + + public: + virtual const std::string &get_params_name (idx_type idx); + }; + + /** + * \brief base interface class for linear solvers + */ + template + class BS_API_PLUGIN linear_solver_base : public bs_node + { + //----------------------------------------- + // TYPES + //----------------------------------------- + public: + typedef typename strategy_t::matrix_t matrix_t; ///< short name to matrix type + typedef typename strategy_t::item_t item_t; ///< short name to array item type (old array_item_t) + typedef typename strategy_t::index_t index_t; ///< short name to matrix's index type + typedef typename strategy_t::item_array_t item_array_t; ///< short name to array of items type (old array_t) + typedef typename strategy_t::index_array_t index_array_t; ///< short name to array type + typedef typename strategy_t::wksp_t wksp_t; + + typedef typename strategy_t::rhs_item_t rhs_item_t; ///< short name for type of rhs + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; ///< short name for rhs array type + + typedef linear_solver_base this_t; ///< typedef to this type + typedef linear_solver_base base_t; ///< typedef to this type. in child classes used as a short name of base class + typedef smart_ptr sp_this_t; ///< short name to smart pointer to this class + typedef smart_ptr sp_prop_t; ///< short name to smart pointer to properties holder class + + typedef smart_ptr sp_matrix_t; ///< short name for smart pointer on matrix + + typedef strategy_t strategy_type; + + //----------------------------------------- + // METHODS + //----------------------------------------- + public: + // constructor + linear_solver_base (bs_type_ctor_param param, bs_node::sp_node node); + // destructor + virtual ~linear_solver_base (); + + //! solve, used vectors to array + virtual int solve (matrix_t * /*matrix*/, typename strategy_t::rhs_item_array_t & /*rhs*/, typename strategy_t::item_array_t & /*sol*/) + { + BS_ASSERT (false && "PURE CALL"); + return 0; + } + + //! solve, used vectors to array + virtual int solve_prec (matrix_t * /*matrix*/, typename strategy_t::item_array_t & /*rhs*/, typename strategy_t::item_array_t & /*sol*/) + { + BS_ASSERT (false && "PURE CALL"); + return 0; + } + + //! setup + virtual int setup (matrix_t * /*matrix*/) + { + BS_ASSERT (false && "PURE CALL"); + return 0; + } + + //! set preconditioner + void set_prec (const this_t *new_prec) + { + prec = new_prec; + set_subnode_in_tree ("prec", sp_this_t (new_prec)); + } + + //! set solver's properties + void set_prop(const linear_solver_prop *new_prop) + { + prop = new_prop; + set_subnode_in_tree ("prop", sp_prop_t (new_prop)); + } + + //! get properties + sp_prop_t get_prop() const + { + return prop; + } + + protected: + + //! set subnode in tree by name + void set_subnode_in_tree (const std::string &name, const sp_obj &obj) + { + //bs_node::erase (name); + //bs_node::insert (obj, name, false); + } + + /** + * \brief Trait class for control of adding new nodes to solver + */ + struct solver_trait : bs_node::sort_traits + { + /** + * \brief Class for sorting sub nodes of solver node + */ + struct solver_key : bs_node::sort_traits::key_type + { + virtual bool sort_order (const key_ptr & ) const + { + return true; + } + }; + + virtual const char * sort_name () const + { + return "solver trait"; + }; + + virtual key_ptr key_generator (const sp_link& /*l*/) const + { + return new solver_key (); + } + + /** + * \brief Check passed parameter on accordance to allowed object types + * + * \param l Link on new object + * \return True if parameter allowed, false in other cases + */ + virtual bool accepts (const sp_link& l) + { + if (l->name() == "prec") + { + sp_this_t sp(l->data (), bs_dynamic_cast ()); + return sp; + } + else if (l->name() == "prop") + { + sp_prop_t sp (l->data (), bs_dynamic_cast ()); + return sp; + } + + return false; + } + }; + + private: + void init(); + + //----------------------------------------- + // VARIABLES + //----------------------------------------- + private: + + + protected: + wksp_t wksp; //!< workspace array + sp_this_t prec; //!< pointer to the preconditioner + sp_prop_t prop; //!< properties for solvers + + public: + BLUE_SKY_TYPE_DECL (linear_solver_base); + }; + + /** + * @brief GMRES linear solver + */ + template + class BS_API_PLUGIN gmres_solver2 : public linear_solver_base + { + //----------------------------------------- + // TYPES + //----------------------------------------- + public: + typedef typename strategy_t::matrix_t matrix_t; ///< short name to matrix type + typedef typename strategy_t::item_array_t item_array_t; ///< short name to array type + typedef typename strategy_t::item_t item_t; ///< short name to array item type + typedef typename strategy_t::index_t index_t; ///< short name to matrix's index type + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::barrier_t barrier_t; + + typedef typename strategy_t::rhs_item_t rhs_item_t; ///< short name for type of rhs + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; ///< short name for rhs array type + + typedef bcsr_matrix bcsr_matrix_t; ///< short name for used matrix + typedef smart_ptr sp_bcsr_matrix_t; ///< short name for smart_pointer on used matrix + + typedef linear_solver_base this_t; ///< typedef to this type + typedef linear_solver_base base_t; ///< typedef to this type. in child classes used as a short name of base class + typedef smart_ptr sp_this_t; ///< short name to smart pointer to this class + typedef smart_ptr sp_prop_t; ///< short name to smart pointer to properties holder class + + typedef smart_ptr sp_matrix_t; ///< short name to smart pointer on matrix_t + + //----------------------------------------- + // METHODS + //----------------------------------------- + public: + //! destructor + virtual ~gmres_solver2 (); + + //! solve + /*virtual int solve (matrix_t *matrix, typename strategy_t::item_array_t & rhs, + typename strategy_t::item_array_t & sol);*/ + + virtual int solve (matrix_t *matrix, rhs_item_array_t & rhs, + item_array_t & sol); + + virtual int solve_prec (matrix_t *matrix, item_array_t & rhs, + item_array_t & sol); + + template + int + templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &sol); + + //! setup + virtual int setup (matrix_t *matrix); + + private: + //----------------------------------------- + // VARIABLES + //----------------------------------------- + public: + int m; //!< number of directions to store + std::vector vec_p; + item_array_t vec_w; + item_array_t vec_r; + + public: + BLUE_SKY_TYPE_DECL (gmres_solver2); + }; + + + /** + * @brief BiCGStab linear solver + */ + template + class BS_API_PLUGIN bicgstab_solver : public linear_solver_base + { + + //----------------------------------------- + // TYPES + //----------------------------------------- + public: + typedef typename strategy_t::matrix_t matrix_t; ///< short name to matrix type + typedef typename strategy_t::item_array_t item_array_t; ///< short name to array type + typedef typename strategy_t::item_t item_t; ///< short name to array item type + typedef typename strategy_t::index_t index_t; ///< short name to matrix's index type + typedef typename strategy_t::matrix_array_t matrix_array_t; ///< short name to matrix array type + + typedef typename strategy_t::rhs_item_t rhs_item_t; ///< short name for type of rhs + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; ///< short name for rhs array type + + typedef typename strategy_t::index_array_t index_array_t; + + typedef linear_solver_base this_t; ///< typedef to this type + typedef linear_solver_base base_t; ///< typedef to this type. in child classes used as a short name of base class + typedef smart_ptr sp_this_t; ///< short name to smart pointer to this class + typedef smart_ptr sp_prop_t; ///< short name to smart pointer to properties holder class + + typedef smart_ptr sp_matrix_t; ///< short name to smart pointer on matrix_t + + typedef bcsr_matrix bcsr_matrix_t; ///< short name for used matrix + typedef smart_ptr sp_bcsr_matrix_t; ///< short name for smart_pointer on used matrix + + + //----------------------------------------- + // METHODS + //----------------------------------------- + public: + //! destructor + virtual ~bicgstab_solver (); + + //! solve + //virtual int solve (matrix_t *matrix, item_array_t &rhs, item_array_t &sol); + virtual int solve (matrix_t *matrix, rhs_item_array_t & rhs, + item_array_t & sol); + + virtual int solve_prec (matrix_t *matrix, item_array_t & rhs, + item_array_t & sol); + + template + int + templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &sol); + + + //! setup + virtual int setup (matrix_t *matrix); + + private: + //----------------------------------------- + // VARIABLES + //----------------------------------------- + public: + + public: + BLUE_SKY_TYPE_DECL (bicgstab_solver); + }; + + //! register linear_solver_prop into kernel + bool + linear_solver_prop_register_type (const blue_sky::plugin_descriptor &pd); + + //! register linear_solvers into kernel + bool + linear_solvers_register_type (const blue_sky::plugin_descriptor &pd); + +} // namespace blue_sky +#endif //__LIN_SOLVER__H diff --git a/bs_base_linear_solvers/include/lu_decomposition.h b/bs_base_linear_solvers/include/lu_decomposition.h new file mode 100644 index 0000000..c4714fc --- /dev/null +++ b/bs_base_linear_solvers/include/lu_decomposition.h @@ -0,0 +1,65 @@ +#ifndef __LU_DECOMPOSITION_H__ +#define __LU_DECOMPOSITION_H__ + + +/*! + \file lu_decomposition.h + \author Borschuk Oleg + \version 0.1 + \date 3.10.2004 + \brief file include declarations of functions to build LU decomposition and to solve matrix + + +---+----------------+ matrix is an array of double where elements stored + |***|****************| by strings + |***|block_size******| |a(0,0) a(0,1) a(0,2)| + +---+----------------+ matrix_size |a(1,0) a(1,1) a(1,2)| => + |**block_string******| |a(2,0) a(2,1) a(2,2)| + |********************| + |********************| => {a(0,0) a(0,1) a(0,2) a(1,0) a(1,1) a(1,2) ...} + +--------------------+ +*/ + +//! minimum for devision +#define MIN_DIV 1.0e-24 + +//! default block size +#define DEF_BLOCK_SIZE 60 + +template +struct BS_API_PLUGIN lu_tools + { + // build LU decomposition for matrix block + static i_type lu_block_decomposition (i_type matrix_size, fp_type *block, i_type block_size = 0); + + // find y in Ly = b + static i_type lu_block_find_L_roots (i_type matrix_size, fp_type *block, fp_type *r_side, i_type block_size = 0); + + // find x in Ux = y + static i_type lu_block_find_U_roots (i_type matrix_size, fp_type *block, fp_type *r_side, i_type block_size = 0); + + // find U in LU = A using known L + static i_type lu_block_find_U (i_type matrix_size, fp_type *block_L, fp_type *block_U, i_type block_size, i_type ncol); + + // find L in LU = A using known U + static i_type lu_block_find_L (i_type matrix_size, fp_type *block_L, fp_type *block_U, i_type block_size, i_type nrow); + + // upgrade block + static i_type lu_block_upgrade (i_type matrix_size, fp_type *block_A, fp_type *block_L, + fp_type *block_U, i_type block_size, i_type nrow, i_type ncol); + + // build lu decomposition using block method on one thread + static i_type lu_decomposition (i_type matrix_size, fp_type *matrix, i_type block_size = DEF_BLOCK_SIZE); + + // update right side + static i_type lu_upgrade_right_side (i_type matrix_size, fp_type *block, i_type nrow, i_type ncol, + fp_type *roots, fp_type *r_side); + // find y in Ly = b + static i_type lu_find_L_roots (i_type matrix_size, fp_type *matrix, fp_type *r_side, + i_type block_size = DEF_BLOCK_SIZE); + + // find x in Ux = y + static i_type lu_find_U_roots (i_type matrix_size, fp_type *matrix, fp_type *r_side, + i_type block_size = DEF_BLOCK_SIZE); + }; + +#endif //__LU_DECOMPOSITION_H__ diff --git a/bs_base_linear_solvers/include/py_linear_solvers.h b/bs_base_linear_solvers/include/py_linear_solvers.h new file mode 100644 index 0000000..97655d4 --- /dev/null +++ b/bs_base_linear_solvers/include/py_linear_solvers.h @@ -0,0 +1,116 @@ +/** + * \file py_linear_solvers.h + * \brief Python wrapper for linear solvers + * \author Miryanov Sergey + * \date 2008-04-04 + */ + +#ifndef BS_LINEAR_SOLVERS_PYTHON_H +#define BS_LINEAR_SOLVERS_PYTHON_H + +#include "strategies.h" +#include "linear_solvers.h" +#include "cgs.h" +#include "tfqmr.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "py_bcsr_matrix.h" +#include "write_time_to_log.h" +#include "dummy_base.h" +#include "construct_python_object.h" +#include "make_me_happy.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "export_python_wrapper.h" + +#ifdef BSPY_EXPORTING_PLUGIN +namespace blue_sky { +namespace python { + + /** + * \brief python wrapper for most linear solvers + */ + STRATEGY_CLASS_WRAPPER (linear_solver_base, py_linear_solver) + { + public: + typedef linear_solver_base linear_solver_base_t; + + typedef typename strategy_t::matrix_t matrix_t; ///< short name for matrix type from wrapped type + typedef typename strategy_t::item_array_t item_array_t; ///< short name for array type from wrapped type + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; ///< short name for type of rhs + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; ///< short name for rhs array type + + typedef py_matrix_base py_matrix_t; + + typedef smart_ptr sp_linear_solver_base_t; + typedef smart_ptr sp_prec_t; ///< short name to smart pointer to this class + typedef smart_ptr sp_prop_t; ///< short name to smart pointer to properties holder class + + typedef linear_solver_base_t wrapped_t; + typedef py_linear_solver_base base_t; + + public: + + STRATEGY_CLASS_WRAPPER_DECL (py_linear_solver); + + WRAPPER_METHOD_R (setup, int, 1, (matrix_t *)); + WRAPPER_METHOD_R (solve, int, 3, (matrix_t *, rhs_item_array_t &, item_array_t &)); + WRAPPER_METHOD_R (solve_prec, int, 3, (matrix_t *, item_array_t &, item_array_t &)); + + void + init_object (linear_solver_base_t *solver) + { + solver_ = sp_linear_solver_base_t (solver); + } + + private: + + sp_linear_solver_base_t solver_; + }; + +#define WRAP_STD_SOLVER(name_, py_name_) \ + STRATEGY_CLASS_WRAPPER (name_, py_name_) \ + { \ + public: \ + \ + typedef typename strategy_t::matrix_t matrix_t; \ + typedef typename strategy_t::item_array_t item_array_t; \ + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; \ + \ + typedef name_ wrapped_t; \ + typedef BOOST_PP_CAT (py_name_, _base) base_t; \ + \ + public: \ + \ + STRATEGY_CLASS_WRAPPER_DECL (py_name_); \ + \ + WRAPPER_METHOD_R (setup, int, 1, (matrix_t *)); \ + WRAPPER_METHOD_R (solve, int, 3, (matrix_t *, rhs_item_array_t &, item_array_t &)); \ + WRAPPER_METHOD_R (solve_prec, int, 3, (matrix_t *, item_array_t &, item_array_t &)); \ + }; + + WRAP_STD_SOLVER (gmres_solver2, py_gmres_solver); + WRAP_STD_SOLVER (bicgstab_solver, py_bicgstab_solver); + WRAP_STD_SOLVER (cgs_solver, py_cgs_solver); + WRAP_STD_SOLVER (tfqmr_solver, py_tfqmr_solver); + + PY_EXPORTER (solver_exporter, default_exporter) + .def ("solve", &T::solve) + .def ("solve_prec", &T::solve_prec) + .def ("setup", &T::setup) + .def ("set_prec", &T::set_prec) + .def ("set_prop", &T::set_prop) + PY_EXPORTER_END; + + //! export linear_solver_prop to python + void py_export_linear_solver_prop (); + + //! export linear solvers to python + void py_export_linear_solvers (); + +} // namespace python +} // namespace blue_sky + +#endif // #ifdef BSPY_EXPORTING_PLUGIN +#endif //#ifndef BS_LINEAR_SOLVERS_PYTHON_H diff --git a/bs_base_linear_solvers/include/solve_helper.h b/bs_base_linear_solvers/include/solve_helper.h new file mode 100644 index 0000000..544b930 --- /dev/null +++ b/bs_base_linear_solvers/include/solve_helper.h @@ -0,0 +1,30 @@ +/** + * \file solve_helper.h + * \brief impl of + * \author Elmira Salimgareeva + * \date 31.03.2009 + * */ + +#ifndef BS_SOLVE_HELPER_H_ +#define BS_SOLVE_HELPER_H_ +namespace blue_sky +{ + + template + int + solve_helper (solver_t *solver, typename solver_t::matrix_t *mx, seq_vector &rhs, typename solver_t::item_array_t &sol) + { + solver->solve (mx, rhs, sol); + return 0; + } + + template + int + solve_helper (solver_t *solver, typename solver_t::matrix_t *mx, seq_vector &rhs, typename solver_t::item_array_t &sol) + { + solver->solve_prec (mx, rhs, sol); + return 0; + } + +} +#endif //#ifndef BS_SOLVE_HELPER_H_ diff --git a/bs_base_linear_solvers/include/tfqmr.h b/bs_base_linear_solvers/include/tfqmr.h new file mode 100644 index 0000000..51094a8 --- /dev/null +++ b/bs_base_linear_solvers/include/tfqmr.h @@ -0,0 +1,78 @@ +/** + * \file tfqmr.h + * \brief TFQMR linear solver + * \author Salimgareeva E.M. + * \date + * */ +#ifndef BS_TFQMR_LINEAR_SOLVER_H_ +#define BS_TFQMR_LINEAR_SOLVER_H_ + +#include "linear_solvers.h" + +namespace blue_sky + { + /** + * @brief TFQMR linear solver + */ + template + class BS_API_PLUGIN tfqmr_solver : public linear_solver_base + { + + //----------------------------------------- + // TYPES + //----------------------------------------- + public: + typedef typename strategy_t::matrix_t matrix_t; ///< short name to matrix type + typedef typename strategy_t::item_array_t item_array_t; ///< short name to array type + typedef typename strategy_t::item_t item_t; ///< short name to array item type + typedef typename strategy_t::index_t index_t; ///< short name to matrix's index type + typedef typename strategy_t::rhs_item_t rhs_item_t; ///< short name for type of rhs + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; ///< short name for rhs array type + + + typedef typename strategy_t::matrix_array_t matrix_array_t; ///< short name to matrix array type + + typedef typename strategy_t::index_array_t index_array_t; + + typedef linear_solver_base this_t; ///< typedef to this type + typedef linear_solver_base base_t; ///< typedef to this type. in child classes used as a short name of base class + typedef smart_ptr sp_this_t; ///< short name to smart pointer to this class + typedef smart_ptr sp_prop_t; ///< short name to smart pointer to properties holder class + + typedef smart_ptr sp_matrix_t; ///< short name to smart pointer on matrix_t + + typedef bcsr_matrix bcsr_matrix_t; ///< short name for used matrix + typedef smart_ptr sp_bcsr_matrix_t; ///< short name for smart_pointer on used matrix + + //----------------------------------------- + // METHODS + //----------------------------------------- + public: + //! destructor + virtual ~tfqmr_solver (); + + //! solve + virtual int solve (matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &sol); + + virtual int solve_prec (matrix_t *matrix, item_array_t &rhs, item_array_t &sol); + + template + int + templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &sol); + + //! setup + virtual int setup (matrix_t *matrix); + + private: + //----------------------------------------- + // VARIABLES + //----------------------------------------- + public: + + public: + BLUE_SKY_TYPE_DECL (tfqmr_solver); + }; + + } // namespace blue_sky + +#endif // #ifndef BS_TFQMR_LINEAR_SOLVER_H_ diff --git a/bs_base_linear_solvers/src/bs_base_linear_solvers.cpp b/bs_base_linear_solvers/src/bs_base_linear_solvers.cpp new file mode 100644 index 0000000..4209046 --- /dev/null +++ b/bs_base_linear_solvers/src/bs_base_linear_solvers.cpp @@ -0,0 +1,33 @@ +// bs_base_linear_solvers.cpp : Defines the entry point for the DLL application. +// + +#include "bs_base_linear_solvers_stdafx.h" + +#include "linear_solvers.h" +#include "py_linear_solvers.h" + +namespace blue_sky { + BLUE_SKY_PLUGIN_DESCRIPTOR_EXT ("bs_base_linear_solvers", "1.0.0", "BS_BASE_LINEAR_SOLVERS", "BS_BASE_LINEAR_SOLVERS", "bs_base_linear_solvers") + + BLUE_SKY_REGISTER_PLUGIN_FUN + { + const plugin_descriptor &pd = *bs_init.pd_; + + bool res = true; + + res &= blue_sky::linear_solver_prop_register_type (pd); BS_ASSERT (res); + res &= blue_sky::linear_solvers_register_type (pd); BS_ASSERT (res); + + return res; + } +} + +#ifdef BSPY_EXPORTING_PLUGIN +BLUE_SKY_INIT_PY_FUN +{ + using namespace blue_sky::python; + + py_export_linear_solver_prop (); + py_export_linear_solvers (); +} +#endif diff --git a/bs_base_linear_solvers/src/cgs.cpp b/bs_base_linear_solvers/src/cgs.cpp new file mode 100644 index 0000000..f7fbcfc --- /dev/null +++ b/bs_base_linear_solvers/src/cgs.cpp @@ -0,0 +1,315 @@ +/** + * \file cgs.cpp + * \brief CGS linear solver impl + * \author Salimgareeva E.M. (algorithm from "A fast Lanczos-type solver for nonsymmetric linear systems", P.Sonneveld) + * \date 11.02.2009 + * */ +#include "bs_base_linear_solvers_stdafx.h" +#include "linear_solvers.h" +#include "cgs.h" +#include "lin_solv_macro.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "save_seq_vector.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + ////////////////////////////////////////////////////////////////////////// + // cgs_solver + + //! constructor + template + cgs_solver::cgs_solver (bs_type_ctor_param param) + : linear_solver_base (param) + {} + + //! copy constructor + template + cgs_solver::cgs_solver(const cgs_solver &solver) + : bs_refcounter (), linear_solver_base (solver) + { + if (&solver != this) + *this = solver; + } + + //! destructor + template + cgs_solver::~cgs_solver () + {} + + + template + int cgs_solver::solve(matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + template + int cgs_solver::solve_prec(matrix_t *matrix, item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + + /*! + * \brief CGS linear solver + * + * \param[in] matrix -- pointer to the matrix + * \param[in] rhs -- right hand side + * \param[out] solution -- solution + * + * \return 0 if success + */ + + //template + //int cgs_solver::solve(matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &solution) + template template int + cgs_solver::templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &solution) + { +#ifdef _DEBUG + BOSOUT (section::solvers, level::debug) << "CGS\n" << bs_end; +#endif + typedef item_t fp_type; + + BS_ERROR (rhs.size (), "cgs_solve"); + BS_ERROR (solution.size (), "cgs_solve"); + BS_ERROR (base_t::prop, "cgs_solve"); + + const smart_ptr &lprop(this->prop); + + fp_type rho_1, rho_2 = 1, alpha = 1, beta, sigma; + int iter; + const double epsmac = 1e-24; + fp_type r_norm, b_norm, den_norm; + //fp_type *x = solution; + + //OMP_TIME_MEASURE_START (cgs_solve_timer); + + item_t tol = this->prop->get_tolerance (); + tol *= tol; + //resid = prop->get_residuals (); + //convergence_rate = prop->get_convergence_rate (); + + index_t max_iter = this->prop->get_max_iters (); + index_t n = matrix->n_rows * matrix->n_block_size; + + item_array_t p (n); + item_array_t phat (n); + item_array_t v (n); + item_array_t tmp (n); + item_array_t q (n); + item_array_t u (n); + item_array_t d (n); + item_array_t dhat (n); + item_array_t r (n); + item_array_t rtilde (n); + item_array_t r_old (n); + + lprop->set_success (0); + + // solution = {0} + assign (solution, n, 0); + + // r = {0} + assign (r, n, 0); + // TODO:paste + assign (tmp, n, 0); + assign (p, n, 0); + assign (v, n, 0); + assign (q, n, 0); + + // p0 = u0 = r0; + //memcpy (p, r, n * sizeof (double)); + u.assign (r.begin (), r.end ()); + // TODO:end + + // r = Ax0 - b + matrix->calc_lin_comb (-1.0, 1.0, solution, rhs, r); + rtilde.assign (r.begin (), r.end ()); + + //tools::save_seq_vector (tools::string_formater ("1_well_bhp.%s.txt", it->first).str).save (it->second); + + r_norm = bos_helper::mv_vector_inner_product (r, r); + + if (r_norm <= tol) // initial guess quite good + return 0; + + rho_1 = r_norm; + b_norm = sqrt (bos_helper::mv_vector_inner_product (rhs, rhs)); + + // TODO:delete + //p.assign (r.begin (), r.end ()); + //rtilde.assign (r.begin (), r.end ()); + //v.assign (n, 0); + // TODO:end + + if (b_norm > epsmac) // choose convergence criterion + { + // |r_i|/|b| <= eps if |b| > 0 + tol *= b_norm; + den_norm = b_norm; + } + else // (r_norm > epsmac) + { + // |r_i|/|r0| <= eps if |b| = 0 + tol *= r_norm; + den_norm = r_norm; + } + + // set up initial norm and convergense factor + lprop->set_relative_factor (den_norm); + + // main loop + for (iter = 0; iter < max_iter; ++iter) + { + //printf ("CGS iteration: %d, resid = %le\n", iter, r_norm); + //fflush (stdout); + // TODO: paste + if (iter) + { + //rho_1 = (r,rtilde) + rho_1 = bos_helper::mv_vector_inner_product (r, rtilde); //in first iter equals to r_norm + if (rho_1 == 0) // failure + { + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + bs_throw_exception ("CGS: Failure - rho_1 == 0"); + } + } + + beta = rho_1/rho_2; // beta = rho_n/rho_n-1 + rho_2 = rho_1; + + // u = r + beta*q + sum_vector(r, 1., q, beta, u); + // tmp = q+beta*p_old + sum_vector(q, 1., p, beta, tmp); + // p_new = u + beta*tmp + sum_vector(u, 1., tmp, beta, p); + + //temp_p.assign (p.begin (), p.end ()); + if (this->prec) + { + if (base_t::prec->solve_prec (matrix, p, phat)) + { + bs_throw_exception ("CGS: Preconditioner failed"); + } + } + else // no precondition (preconditioner=identity_matrix) + { + phat.assign (p.begin (), p.end ()); + } + + // v = A * phat = A * p, if no precondition; + assign (v, n, 0); + + matrix->matrix_vector_product (phat, v); + // sigma = (v,rtilde) + sigma = bos_helper::mv_vector_inner_product (rtilde, v); + + if (sigma > epsmac || sigma < -epsmac) + // alpha = rho_1/sigma + alpha = rho_1/sigma; + else // failure + { + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + bs_throw_exception ("CGS: Failure - sigma == 0"); + } + + // q = u - alpha*v + sum_vector(u, 1., v, -alpha, q); + // d = u + q + sum_vector(u, 1., q, 1., d); + + // dhat = M^(-1) * d; + //temp_d.assign (d.begin (), d.end ()); + if (this->prec) + { + if(base_t::prec->solve_prec (matrix, d, dhat)) + { + bs_throw_exception ("CGS: Preconditioner failed"); + } + } + else // no precondition (preconditioner=identity_matrix) + { + dhat.assign (d.begin (), d.end ()); + } + + assign (tmp, n, 0); + // tmp = A*d + matrix->matrix_vector_product (dhat, tmp); + + // r = r - alpha*tmp + sum_vector(r, 1., tmp, -alpha, r); + // x = x + alpha*dhat + sum_vector(solution, 1., dhat, alpha, solution); + + r_norm = bos_helper::mv_vector_inner_product (r, r, n); + + + if (r_norm <= tol) // && check_resid_for_matbalance (n_rows, nb, r, matb_tol)) + break; + } + + //tools::save_seq_vector ("solution.txt").save(solution); + + //TODO: end + lprop->set_iters (iter + 1); + lprop->set_success (1); + + /* + //additional checking convergence + mv_calc_lin_comb (matrix, -1.0, 1.0, solution, rhs, r); + r_norm = mv_vector_inner_product (r, r, n); + */ + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + //printf ("CGS OK! iters = %d, resid = %le\n", lprop->iters, lprop->final_resid); + //OMP_TIME_MEASURE_END (bicgstab_solve_timer); + + return 0; + } + + /** + * @brief setup for CGS + * + * @param matrix -- input matrix + * + * @return 0 if success + */ + template int + cgs_solver::setup (matrix_t *matrix) + { + if (!matrix) + { + bs_throw_exception ("CGS: Passed matrix is null"); + } + + BS_ASSERT (base_t::prop); + if (base_t::prec) + { + return base_t::prec->setup (matrix); + } + + return 0; + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF(cgs_solver, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(cgs_solver, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (cgs_solver) , 1, (linear_solver_base), "cgs_solver_base_fi", "CGS linear solver", "CGS linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (cgs_solver) , 1, (linear_solver_base), "cgs_solver_base_di", "CGS linear solver", "CGS linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (cgs_solver) , 1, (linear_solver_base), "cgs_solver_base_mixi", "CGS linear solver", "CGS linear solver", false); + } diff --git a/bs_base_linear_solvers/src/linear_solvers.cpp b/bs_base_linear_solvers/src/linear_solvers.cpp new file mode 100644 index 0000000..ad086f0 --- /dev/null +++ b/bs_base_linear_solvers/src/linear_solvers.cpp @@ -0,0 +1,944 @@ +/*! +* \file linear_solvers.cpp +* \brief implementation of linear solvers +* \author Borschuk Oleg +* \date 2006-07-26 +*/ +#include "bs_base_linear_solvers_stdafx.h" + +#include "linear_solvers.h" +#include "lin_solv_macro.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "dummy_base.h" +#include "bos_report.h" +#include "vector_assign.h" + +#ifdef _MPI +#include "mpi_csr_matrix.h" +#include "mpi_vector.h" +#endif // #ifdef _MPI +#include BS_STOP_PLUGIN_IMPORT () + + + +namespace blue_sky +{ +namespace bos_helper +{ +namespace helper +{ +namespace tmp_ns +{ + template struct is_int + { + enum { value = 0}; + }; + template <> struct is_int + { + enum { value = 1}; + }; + template <> struct is_int + { + enum { value = 1}; + }; + template <> struct is_int + { + enum { value = 1}; + }; + template <> struct is_int + { + enum { value = 1}; + }; + +template inline typename vector_v1_t::value_type + mv_vector_inner_product (const vector_v1_t &v1, const vector_v2_t &v2, int /* obsolete */ = 0) + { + BOOST_STATIC_ASSERT (helper::is_int ::value == 0); + BOOST_STATIC_ASSERT (helper::is_int ::value == 0); + + typename vector_v1_t::value_type sum = 0; + size_t i = 0; + size_t n = v1.size (); + + BS_ASSERT (v1.size () == v2.size ()); + +#ifdef MV_VECTOR_INNER_PRODUCT_PARALLEL +#pragma omp parallel for reduction (+: sum) +#endif //MV_VECTOR_INNER_PRODUCT_PARALLEL + for (i = 0; i < n; ++i) + { + sum += v1[i] * v2[i]; + } + + return sum; + } +} +} +} +} + +namespace blue_sky + { + //namespace tmp_ns + //{ + + ////////////////////////////////////////////////////////////////////////// + // linear_solver_prop + + //! constructor + linear_solver_prop::linear_solver_prop (bs_type_ctor_param /*param*/) + { + this->params_names.resize(LS_TOTAL); + EREG(linear_solver_prop,FP_RELATIVE_FACTOR,"relative factor"); + EREG(linear_solver_prop,FP_TOLERANCE,"tolerance"); + EREG(linear_solver_prop,FP_MATBAL_TOLERANCE,"matbal tolerance"); + EREG(linear_solver_prop,FP_FINAL_RESID,"final resid"); + + EREG(linear_solver_prop,I_ITERS,"iterations count"); + EREG(linear_solver_prop,I_MAX_ITERS,"max iterations count"); + EREG(linear_solver_prop,I_SUCCESS,"success"); + + resize (LS_TOTAL); + + set_max_iters (30); + set_tolerance (1.0e-5); + set_relative_factor (1.0); + set_success (0); + set_iters (0); + set_final_resid (0); + + + } + + //! copy constructor + linear_solver_prop::linear_solver_prop (const linear_solver_prop &prop) + : bs_refcounter (), named_pbase () + { + if (&prop != this) + *this = prop; + } + + //! destructor + linear_solver_prop::~linear_solver_prop () + { + } + + + /** + * @brief set maximum number of iterations + * + * @param n_iters -- number of iterations + * + * @return 0 if success + */ + int + linear_solver_prop::set_max_iters (int n_iters) + { + int r_code = 0; + + if (n_iters < 0) + n_iters = 1; + + //FI_DOUBLE_ARRAY_REALLOCATOR (resid, n_iters + 2, r_code); + //FI_DOUBLE_ARRAY_REALLOCATOR (convergence_rate, n_iters + 2, r_code); + + set_param(I_MAX_ITERS,n_iters); + return r_code; + } + + /** + * @brief get parameter name + * + * @param idx - parameter name + * + * @return parameter name + */ + const std::string & linear_solver_prop::get_params_name (idx_type idx) + { + return params_names[idx].name; + } + + ////////////////////////////////////////////////////////////////////////// + // linear_solver_base + + //! constructor + template + linear_solver_base::linear_solver_base (bs_type_ctor_param /*param*/, bs_node::sp_node node) + :bs_node (node) + { + init(); + } + + template + linear_solver_base::linear_solver_base (bs_type_ctor_param) + : bs_node(bs_node::create_node (new solver_trait ())) + { + init(); + } + + template + void linear_solver_base::init() + { + prop = BS_KERNEL.create_object (linear_solver_prop::bs_type ()); + BS_ASSERT (prop); + + //sp_link prec_link = bs_link::create (bs_node::create_node (), "prec"); + //sp_link prop_link = bs_link::create (bs_node::create_node (), "prop"); + + //bs_node::insert (prec_link, false); + //bs_node::insert (prop_link, false); + } + + template + linear_solver_base::linear_solver_base (const linear_solver_base &solver) + : bs_refcounter (), bs_node () + { + if (&solver != this) + *this = solver; + } + + //! destructor + template + linear_solver_base::~linear_solver_base () + { + //prec = 0; + //prop = 0; + } + + ////////////////////////////////////////////////////////////////////////// + // gmres2_solver + + //! constructor + template + gmres_solver2::gmres_solver2 (bs_type_ctor_param param) + : linear_solver_base (param) + { + m = 30; + } + + //! copy constructor + template + gmres_solver2::gmres_solver2(const gmres_solver2 &solver) + : bs_refcounter (), linear_solver_base (solver) + { + if (&solver != this) + *this = solver; + } + + //! destructor + template + gmres_solver2::~gmres_solver2 () + { + m = 30; + } + + + template + int gmres_solver2::solve(matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + template + int gmres_solver2::solve_prec(matrix_t *matrix, item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + + /** + * @brief restarted GMRES linear solver + * + * @param matrix -- matrix + * @param rhs -- right hand side + * @param solution -- solution + * + * @return 0 if success + */ + template template int + gmres_solver2::templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &solution) + { + //tools::save_seq_vector ("rhs_new").save (rhs); + typedef typename strat_t::item_t fp_type; + + BS_ASSERT (matrix); + BS_ASSERT (rhs.size ()); + BS_ASSERT (solution.size ()); + BS_ASSERT (rhs.size () == solution.size ()) (rhs.size ()) (solution.size ()); + BS_ASSERT (base_t::prop); + + const smart_ptr &lprop (base_t::prop); + + fp_type *rs, *hh, *c, *s; + fp_type gamma, t, r_norm, b_norm, den_norm; + fp_type *cur_h; + const double epsmac = 1.e-16; + + // do barrier at mpi or nothing do at seq (base) + // in future we can hold instance of barrier_t as a data member + barrier_t ().barrier (barrier_t::comm_world_v ()); + + index_t n = matrix->n_rows * matrix->n_block_size; + item_t tol = lprop->get_tolerance (); + + // check workspace + assign (base_t::wksp, n * (m + 3) + (m + 2) * (m + 1) + 2 * m, 0); + + vec_p.assign (m + 1, item_array_t ()); + for (int i = 0, cnt = (int)vec_p.size (); i < cnt; ++i) + { + vec_p[i] = item_array_t (); + vec_p[i].template init_by_matrix (matrix); + } + + vec_w.template init_by_matrix (matrix); + vec_r.template init_by_matrix (matrix); + + // initialize work arrays + s = &base_t::wksp[0]; + c = s + m; + rs = c + m; + hh = rs + m + 1; + + lprop->set_success (0); + + assign (solution, n, 0); + + //calculate_init_r (n, matrix, solution, rhs, p); + matrix->calc_lin_comb (-1.0, 1.0, solution, rhs, vec_p[0]); + + b_norm = sqrt (bos_helper::helper::tmp_ns::mv_vector_inner_product (rhs, rhs)); + //BOSOUT (section::solvers, level::low) << "b_norm = " << b_norm << bs_end; + + + /* Since it is does not diminish performance, attempt to return an error flag + and notify users when they supply bad input. */ + + r_norm = sqrt (bos_helper::helper::tmp_ns::mv_vector_inner_product (vec_p[0], vec_p[0])); + + //BOSOUT (section::solvers, level::low) << "r_norm = " << r_norm << bs_end; + + //printf ("Initial_residual %le\n", r_norm / b_norm); + + if (b_norm > epsmac) + { + /* convergence criterion |r_i|/|b| <= accuracy if |b| > 0 */ + tol *= b_norm; + den_norm = b_norm; + } + else + { + /* convergence criterion |r_i|/|r0| <= accuracy if |b| = 0 */ + tol *= r_norm; + den_norm = r_norm; + } + // set up initial norm and convergense factor + lprop->set_relative_factor (den_norm); + + index_t iter = 0; + index_t max_iter = lprop->get_max_iters (); + for (iter = 0; iter < max_iter;) + { + /* initialize first term of hessenberg system */ + rs[0] = r_norm; + + if (r_norm < epsmac || r_norm <= tol) + break; + + t = 1.0 / r_norm; + + scale_vector (vec_p[0], t); + + index_t i = 0; + for (i = 1; i < m && iter < max_iter; ++i, ++iter) + { + barrier_t ().barrier (barrier_t::comm_world_v ()); + + //memset (r, 0, sizeof (double) * n); + if (this->prec) + { + if (this->prec->solve_prec (matrix, vec_p[i - 1], vec_r)) + { + bs_throw_exception ("GMRES: Preconditioner failed"); + } + } + else // no precondition (preconditioner=identity_matrix) + { + vec_r.assign (vec_p[i - 1].begin (), vec_p[i - 1].end ()); + } + + barrier_t ().barrier (barrier_t::comm_world_v ()); + + assign (vec_p[i], n, 0); + matrix->matrix_vector_product (vec_r, vec_p[i]); + + /* modified Gram_Schmidt */ + cur_h = hh + (i - 1) * (m + 1); + for (index_t j = 0; j < i; ++j) + { + cur_h[j] = bos_helper::helper::tmp_ns::mv_vector_inner_product (vec_p[j], vec_p[i], n); + t = -cur_h[j]; + + axpy (vec_p[i], vec_p[j], t); + } + t = sqrt (bos_helper::helper::tmp_ns::mv_vector_inner_product (vec_p[i], vec_p[i], n)); + cur_h[i] = t; + if (t > epsmac) + { + t = 1.0 / t; + + scale_vector (vec_p[i], t); + + } + /* done with modified Gram_schmidt and Arnoldi step. + update factorization of hh */ + for (index_t j = 1; j < i; j++) + { + t = cur_h[j - 1]; + cur_h[j - 1] = c[j - 1] * t + s[j - 1] * cur_h[j]; + cur_h[j] = -s[j - 1] * t + c[j - 1] * cur_h[j]; + } + + gamma = sqrt (cur_h[i - 1] * cur_h[i - 1] + cur_h[i] * cur_h[i]); + + if (gamma = 0; --k) + { + t = rs[k]; + for (index_t j = k + 1; j < i; j++) + { + t -= hh[k + j * (m + 1)] * rs[j]; + } + rs[k] = t / hh[k + k * (m + 1)]; + } + + /* form linear combination of p's to get solution */ + //vec_w.assign (vec_p[0].begin (), vec_p[0].end ()); + memcpy (&vec_w[0], &vec_p[0][0], sizeof (item_t) * n); + t = rs[0]; + + scale_vector (vec_w, t); + + for (index_t j = 1; j < i; j++) + { + t = rs[j]; + axpy (vec_w, vec_p[j], t); + } + + //memset (r, 0, sizeof (double) * n); + + barrier_t ().barrier (barrier_t::comm_world_v ()); + + if (this->prec) + { + if (base_t::prec->solve_prec (matrix, vec_w, vec_r)) + { + bs_throw_exception ("GMRES: Preconditioner failed"); + } + } + else // no precondition (preconditioner=identity_matrix) + { + //memcpy (r, w, n * sizeof (fp_type)); + vec_r.assign (vec_w.begin (), vec_w.end ()); + } + + barrier_t ().barrier (barrier_t::comm_world_v ()); + + axpy (solution, vec_r, 1.0); + + /* check for convergence, evaluate actual residual */ + if (r_norm <= tol) + { + //break; +#if 1 + //calculate_init_r (n, matrix, solution, rhs, r); + matrix->calc_lin_comb (-1.0, 1.0, solution, rhs, vec_r); + + r_norm = sqrt (bos_helper::helper::tmp_ns::mv_vector_inner_product (vec_r, vec_r, n)); + + if (r_norm <= tol) + break; + else + { + //vec_p[0].assign (vec_r.begin (), vec_r.end ()); + memcpy (&vec_p[0][0], &vec_r[0], sizeof (item_t) * n); + i = 0; + ++iter; + } +#endif //0 + } + + /* compute residual vector and continue loop */ + + for (index_t j = i; j > 0; --j) + { + rs[j - 1] = -s[j - 1] * rs[j]; + rs[j] = c[j - 1] * rs[j]; + } + + if (i) + { + t = rs[0]; + scale_vector (vec_p[0], t); + + } + for (index_t j = 1; j < i + 1; ++j) + { + t = rs[j]; + axpy (vec_p[0], vec_p[j], t); + } + } + + lprop->set_iters (iter + 1); + lprop->set_success (1); + + if (den_norm > 1.0e-12) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + +#ifdef _DEBUG + BOSOUT (section::solvers, level::low) << "r_norm = " << r_norm << " r_norm / den_norm = " << r_norm / den_norm << " iter = " << (iter + 1) << bs_end; +#endif + + barrier_t ().barrier (barrier_t::comm_world_v ()); + + return 0; + } + + /** + * @brief setup GMRES + * + * @param matrix -- input matrix + * + * @return 0 if success + */ + template int + gmres_solver2::setup (matrix_t *matrix) + { + BS_ASSERT (matrix); + if (!matrix) + { + bs_throw_exception ("GMRES: Passed matrix is null"); + } + + if (base_t::prec) + { + return base_t::prec->setup (matrix); + } + + return 0; + } + + + ////////////////////////////////////////////////////////////////////////// + // bicgstab_solver + + //! constructor + template + bicgstab_solver::bicgstab_solver (bs_type_ctor_param param) + : linear_solver_base (param) + {} + + //! copy constructor + template + bicgstab_solver::bicgstab_solver(const bicgstab_solver &solver) + : bs_refcounter (), linear_solver_base (solver) + { + if (&solver != this) + *this = solver; + } + + //! destructor + template + bicgstab_solver::~bicgstab_solver () + {} + + + + template + int bicgstab_solver::solve(matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + template + int bicgstab_solver::solve_prec(matrix_t *matrix, item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + /*! + * \brief BiCGStab linear solver + * + * \param[in] matrix -- pointer to the matrix + * \param[in] rhs -- right hand side + * \param[out] solution -- solution + * + * \return 0 if success + */ + template template int + bicgstab_solver::templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &solution) + { + typedef item_t fp_type; + + BS_ERROR (matrix, "bicgstab_solve"); + BS_ERROR (rhs.size (), "bicgstab_solve"); + BS_ERROR (solution.size (), "bicgstab_solve"); + BS_ERROR (base_t::prop, "bicgstab_solve"); + + const smart_ptr &lprop(this->prop); + + fp_type rho_1, rho_2 = 1, alpha = 1, beta, omega = 1; + int iter; + const double epsmac = 1e-24; + fp_type r_norm, b_norm, den_norm, s_norm; + //fp_type *x = solution; + + //OMP_TIME_MEASURE_START (bicgstab_solve_timer); + + item_t tol = this->prop->get_tolerance (); + tol *= tol; + //resid = prop->get_residuals (); + //convergence_rate = prop->get_convergence_rate (); + + index_t max_iter = this->prop->get_max_iters (); + index_t n = matrix->n_rows * matrix->n_block_size; + + item_array_t p (n); + item_array_t phat (n); + item_array_t s (n); + item_array_t shat (n); + item_array_t t (n), v (n), r (n), rtilde (n); + + lprop->set_success (0); + + assign (solution, n, 0); + assign (r, n, 0); + + matrix->calc_lin_comb (-1.0, 1.0, solution, rhs, r); + r_norm = bos_helper::mv_vector_inner_product (r, r); + if (r_norm <= tol) // initial guess quite good + return 0; + + rho_1 = r_norm; + b_norm = sqrt (bos_helper::mv_vector_inner_product (rhs, rhs)); + + p.assign (r.begin (), r.end ()); + rtilde.assign (r.begin (), r.end ()); + assign (v, n, 0); + + if (b_norm > epsmac) // choose convergence criterion + { + // |r_i|/|b| <= eps if |b| > 0 + tol *= b_norm; + den_norm = b_norm; + } + else // (r_norm > epsmac) + { + // |r_i|/|r0| <= eps if |b| = 0 + tol *= r_norm; + den_norm = r_norm; + } + + // set up initial norm and convergense factor + lprop->set_relative_factor (den_norm); + + // main loop + for (iter = 0; iter < max_iter; ++iter) + { + //printf ("BiCGStab iteration: %d, resid = %le\n", iter, r_norm); + //fflush (stdout); + + if (iter) + { + rho_1 = bos_helper::mv_vector_inner_product (r, rtilde); //in first iter equals to r_norm + if (rho_1 == 0) // failure + { + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + bs_throw_exception (boost::format ("BICGSTAB: Failure - rho_1 == 0, resid = %le") % lprop->get_final_resid ()); + } + beta = (rho_1 / rho_2) * (alpha / omega); + // p = r + beta * (p - omega * v); + //AXPY_AYPX (p, -omega, v, beta, r, k, n); + axpy_aypx (p, -omega, v, beta, r); + } + + // phat = M^(-1) * p; + if (this->prec) + { + if (base_t::prec->solve_prec (matrix, p, phat)) + { + bs_throw_exception ("BICGSTAB: Preconditioner failed"); + } + } + else // no precondition (preconditioner=identity_matrix) + { + phat.assign (p.begin (), p.end ()); + } + + // v = A * phat; + assign (v, n, 0); + matrix->matrix_vector_product (phat, v); + + alpha = bos_helper::mv_vector_inner_product (rtilde, v); + if (alpha > epsmac || alpha < -epsmac) + alpha = rho_1 / alpha; + else // failure + { + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + bs_throw_exception (boost::format ("BICGSTAB: Failure - (rtilde, v) == 0, resid = %le") % lprop->get_final_resid ()); + } + + // s = r - alpha * v; + s.assign (r.begin (), r.end ()); + axpy (s, v, -alpha); + //AXPY (s, -alpha, v, k, n); + + //x = x + alpha * phat; + //AXPY (x, alpha, phat, k, n); + //axpy (x, phat, alpha); + axpy (solution, phat, alpha); + + s_norm = bos_helper::mv_vector_inner_product (s, s); + if (s_norm < tol) + { + //check convergence + //matrix->calc_lin_comb (-1.0, 1.0, x, rhs, t);// t is buffer + matrix->calc_lin_comb (-1.0, 1.0, solution, rhs, t);// t is buffer + r_norm = bos_helper::mv_vector_inner_product (t, t); + if (r_norm <= tol) + break; + } + + // shat = M^(-1) * s; + if (this->prec) + { + if (base_t::prec->solve_prec (matrix, s, shat)) + { + bs_throw_exception ("BICGSTAB: Preconditioner failed"); + } + } + else // no precondition (preconditioner=identity_matrix) + { + shat.assign (s.begin (), s.end ()); + } + + // t = A * shat; + assign (t, n, 0); + matrix->matrix_vector_product (shat, t); + + // omega = (t,s) / (t,t); + omega = bos_helper::mv_vector_inner_product (t, t); + if (omega > epsmac) + { + omega = bos_helper::mv_vector_inner_product (t, s) / omega; + } + else // failure + { + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + bs_throw_exception (boost::format ("BICGSTAB: Failure - (t, t) == 0, resid = %le") % lprop->get_final_resid ()); + } + + if (omega < epsmac) // failure + { + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + bs_throw_exception (boost::format ("BICGSTAB: Failure - omega == 0, resid = %le") % lprop->get_final_resid ()); + } + + //x = x + omega * shat; + //AXPY (x, omega, shat, k, n); + //axpy (x, shat, omega); + axpy (solution, shat, omega); + + //r = s - omega * t; + //memcpy (r, s, n * sizeof (fp_type)); + //AXPY (r, -omega, t, k, n); + r.assign (s.begin (), s.end ()); + axpy (r, t, -omega); + /* + //additional check convergence + mv_calc_lin_comb (matrix, -1.0, 1.0, x, rhs, s); // s is buffer + r_norm = mv_vector_inner_product (s, s, n); + */ + r_norm = bos_helper::mv_vector_inner_product (r, r); + if (r_norm <= tol) + break; + + rho_2 = rho_1; + } // end of main loop + + lprop->set_iters (iter + 1); + lprop->set_success (1); + + //printf ("BiCGStab after iteration: %d, resid = %le\n", iter, r_norm); + /* + //additional checking convergence + mv_calc_lin_comb (matrix, -1.0, 1.0, solution, rhs, r); + r_norm = mv_vector_inner_product (r, r, n); + */ + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + BOSOUT (section::solvers, level::low) << "r_norm = " << r_norm << " r_norm / den_norm = " << r_norm / den_norm << " iter = " << iter << bs_end; + + // printf ("BiCGStab OK! iters = %d, resid = %le\n", prop->iters, prop->final_resid); + //OMP_TIME_MEASURE_END (bicgstab_solve_timer); + + return 0; + } + + /** + * @brief setup for BiCGStab + * + * @param matrix -- input matrix + * + * @return 0 if success + */ + template int + bicgstab_solver::setup (matrix_t *matrix) + { + BS_ASSERT (matrix); + if (!matrix) + { + bs_throw_exception ("BICGSTAB: Passed matrix is null"); + } + + BS_ASSERT (base_t::prop); + if (base_t::prec) + { + return base_t::prec->setup (matrix); + } + + return 0; + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE(linear_solver_prop); + BLUE_SKY_TYPE_STD_COPY(linear_solver_prop); + BLUE_SKY_TYPE_IMPL(linear_solver_prop, objbase, "linear_solver_prop", "Property for linear solvers", "Property for linear solvers"); + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF(linear_solver_base, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(linear_solver_base, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (linear_solver_base) , 1, (objbase), "linear_solver_base_fi", "linear solver", "linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (linear_solver_base) , 1, (objbase), "linear_solver_base_di", "linear solver", "linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (linear_solver_base) , 1, (objbase), "linear_solver_base_mixi", "linear solver", "linear solver", false); + +#ifdef _MPI + BLUE_SKY_TYPE_IMPL_T_EXT(1, (linear_solver_base) , 1, (objbase), "linear_solver_mpi_di", "linear solver", "linear solver", false); +#endif + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF(gmres_solver2, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(gmres_solver2, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (gmres_solver2) , 1, (linear_solver_base), "gmres_solver2_base_fi", "GMRES linear solver", "GMRES linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (gmres_solver2) , 1, (linear_solver_base), "gmres_solver2_base_di", "GMRES linear solver", "GMRES linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (gmres_solver2) , 1, (linear_solver_base), "gmres_solver2_base_mixi", "GMRES linear solver", "GMRES linear solver", false); + +#ifdef _MPI + BLUE_SKY_TYPE_IMPL_T_EXT(1, (gmres_solver2) , 1, (linear_solver_base), "gmres_solver2_mpi_di", "GMRES linear solver", "GMRES linear solver", false); +#endif + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF(bicgstab_solver, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(bicgstab_solver, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (bicgstab_solver) , 1, (linear_solver_base), "bicgstab_solver_base_fi", "BiCG linear solver", "BiCG linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (bicgstab_solver) , 1, (linear_solver_base), "bicgstab_solver_base_di", "BiCG linear solver", "BiCG linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (bicgstab_solver) , 1, (linear_solver_base), "bicgstab_solver_base_mixi", "BiCG linear solver", "BiCG linear solver", false); + + ////////////////////////////////////////////////////////////////////////// + // register types + + bool + linear_solver_prop_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + res &= BS_KERNEL.register_type (pd, linear_solver_prop::bs_type ()); + + return res; + } + bool + linear_solvers_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, linear_solver_base::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, linear_solver_base::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, linear_solver_base::bs_type ()); + BS_ASSERT (res); + + + res &= BS_KERNEL.register_type (pd, gmres_solver2::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, gmres_solver2::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, gmres_solver2::bs_type ()); + BS_ASSERT (res); + + + +#ifdef _MPI + res &= BS_KERNEL.register_type (pd, gmres_solver2::bs_type ()); +#endif + + res &= BS_KERNEL.register_type (pd, bicgstab_solver::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, bicgstab_solver::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, bicgstab_solver::bs_type ()); + BS_ASSERT (res); + + + + return res; + } + +// } // namespace tmp_ns +} // namespace blue_sky diff --git a/bs_base_linear_solvers/src/lu_decomposition.cpp b/bs_base_linear_solvers/src/lu_decomposition.cpp new file mode 100644 index 0000000..b083c3e --- /dev/null +++ b/bs_base_linear_solvers/src/lu_decomposition.cpp @@ -0,0 +1,515 @@ +/*! + \file lu_decomposition.cpp + \author Borschuk Oleg + \version 0.1 + \date 3.10.2004 + \brief file include functions to build LU decomposition and to solve matrix +*/ +#include "bs_base_linear_solvers_stdafx.h" + +#include + +#include "lu_decomposition.h" + +#define LU_2x2(m_str_0, m_str_1) \ + m_str_0[1] /= m_str_0[0]; \ + m_str_1[1] -= m_str_0[1] * m_str_1[0]; + +#define LU_3x3(m_str_0, m_str_1, m_str_2) \ + LU_2x2(m_str_0, m_str_1) \ + m_str_0[2] /= m_str_0[0]; \ + m_str_1[2] -= m_str_0[1] * m_str_1[0]; \ + m_str_1[2] /= m_str_1[1]; \ + m_str_2[1] -= m_str_0[1] * m_str_2[0]; \ + m_str_2[2] -= m_str_0[2] * m_str_2[0]; \ + m_str_2[2] -= m_str_2[1] * m_str_1[2]; + + + + +/*! + \fn int lu_block_decomposition (int matrix_size, double *block, int block_size) + \brief build lu decomposition for matrix lock + \param matrix_size -- size of matrix + \param block -- poiter to the first element of block, if need to decompose full + matrix send pointer to the matrix and set block_size to zero, + matrix must be stored by strings + \param block_size -- size of block + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_block_decomposition (i_type matrix_size, fp_type *block, i_type block_size) +{ + using namespace blue_sky; + + BS_ASSERT (block); + BS_ASSERT (matrix_size >= 1) (matrix_size); + BS_ASSERT (block_size == matrix_size) (block_size) (matrix_size); + + // declaration + i_type i, j, k; + + // main loop + fp_type *uprow = &block[0]; + for (k = 0; k < block_size; ++k, uprow += matrix_size) + { + // check diagonal element + if (fabs (uprow[k]) < MIN_DIV) + return -2; + + fp_type diag = (fp_type)(1.0 / uprow[k]); + for (j = k + 1; j < block_size; ++j) + { + uprow[j] *= diag; + } + + // upgrade other elements + fp_type *row = &block[(k + 1) * matrix_size]; + for (i = k + 1; i < block_size; ++i, row += matrix_size) + { + fp_type row_k = row[k]; + for (j = k + 1; j < block_size; ++j) + { + row[j] -= uprow[j] * row_k; + } + } + } + return 0; +} + + +/*! + \fn int lu_block_find_L_roots (int matrix_size, double *block, + double *r_side, int block_size = 0) + \brief find y in Ly = b + \param matrix_size -- size of matrix + \param block -- poiter to the first element of block, if need to find roots in full + matrix send pointer to the matrix and set block_size to zero, + matrix must be stored by strings + \param r_side -- pointer to the first element of block in right side array + \param block_size -- size of block + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_block_find_L_roots (i_type matrix_size, fp_type *block, fp_type *r_side, i_type block_size) +{ + using namespace blue_sky; + BS_ASSERT (block); + BS_ASSERT (r_side); + BS_ASSERT (matrix_size >= 1) (matrix_size); + BS_ASSERT (block_size >= 1) (block_size); + BS_ASSERT (block_size == matrix_size) (block_size) (matrix_size); + + for (i_type i = 0; i < block_size; ++i) + { + BS_ASSERT (fabs (block [i * matrix_size + i]) >= MIN_DIV) (i) (matrix_size) (block [i * matrix_size + i]) (MIN_DIV); + //if (fabs (block[i * matrix_size + i]) < MIN_DIV) + // { + // return -2; + // } + + r_side[i] /= block[i * matrix_size + i]; + fp_type r_side_i = r_side[i]; + fp_type *b = &block[(i + 1) * matrix_size + i]; + for (i_type j = i + 1; j < block_size; ++j, b += matrix_size) + { + r_side[j] -= r_side_i * b[0]; + } + } + return 0; +} + +/*! + \fn int lu_block_find_U_roots (int matrix_size, double *block, + double *r_side, int block_size = 0) + \brief find x in Lx = y + \param matrix_size -- size of matrix + \param block -- poiter to the first element of block, if need to find roots in full + matrix send pointer to the matrix and set block_size to zero, + matrix must be stored by strings + \param r_side -- pointer to the first element of block in right side array + \param block_size -- size of block + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_block_find_U_roots (i_type matrix_size, fp_type *block, fp_type *r_side, i_type block_size) +{ + using namespace blue_sky; + BS_ASSERT (block); + BS_ASSERT (r_side); + BS_ASSERT (matrix_size >= 1) (matrix_size); + BS_ASSERT (block_size >= 1) (block_size); + BS_ASSERT (block_size == matrix_size) (block_size) (matrix_size); + + for (i_type i = block_size - 1; i >= 0; --i) + { + fp_type r_side_i = r_side[i]; + fp_type *b = &block[(i - 1) * matrix_size + i]; + for (i_type j = i - 1; j >= 0; --j, b -= matrix_size) + { + r_side[j] -= r_side_i * b[0]; + } + } + return 0; +} + +/*! + \fn int lu_block_find_U (int matrix_size, double *block_L, + double *block_U, int nrow, int ncol) + \brief find U in LU = A using known L and A + \param matrix_size -- size of matrix + \param block_L -- poiter to the first element of block L + \param block_U -- pointer to the first element of block A and U + \param block_size -- size of block + \param ncol -- number of columns in U block + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_block_find_U (i_type matrix_size, fp_type *block_L, fp_type *block_U, i_type block_size, i_type ncol) +{ + i_type i, j, k; + // check input variables + if (matrix_size < 1 || !block_L || !block_U) + return -1; + for (k = 0; k < ncol; ++k) + { + for (i = 0; i < block_size; ++i) + { + //todo: not need to check values every time + if (fabs (block_L[i * matrix_size + i]) < MIN_DIV) + return -2; + block_U[i * matrix_size + k] /= block_L[i * matrix_size + i]; + for (j = i + 1; j < block_size; ++j) + block_U[j * matrix_size + k] -= block_U[i * matrix_size + k] + * block_L[j * matrix_size + i]; + } + + } + return 0; +} + +/*! + \fn int lu_block_find_L (int matrix_size, double *block_L, + double *block_U, int nrow, int ncol) + \brief find L in LU = A using known U and A + \param matrix_size -- size of matrix + \param block_L -- poiter to the first element of block L and A + \param block_U -- pointer to the first element of block U + \param nrow -- number of rows in L block + \param block_size -- size of block + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_block_find_L (i_type matrix_size, fp_type *block_L, fp_type *block_U, i_type block_size, i_type nrow) +{ + i_type i, j, k; + // check input variables + if (matrix_size < 1 || !block_L || !block_U) + return -1; + for (k = 0; k < nrow; ++k) + { + for (i = 0; i < block_size; ++i) + { + for (j = i + 1; j < block_size; ++j) + block_L[j + k * matrix_size] -= block_L[i + k * matrix_size] + * block_U[j + i * matrix_size]; + } + + } + return 0; +} + +/*! + \fn int lu_block_upgrade (int matrix_size, double *block_A, double *block_L, + double *block_U, int block_size, int nrow, int ncol) + \brief update block_A using given block_L and block_U + \param matrix_size -- size of matrix + \param block_A -- pointer to the first element of block A + \param block_L -- poiter to the first element of block L + \param block_U -- pointer to the first element of block U + \param block_size -- size of block + \param nrow -- number of rows in L block + \param ncol -- number of columns in U block + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_block_upgrade (i_type matrix_size, fp_type *block_A, fp_type *block_L, + fp_type *block_U, i_type block_size, i_type nrow, i_type ncol) +{ + i_type i, j, k; + fp_type update_value; + + // check input data + if (!block_A || !block_L || !block_U || matrix_size < 1 + || block_size < 1 || nrow < 1 || ncol < 1) + return -1; + + // main loop + for (i = 0; i < nrow; ++i) + { + for (j = 0; j < ncol; ++j) + { + update_value = 0; + for (k = 0; k < block_size; ++k) + update_value += block_L[i * matrix_size + k] * block_U[k * matrix_size +j]; + block_A[i * matrix_size + j] -= update_value; + } + } + return 0; +} + +/*! + \fn int lu_decomposition (int matrix_size, double *matrix, int block_size) + \brief build lu decomposition using block method on one thread + \param matrix_size -- size of matrix + \param matrix -- matrix to decompose + \param block_size -- size of block (default value is 60) + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_decomposition (i_type matrix_size, fp_type *matrix, i_type block_size) +{ + i_type i, j, k; + i_type global_i; + i_type ret_code; + // last block size + i_type last_block_size; + // number of blocks in matrix string + i_type number_of_blocks; + // block on the corner + fp_type *corner_block = 0; + // L block + fp_type *block_L = 0; + // U block + fp_type *block_U = 0; + // A block + fp_type *block_A = 0; + + + // check input data + if (matrix_size < 1 || !matrix) + return -1; + if (block_size >= matrix_size || block_size < 2) + return lu_block_decomposition (matrix_size, matrix); + + // calculate number of blocks and size of last block + number_of_blocks = matrix_size / block_size; + last_block_size = matrix_size % block_size; + if (last_block_size > 0) + ++number_of_blocks; + else + last_block_size = block_size; + + // main loop + for (i = 0; i < number_of_blocks; ++i) + { + // find LU decomposition for block[i, i] + global_i = i * block_size; + corner_block = &(matrix[global_i * matrix_size + global_i]); + ret_code = lu_block_decomposition (matrix_size, + corner_block, + ((i + 1) < number_of_blocks ? block_size : last_block_size)); + if (ret_code) return ret_code; + + // find all U blocks in block string + for (k = i + 1; k < number_of_blocks; ++k) + { + ret_code = lu_block_find_U (matrix_size, + corner_block, + &(matrix[global_i * matrix_size + k * block_size]), + block_size, + ((k + 1) < number_of_blocks ? block_size : last_block_size)); + if (ret_code) return ret_code; + } + // find all L blocks in block column + for (k = i + 1; k < number_of_blocks; ++k) + { + ret_code = lu_block_find_L (matrix_size, + &(matrix[k * block_size * matrix_size + global_i]), + corner_block, + block_size, + ((k + 1) < number_of_blocks ? block_size : last_block_size)); + if (ret_code) return ret_code; + } + // update other blocks + for (k = i + 1; k < number_of_blocks; ++k) + { + block_L = &(matrix[k * block_size * matrix_size + global_i]); + for (j = i + 1; j < number_of_blocks; ++j) + { + block_U = &(matrix[global_i * matrix_size + j * block_size]); + block_A = &(matrix[k * block_size * matrix_size + j * block_size]); + ret_code = lu_block_upgrade (matrix_size, block_A, block_L, block_U, block_size, + ((k + 1) < number_of_blocks ? block_size : last_block_size), + ((j + 1) < number_of_blocks ? block_size : last_block_size)); + if (ret_code) return ret_code; + } + } + } + return 0; +} + +/*! + \fn int lu_upgrade_right_side (int matrix_size, double *block, int nrow, int ncol, + double *roots, double *r_side) + \brief update right side + \param matrix_size -- size of matrix + \param block -- pointer to the first element of block + \param nrow -- number of rows in upgrade block + \param ncol -- number of columns in upgrade block + \param roots -- known vector of roots + \param r_side -- vector of upgrade roots + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_upgrade_right_side (i_type matrix_size, fp_type *block, i_type nrow, i_type ncol, + fp_type *roots, fp_type *r_side) +{ + i_type i, j; + fp_type upgrade_value = 0; + fp_type *block_row = 0; + + // check input data + if (matrix_size < 1 || !block || nrow < 1 || ncol < 1 || !roots || !r_side) + return -1; + + for (i = 0; i < nrow; ++i) + { + upgrade_value = 0; + block_row = &(block[i * matrix_size]); + for (j = 0; j < ncol; ++j) + upgrade_value += block_row[j] * roots[j]; + r_side[i] -= upgrade_value; + } + return 0; +} + + +/*! + \fn int lu_find_L_roots (int matrix_size, double *matrix, double *r_side, + int block_size = DEF_BLOCK_SIZE) + \brief find y in Ly = b + \param matrix_size -- size of matrix + \param matrix -- pointer to the lu matrix + \param r_side -- given right side + \param block_size -- block size, default value DEF_BLOCK_SIZE + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_find_L_roots (i_type matrix_size, fp_type *matrix, fp_type *r_side, i_type block_size) +{ + i_type i; + i_type k; + i_type ret_code; + // last block size + i_type last_block_size; + // number of blocks in matrix string + i_type number_of_blocks; + + // check input data + if (matrix_size < 1 || !matrix || !r_side || block_size < 1) + return -1; + + // calculate number of blocks and size of last block + number_of_blocks = matrix_size / block_size; + last_block_size = matrix_size % block_size; + if (last_block_size > 0) + ++number_of_blocks; + else + last_block_size = block_size; + + // main loop + for (i = 0; i < number_of_blocks; ++i) + {//libconfig::ParseException + ret_code = lu_block_find_L_roots (matrix_size, + &(matrix[i * block_size * (matrix_size + 1)]), + &(r_side[i * block_size]), + ((i + 1) < number_of_blocks ? block_size : last_block_size)); + if (ret_code) return ret_code; + + // update all blocks in block column + for (k = i + 1; k < number_of_blocks; ++k) + { + ret_code = lu_upgrade_right_side (matrix_size, + &(matrix[(k * matrix_size + i) * block_size]), + ((k + 1) < number_of_blocks ? block_size :last_block_size), + ((i + 1) < number_of_blocks ? block_size :last_block_size), + &(r_side[i * block_size]), + &(r_side[k * block_size])); + if (ret_code) return ret_code; + + } + } + return 0; +} + +/*! + \fn int lu_find_U_roots (int matrix_size, double *matrix, double *r_side, + int block_size = DEF_BLOCK_SIZE) + \brief find x in Ux = y + \param matrix_size -- size of matrix + \param matrix -- pointer to the lu matrix + \param r_side -- given right side + \param block_size -- block size, default value DEF_BLOCK_SIZE + \return 0 if success + \return < 0 if error occur +*/ +template i_type +lu_tools::lu_find_U_roots (i_type matrix_size, fp_type *matrix, fp_type *r_side, i_type block_size) +{ + i_type i; + i_type k; + i_type ret_code; + // last block size + i_type last_block_size; + // number of blocks in matrix string + i_type number_of_blocks; + + // check input datalibconfig::ParseException + if (matrix_size < 1 || !matrix || !r_side || block_size < 1) + return -1; + + // calculate number of blocks and size of last block + number_of_blocks = matrix_size / block_size; + last_block_size = matrix_size % block_size; + if (last_block_size > 0) + ++number_of_blocks; + else + last_block_size = block_size; + + // main loop + for (i = number_of_blocks - 1; i >= 0; --i) + { + ret_code = lu_block_find_U_roots (matrix_size, + &(matrix[i * block_size * (matrix_size + 1)]), + &(r_side[i * block_size]), + ((i + 1) < number_of_blocks ? block_size : last_block_size)); + if (ret_code) return ret_code; + + // update all blocks in block column + for (k = i - 1; k >= 0; --k) + { + ret_code = lu_upgrade_right_side (matrix_size, + &(matrix[(k * matrix_size + i) * block_size]), + ((k + 1) < number_of_blocks ? block_size :last_block_size), + ((i + 1) < number_of_blocks ? block_size :last_block_size), + &(r_side[i * block_size]), + &(r_side[k * block_size])); + if (ret_code) return ret_code; + + } + } + return 0; +} + +template struct lu_tools; +template struct lu_tools; diff --git a/bs_base_linear_solvers/src/py_linear_solvers.cpp b/bs_base_linear_solvers/src/py_linear_solvers.cpp new file mode 100644 index 0000000..c7d2e75 --- /dev/null +++ b/bs_base_linear_solvers/src/py_linear_solvers.cpp @@ -0,0 +1,57 @@ +/** +* \file py_linear_solvers.cpp +* \brief Python wrapper for linear solvers +* \author Miryanov Sergey +* \date 2008-04-04 +*/ + +#include "bs_base_linear_solvers_stdafx.h" +#include "py_linear_solvers.h" + +using namespace boost::python; +#ifdef BSPY_EXPORTING_PLUGIN + +namespace blue_sky { +namespace python { + ////////////////////////////////////////////////////////////////////////// + //! export linear_solver_prop to python + void py_export_linear_solver_prop () + { + class_ , boost::noncopyable>("linear_solver_prop", no_init) + .def ("__cons__", make_constructor (construct_python_object )) + .def ("__init__", make_function (init_python_object )) + .def ("set_max_iters", &linear_solver_prop::set_max_iters) + .def ("set_tolerance", &linear_solver_prop::set_tolerance) + .def ("check_convergence", &linear_solver_prop::check_convergence) + .def ("get_iters", &linear_solver_prop::get_iters) + .def ("set_iters", &linear_solver_prop::set_iters) + .def ("get_relative_factor", &linear_solver_prop::get_relative_factor) + .def ("get_max_iters", &linear_solver_prop::get_max_iters) + .def ("get_tolerance", &linear_solver_prop::get_tolerance) + .def ("get_final_resid", &linear_solver_prop::get_final_resid) + ; + } + + ////////////////////////////////////////////////////////////////////////// + //! export linear solvers to python + void py_export_linear_solvers () + { + using namespace boost::python; + + strategy_exporter::export_base ("linear_solver"); + + strategy_exporter::export_class ("linear_solver_wrapper"); + strategy_exporter::export_class ("gmres_solver2_seq"); + strategy_exporter::export_class ("bicgstab_solver_seq"); + strategy_exporter::export_class ("cgs_solver_seq"); + strategy_exporter::export_class ("tfqmr_solver_seq"); + +#ifdef _MPI + solver_export , py_matrix_base , mpi_vector > > > ("gmres_solver2_mpi_di"); +#endif + } + +} // namespace python +} // namespace blue_sky +#endif // #ifdef BSPY_EXPORTING_PLUGIN + diff --git a/bs_base_linear_solvers/src/stdafx.cpp b/bs_base_linear_solvers/src/stdafx.cpp new file mode 100644 index 0000000..3b9e69b --- /dev/null +++ b/bs_base_linear_solvers/src/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// bs_base_linear_solvers.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "bs_base_linear_solvers_stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/bs_base_linear_solvers/src/tfqmr.cpp b/bs_base_linear_solvers/src/tfqmr.cpp new file mode 100644 index 0000000..fe3d331 --- /dev/null +++ b/bs_base_linear_solvers/src/tfqmr.cpp @@ -0,0 +1,351 @@ +/** + * \file tfqmr.cpp + * \brief TFQMR linear solver impl + * \author Salimgareeva E.M. (algorithm from "A fast Lanczos-type solver for nonsymmetric linear systems", P.Sonneveld) + * \date 11.02.2009 + * */ +#include "bs_base_linear_solvers_stdafx.h" +#include "linear_solvers.h" +#include "tfqmr.h" +#include "lin_solv_macro.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "save_seq_vector.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + ////////////////////////////////////////////////////////////////////////// + // tfqmr_solver + + //! constructor + template + tfqmr_solver::tfqmr_solver (bs_type_ctor_param param) + : linear_solver_base (param) + {} + + //! copy constructor + template + tfqmr_solver::tfqmr_solver(const tfqmr_solver &solver) + : bs_refcounter (), linear_solver_base (solver) + { + if (&solver != this) + *this = solver; + } + + //! destructor + template + tfqmr_solver::~tfqmr_solver () + {} + + + template + int tfqmr_solver::solve(matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + template + int tfqmr_solver::solve_prec(matrix_t *matrix, item_array_t &rhs, item_array_t &solution) + { + return templ_solve (matrix, rhs, solution); + } + + + + /*! + * \brief TFQMR linear solver + * + * \param[in] matrix -- pointer to the matrix + * \param[in] rhs -- right hand side + * \param[out] solution -- solution + * + * \return 0 if success + */ + template template + int tfqmr_solver::templ_solve(matrix_t *matrix1, rhs_t &rhs, item_array_t &solution) + { + BOSOUT (section::solvers, level::debug) << "TFQMR\n" << bs_end; + typedef item_t fp_type; + + BS_ERROR (matrix1, "tfqmr_solve"); + setup_preconditioner *setup_prec = dynamic_cast *> (static_cast (matrix1)); + + sp_bcsr_matrix_t matrix; + if (setup_prec) + { + setup_prec->prepare_matrix (); + matrix = setup_prec->get_prepared_matrix (); + BS_ASSERT (matrix); + } + else + { + matrix = sp_bcsr_matrix_t (matrix1, bs_dynamic_cast ()); + } + + BS_ERROR (rhs.size (), "tfqmr_solve"); + BS_ERROR (solution.size (), "tfqmr_solve"); + BS_ERROR (base_t::prop, "tfqmr_solve"); + + const smart_ptr &lprop(this->prop); + + fp_type rho_1, rho_2 = 1, alpha = 1, beta, sigma; + int iter; + const double epsmac = 1e-24; + fp_type r_norm = 0; + fp_type b_norm = 0; + fp_type den_norm = 0; + fp_type r_norm_old = 0; + fp_type w_norm = 0; + fp_type eta = 0; + fp_type nu = 0; + fp_type tau = 0; + fp_type c = 0; + //fp_type *x = solution; + + //OMP_TIME_MEASURE_START (tfqmr_solve_timer); + + item_t tol = this->prop->get_tolerance (); + tol *= tol; + //resid = prop->get_residuals (); + //convergence_rate = prop->get_convergence_rate (); + + index_t max_iter = this->prop->get_max_iters (); + index_t n = matrix->n_rows * matrix->n_block_size; + + item_array_t p (n); + item_array_t v (n); + item_array_t w (n); + item_array_t u (n); + item_array_t q (n); + item_array_t d (n); + item_array_t res (n); + item_array_t r (n); + item_array_t rtilde (n); + item_array_t tmp (n); + item_array_t rhat (n); + item_array_t y (n); + //x_cgs = y + n; + + lprop->set_success (0); + + // solution = {0} + solution.assign (n, 0); + // r = {0} + r.assign (n, 0); + // TODO:paste + tmp.assign (n, 0); + p.assign (n, 0); + v.assign (n, 0); + q.assign (n, 0); + d.assign (n, 0); + + // r = Ax0 - b + matrix->calc_lin_comb (-1.0, 1.0, solution, rhs, r); + rtilde.assign (r.begin (), r.end ()); + + // p0 = u0 = r0; + //memcpy (p, r, n * sizeof (double)); + u.assign (r.begin (), r.end ()); + p.assign (r.begin (), r.end ()); + w.assign (r.begin (), r.end ()); + + // tmp = M^(-1) * u; + if (this->prec) + { + if (base_t::prec->solve_prec (matrix, u, tmp)) + { + bs_throw_exception ("TFQMR: Preconditioner failed"); + } + u.assign (tmp.begin (), tmp.end ()); + p.assign (u.begin (), u.end ()); + } + + matrix->matrix_vector_product (p, v); + + //tools::save_seq_vector (tools::string_formater ("1_well_bhp.%s.txt", it->first).str).save (it->second); + + r_norm = bos_helper::mv_vector_inner_product (r, r); + + + if (r_norm <= tol) // initial guess quite good + return 0; + + tau = sqrt (r_norm); + rho_1 = r_norm; + rho_2 = r_norm; + b_norm = sqrt (bos_helper::mv_vector_inner_product (rhs, rhs)); + + + if (b_norm > epsmac) // choose convergence criterion + { + // |r_i|/|b| <= eps if |b| > 0 + tol *= b_norm; + den_norm = b_norm; + } + else // (r_norm > epsmac) + { + // |r_i|/|r0| <= eps if |b| = 0 + tol *= r_norm; + den_norm = r_norm; + } + + // set up initial norm and convergense factor + lprop->set_relative_factor (den_norm); + + index_t m, count; + // main loop + for (iter = 0; iter < max_iter; ++iter) + { + //printf ("TFQMR iteration: %d, resid = %le\n", iter, r_norm); + //fflush (stdout); + // TODO: paste + if (iter) + { + //rho_1 = mv_vector_inner_product (r, rtilde, n);//in first iter equals to r_norm + if (rho_1 == 0) // failure + { + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + bs_throw_exception ("TFQMR: Failure - rho_1 == 0"); + } + sum_vector (u, 1., res, beta, p); //p[n] = u[n]+beta*res + + v.assign (n, 0); + matrix->matrix_vector_product (p, v); //v[n]=Ap[n] + } + + sigma = bos_helper::mv_vector_inner_product (rtilde, v); //sigma=(rtilde,v[n-1]) + + alpha = rho_1/sigma; + + // tmp = M^(-1)*v + if (this->prec) + { + if (base_t::prec->solve_prec (matrix, v, tmp)) + { + bs_throw_exception ("TFQMR: Preconditioner failed"); + } + v.assign (tmp.begin (), tmp.end ()); + } + + sum_vector (u, 1., v, -alpha, q); //q[n] = u[n-1]-alpha*v[n-1] + sum_vector (u, 1., q, 1., res); //res = u[n-1]+q[n] + + tmp.assign (n, 0); + matrix->matrix_vector_product (res, tmp);// tmp=A*res + sum_vector (r, 1., tmp, -alpha, r);// r=r-alpha*res + + //r_norm_old = r_norm; + r_norm = bos_helper::mv_vector_inner_product (r, r); + + for (m = 1; m <= 2 ; m++) + { + if (m == 1) // m is odd + { + y.assign (u.begin (), u.end ()); + w_norm = sqrt(r_norm * r_norm_old); + } + else // m is even + { + y.assign (q.begin (), q.end ()); + w_norm = sqrt(r_norm); + } + + sum_vector (y, 1., d, eta*nu*nu/alpha, d); //d[m] = y[m] + (eta[m-1]*nu[m-1]^2/alpha[n-1])*d[m-1] + nu = w_norm/tau; //nu[m]=||w[m+1]||/tau[m-1] + c = 1./sqrt (1. + nu*nu); + tau = tau*c*nu; //tau[m]=tau[m-1]nu[m]c[m] + eta = c*c*alpha; //eta[m]=c[m]^2*alpha[n-1] + //SUM_VECTOR(x,d,1,alpha,x_cgs,k,n); //x_cgs[n] = x[2n-1]+alpha[n-1]*d[2n] + sum_vector (solution, 1., d, eta, solution); //x[m] = x[m-1]+eta[m]*d[m] + if (r_norm <= tol) + { + count = 1; + break; + } + } + + if (r_norm <= tol) + break; + + rho_1 = bos_helper::mv_vector_inner_product (r, rtilde, n);//in first iter equals to r_norm + beta = rho_1 / rho_2; + + // rhat = M^(-1) * r; + if (this->prec) + { + if (base_t::prec->solve_prec (matrix, r, rhat)) + { + bs_throw_exception ("TFQMR: Preconditioner failed"); + } + } + else // no precondition (preconditioner=identity_matrix) + { + rhat.assign (r.begin (), r.end ()); + } + + sum_vector (rhat, 1., q, beta, u); //u[n] = r[n]+beta*q[n] + sum_vector (q, 1., p, beta, res); //res = q[n]+beta*p[n-1] + + rho_2 = rho_1; + } + + //TODO: end + lprop->set_iters (iter + 1); + lprop->set_success (1); + + /* + //additional checking convergence + mv_calc_lin_comb (matrix, -1.0, 1.0, solution, rhs, r); + r_norm = mv_vector_inner_product (r, r, n); + */ + if (den_norm > epsmac) + lprop->set_final_resid (r_norm / den_norm); + else + lprop->set_final_resid (r_norm); + + //printf ("TFQMR OK! iters = %d, resid = %le\n", lprop->iters, lprop->final_resid); + //OMP_TIME_MEASURE_END (tfqmr_solve_timer); + + return 0; + } + + /** + * @brief setup for TFQMR + * + * @param matrix -- input matrix + * + * @return 0 if success + */ + template int + tfqmr_solver::setup (matrix_t *matrix) + { + if (!matrix) + { + bs_throw_exception ("TFQMR: Passed matrix is null"); + } + + BS_ASSERT (base_t::prop); + if (base_t::prec) + { + return base_t::prec->setup (matrix); + } + + return 0; + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF(tfqmr_solver, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(tfqmr_solver, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (tfqmr_solver) , 1, (linear_solver_base), "tfqmr_solver_base_fi", "tfqmr linear solver", "TFQMR linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (tfqmr_solver) , 1, (linear_solver_base), "tfqmr_solver_base_di", "tfqmr linear solver", "TFQMR linear solver", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (tfqmr_solver) , 1, (linear_solver_base), "tfqmr_solver_base_mixi", "TFQMR linear solver", "TFQMR linear solver", false); + + + } diff --git a/bs_bos_core/SConscript.bs b/bs_bos_core/SConscript.bs new file mode 100644 index 0000000..60840fa --- /dev/null +++ b/bs_bos_core/SConscript.bs @@ -0,0 +1,55 @@ +import os +Import ("*") + +lib_name = "bs_bos_core" +tar_name = "bs_bos_core" + +env = custom_env.Clone () +env.Append (CPPPATH = ["include", + includes["bs_bos_core_base"], + includes["bs_matrix"], + includes["bs_base_linear_solvers"], + includes["bs_csr_ilu_prec"], + includes["bs_bos_core_data_storage"], + includes["bs_mesh_mpfa"], + includes["bs_scal"], + includes["bs_pvt"] + ] + includes["kernel"] + + includes["bs_mesh"] + ) + +libs = ["blue_sky", + "bs_bos_core_base", + "bs_matrix", + "bs_base_linear_solvers", + "bs_csr_ilu_prec", + "bs_bos_core_data_storage", + "bs_scal", + "bs_pvt" + ] + +boost_libs = ["boost_date_time-mt"] + +if (env["cfl"] == "1") : + env.AppendUnique (CPPDEFINES = ["BS_BOS_CORE_USE_CSR_ILU_CFL_PREC"]) + +if (env["hdf5"] == "1") : + env.AppendUnique (CPPDEFINES = defines["bs_hdf5_storage"], CPPPATH = includes["bs_hdf5_storage"]) + libs = libs + ["bs_hdf5_storage"] + +if (build_kind == "debug") : + env.AppendUnique (LIBS = list_suffix (libs, "_d") + list_suffix (boost_libs, "-d")) + lib_name += "_d" +elif (build_kind == "release") : + env.AppendUnique (LIBS = libs + boost_libs) + +bs_bos_core = env.SharedLibrary (target = os.path.join (tar_exe_plugin_dir, lib_name), source = files (["."]).sources) + +env.Alias (tar_name, bs_bos_core) +Export ("bs_bos_core") + +if (env["install"] == 1) : + inst_tar = env.Install ("$plugins_prefix", bs_bos_core) + env.Alias (tar_name, inst_tar) + + diff --git a/bs_bos_core/bs_bos_core.cbp b/bs_bos_core/bs_bos_core.cbp new file mode 100644 index 0000000..ee34bb8 --- /dev/null +++ b/bs_bos_core/bs_bos_core.cbp @@ -0,0 +1,509 @@ + + + + + + diff --git a/bs_bos_core/bs_bos_core.vcproj b/bs_bos_core/bs_bos_core.vcproj new file mode 100644 index 0000000..3c8a974 --- /dev/null +++ b/bs_bos_core/bs_bos_core.vcproj @@ -0,0 +1,1997 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bs_bos_core/include/apply_wefac.h b/bs_bos_core/include/apply_wefac.h new file mode 100644 index 0000000..5d43c49 --- /dev/null +++ b/bs_bos_core/include/apply_wefac.h @@ -0,0 +1,20 @@ +/** + * + * */ +#ifndef BS_MAIN_LOOP_CALC_APPLY_WEFAC_H_ +#define BS_MAIN_LOOP_CALC_APPLY_WEFAC_H_ + +namespace blue_sky + { + + template + inline item_t + apply_wefac (item_t item, wefac_t wefac) + { + return wefac > 0. ? (item_t)(wefac * item) : (item); + } + +} // namespace blue_sky + + +#endif // #ifndef BS_MAIN_LOOP_CALC_APPLY_WEFAC_H_ diff --git a/bs_bos_core/include/calc_model.h b/bs_bos_core/include/calc_model.h new file mode 100644 index 0000000..78ae8eb --- /dev/null +++ b/bs_bos_core/include/calc_model.h @@ -0,0 +1,388 @@ +#ifndef CALC_MODEL_H +#define CALC_MODEL_H + +#include BS_FORCE_PLUGIN_IMPORT () +#include "convert_units.h" +#include "constants.h" +#include "prvd_table.h" +#include "arrays.h" +#include "rocktab_table.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "fi_params.h" +#include "well_type_helper.h" +#include "norm_calc.h" +#include "array_ext.h" +#include "jacobian.h" + +#include "calc_model_data.h" + +namespace blue_sky + { + + enum restore_solution_return_type + { + SMALL_TIME_STEP_FAIL = -1, + SMALL_TIME_STEP_OK = 0, + SMALL_TIME_STEP_CHOP = 256, //#define YS_SMALL_TIME_STEP_CHOP (256) + }; + + template + class calc_model; + + template + struct well_mobility_calc; + + template + class well; + + template + class reservoir; + + namespace wells + { + template + class connection; + } + + /* + template + class BS_API_PLUGIN rs_mesh_iface; + + template + class BS_API_PLUGIN rs_mesh_struct_iface; + */ + + class well_results_storage; + class fip_results_storage; + /////////////////////////////////////////////////////////////////////////// + + + template + struct BS_API_PLUGIN calc_model_data_tmp_holder + { + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::template vec ::type main_var_array_t; + typedef calc_model calc_model_t; + typedef smart_ptr sp_calc_model_t; + +public: + + void save (const sp_calc_model_t &calc_model); + void restore (sp_calc_model_t &calc_model); + +public: + item_array_t pressure; + item_array_t saturation_3p; + item_array_t gas_oil_ratio; + main_var_array_t main_var; + }; + + /////////////////////////////////////////////////////////////////////////// + template + class BS_API_PLUGIN calc_model : public bs_node + { + public: + + typedef strategy_t strategy_type; + + typedef calc_model this_t; + typedef smart_ptr sp_this_t; + + typedef jacobian jacobian_t; + typedef smart_ptr sp_jacobian_t; + typedef jacobian_matrix jacobian_matrix_t; + typedef smart_ptr sp_jacobian_matrix_t; + + typedef idata idata_t; + typedef smart_ptr sp_idata_t; + + typedef rs_mesh_iface mesh_iface_t; + typedef smart_ptr sp_mesh_iface_t; + + typedef rs_smesh_iface smesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + + typedef reservoir reservoir_t; //!< short name + typedef smart_ptr sp_reservoir_t; //!< short name + + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + + typedef typename strategy_t::csr_matrix_t csr_matrix_t; + typedef smart_ptr sp_csr_matrix_t; + + typedef calc_model_data data_t; + typedef typename strategy_t::template vec ::type data_array_t; + + typedef scal_3p scal_3p_t; + typedef scale_array_holder scale_array_holder_t; + + typedef wells::connection connection_t; + typedef well well_t; + + typedef smart_ptr< scal_3p_t, true> sp_scal3p; + typedef smart_ptr sp_scale_array_holder_t; + + typedef smart_ptr< rock_grid< strategy_t >, true> sp_rock_grid; + typedef smart_ptr< fi_params, true> sp_fi_params; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_well_t; + + typedef smart_ptr sp_well_results_storage; + typedef smart_ptr sp_fip_results_storage; + + typedef pvt_base< strategy_t > pvt_base_t; + typedef pvt_oil < strategy_t > pvt_oil_t; + typedef pvt_dead_oil< strategy_t > pvt_dead_oil_t; + typedef pvt_gas< strategy_t > pvt_gas_t; + typedef pvt_water< strategy_t > pvt_water_t; + + typedef smart_ptr sp_pvt_t; + typedef smart_ptr sp_pvt_oil; + typedef smart_ptr sp_pvt_dead_oil; + typedef smart_ptr sp_pvt_gas; + typedef smart_ptr sp_pvt_water; + + typedef std::vector< sp_pvt_t > sp_pvt_array_t; + typedef std::vector< sp_pvt_oil > sp_pvt_oil_array_t; + typedef std::vector< sp_pvt_dead_oil > sp_pvt_dead_oil_array_t; + typedef std::vector< sp_pvt_gas > sp_pvt_gas_array_t; + typedef std::vector< sp_pvt_water > sp_pvt_water_array_t; + + typedef std::vector< int > vec_i; + + typedef boost::array phase_d_t; + typedef boost::array sat_d_t; + + typedef typename strategy_t::template vec ::type main_var_array_t; + + typedef norms_storage norms_storage_t; + + typedef calc_model_data_tmp_holder calc_model_data_tmp_holder_t; + typedef well_mobility_calc well_mobility_calc_t; + + typedef wells::type_helper helper_t; + + typedef typename helper_t::item_q_rate_t item_q_rate_t; + typedef typename helper_t::item_q_rate_inflow_t item_q_rate_inflow_t; + typedef typename helper_t::item_gas_rate_t item_gas_rate_t; + typedef typename helper_t::invers_fvf_avgerage_t invers_fvf_avgerage_t; + + typedef boost::array up_cell_array_t; + + public: + + ~calc_model(); + + void init(); + + const this_t &operator=(const this_t &src); + + // initialize main arrays + int init_main_arrays (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + // initialize arrays for calculation process + int init_calcul_arrays (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + // init initial conditions + int set_initial_data (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + // calc equilibrium + int calc_equil (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + // calc pressure for equil + int equil_calc_pressure (item_t prev_press, item_t cur_d, item_t h, index_t phase, index_t i_pvt, + double rs_type, item_t depth_goc, item_t rs_dat, + val_vs_depth *rsvd, val_vs_depth *pbvd, + item_t &p, item_t *rs = 0); + // initialize saturation array + int init_pressure (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + // initialize saturation array + int init_saturation (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + // initialize phases variables (rs) and select number of phases + int init_rs (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + //int initialize_gas_oil_fluid_volume (const sp_idata_t &input_data); + + // prepare arrays for rst file + //int prepare_data_for_rst (const sp_idata_t &input_data, const sp_mesh &mesh); + + // make initialization for gas-oil model (2ph or 3phase) by solving equation of mass + //int fi_initialization_gas_oil_model (int istart, const sp_idata_t &input_data); + + void init_scale_arrays (const sp_scale_array_holder_t &array_, + const sp_idata_t &idata_, + ARRAY_NAME socr, + ARRAY_NAME scr, + ARRAY_NAME su, + ARRAY_NAME sl, + ARRAY_NAME pc); + void init_scal (); + + void init_pvt_arrays (sp_pvt_oil_array_t &pvto_, + sp_pvt_gas_array_t &pvtg_, + sp_pvt_water_array_t &pvtw_, + const sp_idata_t &idata_); + + static bool is_water_phase (int phases) + { + return FI_CHK_WATER (phases); + } + static bool is_gas_phase (int phases) + { + return FI_CHK_GAS (phases); + } + static bool is_oil_phase (int phases) + { + return FI_CHK_OIL (phases); + } + + const data_t &get_data (index_t n_block) const + { + return data[n_block]; + } + + item_t get_initial_rho (item_t height) const; + void update_min_pressure_range (item_t min_range); + void update_max_pressure_range (item_t max_range); + void calc_prev_fluid_volume (bool istart, const sp_mesh_iface_t &mesh); + + restore_solution_return_type + restore_solution (const sp_mesh_iface_t &mesh, const sp_jacobian_matrix_t &jacobian_mx); + + restore_solution_return_type + apply_newton_correction (item_t mult, index_t istart_line_search, const sp_mesh_iface_t &mesh, const sp_jacobian_matrix_t &jacobian_mx); + + item_t new_simple_get_cell_solution_mult (const sp_mesh_iface_t &mesh, const sp_jacobian_matrix_t &jacobian_mx); + item_t new_simple_get_cell_solution_mult_2 (const sp_mesh_iface_t &mesh, const sp_jacobian_matrix_t &jmatrix) const; + int new_simple_get_cell_solution (const double mult, int istart_linear_search, const sp_mesh_iface_t &msh, const sp_jacobian_matrix_t &jacobian_mx); + int calc_approx_so_sg_ro (const item_t mo_in, const item_t mg_in, const item_t poro, + const item_t ifvf_o, const item_t ifvf_g, const item_t max_ro, + // results + item_t &so, item_t &sg, item_t &ro, + main_var_type &m_var); + + void + init_jacobian (const sp_jacobian_t &input_data, const sp_mesh_iface_t &mesh); + + + bool is_water () const; + bool is_gas () const; + bool is_oil () const; + + index_t water_shift () const; + index_t gas_shift () const; + index_t oil_shift () const; + + + BLUE_SKY_TYPE_DECL_T (calc_model); + + private: + + void + init_boundary_connections (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + + public: + // Variables + main_var_array_t main_variable; //!< (n_elements) main variables (Sg or Ro) per each grid block + auto_value well_model_var_; //!< well model + auto_value well_model_type_; + norms_storage_t norm; + + sp_pvt_dead_oil_array_t pvt_oil_array; //!< (n_pvt_regions) + sp_pvt_water_array_t pvt_water_array; + sp_pvt_gas_array_t pvt_gas_array; + + data_array_t data; //!< n_elements size + + // workspace + item_array_t workspace; //!< n_elements * (n_phase) + + calc_model_data_tmp_holder_t old_data_; + calc_model_data_tmp_holder_t prev_niter_data_; + + //! pressure on the boundary + item_array_t bconn_pressure; + item_array_t bconn_saturation; + item_array_t bconn_gor; + index_array_t bconn_mainvar; + + auto_value linear_search_mult; + auto_value lsearch_force_newton_step; // flag : force to make newton step in any case + + auto_value b_w_w; + auto_value b_w_g; + auto_value b_w_p; + auto_value b_g_w; + auto_value b_g_g; + auto_value b_g_p; + auto_value b_o_w; + auto_value b_o_g; + auto_value b_o_p; + index_array_t iwksp; //!< n_elements + auto_value multi_well_in_cell_flag; //!< if != 0 use sorting + + auto_value ave_volume; + + index_array_t max_norm_counter; + + //! base parameters + public: + + auto_value n_comps; //!< number of components + auto_value n_phases; //!< number of phases + auto_value n_sec_vars; //!< number if secondary variables + auto_value phases; //!< sizeof (int) bit fields (1 -- phase present, 0 -- do not present) + auto_value n_HCcomps; //!< number of hydrocarbon components (n_comps = n_HCcomps + 1) + auto_value n_HCphases; //!< number of hydrocarbon phases (n_phases = n_HCphases + 1) + auto_value n_pri; //!< number of primary variables + auto_value n_sec; //!< number of secondary variables + auto_value n_vars; //!< full number of variables + + phase_d_t phase_d; //!< displacement of phase in arrays + sat_d_t sat_d; //!< displacement of phase in saturation array + + auto_value n_pvt_regions; //!< number of pvt regions + auto_value n_sat_regions; //!< number of sat regions + auto_value n_fip_regions; //!< number of fip regions + + physical_constants internal_constants; //!< physical constants in internal units + + index_array_t pvt_regions; //!< (n_elements) index of PVT table for given block zero base + index_array_t sat_regions; //!< (n_elements) index of SAT table for given block zero base + index_array_t fip_regions; //!< (n_elements) index of FIP region for cell + index_array_t rock_regions; //!< (n_elements) index of ROCK regions + + auto_value + rpo_model; //!< 3-ph oil relative permeability model: flag 0, 1 or 2 (stone model) + sp_scal3p scal_prop; //!< scal properties + sp_rock_grid rock_grid_prop; //!< rock and grid properties + + std::vector > rocktab; //!< (rocktab table) + + + auto_value last_c_norm; + auto_value approx_flag; // flag of initial approximation + + sp_fi_params ts_params; + invers_fvf_avgerage_t invers_fvf_average; //!< (n_phases) 1. / (formation volume factor) for all phases average + + item_array_t plane_flow_rate; //!< (n_planes * n_phases) flow rates for all planes on current time step + item_array_t full_step_plane_flow_rate; //!< (n_planes * n_phases) total flow rates on time step + + item_array_t pressure; + item_array_t saturation_3p; //!< (n_phases * n_elements) + item_array_t gas_oil_ratio; + + sp_csr_matrix_t mat; + sp_well_results_storage well_res; + sp_fip_results_storage fip_res; + }; +} + +#endif // CALC_MODEL_H diff --git a/bs_bos_core/include/calc_model_data.h b/bs_bos_core/include/calc_model_data.h new file mode 100644 index 0000000..be595df --- /dev/null +++ b/bs_bos_core/include/calc_model_data.h @@ -0,0 +1,154 @@ +/** + * \file calc_model_data.h + * \brief calc_model data holder + * \author Sergey Miryanov + * \date 17.07.2009 + * */ +#ifndef BS_BOS_CORE_CALC_MODEL_DATA_H_ +#define BS_BOS_CORE_CALC_MODEL_DATA_H_ + +namespace blue_sky { + + template + struct calc_model_data + { + typedef calc_model_data this_t; + typedef smart_ptr sp_this_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + +//#ifdef _DEBUG + typedef boost::array item_array_N_t; + typedef boost::array item_array_N_1_t; + typedef boost::array item_array_N_N_t; +//#else +// typedef array_ext item_array_N_t; +// typedef array_ext item_array_N_1_t; +// typedef array_ext item_array_N_N_t; +//#endif + +//#ifndef _DEBUG +// calc_model_data () +// : data_ (0) +// { +// } +// +// calc_model_data (size_t n_phases) +// : cap_pressure (0, n_phases - 1) , +// s_deriv_cap_pressure (0, n_phases - 1), +// relative_perm (0, n_phases), +// s_deriv_relative_perm (0, n_phases * n_phases), +// invers_fvf (0, n_phases), +// p_deriv_invers_fvf (0, n_phases), +// invers_viscosity (0, n_phases), +// p_deriv_invers_viscosity (0, n_phases), +// invers_visc_fvf (0, n_phases), +// p_deriv_invers_visc_fvf (0, n_phases), +// density (0, n_phases), +// p_deriv_density (0, n_phases), +// mobility (0, n_phases), +// p_deriv_mobility (0, n_phases), +// s_deriv_mobility (0, n_phases * n_phases), +// prev_fluid_volume (0, n_phases), +// data_ (0) +// { +// allocate_data (size ()); +// // we should deallocate memory. but now it is not a problem. +// } +//#endif + + item_array_N_1_t cap_pressure; + item_array_N_1_t s_deriv_cap_pressure; + + item_array_N_t relative_perm; + item_array_N_N_t s_deriv_relative_perm; + + item_t p_deriv_gas_oil_ratio; + + item_array_N_t invers_fvf; + item_array_N_t p_deriv_invers_fvf; + item_t gor_deriv_invers_fvf; + + item_array_N_t invers_viscosity; + item_array_N_t p_deriv_invers_viscosity; + item_t gor_deriv_invers_viscosity; + + item_array_N_t invers_visc_fvf; + item_array_N_t p_deriv_invers_visc_fvf; + item_t gor_deriv_invers_visc_fvf; + + item_array_N_t density; + item_array_N_t p_deriv_density; + item_t gor_deriv_density; + + item_t porosity; + item_t p_deriv_porosity; + + item_t truns_mult; + item_t p_deriv_truns_mult; + + item_array_N_t mobility; + item_array_N_t p_deriv_mobility; + item_array_N_N_t s_deriv_mobility; + + item_array_N_t prev_fluid_volume; + +//#ifndef _DEBUG +// private: +// void +// allocate_data (size_t data_size) +// { +// delete []data_; +// data_ = aligned_allocator ::allocate (data_size); +// memset (data_, 0, sizeof (item_t) * data_size); +// +// item_t *data = data_; +// data = cap_pressure.init (data); +// data = s_deriv_cap_pressure.init (data); +// data = relative_perm.init (data); +// data = s_deriv_relative_perm.init (data); +// data = invers_fvf.init (data); +// data = p_deriv_invers_fvf.init (data); +// data = invers_viscosity.init (data); +// data = p_deriv_invers_viscosity.init (data); +// data = invers_visc_fvf.init (data); +// data = p_deriv_invers_visc_fvf.init (data); +// data = density.init (data); +// data = p_deriv_density.init (data); +// data = mobility.init (data); +// data = p_deriv_mobility.init (data); +// data = s_deriv_mobility.init (data); +// data = prev_fluid_volume.init (data); +// } +// +// size_t +// size () const +// { +// return cap_pressure.size () +// + s_deriv_cap_pressure.size () +// + relative_perm.size () +// + s_deriv_relative_perm.size () +// + invers_fvf.size () +// + p_deriv_invers_fvf.size () +// + invers_viscosity.size () +// + p_deriv_invers_viscosity.size () +// + invers_visc_fvf.size () +// + p_deriv_invers_visc_fvf.size () +// + density.size () +// + p_deriv_density.size () +// + mobility.size () +// + p_deriv_mobility.size () +// + s_deriv_mobility.size () +// + prev_fluid_volume.size () +// ; +// } +// +// private: +// item_t *data_; +//#endif + }; + +} // namespace blue_sky + +#endif // #ifndef BS_BOS_CORE_CALC_MODEL_DATA_H_ + diff --git a/bs_bos_core/include/calc_model_data_accessors.h b/bs_bos_core/include/calc_model_data_accessors.h new file mode 100644 index 0000000..59e0328 --- /dev/null +++ b/bs_bos_core/include/calc_model_data_accessors.h @@ -0,0 +1,258 @@ +/** + * \file calc_model_data_accessors.h + * \brief accessor for calc_model data + * \author Sergey Miryanov + * \date 12.11.2008 + * */ +#ifndef BS_CALC_MODEL_DATA_ACCESSORS_H_ +#define BS_CALC_MODEL_DATA_ACCESSORS_H_ + +namespace blue_sky + { + +///////////////////////////////////////////////////////////////////////////// +#define DEF_FUN_I(r, name, phase) \ + template <> \ + struct BOOST_PP_CAT (hx_, name) \ + { \ + template \ + static typename strategy_t::item_t \ + get (const calc_model_data &data, const boost::array &phase_d) \ + { \ + BS_ASSERT (phase_d[phase] != -1) (phase); \ + return data.name [phase_d[phase]]; \ + } \ + }; + +#define DEF_FUN_2_III(r, name, phase1, phase2) \ + template <> \ + struct BOOST_PP_CAT (hx_, name) \ + { \ + template \ + static typename strategy_t::item_t \ + get (const calc_model_data &data, const boost::array &phase_d, int n_phases) \ + { \ + BS_ASSERT (phase_d[phase1] != -1) (phase1); \ + BS_ASSERT (phase_d[phase2] != -1) (phase2); \ + return data.name [phase_d[phase1] * n_phases + phase_d[phase2]]; \ + } \ + }; + +#define DEF_FUN_2_II(r, iter_data, phase1) \ + DEF_FUN_2_III (r, BOOST_PP_TUPLE_ELEM (2, 0, iter_data), phase1, BOOST_PP_TUPLE_ELEM (2, 1, iter_data)) + +#define DEF_FUN_2_I(name, ts1, tp1, ts2, tp2) BOOST_PP_CAT(DEF_FUN_2_I_, ts2) (name, ts1, tp1, tp2) + +#define DEF_FUN_2_I_1(name, ts1, tp1, tp2) \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_2_II, (name, BOOST_PP_TUPLE_ELEM (1, 0, tp2)), BOOST_PP_TUPLE_TO_SEQ (ts1, tp1)) + +#define DEF_FUN_2_I_2(name, ts1, tp1, tp2) \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_2_II, (name, BOOST_PP_TUPLE_ELEM (2, 0, tp2)), BOOST_PP_TUPLE_TO_SEQ (ts1, tp1)) \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_2_II, (name, BOOST_PP_TUPLE_ELEM (2, 1, tp2)), BOOST_PP_TUPLE_TO_SEQ (ts1, tp1)) + +#define DEF_FUN_2_I_3(name, ts1, tp1, tp2) \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_2_II, (name, BOOST_PP_TUPLE_ELEM (3, 0, tp2)), BOOST_PP_TUPLE_TO_SEQ (ts1, tp1)) \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_2_II, (name, BOOST_PP_TUPLE_ELEM (3, 1, tp2)), BOOST_PP_TUPLE_TO_SEQ (ts1, tp1)) \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_2_II, (name, BOOST_PP_TUPLE_ELEM (3, 2, tp2)), BOOST_PP_TUPLE_TO_SEQ (ts1, tp1)) + +#define DEF_FUN_PAIR_I(r, iter_data, phase) \ + template <> \ + struct BOOST_PP_CAT (hx_, BOOST_PP_TUPLE_ELEM (3, 0, iter_data)) \ + { \ + template \ + static typename strategy_t::item_t \ + get (const calc_model_data &data, const boost::array &phase_d) \ + { \ + return data.BOOST_PP_TUPLE_ELEM (3, 1, iter_data) [phase] * data.BOOST_PP_TUPLE_ELEM (3, 2, iter_data) [phase]; \ + } \ + }; + + +#define DEF_FUN(name, ts, tp) \ + template \ + struct BOOST_PP_CAT (hx_, name) \ + { \ + template \ + static typename strategy_t::item_t \ + get (const calc_model_data &data, const boost::array &phase_d) \ + { \ + class inclomplete_type_1; \ + inclomplete_type_1 invalid_phase_value; \ + } \ + }; \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_I, name, BOOST_PP_TUPLE_TO_SEQ (ts, tp)) + +#define DEF_FUN_2(name, ts1, tp1, ts2, tp2) \ + template \ + struct BOOST_PP_CAT (hx_, name) \ + { \ + template \ + static typename strategy_t::item_t \ + get (const calc_model_data &data, const boost::array &phase_d, int n_phases) \ + { \ + class inclomplete_type_1; \ + inclomplete_type_1 invalid_phase_value; \ + } \ + }; \ + DEF_FUN_2_I (name, ts1, tp1, ts2, tp2) + +#define DEF_FUN_PAIR(name, name1, name2, ts, tp) \ + template \ + struct BOOST_PP_CAT (hx_, name) \ + { \ + template \ + static typename strategy_t::item_t \ + get (const calc_model_data &data, const boost::array &phase_d) \ + { \ + class inclomplete_type_1; \ + inclomplete_type_1 invalid_phase_value; \ + } \ + }; \ + BOOST_PP_SEQ_FOR_EACH (DEF_FUN_PAIR_I, (name, name1, name2), BOOST_PP_TUPLE_TO_SEQ (ts, tp)) + + DEF_FUN (cap_pressure, 2, (FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (s_deriv_cap_pressure, 2, (FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (relative_perm, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN_2 (s_deriv_relative_perm, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS), 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (invers_fvf, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (p_deriv_invers_fvf, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (invers_viscosity, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (p_deriv_invers_viscosity, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (invers_visc_fvf, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (p_deriv_invers_visc_fvf, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (density, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (p_density, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (mobility, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN (p_deriv_mobility,3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN_2 (s_deriv_mobility, 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS), 3, (FI_PHASE_OIL, FI_PHASE_WATER, FI_PHASE_GAS)) + + DEF_FUN_PAIR (s_deriv_invers_fvf, p_deriv_invers_fvf, s_deriv_cap_pressure, 2, (FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN_PAIR (s_deriv_invers_viscosity, p_deriv_invers_viscosity, s_deriv_cap_pressure, 2, (FI_PHASE_WATER, FI_PHASE_GAS)) + DEF_FUN_PAIR (s_deriv_invers_visc_fvf, p_deriv_invers_visc_fvf, s_deriv_cap_pressure, 2, (FI_PHASE_WATER, FI_PHASE_GAS)) + +///////////////////////////////////////////////////////////////////////////// +#ifdef _DEBUG + +#define CAP_PRESSURE(data, phase_d, phase) hx_cap_pressure::get (data, phase_d) +#define S_DERIV_CAP_PRESSURE(data, phase_d, phase) hx_s_deriv_cap_pressure::get (data, phase_d) +#define RELATIVE_PERM(data, phase_d, phase) hx_relative_perm::get (data, phase_d) +#define S_DERIV_RELATIVE_PERM(data, phase_d, n_phases, phase1, phase2) hx_s_deriv_relative_perm::get (data, phase_d, n_phases) +#define GAS_OIL_RATIO(data) params.gas_oil_ratio[params.n_block] +#define P_DERIV_GAS_OIL_RATIO(data) data.p_deriv_gas_oil_ratio +#define INVERS_FVF(data, phase_d, phase) hx_invers_fvf::get (data, phase_d) +#define P_DERIV_INVERS_FVF(data, phase_d, phase) hx_p_deriv_invers_fvf::get (data, phase_d) +#define GOR_DERIV_INVERS_FVF(data) data.gor_deriv_invers_fvf +#define INVERS_VISCOSITY(data, phase_d, phase) hx_invers_viscosity::get (data, phase_d) +#define P_DERIV_INVERS_VISCOSITY(data, phase_d, phase) hx_p_deriv_invers_viscosity::get (data, phase_d) +#define GOR_DERIV_INVERS_VISCOSITY(data) data.gor_deriv_invers_viscosity +#define INVERS_VISC_FVF(data, phase_d, phase) hx_invers_visc_fvf::get (data, phase_d) +#define P_DERIV_INVERS_VISC_FVF(data, phase_d, phase) hx_p_deriv_invers_visc_fvf::get (data, phase_d) +#define GOR_DERIV_INVERS_VISC_FVF(data) data.gor_deriv_invers_visc_fvf +#define DENSITY(data, phase_d, phase) hx_density::get (data, phase_d) +#define P_DERIV_DENSITY(data, phase_d, phase) hx_p_deriv_density::get (data, phase_d) +#define GOR_DERIV_DENSITY(data) data.gor_deriv_density +#define MOBILITY(data, phase_d, phase) hx_mobility::get (data, phase_d) +#define P_DERIV_MOBILITY(data, phase_d, phase) hx_p_deriv_mobility::get (data, phase_d) +#define S_DERIV_MOBILITY(data, phase_d, n_phases, phase1, phase2) hx_s_deriv_mobility::get (data, phase_d, n_phases) +#define S_DERIV_INVERS_FVF(data, phase_d, phase) hx_s_deriv_invers_fvf::get (data, phase_d) +#define S_DERIV_INVERS_VISCOSITY(data, phase_d, phase) hx_s_deriv_invers_viscosity::get (data, phase_d) +#define S_DERIV_INVERS_VISC_FVF(data, phase_d, phase) hx_s_deriv_invers_visc_fvf::get (data, phase_d) + +#else + +#define CAP_PRESSURE(data, phase_d, phase) data.cap_pressure[phase_d[phase]] +#define S_DERIV_CAP_PRESSURE(data, phase_d, phase) data.s_deriv_cap_pressure[phase_d[phase]] +#define RELATIVE_PERM(data, phase_d, phase) data.relative_perm[phase_d[phase]] +#define S_DERIV_RELATIVE_PERM(data, phase_d, n_phases, phase1, phase2) data.s_deriv_relative_perm[phase_d[phase1] * n_phases + phase_d[phase2]] +#define GAS_OIL_RATIO(data) params.gas_oil_ratio[params.n_block] +#define P_DERIV_GAS_OIL_RATIO(data) data.p_deriv_gas_oil_ratio +#define INVERS_FVF(data, phase_d, phase) data.invers_fvf[phase_d[phase]] +#define P_DERIV_INVERS_FVF(data, phase_d, phase) data.p_deriv_invers_fvf[phase_d[phase]] +#define GOR_DERIV_INVERS_FVF(data) data.gor_deriv_invers_fvf +#define INVERS_VISCOSITY(data, phase_d, phase) data.invers_viscosity[phase_d[phase]] +#define P_DERIV_INVERS_VISCOSITY(data, phase_d, phase) data.p_deriv_invers_viscosity[phase_d[phase]] +#define GOR_DERIV_INVERS_VISCOSITY(data) data.gor_deriv_invers_viscosity +#define INVERS_VISC_FVF(data, phase_d, phase) data.invers_visc_fvf[phase_d[phase]] +#define P_DERIV_INVERS_VISC_FVF(data, phase_d, phase) data.p_deriv_invers_visc_fvf[phase_d[phase]] +#define GOR_DERIV_INVERS_VISC_FVF(data) data.gor_deriv_invers_visc_fvf +#define DENSITY(data, phase_d, phase) data.density[phase_d[phase]] +#define P_DERIV_DENSITY(data, phase_d, phase) data.p_deriv_density[phase_d[phase]] +#define GOR_DERIV_DENSITY(data) data.gor_deriv_density +#define MOBILITY(data, phase_d, phase) data.mobility[phase_d[phase]] +#define P_DERIV_MOBILITY(data, phase_d, phase) data.p_deriv_mobility[phase_d[phase]] +#define S_DERIV_MOBILITY(data, phase_d, n_phases, phase1, phase2) data.s_deriv_mobility[phase_d[phase1] * n_phases + phase_d[phase2]] +#define S_DERIV_INVERS_FVF(data, phase_d, phase) data.p_deriv_invers_fvf[phase_d[phase]] * data.s_deriv_cap_pressure[phase_d[phase]] +#define S_DERIV_INVERS_VISCOSITY(data, phase_d, phase) data.p_deriv_invers_viscosity[phase_d[phase]] * data.s_deriv_cap_pressure[phase_d[phase]] +#define S_DERIV_INVERS_VISC_FVF(data, phase_d, phase) data.p_deriv_invers_visc_fvf[phase_d[phase]] * data.s_deriv_cap_pressure[phase_d[phase]] + +#endif +///////////////////////////////////////////////////////////////////////////// + +#define RELATIVE_PERM_W RELATIVE_PERM(data, params.phase_d, FI_PHASE_WATER) +#define RELATIVE_PERM_G RELATIVE_PERM(data, params.phase_d, FI_PHASE_GAS) +#define RELATIVE_PERM_O RELATIVE_PERM(data, params.phase_d, FI_PHASE_OIL) + +#define S_DERIV_RELATIVE_PERM_WW S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_WATER, FI_PHASE_WATER) +#define S_DERIV_RELATIVE_PERM_WG S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_WATER, FI_PHASE_GAS) +#define S_DERIV_RELATIVE_PERM_WO S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_WATER, FI_PHASE_OIL) +#define S_DERIV_RELATIVE_PERM_GW S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_GAS, FI_PHASE_WATER) +#define S_DERIV_RELATIVE_PERM_GG S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_GAS, FI_PHASE_GAS) +#define S_DERIV_RELATIVE_PERM_GO S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_GAS, FI_PHASE_OIL) +#define S_DERIV_RELATIVE_PERM_OW S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_WATER) +#define S_DERIV_RELATIVE_PERM_OG S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_GAS) +#define S_DERIV_RELATIVE_PERM_OO S_DERIV_RELATIVE_PERM(data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_OIL) + +#define INVERS_FVF_W INVERS_FVF(data, params.phase_d, FI_PHASE_WATER) +#define INVERS_FVF_G INVERS_FVF(data, params.phase_d, FI_PHASE_GAS) +#define INVERS_FVF_O INVERS_FVF(data, params.phase_d, FI_PHASE_OIL) + +#define INVERS_VISCOSITY_W INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_WATER) +#define INVERS_VISCOSITY_G INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_GAS) +#define INVERS_VISCOSITY_O INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_OIL) + +#define INVERS_VISC_FVF_W INVERS_VISC_FVF(data, params.phase_d, FI_PHASE_WATER) +#define INVERS_VISC_FVF_G INVERS_VISC_FVF(data, params.phase_d, FI_PHASE_GAS) +#define INVERS_VISC_FVF_O INVERS_VISC_FVF(data, params.phase_d, FI_PHASE_OIL) + +#define P_DERIV_INVERS_FVF_W P_DERIV_INVERS_FVF(data, params.phase_d, FI_PHASE_WATER) +#define P_DERIV_INVERS_FVF_O P_DERIV_INVERS_FVF(data, params.phase_d, FI_PHASE_OIL) + +#define P_DERIV_INVERS_VISCOSITY_W P_DERIV_INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_WATER) +#define P_DERIV_INVERS_VISCOSITY_O P_DERIV_INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_OIL) + +#define S_DERIV_INVERS_VISCOSITY_W S_DERIV_INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_WATER) +#define S_DERIV_INVERS_VISCOSITY_G S_DERIV_INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_GAS) +#define S_DERIV_INVERS_VISCOSITY_O S_DERIV_INVERS_VISCOSITY(data, params.phase_d, FI_PHASE_OIL) + +#define S_DERIV_INVERS_VISC_FVF_W S_DERIV_INVERS_VISC_FVF(data, params.phase_d, FI_PHASE_WATER) +#define S_DERIV_INVERS_VISC_FVF_G S_DERIV_INVERS_VISC_FVF(data, params.phase_d, FI_PHASE_GAS) +#define S_DERIV_INVERS_VISC_FVF_O S_DERIV_INVERS_VISC_FVF(data, params.phase_d, FI_PHASE_OIL) + +#define P_DERIV_MOBILITY_W P_DERIV_MOBILITY(data, params.phase_d, FI_PHASE_WATER) +#define P_DERIV_MOBILITY_G P_DERIV_MOBILITY(data, params.phase_d, FI_PHASE_GAS) +#define P_DERIV_MOBILITY_O P_DERIV_MOBILITY(data, params.phase_d, FI_PHASE_OIL) + +#define S_DERIV_MOBILITY_OW S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_WATER) +#define S_DERIV_MOBILITY_OG S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_GAS) +#define S_DERIV_MOBILITY_OO S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_OIL) + +#define S_DERIV_MOBILITY_WW S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_WATER, FI_PHASE_WATER) +#define S_DERIV_MOBILITY_WG S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_WATER, FI_PHASE_GAS) +#define S_DERIV_MOBILITY_WO S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_WATER, FI_PHASE_OIL) + +#define S_DERIV_MOBILITY_GW S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_GAS, FI_PHASE_WATER) +#define S_DERIV_MOBILITY_GG S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_GAS, FI_PHASE_GAS) +#define S_DERIV_MOBILITY_GO S_DERIV_MOBILITY(data, params.phase_d, params.n_phases, FI_PHASE_GAS, FI_PHASE_OIL) + +#define MOBILITY_W MOBILITY(data, params.phase_d, FI_PHASE_WATER) +#define MOBILITY_G MOBILITY(data, params.phase_d, FI_PHASE_GAS) +#define MOBILITY_O MOBILITY(data, params.phase_d, FI_PHASE_OIL) + +#define S_DERIV_CAP_PRESSURE_W S_DERIV_CAP_PRESSURE(data, params.phase_d, FI_PHASE_WATER) +#define S_DERIV_CAP_PRESSURE_G S_DERIV_CAP_PRESSURE(data, params.phase_d, FI_PHASE_GAS) + +} // namespace blue_sky + + +#endif // #ifndef BS_CALC_MODEL_DATA_ACCESSORS_H_ + diff --git a/bs_bos_core/include/calc_model_type_helper.h b/bs_bos_core/include/calc_model_type_helper.h new file mode 100644 index 0000000..201b8b3 --- /dev/null +++ b/bs_bos_core/include/calc_model_type_helper.h @@ -0,0 +1,30 @@ +/** + * + * */ +#ifndef BS_CALC_MODEL_TYPE_HELPER_H_ +#define BS_CALC_MODEL_TYPE_HELPER_H_ + +namespace blue_sky + { + + template + struct calc_model_type_helper + { + typedef strategy_type strategy_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + + typedef boost::array well_mobility_t; + typedef boost::array p_deriv_well_mobility_t; + typedef boost::array sat_deriv_well_mobility_t; + typedef boost::array xref_deriv_well_mobility_t; + typedef boost::array flow_deriv_well_mobility_t; + typedef boost::array phase_fvf_t; + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_CALC_MODEL_TYPE_HELPER_H_ + diff --git a/bs_bos_core/include/calc_perf_bhp.h b/bs_bos_core/include/calc_perf_bhp.h new file mode 100644 index 0000000..fad2fdd --- /dev/null +++ b/bs_bos_core/include/calc_perf_bhp.h @@ -0,0 +1,44 @@ +/** + * \file calc_perf_bhp.h + * \brief perforation's bhp calculation + * \author Sergey Miryanov + * \date 18.11.2008 + * */ +#ifndef BS_CALC_PERF_BHP_H_ +#define BS_CALC_PERF_BHP_H_ + +#include "calc_perf_bhp_base.h" + +namespace blue_sky + { + + + template + class BS_API_PLUGIN calc_perf_bhp : public calc_perf_bhp_base + { + public: + + typedef calc_perf_bhp_base base_t; + typedef calc_perf_bhp this_t; + + typedef typename base_t::sp_calc_model_t sp_calc_model_t; + typedef typename base_t::sp_well_t sp_well_t; + typedef typename base_t::sp_mesh_iface_t sp_mesh_iface_t; + typedef typename base_t::item_t item_t; + typedef typename base_t::index_t index_t; + + public: + + void + calculate (sp_well_t &well, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) const; + + BLUE_SKY_TYPE_DECL_T (calc_perf_bhp ); + + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_CALC_PERF_BHP_H_ + diff --git a/bs_bos_core/include/calc_perf_bhp_base.h b/bs_bos_core/include/calc_perf_bhp_base.h new file mode 100644 index 0000000..0c645d4 --- /dev/null +++ b/bs_bos_core/include/calc_perf_bhp_base.h @@ -0,0 +1,52 @@ +/** + * \file calc_perf_bhp_base.h + * \brief base class for perforation's bhp calculation + * \author Sergey Miryanov + * \date 18.11.2008 + * */ +#ifndef BS_CALC_PERF_BHP_BASE_H_ +#define BS_CALC_PERF_BHP_BASE_H_ + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +namespace blue_sky + { + + template + class calc_model; + + template + class well; + + template + class calc_perf_bhp_base : public objbase + { + public: + + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + + typedef calc_model calc_model_t; + typedef well well_t; + typedef rs_mesh_iface mesh_iface_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_mesh_iface_t; + + public: + virtual ~calc_perf_bhp_base () + {} + + virtual void + calculate (sp_well_t &well, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) const = 0; + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_CALC_PERF_BHP_BASE_H_ + diff --git a/bs_bos_core/include/calc_perf_density_base.h b/bs_bos_core/include/calc_perf_density_base.h new file mode 100644 index 0000000..4a0ef82 --- /dev/null +++ b/bs_bos_core/include/calc_perf_density_base.h @@ -0,0 +1,46 @@ +/** + * \file calc_perf_density_base.h + * \brief base class for perforation's density calculation + * \author Sergey Miryanov + * \date 18.11.2008 + * */ +#ifndef BS_CALC_PERF_DENSITY_BASE_H_ +#define BS_CALC_PERF_DENSITY_BASE_H_ + + +namespace blue_sky + { + + template + class calc_model; + + template + class well; + + template + class calc_perf_density_base : public objbase + { + public: + + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + + typedef calc_model calc_model_t; + typedef well well_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_t; + + public: + virtual ~calc_perf_density_base () {} + + virtual void + calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const = 0; + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_CALC_PERF_DENSITY_BASE_H_ + diff --git a/bs_bos_core/include/calc_rho.h b/bs_bos_core/include/calc_rho.h new file mode 100644 index 0000000..7749537 --- /dev/null +++ b/bs_bos_core/include/calc_rho.h @@ -0,0 +1,74 @@ +/** + * \file calc_rho.h + * \brief class for rho calculation + * \author Sergey Miryanov + * \date 26.09.2008 + * */ +#ifndef BS_CALC_RHO_H_ +#define BS_CALC_RHO_H_ + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +namespace blue_sky + { + + template + class calc_model; + + template + class well; + + template + class calc_rho_base : public objbase + { + public: + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef calc_model calc_model_t; + typedef well well_t; + typedef rs_mesh_iface mesh_iface_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_mesh_iface_t; + + public: + virtual ~calc_rho_base () {} + + virtual void calculate (const sp_well_t &well, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) const = 0; + }; + + template + class calc_total_average_rho : public calc_rho_base + { + public: + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef calc_model calc_model_t; + typedef well well_t; + typedef rs_mesh_iface mesh_iface_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_mesh_iface_t; + + public: + + void calculate (const sp_well_t &well, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) const; + + BLUE_SKY_TYPE_DECL_T (calc_total_average_rho ); + }; + + bool + calc_rho_register_types (const blue_sky::plugin_descriptor &pd); + +} // namespace blue_sky + +#endif // #ifndef BS_CALC_RHO_H_ + diff --git a/bs_bos_core/include/calc_well.h b/bs_bos_core/include/calc_well.h new file mode 100644 index 0000000..b7f9bb4 --- /dev/null +++ b/bs_bos_core/include/calc_well.h @@ -0,0 +1,335 @@ +/** + * \file calc_well.h + * \brief calculated wells + * \author Sergey Miryanov + * \date 23.06.2008 + * */ +#ifndef BS_CALC_WELL_H_ +#define BS_CALC_WELL_H_ + +#include "facility_base.h" +#include "well_controller.h" +#include "well_limit_operation.h" +#include "fi_params.h" +#include "well_type_helper.h" + +// TODO: BUG +#include "calc_well_pressure.h" +#include "calc_rho.h" +#include "calc_perf_bhp_base.h" +#include "calc_perf_density_base.h" +#include "well_rate_control.h" +#include "array_ext.h" + +namespace blue_sky + { + + /////////////////////////////////////////////////////////////////////////// + // fwd declarations + class physical_constants; + + template + class calc_model; + + namespace wells + { + template + class connection; + + namespace compute_factors + { + template + struct peaceman_model; + + template + struct baby_odeh_model; + } + } + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + enum well_state_type + { + well_open, + well_shut, + + well_state_total, + }; + + well_state_type + well_state_cast (const std::string &str); + /////////////////////////////////////////////////////////////////////////// + + template + struct well_state + { + auto_value state; + auto_value is_work; + }; + + template + class BS_API_PLUGIN well : public facility_base + { + public: + + typedef well well_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; + + typedef rate_data rate_data_t; + typedef typename rate_data_t::rate_data_inner rate_data_inner_t; + typedef well_state well_state_t; + + typedef wells::well_controller well_controller_t; + typedef wells::well_rate_control well_rate_control_t; + typedef calc_model calc_model_t; + typedef calc_model_data calc_model_data_t; + typedef wells::connection connection_t; + typedef rs_mesh_iface mesh_iface_t; + typedef jacobian_matrix jacobian_matrix_t; + + typedef pvt_oil pvt_oil_t; + typedef pvt_dead_oil pvt_dead_oil_t; + typedef pvt_gas pvt_gas_t; + typedef pvt_water pvt_water_t; + + typedef calc_well_pressure_base calc_well_pressure_t; + typedef calc_rho_base calc_rho_base_t; + typedef calc_perf_density_base calc_perf_density_t; + typedef calc_perf_bhp_base calc_perf_bhp_t; + + typedef nc_ptr nc_calc_model_t; + typedef nc_ptr nc_mesh_iface_t; + typedef nc_ptr nc_jmatrix_t; + + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_well_t; + + typedef smart_ptr sp_pvt_oil_t; + typedef smart_ptr sp_pvt_dead_oil_t; + typedef smart_ptr sp_pvt_gas_t; + typedef smart_ptr sp_pvt_water_t; + + typedef smart_ptr sp_jmatrix_t; + typedef smart_ptr sp_connection_t; + + typedef smart_ptr sp_calc_well_pressure_t; + typedef smart_ptr sp_calc_rho_t; + typedef smart_ptr sp_calc_perf_density_t; + typedef smart_ptr sp_calc_perf_bhp_t; + + typedef smart_ptr sp_params_t; + + public: + virtual sp_connection_t + add_connection (index_t i_coord, index_t j_coord, index_t k_coord, index_t n_block) + { + bs_throw_exception ("PURE CALL"); + } + virtual sp_connection_t + get_connection (index_t idx) const + { + bs_throw_exception ("PURE CALL"); + } + virtual sp_connection_t + get_connection_map (index_t n_block) const + { + bs_throw_exception ("PURE CALL"); + } + virtual size_t + get_connections_count () const + { + bs_throw_exception ("PURE CALL"); + } + + void set_coord (index_t i_coord, index_t j_coord); + void set_bhp_depth (item_t bhp_depth); + void set_state (well_state_type well_state, const sp_calc_model_t &calc_model); + void set_exploitation_factor (item_t exploitation_factor); + + void set_controller (sp_well_controller_t controller); + void set_limit_operation (sp_well_limit_operation_t limit_operation); + + sp_well_controller_t get_controller () const; + sp_well_limit_operation_t get_limit_operation () const; + + const std::string &get_name () const; + void set_name (const std::string &name); + + item_t get_bhp_depth () const + { + return bhp_depth_; + } + + item_t bhp () const + { + return bhp_; + } + + const rate_data_t &rate () const + { + return rate_; + } + const rate_data_t &rate_total () const + { + return rate_total_; + } + + const rate_data_inner_t & + rate_prod () const + { + return rate_.prod; + } + const rate_data_inner_t & + rate_inj () const + { + return rate_.inj; + } + + bool is_open () const + { + if (well_state_.state == well_open) + return true; + return false; + } + + const std::string &name () const; + + void set_bhp (item_t bhp); + + bool fi_check_limits () const; + + item_t get_reference_depth (const sp_mesh_iface_t &mesh) const; + item_t get_reference_pressure () const; + + bool check_connections_bhp (const item_array_t &pressure) const; + + bool is_bhp () const; + bool is_rate () const; + bool is_shut () const; + + const sp_well_controller_t &get_well_controller () const; + + item_t get_input_rate () const; + + bool check_shut (const sp_calc_model_t &calc_model); + + void reset_init_approx (); + + virtual array_ext get_ww_value (); + virtual array_ext get_bw_value (); + + virtual void eliminate (rhs_item_t *array, index_t rw_index, index_t wr_index, double dt, index_t block_size) const; + virtual void process (bool is_start, double dt, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix); + virtual void clear_data (); + + virtual void fill_rows (index_array_t &rows) const; + virtual void fill_jacobian (double dt, index_t block_size, const index_array_t &rows, index_array_t &cols, rhs_item_array_t &values, index_array_t &markers) const; + virtual void fill_rhs (double dt, index_t n_phases, bool is_g, bool is_o, bool is_w, rhs_item_array_t &rhs) const; + virtual void restore_solution (double dt, const item_array_t &p_sol, const item_array_t &s_sol, index_t block_size); + + virtual void custom_init (const sp_calc_model_t &mdl); + + virtual void pre_large_step (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh); + virtual void pre_small_step (); + virtual void pre_newton_step (); + virtual void restart_small_step (); + virtual void restart_newton_step (); + + virtual ~well (); + + well (const std::string &well_name); + + public: + BLUE_SKY_TYPE_DECL_T (well ); + + protected: + + void shut_well (const sp_calc_model_t &well); + void reset_rhs_block (); + + void compute_connection_factor (const physical_constants &internal_constants, + const sp_params_t ¶ms, + const sp_mesh_iface_t &mesh, + const item_array_t &perm, + const item_array_t &ntg, + bool ro_calc_flag); + + public: + + std::string name_; + + auto_value i_coord_; + auto_value j_coord_; + + sp_well_controller_t well_controller_; + +// private: + public: + auto_value bhp_depth_; + auto_value exploitation_factor_; + + well_state_t well_state_; + well_state_t saved_well_state_; + well_state_t saved_niter_well_state_; + + sp_well_limit_operation_t well_limit_operation_; + + rate_data_t rate_; + rate_data_t rate_total_; + rate_data_t rate_rc_; + + item_t bhp_; + item_t gor_; + + protected: + + auto_value init_approx_is_calc_; + auto_value input_reference_depth_; + + sp_calc_well_pressure_t calc_well_pressure_; + sp_calc_rho_t calc_rho_; + sp_calc_perf_density_t calc_perf_density_; + sp_calc_perf_bhp_t calc_perf_bhp_; + + protected: + index_array_t open_connections_; + }; + + template + class BS_API_PLUGIN well_factory : public objbase + { + public: + + typedef well well_t; + typedef wells::connection connection_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + + public: + + virtual ~well_factory () {} + + virtual sp_well_t create_well (const std::string &group_name, const std::string &well_name) const; + virtual sp_connection_t create_connection () const; + + BLUE_SKY_TYPE_DECL_T (well_factory ); + }; + + bool + calc_well_register_types (const blue_sky::plugin_descriptor &pd); + + bool + well_factory_register_type (const blue_sky::plugin_descriptor &pd); + +} // namespace blue_sky + + +#endif // #ifndef BS_CALC_WELL_H_ diff --git a/bs_bos_core/include/calc_well_pressure.h b/bs_bos_core/include/calc_well_pressure.h new file mode 100644 index 0000000..63bd881 --- /dev/null +++ b/bs_bos_core/include/calc_well_pressure.h @@ -0,0 +1,74 @@ +/* + * \file calc_well_pressure.h + * \brief base class for objects that calculate distribution of pressure inside well + * \author Sergey Miryanov + * \date 26.09.2008 + * */ +#ifndef BS_CALC_WELL_PRESSURE_H_ +#define BS_CALC_WELL_PRESSURE_H_ + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +namespace blue_sky + { + + template + class calc_model; + + template + class well; + + template + class calc_well_pressure_base : public objbase + { + public: + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + + typedef calc_model calc_model_t; + typedef well well_t; + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_t; + + public: + virtual ~calc_well_pressure_base () {} + virtual bool calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const = 0; + }; + + template + class calc_well_pressure : public calc_well_pressure_base + { + public: + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef calc_well_pressure_base base_t; + typedef calc_well_pressure this_t; + + typedef typename base_t::sp_calc_model_t sp_calc_model_t; + typedef typename base_t::sp_well_t sp_well_t; + + public: + + bool + calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const; + + BLUE_SKY_TYPE_DECL_T (calc_well_pressure ); + + protected: + + bool + calculate_for_rate (sp_well_t &well, const sp_calc_model_t &calc_model) const; + + }; + + bool + calc_well_pressure_register_types (const blue_sky::plugin_descriptor &pd); + +} // namespace blue_sky + +#endif // #ifndef BS_CALC_WELL_PRESSURE_H_ + diff --git a/bs_bos_core/include/call_helper.h b/bs_bos_core/include/call_helper.h new file mode 100644 index 0000000..4022663 --- /dev/null +++ b/bs_bos_core/include/call_helper.h @@ -0,0 +1,120 @@ +/** + * \file call_helper.cpp + * \brief Helper functions for call methods of derived from py_object classes + * \author Miryanov Sergey + * \date 2008-04-07 + */ + + +#ifndef CALL_HELPER_H_ +#define CALL_HELPER_H_ + +#ifdef BSPY_EXPORTING_PLUGIN + +namespace blue_sky + { + namespace tx + { + + using blue_sky::python::py_objbase; + + ////////////////////////////////////////////////////////////////////////// + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A), A a) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a); + } + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A&), A &a) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a); + } + + ////////////////////////////////////////////////////////////////////////// + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A, A2), A a, A2 a2) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a, a2); + } + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A&, A2&), A &a, A2 &a2) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a, a2); + } + + ////////////////////////////////////////////////////////////////////////// + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A, A2, A3), A a, A2 a2, A3 a3) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a, a2, a3); + } + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A&, A2&, A3&), A &a, A2 &a2, A3 &a3) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a, a2, a3); + } + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A, A2, A3, A4), A a, A2 a2, A3 a3, A4 a4) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a, a2, a3, a4); + } + + template + R call(py_objbase * py, /*typename*/ R(C::*f)(A, A2, A3, A4), A a, A2 a2, A3 a3, A4 a4, A5 a5) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(a, a2, a3, a4, a5); + } + + template + R call (py_objbase * py, /*typename*/ R(C::*f)()) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(); + } + template + R call (py_objbase * py, /*typename*/ R(C::*f)() const) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(); + } + template + R call (const py_objbase * py, /*typename*/ R(C::*f)() const) + { + lsmart_ptr > c(py->get_sp()); + return ((*c).*f)(); + } + + ////////////////////////////////////////////////////////////////////////// + template + void call(py_objbase * py, /*typename*/ void (C::*f)(A), A a) + { + lsmart_ptr > c(py->get_sp()); + ((*c).*f)(a); + } + template + void call(py_objbase * py, /*typename*/ void (C::*f)(A&), A &a) + { + lsmart_ptr > c(py->get_sp()); + ((*c).*f)(a); + } + template + void call(py_objbase * py, /*typename*/ void(C::*f)()) + { + lsmart_ptr > c(py->get_sp()); + ((*c).*f)(); + } + + + } // namespace tx +} // namespace blue_sky + +#endif // #ifdef BSPY_EXPORTING_PLUGIN +#endif // #ifndef CALL_HELPER_H_ diff --git a/bs_bos_core/include/closure.h b/bs_bos_core/include/closure.h new file mode 100644 index 0000000..231f62e --- /dev/null +++ b/bs_bos_core/include/closure.h @@ -0,0 +1,414 @@ +/** + * \file closure.h + * \brief closure impl + * \author Sergey Miryanov + * \date 13.02.2009 + * */ +#ifndef BS_CLOSURE_IMPL_H_ +#define BS_CLOSURE_IMPL_H_ + +namespace blue_sky { + + template + struct closure0 + { + closure0 (M m) + : m (m) + { + } + + R + operator () (T &t) + { + return (t.*m) (); + } + + M m; + }; + template + struct closure0 + { + typedef void R; + + closure0 (M m) + : m (m) + { + } + + R + operator () (T &t) + { + (t.*m) (); + } + + M m; + }; + + template + struct closure1 + { + closure1 (M m, A1 a1) + : m (m) + , a1 (a1) + { + } + + R + operator () (T &t) + { + return (t.*m) (a1); + } + + M m; + A1 a1; + }; + template + struct closure1 + { + closure1 (M m, A1 a1) + : m (m) + , a1 (a1) + { + } + + void + operator () (T &t) + { + return (t.*m) (a1); + } + + M m; + A1 a1; + }; + + template + struct closure2 + { + closure2 (M m, A1 a1, A2 a2) + : m (m) + , a1 (a1) + , a2 (a2) + { + } + + R + operator () (T &t) + { + return (t.*m) (a1, a2); + } + + M m; + A1 a1; + A2 a2; + }; + template + struct closure2 + { + closure2 (M m, A1 a1, A2 a2) + : m (m) + , a1 (a1) + , a2 (a2) + { + } + + void + operator () (T &t) + { + return (t.*m) (a1, a2); + } + + M m; + A1 a1; + A2 a2; + }; + + template + struct closure3 + { + closure3 (M m, A1 a1, A2 a2, A3 a3) + : m (m) + , a1 (a1) + , a2 (a2) + , a3 (a3) + { + } + + R + operator () (T &t) + { + return (t.*m) (a1, a2, a3); + } + + M m; + A1 a1; + A2 a2; + A3 a3; + }; + template + struct closure3 + { + closure3 (M m, A1 a1, A2 a2, A3 a3) + : m (m) + , a1 (a1) + , a2 (a2) + , a3 (a3) + { + } + + void + operator () (T &t) + { + return (t.*m) (a1, a2, a3); + } + + M m; + A1 a1; + A2 a2; + A3 a3; + }; + + template + struct closure4 + { + closure4 (M m, A1 a1, A2 a2, A3 a3, A4 a4) + : m (m) + , a1 (a1) + , a2 (a2) + , a3 (a3) + , a4 (a4) + { + } + + R + operator () (T &t) + { + return (t.*m) (a1, a2, a3, a4); + } + + M m; + A1 a1; + A2 a2; + A3 a3; + A4 a4; + }; + template + struct closure4 + { + closure4 (M m, A1 a1, A2 a2, A3 a3, A4 a4) + : m (m) + , a1 (a1) + , a2 (a2) + , a3 (a3) + , a4 (a4) + { + } + + void + operator () (T &t) + { + return (t.*m) (a1, a2, a3, a4); + } + + M m; + A1 a1; + A2 a2; + A3 a3; + A4 a4; + }; + template + struct closure5 + { + closure5 (M m, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m (m) + , a1 (a1) + , a2 (a2) + , a3 (a3) + , a4 (a4) + , a5 (a5) + { + } + + R + operator () (T &t) + { + return (t.*m) (a1, a2, a3, a4, a5); + } + + M m; + A1 a1; + A2 a2; + A3 a3; + A4 a4; + A5 a5; + }; + template + struct closure5 + { + closure5 (M m, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + : m (m) + , a1 (a1) + , a2 (a2) + , a3 (a3) + , a4 (a4) + , a5 (a5) + { + } + + void + operator () (T &t) + { + return (t.*m) (a1, a2, a3, a4, a5); + } + + M m; + A1 a1; + A2 a2; + A3 a3; + A4 a4; + A5 a5; + }; + + template + struct closure6 + { + closure6 (M m, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m (m), a1 (a1), a2 (a2), a3 (a3), a4 (a4), a5 (a5), a6 (a6) + { + } + + R + operator () (T &t) + { + return (t.*m) (a1, a2, a3, a4, a5, a6); + } + + private: + M m; + A1 a1; + A2 a2; + A3 a3; + A4 a4; + A5 a5; + A6 a6; + }; + template + struct closure6 + { + closure6 (M m, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + : m (m), a1 (a1), a2 (a2), a3 (a3), a4 (a4), a5 (a5), a6 (a6) + { + } + + void + operator () (T &t) + { + (t.*m) (a1, a2, a3, a4, a5, a6); + } + + private: + M m; + A1 a1; + A2 a2; + A3 a3; + A4 a4; + A5 a5; + A6 a6; + }; + + /////////////////////////////////////////////////////////////////////////// + template + closure0 + closure (R (T::*m) () const) + { + return closure0 (m); + } + template + closure0 + closure (R (T::*m) ()) + { + return closure0 (m); + } + + /////////////////////////////////////////////////////////////////////////// + template + closure1 + closure (R (T::*m) (A1) const, A1 a1) + { + return closure1 (m, a1); + } + template + closure1 + closure (R (T::*m) (A1), A1 a1) + { + return closure1 (m, a1); + } + + /////////////////////////////////////////////////////////////////////////// + template + closure2 + closure (R (T::*m) (A1, A2), A1 a1, A2 a2) + { + return closure2 (m, a1, a2); + } + template + closure2 + closure (R (T::*m) (A1, A2) const, A1 a1, A2 a2) + { + return closure2 (m, a1, a2); + } + + /////////////////////////////////////////////////////////////////////////// + template + closure3 + closure (R (T::*m) (A1, A2, A3), A1 a1, A2 a2, A3 a3) + { + return closure3 (m, a1, a2, a3); + } + + /////////////////////////////////////////////////////////////////////////// + template + closure4 + closure (R (T::*m) (A1, A2, A3, A4), A1 a1, A2 a2, A3 a3, A4 a4) + { + return closure4 (m, a1, a2, a3, a4); + } + template + closure4 + closure (R (T::*m) (A1, A2, A3, A4) const, A1 a1, A2 a2, A3 a3, A4 a4) + { + return closure4 (m, a1, a2, a3, a4); + } + + /////////////////////////////////////////////////////////////////////////// + template + closure5 + closure (R (T::*m) (A1, A2, A3, A4, A5) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + { + return closure5 (m, a1, a2, a3, a4, a5); + } + template + closure5 + closure (R (T::*m) (A1, A2, A3, A4, A5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) + { + return closure5 (m, a1, a2, a3, a4, a5); + } + + /////////////////////////////////////////////////////////////////////////// + template + closure6 + closure (R (T::*m) (A1, A2, A3, A4, A5, A6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + { + return closure6 (m, a1, a2, a3, a4, a5, a6); + } + template + closure6 + closure (R (T::*m) (A1, A2, A3, A4, A5, A6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) + { + return closure6 (m, a1, a2, a3, a4, a5, a6); + } + +} // namespace blue_sky + + +#endif // #ifndef BS_CLOSURE_IMPL_H_ + diff --git a/bs_bos_core/include/compute_acc_rates.h b/bs_bos_core/include/compute_acc_rates.h new file mode 100644 index 0000000..bcca508 --- /dev/null +++ b/bs_bos_core/include/compute_acc_rates.h @@ -0,0 +1,74 @@ +/** + * + * */ +#ifndef BS_MAIN_LOOP_CALC_COMPUTE_ACC_RATES_H_ +#define BS_MAIN_LOOP_CALC_COMPUTE_ACC_RATES_H_ + +#include "apply_wefac.h" + +namespace blue_sky + { + + template + inline void + main_loop_calc ::compute_acc_rates () + { + typedef typename calc_model_t::strategy_type strategy_type; + typedef typename calc_model_t::well_t well_t; + typedef typename calc_model_t::reservoir_t::facility_manager_t::well_const_iterator_t well_iterator_t; + + typedef typename calc_model_t::sp_well_t sp_well_t; + + well_iterator_t wb = reservoir_->get_facility_list ()->wells_begin (); + well_iterator_t we = reservoir_->get_facility_list ()->wells_end (); + + typename reservoir_t::rate_data_t &rs_rate = reservoir_->rate_; + typename reservoir_t::rate_data_t &rs_rate_rc = reservoir_->rate_rc_; + typename reservoir_t::rate_data_t &rs_rate_wefac = reservoir_->rate_wefac_; + typename reservoir_t::rate_data_t &rs_rate_rc_wefac = reservoir_->rate_rc_wefac_; + typename reservoir_t::rate_data_t &rs_rate_initial = reservoir_->rate_initial_; + typename reservoir_t::rate_data_t &rs_rate_total = reservoir_->rate_total_; + + rs_rate = 0; + rs_rate_rc = 0; + rs_rate_wefac = 0; + rs_rate_rc_wefac = 0; + rs_rate_initial = 0; + rs_rate_total = 0; + + for (; wb != we; ++wb) + { + sp_well_t well (wb->second, bs_dynamic_cast ()); + + bool is_prod = well->get_well_controller ()->is_production (); + item_t wefac = apply_wefac (1.0, well->exploitation_factor_); + item_t wefac_dt = apply_wefac (dt_, wefac); + + //if (well->is_shut () || !well->well_state_.is_work) + // continue; + + // TODO: OPT: + if (is_prod) + { + well->rate_total_.prod += well->rate ().prod * wefac_dt; + } + else + { + well->rate_total_.inj += well->rate ().inj * wefac_dt; + } + + rs_rate += well->rate (); + rs_rate_rc += well->rate_rc_; + rs_rate_wefac += well->rate () * wefac; + rs_rate_rc_wefac += well->rate_rc_ * wefac; + rs_rate_initial += well->rate () * wefac; + rs_rate_total += well->rate_total_; + } + } + + +} // namespace blue_sky + + + +#endif // #ifndef BS_MAIN_LOOP_CALC_COMPUTE_ACC_RATES_H_ diff --git a/bs_bos_core/include/csr_ilu_cfl.h b/bs_bos_core/include/csr_ilu_cfl.h new file mode 100644 index 0000000..c5e8c24 --- /dev/null +++ b/bs_bos_core/include/csr_ilu_cfl.h @@ -0,0 +1,93 @@ +/** +* \file csr_ilu_cfl.h +* \brief child for class csr_ilu (for adaptive cpr) +* \author Elmira Salimgareeva +* \date 11.05.2009 +* */ + +#ifndef BS_CSR_ILU_CFL_PREC_H_ +#define BS_CSR_ILU_CFL_PREC_H_ + + +#include BS_FORCE_PLUGIN_IMPORT () +#include "linear_solvers.h" +#include "csr_ilu_prec.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "calc_model.h" + + +namespace blue_sky +{ + + template + class BS_API_PLUGIN csr_ilu_cfl_prec: public csr_ilu_prec + { + //------------------------------------- + // TYPES + //------------------------------------- + + public: + typedef typename strategy_t::matrix_t matrix_t; //< short name for matrix type + typedef typename strategy_t::item_array_t item_array_t; //< short name for array + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename strategy_t::item_t item_t; //< short name for array item type + typedef typename strategy_t::rhs_item_t rhs_item_t; + typedef typename strategy_t::index_t index_t; //< short name for matrix'es index type + typedef typename strategy_t::index_array_t index_array_t; + typedef calc_model calc_model_t; + typedef jacobian_matrix jmatrix_t; + typedef rs_mesh_iface mesh_iface_t; + typedef typename calc_model_t::data_t data_t; + typedef typename calc_model_t::data_array_t data_array_t; + + typedef typename calc_model_t::sp_mesh_iface_t sp_mesh_iface_t; + typedef typename calc_model_t::sp_jacobian_matrix_t sp_jmatrix_t; + + typedef csr_ilu_prec csr_ilu_prec_t; + + private: + typedef bcsr_matrix bcsr_matrix_t; //< short name for used matrix + typedef smart_ptr sp_bcsr_matrix_t; //< short name for smart pointer for matrix + + //------------------------------------ + // METHODS + //------------------------------------ + public: + + //! destructor + ~csr_ilu_cfl_prec (); + + //! solve + virtual int solve (matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &sol); + + virtual int solve_prec (matrix_t *matrix, item_array_t &rhs, item_array_t &sol); + + //! setup via merging matrices extracted from matrix + virtual int setup (matrix_t *matrix); + + //! init variables + //void init_variables (item_t dt, const sp_bcsr_matrix_t &trns_matrix, item_array_t *pressure, data_array_t *data, const sp_mesh_t &sp_mesh); + + private: + + //void cfl_calc (); + + sp_bcsr_matrix_t create_merged_matrix_for_ilu (jmatrix_t *matrix, const rhs_item_array_t &cfl_vector_); + + public: + BLUE_SKY_TYPE_DECL (csr_ilu_cfl_prec); + + + //--------------------------------------- + // VARIABLES + //--------------------------------------- + private: + sp_bcsr_matrix_t sp_ilu_cfl_; + + }; + +} + + +#endif // #ifdef BS_CSR_ILU_CFL_PREC_H_ diff --git a/bs_bos_core/include/data_storage_interface.h b/bs_bos_core/include/data_storage_interface.h new file mode 100644 index 0000000..fa84bfc --- /dev/null +++ b/bs_bos_core/include/data_storage_interface.h @@ -0,0 +1,82 @@ +/** + * \file data_storage_interface.h + * \brief interface for storage different data + * \author Sergey Miryanov + * \date 21.07.2008 + * */ +#ifndef BS_DATA_STORAGE_INTERFACE_H_ +#define BS_DATA_STORAGE_INTERFACE_H_ + +namespace blue_sky + { + + class BS_API_PLUGIN data_storage : public objbase + { + public: + + virtual ~data_storage () {} + virtual data_storage &save (const std::string &name, const std::string &value); + + template + data_storage &save (const std::string &name, const T &t) + { + return save (name, boost::lexical_cast (t)); + } + + BLUE_SKY_TYPE_DECL (data_storage); + }; + + class BS_API_PLUGIN data_serializer : public objbase + { + public: + + typedef smart_ptr sp_storage_t; + + public: + + virtual ~data_serializer () {} + virtual void save (const sp_storage_t &storage, const sp_obj &obj) const; + + const type_descriptor &handled_type () const; + + BLUE_SKY_TYPE_DECL (data_serializer); + + protected: + + type_descriptor handled_type_; + }; + + class BS_API_PLUGIN data_storage_interface : public objbase + { + public: + + typedef sp_obj sp_storage_t; + typedef smart_ptr sp_serializer_t; + typedef bos_val_table serializer_list_t; + typedef smart_ptr sp_serializer_list_t; + + public: + virtual ~data_storage_interface () {} + + void save (const sp_obj &obj) const; + + void register_serializer (const sp_serializer_t &serializer); + void set_storage (const sp_storage_t &storage); + + BLUE_SKY_TYPE_DECL (data_storage_interface); + + private: + + sp_storage_t storage_; + sp_serializer_list_t serializer_list_; + }; + + ////////////////////////////////////////////////////////////////////////// + bool data_storage_register_type (const plugin_descriptor &pd); + bool data_serializer_register_type (const plugin_descriptor &pd); + bool data_storage_interface_register_type (const plugin_descriptor &pd); + +} // namespace blue_sky + + +#endif // #ifndef BS_DATA_STORAGE_INTERFACE_H_ diff --git a/bs_bos_core/include/date_sim.h b/bs_bos_core/include/date_sim.h new file mode 100644 index 0000000..638d381 --- /dev/null +++ b/bs_bos_core/include/date_sim.h @@ -0,0 +1,28 @@ +#ifndef DATE_SIM_H +#define DATE_SIM_H +/*! + \file date_sim.h + \brief typedef of date structure +*/ + +//! Date structure +typedef struct tm DATE_SIM; + +inline bool operator < (const tm &left, const tm &right) +{ + if (left.tm_yearright.tm_year) return false; + else + { + if (left.tm_monright.tm_mon) return false; + else + { + if (left.tm_mdayright.tm_mday) return false; + } + } + return false; +} + +#endif // DATE_SIM_H diff --git a/bs_bos_core/include/debug_tools.h b/bs_bos_core/include/debug_tools.h new file mode 100644 index 0000000..fe3c496 --- /dev/null +++ b/bs_bos_core/include/debug_tools.h @@ -0,0 +1,74 @@ +#ifndef __DEBUG_TOOLS_H_ +#define __DEBUG_TOOLS_H_ +/*! + * \file debug_tools.h + * \brief usefull tools for debug + * \author Borschuk Oleg + * \date 2006-06-19 + */ +#ifdef _MPI +#include +#endif + +#include + +// Generate a messagebox with error message and exit a program +int error_messager (const char *filenum, const int line, const char *errormessage); + +/** */ +struct AutoFile + { + /** */ + FILE *fp_; + + AutoFile(FILE *fp = 0) : fp_(fp) {} + + ~AutoFile() + { + if (fp_) + fclose(fp_); + } + + FILE *operator()() const + { + return fp_; + } + }; + +bool file_exists(const char *file_name); + +/*! + \param offset number of items from beginning of file + \return 0 if successful + */ +int write_vector_to_file(FILE *fp, double *vector, size_t n, int offset); + +int write_vector_to_file(const char *file_name, double *vector, size_t n, int offset); + +/*! + \param offset number of items from beginning of file + \return 0 if successful + */ +int read_vector_from_file(FILE *fp, double *vector, size_t n, int offset); + +int read_vector_from_file(const char *file_name, double *vector, size_t n, int offset); + +// print vector to file (one string is one value) +// DANGER! overflow is not checked! + +int write_vector_to_file (const char *file_name, double *vector, const int n); + +// print int vector to file (one string is one value) +// DANGER! overflow is not checked! +int write_int_vector_to_file (const char *file_name, int* vector, const int n); +#ifdef _MPI +int mpi_write_int_vector_to_file (const char *file_name, int* vector, const int n, MPI_Comm comm); +int mpi_write_vector_to_file (const char *file_name, double* vector, const int n, MPI_Comm comm); +#endif +// read vector from file +// DANGER! overflow is not checked! +int read_vector_from_file (const char *file_name, double* vector, const int n); + +int write_int_vector_to_file (const char *file_name, int* vector, const int n); +#endif //__DEBUG_TOOLS_H_ + diff --git a/bs_bos_core/include/default_connection.h b/bs_bos_core/include/default_connection.h new file mode 100644 index 0000000..aa53ab7 --- /dev/null +++ b/bs_bos_core/include/default_connection.h @@ -0,0 +1,57 @@ +/** + * \file default_connection.h + * \brief default impl of connection + * \author Sergey Miryanov + * \date 20.05.2009 + * */ +#ifndef BS_BOS_CORE_DEFAULT_CONNECTION_H_ +#define BS_BOS_CORE_DEFAULT_CONNECTION_H_ + +#include "well_connection.h" +#include "array_ext.h" + +namespace blue_sky { +namespace wells { + + template + class BS_API_PLUGIN default_connection : public connection + { + public: + + typedef connection base_t; + typedef typename base_t::item_t item_t; + typedef typename base_t::rhs_item_t rhs_item_t; + + public: + + BLUE_SKY_TYPE_DECL_T (default_connection ); + + void clear_data (); + array_ext get_rw_value (); + array_ext get_wr_value (); + array_ext get_rr_value (); + array_ext get_ps_value (); + array_ext get_rate_value (); + + public: + + enum + { + rr_value_count = FI_PHASE_TOT * FI_PHASE_TOT + FI_PHASE_TOT, + }; + + boost::array mobility_value; + boost::array rate_value; + boost::array ps_value; + boost::array rr_value; + boost::array rw_value; + boost::array wr_value; + }; + + +} // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_BOS_CORE_DEFAULT_CONNECTION_H_ + + diff --git a/bs_bos_core/include/default_rr_eliminator.h b/bs_bos_core/include/default_rr_eliminator.h new file mode 100644 index 0000000..9acd3f0 --- /dev/null +++ b/bs_bos_core/include/default_rr_eliminator.h @@ -0,0 +1,133 @@ +/** + * \file default_rr_eliminator.h + * \brief eliminate rr for default well impl + * \author Sergey Miryanov + * \date 20.05.2009 + * */ +#ifndef BS_DEFAULT_RR_ELIMINATOR_H_ +#define BS_DEFAULT_RR_ELIMINATOR_H_ + +namespace blue_sky { + + template + struct default_rr_eliminator + { + void + process_diag_rate () + { + //res += (rr - rw * wr) * dt; + } + void + process_diag_bhp () + { + //res += rr * dt; + } + void + process_rate () + { + //res += (-1) * rw * wr * dt; + } + }; + template <> + struct default_rr_eliminator <3> + { + template + static void + process_diag_rate (res_t &res, const rr_t &rr, const rw_t &rw, const wr_t &wr, dt_t dt) + { + res[0] += (rr[0] - (rw[0] * wr[0])) * dt; + res[1] += (rr[1] - (rw[0] * wr[1])) * dt; + res[2] += (rr[2] - (rw[0] * wr[2])) * dt; + res[3] += (rr[3] - (rw[1] * wr[0])) * dt; + res[4] += (rr[4] - (rw[1] * wr[1])) * dt; + res[5] += (rr[5] - (rw[1] * wr[2])) * dt; + res[6] += (rr[6] - (rw[2] * wr[0])) * dt; + res[7] += (rr[7] - (rw[2] * wr[1])) * dt; + res[8] += (rr[8] - (rw[2] * wr[2])) * dt; + } + template + static void + process_diag_bhp (res_t &res, const rr_t &rr, dt_t dt) + { + res[0] += rr[0] * dt; + res[1] += rr[1] * dt; + res[2] += rr[2] * dt; + res[3] += rr[3] * dt; + res[4] += rr[4] * dt; + res[5] += rr[5] * dt; + res[6] += rr[6] * dt; + res[7] += rr[7] * dt; + res[8] += rr[8] * dt; + } + template + static void + process_rate (res_t &res, const rw_t &rw, const wr_t &wr, dt_t dt) + { + res[0] += -(rw[0] * wr[0]) * dt; + res[1] += -(rw[0] * wr[1]) * dt; + res[2] += -(rw[0] * wr[2]) * dt; + res[3] += -(rw[1] * wr[0]) * dt; + res[4] += -(rw[1] * wr[1]) * dt; + res[5] += -(rw[1] * wr[2]) * dt; + res[6] += -(rw[2] * wr[0]) * dt; + res[7] += -(rw[2] * wr[1]) * dt; + res[8] += -(rw[2] * wr[2]) * dt; + } + }; + template <> + struct default_rr_eliminator <2> + { + template + static void + process_diag_rate (res_t &res, const rr_t &rr, const rw_t &rw, const wr_t &wr, dt_t dt) + { + res[0] += (rr[0] - (rw[0] * wr[0])) * dt; + res[1] += (rr[1] - (rw[0] * wr[1])) * dt; + res[2] += (rr[2] - (rw[1] * wr[0])) * dt; + res[3] += (rr[3] - (rw[1] * wr[1])) * dt; + } + template + static void + process_diag_bhp (res_t &res, const rr_t &rr, dt_t dt) + { + res[0] += rr[0] * dt; + res[1] += rr[1] * dt; + res[2] += rr[2] * dt; + res[3] += rr[3] * dt; + } + template + static void + process_rate (res_t &res, const rw_t &rw, const wr_t &wr, dt_t dt) + { + res[0] += -(rw[0] * wr[0]) * dt; + res[1] += -(rw[0] * wr[1]) * dt; + res[2] += -(rw[1] * wr[0]) * dt; + res[3] += -(rw[1] * wr[1]) * dt; + } + }; + template <> + struct default_rr_eliminator <1> + { + template + static void + process_diag_rate (res_t &res, const rr_t &rr, const rw_t &rw, const wr_t &wr, dt_t dt) + { + res[0] += (rr[0] - (rw[0] * wr[0])) * dt; + } + template + static void + process_diag_bhp (res_t &res, const rr_t &rr, dt_t dt) + { + res[0] += rr[0] * dt; + } + template + static void + process_rate (res_t &res, const rw_t &rw, const wr_t &wr, dt_t dt) + { + res[0] += -(rw[0] * wr[0]) * dt; + } + }; +} // namespace blue_sky + +#endif // #ifndef BS_DEFAULT_RR_ELIMINATOR_H_ + diff --git a/bs_bos_core/include/default_well.h b/bs_bos_core/include/default_well.h new file mode 100644 index 0000000..f667beb --- /dev/null +++ b/bs_bos_core/include/default_well.h @@ -0,0 +1,110 @@ +/** + * \file default_well.h + * \brief default well for bs_bos_core + * \author Sergey Miryanov + * \date 20.05.2009 + * */ +#ifndef BS_BOS_CORE_DEFAULT_WELL_H_ +#define BS_BOS_CORE_DEFAULT_WELL_H_ + +#include "calc_well.h" +#include "default_connection.h" + +namespace blue_sky { +namespace wells { + + template + class BS_API_PLUGIN default_well : public well + { + public: + typedef well base_t; + typedef well well_t; + typedef typename base_t::item_array_t item_array_t; + typedef typename base_t::rhs_item_array_t rhs_item_array_t; + typedef typename base_t::index_array_t index_array_t; + typedef typename base_t::index_t index_t; + typedef typename base_t::item_t item_t; + typedef typename base_t::rhs_item_t rhs_item_t; + + typedef typename base_t::sp_calc_model_t sp_calc_model_t; + typedef typename base_t::sp_mesh_iface_t sp_mesh_iface_t; + typedef typename base_t::sp_jmatrix_t sp_jmatrix_t; + + typedef typename base_t::connection_t connection_t; + typedef default_connection default_connection_t; + + typedef typename base_t::sp_connection_t sp_connection_t; + typedef smart_ptr sp_default_connection_t; + + typedef seq_vector connection_list_t; + typedef index_t connection_block_t; + typedef index_t connection_index_t; + typedef std::map connection_map_t; + + public: + + default_well (const std::string &well_name); + + BLUE_SKY_TYPE_DECL_T (default_well ); + + void + restore_solution (double dt, const item_array_t &p_sol, const item_array_t &s_sol, index_t block_size); + + void + process (bool is_start, double dt, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix); + + void + eliminate (rhs_item_t *array, index_t rw_index, index_t wr_index, double dt, index_t block_size) const; + + void + clear_data (); + + array_ext + get_ww_value (); + + array_ext + get_bw_value (); + + protected: + void + process_internal (bool is_start, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix); + + template + void + calc_rate_and_derivs (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix); + + template + void + calc_rate_and_derivs_concrete (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix); + + public: + sp_connection_t + add_connection (index_t i_coord, index_t j_coord, index_t k_coord, index_t n_block); + + sp_connection_t + get_connection (index_t idx) const; + + sp_connection_t + get_connection_map (index_t n_block) const; + + virtual size_t + get_connections_count () const; + + public: + + item_t ww_value; + item_t bw_value; + + connection_list_t connection_list_; + connection_map_t connection_map_; + }; + + bool + default_well_register_types (const blue_sky::plugin_descriptor &pd); + + +} // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_BOS_CORE_DEFAULT_WELL_H_ + diff --git a/bs_bos_core/include/default_well_rate_control_factory.h b/bs_bos_core/include/default_well_rate_control_factory.h new file mode 100644 index 0000000..60445ef --- /dev/null +++ b/bs_bos_core/include/default_well_rate_control_factory.h @@ -0,0 +1,36 @@ +/** + * \file default_well_rate_control_factory.h + * \brief factory to construct well_rate_control for default well model + * \author Sergey Miryanov + * \date 21.05.2009 + * */ +#ifndef BS_BOS_CORE_DEFAULT_WELL_RATE_CONTROL_FACTORY_H_ +#define BS_BOS_CORE_DEFAULT_WELL_RATE_CONTROL_FACTORY_H_ + +#include "well_rate_control_interface.h" + +namespace blue_sky { +namespace wells { + + template + class BS_API_PLUGIN default_well_rate_control_factory : public well_rate_control_factory + { + public: + + typedef well_rate_control_factory base_t; + typedef typename base_t::sp_calc_model_t sp_calc_model_t; + typedef typename base_t::sp_well_rate_control_t sp_well_rate_control_t; + + sp_well_rate_control_t + create_control (rate_control_type control_type, bool is_bhp, bool is_production, const sp_calc_model_t &calc_model); + + BLUE_SKY_TYPE_DECL_T (default_well_rate_control_factory); + }; + + + +} // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_BOS_CORE_DEFAULT_WELL_RATE_CONTROL_FACTORY_H_ + diff --git a/bs_bos_core/include/event_base.h b/bs_bos_core/include/event_base.h new file mode 100644 index 0000000..e555832 --- /dev/null +++ b/bs_bos_core/include/event_base.h @@ -0,0 +1,137 @@ +/** + * @file event_base.h + * @brief + * @author Morozov Andrey + * @date 2008-06-07 + * */ + +#ifndef EVENT_BASE_H_ +#define EVENT_BASE_H_ + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" +#include "data_storage_interface.h" + +namespace blue_sky + { + + template + class reservoir; + + template + class calc_model; + + template + class BS_API_PLUGIN event_base : public objbase //: public named_pbase//, public combase + { + //----------------------------------------- + // TYPES + //----------------------------------------- + public: + //TODO:change objbase to reservoir + typedef reservoir reservoir_t; + typedef rs_mesh_iface mesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_top; + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_named_pbase; + + typedef event_base self_t; + typedef self_t this_t; + + typedef named_pbase::ndt_t ndt_t; + typedef named_pbase::named_pbase_idxs named_pbase_idxs; + + //additional + public: + + //----------------------------------------- + // METHODS + //----------------------------------------- + //blue-sky class declaration + public: + BLUE_SKY_TYPE_DECL(event_base); + + public: + //! destructor + virtual ~event_base (); + + virtual void apply(const sp_top &top, const sp_mesh_iface_t &mesh, + const sp_calc_model_t &calc_model) const; //!< virtual apply function + + //!< initialization + void + init (const std::string &event_name, const std::string ¶ms); + + void + add_next_line (const std::string &event_name, const std::string ¶ms); + + //!< check is keyword (or event) is multiline + virtual bool + is_multi_line () const + { + return false; + } + + protected: + + + + virtual sp_named_pbase + main_params () const + { + return 0; + } + + virtual sp_named_pbase + add_next_line_params () + { + bs_throw_exception ("PURE CALL"); + } + + + //!< parameters string parsing + void + parse (const std::string ¶ms_str, const sp_named_pbase ¶ms); + + //!< functions used by boost spirit parser + void + save_def (const sp_named_pbase ¶ms, const char c = '_'); //!< skip a default value + + //!< clear num + void + clear_num (const sp_named_pbase ¶ms, const char *begin = 0, const char *end = 0); + + //! next_line_params; //!< next lines params + }; + + debug_data debug_data_; //!< debug data +#endif + + int num; //!< temporary variables to store a number of same parameters + int index; //!< index of parameter which is parsed in this moment + bool no_error_; + }; + + bool + event_base_register_types (const plugin_descriptor &pd); + +}//namespace blue_sky + +#endif//EVENT_BASE_H_ + diff --git a/bs_bos_core/include/event_filter.h b/bs_bos_core/include/event_filter.h new file mode 100644 index 0000000..c685ca8 --- /dev/null +++ b/bs_bos_core/include/event_filter.h @@ -0,0 +1,39 @@ +/** + * \file event_filter.h + * \brief filter events + * \author Sergey Miryanov + * \date 15.12.2008 + * */ +#ifndef BS_EVENT_FILTER_H_ +#define BS_EVENT_FILTER_H_ + +namespace blue_sky + { + + class BS_API_PLUGIN event_filter : public objbase + { + public: + + virtual ~event_filter () {} + virtual bool accept_well (const std::string &name) const; + + virtual void add_filter_well (const std::string &well_name); + virtual void set_reject_all (bool reject_all); + + BLUE_SKY_TYPE_DECL (event_filter); + + protected: + + typedef std::list well_name_list_t; + + well_name_list_t well_name_list_; + auto_value reject_all_; + + }; + + +} // namespace blue_sky + + +#endif // BS_EVENT_FILTER_H_ + diff --git a/bs_bos_core/include/event_manager.h b/bs_bos_core/include/event_manager.h new file mode 100644 index 0000000..35a4f2e --- /dev/null +++ b/bs_bos_core/include/event_manager.h @@ -0,0 +1,83 @@ +/** +* @file well_event.h +* @brief declaration of event manager class +* @author Morozov Andrey +* @date 2008-06-07 +*/ +#ifndef EVENT_MANAGER_H_ +#define EVENT_MANAGER_H_ + +#include "event_base.h" + +namespace blue_sky + { + + template + class event_base; + + template + class reservoir; + + /** + * @brief even_manager class to store events and to manage of them. + */ + template + class BS_API_PLUGIN event_manager : public objbase + { + //----------------------------------------- + // TYPES + //----------------------------------------- + public: + typedef event_base event_base_t; + typedef smart_ptr < event_base_t > sp_event_base; + typedef reservoir sp_top; + typedef event_manager self_t; + typedef self_t this_t; + typedef std::list < sp_event_base > sp_event_base_list; + typedef boost::posix_time::ptime date_t; + typedef std::map event_map; + + //----------------------------------------- + // METHODS + //----------------------------------------- + //blue-sky class declaration + public: + BLUE_SKY_TYPE_DECL(event_manager); + + public: + //! destructor + virtual ~event_manager (); + + void + process_event (const date_t &date, const std::string &event_name, const std::string &event_params); + + void + end_event (); + + sp_event_base + create_event(const boost::posix_time::ptime &date, const std::string & event_name, const std::string & event_params); + + + //void save_keyword(iterator_t first, iterator_t const& last); + //void free_keyword(iterator_t first, iterator_t const& last); + //void read_event(iterator_t first, iterator_t const& last); + + //----------------------------------------- + // VARIABLES + //----------------------------------------- + public: + event_map event_list; + + private: + sp_event_base current_event_; + }; + + bool + well_events_register_type (const blue_sky::plugin_descriptor &pd); + + bool + event_manager_register_types (const plugin_descriptor &pd); + +}//ns bs + +#endif // #ifndef EVENT_MANAGER_H_ diff --git a/bs_bos_core/include/exp_temp_mx.h b/bs_bos_core/include/exp_temp_mx.h new file mode 100644 index 0000000..2c2f71d --- /dev/null +++ b/bs_bos_core/include/exp_temp_mx.h @@ -0,0 +1,961 @@ +/** + * \file exp_temp_mx.h + * \brief matrix arithmetics on expression templates + * \author Sergey Miryanov + * \date 20.10.2008 + * */ +#ifndef BS_EXPRESSION_TEMPLATES_MATRIX_ARITHMETIC_H_ +#define BS_EXPRESSION_TEMPLATES_MATRIX_ARITHMETIC_H_ + +namespace blue_sky + { + + struct ref_trait {}; + struct ref_unsafe_trait {}; + struct const_trait {}; + struct const_unsafe_trait {}; + + template + struct mx_holder + { + typedef array_t_ array_t; + typedef typename array_t::value_type value_type; + typedef mx_holder this_t; + + mx_holder (const array_t &array_, size_t size) + : array_ (array_) + , block_size_ (size * size) + { + BS_ASSERT (block_size_ <= 9) (block_size_); + } + + value_type + operator [] (size_t i) const + { + return array_[i]; + } + + size_t + block_size () const + { + return block_size_; + } + + const array_t &array_; + size_t block_size_; + }; + template + struct mx_holder + { + + typedef array_t_ array_t; + typedef typename array_t::value_type value_type; + typedef mx_holder this_t; + + mx_holder (array_t &array_, size_t idx, size_t size) + : array_ (array_) + , block_size_ (size * size) + , idx_ (idx * block_size_) + { + BS_ASSERT (block_size_ <= 9) (block_size_); + } + + template + this_t & + operator= (const op_t &op) + { + for (size_t i = 0, cnt = block_size_; i < cnt; ++i) + { + array_[i + idx_] = op[i]; + } + + return *this; + } + + template + this_t & + operator+= (const op_t &op) + { + for (size_t i = 0, cnt = block_size_; i < cnt; ++i) + { + array_[i + idx_] += op[i]; + } + + return *this; + } + + value_type & + operator [] (size_t index) + { + if (idx_ + index >= array_.size ()) + throw bs_exception ("mx_holder[]", "index out of range"); + + return array_[idx_ + index]; + } + + array_t &array_; + size_t block_size_; + size_t idx_; + }; + template + struct clmn_holder + { + + typedef array_t_ array_t; + typedef typename array_t::value_type value_type; + typedef clmn_holder this_t; + + clmn_holder (const array_t &array_, size_t size) + : array_ (array_) + , block_size_ (size) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + value_type + operator [] (size_t i) const + { + return array_[i % block_size_]; + } + + size_t + block_size () const + { + return block_size_; + } + + const array_t &array_; + size_t block_size_; + }; + template + struct clmn_holder + { + typedef array_t_ array_t; + typedef typename array_t::value_type value_type; + typedef clmn_holder this_t; + + clmn_holder (const array_t &array_, size_t index, size_t size) + : array_ (array_) + , index_ (index * size) + , block_size_ (size) + , unsafe_array_ (&array_[index_]) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + value_type + operator [] (size_t i) const + { + return unsafe_array_[i % block_size_]; + } + + size_t + block_size () const + { + return block_size_; + } + + const array_t &array_; + size_t index_; + size_t block_size_; + const value_type *unsafe_array_; + }; + template + struct clmn_holder + { + typedef array_t_ array_t; + typedef typename array_t::value_type value_type; + typedef clmn_holder this_t; + + clmn_holder (array_t &array, size_t idx, size_t size) + : array_ (array) + , idx_ (idx * size) + , block_size_ (size) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + template + this_t & + operator= (const op_t &op) + { + for (size_t i = 0, cnt = block_size_; i < cnt; ++i) + { + array_[idx_ + i] = op[i]; + } + + return *this; + } + + array_t &array_; + size_t idx_; + size_t block_size_; + }; + + template + struct line_holder + { + typedef array_type array_t; + typedef typename array_t::value_type value_type; + typedef line_holder this_t; + + line_holder (const array_t &array_, size_t size) + : array_ (array_) + , block_size_ (size) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + value_type + operator [] (size_t i) const + { + return array_[i % block_size_]; + } + size_t + block_size () const + { + return block_size_; + } + + const array_t &array_; + size_t block_size_; + }; + + template + struct line_holder + { + typedef array_type array_t; + typedef typename array_t::value_type value_type; + typedef line_holder this_t; + + line_holder (const array_t &array_, size_t index, size_t size) + : array_ (array_) + , index_ (index) + , block_size_ (size) + , unsafe_array_ (&array_[index_ * block_size_]) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + value_type + operator [] (size_t i) const + { + return unsafe_array_[i % block_size_]; + } + size_t + block_size () const + { + return block_size_; + } + + const array_t &array_; + size_t block_size_; + size_t index_; + const value_type *unsafe_array_; + }; + + template + struct line_holder + { + typedef array_type array_t; + typedef typename array_t::value_type value_type; + typedef line_holder this_t; + + line_holder (const array_t &array_, size_t index, size_t size) + : array_ (array_) + , index_ (index) + , block_size_ (size) + , unsafe_array_ (&array_[index_ * block_size_]) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + template + this_t & + operator= (const op_t &op) + { + for (size_t i = 0, cnt = block_size_; i < cnt; ++i) + { + unsafe_array_[i] = op [i]; + } + + return *this; + } + + const array_t &array_; + size_t block_size_; + size_t index_; + const value_type *unsafe_array_; + }; + + template + struct line_holder + { + typedef array_type array_t; + typedef typename array_t::value_type value_type; + typedef line_holder this_t; + + line_holder (array_t &array_, size_t size) + : array_ (array_) + , block_size_ (size) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + template + this_t & + operator= (const op_t &op) + { + for (size_t i = 0, cnt = block_size_; i < cnt; ++i) + { + array_[i] = op[i]; + } + + return *this; + } + + array_t &array_; + size_t block_size_; + }; + + template + struct mx_op + { + typedef typename mx_op_t::value_type value_type; + typedef mx_op_t op_t; + + mx_op (const mx_op_t &mx_op_) + : mx_op_ (mx_op_) + { + } + + value_type + operator [] (size_t i) const + { + return mx_op_[i]; + } + + size_t + block_size () const + { + return mx_op_.block_size (); + } + + mx_op_t mx_op_; + }; + + template + struct clmn_op + { + typedef typename clmn_op_t::value_type value_type; + typedef clmn_op_t op_t; + + clmn_op (const clmn_op_t &clmn_op_) + : clmn_op_ (clmn_op_) + { + } + + value_type + operator [] (size_t i) const + { + return clmn_op_ [i]; + } + + size_t + block_size () const + { + return clmn_op_.block_size (); + } + + clmn_op_t clmn_op_; + }; + + template + struct line_op + { + typedef typename line_op_t::value_type value_type; + typedef line_op_t op_t; + + line_op (const line_op_t &line_op) + : line_op_ (line_op) + { + } + + value_type + operator [] (size_t i) const + { + return line_op_[i]; + } + + size_t + block_size () const + { + return line_op_.block_size (); + } + + line_op_t line_op_; + }; + + template + struct scalar_op + { + typedef scalar_op_t op_t; + typedef typename op_t::value_type value_type; + + scalar_op (const op_t &op) + : op_ (op) + { + } + + operator value_type () const + { + return op_; + } + + op_t op_; + }; + + /// + template + struct mx_mul + { + typedef typename lhs_t::value_type value_type; + + mx_mul (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + template + mx_mul (const lhs_t &lhs, const array_t &array) + : lhs_ (lhs) + , rhs_ (rhs_t (array)) + { + } + + template + mx_mul (const array_t &array, const rhs_t &rhs) + : lhs_ (lhs_t (array)) + , rhs_ (rhs) + { + } + + value_type + operator [] (size_t i) const + { + size_t bs = lhs_.block_size (); + size_t ri = i / bs; + size_t ci = i % bs; + + value_type res = 0; + for (size_t j = 0; j < bs; ++j) + { + res += lhs_[ri * bs + j] * rhs_[j * bs + ci]; + } + + return res; + } + + size_t + block_size () const + { + return lhs_.block_size (); + } + + lhs_t lhs_; + rhs_t rhs_; + }; + + template + struct mx_sub + { + typedef typename lhs_t::value_type value_type; + + mx_sub (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + template + mx_sub (const lhs_t &lhs, const array_t &array) + : lhs_ (lhs) + , rhs_ (rhs_t (array)) + { + } + + template + mx_sub (const array_t &array, const rhs_t &rhs) + : lhs_ (lhs_t (array)) + , rhs_ (rhs) + { + } + + value_type + operator [] (size_t i) const + { + return lhs_[i] - rhs_[i]; + } + + size_t + block_size () const + { + return lhs_.block_size (); + } + + lhs_t lhs_; + rhs_t rhs_; + }; + + template + struct mx_clmn_mul + { + typedef typename lhs_t::value_type value_type; + + mx_clmn_mul (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + value_type + operator [] (size_t i) const + { + return lhs_[i] * rhs_[i / lhs_.block_size ()]; + } + + size_t + block_size () const + { + return lhs_.block_size (); + } + + lhs_t lhs_; + rhs_t rhs_; + }; + + template + struct clmn_line_mul + { + typedef typename lhs_t::value_type value_type; + + clmn_line_mul (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + value_type + operator [] (size_t i) const + { + size_t bs = lhs_.block_size (); + size_t ri = i / bs; + size_t ci = i % bs; + + return lhs_[ri] * rhs_[ci]; + } + + size_t + block_size () const + { + return lhs_.block_size (); + } + + const lhs_t &lhs_; + const rhs_t &rhs_; + }; + template + struct line_clmn_mul + { + typedef typename lhs_t::value_type value_type; + + line_clmn_mul (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + operator value_type () const + { + value_type res = 0; + for (size_t i = 0, cnt = lhs_.block_size (); i < cnt; ++i) + { + res += lhs_[i] * rhs_[i]; + } + + return res; + } + + lhs_t lhs_; + rhs_t rhs_; + }; + + + template + struct clmn_sub + { + typedef typename lhs_t::value_type value_type; + + clmn_sub (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + value_type + operator [] (size_t i) const + { + return lhs_[i] - rhs_[i]; + } + + size_t + block_size () const + { + return lhs_.block_size (); + } + + lhs_t lhs_; + rhs_t rhs_; + }; + + template + struct mx_scalar_mul + { + typedef array_t_ array_t; + typedef typename array_t::value_type value_type; + typedef mx_scalar_mul this_t; + + mx_scalar_mul (const array_t &lhs, value_type rhs, size_t size) + : lhs_ (lhs) + , rhs_ (rhs) + , block_size_ (size * size) + { + BS_ASSERT (block_size_ <= 9) (block_size_); + } + + value_type + operator [] (size_t i) const + { + return lhs_[i] * rhs_; + } + + size_t + block_size () const + { + return block_size_; + } + + array_t lhs_; + value_type rhs_; + size_t block_size_; + }; + template + struct clmn_scalar_mul + { + typedef array_type array_t; + typedef typename array_t::value_type value_type; + typedef clmn_scalar_mul this_t; + + clmn_scalar_mul (const array_t &lhs, value_type rhs, size_t size) + : lhs_ (lhs) + , rhs_ (rhs) + , block_size_ (size) + { + BS_ASSERT (block_size_ <= 3) (block_size_); + } + + value_type + operator [] (size_t i) const + { + BS_ASSERT (i < block_size_); + return lhs_[i] * rhs_; + } + + size_t + block_size () const + { + return block_size_; + } + + const array_t &lhs_; + value_type rhs_; + size_t block_size_; + }; + + template + struct line_mul + { + typedef typename lhs_t::value_type value_type; + + line_mul (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + value_type + operator [] (size_t i) const + { + return lhs_[i] * rhs_[i]; + } + + size_t + block_size () const + { + return lhs_.block_size (); + } + + lhs_t lhs_; + rhs_t rhs_; + }; + template + struct line_sub + { + typedef typename lhs_t::value_type value_type; + + line_sub (const lhs_t &lhs, const rhs_t &rhs) + : lhs_ (lhs) + , rhs_ (rhs) + { + } + + value_type + operator [] (size_t i) const + { + return lhs_[i] - rhs_[i]; + } + + size_t + block_size () const + { + return lhs_.block_size (); + } + + lhs_t lhs_; + rhs_t rhs_; + }; + + + template + struct mx_inverse + { + typedef array_t_ array_t; + typedef typename array_t::value_type value_type; + typedef mx_inverse this_t; + + mx_inverse (const array_t &mx, size_t size) + : mx_ (mx) + , block_size_ (size * size) + { + BS_ASSERT (block_size_ <= 9) (block_size_); + calc_inverse_matrix (block_size_, mx_); + } + + value_type + operator [] (size_t i) const + { + return mx_[i]; + } + + size_t + block_size () const + { + return block_size_; + } + + array_t mx_; + size_t block_size_; + }; + + /// + template + mx_op > + operator* (const mx_op &lhs, const mx_op &rhs) + { + return mx_op > (mx_mul (lhs.mx_op_, rhs.mx_op_)); + } + template + mx_op > > + operator* (const mx_op &lhs, const mx_holder &rhs) + { + return mx_op > > (mx_mul > (lhs.mx_op_, rhs)); + } + template + mx_op , rhs_t> > + operator* (const mx_holder &lhs, const mx_op &rhs) + { + return mx_op , rhs_t> > (mx_mul , rhs_t> (lhs, rhs.mx_op_)); + } + template + mx_op , rhs_t> > + operator- (const mx_holder &lhs, const mx_op &rhs) + { + return mx_op , rhs_t> > (mx_sub , rhs_t> (lhs, rhs.mx_op_)); + } + template + mx_op > > + operator- (const mx_op &lhs, const mx_holder &rhs) + { + return mx_op > > (mx_sub > (lhs.mx_op_, rhs)); + } + template + mx_op > + operator- (const mx_op &lhs, const mx_op &rhs) + { + return mx_op > (mx_sub (lhs.mx_op_, rhs.mx_op_)); + } + + template + mx_op , line_holder > > + operator* (const clmn_holder &lhs, const line_holder &rhs) + { + return mx_op , line_holder > > (clmn_line_mul , line_holder > (lhs, rhs)); + } + template + mx_op , line_holder > > + operator* (const clmn_holder &lhs, const line_holder &rhs) + { + return mx_op , line_holder > > (clmn_line_mul , line_holder > (lhs, rhs)); + } + template + mx_op > > + operator* (const clmn_op &lhs, line_holder &rhs) + { + return mx_op > > (clmn_line_mul > (lhs.clmn_op_, rhs)); + } + template + line_op , line_holder > > + operator* (const line_holder &lhs, const line_holder &rhs) + { + return line_op , line_holder > > (line_mul , line_holder > (lhs, rhs)); + } + template + scalar_op , clmn_holder > > + operator* (const line_holder &lhs, const clmn_holder &rhs) + { + return scalar_op , clmn_holder > > (line_clmn_mul , clmn_holder > (lhs, rhs)); + } + template + scalar_op > > + operator* (const line_op &lhs, const clmn_holder &rhs) + { + return scalar_op > > (line_clmn_mul > (lhs.line_op_, rhs)); + } + template + line_op > + operator* (const line_op &lhs, const line_op &rhs) + { + return line_op > (line_mul (lhs.line_op_, rhs.line_op_)); + } + template + line_op > > + operator* (const line_op &lhs, const line_holder &rhs) + { + return line_op > > (line_mul > (lhs.line_op_, rhs)); + } + template + line_op , rhs_t> > + operator- (const line_holder &lhs, const line_op &rhs) + { + return line_op , rhs_t> > (line_sub , rhs_t> (lhs, rhs.line_op_)); + } + template + line_op > + operator- (const line_op &lhs, const line_op &rhs) + { + return line_op > (line_sub (lhs.line_op_, rhs.line_op_)); + } + template + clmn_op , clmn_holder > > + operator* (const mx_holder &mx, const clmn_holder &column) + { + return clmn_op , clmn_holder > > (mx_clmn_mul , clmn_holder > (mx, column)); + } + template + clmn_op > > + operator* (const mx_op &lhs, const clmn_holder &column) + { + return clmn_op > > (mx_clmn_mul > (lhs.mx_op_, column)); + } + // + template + clmn_op > + operator- (const clmn_op &lhs, const clmn_op &rhs) + { + return clmn_op > (clmn_sub (lhs.clmn_op_, rhs.clmn_op_)); + } + template + clmn_op , clmn_holder > > + operator- (const clmn_holder &lhs, const clmn_holder &rhs) + { + return clmn_op , clmn_holder > > (clmn_sub , clmn_holder > (lhs, rhs)); + } + template + clmn_op , rhs_t> > + operator- (const clmn_holder &lhs, const clmn_op &rhs) + { + return clmn_op , rhs_t> > (clmn_sub , rhs_t> (lhs, rhs.clmn_op_)); + } + // + template + mx_op > + operator* (const mx_t &mx, typename mx_t::value_type scalar) + { + return mx_op > (mx_scalar_mul (mx.array_, scalar, mx.block_size_)); + } + template + mx_op > + operator* (const mx_op &mx, typename lhs_t::value_type scalar) + { + return mx_op > (mx_scalar_mul (mx.mx_op_, scalar, (size_t)mx.block_size ())); + } + template + clmn_op > + operator* (const clmn_holder &clmn, typename array_t::value_type scalar) + { + return clmn_op > (clmn_scalar_mul (clmn.array_, scalar, clmn.block_size_)); + } + template + clmn_op > + operator* (const clmn_op &clmn, typename lhs_t::value_type scalar) + { + return clmn_op > (clmn_scalar_mul (clmn.clmn_op_, scalar, (size_t)clmn.block_size ())); + } + template + clmn_op > + operator* (typename array_t::value_type scalar, const clmn_holder &clmn) + { + return clmn_op > (clmn_scalar_mul (clmn.array_, scalar, clmn.block_size_)); + } + template + line_op > + operator* (lhs_t scalar, const line_holder &rhs) + { + return line_op > (clmn_scalar_mul (rhs.array_, scalar, rhs.block_size ())); + } + template + line_op > + operator* (const line_holder &lhs, typename lhs_t::value_type scalar) + { + return line_op > (clmn_scalar_mul (lhs.array_, scalar, lhs.block_size ())); + } + template + item_t + operator- (item_t lhs, const scalar_op &rhs) + { + return lhs - static_cast (rhs); + } + // + template + mx_op > + inverse (const mx_t &mx) + { + return mx_op > (mx_inverse (mx.array_, mx.block_size_)); + } + +} // namespace blue_sky + + +#endif // #ifndef BS_EXPRESSION_TEMPLATES_MATRIX_ARITHEMTIC_H_ + diff --git a/bs_bos_core/include/facility_base.h b/bs_bos_core/include/facility_base.h new file mode 100644 index 0000000..2242f4a --- /dev/null +++ b/bs_bos_core/include/facility_base.h @@ -0,0 +1,55 @@ +/** + * \file facility_base.h + * \brief base class for facilities (wells and unnamed wells) + * \author Sergey Miryanov + * \date 16.07.2008 + */ +#ifndef BS_FACILITY_BASE_H_ +#define BS_FACILITY_BASE_H_ + +#include "calc_model.h" + +namespace blue_sky { + + template + class BS_API_PLUGIN facility_base : public objbase + { + public: + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename strategy_t::index_t index_t; + + typedef calc_model calc_model_t; + typedef rs_mesh_iface mesh_iface_t; + typedef jacobian_matrix jmatrix_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_jmatrix_t; + + public: + //! destructor + virtual ~facility_base () {} + + virtual void fill_rows (index_array_t &rows) const = 0; + virtual void fill_jacobian (double dt, index_t block_size, const index_array_t &rows, index_array_t &cols, rhs_item_array_t &values, index_array_t &markers) const = 0; + virtual void fill_rhs (double dt, index_t n_phases, bool is_g, bool is_o, bool is_w, rhs_item_array_t &rhs) const = 0; + + virtual void process (bool is_start, double dt, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix) = 0; + + virtual void restore_solution (double dt, const item_array_t &p_sol, const item_array_t &s_sol, index_t block_size) = 0; + + virtual void pre_large_step (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) = 0; + virtual void pre_small_step () = 0; + virtual void pre_newton_step () = 0; + + virtual void restart_small_step () = 0; + virtual void restart_newton_step () = 0; + }; + +} // namespace blue_sky + + +#endif // #ifndef BS_FACILITY_BASE_H_ + diff --git a/bs_bos_core/include/facility_manager.h b/bs_bos_core/include/facility_manager.h new file mode 100644 index 0000000..d65248f --- /dev/null +++ b/bs_bos_core/include/facility_manager.h @@ -0,0 +1,75 @@ +/** + * \file facility_manager.h + * \brief facilities manager + * \author Sergey Miryanov + * \date 16.07.2008 + * */ +#ifndef BS_FACILITY_MANAGER_H_ +#define BS_FACILITY_MANAGER_H_ + +#include "facility_base.h" +#include "well_iterator.h" + +namespace blue_sky + { + + template + class well; + + class data_storage_interface; + + template + class BS_API_PLUGIN facility_manager : public objbase + { + public: + + typedef facility_base facility_base_t; + typedef well well_t; + + typedef smart_ptr sp_facility_t; + typedef bos_val_table facility_map_t; + typedef smart_ptr sp_facility_map_t; + typedef smart_ptr sp_well_t; + + typedef smart_ptr sp_storage_t; + + typedef typename facility_map_t::iterator facility_iterator_t; + typedef typename facility_map_t::const_iterator facility_const_iterator_t; + + //typedef well_iterator well_iterator_t; + typedef facility_iterator_t well_iterator_t; + typedef facility_const_iterator_t well_const_iterator_t; + + public: + + sp_well_t get_well (const std::string &group_name, const std::string &well_name) const; + sp_well_t get_well (const std::string &well_name) const; + + void add_well (const sp_well_t &well); + + void save_data (const sp_storage_t &storage) const; + + well_const_iterator_t wells_begin () const; + well_const_iterator_t wells_end () const; + //well_iterator_t wells_begin (); + //well_iterator_t wells_end (); + + //unsigned int wells_size () const; + + BLUE_SKY_TYPE_DECL_T (facility_manager); + + private: + + sp_facility_map_t facility_list_; + + }; + + bool + facility_manager_register_type (const blue_sky::plugin_descriptor &pd); + + +} // namespace blue_sky + + +#endif // #ifndef BS_FACILITY_MANAGER_H_ + diff --git a/bs_bos_core/include/fi_operator.h b/bs_bos_core/include/fi_operator.h new file mode 100644 index 0000000..ac83bf1 --- /dev/null +++ b/bs_bos_core/include/fi_operator.h @@ -0,0 +1,1332 @@ +/** + * \file fi_operator.h + * \brief fi_operator + * \author Sergey Miryanov + * \date 12.01.2009 + * */ +#ifndef BS_FI_OPERATOR_H_ +#define BS_FI_OPERATOR_H_ + +#include BS_FORCE_PLUGIN_IMPORT () +#include "switch_main_vars.h" +#include "pvt_water.h" +#include "pvt_dead_oil.h" +#include "pvt_gas.h" +#include "scal_region_info.h" +#include "scal_region.h" +#include "scal_2p_data_holder.h" +#include "scal_3p.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "calc_model.h" +#include "norm_calc.h" + +namespace blue_sky { + + template + struct fi_operator_impl + { + typedef strategy_type strategy_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::csr_matrix_t bcsr_matrix_t; + + typedef calc_model calc_model_t; + typedef typename calc_model_t::data_t data_t; + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::main_var_array_t main_var_array_t; + typedef norms_storage norms_storage_t; + typedef reservoir reservoir_t; + typedef rs_mesh_iface mesh_iface_t; + typedef jacobian jacobian_t; + typedef jacobian_matrix jmatrix_t; + + typedef typename calc_model_t::sp_this_t sp_calc_model_t; + typedef typename calc_model_t::sp_reservoir_t sp_reservoir_t; + typedef typename calc_model_t::sp_jacobian_t sp_jacobian_t; + typedef typename calc_model_t::sp_jacobian_matrix_t sp_jmatrix_t; + typedef typename calc_model_t::sp_mesh_iface_t sp_mesh_iface_t; + typedef typename calc_model_t::sp_rock_grid sp_rock_grid_prop_t; + typedef smart_ptr sp_bcsr_matrix_t; + + typedef typename calc_model_t::sp_pvt_dead_oil_array_t sp_pvt_dead_oil_array_t; + typedef typename calc_model_t::sp_pvt_gas_array_t sp_pvt_gas_array_t; + typedef typename calc_model_t::sp_pvt_water_array_t sp_pvt_water_array_t; + + enum { + n_phases = is_w + is_g + is_o, + b_sqr = n_phases * n_phases, + is_1p = n_phases == 1, + }; + + public: + fi_operator_impl (sp_calc_model_t &calc_model, sp_reservoir_t &reservoir, const sp_mesh_iface_t &mesh, sp_jacobian_t &jacobian, sp_jmatrix_t &jmatrix) + : calc_model_ (calc_model), + rock_grid_prop_ (calc_model_->rock_grid_prop), + reservoir_ (reservoir), + jacobian_ (jacobian), + jmatrix_ (jmatrix), + mesh_ (mesh), + trns_matrix_ (jmatrix_->trns_matrix), + trns_values_ (trns_matrix_->get_values ()), + trns_rows_ptr_ (trns_matrix_->get_rows_ptr ()), + trns_cols_ptr_ (trns_matrix_->get_cols_ind ()), + reg_matrix_ (jmatrix_->get_regular_matrix ()), + reg_values_ (reg_matrix_->get_values ()), + reg_rows_ptr_ (reg_matrix_->get_rows_ptr ()), + reg_cols_ptr_ (reg_matrix_->get_cols_ind ()), + m_array_ (jmatrix_->m_array), + p_array_ (jmatrix_->p_array), + rhs_ (jmatrix_->get_rhs ()), + sol_ (jmatrix_->get_solution ()), + flux_rhs_ (jmatrix_->get_rhs_flux ()), + sp_diag_ (jmatrix_->get_sp_diagonal ()), + s_rhs_ (jmatrix_->get_sec_rhs ()), + depths_ (mesh_->get_depths ()), + n_cells_ (mesh->get_n_active_elements()), + n_connections_ (mesh_->get_n_connections ()), + n_sec_vars (calc_model_->n_sec_vars), + d_w (calc_model_->phase_d[FI_PHASE_WATER]), + d_g (calc_model_->phase_d[FI_PHASE_GAS]), + d_o (calc_model_->phase_d[FI_PHASE_OIL]), + ds_w (calc_model_->sat_d[FI_PHASE_WATER]), + ds_g (calc_model_->sat_d[FI_PHASE_GAS]), + d_gg (d_g * n_phases + d_g), + d_gw (d_g * n_phases + d_w), + d_go (d_g * n_phases + d_o), + d_wg (d_w * n_phases + d_g), + d_ww (d_w * n_phases + d_w), + d_wo (d_w * n_phases + d_o), + d_og (d_o * n_phases + d_g), + d_ow (d_o * n_phases + d_w), + d_oo (d_o * n_phases + d_o), + data_ (calc_model_->data), + saturation_3p_ (calc_model_->saturation_3p), + pressure_ (calc_model_->pressure), + gas_oil_ratio_ (calc_model_->gas_oil_ratio), + main_vars_ (calc_model_->main_variable), + volume_ (rock_grid_prop_->volume), + poro_array_ (rock_grid_prop_->porosity_p_ref), + rock_grid_comp_const_ (rock_grid_prop_->comp_const), + rock_grid_comp_ref_pressure_ (rock_grid_prop_->comp_ref_pressure), + sat_regions_ (calc_model_->sat_regions), + pvt_regions_ (calc_model_->pvt_regions), + pvt_oil_array (calc_model_->pvt_oil_array), + pvt_water_array (calc_model_->pvt_water_array), + pvt_gas_array (calc_model_->pvt_gas_array), + min_p_ ((item_t) calc_model_->ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MIN)), + max_p_ ((item_t) calc_model_->ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MAX)), + drsdt_ ((item_t) calc_model_->ts_params->get_float (fi_params::DRSDT)), + rhs_residual_ ((item_t) calc_model_->ts_params->get_float (fi_params::NEWTON_RESIDUAL)), + mb_error_ ((item_t) calc_model_->ts_params->get_float (fi_params::MASS_BALANS_ERROR)), + s_rhs_norm_ ((item_t) calc_model_->ts_params->get_float (fi_params::S_RHS_NORM)), + norm_ (calc_model_->norm), + cfl_ (jmatrix_->get_cfl_vector ()) + { + } + + fi_operator_return_type + fi_operator (double &dt, index_t istart, index_t istart_well_contr, index_t &, bool update_rhs_after_gauss_elimination, bool save_debug_files) + { + save_debug_files; + item_t mult = 1.0; + bool tuning = calc_model_->ts_params->get_bool (fi_params::NEWTON_TUNING); + + static norms_storage_t base_norm; + + if (istart) + { + reservoir_->init_jacobian (jmatrix_, n_cells_); + } + + index_t n_approx = 5; + for (index_t i = 0; i < n_approx; ++i) + { + mult = 1.0; + + // prepare well jacobian part + jmatrix_->init (n_cells_, n_phases, 3, 0, n_sec_vars); + + if (is_o && is_g) + { + fi_operator_switch_main_vars (dt); + } + + if (n_phases > 1) + { + // calculate saturation properties + calc_model_->scal_prop->process (saturation_3p_, + sat_regions_, + rock_grid_prop_->permeability, + poro_array_, + data_); + } + + // calculate properties for cells + // fill accumulative part of Jacobian (dM/dt) + fi_operator_cells ((istart == 1) ? 1 : 0, dt); + fi_operator_fill (); + + //if (!rsv_status->fip_data_is_calculated) + //{ + // rsv_status->fi_calculate_fip_data (this, /*precsn*/ 1e-8); + // rsv_status->fip_data_is_calculated = 1; + // copy_fip_data_to_storage (0.0); + //} + + // calculate Flux part of jacobian (T * M* (Pi - Pj - H)) + // calculate boundary Fluxes + + //!TODO: + if (block_connections_mpfa (dt))// || fi_operator_boundary_block_connections (*dt)) + throw bs_exception("fi_operator_block_connections_mpfa", "return -1"); + + if (update_rhs_after_gauss_elimination) + { + // calculate well controls and rates + reservoir_->calc_wells (((istart_well_contr == 1) ? 1 : 0), dt, calc_model_, mesh_, jmatrix_); + + // fill rhs from wells + reservoir_->fill_rhs_wells (dt, calc_model_, flux_rhs_, update_rhs_after_gauss_elimination); + } + + norm_calc (); + + if (update_rhs_after_gauss_elimination) + { + // fill jacobian (irregular matrix) by wells + reservoir_->end_jacobian (dt, calc_model_, jacobian_); + } + +#ifdef _DEBUG + //if (save_debug_files) + { + debug_save_data (dt); + } +#endif + + if (check_norm (istart)) + return FI_OPERATOR_RETURN_FAIL; + + if (check_solution_mult_cell (istart, i, n_approx, base_norm)) + continue; + + do_dt_reduce (dt, istart); + do_dt_tuning (dt, tuning); + + break; + } + + base_norm = norm_; + + jmatrix_->clear_solution (); // clear solution vector + jmatrix_->summ_rhs (); // summarize rhs + + return FI_OPERATOR_RETURN_OK; + } + + void + fi_operator_init (index_t istart, double dt) + { + if (is_o && is_g) + { + fi_operator_switch_main_vars (dt); + } + + if (n_phases > 1) + { + // calculate saturation properties + calc_model_->scal_prop->process (saturation_3p_, + sat_regions_, + rock_grid_prop_->permeability, + poro_array_, + data_); + } + + fi_operator_cells (istart, dt); + } + + //! calculate phisical parameters for all cells + void + fi_operator_cells (index_t istart, const item_t dt) + { + // local declaration + index_t i; + rhs_item_t *jac_block = 0; + rhs_item_t *rhs_block = 0; + index_t b_sqr = n_phases * n_phases; + + rhs_item_array_t &main_diag_acc = jmatrix_->get_regular_acc_diag();//get_main_diagonal_accumulative (); + rhs_item_array_t &ss_diag = jmatrix_->get_ss_diagonal (); + rhs_item_array_t &sp_diag = jmatrix_->get_sp_diagonal (); + rhs_item_array_t &s_rhs = jmatrix_->get_sec_rhs (); + rhs_item_array_t &rhs = jmatrix_->get_rhs (); + + BS_ERROR (!main_diag_acc.empty (), "fi_operator_cells"); + BS_ERROR (!ss_diag.empty (), "fi_operator_cells"); + BS_ERROR (!sp_diag.empty (), "fi_operator_cells"); + BS_ERROR (!s_rhs.empty (), "fi_operator_cells"); + BS_ERROR (!rhs.empty (), "fi_operator_cells"); + + index_t switch_to_sg_count = 0; + index_t switch_to_ro_count = 0; + index_t switch_to_momg_count = 0; + item_t total_volume = 0.0; + rhs_item_t *ss_block = 0; + rhs_item_t *sp_block = 0; + rhs_item_t *s_rhs_block = 0; + +#ifdef _MPI + int n_left = 0;///mpi_decomp->get_recv_l (); + int n_own = 0;///mpi_decomp->get_n_local_own () + n_left; + ///rhs -= n_left * n_phases; + double mpi_invers_fvf_average[3]; + int n_procs; +#endif //_MPI + +#ifdef FI_OPERATOR_CELLS_PARALLEL + double invers_fvf_average_w = 0.; + double invers_fvf_average_g = 0.; + double invers_fvf_average_o = 0.; +#endif //FI_OPERATOR_CELLS_PARALLEL + + + // set flag to 0 at newton iteration + calc_model_->lsearch_force_newton_step = 0; + + // set equal to 0 + assign (calc_model_->invers_fvf_average, 0); + + // set flag to 0 at newton iteration +#ifdef FI_OPERATOR_CELLS_PARALLEL +#pragma omp parallel for private (jac_block, rhs_block) \ + reduction (+:invers_fvf_average_w, invers_fvf_average_g, invers_fvf_average_o,total_volume) +#endif //FI_OPERATOR_CELLS_PARALLEL + // loop through all cells + for (i = 0; i < n_cells_; ++i) + { + jac_block = &main_diag_acc[b_sqr * i]; + ss_block = &ss_diag[n_sec_vars * n_sec_vars * i]; + s_rhs_block = &s_rhs[n_sec_vars * i]; + rhs_block = &rhs[i * n_phases]; +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + if ((i < n_left) || (i >= n_own)) + { + ///jac_block = just_double; + ///rhs_block = just_double; + } + else + { + jac_block -= n_left * b_sqr; + } +#endif //_MPI + + // calculate properties for cell i +#ifdef FI_OPERATOR_CELLS_PARALLEL + fi_operator_cell (istart, dt, i, jac_block, rhs_block, + ss_block, s_rhs_block, + switch_to_sg_count, switch_to_ro_count, switch_to_momg_count, + invers_fvf_average_w, invers_fvf_average_g, invers_fvf_average_o, total_volume); +#else //FI_OPERATOR_CELLS_PARALLEL + fi_operator_cell (istart, dt, i, jac_block, rhs_block, + ss_block, s_rhs_block, + switch_to_sg_count, switch_to_ro_count, switch_to_momg_count, + total_volume); +#endif //FI_OPERATOR_CELLS_PARALLEL + } + +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + double mpi_total_volume; + MPI_Allreduce (&total_volume, &mpi_total_volume, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + total_volume = mpi_total_volume; + + MPI_Allreduce (&invers_fvf_average, &mpi_invers_fvf_average, FI_PHASE_TOT, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + if (is_w) + invers_fvf_average[d_w] = mpi_invers_fvf_average[d_w]; + if (is_g) + invers_fvf_average[d_g] = mpi_invers_fvf_average[d_g]; + if (is_o) + invers_fvf_average[d_o] = mpi_invers_fvf_average[d_o]; + + ///n_elements = mpi_decomp->get_n_elements (); +#endif //_MPI + +#ifdef FI_OPERATOR_CELLS_PARALLEL + if (is_w) + invers_fvf_average[d_w] = invers_fvf_average_w / (double) n_elements; + if (is_g) + invers_fvf_average[d_g] = invers_fvf_average_g / (double) n_elements; + if (is_o) + invers_fvf_average[d_o] = invers_fvf_average_o / (double) n_elements; +#else //FI_OPERATOR_CELLS_PARALLEL + + if (is_w) + calc_model_->invers_fvf_average[d_w] /= (item_t) n_cells_; + if (is_g) + calc_model_->invers_fvf_average[d_g] /= (item_t) n_cells_; + if (is_o) + calc_model_->invers_fvf_average[d_o] /= (item_t) n_cells_; +#endif //FI_OPERATOR_CELLS_PARALLEL + + calc_model_->ave_volume = total_volume / (item_t) n_cells_; + } + +#define POROSITY data_i.porosity +#define P_DERIV_POROSITY data_i.p_deriv_porosity +#define INVERS_FVF_O data_i.invers_fvf[d_o] +#define INVERS_FVF_G data_i.invers_fvf[d_g] +#define INVERS_FVF_W data_i.invers_fvf[d_w] +#define P_DERIV_INVERS_FVF_O data_i.p_deriv_invers_fvf[d_o] +#define P_DERIV_INVERS_FVF_G data_i.p_deriv_invers_fvf[d_g] +#define P_DERIV_INVERS_FVF_W data_i.p_deriv_invers_fvf[d_w] +#define GAS_OIL_RATIO gas_oil_ratio_[i] +#define P_DERIV_GAS_OIL_RATIO data_i.p_deriv_gas_oil_ratio +#define VOLUME volume_[i] +#define S_DERIV_CAP_PRESSURE_G data_i.s_deriv_cap_pressure[ds_g] +#define S_DERIV_CAP_PRESSURE_W data_i.s_deriv_cap_pressure[ds_w] +#define GOR_DERIV_INVERS_FVF data_i.gor_deriv_invers_fvf +#define PREV_FLUID_VOLUME_O data_i.prev_fluid_volume[d_o] +#define PREV_FLUID_VOLUME_G data_i.prev_fluid_volume[d_g] +#define PREV_FLUID_VOLUME_W data_i.prev_fluid_volume[d_w] + + struct local_data + { + item_t sat_w; + item_t sat_g; + item_t sat_o; + boost::array ps_block; + }; + + BS_FORCE_INLINE void + fill_jacobian (index_t i, const data_t &data_i, rhs_item_t *jac_block, local_data &local_data_) + { + // water equation + if (is_w) + { + item_t p_der = VOLUME * (P_DERIV_POROSITY * INVERS_FVF_W + POROSITY * P_DERIV_INVERS_FVF_W); + item_t sw_der = VOLUME * POROSITY * (INVERS_FVF_W + local_data_.sat_w * P_DERIV_INVERS_FVF_W * S_DERIV_CAP_PRESSURE_W); + + if (n_phases == 3) + { + jac_block[p3_wat_po] = p_der * local_data_.sat_w; + jac_block[p3_wat_sg] = 0; + jac_block[p3_wat_so] = 0; + local_data_.ps_block[p3_wat] = sw_der; + } + else if (n_phases == 2) + { + jac_block[p2ow_wat_po] = p_der * local_data_.sat_w; + jac_block[p2ow_wat_so] = 0; + local_data_.ps_block[p2ow_wat] = sw_der; + } + else + { + jac_block[0] = p_der; + } + } + // gas equation + if (is_g) + { + if (n_phases > 1) + { + item_t drg_p = 0, drg_sg = 0, drg_so = 0; + if (FI_CHK_SG (main_vars_, i)) + { + //drg_p = VOLUME * (sat_g * (P_DERIV_POROSITY * INVERS_FVF_G + POROSITY * P_DERIV_INVERS_FVF_G) + + // sat_o * (GAS_OIL_RATIO * (P_DERIV_POROSITY * INVERS_FVF_O + POROSITY * P_DERIV_INVERS_FVF_O) + // + POROSITY * INVERS_FVF_O * P_DERIV_GAS_OIL_RATIO)); + drg_p = VOLUME * (local_data_.sat_g * (P_DERIV_POROSITY * INVERS_FVF_G + POROSITY * P_DERIV_INVERS_FVF_G) + + local_data_.sat_o * (P_DERIV_POROSITY * INVERS_FVF_O * GAS_OIL_RATIO + POROSITY * (P_DERIV_GAS_OIL_RATIO * INVERS_FVF_O + GAS_OIL_RATIO * P_DERIV_INVERS_FVF_O))); + drg_sg = VOLUME * POROSITY * (INVERS_FVF_G + local_data_.sat_g * P_DERIV_INVERS_FVF_G * S_DERIV_CAP_PRESSURE_G - GAS_OIL_RATIO * INVERS_FVF_O); + } + else if (FI_CHK_RO (main_vars_, i)) + { + drg_p = VOLUME * local_data_.sat_o * GAS_OIL_RATIO * (P_DERIV_POROSITY * INVERS_FVF_O + P_DERIV_INVERS_FVF_O * POROSITY); + drg_sg = VOLUME * POROSITY * local_data_.sat_o * (INVERS_FVF_O + GAS_OIL_RATIO * GOR_DERIV_INVERS_FVF); + } + drg_so = VOLUME * POROSITY * GAS_OIL_RATIO * INVERS_FVF_O; + if (FI_CHK_MOMG (main_vars_, i)) + { + drg_p = 0; + drg_sg = VOLUME; + drg_so = 0; + } + if (n_phases == 3) + { + jac_block[p3_gas_po] = drg_p; + jac_block[p3_gas_sg] = drg_sg; + jac_block[p3_gas_so] = drg_so; + local_data_.ps_block[p3_gas] = 0; + } + else + { + jac_block[p2og_gas_po] = drg_p; + jac_block[p2og_gas_sg] = drg_sg; + local_data_.ps_block[p2og_gas] = drg_so; + } + } + else + { + jac_block[0] = VOLUME * (P_DERIV_POROSITY * INVERS_FVF_G + P_DERIV_INVERS_FVF_G * POROSITY); + } + + } + // oil equation + if (is_o) + { + if (n_phases == 3) + { + jac_block[p3_oil_po] = VOLUME * local_data_.sat_o * (P_DERIV_POROSITY * INVERS_FVF_O + P_DERIV_INVERS_FVF_O * POROSITY); + jac_block[p3_oil_so] = /*-*/VOLUME * POROSITY * INVERS_FVF_O; + + if (FI_CHK_SG (main_vars_, i)) + { + //jac_block[p3_oil_sg] = 0.0; + jac_block[p3_oil_sg] = -VOLUME * POROSITY * INVERS_FVF_O; + } + else if (FI_CHK_RO (main_vars_, i)) + { + jac_block[p3_oil_sg] = VOLUME * POROSITY * local_data_.sat_o * GOR_DERIV_INVERS_FVF; + } + local_data_.ps_block[p3_oil] = 0.0; + + if (FI_CHK_MOMG (main_vars_, i)) + { + jac_block[p3_oil_po] = 0; + jac_block[p3_oil_so] = VOLUME; + jac_block[p3_oil_sg] = 0.0; + } + } + else if (n_phases == 2 && is_g) + { + jac_block[p2og_oil_po] = VOLUME * local_data_.sat_o * (P_DERIV_POROSITY * INVERS_FVF_O + P_DERIV_INVERS_FVF_O * POROSITY); + + if (FI_CHK_SG (main_vars_, i)) + jac_block[p2og_oil_sg] = 0.0; + else if (FI_CHK_RO (main_vars_, i)) + { + jac_block[p2og_oil_sg] = VOLUME * POROSITY * local_data_.sat_o * GOR_DERIV_INVERS_FVF; + } + local_data_.ps_block[p2og_oil] = /*-*/VOLUME * POROSITY * INVERS_FVF_O; + if (FI_CHK_MOMG (main_vars_, i)) + { + jac_block[p2og_oil_po] = 0; + local_data_.ps_block[p2og_oil] = VOLUME; + jac_block[p2og_oil_sg] = 0.0; + } + } + else if (n_phases == 2 && is_w) + { + jac_block[p2ow_oil_po] = VOLUME * local_data_.sat_o * (P_DERIV_POROSITY * INVERS_FVF_O + P_DERIV_INVERS_FVF_O * POROSITY); + jac_block[p2ow_oil_so] = /*-*/VOLUME * POROSITY * INVERS_FVF_O; + local_data_.ps_block[p2ow_oil] = 0.0; + } + else + { + jac_block[0] = VOLUME * (P_DERIV_POROSITY * INVERS_FVF_O + P_DERIV_INVERS_FVF_O * POROSITY); + } + } + } + + /** + * \brief switch main vars for gas phase (Undersaturated conditon or free gas exist) + * */ + void + fi_operator_switch_main_vars (double dt) + { + typedef typename calc_model_t::sp_pvt_oil sp_pvt_oil_t; + + sp_pvt_oil_t pvt_oil; + index_t prev_pvt_reg = -1; + + index_t switch_to_sg_count = 0; + index_t switch_to_ro_count = 0; + index_t switch_to_momg_count = 0; + + for (index_t i = 0, cnt = n_cells_; i < cnt; ++i) + { + index_t pvt_reg = pvt_regions_[i]; + if (pvt_reg != prev_pvt_reg) + { + prev_pvt_reg = pvt_reg; + pvt_oil = pvt_oil_array [pvt_reg]; + } + + switch_main_vars ::do_switch ( + is_w, is_g, is_o, + d_o, d_g, d_w, + pvt_oil_array [pvt_reg], + pressure_[i], + main_vars_[i], + &saturation_3p_[i * n_phases], + gas_oil_ratio_[i], + calc_model_->lsearch_force_newton_step, + drsdt_, + dt, + calc_model_->old_data_.gas_oil_ratio[i], + switch_to_sg_count, + switch_to_ro_count, + switch_to_momg_count, + i); + } + + BOSOUT (section::iters, level::medium) + << "Switch to Sg: " << switch_to_sg_count + << "\tSwitch to Ro: " << switch_to_ro_count + << "\tSwitch to MoMg: " << switch_to_momg_count + << bs_end; + } + + BS_FORCE_INLINE void + fill_acc_rhs (index_t i, const data_t &data_i, rhs_item_t *rhs_block, local_data &local_data_) + { + // water + if (is_w) + { + item_t r_wat = 0; + item_t sat_w__ = n_phases > 1 ? local_data_.sat_w : 1.0; + + r_wat = -VOLUME * (POROSITY * INVERS_FVF_W * sat_w__ - PREV_FLUID_VOLUME_W); + //if (istart) + // r_wat = 0.0; + + if (n_phases == 3) + rhs_block[p3_wat] = r_wat; + else if (n_phases == 2) + rhs_block[p2ow_wat] = r_wat; + else + rhs_block[0] = r_wat; + } + // gas + if (is_g) + { + item_t r_gas = 0; + + if (n_phases > 1) + { + if (FI_CHK_SG (main_vars_, i)) + { + r_gas = -VOLUME * (POROSITY * INVERS_FVF_G * local_data_.sat_g + GAS_OIL_RATIO * POROSITY * local_data_.sat_o * INVERS_FVF_O - PREV_FLUID_VOLUME_G); + } + else if (FI_CHK_RO (main_vars_, i)) + { + r_gas = -VOLUME * (GAS_OIL_RATIO * POROSITY * local_data_.sat_o * INVERS_FVF_O - PREV_FLUID_VOLUME_G); + } + else if (FI_CHK_MOMG (main_vars_, i)) + { + r_gas = VOLUME * PREV_FLUID_VOLUME_G; + } + } + else + { + r_gas = -VOLUME * (POROSITY * INVERS_FVF_G - PREV_FLUID_VOLUME_G); + } + //if (istart) + // r_gas = 0.0; + + if (n_phases == 3) + rhs_block[p3_gas] = r_gas; + else if (n_phases == 2) + rhs_block[p2og_gas] = r_gas; + else + rhs_block[0] = r_gas; + } + // oil + if (is_o) + { + item_t r_oil = 0; + item_t sat_o__ = n_phases > 1 ? local_data_.sat_o : 1.0; + + r_oil = -VOLUME * (POROSITY * INVERS_FVF_O * sat_o__ - PREV_FLUID_VOLUME_O); + //if (istart) + // r_oil = 0.0; + + if (n_phases == 3) + rhs_block[p3_oil] = r_oil; + else if (n_phases == 2 && is_w) + rhs_block[p2ow_oil] = r_oil; + else if (n_phases == 2 && is_g) + rhs_block[p2og_oil] = r_oil; + else + rhs_block[0] = r_oil; + } + } + + BS_FORCE_INLINE void + eliminate_cell (const local_data &local_data_, rhs_item_t *jac_block, rhs_item_t *rhs_block, rhs_item_t *sp_block, rhs_item_t *s_rhs_block) + { + // Schur complemet 1) App-ApsDssDsp and 2) Bp-ApsDssBs (Dss=Ass^(-1); Dsp=Asp) + // 1) + M_MINUS_VV_PROD (n_phases, local_data_.ps_block, sp_block, jac_block); + // 2) + V_MINUS_VS_PROD (n_phases, local_data_.ps_block, s_rhs_block, rhs_block); + } + + void + fi_operator_fill () + { + index_t b_sqr = n_phases * n_phases; + rhs_item_array_t &main_diag_acc = jmatrix_->get_regular_acc_diag();//get_main_diagonal_accumulative (); + rhs_item_array_t &ss_diag = jmatrix_->get_ss_diagonal (); + rhs_item_array_t &sp_diag = jmatrix_->get_sp_diagonal (); + rhs_item_array_t &s_rhs = jmatrix_->get_sec_rhs (); + rhs_item_array_t &rhs = jmatrix_->get_rhs (); + + BS_ASSERT (!main_diag_acc.empty ()); + BS_ASSERT (!ss_diag.empty ()); + BS_ASSERT (!sp_diag.empty ()); + BS_ASSERT (!s_rhs.empty ()); + BS_ASSERT (!rhs.empty ()); + + // loop through all cells + for (index_t i = 0; i < n_cells_; ++i) + { + rhs_item_t *jac_block = &main_diag_acc[b_sqr * i]; + rhs_item_t *ss_block = &ss_diag[n_sec_vars * n_sec_vars * i]; + rhs_item_t *sp_block = &sp_diag[n_sec_vars * n_phases * i]; + rhs_item_t *s_rhs_block = &s_rhs[n_sec_vars * i]; + rhs_item_t *rhs_block = &rhs[i * n_phases]; + + index_t i_w = FI_PH_IND (i, d_w, n_phases); + index_t i_g = FI_PH_IND (i, d_g, n_phases); + index_t i_o = FI_PH_IND (i, d_o, n_phases); + + local_data local_data_; + const data_t &data_i = data_[i]; + + // fill ss and sp part of blocks + if (n_phases > 1) + ss_block[0] = 1; + if (n_phases == 3) + { + s_rhs_block[0] = 1.0 - saturation_3p_[i_w] - saturation_3p_[i_g] - saturation_3p_[i_o]; + if (FI_CHK_SG (main_vars_, i)) + { + sp_block[p3_sg] = 1.0; + sp_block[p3_so] = 1.0; + sp_block[p3_po] = 0; + } + else if (FI_CHK_RO (main_vars_, i)) + { + sp_block[p3_sg] = 0; + sp_block[p3_so] = 1.0; + sp_block[p3_po] = 0; + } + else if (FI_CHK_MOMG (main_vars_, i)) + { + sp_block[p3_sg] = 0; + sp_block[p3_so] = 0; + sp_block[p3_po] = 0; + } + } + else if (n_phases == 2 && is_w && is_o) + { + s_rhs_block[0] = 1.0 - saturation_3p_[i_w] - saturation_3p_[i_o]; + sp_block[p2ow_so] = 1; + sp_block[p2ow_po] = 0; + } + else if (n_phases == 2 && is_g && is_o) + { + s_rhs_block[0] = 1.0 - saturation_3p_[i_g] - saturation_3p_[i_o]; + if (FI_CHK_SG (main_vars_, i)) + { + sp_block[p2og_sg] = 1; + sp_block[p2og_po] = 0; + } + else if (FI_CHK_RO (main_vars_, i)) + { + sp_block[p2og_sg] = 0; + sp_block[p2og_po] = 0; + } + } + + assign (local_data_.ps_block, 0); + local_data_.sat_w = local_data_.sat_g = local_data_.sat_o = 0.0; + // set up saturation + if (is_w && n_phases > 1) + local_data_.sat_w = saturation_3p_[i_w]; + if (is_g && n_phases > 1) + local_data_.sat_g = saturation_3p_[i_g]; + if (is_o && n_phases > 1) + local_data_.sat_o = saturation_3p_[i_o]; + + fill_jacobian (i, data_i, jac_block, local_data_); + fill_acc_rhs (i, data_i, rhs_block, local_data_); + eliminate_cell (local_data_, jac_block, rhs_block, sp_block, s_rhs_block); + +//#ifdef _DEBUG +// for (index_t j = 0; j < b_sqr; ++j) +// { +// if (jac_block[j] == 0) +// { +// index_t i_coord = 0, j_coord = 0, k_coord = 0; +// //mesh_->get_element_int_to_ijk (i, i_coord, j_coord, k_coord); +// +// size_t iiiiiiiiii = 0; +// } +// } +//#endif + + } + } + +#ifdef FI_OPERATOR_CELLS_PARALLEL + inline void + fi_operator_cell (index_t istart, const item_t dt, + index_t cell_ind, item_t *jac_block, + item_t *rhs_block, + item_t *ss_block, + item_t *s_rhs_block, + int &switch_to_sg_count, + int &switch_to_ro_count, + int &switch_to_momg_count, + item_t &invers_fvf_average_w, + item_t &invers_fvf_average_g, + item_t &invers_fvf_average_o, + item_t &total_volume, + const sp_mesh_iface_t &mesh) +#else //FI_OPERATOR_CELLS_PARALLEL + inline void + fi_operator_cell (index_t /*istart*/, const item_t dt, + index_t cell_ind, rhs_item_t * /*jac_block*/, + rhs_item_t * /*rhs_block*/, + rhs_item_t * /*ss_block*/, + rhs_item_t * /*s_rhs_block*/, + int &/*switch_to_sg_count*/, + int &/*switch_to_ro_count*/, + int &/*switch_to_momg_count*/, + item_t &total_volume) +#endif //FI_OPERATOR_CELLS_PARALLEL + + { + local_data local_data_; + item_t p_water; + item_t p_gas; + item_t p_oil; + index_t i_temp; + +#ifdef _MPI + int n_left = 0;///mpi_decomp->get_recv_l (); + int n_own = 0;///mpi_decomp->get_n_local_own () + n_left; +#endif //_MPI + + // base constants + index_t i = cell_ind; + + item_t gor = 0.0; + item_t d_gor = 0.0; + // get saturation region number + index_t pvt_reg = pvt_regions_[i]; + + assign (local_data_.ps_block, 0); + // check pressure for consistency + if (pressure_[i] < min_p_ || pressure_[i] > max_p_) + { + BOSERR (section::iters, level::error) << boost::format ("Pressure %f in cell [%d] is out of range") % + pressure_[i] % i << bs_end; + } + + data_t &data_i = data_[i]; + + // calculate pressures for all phases + p_oil = p_water = p_gas = pressure_[i]; + if (n_phases > 1) + { + if (is_w) + p_water += data_i.cap_pressure[ds_w]; + if (is_g) + p_gas += data_i.cap_pressure[ds_g]; + } + + // calculate pvt properties + i_temp = n_phases * i; + if (is_w) + { + pvt_water_array[pvt_reg]->calc( + p_water, + &data_i.invers_fvf[d_w], + &data_i.p_deriv_invers_fvf[d_w], + &data_i.invers_viscosity[d_w], + &data_i.p_deriv_invers_viscosity[d_w], + &data_i.invers_visc_fvf[d_w], + &data_i.p_deriv_invers_visc_fvf[d_w]); + } + + if (is_g) + { + pvt_gas_array[pvt_reg]->calc( + p_gas, + &data_i.invers_fvf[d_g], + &data_i.p_deriv_invers_fvf[d_g], + &data_i.invers_viscosity[d_g], + &data_i.p_deriv_invers_viscosity[d_g], + &data_i.invers_visc_fvf[d_g], + &data_i.p_deriv_invers_visc_fvf[d_g]); + } + + if (is_o && is_g) // gas and oil + { + pvt_oil_array[pvt_reg]->calc( + is_g, main_vars_[i],p_oil, gas_oil_ratio_[i], + &data_i.invers_fvf[d_o], + &data_i.p_deriv_invers_fvf[d_o], + &data_i.gor_deriv_invers_fvf, + &data_i.invers_viscosity[d_o], + &data_i.p_deriv_invers_viscosity[d_o], + &data_i.gor_deriv_invers_viscosity, + &data_i.invers_visc_fvf[d_o], + &data_i.p_deriv_invers_visc_fvf[d_o], + &data_i.gor_deriv_invers_visc_fvf, + &gor, &d_gor, drsdt_, dt, calc_model_->old_data_.gas_oil_ratio[i] + ); + } + else if (is_o) // oil only + { + pvt_oil_array[pvt_reg]->calc( + is_g, -1, p_oil, 0, + &data_i.invers_fvf[d_o], + &data_i.p_deriv_invers_fvf[d_o], + 0, + &data_i.invers_viscosity[d_o], + &data_i.p_deriv_invers_viscosity[d_o], + 0, + &data_i.invers_visc_fvf[d_o], + &data_i.p_deriv_invers_visc_fvf[d_o], + 0, + 0, 0 + ); + } + + // calculate porosity and derivate + calc_porosity_and_deriv (i, + pvt_reg, + &data_i.porosity, + &data_i.p_deriv_porosity, + &data_i.truns_mult, + &data_i.p_deriv_truns_mult); + + total_volume += data_i.porosity * volume_[i]; + + item_t oil_surface_density = pvt_oil_array[pvt_reg]->get_surface_density (); + item_t gas_surface_density = pvt_gas_array[pvt_reg]->get_surface_density (); + item_t water_surface_density = pvt_water_array[pvt_reg]->get_surface_density (); + + // calculate density + // oil + if (is_o) + { + if (is_g) + { + // Kamaltinova A. + if (FI_CHK_SG (main_vars_, i)) + { + gas_oil_ratio_[i] = gor; + data_i.p_deriv_gas_oil_ratio = d_gor; + data_i.density[d_o] = data_i.invers_fvf[d_o] * (oil_surface_density + gor * gas_surface_density); + //data_i.p_deriv_density[d_o] = data_i.p_deriv_invers_fvf[d_o] * oil_surface_density + gas_surface_density; + data_i.p_deriv_density[d_o] = data_i.p_deriv_invers_fvf[d_o] * oil_surface_density + gas_surface_density * (gas_oil_ratio_[i] * data_i.p_deriv_invers_fvf[d_o] + data_i.invers_fvf[d_o] * data_i.p_deriv_gas_oil_ratio); + data_i.gor_deriv_density = 0.0; + } + else if (FI_CHK_RO (main_vars_, i)) + { + data_i.density[d_o] = data_i.invers_fvf[d_o] * (oil_surface_density + gas_oil_ratio_[i] * gas_surface_density); + data_i.p_deriv_gas_oil_ratio = 0.0; + data_i.p_deriv_density[d_o] = data_i.p_deriv_invers_fvf[d_o] * (oil_surface_density + gas_oil_ratio_[i] * gas_surface_density); + data_i.gor_deriv_density = data_i.gor_deriv_invers_fvf * (oil_surface_density + gas_oil_ratio_[i] * gas_surface_density) + data_i.invers_fvf[d_o] * gas_surface_density; + } + else if (FI_CHK_MOMG (main_vars_, i)) + { + gas_oil_ratio_[i] = gor; + data_i.p_deriv_gas_oil_ratio = d_gor; + data_i.density[d_o] = data_i.invers_fvf[d_o] * oil_surface_density; + } + } + else + { + data_i.density[d_o] = data_i.invers_fvf[d_o] * oil_surface_density; + data_i.p_deriv_density[d_o] = data_i.p_deriv_invers_fvf[d_o] * oil_surface_density; + } + } + + // calculate water density + if (is_w) + { + data_i.density[d_w] = data_i.invers_fvf[d_w] * water_surface_density; + data_i.p_deriv_density[d_w] = data_i.p_deriv_invers_fvf[d_w] * water_surface_density; + } + // calculate gas density + if (is_g) + { + data_i.density[d_g] = data_i.invers_fvf[d_g] * gas_surface_density; + data_i.p_deriv_density[d_g] = data_i.p_deriv_invers_fvf[d_g] * gas_surface_density; + } + + //Kamaltinova A. + // calculate mobility + //water phase + if (is_w) + { + // mobility = 1/(B*mu) + data_i.mobility[d_w] = data_i.invers_visc_fvf[d_w]; + data_i.p_deriv_mobility[d_w] = data_i.p_deriv_invers_visc_fvf[d_w]; + if (n_phases > 1) + { + // mobility = mobility*k' + data_i.mobility[d_w] *= data_i.relative_perm[d_w]; + data_i.p_deriv_mobility[d_w] *= data_i.relative_perm[d_w]; + data_i.s_deriv_mobility[d_ww] = data_i.s_deriv_relative_perm[d_ww] * data_i.invers_visc_fvf[d_w] + + data_i.relative_perm[d_w] * data_i.p_deriv_invers_visc_fvf[d_w] * data_i.s_deriv_cap_pressure[ds_w]; + if (is_o) + data_i.s_deriv_mobility[d_wo] = 0.0; + if (is_g) + data_i.s_deriv_mobility[d_wg] = 0.0; + } + } + //gas phase + if (is_g) + { + data_i.mobility[d_g] = data_i.invers_visc_fvf[d_g]; + data_i.p_deriv_mobility[d_g] = data_i.p_deriv_invers_visc_fvf[d_g]; + if (n_phases > 1) + { + data_i.mobility[d_g] *= data_i.relative_perm[d_g]; + data_i.p_deriv_mobility[d_g] *= data_i.relative_perm[d_g]; + + if (FI_CHK_SG (main_vars_, i)) + { + data_i.s_deriv_mobility[d_gg] = data_i.s_deriv_relative_perm[d_gg] * data_i.invers_visc_fvf[d_g] + + data_i.relative_perm[d_g] * data_i.p_deriv_invers_visc_fvf[d_g] * data_i.s_deriv_cap_pressure[ds_g]; + } + else + { + data_i.s_deriv_mobility[d_gg] = 0; + data_i.mobility[d_g] = 0; + data_i.p_deriv_mobility[d_g] = 0; + } + + data_i.s_deriv_mobility[d_go] = 0; + + if (is_w) + data_i.s_deriv_mobility[d_gw] = 0; + + if (FI_CHK_MOMG (main_vars_, i)) + { + data_i.mobility[d_g] = 0; + data_i.p_deriv_mobility[d_g] = 0; + } + } + } + //oil phase + if (is_o) + { + data_i.mobility[d_o] = data_i.invers_visc_fvf[d_o]; + data_i.p_deriv_mobility[d_o] = data_i.p_deriv_invers_visc_fvf[d_o]; + if (n_phases > 1) + { + data_i.mobility[d_o] *= data_i.relative_perm[d_o]; + data_i.p_deriv_mobility[d_o] *= data_i.relative_perm[d_o]; + + data_i.s_deriv_mobility[d_oo] = data_i.s_deriv_relative_perm[d_oo] * data_i.invers_visc_fvf[d_o]; + + if (is_w) + data_i.s_deriv_mobility[d_ow] = data_i.s_deriv_relative_perm[d_ow] * data_i.invers_visc_fvf[d_o]; + + if (is_g) + { + if (FI_CHK_SG (main_vars_, i)) + data_i.s_deriv_mobility[d_og] = data_i.s_deriv_relative_perm[d_og] * data_i.invers_visc_fvf[d_o]; + else if (FI_CHK_RO (main_vars_, i)) + data_i.s_deriv_mobility[d_og] = data_i.relative_perm[d_o] * data_i.gor_deriv_invers_visc_fvf; + else if (FI_CHK_MOMG (main_vars_, i)) + { + data_i.mobility[d_o] = 0; + data_i.p_deriv_mobility[d_o] = 0; + data_i.s_deriv_mobility[d_oo] = 0; + data_i.s_deriv_mobility[d_og] = 0; + if (is_w) + data_i.s_deriv_mobility[d_ow] = 0; + } + } + } + } + +#ifdef FI_OPERATOR_CELLS_PARALLEL + if (is_w) + invers_fvf_average_w += invers_fvf[i_w]; + if (is_g) + invers_fvf_average_g += invers_fvf[i_g]; + if (is_o) + invers_fvf_average_o += invers_fvf[i_o]; +#else //FI_OPERATOR_CELLS_PARALLEL + +#ifdef _MPI + if (i >= n_left && i < n_own) + { +#endif //_MPI + if (is_w) + calc_model_->invers_fvf_average[d_w] += data_i.invers_fvf[d_w]; + if (is_g) + calc_model_->invers_fvf_average[d_g] += data_i.invers_fvf[d_g]; + if (is_o) + calc_model_->invers_fvf_average[d_o] += data_i.invers_fvf[d_o]; +#ifdef _MPI + } +#endif //_MPI + +#endif //FI_OPERATOR_CELLS_PARALLEL + + } + + bool + check_norm (index_t istart) + { + if (!istart) + { +#ifdef _DEBUG + BOSOUT (section::iters, level::debug) << "rhs_residual: " << fabs (norm_.val[norms::C_CPV]) << " / " << rhs_residual_ << bs_end; + BOSOUT (section::iters, level::debug) << "mb_error: " << fabs (norm_.val[norms::MB_ERR]) << " / " << mb_error_ << bs_end; + BOSOUT (section::iters, level::debug) << "s_rhs: " << fabs (norm_.val[norms::S_RHS]) << " / " << s_rhs_norm_ << bs_end; +#endif + + return fabs (norm_.val[norms::C_CPV]) < rhs_residual_ + && fabs (norm_.val[norms::MB_ERR]) < mb_error_ + //&& fabs (norm_.val[norms::S_RHS]) < s_rhs_norm_ + ; + } + + return false; + } + bool + check_solution_mult_cell (index_t istart, index_t iteration, index_t n_approx, const norms_storage_t &base_norm) + { + // if we return false here - we got smaller number of newtonian iterations + // if we compute solution_mult_cell - we got bigger number of newtonian iterations + return false; + + if (!istart && !iteration) + { + BOSOUT (section::iters, level::debug) << "check_solution_mult_cell" << bs_end; + + item_t mult = calc_solution_mult_cell (base_norm); + if (mult < 0.9 && iteration < n_approx - 1) + { + if (mult < item_t (0.1)) + mult = item_t (0.1); + + BOSOUT (section::iters, level::debug) << "check_solution_mult_cell 2, mult = " << mult << bs_end; + + restore_prev_niter_vars (); + if (calc_model_->apply_newton_correction (mult, 2, mesh_, jmatrix_)) + bs_throw_exception ("apply_newton_correction failed"); + + return true; + } +#ifdef _DEBUG + else + { + BOSOUT (section::iters, level::debug) << "check_solution_mult_cell 3, mult = " << mult << bs_end; + } +#endif + } + + return false; + } + + void + do_dt_reduce (double &dt, index_t istart) + { + if (/*false && */istart) + { + item_t dt_mult = calc_step_dt_mult (0, (item_t) calc_model_->ts_params->get_float (fi_params::MAX_NORM_ON_FIRST_N)); + if (dt_mult < 0.95) + { + jmatrix_->mult_flux_part (dt_mult); + dt *= dt_mult; + + BOSOUT (section::iters, level::medium) << "dT reduced by factor " << dt_mult << ": " << dt << bs_end; + } + dt_mult = 0; + } + } + void + do_dt_tuning (const double &dt, bool tuning) + { + if (tuning) + { + item_t dt_mult = calc_step_dt_mult (0, (item_t) calc_model_->ts_params->get_float (fi_params::MAX_NORM_ON_TS)); + if (dt_mult < 0.95) + { + jmatrix_->mult_flux_part (dt_mult); + + BOSOUT (section::iters, level::medium) << "Use dT " << dt_mult * (dt) << " instead of original dT " << dt << bs_end; + } + else + dt_mult = 1.0; + } + } + + void + save_prev_niter_vars () + { + int is_line_search = calc_model_->ts_params->get_int (fi_params::SELECT_SOL_STEPS); + if (is_line_search != 0) + { + calc_model_->prev_niter_data_.save (calc_model_); + reservoir_->pre_newton_step (); + } + } + + void + restore_prev_niter_vars () + { + reservoir_->restart_newton_step (); + } + + /** + * @brief calculate norms + * + * @param i_start -- if ne 0 + * + * @return + * */ + void + norm_calc (); + + // calculate norm in one cell and update norm storage + void + update_norm_by_cell (index_t i, norms_storage_t &ns); + + /** + * @brief calculate dt at the first newton iteration on time step + * + * @param dt -- time step length + * + * @return 0 -- if success + * */ + item_t + calc_step_dt_mult (item_t prev_mult, item_t max_res); + + /** + * @brief calculate porosity and derivativies, also calculate trunsmissibility multiplier + * + * @param i -- cell index + * @param pvt_reg -- PVT region index + * @param poro -- porosity + * @param dp_poro -- porosity derivative + * @param t_mult -- trunsmissibility multiplier + * @param dp_t_mult -- trunsmissibility multiplier derivative + * */ + void + calc_porosity_and_deriv (index_t i, + index_t pvt_reg, + item_t *poro, + item_t *dp_poro, + item_t *t_mult, + item_t *dp_t_mult); + + void + calc_prev_fluid_volume (); + + void + debug_save_data (item_t dt); + + item_t + calc_solution_mult_cell (const norms_storage_t &base_norm); + + bool + block_connections_mpfa (const item_t &dt); + + public: + sp_calc_model_t &calc_model_; + const sp_rock_grid_prop_t &rock_grid_prop_; + sp_reservoir_t &reservoir_; + sp_jacobian_t &jacobian_; + sp_jmatrix_t &jmatrix_; + const sp_mesh_iface_t &mesh_; + + sp_bcsr_matrix_t trns_matrix_; + const rhs_item_array_t &trns_values_; + const index_array_t &trns_rows_ptr_; + const index_array_t &trns_cols_ptr_; + + sp_bcsr_matrix_t reg_matrix_; + rhs_item_array_t ®_values_; + const index_array_t ®_rows_ptr_; + const index_array_t ®_cols_ptr_; + + const index_array_t &m_array_; + const index_array_t &p_array_; + + rhs_item_array_t &rhs_; + item_array_t &sol_; + rhs_item_array_t &flux_rhs_; + rhs_item_array_t &sp_diag_; + rhs_item_array_t &s_rhs_; + + const item_array_t &depths_; + + index_t n_cells_; + index_t n_connections_; + + index_t n_sec_vars; + + index_t d_w; + index_t d_g; + index_t d_o; + index_t ds_w; + index_t ds_g; + + index_t d_gg, d_gw, d_go; + index_t d_wg, d_ww, d_wo; + index_t d_og, d_ow, d_oo; + + data_array_t &data_; + item_array_t &saturation_3p_; + const item_array_t &pressure_; + item_array_t &gas_oil_ratio_; + main_var_array_t &main_vars_; + const item_array_t &volume_; + const item_array_t &poro_array_; + const item_array_t &rock_grid_comp_const_; + const item_array_t &rock_grid_comp_ref_pressure_; + const index_array_t &sat_regions_; + const index_array_t &pvt_regions_; + + const sp_pvt_dead_oil_array_t &pvt_oil_array; //!< (n_pvt_regions) + const sp_pvt_water_array_t &pvt_water_array; + const sp_pvt_gas_array_t &pvt_gas_array; + + item_t min_p_; + item_t max_p_; + item_t drsdt_; + item_t rhs_residual_; + item_t mb_error_; + item_t s_rhs_norm_; + + norms_storage_t &norm_; + rhs_item_array_t &cfl_; + }; + +} // namespace blue_sky + +#include "fi_operator_norm_calc.h" +#include "fi_operator_calc_step_dt_mult.h" +#include "fi_operator_calc_porosity_and_deriv.h" +#include "fi_operator_calc_prev_fluid_volume.h" +#include "fi_operator_save_debug_data.h" +#include "fi_operator_calc_solution_mult_cell.h" + +#ifdef BS_USE_TPFA_ +#include "fi_operator_block_connections_mpfa.h" +#else +#include "fi_operator_block_connections_mpfa_2.h" +#endif + +#endif // #ifndef BS_FI_OPERATOR_H_ + diff --git a/bs_bos_core/include/fi_operator_block_connections_mpfa.h b/bs_bos_core/include/fi_operator_block_connections_mpfa.h new file mode 100644 index 0000000..0bf1354 --- /dev/null +++ b/bs_bos_core/include/fi_operator_block_connections_mpfa.h @@ -0,0 +1,951 @@ +/** + * \file fi_operator_block_connections_mpfa.h + * \brief old (two point) mpfa impl + * \author Sergey Miryanov + * \date 06.04.2009 + * */ +#ifndef BS_FI_OPERATOR_BLOCK_CONNECTIONS_MPFA_H_ +#define BS_FI_OPERATOR_BLOCK_CONNECTIONS_MPFA_H_ + +namespace blue_sky { + + namespace tpfa + { + template + struct mpfa_impl + { + public: + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef boost::array up_cell_array_t; + typedef calc_model calc_model_t; + typedef typename calc_model_t::data_t data_t; + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::main_var_array_t main_var_array_t; + + public: + mpfa_impl (const fi_operator_impl &fi_operator_, item_array_t &rhs_, item_array_t ®_values_) + : fi_operator_ (fi_operator_), + n_phases (fi_operator_.n_phases), + is_w (fi_operator_.is_w), + is_g (fi_operator_.is_g), + is_o (fi_operator_.is_o), + d_w (fi_operator_.d_w), + d_g (fi_operator_.d_g), + d_o (fi_operator_.d_o), + saturation_3p_ (fi_operator_.saturation_3p_), + pressure_ (fi_operator_.pressure_), + gas_oil_ratio_ (fi_operator_.gas_oil_ratio_), + main_vars_ (fi_operator_.main_vars_), + data_ (fi_operator_.data_), + gravity_ (fi_operator_.calc_model_->internal_constants.gravity_constant), + n_sec_vars (fi_operator_.n_sec_vars), + rhs_ (rhs_), + reg_values_ (reg_values_) + { + } + + /*BS_FORCE_INLINE*/ void + mpfa_calc_avarage_density(item_t *ave_density, + const index_t *cell_ind_block, + const int &n_cells_in_conn) const + { + item_t counter[FI_PHASE_TOT] = {0}; + index_t flag[FI_PHASE_TOT] = {0}; + + memset (ave_density, 0, sizeof (item_t) * FI_PHASE_TOT); + //ave_density[0] = ave_density[1] = ave_density[2] = 0; + + for (int j = 0; j < n_cells_in_conn; ++j) + { + index_t ic = cell_ind_block[j]; + index_t idx = ic * n_phases; + const data_t &data_ic = data_[ic]; + + if (n_phases > 1) + { + bool is_w_ = is_w && saturation_3p_[idx + d_w] > EPS_DIV; + bool is_g_ = is_g && saturation_3p_[idx + d_g] > EPS_DIV; + bool is_o_ = is_o && saturation_3p_[idx + d_o] > EPS_DIV; + + if (is_w_) + { + ave_density[d_w] += data_ic.density[d_w]; + ++counter[d_w]; + ++flag[d_w]; + } + if (is_g_) + { + ave_density[d_g] += data_ic.density[d_g]; + ++counter[d_g]; + ++flag[d_g]; + } + if (is_o_) + { + ave_density[d_o] += data_ic.density[d_o]; + ++counter[d_o]; + ++flag[d_o]; + } + } + else + { + ave_density[0] += data_ic.density[0]; + ++counter[0]; + ++flag[0]; + } + } + for (int j = 0; j < n_phases; ++j) + { + if (flag[j]) + ave_density[j] /= counter[j]; + } + } + + BS_FORCE_INLINE void + mpfa_calc_potential (item_t *cell_pot, + item_t *sum_cell_pot, + item_t *ave_density, + const item_t *truns_block, + const item_array_t &depth, + const index_t * cell_ind_block, + index_t cell_m, + item_t dt, + int n_cells_in_conn) const + { + item_t g_h = gravity_; + item_t base_h = depth[cell_m]; + sum_cell_pot[0] = sum_cell_pot[1] = sum_cell_pot[2] = 0; + + for (index_t j = 0; j < n_cells_in_conn; ++j) + { + index_t ic = cell_ind_block[j]; + item_t dh = depth[ic] - base_h; + const data_t &data_ic = data_[ic]; + item_t truns_block_dt = truns_block[j] * dt; + + if (is_w) + { + index_t k = j * n_phases + d_w; + cell_pot[k] = pressure_[ic] - ave_density[d_w] * g_h * dh; + if (this->n_phases > 1) + cell_pot[k] += data_ic.cap_pressure[d_w]; + sum_cell_pot[d_w] += cell_pot[k] * truns_block_dt; + } + if (is_g) + { + index_t k = j * this->n_phases + d_g; + cell_pot[k] = pressure_[ic] - ave_density[d_g] * g_h * dh; + if (this->n_phases > 1) + cell_pot[k] += data_ic.cap_pressure[d_g]; + sum_cell_pot[d_g] += cell_pot[k] * truns_block_dt; + } + if (is_o) + { + index_t k = j * this->n_phases + d_o; + cell_pot[k] = pressure_[ic] - ave_density[d_o] * g_h * dh; + sum_cell_pot[d_o] += cell_pot[k] * truns_block_dt; + } + } + } + + /*BS_FORCE_INLINE */void + mpfa_calc_upstream(up_cell_array_t &up_cell, + item_t *sum_cell_pot, + const index_t &cell_m, + const index_t &cell_p) const + { + index_t cell_[] = {cell_m, cell_p}; + for (int j = 0; j < n_phases; ++j) + { + up_cell[j] = cell_[sum_cell_pot[j] > 0 ? 0 : 1]; + } + } + + /*BS_FORCE_INLINE */void + mpfa_fill_rhs(item_t * & rhs_m, + item_t * & rhs_p, + const up_cell_array_t &up_cell, + const item_t *truns_block, + item_t *cell_pot, + item_array_t &flux_rhs, + const item_t &dt, + const int &n_cells_in_conn, + const index_t &cell_m, + const index_t &cell_p, + const index_t &equ_w, const index_t equ_g, const index_t &equ_o) const + { + rhs_m = &flux_rhs[0] + cell_m * this->n_phases; + rhs_p = &flux_rhs[0] + cell_p * this->n_phases; + item_t rhs_block_m[3] = {0}, rhs_block_p[3] = {0}; + //rhs_block_m[0] = rhs_block_m[1] = rhs_block_m[2] = 0; + //rhs_block_p[0] = rhs_block_p[1] = rhs_block_p[2] = 0; + + static data_t dummy_data; + const data_t &data_m = data_[cell_m]; + const data_t &data_w = is_w ? data_[up_cell[d_w]] : dummy_data; + const data_t &data_g = is_g ? data_[up_cell[d_g]] : dummy_data; + const data_t &data_o = is_o ? data_[up_cell[d_o]] : dummy_data; + + item_t flow_m = data_m.truns_mult * dt; + item_t flow_w = is_w ? flow_m * data_w.mobility[d_w] : 0; + item_t flow_g = is_g ? flow_m * data_g.mobility[d_g] : 0; + item_t flow_o = is_o ? flow_m * data_o.mobility[d_o] : 0; + + index_t k_j = 0; + for (int j = 0; j < n_cells_in_conn; ++j, k_j += n_phases) + { + // water + if (is_w) + { + index_t k = k_j + d_w; + item_t flow = flow_w * truns_block[j] * cell_pot[k]; + rhs_block_m[equ_w] -= flow; + rhs_block_p[equ_w] += flow; + } + // oil + if (is_o) + { + index_t k = k_j + d_o; + item_t flow = flow_o * truns_block[j] * cell_pot[k]; + rhs_block_m[equ_o] -= flow; + rhs_block_p[equ_o] += flow; + // disolved gas + if (is_g) + { + flow *= gas_oil_ratio_[up_cell[d_o]]; + rhs_block_m[equ_g] -= flow; + rhs_block_p[equ_g] += flow; + } + } + // gas + if (is_g) + { + index_t k = k_j + d_g; + item_t flow = flow_g * truns_block[j] * cell_pot[k]; + rhs_block_m[equ_g] -= flow; + rhs_block_p[equ_g] += flow; + } + } + for (int j = 0; j < n_phases; ++j) + { + rhs_m[j] += rhs_block_m[j]; + rhs_p[j] += rhs_block_p[j]; + } + } + + /*BS_FORCE_INLINE*/ void + mpfa_fill_jacobian( boost::array &m_mem, + boost::array &p_mem, + const up_cell_array_t &up_cell, + const item_t *cell_pot, + const item_t *truns_block, + item_t * &rhs_m, + item_t * &rhs_p, + const index_t *cell_ind_block, + item_array_t &sp_diag, + item_array_t &s_rhs, + const item_t &dt, + const int &n_cells_in_conn, + const index_t &cell_m, + const index_t &cell_p, + const index_t &equ_w, const index_t equ_g, const index_t &equ_o) const + { + //m_mem.assign(0); + //p_mem.assign(0); + assign (m_mem, item_t (0)); + assign (p_mem, item_t (0)); + + static data_t dummy_data; + + item_t *sp_diag_val = &sp_diag[0]; + item_t *s_rhs_val = &s_rhs[0]; + + const data_t *data_m = &data_[cell_m]; + const data_t *data_w = &dummy_data; + const data_t *data_o = &dummy_data; + const data_t *data_g = &dummy_data; + + index_t up_cell_dw = 0; + index_t up_cell_do = 0; + index_t up_cell_dg = 0; + + index_t sp_size_w = 0; + index_t sp_size_o = 0; + index_t sp_size_g = 0; + + index_t rhs_size_w = 0; + index_t rhs_size_o = 0; + index_t rhs_size_g = 0; + + item_t truns_mob_w = 0; + item_t truns_mob_o = 0; + item_t truns_mob_g = 0; + + item_t truns_p_mob_w = 0; + item_t truns_p_mob_o = 0; + item_t truns_p_mob_g = 0; + + item_t truns_s_mob_ww = 0; + item_t truns_s_mob_ow = 0; + item_t truns_s_mob_og = 0; + item_t truns_s_mob_oo = 0; + item_t truns_s_mob_gg = 0; + + // calculate mobility indexies + index_t mob_w_dw = d_w * n_phases + d_w; + index_t mob_o_dw = d_o * n_phases + d_w; + index_t mob_o_dg = d_o * n_phases + d_g; + index_t mob_o_do = d_o * n_phases + d_o; + index_t mob_g_dg = d_g * n_phases + d_g; + + if (is_w) + { + data_w = &data_[up_cell[d_w]]; + up_cell_dw = up_cell[d_w]; + sp_size_w = n_sec_vars * this->n_phases * up_cell_dw; + rhs_size_w = n_sec_vars * up_cell_dw; + truns_mob_w = data_m->truns_mult * dt * data_w->mobility[d_w]; + truns_p_mob_w = data_m->truns_mult *dt * data_w->p_deriv_mobility[d_w]; + truns_s_mob_ww = data_m->truns_mult * dt * data_w->s_deriv_mobility[mob_w_dw]; + } + + if (is_o) + { + data_o = &data_[up_cell[d_o]]; + up_cell_do = up_cell[d_o]; + rhs_size_o = n_sec_vars * up_cell_do; + sp_size_o = n_sec_vars * this->n_phases * up_cell_do; + truns_mob_o = data_m->truns_mult * dt * data_o->mobility[d_o]; + truns_p_mob_o = data_m->truns_mult *dt * data_o->p_deriv_mobility[d_o]; + truns_s_mob_ow = data_m->truns_mult * dt * data_o->s_deriv_mobility[mob_o_dw]; + truns_s_mob_og = data_m->truns_mult * dt * data_o->s_deriv_mobility[mob_o_dg]; + truns_s_mob_oo = data_m->truns_mult * dt * data_o->s_deriv_mobility[mob_o_do]; + } + if (is_g) + { + data_g = &data_[up_cell[d_g]]; + up_cell_dg = up_cell[d_g]; + sp_size_g = n_sec_vars * this->n_phases * up_cell_dg; + rhs_size_g = n_sec_vars * up_cell_dg; + truns_mob_g = data_m->truns_mult * dt * data_g->mobility[d_g]; + truns_p_mob_g = data_m->truns_mult *dt * data_g->p_deriv_mobility[d_g]; + truns_s_mob_gg = data_m->truns_mult * data_g->s_deriv_mobility[mob_g_dg]; + } + + index_t k_j = 0; + for (int j = 0; j < n_cells_in_conn; ++j, k_j += n_phases) + { + index_t ic = cell_ind_block[j]; + + index_t k; + item_t dsw, dsg, dso, dpo; + item_t dsw_up, dsg_up, dpo_up, dso_up; + + item_t *pp_block_m = &m_mem [j * 9]; + item_t *pp_block_p = &p_mem [j * 9]; + item_t *pp_block_m_up; + item_t *pp_block_p_up; + item_t ps_block_p_up[3]; + item_t ps_block_m_up[3]; + item_t *sp_block_up; + item_t *s_rhs_block_up; + + item_t ps_block_m[FI_PHASE_TOT] = {0}; // temporary block for PS + item_t ps_block_p[FI_PHASE_TOT] = {0}; // temporary block for PS + + item_t *sp_block = sp_diag_val + n_sec_vars * this->n_phases * ic; + item_t *s_rhs_block = s_rhs_val + n_sec_vars * ic; + + item_t truns_block_j = truns_block[j]; + + // water + if (is_w) + { + ps_block_p_up[0] = ps_block_p_up[1] = ps_block_p_up[2] = 0; + ps_block_m_up[0] = ps_block_m_up[1] = ps_block_m_up[2] = 0; + sp_block_up = sp_diag_val + sp_size_w; + s_rhs_block_up = s_rhs_val + rhs_size_w; + + if (up_cell_dw == cell_ind_block[0]) + { + pp_block_m_up = &m_mem[0]; + pp_block_p_up = &p_mem[0]; + } + else + { + pp_block_m_up = &m_mem[9]; + pp_block_p_up = &p_mem[9]; + } + k = k_j + d_w; + item_t cell_pot_k = cell_pot[k]; + dpo = truns_mob_w * truns_block[j]; + dpo_up = 0; + if (ic == up_cell_dw) + { + dpo += truns_p_mob_w * truns_block_j * cell_pot_k; + } + else + { + dpo_up = truns_p_mob_w * truns_block_j * cell_pot_k; + } + + if (n_phases > 1) + { + dsg = 0; + dso = 0; + dsw = truns_mob_w * truns_block_j * data_[ic].s_deriv_cap_pressure[d_w]; + dsg_up = dso_up = dsw_up = 0; + if (ic == up_cell_dw) + { + dsw += truns_s_mob_ww * truns_block_j * cell_pot_k; + } + else + { + dsw_up = truns_s_mob_ww * truns_block_j * cell_pot_k; + } + if (n_phases == 3) + { + pp_block_m[p3_wat_po] += dpo; + pp_block_m_up[p3_wat_po] += dpo_up; + pp_block_p[p3_wat_po] -= dpo; + pp_block_p_up[p3_wat_po] -= dpo_up; + + ps_block_m[p3_wat] += dsw; + ps_block_m_up[p3_wat] += dsw_up; + ps_block_p[p3_wat] += -dsw; + ps_block_p_up[p3_wat] += -dsw_up; + } + else + { + pp_block_m[p2ow_wat_po] += dpo; + pp_block_m_up[p2ow_wat_po] += dpo_up; + pp_block_p[p2ow_wat_po] -= dpo; + pp_block_p_up[p2ow_wat_po] -= dpo_up; + + ps_block_m[p2ow_wat] += dsw; + ps_block_m_up[p2ow_wat] += dsw_up; + ps_block_p[p2ow_wat] += -dsw; + ps_block_p_up[p2ow_wat] += -dsw_up; + } + + M_MINUS_VV_PROD (n_phases, ps_block_m_up, sp_block_up, pp_block_m_up); + V_MINUS_VS_PROD (n_phases, ps_block_m_up, s_rhs_block_up, rhs_m); + + M_MINUS_VV_PROD (n_phases, ps_block_p_up, sp_block_up, pp_block_p_up); + V_MINUS_VS_PROD (n_phases, ps_block_p_up, s_rhs_block_up, rhs_p); + } + else + { + pp_block_m[0] += dpo; + pp_block_m_up[0] += dpo_up; + pp_block_p[0] -= dpo; + pp_block_p_up[0] -= dpo_up; + } + } + // oil + if (is_o) + { + item_t g_dpo, g_dso, g_dsw, g_dsg; + item_t g_dpo_up, g_dso_up, g_dsw_up, g_dsg_up; + k = k_j + d_o; + item_t cell_pot_k = cell_pot[k]; + + ps_block_p_up[0] = ps_block_p_up[1] = ps_block_p_up[2] = 0; + ps_block_m_up[0] = ps_block_m_up[1] = ps_block_m_up[2] = 0; + sp_block_up = sp_diag_val + sp_size_o; + s_rhs_block_up = s_rhs_val + rhs_size_o; + + if (up_cell_do == cell_ind_block[0]) + { + pp_block_m_up = &m_mem[0]; + pp_block_p_up = &p_mem[0]; + } + else + { + pp_block_m_up = &m_mem[9]; + pp_block_p_up = &p_mem[9]; + } + + // calculate pressure derivatives + dpo = truns_mob_o * truns_block_j; + dpo_up = 0; + if (ic == up_cell_do) + { + dpo += truns_p_mob_o * truns_block_j * cell_pot_k; + } + else + { + dpo_up = truns_p_mob_o * truns_block_j * cell_pot_k; + } + if (is_g) + { + g_dpo = gas_oil_ratio_[up_cell_do] * dpo; + g_dpo_up = gas_oil_ratio_[up_cell_do] * dpo_up; + if (ic == up_cell_do && FI_CHK_SG (main_vars_, ic)) + { + g_dpo += truns_mob_o * truns_block_j * data_o->p_deriv_gas_oil_ratio * cell_pot_k; + } + else if (FI_CHK_SG (main_vars_, up_cell_do)) + { + g_dpo_up += truns_mob_o * truns_block_j * data_o->p_deriv_gas_oil_ratio * cell_pot_k; + } + } + + dsw = 0; + dso = 0; + dsg = 0; + dsw_up = 0; + dso_up = 0; + dsg_up = 0; + + // calculate saturation deriv + if (ic == up_cell[d_o]) + { + if (is_w) + dsw = truns_s_mob_ow * truns_block_j * cell_pot_k; + if (is_g) + dsg = truns_s_mob_og * truns_block_j * cell_pot_k; + if (n_phases > 1) + dso = truns_s_mob_oo * truns_block_j * cell_pot_k; + } + else + { + if (is_w) + dsw_up = truns_s_mob_ow * truns_block_j * cell_pot_k; + if (is_g) + dsg_up = truns_s_mob_og * truns_block_j * cell_pot_k; + if (n_phases > 1) + dso_up = truns_s_mob_oo * truns_block_j * cell_pot_k; + } + if (is_g) + { + g_dso = gas_oil_ratio_[up_cell_do] * dso; + g_dso_up = gas_oil_ratio_[up_cell_do] * dso_up; + if (is_w) + { + g_dsw = gas_oil_ratio_[up_cell_do] * dsw; + g_dsw_up = gas_oil_ratio_[up_cell_do] * dsw_up; + } + + g_dsg = gas_oil_ratio_[up_cell_do] * dsg; + g_dsg_up = gas_oil_ratio_[up_cell_do] * dsg_up; + + if (ic == up_cell[d_o] && FI_CHK_RO (main_vars_, ic)) + { + g_dsg += truns_s_mob_og * truns_block_j * cell_pot_k; + } + else if (FI_CHK_RO (main_vars_, ic)) + { + g_dsg_up += truns_s_mob_og * truns_block_j * cell_pot_k; + } + } + + if (n_phases == 3) + { + //oil + pp_block_m[p3_oil_po] += dpo; + pp_block_m[p3_oil_so] += dso; + pp_block_m[p3_oil_sg] += dsg; + ps_block_m[p3_oil] += dsw; + + pp_block_p[p3_oil_po] -= dpo; + pp_block_p[p3_oil_so] -= dso; + pp_block_p[p3_oil_sg] -= dsg; + ps_block_p[p3_oil] += -dsw; + + pp_block_m_up[p3_oil_po] += dpo_up; + pp_block_m_up[p3_oil_so] += dso_up; + pp_block_m_up[p3_oil_sg] += dsg_up; + ps_block_m_up[p3_oil] += dsw_up; + + pp_block_p_up[p3_oil_po] -= dpo_up; + pp_block_p_up[p3_oil_so] -= dso_up; + pp_block_p_up[p3_oil_sg] -= dsg_up; + ps_block_p_up[p3_oil] += -dsw_up; + + // gas + pp_block_m[p3_gas_po] += g_dpo; + pp_block_m[p3_gas_so] += g_dso; + pp_block_m[p3_gas_sg] += g_dsg; + ps_block_m[p3_gas] += g_dsw; + + pp_block_p[p3_gas_po] -= g_dpo; + pp_block_p[p3_gas_so] -= g_dso; + pp_block_p[p3_gas_sg] -= g_dsg; + ps_block_p[p3_gas] += -g_dsw; + + pp_block_m_up[p3_gas_po] += g_dpo_up; + pp_block_m_up[p3_gas_so] += g_dso_up; + pp_block_m_up[p3_gas_sg] += g_dsg_up; + ps_block_m_up[p3_gas] += g_dsw_up; + + pp_block_p_up[p3_gas_po] -= g_dpo_up; + pp_block_p_up[p3_gas_so] -= g_dso_up; + pp_block_p_up[p3_gas_sg] -= g_dsg_up; + ps_block_p_up[p3_gas] += -g_dsw_up; + } + else if (is_w) + { + pp_block_m[p2ow_oil_po] += dpo; + pp_block_m[p2ow_oil_so] += dso; + ps_block_m[p2ow_oil] += dsw; + + pp_block_p[p2ow_oil_po] -= dpo; + pp_block_p[p2ow_oil_so] -= dso; + ps_block_p[p2ow_oil] += -dsw; + + pp_block_m_up[p2ow_oil_po] += dpo_up; + pp_block_m_up[p2ow_oil_so] += dso_up; + ps_block_m_up[p2ow_oil] += dsw_up; + + pp_block_p_up[p2ow_oil_po] -= dpo_up; + pp_block_p_up[p2ow_oil_so] -= dso_up; + ps_block_p_up[p2ow_oil] += -dsw_up; + } + else if (is_g) + { + // oil + pp_block_m[p2og_oil_po] += dpo; + pp_block_m[p2og_oil_sg] += dsg; + ps_block_m[p2og_oil] += dso; + + pp_block_p[p2og_oil_po] -= dpo; + pp_block_p[p2og_oil_sg] -= dsg; + ps_block_p[p2og_oil] += -dso; + + pp_block_m_up[p2og_oil_po] += dpo_up; + pp_block_m_up[p2og_oil_sg] += dsg_up; + ps_block_m_up[p2og_oil] += dso_up; + + pp_block_p_up[p2og_oil_po] -= dpo_up; + pp_block_p_up[p2og_oil_sg] -= dsg_up; + ps_block_p_up[p2og_oil] += -dso_up; + + // gas + pp_block_m[p2og_gas_po] += g_dpo; + pp_block_m[p2og_gas_sg] += g_dsg; + ps_block_m[p2og_gas] += g_dso; + + pp_block_p[p2og_gas_po] -= g_dpo; + pp_block_p[p2og_gas_sg] -= g_dsg; + ps_block_p[p2og_gas] += -g_dso; + + pp_block_m_up[p2og_gas_po] += g_dpo_up; + pp_block_m_up[p2og_gas_sg] += g_dsg_up; + ps_block_m_up[p2og_gas] += g_dso_up; + + pp_block_p_up[p2og_gas_po] -= g_dpo_up; + pp_block_p_up[p2og_gas_sg] -= g_dsg_up; + ps_block_p_up[p2og_gas] += -g_dso_up; + } + else + { + pp_block_m[0] += dpo; + pp_block_p[0] -= dpo; + + pp_block_m_up[0] += dpo_up; + pp_block_p_up[0] -= dpo_up; + } + if (n_phases > 1) + { + M_MINUS_VV_PROD (n_phases, ps_block_m_up, sp_block_up, pp_block_m_up); + V_MINUS_VS_PROD (n_phases, ps_block_m_up, s_rhs_block_up, rhs_m); + + M_MINUS_VV_PROD (n_phases, ps_block_p_up, sp_block_up, pp_block_p_up); + V_MINUS_VS_PROD (n_phases, ps_block_p_up, s_rhs_block_up, rhs_p); + } + } + // gas + if (is_g) + { + //index_t mobg = 0; + k = k_j + d_g; + + ps_block_p_up[0] = ps_block_p_up[1] = ps_block_p_up[2] = 0; + ps_block_m_up[0] = ps_block_m_up[1] = ps_block_m_up[2] = 0; + sp_block_up = sp_diag_val + sp_size_g; + s_rhs_block_up = s_rhs_val + rhs_size_g; + + if (up_cell_dg == cell_ind_block[0]) + { + pp_block_m_up = &m_mem[0]; + pp_block_p_up = &p_mem[0]; + } + else + { + pp_block_m_up = &m_mem[9]; + pp_block_p_up = &p_mem[9]; + } + + // calculate pressure derivaties + dpo = truns_mob_g * truns_block[j]; + dpo_up = 0; + if (ic == up_cell_dg) + dpo += truns_p_mob_g * truns_block[j] * cell_pot[k]; + else + dpo_up = truns_p_mob_g * truns_block[j] * cell_pot[k]; + + dsw = 0; + dso = 0; + dsg = 0; + dsw_up = dso_up = dsg_up = 0; + // calculate mobility indexies + //mobg = d_g * n_phases + d_g; + + if (is_o) + { + dsg += truns_mob_g * truns_block[j] * data_[ic].s_deriv_cap_pressure[d_g]; + dsg_up = 0; + if (ic == up_cell_dg) + { + dsg += truns_s_mob_gg * truns_block[j] * cell_pot[k]; + } + else + { + dsg_up = truns_s_mob_gg * truns_block[j] * cell_pot[k]; + } + } + if (n_phases > 1 && !(FI_CHK_SG (main_vars_, up_cell_dg))) + { + dpo = dpo_up = 0; + dso = dso_up = 0; + dsg = dsg_up = 0; + dsw = dsw_up = 0; + } + + if (n_phases == 3) + { + pp_block_m[p3_gas_po] += dpo; + pp_block_m[p3_gas_so] += dso; + pp_block_m[p3_gas_sg] += dsg; + ps_block_m[p3_gas] += dsw; + + pp_block_p[p3_gas_po] -= dpo; + pp_block_p[p3_gas_so] -= dso; + pp_block_p[p3_gas_sg] -= dsg; + ps_block_p[p3_gas] += -dsw; + + // up block + pp_block_m_up[p3_gas_po] += dpo_up; + pp_block_m_up[p3_gas_so] += dso_up; + pp_block_m_up[p3_gas_sg] += dsg_up; + ps_block_m_up[p3_gas] += dsw_up; + + pp_block_p_up[p3_gas_po] -= dpo_up; + pp_block_p_up[p3_gas_so] -= dso_up; + pp_block_p_up[p3_gas_sg] -= dsg_up; + ps_block_p_up[p3_gas] += -dsw_up; + } + else if (n_phases == 2) + { + pp_block_m[p2og_gas_po] += dpo; + pp_block_m[p2og_gas_sg] += dsg; + ps_block_m[p2og_gas] += dso; + + pp_block_p[p2og_gas_po] -= dpo; + pp_block_p[p2og_gas_sg] -= dsg; + ps_block_p[p2og_gas] += -dso; + + // up block + pp_block_m_up[p2og_gas_po] += dpo_up; + pp_block_m_up[p2og_gas_sg] += dsg_up; + ps_block_m_up[p2og_gas] += dso_up; + + pp_block_p_up[p2og_gas_po] -= dpo_up; + pp_block_p_up[p2og_gas_sg] -= dsg_up; + ps_block_p_up[p2og_gas] += -dso_up; + } + else + { + pp_block_m[0] += dpo; + pp_block_p[0] -= dpo; + + // up block + pp_block_m_up[0] += dpo_up; + pp_block_p_up[0] -= dpo_up; + } + if (n_phases > 1) + { + M_MINUS_VV_PROD (n_phases, ps_block_m_up, sp_block_up, pp_block_m_up); + M_MINUS_VV_PROD (n_phases, ps_block_p_up, sp_block_up, pp_block_p_up); + V_MINUS_VS_PROD (n_phases, ps_block_m_up, s_rhs_block_up, rhs_m); + V_MINUS_VS_PROD (n_phases, ps_block_p_up, s_rhs_block_up, rhs_p); + } + } + M_MINUS_VV_PROD (n_phases, ps_block_m, sp_block, pp_block_m); + M_MINUS_VV_PROD (n_phases, ps_block_p, sp_block, pp_block_p); + + V_MINUS_VS_PROD (n_phases, ps_block_m, s_rhs_block, rhs_m); + V_MINUS_VS_PROD (n_phases, ps_block_p, s_rhs_block, rhs_p); + } + + } + + public: + + const fi_operator_impl &fi_operator_; + index_t n_phases; + bool is_w; + bool is_g; + bool is_o; + index_t d_w; + index_t d_g; + index_t d_o; + const item_array_t &saturation_3p_; + const item_array_t &pressure_; + const item_array_t &gas_oil_ratio_; + const main_var_array_t &main_vars_; + const data_array_t &data_; + item_t gravity_; + index_t n_sec_vars; + item_array_t &rhs_; + item_array_t ®_values_; + }; + } // tpfa + + template + bool + fi_operator_impl ::block_connections_mpfa (const item_t &dt) + { + //// TODO: + //// Miryanov: we keep a new version for performance measurement on geostation on large models + //if (n_phases == 3) + // { + // return mpfa_calc_3phase (this).calc (dt); + // } + //else if (n_phases == 2 && is_w) + // { + // return mpfa_calc_2phase_ow (this).calc (dt); + // } + //else if (n_phases == 2 && is_g) + // { + // return mpfa_calc_2phase_og (this).calc (dt); + // } + //else if (is_w) + // { + // return mpfa_calc_1phase_w (this).calc (dt); + // } + //else if (is_g) + // { + // return mpfa_calc_1phase_g (this).calc (dt); + // } + //else if (is_o) + // { + // return mpfa_calc_1phase_o (this).calc (dt); + // } + //else + // { + // throw bs_exception ("block_connections_mpfa", "NOT IMPL YET"); + // } + + index_t b_sqr = n_phases * n_phases; + index_t equ_w = 0, equ_g = 0, equ_o = 0; + + boost::array ave_density; // average density of phase over all cells involved in MPFA connection + + //potential + item_t cell_pot[2 * FI_PHASE_TOT]; // potential for cell + item_t sum_cell_pot[FI_PHASE_TOT]; + + //up_stream + typedef tpfa::mpfa_impl mpfa_impl_t; + typename mpfa_impl_t::up_cell_array_t up_cell; // index of upstream cell + + //rhs + item_t * rhs_m; + item_t * rhs_p; + + //jacobian + boost::array m_mem; + boost::array p_mem; + + assign (flux_rhs_, 0); + + // TPFA: (SHOULD BE REMOVED AFTER FULL MPFA IMPL) + // number of cells used to build MPFA for one connection + index_t n_cells_in_conn = 2; + + if (n_phases == 3) + { + equ_w = p3_wat; + equ_g = p3_gas; + equ_o = p3_oil; + } + else if (n_phases == 2 && is_w) + { + equ_w = p2ow_wat; + equ_o = p2ow_oil; + } + else if (n_phases == 2 && is_g) + { + equ_g = p2og_gas; + equ_o = p2og_oil; + } + else + { + equ_g = equ_w = equ_o = 0; + } + + mpfa_impl_t mpfa (*this, flux_rhs_, reg_values_); + + // main loop through connections + for (index_t i = 0; i < n_connections_; ++i) + { + index_t row_i = trns_rows_ptr_[i]; + const item_t *truns_block = &trns_values_[row_i]; // temporary array for TPFA connection (SHOULD BE REMOVED AFTER FULL MPFA IMPL) + + // temporary array for TPFA cell ind (SHOULD BE REMOVED AFTER FULL MPFA IMPL) + const index_t *cell_ind_block = &trns_cols_ptr_[row_i]; + + index_t cell_m = cell_ind_block[0]; //pervii v cols index v stroke // index of primary cell in MPFA connection (minus) + index_t cell_p = cell_ind_block[1]; //vtoroi // index of primary cell in MPFA connection (plus) + const index_t *m_mem_ptr = &m_array_[row_i]; // ptr to the block in matrix row cell_m for columns with indexies #cell_ind_block + const index_t *p_mem_ptr = &p_array_[row_i]; // ptr to the block in matrix row cell_p for columns with indexies #cell_ind_block + + //fills ave_density and ++s counter + mpfa.mpfa_calc_avarage_density(&ave_density[0], cell_ind_block, n_cells_in_conn); + + //fills cell_pot and sum_cell_pot + mpfa.mpfa_calc_potential(cell_pot, sum_cell_pot, &ave_density[0], truns_block, depths_, + cell_ind_block, cell_m, dt, n_cells_in_conn); + + //fills up_cell + mpfa.mpfa_calc_upstream(up_cell, sum_cell_pot, cell_m, cell_p); + + //fills rhs_m and rhs_p + mpfa.mpfa_fill_rhs(rhs_m, rhs_p, up_cell, truns_block, cell_pot, mpfa.rhs_, dt, n_cells_in_conn, + cell_m, cell_p, equ_w, equ_g, equ_o); + + + //fills m_mem and p_mem + mpfa.mpfa_fill_jacobian(m_mem, p_mem, up_cell, cell_pot, truns_block, rhs_m, rhs_p, + cell_ind_block, sp_diag_, s_rhs_, dt, n_cells_in_conn, + cell_m, cell_p, equ_w, equ_g, equ_o); + + item_t * block_m1 = &mpfa.reg_values_[m_mem_ptr[0] * b_sqr]; + item_t * block_p1 = &mpfa.reg_values_[p_mem_ptr[0] * b_sqr]; + item_t * block_m2 = &mpfa.reg_values_[m_mem_ptr[1] * b_sqr]; + item_t * block_p2 = &mpfa.reg_values_[p_mem_ptr[1] * b_sqr]; + + for (index_t j = 0; j < b_sqr; ++j) + { + block_m1[j] += m_mem[j]; + block_p1[j] += p_mem[j]; + + block_m2[j] += m_mem[9 + j]; + block_p2[j] += p_mem[9 + j]; + } + + // END OF JACOBIAN filling + } + + return 0; + } + +} // namespace blue_sky + + +#endif // BS_FI_OPERATOR_BLOCK_CONNECTIONS_MPFA_H_ + diff --git a/bs_bos_core/include/fi_operator_block_connections_mpfa_2.h b/bs_bos_core/include/fi_operator_block_connections_mpfa_2.h new file mode 100644 index 0000000..7102f09 --- /dev/null +++ b/bs_bos_core/include/fi_operator_block_connections_mpfa_2.h @@ -0,0 +1,884 @@ +/** + * \file fi_operator_block_connections_mpfa_2.h + * \brief new (full mpfa) mpfa impl + * \author Sergey Miryanov + * \date 06.04.2009 + * */ +#ifndef BS_FI_OPERATOR_BLOCK_CONNECTION_MPFA_2_H_ +#define BS_FI_OPERATOR_BLOCK_CONNECTION_MPFA_2_H_ + +#include "calc_model.h" +#include "matrix_vector_op.h" +#include "pp_index.h" + +#define IS_STABLE 0 +#define UNKNOWN -1 + +namespace blue_sky { + + namespace mpfa + { + #define PSI_W psi_[d_w] + #define PSI_G psi_[d_g] + #define PSI_O psi_[d_o] + #define RHO_W rho_[d_w] + #define RHO_G rho_[d_g] + #define RHO_O rho_[d_o] + #define UP_W up_[d_w] + #define UP_G up_[d_g] + #define UP_O up_[d_o] + #define UP_CELL_W up_cell_[d_w] + #define UP_CELL_G up_cell_[d_g] + #define UP_CELL_O up_cell_[d_o] + #define FLOW_W flow_[d_w] + #define FLOW_G flow_[d_g] + #define FLOW_O flow_[d_o] + + #define CAP_PRESSURE_K_W data_[k_cell].cap_pressure [d_w] + #define CAP_PRESSURE_K_G data_[k_cell].cap_pressure [d_g] + #define PRESSURE_K pressure_[k_cell] + #define S_DERIV_CAP_PRESSURE_K_W data_[k_cell].s_deriv_cap_pressure [ds_w] + #define S_DERIV_CAP_PRESSURE_K_G data_[k_cell].s_deriv_cap_pressure [ds_g] + + #define MOBILITY_UP_W mobility_up_w + #define MOBILITY_UP_G mobility_up_g + #define MOBILITY_UP_O mobility_up_o + #define GOR_UP_O gor_up_o + #define SW_DERIV_MOBILITY_UP_W sw_deriv_mobility_up_w + #define SW_DERIV_MOBILITY_UP_G sw_deriv_mobility_up_g + #define SW_DERIV_MOBILITY_UP_O sw_deriv_mobility_up_o + #define SG_DERIV_MOBILITY_UP_W sg_deriv_mobility_up_w + #define SG_DERIV_MOBILITY_UP_G sg_deriv_mobility_up_g + #define SG_DERIV_MOBILITY_UP_O sg_deriv_mobility_up_o + #define SO_DERIV_MOBILITY_UP_W so_deriv_mobility_up_w + #define SO_DERIV_MOBILITY_UP_G so_deriv_mobility_up_g + #define SO_DERIV_MOBILITY_UP_O so_deriv_mobility_up_o + #define P_DERIV_MOBILITY_UP_W p_deriv_mobility_up_w + #define P_DERIV_MOBILITY_UP_G p_deriv_mobility_up_g + #define P_DERIV_MOBILITY_UP_O p_deriv_mobility_up_o + #define MAIN_VAR_UP_G main_var_up_g + #define MAIN_VAR_UP_O main_var_up_o + #define P_DERIV_GOR_UP_O p_deriv_gor_up_o + + template + struct mpfa_base_impl + { + public: + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef boost::array up_cell_array_t; + typedef calc_model calc_model_t; + typedef typename calc_model_t::data_t data_t; + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::main_var_array_t main_var_array_t; + + typedef typename calc_model_t::sp_pvt_dead_oil_array_t sp_pvt_dead_oil_array_t; + typedef typename calc_model_t::sp_pvt_gas_array_t sp_pvt_gas_array_t; + typedef typename calc_model_t::sp_pvt_water_array_t sp_pvt_water_array_t; + + + typedef rs_mesh_iface mesh_iface_t; + //typedef nc_ptr nc_mesh_iface_t; + typedef smart_ptr sp_mesh_iface_t; + typedef rs_smesh_iface rs_smesh_iface_t; + + + enum + { + n_phases = is_w + is_g + is_o, + b_sqr = n_phases * n_phases, + }; + + enum + { + is_1p = n_phases == 1, + is_2p = n_phases == 2, + is_3p = n_phases == 3, + }; + + enum + { + gas_sg = detail::pp_index ::gas_sg, + gas_so = detail::pp_index ::gas_so, + gas_po = detail::pp_index ::gas_po, + oil_sg = detail::pp_index ::oil_sg, + oil_so = detail::pp_index ::oil_so, + oil_po = detail::pp_index ::oil_po, + wat_sg = detail::pp_index ::wat_sg, + wat_so = detail::pp_index ::wat_so, + wat_po = detail::pp_index ::wat_po, + }; + + enum + { + gas_idx = 0, + oil_idx = is_g, + wat_idx = is_g + is_o, + + gas_sw = !is_1p ? b_sqr + gas_idx : -1, + oil_sw = !is_1p ? b_sqr + oil_idx : -1, + wat_sw = !is_1p ? b_sqr + wat_idx : -1, + }; + + public: + mpfa_base_impl (const fi_operator_impl &fi_operator_, rhs_item_array_t &rhs_, rhs_item_array_t ®_values_) + : d_w (fi_operator_.d_w), + d_g (fi_operator_.d_g), + d_o (fi_operator_.d_o), + ds_w (fi_operator_.ds_w), + ds_g (fi_operator_.ds_g), + saturation_3p_ (fi_operator_.saturation_3p_), + pressure_ (fi_operator_.pressure_), + gas_oil_ratio_ (fi_operator_.gas_oil_ratio_), + main_vars_ (fi_operator_.main_vars_), + data_ (fi_operator_.data_), + depths_ (fi_operator_.depths_), + gravity_ (fi_operator_.calc_model_->internal_constants.gravity_constant), + n_sec_vars (fi_operator_.n_sec_vars), + sp_diag_ (fi_operator_.sp_diag_), + s_rhs_ (fi_operator_.s_rhs_), + reg_values_ (reg_values_), + rhs_ (rhs_), + m_mem (0), + p_mem (0), + depth_top (0), + mesh_ (fi_operator_.mesh_) + + { + } + + BS_FORCE_INLINE void + fill_jacobian_k_derivs (index_t k) const + { + rhs_item_t *jacobian_ik = ®_values_ [m_mem[k] * b_sqr]; + rhs_item_t *jacobian_jk = ®_values_ [p_mem[k] * b_sqr]; + + for (index_t i = 0; i < b_sqr; ++i) + { + jacobian_ik [i] += pp[i]; + jacobian_jk [i] -= pp[i]; + } + } + + void + compute_rho (const index_t *cells, index_t cells_count) + { + boost::array counter; + boost::array flag; + + assign (rho_, 0); + assign (counter, 0); + assign (flag, 0); + + for (index_t j = 0; j < cells_count; ++j) + { + index_t ic = cells[j]; + index_t idx = ic * n_phases; + const data_t &data_ic = data_[ic]; + + if (n_phases > 1) // BUG: should be checked + { + bool is_g_ = is_g && saturation_3p_[idx + d_g] > EPS_DIV; + bool is_o_ = is_o && saturation_3p_[idx + d_o] > EPS_DIV; + bool is_w_ = is_w && saturation_3p_[idx + d_w] > EPS_DIV; + + if (is_g_) + { + rho_[d_g] += data_ic.density[d_g]; + ++counter[d_g]; + ++flag[d_g]; + } + if (is_o_) + { + rho_[d_o] += data_ic.density[d_o]; + ++counter[d_o]; + ++flag[d_o]; + } + if (is_w_) + { + rho_[d_w] += data_ic.density[d_w]; + ++counter[d_w]; + ++flag[d_w]; + } + } + else + { + rho_[0] += data_ic.density[0]; + ++counter[0]; + ++flag[0]; + } + } + for (index_t j = 0; j < n_phases; ++j) + { + if (flag[j]) + rho_[j] /= counter[j]; + } + } + + void + compute_psi (const rhs_item_t *truns, const index_t *cells, index_t cells_count) + { + assign (psi_, 0); + + depth_top = depths_ [cells[0]]; + for (index_t k = 0; k < cells_count; ++k) + { + index_t k_cell = cells [k]; + rhs_item_t truns_k = truns[k]; + item_t g_h = gravity_ * (depths_[k_cell] - depth_top); + item_t p = PRESSURE_K; + + if (is_g) PSI_G += truns_k * (p + CAP_PRESSURE_K_G - RHO_G * g_h); + if (is_o) PSI_O += truns_k * (p - RHO_O * g_h); + if (is_w) PSI_W += truns_k * (p + CAP_PRESSURE_K_W - RHO_W * g_h); + } + } + + void + compute_upstream (index_t i, index_t j, index_t i_cell, index_t j_cell) + { + index_t up_i[] = {j, i}; + index_t up_cell[] = {j_cell, i_cell}; + + if (is_g) UP_G = up_i[PSI_G > 0.0]; + if (is_o) UP_O = up_i[PSI_O > 0.0]; + if (is_w) UP_W = up_i[PSI_W > 0.0]; + if (is_g) UP_CELL_G = up_cell[PSI_G > 0.0]; + if (is_o) UP_CELL_O = up_cell[PSI_O > 0.0]; + if (is_w) UP_CELL_W = up_cell[PSI_W > 0.0]; + + if (is_w) sw_deriv_mobility_up_w = data_[UP_CELL_W].s_deriv_mobility[d_w * n_phases + d_w]; + if (is_w && is_g) sw_deriv_mobility_up_g = data_[UP_CELL_G].s_deriv_mobility[d_w * n_phases + d_g]; + if (is_w && is_o) sw_deriv_mobility_up_o = data_[UP_CELL_O].s_deriv_mobility[d_w * n_phases + d_o]; + if (is_g && is_w) sg_deriv_mobility_up_w = data_[UP_CELL_W].s_deriv_mobility[d_g * n_phases + d_w]; + if (is_g) sg_deriv_mobility_up_g = data_[UP_CELL_G].s_deriv_mobility[d_g * n_phases + d_g]; + if (is_g && is_o) sg_deriv_mobility_up_o = data_[UP_CELL_O].s_deriv_mobility[d_g * n_phases + d_o]; + if (is_o && is_w) so_deriv_mobility_up_w = data_[UP_CELL_W].s_deriv_mobility[d_o * n_phases + d_w]; + if (is_o && is_g) so_deriv_mobility_up_g = data_[UP_CELL_G].s_deriv_mobility[d_o * n_phases + d_g]; + if (is_o) so_deriv_mobility_up_o = data_[UP_CELL_O].s_deriv_mobility[d_o * n_phases + d_o]; + if (is_w) p_deriv_mobility_up_w = data_[UP_CELL_W].p_deriv_mobility[d_w]; + if (is_g) p_deriv_mobility_up_g = data_[UP_CELL_G].p_deriv_mobility[d_g]; + if (is_o) p_deriv_mobility_up_o = data_[UP_CELL_O].p_deriv_mobility[d_o]; + if (is_w) mobility_up_w = data_[UP_CELL_W].mobility [d_w]; + if (is_g) mobility_up_g = data_[UP_CELL_G].mobility [d_g]; + if (is_o) mobility_up_o = data_[UP_CELL_O].mobility [d_o]; + if (is_o && is_g) gor_up_o = gas_oil_ratio_[UP_CELL_O]; + if (is_o && is_g) p_deriv_gor_up_o = data_[UP_CELL_O].p_deriv_gas_oil_ratio; + if (is_g) main_var_up_g = main_vars_[UP_CELL_G]; + if (is_o) main_var_up_o = main_vars_[UP_CELL_O]; + } + + void + compute_flow (const double &dt) + { + if (is_g) FLOW_G = dt * MOBILITY_UP_G * PSI_G; + if (is_o) FLOW_O = dt * MOBILITY_UP_O * PSI_O; + if (is_w) FLOW_W = dt * MOBILITY_UP_W * PSI_W; + + if (is_g && is_o) + FLOW_G += FLOW_O * GOR_UP_O; + } + + void + fill_rhs (index_t i_cell, index_t j_cell) + { + if (is_g) + { + rhs_ [i_cell * n_phases + gas_idx] += -FLOW_G; + rhs_ [j_cell * n_phases + gas_idx] -= -FLOW_G; + } + if (is_o) + { + rhs_ [i_cell * n_phases + oil_idx] += -FLOW_O; + rhs_ [j_cell * n_phases + oil_idx] -= -FLOW_O; + } + if (is_w) + { + rhs_ [i_cell * n_phases + wat_idx] += -FLOW_W; + rhs_ [j_cell * n_phases + wat_idx] -= -FLOW_W; + } + } + + inline item_t + wat_sw_deriv (index_t k_cell, main_var_type main_var, item_t truns) + { + return MOBILITY_UP_W * truns * S_DERIV_CAP_PRESSURE_K_W; + } + inline item_t + wat_sw_deriv_up () + { + return SW_DERIV_MOBILITY_UP_W * PSI_W; + } + inline item_t + wat_po_deriv (index_t k_cell, main_var_type main_var, item_t truns) + { + return MOBILITY_UP_W * truns; + } + inline item_t + wat_po_deriv_up () + { + return P_DERIV_MOBILITY_UP_W * PSI_W; + } + inline item_t + wat_sg_deriv_up () + { + return SW_DERIV_MOBILITY_UP_G * PSI_W; + } + inline item_t + wat_so_deriv_up () + { + return SW_DERIV_MOBILITY_UP_O * PSI_W; + } + + inline item_t + gas_sw_deriv_up () + { + return SG_DERIV_MOBILITY_UP_W * PSI_G; + } + inline item_t + gas_po_deriv (index_t k_cell, main_var_type main_var, item_t truns) + { + return MOBILITY_UP_G * truns; + } + inline item_t + gas_po_deriv_up () + { + return P_DERIV_MOBILITY_UP_G * PSI_G; + } + inline item_t + gas_sg_deriv (index_t k_cell, main_var_type main_var, item_t truns) + { + return main_var == FI_SG_VAR ? MOBILITY_UP_G * truns * S_DERIV_CAP_PRESSURE_K_G : 0; + } + inline item_t + gas_sg_deriv_up () + { + return MAIN_VAR_UP_G == FI_SG_VAR ? SG_DERIV_MOBILITY_UP_G * PSI_G : 0; + } + inline item_t + gas_so_deriv_up () + { + return SG_DERIV_MOBILITY_UP_O * PSI_G; + } + + inline item_t + oil_sw_deriv_up () + { + return SO_DERIV_MOBILITY_UP_W * PSI_O; + } + inline item_t + oil_po_deriv (index_t k_cell, main_var_type main_var, item_t truns) + { + return MOBILITY_UP_O * truns; + } + inline item_t + oil_po_deriv_up () + { + return P_DERIV_MOBILITY_UP_O * PSI_O; + } + inline item_t + oil_sg_deriv_up () + { + return MAIN_VAR_UP_O == FI_SG_VAR ? (SO_DERIV_MOBILITY_UP_G * PSI_O) : (data_[UP_CELL_O].gor_deriv_invers_visc_fvf * data_[UP_CELL_O].relative_perm[d_o] * PSI_O); + } + inline item_t + oil_so_deriv_up () + { + return SO_DERIV_MOBILITY_UP_O * PSI_O; + } + + /** + * \brief compute derivatives for k cell + * \detail + * ps [p3_gas] = 0; + * ps [p3_oil] = 0; + * ps [p3_wat] = wat_sw_deriv (k_cell, main_var, truns); + * + * pp [p3_gas_sg] = gas_sg_deriv (k_cell, main_var, truns); + * pp [p3_gas_so] = 0; + * pp [p3_gas_po] = gas_po_deriv (k_cell, main_var, truns); + * + * pp [p3_oil_sg] = 0; + * pp [p3_oil_so] = 0; + * pp [p3_oil_po] = oil_po_deriv (k_cell, main_var, truns); + * + * pp [p3_wat_sg] = 0; + * pp [p3_wat_so] = 0; + * pp [p3_wat_po] = wat_po_deriv (k_cell, main_var, truns); + * + * pp [p3_gas_sg] += GOR_UP_O * pp [p3_oil_sg]; + * pp [p3_gas_so] += GOR_UP_O * pp [p3_oil_so]; + * pp [p3_gas_po] += GOR_UP_O * pp [p3_oil_po]; + * ps [p3_gas] += GOR_UP_O * ps [p3_oil]; + * */ + void + compute_k_derivs (index_t k, index_t k_cell, main_var_type main_var, item_t truns, index_t i_cell, index_t j_cell) + { + assign (pp, 0); + + // if one phase and phase is gas + if (is_g && !is_1p) pp [gas_sg] = gas_sg_deriv (k_cell, main_var, truns); + if (is_g) pp [gas_po] = gas_po_deriv (k_cell, main_var, truns); + if (is_o) pp [oil_po] = oil_po_deriv (k_cell, main_var, truns); + if (is_w) pp [wat_po] = wat_po_deriv (k_cell, main_var, truns); + if (is_w && !is_1p) pp [wat_sw] = wat_sw_deriv (k_cell, main_var, truns); + + if (is_g && is_o) pp [gas_po] += GOR_UP_O * pp [oil_po]; + + if (!is_1p) + { + const rhs_item_t *sp = &sp_diag_ [k_cell * n_phases]; + const item_t sr = s_rhs_ [k_cell]; + rhs_item_t *ri = &rhs_ [i_cell * n_phases]; + rhs_item_t *rj = &rhs_ [j_cell * n_phases]; + + m_minus_vv_prod ::eliminate (&pp[b_sqr], sp, pp); + v_minus_vs_prod ::eliminate (&pp[b_sqr], sr, ri); + v_minus_vs_prod ::eliminate (&pp[b_sqr], -sr, rj); + } + fill_jacobian_k_derivs (k); + } + + void + compute_up_derivs (const double &dt, index_t i_cell, index_t j_cell) + { + if (is_g && !is_1p) pp [gas_sg] = dt * gas_sg_deriv_up (); + if (is_g && !is_1p) pp [gas_so] = dt * gas_so_deriv_up (); + if (is_g) pp [gas_po] = dt * gas_po_deriv_up (); + + if (is_o && is_g) pp [oil_sg] = dt * oil_sg_deriv_up (); + if (is_o && !is_1p) pp [oil_so] = dt * oil_so_deriv_up (); + if (is_o) pp [oil_po] = dt * oil_po_deriv_up (); + + if (is_w && is_g) pp [wat_sg] = dt * wat_sg_deriv_up (); + if (is_w && is_o) pp [wat_so] = dt * wat_so_deriv_up (); + if (is_w) pp [wat_po] = dt * wat_po_deriv_up (); + + if (is_g && is_w) pp [gas_sw] = dt * gas_sw_deriv_up (); + if (is_o && is_w) pp [oil_sw] = dt * oil_sw_deriv_up (); + if (is_w && !is_1p) pp [wat_sw] = dt * wat_sw_deriv_up (); + + if (!is_1p) + eliminate (i_cell, j_cell); + + fill_jacobian (); + + if (is_g && is_o) + { + pp [gas_sg] = GOR_UP_O * dt * oil_sg_deriv_up (); + pp [gas_so] = GOR_UP_O * dt * oil_so_deriv_up (); + pp [gas_po] = GOR_UP_O * dt * oil_po_deriv_up (); + pp [gas_sw] = GOR_UP_O * pp [oil_sw]; + + if (MAIN_VAR_UP_O == FI_SG_VAR) + { + pp [gas_po] += P_DERIV_GOR_UP_O * FLOW_O; + } + else + { + pp [gas_sg] += FLOW_O; + } + + BS_ASSERT (gas_sg == 0) ((int)gas_sg); + BS_ASSERT (p3_gas == 0) ((int)p3_gas); + + if (!is_1p) + { + const rhs_item_t *sp_o = &sp_diag_ [UP_CELL_O * n_phases]; + pp [gas_idx * n_phases + 0] -= pp [gas_sw] * sp_o [0]; + pp [gas_idx * n_phases + 1] -= pp [gas_sw] * sp_o [1]; + pp [gas_idx * n_phases + 2] -= pp [gas_sw] * sp_o [2]; + + rhs_ [i_cell * n_phases + gas_idx] -= pp [gas_sw] * s_rhs_ [UP_CELL_O]; + rhs_ [j_cell * n_phases + gas_idx] += pp [gas_sw] * s_rhs_ [UP_CELL_O]; + } + + for (index_t i = 0; i < n_phases; ++i) + { + reg_values_ [i + m_mem[UP_O] * b_sqr + gas_idx * n_phases] += pp[i + gas_idx * n_phases]; + reg_values_ [i + p_mem[UP_O] * b_sqr + gas_idx * n_phases] -= pp[i + gas_idx * n_phases]; + } + } + } + + void eliminate (index_t i_cell, index_t j_cell) + { + BS_ASSERT (!is_1p); + if (is_g) + { + const rhs_item_t *sp_g = &sp_diag_ [UP_CELL_G * n_phases]; + if (n_phases > 0) pp [gas_idx * n_phases + 0] -= pp [gas_sw] * sp_g [0]; + if (n_phases > 1) pp [gas_idx * n_phases + 1] -= pp [gas_sw] * sp_g [1]; + if (n_phases > 2) pp [gas_idx * n_phases + 2] -= pp [gas_sw] * sp_g [2]; + } + + if (is_o) + { + const rhs_item_t *sp_o = &sp_diag_ [UP_CELL_O * n_phases]; + if (n_phases > 0) pp [oil_idx * n_phases + 0] -= pp [oil_sw] * sp_o [0]; + if (n_phases > 1) pp [oil_idx * n_phases + 1] -= pp [oil_sw] * sp_o [1]; + if (n_phases > 2) pp [oil_idx * n_phases + 2] -= pp [oil_sw] * sp_o [2]; + } + + if (is_w) + { + const rhs_item_t *sp_w = &sp_diag_ [UP_CELL_W * n_phases]; + if (n_phases > 0) pp [wat_idx * n_phases + 0] -= pp [wat_sw] * sp_w [0]; + if (n_phases > 1) pp [wat_idx * n_phases + 1] -= pp [wat_sw] * sp_w [1]; + if (n_phases > 2) pp [wat_idx * n_phases + 2] -= pp [wat_sw] * sp_w [2]; + } + + if (is_g) rhs_ [i_cell * n_phases + gas_idx] -= pp [gas_sw] * s_rhs_ [UP_CELL_G]; + if (is_o) rhs_ [i_cell * n_phases + oil_idx] -= pp [oil_sw] * s_rhs_ [UP_CELL_O]; + if (is_w) rhs_ [i_cell * n_phases + wat_idx] -= pp [wat_sw] * s_rhs_ [UP_CELL_W]; + + if (is_g) rhs_ [j_cell * n_phases + gas_idx] += pp [gas_sw] * s_rhs_ [UP_CELL_G]; + if (is_o) rhs_ [j_cell * n_phases + oil_idx] += pp [oil_sw] * s_rhs_ [UP_CELL_O]; + if (is_w) rhs_ [j_cell * n_phases + wat_idx] += pp [wat_sw] * s_rhs_ [UP_CELL_W]; + } + + void + fill_jacobian () + { + for (index_t i = 0; i < n_phases; ++i) + { + if (is_g) reg_values_ [i + m_mem[UP_G] * b_sqr + gas_idx * n_phases] += pp[i + gas_idx * n_phases]; + if (is_o) reg_values_ [i + m_mem[UP_O] * b_sqr + oil_idx * n_phases] += pp[i + oil_idx * n_phases]; + if (is_w) reg_values_ [i + m_mem[UP_W] * b_sqr + wat_idx * n_phases] += pp[i + wat_idx * n_phases]; + + if (is_g) reg_values_ [i + p_mem[UP_G] * b_sqr + gas_idx * n_phases] -= pp[i + gas_idx * n_phases]; + if (is_o) reg_values_ [i + p_mem[UP_O] * b_sqr + oil_idx * n_phases] -= pp[i + oil_idx * n_phases]; + if (is_w) reg_values_ [i + p_mem[UP_W] * b_sqr + wat_idx * n_phases] -= pp[i + wat_idx * n_phases]; + } + } + + // Salimgareeva EM, 1.07.09 + + + struct cfl_info + { + rhs_item_array_t f11_i; + rhs_item_array_t f12_i; + rhs_item_array_t f21_i; + rhs_item_array_t f22_i; + + cfl_info (index_t n_elems) + { + f11_i.assign (n_elems, 0.0f); + f12_i.assign (n_elems, 0.0f); + f21_i.assign (n_elems, 0.0f); + f22_i.assign (n_elems, 0.0f); + } + + void clear (index_t n_elems) + { + f11_i.assign (n_elems, 0.0f); + f12_i.assign (n_elems, 0.0f); + f21_i.assign (n_elems, 0.0f); + f22_i.assign (n_elems, 0.0f); + } + rhs_item_t calc_F_i (item_t dt, item_t i) + { + return dt*fabs(0.5*(f11_i[i]+f22_i[i]+sqrt((f11_i[i]+f22_i[i])*(f11_i[i]+f22_i[i])-4*(f11_i[i]*f22_i[i]-f12_i[i]*f21_i[i])))); + } + }; + + + void + fill_cfl (cfl_info &f, const rhs_item_t *truns, index_t i_cell, index_t j_cell, rhs_item_array_t &cfl, item_array_t &saturation_3p) + { + + int k; + index_t i, j, k_cell; + const data_t &data_ic = data_[i_cell]; + const data_t &data_jc = data_[j_cell]; + + item_t mobility_tot = 0; + if (is_g) mobility_tot += MOBILITY_UP_G; + if (is_o) mobility_tot += MOBILITY_UP_O; + if (is_w) mobility_tot += MOBILITY_UP_W; + + item_t p_cwoi_deriv = data_[i_cell].s_deriv_cap_pressure[ds_w]; + item_t p_cwoj_deriv = data_[j_cell].s_deriv_cap_pressure[ds_w]; + item_t p_cgoi_deriv = 0; + item_t p_cgoj_deriv = 0; + item_t p_cwoi = data_[i_cell].cap_pressure[ds_w]; + item_t p_cwoj = data_[j_cell].cap_pressure[ds_w]; + item_t p_cgoi = 0; + item_t p_cgoj = 0; + + + if (is_g == 1) + { + p_cgoi_deriv = data_[i_cell].s_deriv_cap_pressure[ds_g]; + p_cgoj_deriv = data_[j_cell].s_deriv_cap_pressure[ds_g]; + p_cgoi = data_[i_cell].cap_pressure[ds_g]; + p_cgoj = data_[j_cell].cap_pressure[ds_g]; + } + + + item_t delta_psi_w = fabs(psi_[d_w]); + item_t delta_psi_o = fabs(psi_[d_o]); + + item_t delta_psi_g; + if (is_g == 1) delta_psi_g = fabs(psi_[d_g]); + + + if (is_g == 0) + { + f.f11_i[i_cell] += /*truns[i_cell]*/(MOBILITY_UP_O*SW_DERIV_MOBILITY_UP_W*delta_psi_w + - MOBILITY_UP_W*SW_DERIV_MOBILITY_UP_O*delta_psi_o - truns[0]*MOBILITY_UP_W*MOBILITY_UP_O + *(p_cwoi_deriv + p_cwoj_deriv))/mobility_tot; + + f.f11_i[j_cell] = f.f11_i[i_cell]; + } + else + { + f.f11_i[i_cell] += /*truns[i_cell]*/((MOBILITY_UP_G + MOBILITY_UP_O)*SW_DERIV_MOBILITY_UP_W*delta_psi_w + - MOBILITY_UP_W*SW_DERIV_MOBILITY_UP_O*delta_psi_o - truns[0]*MOBILITY_UP_W*(MOBILITY_UP_G + MOBILITY_UP_O) + *(p_cwoi_deriv + p_cwoj_deriv))/mobility_tot; + + f.f11_i[j_cell] = f.f11_i[i_cell]; + } + + if (is_g == 0) + { + f.f12_i[i_cell] = 0; + f.f12_i[j_cell] = f.f12_i[i_cell]; + } + + else + { + f.f12_i[i_cell] += -/*truns[i_cell]*/((MOBILITY_UP_W*SG_DERIV_MOBILITY_UP_O*delta_psi_o) + MOBILITY_UP_W*SG_DERIV_MOBILITY_UP_G + *delta_psi_g-(MOBILITY_UP_O + MOBILITY_UP_G)*SG_DERIV_MOBILITY_UP_W*delta_psi_w + truns[0]*MOBILITY_UP_W*MOBILITY_UP_G + *(p_cgoi_deriv + p_cgoj_deriv))/mobility_tot; + + f.f12_i[j_cell] = f.f12_i[i_cell]; + } + + if (is_g == 0) + { + f.f21_i[i_cell] = 0; + f.f21_i[j_cell] = f.f21_i[i_cell]; + } + + else + { + f.f21_i[i_cell] += -/*truns[i_cell]*/((MOBILITY_UP_G*SW_DERIV_MOBILITY_UP_W)*delta_psi_w + MOBILITY_UP_G*SW_DERIV_MOBILITY_UP_O + *delta_psi_o - truns[0]*MOBILITY_UP_G*MOBILITY_UP_W*(p_cgoi_deriv + p_cgoj_deriv))/mobility_tot; + + f.f21_i[j_cell] = f.f21_i[i_cell];//((MOBILITY_UP_G*SW_DERIV_MOBILITY_UP_W)*delta_psi_w + MOBILITY_UP_G*SW_DERIV_MOBILITY_UP_O + //*delta_psi_o - truns[1]*MOBILITY_UP_G*MOBILITY_UP_W*(p_cgoi_deriv + p_cgoj_deriv))/mobility_tot; + } + + if (is_g == 0) + { + f.f22_i[i_cell] = 0; + f.f22_i[j_cell] = f.f22_i[i_cell]; + } + + else + { + f.f22_i[i_cell] += /*truns[i_cell]*/(-MOBILITY_UP_G*SG_DERIV_MOBILITY_UP_O*delta_psi_o + (MOBILITY_UP_W + MOBILITY_UP_O) + *SG_DERIV_MOBILITY_UP_G*delta_psi_g - MOBILITY_UP_G*SG_DERIV_MOBILITY_UP_W*delta_psi_w + + truns[0]*MOBILITY_UP_G*(MOBILITY_UP_O + MOBILITY_UP_W)*(p_cgoi_deriv + p_cgoj_deriv))/mobility_tot; + + f.f22_i[j_cell] = f.f22_i[i_cell]; + } + + // check addition condition + if (fabs (saturation_3p[i_cell * n_phases + d_w] - saturation_3p[j_cell * n_phases + d_w]) > 0.0001 || + fabs (saturation_3p[i_cell * n_phases + d_o] - saturation_3p[j_cell * n_phases + d_o]) > 0.0001) + { + cfl[i_cell] = UNKNOWN; + cfl[j_cell] = UNKNOWN; + } + } + + public: + + boost::array pp; + + index_t d_w; + index_t d_g; + index_t d_o; + index_t ds_w; + index_t ds_g; + const item_array_t &saturation_3p_; + const item_array_t &pressure_; + const item_array_t &gas_oil_ratio_; + const main_var_array_t &main_vars_; + const data_array_t &data_; + const item_array_t &depths_; + item_t gravity_; + index_t n_sec_vars; + + const rhs_item_array_t &sp_diag_; + const rhs_item_array_t &s_rhs_; + rhs_item_array_t ®_values_; + rhs_item_array_t &rhs_; + + boost::array rho_; + boost::array psi_; + boost::array up_; + boost::array up_cell_; + boost::array flow_; + + const index_t *m_mem; + const index_t *p_mem; + + item_t depth_top; + item_t sw_deriv_mobility_up_w; + item_t sw_deriv_mobility_up_g; + item_t sw_deriv_mobility_up_o; + item_t sg_deriv_mobility_up_w; + item_t sg_deriv_mobility_up_g; + item_t sg_deriv_mobility_up_o; + item_t so_deriv_mobility_up_w; + item_t so_deriv_mobility_up_g; + item_t so_deriv_mobility_up_o; + item_t p_deriv_mobility_up_w; + item_t p_deriv_mobility_up_g; + item_t p_deriv_mobility_up_o; + item_t mobility_up_w; + item_t mobility_up_g; + item_t mobility_up_o; + item_t gor_up_o; + item_t p_deriv_gor_up_o; + main_var_type main_var_up_g; + main_var_type main_var_up_o; + const sp_mesh_iface_t &mesh_; + }; + + template + void + block_connections_mpfa (typename mpfa_t::item_t dt, fi_operator_t &fi_operator, mpfa_t mpfa_) + { + typedef typename mpfa_t::index_t index_t; + typedef typename mpfa_t::item_t item_t; + typedef typename mpfa_t::rhs_item_t rhs_item_t; + typedef typename mpfa_t::item_array_t item_array_t; + + typedef rs_mesh_iface mesh_iface_t; + typedef smart_ptr sp_mesh_iface_t; + typedef rs_smesh_iface rs_smesh_iface_t; + +#ifdef BS_BOS_CORE_USE_CSR_ILU_CFL_PREC + index_t n_active_cells = fi_operator.n_cells_; + bool use_cfl = fi_operator.calc_model_->ts_params->get_bool (fi_params::USE_CFL); + static typename mpfa_t::cfl_info cfl (n_active_cells); + + if (use_cfl) + { + cfl.clear (n_active_cells); + assign (fi_operator.cfl_, n_active_cells, 0); + } +#endif + + // trns: rows - number of cell = row, cols are indies neigh. cells + // cycle by connections + for (index_t con = 0; con < fi_operator.n_connections_; ++con) + { + const index_t row[] = {fi_operator.trns_rows_ptr_[con], fi_operator.trns_rows_ptr_[con + 1]}; + BS_ASSERT (row[1] - row[0] >= 2) (row[0]) (row[1]); + + const index_t *cells = &fi_operator.trns_cols_ptr_[row[0]]; + const rhs_item_t *truns = &fi_operator.trns_values_[row[0]]; + + index_t i = cells[0]; + index_t j = cells[1]; + + mpfa_.m_mem = &fi_operator.m_array_[row[0]]; + mpfa_.p_mem = &fi_operator.p_array_[row[0]]; + + mpfa_.compute_rho (cells, row[1] - row[0]); + mpfa_.compute_psi (truns, cells, row[1] - row[0]); + mpfa_.compute_upstream (0, 1, i, j); + mpfa_.compute_flow (dt); + + mpfa_.fill_rhs (i, j); + + for (index_t k = 0, kcnt = row[1] - row[0]; k < kcnt; ++k) + { + mpfa_.compute_k_derivs (k, cells[k], fi_operator.main_vars_[cells[k]], dt * truns [k], i, j); + } + + mpfa_.compute_up_derivs (dt, i, j); + + +#ifdef BS_BOS_CORE_USE_CSR_ILU_CFL_PREC + if (use_cfl) + { + // count cfl vector, needs for ACPR + mpfa_.fill_cfl (cfl, truns, i, j, fi_operator.cfl_, fi_operator.saturation_3p_); + } +#endif + } + +#ifdef BS_BOS_CORE_USE_CSR_ILU_CFL_PREC + if (use_cfl) + { + for (index_t k = 0; k < n_active_cells; ++k) + { + if (fi_operator.cfl_[k] == UNKNOWN) + { + fi_operator.cfl_[k] = cfl.calc_F_i (dt, k) / fi_operator.volume_[k]; + } + else + fi_operator.cfl_[k] = IS_STABLE; + } + } +#endif + } + } // namespace mpfa + + template + bool + fi_operator_impl ::block_connections_mpfa (const item_t &dt) + { + mpfa::block_connections_mpfa (dt, *this, mpfa::mpfa_base_impl (*this, flux_rhs_, reg_values_)); + + //if (n_phases == 3) + // { + // mpfa::block_connections_mpfa (dt, *this, mpfa::mpfa_base_impl (*this, flux_rhs_, reg_values_)); + // } + //else if (is_w && is_o) + // { + // mpfa::block_connections_mpfa (dt, *this, mpfa::mpfa_base_impl (*this, rhs_, reg_values_)); + // } + //else if (is_g && is_o) + // { + // mpfa::block_connections_mpfa (dt, *this, mpfa::mpfa_base_impl (*this, rhs_, reg_values_)); + // } + //else if (is_w) + // { + // mpfa::block_connections_mpfa (dt, *this, mpfa::mpfa_base_impl (*this, rhs_, reg_values_)); + // } + //else if (is_g) + // { + // mpfa::block_connections_mpfa (dt, *this, mpfa::mpfa_base_impl (*this, rhs_, reg_values_)); + // } + //else if (is_o) + // { + // mpfa::block_connections_mpfa (dt, *this, mpfa::mpfa_base_impl (*this, rhs_, reg_values_)); + // } + //else + // { + // throw bs_exception ("block_connections_mpfa", "unknown phase value"); + // } + + return false; + } + + + +} // namespace blue_sky + + + +#endif // BS_FI_OPERATOR_BLOCK_CONNECTION_MPFA_2_H_ + diff --git a/bs_bos_core/include/fi_operator_calc_porosity_and_deriv.h b/bs_bos_core/include/fi_operator_calc_porosity_and_deriv.h new file mode 100644 index 0000000..d891656 --- /dev/null +++ b/bs_bos_core/include/fi_operator_calc_porosity_and_deriv.h @@ -0,0 +1,66 @@ +/** + * \file fi_operator_calc_porosity_and_deriv.h + * \brief calculate porosity and derivativies, also calculate trunsmissibility multiplier + * \author Sergey Miryanov + * \date 23.01.2009 + * */ +#ifndef BS_FI_OPERATOR_CALC_POROSITY_AND_DERIV_H_ +#define BS_FI_OPERATOR_CALC_POROSITY_AND_DERIV_H_ + +namespace blue_sky { + + /** + * @brief calculate porosity and derivativies, also calculate trunsmissibility multiplier + * + * @param i -- cell index + * @param pvt_reg -- PVT region index + * @param poro -- porosity + * @param dp_poro -- porosity derivative + * @param t_mult -- trunsmissibility multiplier + * @param dp_t_mult -- trunsmissibility multiplier derivative + */ + template + BS_FORCE_INLINE void + fi_operator_impl ::calc_porosity_and_deriv (index_t i, + index_t pvt_reg, + item_t *poro, + item_t *dp_poro, + item_t *t_mult, + item_t *dp_t_mult) + { + // if ROCKTAB keyword specified use it + if (calc_model_->rocktab.size ()) // use rocktab + { + item_t phi_m = 0, d_phi_m = 0; + + // get region + index_t reg = calc_model_->rock_regions[i]; + // interpolate + calc_model_->rocktab[reg].interpolate (pressure_[i], &phi_m, &d_phi_m, t_mult, dp_t_mult); + // calculate porosity + *poro = poro_array_[i] * phi_m; + if (*poro > 1) + { + *poro = 1; + } + // calculate porosity derivative + *dp_poro = poro_array_[i] * d_phi_m; + } + else // use compressibility to calculate porosity + { + // calculate porisity and derivate + item_t d = rock_grid_comp_const_[pvt_reg] * (pressure_[i] - rock_grid_comp_ref_pressure_[pvt_reg]); + + //*poro = rock_grid_prop.porosity_p_ref[i] * (1.0 + d + d * d * 0.5); + //*dp_poro = rock_grid_prop.porosity_p_ref[i] * rock_grid_prop.comp_const[pvt_reg] * (1.0 + d); + *poro = poro_array_[i] * (1.0 + d); + *dp_poro = poro_array_[i] * rock_grid_comp_const_[pvt_reg]; + *t_mult = 1.0; + *dp_t_mult = 0.0; + } + } + +} // namespace blue_sky + +#endif // #ifndef BS_FI_OPERATOR_CALC_POROSITY_AND_DERIV_H_ + diff --git a/bs_bos_core/include/fi_operator_calc_prev_fluid_volume.h b/bs_bos_core/include/fi_operator_calc_prev_fluid_volume.h new file mode 100644 index 0000000..cbbe5fe --- /dev/null +++ b/bs_bos_core/include/fi_operator_calc_prev_fluid_volume.h @@ -0,0 +1,79 @@ +/** + * \file fi_operator_calc_prev_fluid_volume.h + * \brief + * \author Sergey Miryanov + * \date 23.01.2009 + * */ +#ifndef BS_FI_OPERATOR_CALC_PREV_FLUID_VOLUME_H_ +#define BS_FI_OPERATOR_CALC_PREV_FLUID_VOLUME_H_ + +namespace blue_sky { + + template + BS_FORCE_INLINE void + fi_operator_impl ::calc_prev_fluid_volume () + { + BS_ASSERT (calc_model_->phase_d[FI_PHASE_WATER] == calc_model_->sat_d[FI_PHASE_WATER]) (calc_model_->phase_d[FI_PHASE_WATER]) (calc_model_->sat_d[FI_PHASE_WATER]); + BS_ASSERT (calc_model_->phase_d[FI_PHASE_GAS] == calc_model_->sat_d[FI_PHASE_GAS]) (calc_model_->phase_d[FI_PHASE_GAS]) (calc_model_->sat_d[FI_PHASE_GAS]); + + for (index_t i = 0; i < n_cells_; ++i) + { + index_t i_w = FI_PH_IND (i, d_w, n_phases); + index_t i_g = FI_PH_IND (i, d_g, n_phases); + index_t i_o = FI_PH_IND (i, d_o, n_phases); + + item_t sat_w = 0.0, sat_g = 0.0, sat_o = 0.0; + // set up saturation + if (is_w && n_phases > 1) + sat_w = saturation_3p_[i_w]; + if (is_g && n_phases > 1) + sat_g = saturation_3p_[i_g]; + + if (is_o && n_phases > 1) + sat_o = saturation_3p_[i_o]; +#if 0 + if (is_o) + { + if (is_g && is_w) + sat_o = 1.0 - sat_w - sat_g; + else if (is_g) + sat_o = 1.0 - sat_g; + else if (is_w) + sat_o = 1.0 - sat_w; + } +#endif //0 + + if (is_o) + { + if (n_phases > 1) + data_[i].prev_fluid_volume[d_o] = data_[i].porosity * data_[i].invers_fvf[d_o] * sat_o; + else + data_[i].prev_fluid_volume[d_o] = data_[i].porosity * data_[i].invers_fvf[d_o]; + } + + if (is_w) + { + if (n_phases > 1) + data_[i].prev_fluid_volume[d_w] = data_[i].porosity * data_[i].invers_fvf[d_w] * sat_w; + else + data_[i].prev_fluid_volume[d_w] = data_[i].porosity * data_[i].invers_fvf[d_w]; + } + + if (is_g) + { + if (is_o) + { + data_[i].prev_fluid_volume[d_g] = data_[i].porosity * gas_oil_ratio_[i] * sat_o * data_[i].invers_fvf[d_o]; + if (FI_CHK_SG (main_vars_, i)) + data_[i].prev_fluid_volume[d_g] += data_[i].porosity * data_[i].invers_fvf[d_g] * sat_g; + } + else + data_[i].prev_fluid_volume[d_g] = data_[i].porosity * data_[i].invers_fvf[d_g]; + } + } + } + +} // namespace blue_sky + +#endif // #ifndef BS_FI_OPERATOR_CALC_PREV_FLUID_VOLUME_H_ + diff --git a/bs_bos_core/include/fi_operator_calc_solution_mult_cell.h b/bs_bos_core/include/fi_operator_calc_solution_mult_cell.h new file mode 100644 index 0000000..52e0fb3 --- /dev/null +++ b/bs_bos_core/include/fi_operator_calc_solution_mult_cell.h @@ -0,0 +1,42 @@ +/** + * \file fi_operator_calc_solution_mult_cell.h + * \brief calculate multiplier for solution + * \author Sergey Miryanov + * \date 08.02.2009 + * */ +#ifndef BS_FI_OPERATOR_CALC_SOLUTION_MULT_CELL_H_ +#define BS_FI_OPERATOR_CALC_SOLUTION_MULT_CELL_H_ + +namespace blue_sky { + + template + BS_FORCE_INLINE typename strategy_t::item_t + fi_operator_impl ::calc_solution_mult_cell (const norms_storage_t &old_norm) + { + item_t d = 0.0; + item_t mult = 0.0; + const static item_t eps = item_t (1.0e-8); + norms_storage_t norm; + + for (index_t id = norms::C_ACPV_GAS; id <= norms::C_ACPV_OIL; ++id) + { + norm.clear (); + update_norm_by_cell (old_norm.idx[id], norm); + norm.val[id] /= calc_model_->ave_volume; + + item_t abs_old = fabs (old_norm.val[id]); + item_t abs_new = fabs (norm.val[id]); + if ((old_norm.val[id] * norm.val[id]) < -eps || (abs_old > abs_new)) + { + mult += abs_new * abs_old / fabs (old_norm.val[id] - norm.val[id]); + d += abs_new; + } + } + + return (d > eps) ? mult / d : 1.0; + } +} + + +#endif // #ifndef BS_FI_OPERATOR_CALC_SOLUTION_MULT_CELL_H_ + diff --git a/bs_bos_core/include/fi_operator_calc_step_dt_mult.h b/bs_bos_core/include/fi_operator_calc_step_dt_mult.h new file mode 100644 index 0000000..3c1ff5c --- /dev/null +++ b/bs_bos_core/include/fi_operator_calc_step_dt_mult.h @@ -0,0 +1,119 @@ +/** + * \file calc_step_dt_mult.h + * \brief + * \author Sergey Miryanov + * \date 23.01.2009 + * */ +#ifndef BS_FI_OPERATOR_CALC_STEP_DT_MULT_H_ +#define BS_FI_OPERATOR_CALC_STEP_DT_MULT_H_ + +namespace blue_sky { + + template + BS_FORCE_INLINE typename strategy_t::item_t + fi_operator_impl ::calc_step_dt_mult (item_t prev_mult, item_t max_res) + { + item_t coef = 1.0, m_r, d, d_mult; + index_t i; + index_t equ_w, equ_g, equ_o; +#ifdef _MPI + index_t n_left = 0;///mpi_decomp->get_recv_l (); + index_t n_own = 0;///mpi_decomp->get_n_local_own () + n_left; + item_t mpi_coef; +#endif //_MPI + + +#ifdef _MPI + for (i = n_left; i < n_own; ++i) +#else //_MPI + for (i = 0; i < n_cells_; ++i) +#endif //_MPI + { + if (n_phases == 3) + { + equ_w = i * n_phases + p3_wat; + equ_g = i * n_phases + p3_gas; + equ_o = i * n_phases + p3_oil; + } + else if (n_phases == 2 && is_w) + { + equ_w = i * n_phases + p2ow_wat; + equ_o = i * n_phases + p2ow_oil; + } + else if (n_phases == 2 && is_g) + { + equ_g = i * n_phases + p2og_gas; + equ_o = i * n_phases + p2og_oil; + } + else + { + equ_g = equ_w = equ_o = i * n_phases + 0; + } +#ifdef _MPI + equ_w -= n_phases * n_left; + equ_g -= n_phases * n_left; + equ_o -= n_phases * n_left; +#endif //_MPI + d_mult = (calc_model_->ave_volume * data_[i].porosity); + if (is_w) + { + m_r = max_res * d_mult * calc_model_->invers_fvf_average[d_w]; + if (rhs_[equ_w] * flux_rhs_[equ_w] <= EPS_DIV + && fabs (flux_rhs_[equ_w]) > fabs (rhs_[equ_w]) + && fabs (flux_rhs_[equ_w] + rhs_[equ_w]) > m_r) + { + if (flux_rhs_[equ_w] > 0) + d = (m_r - rhs_[equ_w]) / flux_rhs_[equ_w]; + else + d = -(m_r + rhs_[equ_w]) / flux_rhs_[equ_w]; + if (d < coef) + coef = d; + } + } + if (is_g) + { + m_r = max_res * d_mult * calc_model_->invers_fvf_average[d_g]; + if (rhs_[equ_g] * flux_rhs_[equ_g] <= EPS_DIV + && fabs (flux_rhs_[equ_g]) > fabs (rhs_[equ_g]) + && fabs (flux_rhs_[equ_g] + rhs_[equ_g]) > m_r) + { + if (flux_rhs_[equ_g] > 0) + d = (m_r - rhs_[equ_g]) / flux_rhs_[equ_g]; + else + d = -(m_r + rhs_[equ_g]) / flux_rhs_[equ_g]; + if (d < coef) + coef = d; + } + } + if (is_o) + { + m_r = max_res * d_mult * calc_model_->invers_fvf_average[d_o]; + if (rhs_[equ_o] * flux_rhs_[equ_o] <= EPS_DIV + && fabs (flux_rhs_[equ_o]) > fabs (rhs_[equ_o]) + && fabs (flux_rhs_[equ_o] + rhs_[equ_o]) > m_r) + { + if (flux_rhs_[equ_o] > 0) + d = (m_r - rhs_[equ_o]) / flux_rhs_[equ_o]; + else + d = -(m_r + rhs_[equ_o]) / flux_rhs_[equ_o]; + if (d < coef) + coef = d; + } + } + + } + if (coef < prev_mult) + coef = prev_mult; + +#ifdef _MPI + MPI_Allreduce (&coef, &mpi_coef, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); + coef = mpi_coef; +#endif + return coef; + } + +} + + +#endif // #ifndef BS_FI_OPERATOR_CALC_STEP_DT_MULT_H_ + diff --git a/bs_bos_core/include/fi_operator_norm_calc.h b/bs_bos_core/include/fi_operator_norm_calc.h new file mode 100644 index 0000000..8a28310 --- /dev/null +++ b/bs_bos_core/include/fi_operator_norm_calc.h @@ -0,0 +1,295 @@ +/** + * \file fi_operator_norm_calc.h + * \brief norm calculation for fi_operator + * \author Sergey Miryanov + * \date 23.01.2009 + * */ +#ifndef BS_FI_OPERATOR_NORM_CALC_H_ +#define BS_FI_OPERATOR_NORM_CALC_H_ + +namespace blue_sky { + +#define MAX_AND_INDEX(NEW,OLD,I,I_OLD) if (fabs (NEW) > fabs (OLD)) {(OLD) = (NEW); (I_OLD) = (I);} +#ifdef _MPI +struct di + { + double d; + int i; + }; +#define MPI_MAX_AND_INDEX(NEW,I,DI_OLD,DI_NEW) DI_OLD.d = fabs (NEW); DI_OLD.i = (NEW > 0) ? I : -I;\ + MPI_Allreduce (&DI_OLD, &DI_NEW, 1, MPI_DOUBLE_INT, MPI_MAXLOC, MPI_COMM_WORLD); \ + NEW = (DI_NEW.i > 0) ? DI_NEW.d : - DI_NEW.d; I = abs(DI_NEW.i); +#endif //_MPI + + /** + * @brief calculate norms + * + * @param i_start -- if ne 0 + * + * @return + */ + template + BS_FORCE_INLINE void + fi_operator_impl ::norm_calc () + { + double pv = 0; + +#ifdef _MPI + int n_left = 0;///mpi_decomp->get_recv_l (); + int n_right = n_cells_;///mpi_decomp->get_n_local_own () + n_left; + int n_offset = 0;///mpi_decomp->get_elem_own_displ () + n_left; + double mpi_l2_norm[6], mpi_mat_balance[3]; + struct di max_ind_old, max_ind_new; +#else //_MPI + int n_left = 0; + int n_right = n_cells_; +#endif //_MPI + + norm_.clear (); + for (index_t i = n_left; i < n_right; ++i) + { + // calculate total poro volume + pv += volume_[i] * data_[i].porosity; + update_norm_by_cell (i, norm_); + } + +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + // get global pv + double mpi_pv; + MPI_Allreduce (&pv, &mpi_pv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + pv = mpi_pv; + + ///TODO: MPI_TYPE check! + + // collecting l2 norms from all procs + MPI_Allreduce (&norm.val[norms::L2_CPV_WATER], &mpi_l2_norm[0], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::L2_CPV_GAS], &mpi_l2_norm[1], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::L2_CPV_OIL], &mpi_l2_norm[2], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::L2_ACPV_WATER], &mpi_l2_norm[3], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::L2_ACPV_GAS], &mpi_l2_norm[4], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::L2_ACPV_OIL], &mpi_l2_norm[5], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::MB_ERR_WATER], &mpi_mat_balance[0], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::MB_ERR_GAS], &mpi_mat_balance[1], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + MPI_Allreduce (&norm.val[norms::MB_ERR_OIL], &mpi_mat_balance[2], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + + + norm.val[norms::L2_CPV_WATER] = mpi_l2_norm[0]; + norm.val[norms::L2_CPV_GAS] = mpi_l2_norm[1]; + norm.val[norms::L2_CPV_OIL] = mpi_l2_norm[2]; + norm.val[norms::L2_ACPV_WATER] = mpi_l2_norm[3]; + norm.val[norms::L2_ACPV_GAS] = mpi_l2_norm[4]; + norm.val[norms::L2_ACPV_OIL] = mpi_l2_norm[5]; + norm.val[norms::MB_ERR_WATER] = mpi_mat_balance[0]; + norm.val[norms::MB_ERR_GAS] = mpi_mat_balance[1]; + norm.val[norms::MB_ERR_OIL] = mpi_mat_balance[2]; + + MPI_MAX_AND_INDEX (norm.val[norms::C_CPV_WATER], norm.idx[norms::C_CPV_WATER], max_ind_old, max_ind_new); + MPI_MAX_AND_INDEX (norm.val[norms::C_CPV_GAS], norm.idx[norms::C_CPV_GAS], max_ind_old, max_ind_new); + MPI_MAX_AND_INDEX (norm.val[norms::C_CPV_OIL], norm.idx[norms::C_CPV_OIL], max_ind_old, max_ind_new); + MPI_MAX_AND_INDEX (norm.val[norms::C_ACPV_WATER], norm.idx[norms::C_ACPV_WATER], max_ind_old, max_ind_new); + MPI_MAX_AND_INDEX (norm.val[norms::C_ACPV_GAS], norm.idx[norms::C_ACPV_GAS], max_ind_old, max_ind_new); + MPI_MAX_AND_INDEX (norm.val[norms::C_ACPV_OIL], norm.idx[norms::C_ACPV_OIL], max_ind_old, max_ind_new); + + ///n = mpi_decomp->get_n_elements (); +#endif //_MPI + + double n = 1.0 / double (n_cells_); + norm_.val[norms::L2_CPV_WATER] = sqrt (norm_.val[norms::L2_CPV_WATER]) * n; + norm_.val[norms::L2_CPV_GAS] = sqrt (norm_.val[norms::L2_CPV_GAS]) * n; + norm_.val[norms::L2_CPV_OIL] = sqrt (norm_.val[norms::L2_CPV_OIL]) * n; + norm_.val[norms::L2_ACPV_WATER] = sqrt (norm_.val[norms::L2_ACPV_WATER]) * n; + norm_.val[norms::L2_ACPV_GAS] = sqrt (norm_.val[norms::L2_ACPV_GAS]) * n; + norm_.val[norms::L2_ACPV_OIL] = sqrt (norm_.val[norms::L2_ACPV_OIL]) * n; + + // C_CPV and + if (is_w) + { + MAX_AND_INDEX (norm_.val[norms::C_CPV_WATER], norm_.val[norms::C_CPV], + norm_.idx[norms::C_CPV_WATER], norm_.idx[norms::C_CPV]); + norm_.val[norms::C_ACPV_WATER] /= calc_model_->ave_volume; + + MAX_AND_INDEX (norm_.val[norms::C_ACPV_WATER], norm_.val[norms::C_ACPV], + norm_.idx[norms::C_ACPV_WATER], norm_.idx[norms::C_ACPV]); + + MAX_AND_INDEX (norm_.val[norms::L2_CPV_WATER], norm_.val[norms::L2_CPV], + norm_.idx[norms::L2_CPV_WATER], norm_.idx[norms::L2_CPV]); + + MAX_AND_INDEX (norm_.val[norms::L2_ACPV_WATER], norm_.val[norms::L2_ACPV], + norm_.idx[norms::L2_ACPV_WATER], norm_.idx[norms::L2_ACPV]); + + norm_.val[norms::MB_ERR_WATER] /= pv * calc_model_->invers_fvf_average[d_w]; + MAX_AND_INDEX (norm_.val[norms::MB_ERR_WATER], norm_.val[norms::MB_ERR], + norm_.idx[norms::MB_ERR_WATER], norm_.idx[norms::MB_ERR]); + } + if (is_o) + { + MAX_AND_INDEX (norm_.val[norms::C_CPV_OIL], norm_.val[norms::C_CPV], + norm_.idx[norms::C_CPV_OIL], norm_.idx[norms::C_CPV]); + norm_.val[norms::C_ACPV_OIL] /= calc_model_->ave_volume; + + MAX_AND_INDEX (norm_.val[norms::C_ACPV_OIL], norm_.val[norms::C_ACPV], + norm_.idx[norms::C_ACPV_OIL], norm_.idx[norms::C_ACPV]); + + MAX_AND_INDEX (norm_.val[norms::L2_CPV_OIL], norm_.val[norms::L2_CPV], + norm_.idx[norms::L2_CPV_OIL], norm_.idx[norms::L2_CPV]); + + MAX_AND_INDEX (norm_.val[norms::L2_ACPV_OIL], norm_.val[norms::L2_ACPV], + norm_.idx[norms::L2_ACPV_OIL], norm_.idx[norms::L2_ACPV]); + + norm_.val[norms::MB_ERR_OIL] /= pv * calc_model_->invers_fvf_average[d_o]; + MAX_AND_INDEX (norm_.val[norms::MB_ERR_OIL], norm_.val[norms::MB_ERR], + norm_.idx[norms::MB_ERR_OIL], norm_.idx[norms::MB_ERR]); + + } + if (is_g) + { + MAX_AND_INDEX (norm_.val[norms::C_CPV_GAS], norm_.val[norms::C_CPV], + norm_.idx[norms::C_CPV_GAS], norm_.idx[norms::C_CPV]); + norm_.val[norms::C_ACPV_GAS] /= calc_model_->ave_volume; + + MAX_AND_INDEX (norm_.val[norms::C_ACPV_GAS], norm_.val[norms::C_ACPV], + norm_.idx[norms::C_ACPV_GAS], norm_.idx[norms::C_ACPV]); + + MAX_AND_INDEX (norm_.val[norms::L2_CPV_GAS], norm_.val[norms::L2_CPV], + norm_.idx[norms::L2_CPV_GAS], norm_.idx[norms::L2_CPV]); + + MAX_AND_INDEX (norm_.val[norms::L2_ACPV_GAS], norm_.val[norms::L2_ACPV], + norm_.idx[norms::L2_ACPV_GAS], norm_.idx[norms::L2_ACPV]); + + norm_.val[norms::MB_ERR_GAS] /= pv * calc_model_->invers_fvf_average[d_g]; + MAX_AND_INDEX (norm_.val[norms::MB_ERR_GAS], norm_.val[norms::MB_ERR], + norm_.idx[norms::MB_ERR_GAS], norm_.idx[norms::MB_ERR]); + } + + +#ifdef _MPI + if ((norm_.idx[norms::C_CPV] - n_offset >= n_left) && (norm_.idx[norms::C_CPV] - n_offset < n_right)) + { + calc_model_->max_norm_counter[norm_.idx[norms::C_CPV] - n_offset]++; + } +#else //_MPI + calc_model_->max_norm_counter[norm_.idx[norms::C_CPV]]++; +#endif //_MPI + } + + // calculate norm in one cell and update norm storage + template + BS_FORCE_INLINE void + fi_operator_impl ::update_norm_by_cell (index_t i, norms_storage_t &ns) + { + double norm_mult, r, d; + + int equ_w, equ_g, equ_o; + if (n_phases == 3) + { + equ_w = i * n_phases + p3_wat; + equ_g = i * n_phases + p3_gas; + equ_o = i * n_phases + p3_oil; + } + else if (n_phases == 2 && is_w) + { + equ_w = i * n_phases + p2ow_wat; + equ_o = i * n_phases + p2ow_oil; + } + else if (n_phases == 2 && is_g) + { + equ_g = i * n_phases + p2og_gas; + equ_o = i * n_phases + p2og_oil; + } + else + { + equ_g = equ_w = equ_o = i * n_phases + 0; + } +#ifdef _MPI + int n_left = 0;///mpi_decomp->get_recv_l (); + int n_offset = 0;///mpi_decomp->get_elem_own_displ () + n_left; + ///rhs -= n_phases * n_left; + ///flux_rhs -= n_phases * n_left; +#endif //_MPI + + // calculate multiplier + norm_mult = 1.0 / (volume_[i] * data_[i].porosity); + +#ifdef _MPI + // remember absolute (global) cell number for norms + i += n_offset; +#endif //_MPI + + // water + if (is_w) + { + r = rhs_[equ_w] + flux_rhs_[equ_w]; + + // mat balanse + ns.val[norms::MB_ERR_WATER] += r / calc_model_->invers_fvf_average[d_w]; + + // C_CPV_WATER + d = r * norm_mult / calc_model_->invers_fvf_average[d_w]; + MAX_AND_INDEX (d, ns.val[norms::C_CPV_WATER], i, ns.idx[norms::C_CPV_WATER]); + + // L2_CPV_WATER + ns.val[norms::L2_CPV_WATER] += d * d; + + // C_ACPV_WATER + d = r / data_[i].invers_fvf[d_w]; + MAX_AND_INDEX (d, ns.val[norms::C_ACPV_WATER], i, ns.idx[norms::C_ACPV_WATER]); + + // L2_ACPV_WATER + ns.val[norms::L2_ACPV_WATER] += d * d; + } + // gas + if (is_g) + { + r = rhs_[equ_g] + flux_rhs_[equ_g]; + + // mat balanse + ns.val[norms::MB_ERR_GAS] += r / calc_model_->invers_fvf_average[d_g]; + + // C_CPV_GAS + d = r * norm_mult / calc_model_->invers_fvf_average[d_g]; + MAX_AND_INDEX (d, ns.val[norms::C_CPV_GAS], i, ns.idx[norms::C_CPV_GAS]); + + // L2_CPV_GAS + ns.val[norms::L2_CPV_GAS] += d * d; + + // C_ACPV_GAS + d = r / data_[i].invers_fvf[d_g]; + MAX_AND_INDEX (d, ns.val[norms::C_ACPV_GAS], i, ns.idx[norms::C_ACPV_GAS]); + + // L2_ACPV_GAS + ns.val[norms::L2_ACPV_GAS] += d * d; + } + // oil + if (is_o) + { + r = rhs_[equ_o] + flux_rhs_[equ_o]; + + // mat balanse + ns.val[norms::MB_ERR_OIL] += r / calc_model_->invers_fvf_average[d_o]; + + // C_CPV_OIL + d = r * norm_mult / calc_model_->invers_fvf_average[d_o]; + MAX_AND_INDEX (d, ns.val[norms::C_CPV_OIL], i, ns.idx[norms::C_CPV_OIL]); + + // L2_CPV_OIL + ns.val[norms::L2_CPV_OIL] += d * d; + + // C_ACPV_OIL + d = r / data_[i].invers_fvf[d_o]; + MAX_AND_INDEX (d, ns.val[norms::C_ACPV_OIL], i, ns.idx[norms::C_ACPV_OIL]); + + // L2_ACPV_OIL + ns.val[norms::L2_ACPV_OIL] += d * d; + } + + rhs_item_array_t &s_rhs = jmatrix_->get_sec_rhs (); + for (index_t j = 0, j_cnt = n_sec_vars; j < j_cnt; ++j) + { + MAX_AND_INDEX (s_rhs[i * n_sec_vars + j], ns.val[norms::S_RHS], i, ns.idx[norms::S_RHS]); + } + } + +} // namespace blue_sky + +#endif // #ifndef BS_FI_OPERATOR_NORM_CALC_H_ diff --git a/bs_bos_core/include/fi_operator_save_debug_data.h b/bs_bos_core/include/fi_operator_save_debug_data.h new file mode 100644 index 0000000..d7f5eb9 --- /dev/null +++ b/bs_bos_core/include/fi_operator_save_debug_data.h @@ -0,0 +1,319 @@ +/** + * \file fi_operator_save_debug_data.h + * \brief save debug data on each fi_operator iteration + * \author Sergey Miryanov + * \date 03.02.2009 + * */ +#ifndef BS_FI_OPERATOR_SAVE_DEBUG_DATA_H_ +#define BS_FI_OPERATOR_SAVE_DEBUG_DATA_H_ + +#include "save_connection_data.h" +#include "string_formater.h" +#include "calc_well.h" +#include "well_iterator.h" +#include "rr_rw_wr_saver.h" +#include "well_type_helper.h" +#include "member_accessor.h" + +#define SAVE_BOOST_ARRAY(name, size_j) \ + tools::save_seq_vector (tools::string_formater (std::string (BOOST_PP_STRINGIZE(name)) + std::string (".bs.%d.txt"), iter_counter).str) \ + .save_via_fn (debug::BOOST_PP_CAT (save_, name) (calc_model_->data, size_j)); + +#define SAVE_ITEM(name) \ + tools::save_seq_vector (tools::string_formater (std::string (BOOST_PP_STRINGIZE(name)) + std::string (".bs.%d.txt"), iter_counter).str) \ + .save_via_fn (debug::BOOST_PP_CAT (save_, name) (calc_model_->data)); + +namespace blue_sky { + + namespace debug { + + template + struct ww_diveder + { + typedef typename well_t::item_t item_t; + item_t operator () (const well_t *well) const + { + return 1.0 / well->get_ww_value (); + } + }; + template + struct ww_accessor + { + typedef typename well_t::item_t item_t; + item_t operator () (const well_t *well) const + { + return well->get_ww_value (); + } + }; + template + struct bw_accessor + { + typedef typename well_t::item_t item_t; + item_t operator () (const well_t *well) const + { + return well->get_bw_value (); + } + }; + + template + struct rr + { + typedef typename connection_t::item_t item_t; + item_t operator () (const connection_t *c, size_t i) const + { + return c->get_rr_value () [i]; + }; + }; + template + struct rw + { + typedef typename connection_t::item_t item_t; + item_t operator () (const connection_t *c, size_t i) const + { + return c->get_rw_value () [i]; + }; + }; + template + struct wr + { + typedef typename connection_t::item_t item_t; + item_t operator () (const connection_t *c, size_t i) const + { + return c->get_wr_value () [i]; + }; + }; + template + struct rate + { + typedef typename connection_t::item_t item_t; + item_t operator () (const connection_t *c, size_t i) const + { + return c->get_rate_value () [i]; + } + }; + + template + struct cur_bhp + { + typedef typename connection_t::item_t item_t; + item_t operator () (const connection_t *c) const + { + return c->get_cur_bhp (); + }; + }; + template + struct density + { + typedef typename connection_t::item_t item_t; + item_t operator () (const connection_t *c) const + { + return c->density; + }; + }; + template + struct bulkp + { + typedef typename connection_t::item_t item_t; + item_t operator () (const connection_t *c) const + { + return c->bulkp; + }; + }; + +#define MEMBER_SAVER(name) \ + template \ + struct BOOST_PP_CAT (save_, name) \ + { \ + typedef item_t value_type; \ + \ + BOOST_PP_CAT (save_, name) (const data_array_t &data_, size_t size_j_) \ + : data_ (data_) \ + , size_j_ (size_j_) \ + { \ + } \ + \ + size_t \ + size_i () const \ + { \ + return data_.size (); \ + } \ + \ + size_t \ + size_j () const \ + { \ + return size_j_; \ + } \ + \ + item_t \ + get (size_t i, size_t j) const \ + { \ + return data_[i].name[j]; \ + } \ + \ + const data_array_t &data_; \ + size_t size_j_; \ + }; + +#define MEMBER_SAVER_2(name) \ + template \ + struct BOOST_PP_CAT (save_, name) \ + { \ + typedef item_t value_type; \ + \ + BOOST_PP_CAT (save_, name) (const data_array_t &data_) \ + : data_ (data_) \ + { \ + } \ + \ + size_t \ + size_i () const \ + { \ + return data_.size (); \ + } \ + \ + size_t \ + size_j () const \ + { \ + return 1; \ + } \ + \ + item_t \ + get (size_t i, size_t j) const \ + { \ + return data_[i].name; \ + } \ + \ + const data_array_t &data_; \ + }; + + MEMBER_SAVER (mobility); + MEMBER_SAVER (p_deriv_mobility); + MEMBER_SAVER (s_deriv_mobility); + MEMBER_SAVER (density); + MEMBER_SAVER (p_deriv_density); + MEMBER_SAVER (relative_perm); + MEMBER_SAVER (s_deriv_relative_perm); + MEMBER_SAVER (invers_visc_fvf); + MEMBER_SAVER (p_deriv_invers_visc_fvf); + MEMBER_SAVER (cap_pressure); + MEMBER_SAVER (s_deriv_cap_pressure); + + MEMBER_SAVER_2 (gor_deriv_invers_fvf); + MEMBER_SAVER_2 (gor_deriv_invers_viscosity); + MEMBER_SAVER_2 (gor_deriv_invers_visc_fvf); + + } + /** + * \brief debug function for output data + * \param dt current dt step + * */ + template + void + fi_operator_impl ::debug_save_data (item_t dt) + { + static int iter_counter = 0; + iter_counter++; + //int zxczxc = iter_counter; + + //tools::save_seq_vector (tools::string_formater ("rhs.bs.%d.txt", iter_counter).str).save (jmatrix_->get_rhs ()); + //tools::save_seq_vector (tools::string_formater ("rhs_flux.bs.%d.txt", iter_counter).str).save (jmatrix_->get_rhs_flux ()); + //tools::save_seq_vector (tools::string_formater ("sol.bs.%d.txt", iter_counter).str).save (jmatrix_->get_solution ()); + //tools::save_seq_vector (tools::string_formater ("regular_diag.bs.%d.txt", iter_counter).str).save (jmatrix_->get_regular_acc_diag ()); + + //jmatrix_->get_regular_matrix ()->ascii_write_in_csr_format (tools::string_formater ("regular_csr_matrix.bs.%d.txt", iter_counter).str); + //jmatrix_->get_irregular_matrix ()->ascii_write_in_csr_format (tools::string_formater ("irregular_csr_matrix.bs.%d.txt", iter_counter).str); + + //SAVE_BOOST_ARRAY (cap_pressure, calc_model_->n_phases - 1); + //SAVE_BOOST_ARRAY (s_deriv_cap_pressure, calc_model_->n_phases - 1); + //SAVE_BOOST_ARRAY (relative_perm, calc_model_->n_phases); + //SAVE_BOOST_ARRAY (s_deriv_relative_perm, (2 * (calc_model_->n_phases - 1))); + //////tools::save_seq_vector (tools::string_formater ("gor.bs.%d.txt", iter_counter).str).save (calc_model_->gas_oil_ratio); + //////SAVE_ITEM (p_deriv_gas_oil_ratio); + + //SAVE_BOOST_ARRAY (invers_fvf); + //SAVE_BOOST_ARRAY (p_deriv_invers_fvf); + //SAVE_ITEM (gor_deriv_invers_fvf); + + //SAVE_BOOST_ARRAY (invers_viscosity); + //SAVE_BOOST_ARRAY (p_deriv_invers_viscosity); + //SAVE_ITEM (gor_deriv_invers_viscosity); + + //SAVE_BOOST_ARRAY (invers_visc_fvf, calc_model_->n_phases); + //SAVE_BOOST_ARRAY (p_deriv_invers_visc_fvf, calc_model_->n_phases); + //SAVE_ITEM (gor_deriv_invers_visc_fvf); + + ////SAVE_ITEM (porosity); + ////SAVE_ITEM (p_deriv_porosity); + + //SAVE_BOOST_ARRAY (density, calc_model_->n_phases); + //SAVE_BOOST_ARRAY (p_deriv_density, calc_model_->n_phases); + + //SAVE_BOOST_ARRAY (mobility, calc_model_->n_phases); + //SAVE_BOOST_ARRAY (p_deriv_mobility, calc_model_->n_phases); + //SAVE_BOOST_ARRAY (s_deriv_mobility, (2 * (calc_model_->n_phases - 1))); + + //tools::save_seq_vector (tools::string_formater ("sat_3p.bs.%d.txt", iter_counter).str).save (calc_model_->saturation_3p); + //tools::save_seq_vector (tools::string_formater ("pressure.bs.%d.txt", iter_counter).str).save (calc_model_->pressure); + //tools::save_seq_vector (tools::string_formater ("gas_oil_ratio.bs.%d.txt", iter_counter).str).save (calc_model_->gas_oil_ratio); + + //tools::save_seq_vector ("perm.bs.txt").save (tools::float_saver (calc_model_->rock_grid_prop->permeability)); + //tools::save_seq_vector ("poro.bs.txt").save (tools::float_saver (calc_model_->rock_grid_prop->porosity_p_ref)); + //tools::save_seq_vector ("ngt.bs.txt").save (tools::float_saver (calc_model_->rock_grid_prop->net_to_gros)); + //tools::save_seq_vector ("volume.bs.txt").save (tools::float_saver (calc_model_->rock_grid_prop->volume)); + + //tools::save_seq_vector (tools::string_formater ("s_rhs.bs.%d.txt", iter_counter).str).save (jmatrix_->get_sec_rhs ()); + //tools::save_seq_vector (tools::string_formater ("ss_diag.bs.%d.txt", iter_counter).str).save (jmatrix_->get_ss_diagonal ()); + //tools::save_seq_vector (tools::string_formater ("sp_diag.bs.%d.txt", iter_counter).str).save (jmatrix_->get_sp_diagonal ()); + + typedef typename calc_model_t::reservoir_t::facility_manager_t::well_const_iterator_t well_iterator_t; + well_iterator_t wb = reservoir_->get_facility_list ()->wells_begin (); + well_iterator_t we = reservoir_->get_facility_list ()->wells_end (); + + typedef wells::type_helper type_helper_t; + typedef typename type_helper_t::item_rr_block_t item_rr_block_t; + typedef typename type_helper_t::item_rw_block_t item_rw_block_t; + typedef typename type_helper_t::item_wr_block_t item_wr_block_t; + + using namespace debug; + typedef rr > rr_t; + typedef rw > rw_t; + typedef wr > wr_t; + typedef rate > rate_t; + typedef cur_bhp > cur_bhp_t; + typedef density > density_t; + typedef bulkp > bulkp_t; + typedef ww_diveder > ww_diveder_t; + typedef bw_accessor > bw_accessor_t; + + //tools::save_seq_vector (tools::string_formater ("rr.bs.%d.txt", iter_counter).str) + //.save (tools::rr_rw_wr_saver (wb, we, reservoir_->get_connections_count ())); + //tools::save_seq_vector (tools::string_formater ("rw.bs.%d.txt", iter_counter).str) + //.save (tools::rr_rw_wr_saver (wb, we, reservoir_->get_connections_count ())); + //tools::save_seq_vector (tools::string_formater ("wr.bs.%d.txt", iter_counter).str) + //.save (tools::rr_rw_wr_saver (wb, we, reservoir_->get_connections_count ())); + //tools::save_seq_vector (tools::string_formater ("rate.bs.%d.txt", iter_counter).str) + //.save (tools::rr_rw_wr_saver (wb, we, reservoir_->get_connections_count ())); + + //tools::save_seq_vector (tools::string_formater ("con_cur_bhp.bs.%d.txt", iter_counter).str) + //.save (tools::connection_member_saver (wb, we, reservoir_->get_connections_count ())); + //tools::save_seq_vector (tools::string_formater ("con_density.bs.%d.txt", iter_counter).str) + //.save (tools::connection_member_saver (wb, we, reservoir_->get_connections_count ())); + //tools::save_seq_vector (tools::string_formater ("con_bulkp.bs.%d.txt", iter_counter).str) + //.save (tools::connection_member_saver (wb, we, reservoir_->get_connections_count ())); + + //tools::save_seq_vector (tools::string_formater ("ww.bs.%d.txt", iter_counter).str) + //.save (tools::well_member_saver (wb, we)); + //tools::save_seq_vector (tools::string_formater ("bw.bs.%d.txt", iter_counter).str) + //.save (tools::well_member_saver (wb, we)); + + //static save_connection_data connection_data; + //connection_data.save ("con_data.bs.%d.txt", calc_model_, dt, reservoir_->get_facility_list ()->wells_begin (), reservoir_->get_facility_list ()->wells_end (), iter_counter, 0); + + BOSOUT (section::iters, level::debug) << "iter_counter: " << iter_counter << bs_end; + } + +} // namespace blue_sky + + +#endif // #ifndef BS_FI_OPERATOR_SAVE_DEBUG_DATA_H_ + diff --git a/bs_bos_core/include/fi_params.h b/bs_bos_core/include/fi_params.h new file mode 100644 index 0000000..b952c88 --- /dev/null +++ b/bs_bos_core/include/fi_params.h @@ -0,0 +1,183 @@ +/*! \file fi_params.h + \brief Comtains fi_params - named_pbase inherited class + \author Nikonov Max +*/ + +#ifndef FI_PARAMS_H +#define FI_PARAMS_H + +namespace blue_sky + { + class BS_API_PLUGIN fi_params : public named_pbase + { + public: + //! blue-sky class declaration + BLUE_SKY_TYPE_DECL(fi_params); + public: + //! enumeration definitions + PROP_BASE_IDX_DECL_BEGIN(fi_params,named_pbase) + //! indexes for floating point parameters + FI_PARAMS_START, + PVT_PRESSURE_RANGE_MAX, //!< PVT tables maximum pressure + PVT_PRESSURE_RANGE_MIN, //!< PVT tables minimal pressure + PVTO_RS_RANGE_MAX, //!< PVTO maximum RS for slop table + PVTO_RS_RANGE_MIN, //!< PVTO minimum RS for slop table + MAX_TS, //!< maximum allowed time step length + MIN_TS, //!< minimum allowed time step length + FIRST_TS, //!< first simulation time step length + LIN_SOLV_RESIDUAL, //!< tolerance for linear solver + NEWTON_RESIDUAL, //!< tolerance for newton process + TS_INC_MULT, //!< multiplier for incrementing time step length + TS_DEC_MULT, //!< multiplier for decrementing time step length + OVERDRAFT, //!< overdraft factor (any time step could be multiplied by this factor to achieve end of report time step) + MAX_P_CORRECTION, //!< maximum allowed newton correction for pressure + MAX_S_CORRECTION, //!< maximum allowed newton correction for saturation + MAX_RS_CORRECTION, //!< maximum allowed newton correction for gas oil ratio + MAX_P_WELL_CORRECTION, //!< maximum allowed newton correction for well pressure + WAT_ROW_MULT, //!< multiplier for water equation in Jacobian + GAS_ROW_MULT, //!< multiplier for gas equation in Jacobian + OIL_ROW_MULT, //!< multiplier for oil equation in Jacobian + PRESSURE_COL_MULT, //!< multiplier for pressure derivates column in Jacobian + TS_OMEGA, //!< omega coef in time step controling + TS_DP, //!< pressure change for time step controling + TS_DS, //!< saturation change for time step controling + DP_MIN_CHOP, //!< minimum pressure chop + DS_MIN_CHOP, //!< minimum saturation chop + MAX_ALLOWED_LIN_SOLV_RESID, //!< maximum allowed residual + AMG_RESID, //!< tolerance for AMG preconditioner + TS_DRS, //!< Rs change for time step controling + MAX_NORM_ON_TS, //!< if norm on time step is greater than this value restart occur + DRSDT, //!< Maximum rate of increase of solution GOR + GAS_NORM_MULT, //!< multiplier for gas norm + // compositional + //COMP_PARAMS_D_MASS_BALANCE, //!< Scaled mass balance equation residuals. Equations are scaled by the accumulation terms (component mass dividing timestep size). + //COMP_PARAMS_D_PHASE_EQUIL, //!< Scaled phase equilibrium relation residuals. These are scaled by the component fugacities in the gas phase + //COMP_PARAMS_D_WELL_RATE, //!< Scaled well equation residuals, scaled by well input rate + //COMP_PARAMS_D_MAX_DP, //!< The maximum scaled pressure change (absolute pressure change divided by the average reservoir pressure) + //COMP_PARAMS_D_MAX_DS, //!< The maximum absolute saturation change + //COMP_PARAMS_D_MAX_DXCP, //!< The maximum absolute component mole fraction change + //COMP_PARAMS_D_TS_DP, //!< time step controling pressure change + //COMP_PARAMS_D_TS_DS, //!< time step controling saturation change + //COMP_PARAMS_D_TS_DXCP, //!< time step controling mole fraction change + //COMP_PARAMS_D_MAX_P_CORRECTION, //!< maximum allowed newton correction for pressure + //COMP_PARAMS_D_MAX_S_CORRECTION, //!< maximum allowed newton correction for saturation + //COMP_PARAMS_D_MAX_XCP_CORRECTION, //!< maximum allowed newton correction for mole fraction + // black oil + MASS_BALANS_ERROR, //!< maximum allowed mass balans error + MAX_NORM_ON_FIRST_N, //!< maximum allowed norm on first newton iteration + P_DIMENSION_LESS_SCALE_FACTOR, //!< scale factor for dimension less pressure + APPL_CHOP_PERC, //!< typically (0.25-0.4) + APPL_CHOP_BND, //!< typically (0.1-0.25) + LIN_SOLV_MATBAL_RESIDUAL, //!< mat. balans tolerance for linear solver + S_RHS_NORM, //!< max value for secondary rhs + D_TOTAL, //!< all parameters should be before this item + + //! indexes for integer parameters + PVT_INTERP_POINTS, //!< number of interpolation points + NEWTON_ITERS_NUM, //!< maximum allowed newton iterations number + LIN_ITERS_NUM, //!< maximum allowed linear iterations number + NEWTON_ITERS_INC, //!< number of newton iterations to increment step length + NEWTON_ITERS_AMG, //!< number of newton iterations to build full amg setup + APPROX_STEPS, //!< number of approximation steps + SELECT_SOL_STEPS, //!< number of steps to select newton correction force term + LIN_SOLVER_TYPE, //!< type of linear solver + GMRES_ORTONORM_VLEN, //!< number of vectors in GMRES to ortonorm + AMG_LIN_ITERS_NUM, //!< maximum allowed AMG solver iterations + WELL_NEWTON_ITERS_NUM, //!< maximum number of well internal newton iterations + PREC_TYPE, //!< type of the preconditioner for linear solver + PREC_TYPE_ONE_PHASE, //!< type of the preconditioner for linear solver for 1-phase problem + MIN_CELLS_IN_REGION, //!< minimum allowed cells in region for ACTNUM = 1 + SAVE_STEP_DATA_PERIOD, //!< save step data every n step + I_TOTAL, //!< all parameters should be before this item + + //! indexes for boolean parameters + PRINT_PVTO_TABLE, //!< if this item is set print PVTO to LOG file + PRINT_PVTW_TABLE, //!< print pvtw interpolation table + PRINT_PVTG_TABLE, //!< print pvtg interpolation table + STORE_PANE_FLOW_RATES, + NEW_TS_SELECTION_ALGORITHM, //!< use new algorithm for ts selection + SAVE_STEP_MAPS, //!< save maps on time step in the rst file + SAVE_INITIAL_DATA, //!< save initial data in the rst file + SAVE_RESTART_DATA, //!< save restart information + NEWTRANS, //!< correct transmissibility calculation between cells + CHECKS_FOR_MULTI_CONN, //!< check for multi connections in one cell + USE_TIMESTEP_FILE, //!< save time steps into *tsl file + SIMPLE_GET_CELL_SOLUTION, //!< enable simple solution restore algorithm + USE_LOW_SKIN_TRANS_MULT, //!< if this item is set use calculation of trans mults for low skin + SAVE_MESH_DATA, //!< save initial data in the rst file + SAVE_CALC_DATA, //!< save solution vector at each large time step into .dmp file + LOAD_CALC_DATA, //!< load initial guesses for Newton iterations from .dmp file + SAVE_NORM_DATA, //!< save cells norms to .cel file + DENS_JAC_SCALE, //!< enable densities based multiplier's for gas and oil equation's in Jacobian + NEWTON_TUNING, + SAVE_CROSSFLOW, + G_FRACTURE, + CLAMP_PRESSURE, //!< clamp pressure values at each Newton iteration between possible min and max + G_FRACTURE_FINAL, + SAVE_CONN_DATA, //!< save connection rates to rst file + DISABLE_FRACTURE_CHECK, + COMPRESS_IRR, //!< compress irregular matrix + REMOVE_ISOLATED_REGIONS, //!< make isolated regions with out wells inactive + SAVE_WRATES_TO_ASCII_FILE, //!< save well rates to ascii file + CREATE_HDF5_FILE, //!< create hdf5 file + WRITE_PRESSURE_TO_HDF5, //!< write pressure to hdf5 + WRITE_SATURATION_TO_HDF5, //!< write saturation to hdf5 + FIX_SOIL_BUG, + DISABLE_CROSSFLOW, + WRITE_GAS_OIL_RATIO_TO_HDF5, //!< write gas-oil ratio values to hdf5 file + WRITE_FIP_RESULTS_TO_HDF5, //!< write data by fip regions to hdf5 file + WRITE_WELL_RESULTS_TO_HDF5, //!< write well data to hdf5 file + WRITE_CONN_RESULTS_TO_HDF5, //!< write connection data to hdf5 file + WRITE_PLANE_FLOW_RATES_TO_HDF5, //!< write plane flow rates to hdf5 file + USE_CFL, //!< compute CFL in fi_operator and use csr_ilu_cfl_prec, used only if BS_BOS_CORE_USE_CSR_ILU_CFL_PREC defined + WRITE_CFL_TO_HDF5, //!< write CFL vector to hdf5 file + B_TOTAL, //!< all parameters should be before this item + FI_PARAMS_TOTAL, + PROP_BASE_IDX_DECL_END + + //! virtual dtor + virtual ~fi_params (); + + //! method for access property table + PBASE_ACCESS_MS(fi_params) + + public: + typedef smart_ptr sp_reader_t; + + //! Assignment operator + const fi_params &operator=(const fi_params&); + //! Update operator + const fi_params &operator+=(const fi_params&); + + //! set default values for properties + void set_default_values (); + + // read params from keyword data file + void read_from_keyword_data_file (sp_reader_t r); + + //! write data to result file + //int write_data_to_res_file (res_frame_ctrl *parent_frame, int id = YS_ID_FI_PARAMS); + + //! read data from result file + //int read_data_from_res_file (res_frame_ctrl *parent_frame); + + //! returns name by index + virtual const std::string &get_params_name (idx_type idx); + }; + +#ifdef BSPY_EXPORTING_PLUGIN + void + inline py_export_fi_params () + { + using namespace boost::python; + class_ , boost::noncopyable> ("fi_params", no_init) + ; + + register_ptr_to_python > (); + implicitly_convertible , smart_ptr > (); + } +#endif + +} + +#endif // FI_PARAMS_H diff --git a/bs_bos_core/include/fip_results_storage.h b/bs_bos_core/include/fip_results_storage.h new file mode 100644 index 0000000..c2eb646 --- /dev/null +++ b/bs_bos_core/include/fip_results_storage.h @@ -0,0 +1,173 @@ +#ifndef __BS_FIP_RESULTS_STORAGE_H +#define __BS_FIP_RESULTS_STORAGE_H + +#include "calc_model.h" + +namespace blue_sky + { + + enum fip_d_params + { + FIP_D_PARAM_COIP = 0, + FIP_D_PARAM_CMOIP, + FIP_D_PARAM_CWIP, + FIP_D_PARAM_CGIP, + FIP_D_PARAM_HPROD, + FIP_D_PARAM_PAV, + FIP_D_PARAM_CPVOL, + + FIP_D_PARAM_OIL_IN, + FIP_D_PARAM_WATER_IN, + FIP_D_PARAM_WATER_OUT, + + FIP_D_PARAM_SWAV, + FIP_D_PARAM_SOAV, + FIP_D_PARAM_SGAV, + FIP_D_PARAM_GOR, + + FIP_D_PARAM_COUNT + }; + + class BS_API_PLUGIN fip_results + { + // methods + public: + // default constructor + fip_results (); + // default destructor + ~fip_results (); + + // variables + public: + typedef std::vector dates_type; + typedef std::vector d_params_internal_type; + typedef std::vector d_params_type; + + dates_type dates; //!< dates array + d_params_type d_params; //!< set of float parameter arrays + }; + + + class BS_API_PLUGIN fip_results_storage : public objbase + { + BLUE_SKY_TYPE_DECL (fip_results_storage); + // methods + public: + ~fip_results_storage (); + // get summary fip data for all time steps for region + int get_summary_fip_data_for_region (); + + // variables + public: + typedef std::map fip_type; + typedef std::pair fip_pair_type; + fip_type fip; + + }; + + + template + struct save_fip_data + { + typedef calc_model calc_model_t; + typedef typename strategy_t::index_t index_t; + + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::item_t item_t; + typedef typename calc_model_t::helper_t::item_rr_block_t item_rr_block_t; + typedef typename calc_model_t::helper_t::item_rw_block_t item_rw_block_t; + typedef typename calc_model_t::helper_t::item_wr_block_t item_wr_block_t; + typedef typename calc_model_t::connection_t connection_t; + typedef typename calc_model_t::well_t well_t; + typedef typename calc_model_t::reservoir_t::facility_manager_t::well_iterator_t well_iterator_t; + typedef typename calc_model_t::strategy_type strategy_type; + + typedef smart_ptr sp_calc_model_t; + typedef typename calc_model_t::sp_well_t sp_well_t; + typedef typename calc_model_t::sp_connection_t sp_connection_t; + typedef smart_ptr sp_fip_results_storage; + +//! copy current fip data to storage + void + copy_fip_data_to_storage (sp_calc_model_t &calc_model, item_t dt) + { + const sp_fip_results_storage &f_res (calc_model->fip_res); + /* + int i; + fip_data *fd; + int fip_region = rsv_status->fip_region; + float fip_params[FIP_D_PARAM_COUNT] = {0}; + + CH_PTR (rsv_status); + + for (i = 0; i < fip_region; i++) + { + fip_results &fr = f_res.fip[i]; + fd = &(rsv_status->current_fip[i]); + + fr.dates.push_back (time + time_step_length); + + fip_params[FIP_D_PARAM_COIP] += (float)fd->COIP; + fip_params[FIP_D_PARAM_CMOIP] += (float)fd->CMOIP; + fip_params[FIP_D_PARAM_CWIP] += (float)fd->CWIP; + fip_params[FIP_D_PARAM_CGIP] += (float)fd->CGIP; + fip_params[FIP_D_PARAM_HPROD] += (float)fd->HPROD; + fip_params[FIP_D_PARAM_CPVOL] += (float)fd->CPVOL; + #ifdef _MPI + fip_params[FIP_D_PARAM_OIL_IN] += (float)fd->mpi_oil_in; + fip_params[FIP_D_PARAM_WATER_IN] += (float)fd->mpi_water_in; + fip_params[FIP_D_PARAM_WATER_OUT] += (float)fd->mpi_water_out; + #else //_MPI + fip_params[FIP_D_PARAM_OIL_IN] += (float)fd->oil_in; + fip_params[FIP_D_PARAM_WATER_IN] += (float)fd->water_in; + fip_params[FIP_D_PARAM_WATER_OUT] += (float)fd->water_out; + #endif //_MPI + fip_params[FIP_D_PARAM_SWAV] += (float)fd->SWAV; + fip_params[FIP_D_PARAM_SOAV] += (float)fd->SOAV; + fip_params[FIP_D_PARAM_SGAV] += (float)fd->SGAV; + + fr.d_params[FIP_D_PARAM_COIP].push_back ((float)fd->COIP); + fr.d_params[FIP_D_PARAM_CMOIP].push_back ((float)fd->CMOIP); + fr.d_params[FIP_D_PARAM_CWIP].push_back ((float)fd->CWIP); + fr.d_params[FIP_D_PARAM_CGIP].push_back ((float)fd->CGIP); + fr.d_params[FIP_D_PARAM_HPROD].push_back ((float)fd->HPROD); + fr.d_params[FIP_D_PARAM_CPVOL].push_back ((float)fd->CPVOL); + fr.d_params[FIP_D_PARAM_PAV].push_back ((float)fd->PAV); + #ifdef _MPI + fr.d_params[FIP_D_PARAM_OIL_IN].push_back ((float)fd->mpi_oil_in); + fr.d_params[FIP_D_PARAM_WATER_IN].push_back ((float)fd->mpi_water_in); + fr.d_params[FIP_D_PARAM_WATER_OUT].push_back ((float)fd->mpi_water_out); + #else //_MPI + fr.d_params[FIP_D_PARAM_OIL_IN].push_back ((float)fd->oil_in); + fr.d_params[FIP_D_PARAM_WATER_IN].push_back ((float)fd->water_in); + fr.d_params[FIP_D_PARAM_WATER_OUT].push_back ((float)fd->water_out); + #endif //_MPI + fr.d_params[FIP_D_PARAM_SWAV].push_back ((float)fd->SWAV); + fr.d_params[FIP_D_PARAM_SOAV].push_back ((float)fd->SOAV); + fr.d_params[FIP_D_PARAM_SGAV].push_back ((float)fd->SGAV); + fr.d_params[FIP_D_PARAM_GOR].push_back ((float)fd->GOR); + } + + fip_results &fr = f_res.fip[fip_region]; + + fr.dates.push_back (time + time_step_length); + fr.d_params[FIP_D_PARAM_COIP].push_back (fip_params[FIP_D_PARAM_COIP]); + fr.d_params[FIP_D_PARAM_CMOIP].push_back (fip_params[FIP_D_PARAM_CMOIP]); + fr.d_params[FIP_D_PARAM_CWIP].push_back (fip_params[FIP_D_PARAM_CWIP]); + fr.d_params[FIP_D_PARAM_CGIP].push_back (fip_params[FIP_D_PARAM_CGIP]); + fr.d_params[FIP_D_PARAM_HPROD].push_back (fip_params[FIP_D_PARAM_HPROD]); + fr.d_params[FIP_D_PARAM_CPVOL].push_back (fip_params[FIP_D_PARAM_CPVOL]); + fr.d_params[FIP_D_PARAM_PAV].push_back (float (rsv_status->pav)); + fr.d_params[FIP_D_PARAM_OIL_IN].push_back (fip_params[FIP_D_PARAM_OIL_IN]); + fr.d_params[FIP_D_PARAM_WATER_IN].push_back (fip_params[FIP_D_PARAM_WATER_IN]); + fr.d_params[FIP_D_PARAM_WATER_OUT].push_back (fip_params[FIP_D_PARAM_WATER_OUT]); + fr.d_params[FIP_D_PARAM_SWAV].push_back (fip_params[FIP_D_PARAM_SWAV]); + fr.d_params[FIP_D_PARAM_SOAV].push_back (fip_params[FIP_D_PARAM_SOAV]); + fr.d_params[FIP_D_PARAM_SGAV].push_back (fip_params[FIP_D_PARAM_SGAV]); + fr.d_params[FIP_D_PARAM_GOR].push_back (float (rsv_status->gor)); + */ + } + }; + +} //blue_sky +#endif //__BS_FIP_RESULTS_STORAGE_H diff --git a/bs_bos_core/include/for_each_well.h b/bs_bos_core/include/for_each_well.h new file mode 100644 index 0000000..6ee7ed5 --- /dev/null +++ b/bs_bos_core/include/for_each_well.h @@ -0,0 +1,99 @@ +/** + * \file for_each_well.h + * \brief well traversers + * \author Sergey Miryanov + * \date 13.02.2009 + * */ +#ifndef BS_FOR_EACH_WELL_H_ +#define BS_FOR_EACH_WELL_H_ + +namespace blue_sky { + + template + void + for_each_well (facility_manager &facility_list, method_t method) + { + typename facility_manager ::well_const_iterator_t wb = facility_list.wells_begin (); + typename facility_manager ::well_const_iterator_t we = facility_list.wells_end (); + typedef well well_t; + typedef smart_ptr sp_well_t; + + for (; wb != we; ++wb) + { + sp_well_t well (wb->second, bs_dynamic_cast ()); + BS_ASSERT (well); + + if (well->get_connections_count ()) + { + method (*well); + } + } + } + + template + void + for_each_facility (facility_manager &facility_list, method_t method) + { + typename facility_manager ::well_const_iterator_t wb = facility_list.wells_begin (); + typename facility_manager ::well_const_iterator_t we = facility_list.wells_end (); + + for (; wb != we; ++wb) + { + method (*wb->second); + + //if (well->get_connections_count ()) + // { + // method (*well); + // } + } + } + + template + bool + for_each_well_while_cond (facility_manager &facility_list, method_t method) + { + typename facility_manager ::well_const_iterator_t wb = facility_list.wells_begin (); + typename facility_manager ::well_const_iterator_t we = facility_list.wells_end (); + typedef well well_t; + typedef smart_ptr sp_well_t; + + for (; wb != we; ++wb) + { + sp_well_t well (wb->second, bs_dynamic_cast ()); + BS_ASSERT (well); + if (well->get_connections_count () && method (*well)) + { + return true; + } + } + + return false; + } + template + size_t + for_each_well_acc (facility_manager &facility_list, method_t method) + { + typename facility_manager ::well_const_iterator_t wb = facility_list.wells_begin (); + typename facility_manager ::well_const_iterator_t we = facility_list.wells_end (); + typedef well well_t; + typedef smart_ptr sp_well_t; + + size_t acc = 0; + for (; wb != we; ++wb) + { + sp_well_t well (wb->second, bs_dynamic_cast ()); + BS_ASSERT (well); + + if (well->get_connections_count ()) + { + acc += method (*well); + } + } + + return acc; + } + +} // namespace blue_sky + +#endif // #ifndef BS_FOR_EACH_WELL_H_ + diff --git a/bs_bos_core/include/fracture.h b/bs_bos_core/include/fracture.h new file mode 100644 index 0000000..5f62fc5 --- /dev/null +++ b/bs_bos_core/include/fracture.h @@ -0,0 +1,55 @@ +#ifndef FRACTURE_H +#define FRACTURE_H + +namespace blue_sky + { + class fracture + { + public: + //! default ctor + fracture(); + //! copy ctor + fracture(const fracture&); + //! dtor + ~fracture(); + + //! Assignment operator + fracture &operator=(const fracture&); + + //! initialization + void init(); + + //! for get and set well's name + std::string &tname(); + + //! check data + int check_data() const; + + //data + int dim[4]; //!< coordinates accessed as array + double frac_len; //!< fracture lenght + double frac_angle; //!< fracture angle + double frac_skin; //!< fracture skin factor + double frac_perm; //!< fracture permeability + double frac_width; //!< fracture width + + int frac_flag; + + int connection_type; + + //! FRACTURE creation time as amount of days from + //! starting date, negative value means not + //! initialized + double start_time; + + int is_activated; //!< show whether fracture already activated + int ignore_fracture; //!< ignore this fracture (for example, if + //! fracture placed in inactive block) + + private: + //! name of well with fracture + std::string name; + }; +}; + +#endif // FRACTURE_H diff --git a/bs_bos_core/include/generate_numeric_jacobian.h b/bs_bos_core/include/generate_numeric_jacobian.h new file mode 100644 index 0000000..2e6dcb4 --- /dev/null +++ b/bs_bos_core/include/generate_numeric_jacobian.h @@ -0,0 +1,257 @@ +/** + * \file generate_numeric_jacobian.h + * \brief + * \author Sergey Miryanov + * \date 27.11.2008 + * */ +#ifndef BS_MAIN_LOOP_GENERATE_NUMERIC_JACOBIAN_H_ +#define BS_MAIN_LOOP_GENERATE_NUMERIC_JACOBIAN_H_ + +#include "string_formater.h" + +namespace blue_sky + { + + namespace xxx + { + + template + struct clmn_holder + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + + typedef typename strategy_t::item_array_t item_array_t; + + clmn_holder (item_array_t &dst, index_t index, index_t shift, index_t block) + : dst (dst) + , index (index) + , shift (shift) + , block (block) + { + } + + template + clmn_holder & + operator-= (const op_t &op) + { + index_t idx = 0; + for (index_t i = 0, cnt = (index_t)op.size (), clmn_count = (index_t)op.size () / block; i < clmn_count; ++i) + { + index_t i_idx = index * block * block + shift + i * clmn_count * block * block; + for (index_t j = 0, k = 0; j < block; ++j, ++idx, k += block) + { + dst [i_idx + k] -= op[idx]; + } + } + + return *this; + } + + item_array_t &dst; + index_t index; + index_t shift; + index_t block; + }; + + template + struct clmn_sub + { + clmn_sub (const array_t &lhs, const array_t &rhs) + : lhs (lhs) + , rhs (rhs) + { + } + + size_t + size () const + { + return lhs.size (); + } + + typedef typename array_t::value_type value_type; + value_type + operator[] (size_t i) const + { + return lhs[i] - rhs[i]; + } + + const array_t &lhs; + const array_t &rhs; + }; + + template + struct clmn_sub_div + { + typedef typename lhs_t::value_type value_type; + + clmn_sub_div (const lhs_t &lhs, value_type scalar) + : lhs (lhs) + , scalar (scalar) + { + } + + size_t + size () const + { + return lhs.size (); + } + + value_type + operator[] (size_t i) const + { + return lhs[i] / scalar; + } + + const lhs_t &lhs; + value_type scalar; + }; + template + struct clmn_sub_div_mul + { + typedef typename lhs_t::value_type value_type; + + clmn_sub_div_mul (const lhs_t &lhs, value_type scalar) + : lhs (lhs) + , scalar (scalar) + { + } + + size_t + size () const + { + return lhs.size (); + } + + value_type + operator[] (size_t i) const + { + return lhs[i] * scalar; + } + + const lhs_t &lhs; + value_type scalar; + }; + + template + clmn_sub + operator- (const array_t &lhs, const array_t &rhs) + { + return clmn_sub (lhs, rhs); + } + template + clmn_sub_div + operator/ (const lhs_t &lhs, const item_t &scalar) + { + return clmn_sub_div (lhs, scalar); + } + template + clmn_sub_div_mul + operator* (const lhs_t &lhs, const item_t &scalar) + { + return clmn_sub_div_mul (lhs, scalar); + } + } // namespace xxx + + + template + inline void + main_loop_calc ::generate_numeric_jacobian (int /*init*/) + { + throw bs_exception ("generate_numeric_jacobian", "NOT IMPL YET"); + //using namespace xxx; + + //locked_jmatrix_t jmatrix_ (jacobian_->get_jmatrix ()); + + //calc_model_->fi_operator (dt_, init, init, number_of_small_time_steps, reservoir_, mesh_, jacobian_, false, false); + //item_array_t init_rhs; + //init_rhs.assign (jmatrix_->get_rhs ().begin (), jmatrix_->get_rhs ().end ()); + + //index_t cells_num = mesh_->get_n_active_elements(); + //index_t n_phases = calc_model_->n_phases; + //index_t b_sqr = n_phases * n_phases; + + //item_array_t numeric_jacobian; + //numeric_jacobian.resize (b_sqr * cells_num * cells_num); + + //item_array_t &pressure = calc_model_->pressure; + //item_array_t &sat = calc_model_->saturation_3p; + //item_array_t &gor = calc_model_->gas_oil_ratio; + + //const typename calc_model_t::main_var_array_t &main_var = calc_model_->main_variable; + + //bool is_o = calc_model_->is_oil (); + //bool is_w = calc_model_->is_water (); + //bool is_g = calc_model_->is_gas (); + + //index_t d_o = n_phases == 3 ? p3_oil : (is_o && is_w ? p2ow_oil : (is_o && is_g ? p2og_oil : 0)); + //index_t d_w = n_phases == 3 ? p3_wat : (is_o && is_w ? p2ow_wat : (0)); + //index_t d_g = n_phases == 3 ? p3_gas : (is_o && is_w ? 0 : (is_o && is_g ? p2og_gas : 0)); + + //index_t i_o = calc_model_->phase_d[FI_PHASE_OIL]; + //index_t i_w = calc_model_->phase_d[FI_PHASE_WATER]; + //index_t i_g = calc_model_->phase_d[FI_PHASE_GAS]; + +#ifdef _DEBUG + //item_t *p_sat = &sat[0]; +#endif + + //item_t eps = 1.0e-8; + //for (index_t i = 0; i < cells_num; ++i) + // { + // if (is_g) + // { + // if (main_var[i] == FI_SG_VAR) + // { + // sat [i * n_phases + i_g] += eps; + // sat [i * n_phases + i_w] -= eps; + // calc_model_->fi_operator (dt_, init, init, number_of_small_time_steps, reservoir_, mesh_, jacobian_, false, false); + // item_array_t &sat_g_rhs = jmatrix_->get_rhs (); + // clmn_holder (numeric_jacobian, i, d_g, n_phases) -= (sat_g_rhs - init_rhs) / (eps); + // sat [i * n_phases + i_g] -= eps; + // sat [i * n_phases + i_w] += eps; + // } + // else if (main_var[i] == FI_RO_VAR) + // { + // gor [i] += eps; + // sat [i * n_phases + i_w] -= eps; + // calc_model_->fi_operator (dt_, init, init, number_of_small_time_steps, reservoir_, mesh_, jacobian_, false, false); + // item_array_t &sat_g_rhs = jmatrix_->get_rhs (); + // clmn_holder (numeric_jacobian, i, d_g, n_phases) -= (sat_g_rhs - init_rhs) / (eps); + // gor [i] -= eps; + // sat [i * n_phases + i_w] += eps; + // } + // } + + // if (is_o) + // { + // sat [i * n_phases + i_o] += eps; + // sat [i * n_phases + i_w] -= eps; + // calc_model_->fi_operator (dt_, init, init, number_of_small_time_steps, reservoir_, mesh_, jacobian_, false, false); + // item_array_t &sat_o_rhs = jmatrix_->get_rhs (); + // clmn_holder (numeric_jacobian, i, d_o, n_phases) -= (sat_o_rhs - init_rhs) / (eps); + // sat [i * n_phases + i_o] -= eps; + // sat [i * n_phases + i_w] += eps; + // } + + // if (is_w) + // { + // pressure[i] += eps; + // calc_model_->fi_operator (dt_, init, init, number_of_small_time_steps, reservoir_, mesh_, jacobian_, false, false); + // item_array_t &pressure_rhs = jmatrix_->get_rhs (); + // clmn_holder (numeric_jacobian, i, d_w, n_phases) -= (pressure_rhs - init_rhs) / (eps); + // pressure[i] -= eps; + // } + + // tools::save_seq_vector ("numeric_jacobian.txt").save (numeric_jacobian); + // } + + //static size_t iter_counter = 0; + //++iter_counter; + //tools::save_seq_vector (tools::string_formater ("numeric_jacobian.bs.%d.txt", iter_counter).str).save (numeric_jacobian); + } + +} // namespace blue_sky + +#endif // #ifndef BS_MAIN_LOOP_GENERATE_NUMERIC_JACOBIAN_H_ + diff --git a/bs_bos_core/include/inverse_matrix.h b/bs_bos_core/include/inverse_matrix.h new file mode 100644 index 0000000..8627932 --- /dev/null +++ b/bs_bos_core/include/inverse_matrix.h @@ -0,0 +1,114 @@ +///** +// * \file inverse_matrix.h +// * \brief calc invers of matrix +// * \author Sergey Miryanov +// * \date 25.06.2008 +// * */ +//#ifndef BS_CALC_INVERSE_MATRIX_H_ +//#define BS_CALC_INVERSE_MATRIX_H_ +// +//namespace blue_sky { +//namespace tools { +// +// template +// struct inverse_block +// { +// typedef typename array_t::value_type item_t; +// +// inverse_block (array_t &dst, const array_t &src_, index_t bs_) +// : dst (dst) +// , block_size (bs_) +// , b_sqr (bs_ * bs_) +// { +// // TODO: !! +// array_t &src__ = const_cast (src_); +// src.assign (src__.begin (), src__.end ()); +// } +// +// void inverse (index_t index) +// { +// identity_matrix (index); +// +// for (index_t i = 0; i < block_size; ++i) +// { +// process_lower_row (index, i); +// } +// for (index_t i = block_size - 1; i >= 0; --i) +// { +// process_upper_row (index, i); +// } +// for (index_t i = 0; i < block_size; ++i) +// { +// process_diagonal (index, i); +// } +// } +// +// private: +// void process_lower_row (index_t index, index_t row_idx) +// { +// index_t row_idx_ = (index * b_sqr) + (row_idx * block_size); +// +// item_t mul0 = src[row_idx_]; +// for (index_t i = row_idx + 1; i < block_size; ++i) +// { +// index_t idx = index * b_sqr + i * block_size; +// item_t mul = src[idx]; +// for (index_t j = 0; j < block_size; ++j) +// { +// src[idx + j] = src[idx + j] * mul0 - src[row_idx_ + j] * mul; +// dst[idx + j] = dst[idx + j] * mul0 - dst[row_idx_ + j] * mul; +// } +// } +// } +// +// void process_upper_row (index_t index, index_t row_index) +// { +// index_t row_idx = (index *b_sqr) + (row_index * block_size); +// +// item_t mul0 = src[row_idx + row_index]; +// for (index_t i = row_index - 1; i >= 0; --i) +// { +// index_t idx = index * b_sqr + i * block_size; +// item_t mul = src[idx + row_index]; +// for (index_t j = block_size - 1; j >= 0; --j) +// { +// src[idx + j] = src[idx + j] * mul0 - src[row_idx + j] * mul; +// dst[idx + j] = dst[idx + j] * mul0 - dst[row_idx + j] * mul; +// } +// } +// } +// +// void process_diagonal (index_t index, index_t row_index) +// { +// index_t row_idx = (index * b_sqr) + (row_index * block_size); +// item_t div = src[row_idx + row_index]; +// +// for (index_t i = 0; i < block_size; ++i) +// { +// dst[row_idx + i] /= div; +// } +// } +// +// void identity_matrix (index_t index) +// { +// for (index_t i = 0; i < b_sqr; ++i) +// { +// dst[index * b_sqr + i] = 0; +// } +// for (index_t i = 0; i < block_size; ++i) +// { +// dst[index * b_sqr + i * block_size + i] = 1.0; +// } +// } +// +// array_t &dst; +// array_t src; +// index_t block_size; +// index_t b_sqr; +// }; +// +//} // namespace tools +//} // namespace blue_sky +// +// +//#endif // #ifndef BS_CALC_INVERSE_MATRIX_H_ diff --git a/bs_bos_core/include/jacobian.h b/bs_bos_core/include/jacobian.h new file mode 100644 index 0000000..11e8933 --- /dev/null +++ b/bs_bos_core/include/jacobian.h @@ -0,0 +1,142 @@ +/** +* @file jacobian.h +* @brief implemetation of jacobian matrix +* @author Morozov Andrew +* @date 2008-05-29 +*/ + +#ifndef JACOBIAN_H_ +#define JACOBIAN_H_ + +#include "fi_params.h" +#include BS_FORCE_PLUGIN_IMPORT () +#include "linear_solvers.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "make_me_happy.h" + +namespace blue_sky +{ + /* + template + + class BS_API_PLUGIN rs_mesh_iface; + */ + /*! \class jacobian + \brief Class for solving jacobian matrix + */ + template + class BS_API_PLUGIN jacobian : public bs_node + { + public: + typedef typename strategy_t::matrix_t matrix_t; ///< short name to matrix type + typedef typename strategy_t::item_array_t item_array_t; ///< short name to array type + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename strategy_t::item_t item_t; ///< short name to array item type + typedef typename strategy_t::index_t index_t; ///< short name to matrix's index type + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::barrier_t barrier_t; + typedef rs_mesh_iface < strategy_t > mesh_iface_t; + typedef typename strategy_t::csr_matrix_t bcsr_matrix_t; + typedef linear_solver_base linear_solver_base_t; + + typedef smart_ptr sp_matrix_t; + typedef smart_ptr sp_bcsr_matrix_t; + typedef smart_ptr , true> sp_jmatrix; //!< matrix type + typedef smart_ptr , true> sp_lsolver; //!< solver & preconditioner type + typedef smart_ptr sp_fi_params; + + typedef smart_ptr sp_mesh_iface_t; + + typedef jacobian this_t; + + //! set solver + void set_solver(const sp_lsolver &s) + { + solver = s; + } + //! set preconditioner + void set_prec (const sp_lsolver &p) + { + preconditioner = p; + } + //! set jacobian matrix + void + set_jmatrix (const sp_jmatrix &mx) + { + jm = mx; + } + + //! get jacobian matrix + const sp_jmatrix & + get_jmatrix() const + { + return jm; + } + //! get solver + const sp_lsolver &get_solver () const; + //! get preconditioner + const sp_lsolver &get_prec () const; + + //! set up params for solver + int setup_solver_params (well_model_type model_type, int n_phases, const sp_fi_params &ts_params); + + //! run solver setup + int setup (); + + void begin (); + void end (); + + //! solve + item_t solve (index_t &n_lin_iters); + + //! \struct jacob_traits + //! \brief For sorting jacobian children + struct jacob_traits : bs_node::sort_traits + { + struct jacob_key : bs_node::sort_traits::key_type + { + virtual bool sort_order (const key_ptr & ) const + { + return true; + } + }; + + virtual const char * sort_name () const + { + return "jacob trait"; + }; + + virtual key_ptr key_generator (const sp_link& /*l*/) const + { + return new jacob_key (); + } + + virtual bool accepts (const sp_link& l) + { + return smart_ptr< this_t, true >(l->data(), bs_dynamic_cast()); + } + }; + + public: + virtual ~jacobian() + { + } + + BLUE_SKY_TYPE_DECL_T (jacobian); + + private: + void setup_solver (const sp_fi_params &ts_params); + void setup_preconditioner (const sp_fi_params &ts_params); + + protected: + + sp_jmatrix jm; //!< jacobian matrix + sp_lsolver solver; //!< solver + sp_lsolver preconditioner; //!< preconditioner + auto_value solver_is_gmres_flag; //!< if != 0 solver point to the GMRES solver + auto_value prec_is_cpr_flag; //!< if != 0 if using CPR precondition + }; + +} // namespace blue_sky +#endif // JACOBIAN_H_ diff --git a/bs_bos_core/include/jacobian_impl.h b/bs_bos_core/include/jacobian_impl.h new file mode 100644 index 0000000..a1c9121 --- /dev/null +++ b/bs_bos_core/include/jacobian_impl.h @@ -0,0 +1,181 @@ +/** + * \file jacobian_impl.h + * \brief impl of jacobian method + * \author Sergey Miryanov + * \date 23.01.2009 + * */ +#ifndef BS_JACOBIAN_IMPL_H_ +#define BS_JACOBIAN_IMPL_H_ +#include "solve_helper.h" + +namespace blue_sky { + + template + struct jacobian_impl + { + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::matrix_t matrix_t; + typedef typename strategy_t::csr_matrix_t bcsr_matrix_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + + typedef jacobian jacobian_t; + typedef jacobian_matrix jmatrix_t; + typedef linear_solver_base linear_solver_t; + + typedef smart_ptr sp_jacobian_t; + typedef smart_ptr sp_jmatrix_t; + typedef smart_ptr sp_linear_solver_t; + typedef smart_ptr sp_matrix_t; + typedef smart_ptr sp_bcsr_matrix_t; + + typedef sp_linear_solver_t sp_solver_t; + + jacobian_impl (sp_jacobian_t &jacobian, sp_jmatrix_t &jmatrix) + : jacobian_ (jacobian), + jmatrix_ (jmatrix), + solver_ (jacobian_->get_solver ()), + preconditioner_ (jacobian_->get_prec ()), + rhs_ (jmatrix_->get_rhs ()), + sol_ (jmatrix_->get_solution ()), + regular_matrix_ (jmatrix_->get_regular_matrix ()), + irregular_matrix_ (jmatrix_->get_irregular_matrix ()) + { + if (!jmatrix_) + { + bs_throw_exception ("Jacobian matrix is not inited!"); + } + if (!solver_) + { + bs_throw_exception ("Solver is not inited!"); + } + if (!preconditioner_) + { + bs_throw_exception ("Preconditioner is not inited!"); + } + } + + void + setup_jacobian () + { + full_matrix_print (); + + jmatrix_->prepare_matrix (); + + OMP_TIME_MEASURE_START(gmres_setup_timer); + if (0 != solver_->setup (jmatrix_)) + { + bs_throw_exception ("Internal error: cannot build preconditioner for linear solver."); + } + OMP_TIME_MEASURE_END (gmres_setup_timer); + } + + item_t + solve_jacobian (index_t &n_lin_iters) + { +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + //!ret_code = solver->solve (jm, jm->get_mpi_rhs(), jm->get_mpi_sol()); +#else //_MPI + sp_matrix_t working_matrix; + //const blue_sky::setup_preconditioner *setup_prec = dynamic_cast *> ((objbase *)jmatrix_.get ()); + //if (setup_prec) + // { + // working_matrix = setup_prec->get_prepared_matrix (); + // } + //else + // { + // working_matrix = jmatrix_.get (); + // } + + // TODO: BUG + working_matrix = jmatrix_->get_prepared_matrix (); + const sp_matrix_t &locked_working_mx (working_matrix); + + debug::print_memory_info ("-> jacobian_solver_solve"); + index_t ret_code = solve_helper (&*solver_, &(*locked_working_mx), rhs_, sol_); + debug::print_memory_info ("<- jacobian_solver_solve"); +#endif //_MPI + + jmatrix_->restore_sec_solution (); + + static size_t iter_counter = 0; + ++iter_counter; + ////jmatrix_->get_regular_matrix ()->ascii_write_in_csr_format (tools::string_formater ("j_reg_mx.bs.%d.txt", iter_counter).str); + ////jmatrix_->get_irregular_matrix ()->ascii_write_in_csr_format (tools::string_formater ("j_irreg_mx.bs.%d.txt", iter_counter).str); + //tools::save_seq_vector (tools::string_formater ("j_rhs.bs.%d.txt", iter_counter).str).save (rhs_); + //tools::save_seq_vector (tools::string_formater ("j_rhs_flux.bs.%d.txt", iter_counter).str).save (jmatrix_->get_rhs_flux ()); + //tools::save_seq_vector (tools::string_formater ("j_sol.bs.%d.txt", iter_counter).str).save (sol_); + //tools::save_seq_vector (tools::string_formater ("j_sec_sol.bs.%d.txt", iter_counter).str).save (jmatrix_->get_sec_solution ()); + + if (ret_code < 0) + { + BOSERR (section::solvers, level::error) << "Linear solver failed with retcode = " << ret_code << bs_end; + return 10.0f; + } + +#ifdef __FULL_MATRIX_PRINT__ + ++cur_iter; +#endif //__FULL_MATRIX_PRINT__ + + n_lin_iters = solver_->get_prop()->get_iters(); + item_t tol = solver_->get_prop()->get_final_resid(); + if (tol > solver_->get_prop()->get_tolerance()) + { + BOSERR (section::solvers, level::error) + << "Linear solver failed with tolerance " + << tol + << bs_end; + } + else + { + BOSOUT (section::solvers, level::medium) + << "Linear solver iterations " + << n_lin_iters + << ", tol = " << tol + << ", ret_code = " << ret_code + << bs_end; + } + + return tol; + } + + void + full_matrix_print () + { +#ifdef __FULL_MATRIX_PRINT__ + if (jacobian_->cur_iter % jacobian_->sav_iters == 0) + { + char reg_filename [50]; + char irr_filename [50]; + + sprintf (reg_filename, "regular_matrix%d.bs.b", jacobian_->cur_iter); + sprintf (irr_filename, "irregular_matrix%d.bs.csr", jacobian_->cur_iter); + + regular_matrix_->ascii_write_in_csr_format(reg_filename); + irregular_matrix_->ascii_write_in_csr_format(irr_filename); + } +#endif + } + + private: + + sp_jacobian_t &jacobian_; + sp_jmatrix_t &jmatrix_; + sp_solver_t solver_; + sp_solver_t preconditioner_; + + rhs_item_array_t &rhs_; + item_array_t &sol_; + + sp_matrix_t regular_matrix_; + sp_matrix_t irregular_matrix_; + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_JACOBIAN_IMPL_H_ + diff --git a/bs_bos_core/include/keyword_manager.h b/bs_bos_core/include/keyword_manager.h new file mode 100644 index 0000000..6d8ee9c --- /dev/null +++ b/bs_bos_core/include/keyword_manager.h @@ -0,0 +1,187 @@ + /** + * @file keywords.h + * @brief declaration of keyword hadling class + * @author Morozov Andrey + * @date 2008-07-02 + * */ +#ifndef KEYWORD_MANAGER_H_ +#define KEYWORD_MANAGER_H_ + +#include BS_FORCE_PLUGIN_IMPORT () +//#include "scal_3p.h" +#include "main_def.h" +#include "read_class.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "keyword_manager_iface.h" +#include "date_sim.h" + +namespace blue_sky +{ + + template + class BS_API_PLUGIN keyword_info_base; + + //! keyword_manager - class-factory which contain a set of handlers for different keywords + template + class BS_API_PLUGIN keyword_manager: public keyword_manager_iface + { + public: + //----------------------------------------- + // TYPES + //----------------------------------------- + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef strategy_t strategy_type; + + typedef keyword_manager this_t; // base_t; + + typedef idata idata_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef keyword_info_base keyword_info_base_t; + typedef keyword_params keyword_params_t; + + typedef smart_ptr sp_this_t; // sp_reader_t; // sp_idata_t; // sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_keyword_info_base_t; + typedef smart_ptr sp_objbase; + + + typedef typename base_t::handler_t handler_t; + typedef typename base_t::keyword_handler keyword_handler; + typedef typename base_t::shared_handler_t shared_handler_t; + + + + //! typedef for map of handlers, keyword_params ¶ms + typedef std::map handlers_t; + typedef std::map > supported_keywords_t; + + + //----------------------------------------- + // VARIABLES + //----------------------------------------- + handlers_t handlers; //register_keywords();//em); + this->register_plugin_keywords(); + } + + //! handle keyword, called from data_manager.read_keyword_file + void handle_keyword (const std::string &keyword, keyword_params_t ¶ms); + + //! registration of active keyword in factory + void register_keyword(const std::string &keyword, keyword_handler handler); + + //! registration of active keyword in factory + void register_keyword (const std::string &keyword, const shared_handler_t &handler); + + //! registration of supported keywords in factory + void register_supported_keyword(const std::string &keyword, const std::string &provider); + + //! registration of known keywords + void register_keywords(); //const sp_event_manager_t &em); + + //! registration of known keywords + void register_plugin_keywords(); + + //! return starting date + boost::posix_time::ptime get_starting_date () {return starting_date;} + + bool + is_keyword_supported (const std::string &keyword, keyword_params_t ¶ms) const; + + bool + is_keyword_activated (const std::string &keyword, keyword_params_t ¶ms) const; + + private: + //! Following functions are keyword handlers + //! General functions for pooled keyword handle + static void int_array_handler (const std::string &keyword, keyword_params_t ¶ms); + static void float_array_handler (const std::string &keyword, keyword_params_t ¶ms); + //! Handling of event keywords + static void event_handler (const std::string &keyword, keyword_params_t ¶ms); + //! Named keywords + static void TITLE_handler (const std::string &keyword, keyword_params_t ¶ms); + static void OIL_handler (const std::string &keyword, keyword_params_t ¶ms); + static void WATER_handler (const std::string &keyword, keyword_params_t ¶ms); + static void GAS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void PROCESS_PARAMS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void RESTART_handler (const std::string &/*keyword*/, keyword_params_t &/*params*/) + { + BOSOUT << "RESTART: NOT_IMPL_YET" << bs_end; + } + static void REPORTS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void REPORTFILE_handler (const std::string &keyword, keyword_params_t ¶ms); + static void REPORTSCREEN_handler (const std::string &keyword, keyword_params_t ¶ms); + static void ARITHMETIC_handler (const std::string &keyword, keyword_params_t ¶ms); + static void STONE1_handler (const std::string &keyword, keyword_params_t ¶ms); + static void STONE2_handler (const std::string &keyword, keyword_params_t ¶ms); + static void RELATIVE_PERM_DEFAULT_handler (const std::string &keyword, keyword_params_t ¶ms); + static void UNITS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void DIMENS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void ROCKCOMP_handler (const std::string &keyword, keyword_params_t ¶ms); + static void REGDIMS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void REGNUM_handler (const std::string &keyword, keyword_params_t ¶ms); + static void EQLDIMS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void TABDIMS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void COORD_handler (const std::string &keyword, keyword_params_t ¶ms); + static void ZCORN_handler (const std::string &keyword, keyword_params_t ¶ms); + static void MINPV_handler (const std::string &keyword, keyword_params_t ¶ms); + static void MINSV_handler (const std::string &keyword, keyword_params_t ¶ms); + static void DENSITY_handler (const std::string &keyword, keyword_params_t ¶ms); + static void ROCKTAB_handler (const std::string &keyword, keyword_params_t ¶ms); + static void PVTO_handler (const std::string &keyword, keyword_params_t ¶ms); + static void PVDO_handler (const std::string &keyword, keyword_params_t ¶ms); + static void PVTW_handler (const std::string &keyword, keyword_params_t ¶ms); + static void PVDG_handler (const std::string &keyword, keyword_params_t ¶ms); + static void ROCK_handler (const std::string &keyword, keyword_params_t ¶ms); + static void SWOF_handler (const std::string &keyword, keyword_params_t ¶ms); + static void SGOF_handler (const std::string &keyword, keyword_params_t ¶ms); + static void SWFN_handler (const std::string &keyword, keyword_params_t ¶ms); + static void SGFN_handler (const std::string &keyword, keyword_params_t ¶ms); + static void SOF3_handler (const std::string &keyword, keyword_params_t ¶ms); + static void SOF2_handler (const std::string &keyword, keyword_params_t ¶ms); + static void EQUIL_handler (const std::string &keyword, keyword_params_t ¶ms); + static void PRVD_handler (const std::string &keyword, keyword_params_t ¶ms); + static void RSVD_handler (const std::string &keyword, keyword_params_t ¶ms); + static void PBVD_handler (const std::string &keyword, keyword_params_t ¶ms); + static void START_handler (const std::string &keyword, keyword_params_t ¶ms); + static void DATE_handler (const std::string &keyword, keyword_params_t ¶ms); + static void DATES_handler (const std::string &keyword, keyword_params_t ¶ms); + static void TSTEP_handler (const std::string &keyword, keyword_params_t ¶ms); + static void TSTEPS_handler (const std::string &keyword, keyword_params_t ¶ms); + static void WELLDIMS_handler (const std::string &/*keyword*/, keyword_params_t &/*params*/) + { + BOSOUT << "WELLDIMS: NOT_IMPL_YET" << bs_end; + } + }; + +}//ns bs + +#endif //KEYWORD_MANAGER_H_ + diff --git a/bs_bos_core/include/macroses.h b/bs_bos_core/include/macroses.h new file mode 100644 index 0000000..3eb4442 --- /dev/null +++ b/bs_bos_core/include/macroses.h @@ -0,0 +1,75 @@ +#ifndef __MACROSES_H__ +#define __MACROSES_H__ +/*! + * \file macroses.h + * \brief usefull macroses + * \author Borschuk Oleg + * \date 2005-09-26 + */ +#include "memory_macroses.h" +#include "debug_macroses.h" + +//! calculate vector from begin and end points, N_S -- start point, N_E -- end point, V -- output vector +#define CALC_VECTOR(N_S,N_E,V) (V)[0] = (N_E).array[0] - (N_S).array[0];(V)[2] = (N_E).array[2] - (N_S).array[2];(V)[1] = (N_E).array[1] - (N_S).array[1]; + +//! calculate triange area, V1 -- first vector, V2 -- second vector +#define CALC_TRIANGLE_AREA(V1,V2) (0.5 * fabs((V1)[1] * (V2)[2] - (V1)[2] * (V2)[1] + (V1)[2] * (V2)[0] - (V1)[0] * (V2)[2] + (V1)[0] * (V2)[1] - (V1)[1] * (V2)[0])) + +//! calculate vect mult +#define CALC_VECT_MULT(V1,V2,R) \ + R[0] = (V1)[1] * (V2)[2] - (V1)[2] * (V2)[1]; \ + R[1] = (V1)[2] * (V2)[0] - (V1)[0] * (V2)[2]; \ + R[2] = (V1)[0] * (V2)[1] - (V1)[1] * (V2)[0]; + +//! calculate vect norm +#define CALC_VECT_NORM(V) sqrt((V)[0] * (V)[0] + (V)[1] * (V)[1] + (V)[2] * (V)[2]) +//! calculate geometric average +#define CALC_GEOM_AVERAGE(D1,D2) ((D1) * (D2) / ((D1) + (D2))) + +//! calculate cell ijk index from linear index IND -- linear index, NX, NY, NZ -- dimens, I, J, K -- output indexes +#define CALC_IJK_FROM_INDEX(IND,NX,NY,NZ,I,J,K) \ + (K) = (int)((IND) / ((NX) * (NY))); \ + (IND) -= (K) * (NX) * (NY); \ + (J) = (int)((IND) / (NX)); \ + (I) = (IND) - (J) * (NX); + +//! calculate cell ijk index from linear index IND -- linear index, NX, NY, NZ -- dimens, I, J, K -- output indexes +//Defined by GataullinT +#define CALC_INDEX_FROM_IJK(IND,NX,NY,NZ,I,J,K) \ +IND = I + J * NX + K * NX * NY \ + + +/////////////////// UFASOLVER VERSION AND DEMO //////////////////////////////////// +#if defined(_UFASOLVER_DEMO_VERSION_) || defined(_SGM_KERNEL_DEMO_) +//! max number of elements in mesh +#define DEMO_MAX_NUMBER_OF_ELEMENTS 1000 +//! max number of wells in reservoir status +#define DEMO_MAX_NUMBER_OF_WELLS 10 +//! check mesh elements +#define CHECK_DEMO_VERSION(N) \ +if ((N) > DEMO_MAX_NUMBER_OF_ELEMENTS) \ + { \ + rep->print (LOG_INIT_SECTION, LOG_CRIT, \ + GET_TEXT ("\nSorry, but this DEMO version not support meshes larger than %d grid blocks.\n"), DEMO_MAX_NUMBER_OF_ELEMENTS); \ + rep->print (LOG_INIT_SECTION, LOG_CRIT, \ + GET_TEXT ("For purchase full version please email on bos@ngt.ru \nor see http://www.ngt.ru/soft/bos.html for more information.\n")); \ + return -13; \ + } +//! check number of wells +#define CHECK_DEMO_WELLS(OBJECT,RET) \ + if ((OBJECT)->demo_well_count > DEMO_MAX_NUMBER_OF_WELLS) \ + { \ + rep->print (LOG_INIT_SECTION, LOG_CRIT, \ + GET_TEXT ("\nSorry, but this DEMO version not support number of wells greater than %d.\n"), DEMO_MAX_NUMBER_OF_WELLS); \ + rep->print (LOG_INIT_SECTION, LOG_CRIT, \ + GET_TEXT ("For purchase full version please email on bos@ngt.ru \nor see http://www.ngt.ru/soft/bos.html for more information.\n")); \ + return (RET); \ + } +#endif // _UFASOLVER_DEMO_VERSION_ + +//! Minimum of a and b +#define MIN(a,b) ((a)<(b)?(a):(b)) +//! Maximum of a and b +#define MAX(a,b) ((a)<(b)?(b):(a)) + +#endif //__MACROSES_H__ diff --git a/bs_bos_core/include/main_loop_calc.h b/bs_bos_core/include/main_loop_calc.h new file mode 100644 index 0000000..6ee8310 --- /dev/null +++ b/bs_bos_core/include/main_loop_calc.h @@ -0,0 +1,1085 @@ +/** + * + * */ +#ifndef BS_MAIN_LOOP_CALC_H_ +#define BS_MAIN_LOOP_CALC_H_ + +#include "data_storage_interface.h" +#include "event_manager.h" + +#include "well_rate_control.h" + +#include "string_formater.h" +#include "well_type_helper.h" +#include "well_connection.h" +#include "calc_well.h" +#include "rr_rw_wr_saver.h" + +#include "save_connection_data.h" + +#include "fi_operator.h" +#include "jacobian_impl.h" +#include "well_results_storage.h" +#include "fip_results_storage.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "scale_array_holder.h" +#include "print_process_memory_info.h" +#include "path_tools.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "well_reporter.h" + +namespace blue_sky + { + + template + struct main_loop_calc_base + { + typedef event_manager event_manager_t; + typedef typename event_manager_t::sp_event_base_list sp_event_base_list_t; + + virtual ~main_loop_calc_base () {} + + virtual void ready () = 0; + virtual void go () = 0; + virtual void end () = 0; + + virtual void apply_events (const sp_event_base_list_t &) = 0; + }; + + template + struct main_loop_calc : public main_loop_calc_base + { + typedef main_loop_calc_base base_t; + typedef main_loop_calc this_t; + + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef calc_model calc_model_t; + typedef event_manager event_manager_t; + typedef rock_grid rock_grid_t; + typedef reservoir reservoir_t; + typedef rs_mesh_iface mesh_iface_t; + typedef jacobian jacobian_t; + typedef reservoir_simulator reservoir_simulator_t; + typedef idata idata_t; + typedef typename calc_model_t::scal_3p_t scal_3p_t; + typedef jacobian_matrix jmatrix_t; + + typedef typename event_manager_t::sp_event_base_list sp_event_base_list_t; + typedef trans_multipliers_calc trans_multipliers_calc_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_event_manager_t; + typedef smart_ptr sp_rock_grid_t; + typedef smart_ptr sp_reservoir_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_jacobian_t; + typedef smart_ptr sp_fi_params_t; + typedef smart_ptr sp_storage_t; + typedef smart_ptr sp_rs_t; + typedef smart_ptr sp_idata_t; + typedef typename calc_model_t::sp_scal3p sp_scal3p_t; + typedef smart_ptr sp_jmatrix_t; + + typedef boost::posix_time::ptime ptime; + + main_loop_calc (const sp_rs_t &rs) + : rs_ (rs) + , calc_model_ (rs->cm) + , event_manager_ (rs->em) + , rock_grid_prop_ (calc_model_->rock_grid_prop) + , facility_storage_ (rs->facility_storage_) + , reservoir_ (rs->reservoir_) + , mesh_ (rs->mesh) + , jacobian_ (rs->jacobian_) + , params_ (calc_model_->ts_params) + , data_map_ (rs->dm->data) + , height_ (0) + , rho_ (0) + { + number_of_newtonian_iterations = 0; + number_of_linear_iterations = 0; + number_of_restarts = 0; + number_of_max_iters_restarts = 0; + number_of_fi_operator_restarts = 0; + number_of_close_wells_restarts = 0; + + large_time_step_length_ = 0; + large_time_step_start_ = 0; + large_time_step_end_ = 0; + + num_last_newton_iters_ = 0; + num_last_lin_iters_ = 0; + + number_of_small_time_steps = 0; + number_of_large_time_steps = 1; + + height_ = 0; + rho_ = 0; + min_z_ = 0; + max_z_ = 0; + dt_ = 0; + current_time_ = 0; + + do_calc_prev_fluid_volume_ = true; + + if (calc_model_->n_phases > 1) + { + if (calc_model_->phase_d[FI_PHASE_WATER] != calc_model_->sat_d[FI_PHASE_WATER]) + bs_throw_exception ((boost::format ("Phase index (%d) for water should be equal to saturation index (%d)") % calc_model_->phase_d[FI_PHASE_WATER] % calc_model_->sat_d[FI_PHASE_WATER]).str ()); + + if (calc_model_->phase_d[FI_PHASE_GAS] != calc_model_->sat_d[FI_PHASE_GAS]) + bs_throw_exception ((boost::format ("Phase index (%d) for gas should be equal to saturation index (%d)") % calc_model_->phase_d[FI_PHASE_GAS] % calc_model_->sat_d[FI_PHASE_GAS]).str ()); + } + } + + inline void + fi_operator_cells (index_t i) + { + sp_jmatrix_t jmatrix = jacobian_->get_jmatrix (); + fi_operator_impl fi_operator_impl_ (calc_model_, reservoir_, mesh_, jacobian_, jmatrix); + fi_operator_impl_.fi_operator_init (i, dt_); + } + + inline void + apply_events (const sp_event_base_list_t &event_list) + { + typename sp_event_base_list_t::const_iterator it = event_list.begin (); + typename sp_event_base_list_t::const_iterator e = event_list.end (); + + for (; it != e; ++it) + { + (*it)->apply (reservoir_, mesh_, calc_model_); + } + } + + inline void + compute_jacobian () + { + reservoir_->compute_jacobian (calc_model_); + } + + inline item_t + get_dt () const + { + //if (ts_it != ts_it_end && (int)ts_it->size () > small_time_step_num && use_timestep_file) + // { + // dt = (*ts_it)[small_time_step_num].step; + // if (t + dt > large_time_step_end) + // dt = large_time_step_end - t; + // } + //else if (ts->ts_params.check_d_params (FI_PARAMS_D_FIRST_TS) + // || (small_time_step_num == 0 && !l_time_step_num)) + + // { + // dt = model_base->ts_params.get_d_param (FI_PARAMS_D_FIRST_TS); + // printf ("hello\n"); + // } + //else + // dt = model_base->increase_ts (dt, large_time_step_end - t, nniters); + + // miryanov + if (/*get_first_ts () || */(number_of_small_time_steps == 0 && !number_of_large_time_steps)) + { + BOSOUT (section::app_info, level::debug) << "number_of_small_time_steps == 0 && !number_of_large_time_steps" << bs_end; + return (std::min ) (1.0/*get_first_ts ()*/, (item_t)large_time_step_end_); + } + else + { + BOSOUT (section::main_loop, level::low) << "increase_ts" << bs_end; + return increase_ts (dt_, large_time_step_end_ - current_time_, num_last_newton_iters_); + } + } + + inline void + init_custom_wells (const sp_calc_model_t &calc_model) + { + reservoir_->init_custom_wells (calc_model); + } + + inline void + process_small_steps () + { + setup_jacobian_solver_params (); + + sp_jmatrix_t jmatrix = jacobian_->get_jmatrix (); + fi_operator_impl fi_operator (calc_model_, reservoir_, mesh_, jacobian_, jmatrix); + jacobian_impl jacobian_impl_ (jacobian_, jmatrix); + + for (number_of_small_time_steps = 0; current_time_ < large_time_step_end_ - EPS_DIFF; ++number_of_small_time_steps) + { + do_calc_prev_fluid_volume_ = true; + dt_ = get_dt (); + save_base_vars (); + + for (;;) + { + // no neighbours + calc_model_->approx_flag = false; + if (get_clamp_pressure ()) + compute_solution_range (); + + rs_->on_small_step_start (); + index_t ret_code = compute_small_time_step (fi_operator, jacobian_impl_, num_last_newton_iters_, num_last_lin_iters_); + if (ret_code >= 0 && ret_code <= get_newton_iters_num ()) + { + if (!process_well_model ()) + break; + else + { + do_calc_prev_fluid_volume_ = false; + continue; + } + } + else if (ret_code >= 0) + { + newton_iter_fail(ret_code); + } + } + + newton_iter_success(); + } + } + + BS_FORCE_INLINE + void + newton_iter_fail (size_t ret_code) + { + restore_base_vars (); + item_t old_dt = dt_; + dt_ = decrease_ts (dt_, large_time_step_end_ - current_time_); + + BOSOUT (section::main_loop, level::low) << "have to decrease dt " << old_dt << " -> " << (double)dt_ << bs_end; + if (fabs (old_dt - dt_) < 1.0e-12) + { + throw bs_exception ("process_small_step", "Newton process failed"); + } + + if (ret_code > get_newton_iters_num ()) + { + update_number_of_fi_operator_restarts (); + update_number_of_restarts (); + } + else if (ret_code == get_newton_iters_num ()) + { + update_number_of_max_iters_restarts (); + update_number_of_restarts (); + } + + do_calc_prev_fluid_volume_ = false; + rs_->on_newton_iter_fail (); + } + BS_FORCE_INLINE + void + newton_iter_success () + { + update_number_of_newtonian_iterations (num_last_newton_iters_); + update_number_of_linear_iterations (num_last_lin_iters_); + update_current_time (dt_); + + fi_borates_total (); + + //save_newton_iter_info (); + + //print_saturation (); + //print_pressure (); + //print_volume (); + + + BOSOUT (section::main_loop, level::high) + << (boost::format ("Info: Newtonian iteration [%d], linear interations [%d]") % (size_t)num_last_newton_iters_ % (size_t)num_last_lin_iters_).str () << "\n" + << (boost::format (" dt: [%10.20lf] on time [%10.20lf]") % (double)dt_ % (double)current_time_).str () << bs_end; + + rs_->on_newton_iter_success (); + } + + inline void + save_newton_iter_info () + { + static FILE *file = fopen ("newton_iter_info.bs.txt", "wt"); + if (!file) + { + throw bs_exception ("can't open file", ""); + } + + fprintf (file, "newtonian iters: %d, linear iters: %d, dt = %.20e on time = %.20e\n", (int)num_last_newton_iters_, (int)num_last_lin_iters_, (double)dt_, (double)current_time_); + fflush (file); + } + + void + print_saturation () + { + static size_t iter_counter = 0; + ++iter_counter; + tools::save_seq_vector (tools::string_formater ("nw_saturation.bs.%d.txt", iter_counter).str).save (calc_model_->saturation_3p); + } + void + print_pressure () + { + static size_t iter_counter = 0; + ++iter_counter; + tools::save_seq_vector (tools::string_formater ("nw_pressure.bs.%d.txt", iter_counter).str).save (calc_model_->pressure); + } + + void + print_volume () + { + static size_t iter_counter = 0; + ++iter_counter; + tools::save_seq_vector (tools::string_formater ("nw_volumes.bs.%d.txt", iter_counter).str).save (calc_model_->rock_grid_prop->volume); + } + + inline bool + process_well_model () + { + if (calc_model_->well_model_var_ == WELL_MODEL_1VAR) + { + return process_well_model_1var (); + } + if (calc_model_->well_model_var_ == WELL_MODEL_3VAR) + { + return process_well_model_3var (); + } + + return false; + } + + inline bool + process_well_model_1var () + { + int ret_code = fi_borates_check_well_consistensy (); + if (ret_code < 0) + { + restore_base_vars (); + + //TODO: LOG + update_number_of_restarts (); + } + else if (ret_code > 0) + { + restore_base_vars (); + + item_t old_dt = dt_; + dt_ = decrease_ts (dt_, large_time_step_end_ - current_time_); + + if (fabs (old_dt - dt_) < 1.0e-12) + { + throw bs_exception ("process_well_model_1var", "Newton process failed"); + } + + update_number_of_restarts (); + } + + return ret_code != 0; + } + + inline bool + process_well_model_3var () + { + if (false) + { + restore_base_vars (); + + // TODO: LOG + + update_number_of_close_wells_restarts (); + update_number_of_restarts (); + return true; + } + + return false; + } + + inline void + fi_borates_total () + { + // TODO: MPI staff + compute_acc_rates (); + } + + inline index_t + fi_borates_check_well_consistensy () + { + BS_ASSERT (false && "NOT IMPL YET"); + return 0; + } + + inline void + set_approx_solution () + { + BS_ASSERT (false && "NOT IMPL YET. IN OLD CODE TOO."); + } + + inline item_t + get_newton_iters_num () const + { + return params_->get_int (fi_params::NEWTON_ITERS_NUM); + } + + inline item_t + get_clamp_pressure () const + { + return params_->get_bool (fi_params::CLAMP_PRESSURE); + } + + inline item_t + get_max_tolerance () const + { + return params_->get_float (fi_params::MAX_ALLOWED_LIN_SOLV_RESID); + } + + inline item_t + get_small_ts () const + { + return 10 * params_->get_float (fi_params::MIN_TS); + } + inline item_t + get_first_ts () const + { + BOSOUT (section::main_loop, level::low) << "get_first_ts: " << params_->get_float (fi_params::FIRST_TS) << bs_end; + return params_->get_float (fi_params::FIRST_TS); + //return params_->check_value (fi_params::FIRST_TS); + } + + inline index_t + get_n_max_iters () const + { + if (calc_model_->approx_flag) + return params_->get_int (fi_params::APPROX_STEPS); + else + return params_->get_int (fi_params::NEWTON_ITERS_NUM); + } + inline index_t + get_istart () const + { + return 1; + } + + inline index_t + compute_small_time_step (fi_operator_impl &fi_operator, + jacobian_impl &jacobian_impl_, + index_t &nniters, index_t &nliters) + { + index_t max_n_iters = get_n_max_iters (); + index_t istart = get_istart (); + nniters = 0; + nliters = 0; + + for (index_t i = 0; i < max_n_iters + 1; ++i, ++nniters) + { + int init = (i == 0) ? istart : 0; + + if (do_calc_prev_fluid_volume_ && init) + fi_operator.calc_prev_fluid_volume (); + + if (istart && !number_of_small_time_steps) + { + set_approx_solution (); + } + + if (false) + generate_numeric_jacobian (init); + + rs_->on_before_fi_operator (); + fi_operator_return_type finish_flag = fi_operator.fi_operator (dt_, init, init, number_of_small_time_steps, true, false); + if (finish_flag == FI_OPERATOR_RETURN_RESTART || i == max_n_iters) + { + return max_n_iters + 1; + } + else if (finish_flag == FI_OPERATOR_RETURN_FAIL) + { + return i; + } + + rs_->on_before_jacobian_setup (); + jacobian_impl_.setup_jacobian (); + + rs_->on_before_jacobian_solve (); + index_t n_current_liters = 0; + item_t tolerance = jacobian_impl_.solve_jacobian (n_current_liters); + if (tolerance > get_max_tolerance ()) + { + return max_n_iters + 1; + } + nliters += n_current_liters; + + rs_->on_before_restore_solution (); + fi_operator.save_prev_niter_vars (); + restore_solution_return_type ret_code = calc_model_->restore_solution (fi_operator.mesh_, fi_operator.jmatrix_); + if (ret_code == SMALL_TIME_STEP_CHOP) + { + check_time_step (); + } + else if (ret_code == SMALL_TIME_STEP_FAIL) + { + return max_n_iters + 1; + } + + reservoir_->restore_wells_solution (dt_, fi_operator.sol_, fi_operator.jmatrix_->get_sec_solution (), calc_model_->n_phases); + } + + return max_n_iters + 1; + } + + void print_memory_at_the_end () + { +#ifdef BS_BOS_CORE_DEBUG_MEMORY + BOSOUT (section::app_info, level::debug) << "at the end" << bs_end; + BS_KERNEL.get_memory_manager ().print_info (false); +#endif + } + void print_memory_before_jacobian_solve () + { +#ifdef BS_BOS_CORE_DEBUG_MEMORY + BOSOUT (section::app_info, level::debug) << "before solve_jacobian" << bs_end; + BS_KERNEL.get_memory_manager ().print_info (false); +#endif + } + void print_memory_before_jacobian_setup () + { +#ifdef BS_BOS_CORE_DEBUG_MEMORY + BOSOUT (section::app_info, level::debug) << "before setup_jacobian" << bs_end; + BS_KERNEL.get_memory_manager ().print_info (false); +#endif + } + void print_memory_before_fi_operator () + { +#ifdef BS_BOS_CORE_DEBUG_MEMORY + BOSOUT (section::app_info, level::debug) << "before fi_operator" << bs_end; + BS_KERNEL.get_memory_manager ().print_info (false); +#endif + } + + inline void + generate_numeric_jacobian (int init); + + inline void + compute_acc_rates (); + + inline void + check_time_step () + { + if (dt_ < get_small_ts ()) + { + throw bs_exception ("compute_small_step", "Non-Linear Equation Convergence Failure"); + } + } + + inline void + compute_solution_range () + { + get_min_max_z (); // TODO: should be called only once + + height_ = max_z_ - min_z_; // TODO: should be called only once + rho_ = calc_model_->get_initial_rho (height_); // TODO: should be called only once + + BS_ASSERT (min_z_ <= max_z_) (min_z_) (max_z_); + calc_model_->update_min_pressure_range (min_z_ - 10); + calc_model_->update_max_pressure_range (max_z_ + 10); + } + + inline void + setup_jacobian_solver_params () + { + jacobian_->setup_solver_params (calc_model_->well_model_type_, calc_model_->n_phases, params_); + } + inline void + setup_jacobian () + { + if (jacobian_->setup ()) + { + throw bs_exception ("compute_small_time_step", "return -1"); + } + } + inline item_t + solve_jacobian (index_t &n) + { + return jacobian_->solve (n); + } + + inline void + get_min_max_z () + { + item_t foo; + mesh_->get_dimensions_range (foo, foo, foo, foo, max_z_, min_z_); + } + + inline void + save_data () + { + reservoir_->save_data (facility_storage_); + } + + /** + * \brief check limits + * \return true for stop simulation and false in other cases + * */ + inline bool + check_limits () + { + return reservoir_->check_limits (params_); + } + + inline item_t + decrease_ts (double old_ts, double max_ts) const + { + double new_ts = old_ts * params_->get_float (fi_params::TS_DEC_MULT); + if (new_ts < params_->get_float (fi_params::MIN_TS)) + new_ts = params_->get_float (fi_params::MIN_TS); + if (new_ts > params_->get_float (fi_params::MAX_TS)) + new_ts = params_->get_float (fi_params::MAX_TS); + + if (new_ts * params_->get_float (fi_params::OVERDRAFT) > max_ts) + new_ts = max_ts; + + return new_ts; + } + + inline item_t + increase_ts (item_t old_ts, item_t max_ts, index_t n_iters) const + { + item_t new_ts; + index_t i, n; + item_t dp = 0; + item_t ds = 0; + item_t drs = 0; + item_t dp_max = 0; + item_t ds_max = 0; + item_t drs_max = 0; + item_t user_dp; + item_t user_ds; + item_t user_drs; + item_t user_omega; + item_t alpha; + item_t alpha2; + index_t ds_w, ds_g; + index_t flag = 0; + index_t dp_i = 0, ds_i = 0, drs_i = 0; + index_t n_left = 0, n_right = 0; + +#ifdef _MPI + item_t mpi_dp_max, mpi_ds_max, mpi_drs_max; +#endif //_MPI + + if (!params_->get_bool (fi_params::NEW_TS_SELECTION_ALGORITHM)) + { + if (n_iters <= params_->get_int (fi_params::NEWTON_ITERS_NUM) + - params_->get_int (fi_params::NEWTON_ITERS_INC)) + new_ts = old_ts * params_->get_float (fi_params::TS_INC_MULT); + else + new_ts = old_ts; + } + else + { + BS_ASSERT (mesh_); + + user_dp = params_->get_float (fi_params::TS_DP); + user_ds = params_->get_float (fi_params::TS_DS); + user_drs = params_->get_float (fi_params::TS_DRS); + user_omega = params_->get_float (fi_params::TS_OMEGA); + ds_w = calc_model_->sat_d[FI_PHASE_WATER]; + ds_g = calc_model_->sat_d[FI_PHASE_GAS]; + + n = (int)mesh_->get_n_active_elements(); + +#ifdef _MPI + n_left = 0;///mpi_decomp->get_recv_l (); + n_right = n;///mpi_decomp->get_n_local_own () + n_left; +#else //_MPI + n_left = 0; + n_right = n; +#endif //_MPI + + // calculate pressure and saturation changing + for (i = n_left; i < n_right; ++i) + { + dp = (calc_model_->pressure[i] - calc_model_->old_data_.pressure[i]); + if (fabs (dp_max) < fabs(dp)) + { + dp_max = dp; + dp_i = i; + } + } + + n_left *= (calc_model_->n_phases); + n_right *= (calc_model_->n_phases); + + if (calc_model_->n_phases > 1) + for (i = n_left; i < n_right; ++i) + { + ds = (calc_model_->saturation_3p[i] - calc_model_->old_data_.saturation_3p[i]); + if (fabs (ds_max) < fabs(ds)) + { + ds_max = ds; + ds_i = (int)(i / (calc_model_->n_phases)); + } + } + + if (FI_CHK_OIL_GAS (calc_model_->phases)) + { +#ifdef _MPI + n_left = 0;///mpi_decomp->get_recv_l (); + n_right = n;///mpi_decomp->get_n_local_own () + n_left; +#else //_MPI + n_left = 0; + n_right = n; +#endif //_MPI + for (i = n_left; i < n_right; ++i) + { + drs = (calc_model_->old_data_.gas_oil_ratio[i] - calc_model_->gas_oil_ratio[i]); + if (fabs(drs_max) < fabs(drs)) + { + drs_max = drs; + drs_i = i; + } + + } + } + +#ifdef _MPI + BS_ASSERT(false&&"MPI: NOT IMPL YET"); + //dp_max = fabs (dp_max); + //ds_max = fabs (ds_max); + //drs_max = fabs (drs_max); + //MPI_Allreduce (&dp_max, &mpi_dp_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + //MPI_Allreduce (&ds_max, &mpi_ds_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + //MPI_Allreduce (&drs_max, &mpi_drs_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + //dp_max = mpi_dp_max; + //ds_max = mpi_ds_max; + //drs_max = mpi_drs_max; +#endif //_MPI + + dp = (1.0 + user_omega) * user_dp / (dp_max + user_omega * user_dp); + if (calc_model_->n_phases > 1) + ds = (1.0 + user_omega) * user_ds / (ds_max + user_omega * user_ds); + drs = (1.0 + user_omega) * user_drs / (drs_max + user_omega * user_drs); + + BOSOUT (section::main_loop, level::low) + << "dp_max[ " << dp_i << "] = " << dp_max + << ", ds_max[" << ds_i << "] = " << ds_max + << ", drs_max[" << drs_i << "] = " << drs_max + << bs_end; + + alpha = dp; + + if (calc_model_->n_phases > 1) + if (ds < alpha) + { + alpha = ds; + flag = 1; + } + if (drs < alpha) + { + alpha = drs; + flag = 2; + } + //printf ("FLAG = %d\n", flag); + if (alpha < 1) + alpha = 1; + alpha2 = 1.0; + if (n_iters <= params_->get_int (fi_params::NEWTON_ITERS_NUM) - params_->get_int (fi_params::NEWTON_ITERS_INC)) + alpha2 = params_->get_float (fi_params::TS_INC_MULT); + if (alpha > alpha2) + alpha = alpha2; + new_ts = old_ts * alpha; + } + + if (new_ts < params_->get_float (fi_params::MIN_TS)) + new_ts = params_->get_float (fi_params::MIN_TS); + if (new_ts > params_->get_float (fi_params::MAX_TS)) + new_ts = params_->get_float (fi_params::MAX_TS); + + // select time step length + if (new_ts * params_->get_float (fi_params::OVERDRAFT) > max_ts) + new_ts = max_ts; + else if (new_ts > max_ts) + new_ts = max_ts; + else if (max_ts - new_ts < new_ts) + new_ts = max_ts * 0.5; + + BOSOUT (section::main_loop, level::low) << "increase ts: " << old_ts << " -> " << new_ts << bs_end; + return new_ts; + } + + // TODO: BAD DESIGN: + inline void + save_base_vars () + { + calc_model_->old_data_.save (calc_model_); + reservoir_->pre_small_step (); + } + inline void + restore_base_vars () + { +#ifdef _DEBUG + BOSOUT (section::main_loop, level::debug) << "restore_base_vars" << bs_end; +#endif + calc_model_->old_data_.restore (calc_model_); + reservoir_->restart_small_step (); + } + + inline void + update_number_of_newtonian_iterations (index_t nniters) + { + number_of_newtonian_iterations += nniters; + } + inline void + update_number_of_linear_iterations (index_t nliters) + { + number_of_linear_iterations += nliters; + } + inline void + update_current_time (item_t step_) + { + current_time_ += step_; + } + inline void + update_number_of_fi_operator_restarts () + { + ++number_of_fi_operator_restarts; + } + inline void + update_number_of_restarts () + { + ++number_of_restarts; + } + inline void + update_number_of_max_iters_restarts () + { + ++number_of_max_iters_restarts; + } + inline void + update_number_of_close_wells_restarts () + { + ++number_of_close_wells_restarts; + } + + + BS_FORCE_INLINE bool + update_large_time_step_length (const ptime ¤t_time, const ptime &next_time) + { + using namespace boost::posix_time; + + time_period tp (current_time, next_time); + time_duration td (tp.length ()); + + large_time_step_length_ = item_t (td.total_milliseconds ()) / item_t (24.0 * 60 * 60 * 1000); + + if (large_time_step_length_ > 0) + { + large_time_step_start_ = large_time_step_end_; + large_time_step_end_ = large_time_step_end_ + large_time_step_length_; + return true; + } + + return false; + } + + inline void + update_large_time_step_num () + { + ++number_of_large_time_steps; + } + + void + print_mesh_info () + { + BOSOUT (section::mesh, level::medium) << "mesh cells: " << mesh_->get_n_active_elements () << bs_end; + BOSOUT (section::mesh, level::medium) << "mesh connections: " << mesh_->get_n_connections () << bs_end; + } + + void + print_pvt_info () + { + for (size_t i = 0, cnt = calc_model_->pvt_water_array.size (); i < cnt; ++i) + { + calc_model_->pvt_water_array[i]->print (); + } + for (size_t i = 0, cnt = calc_model_->pvt_oil_array.size (); i < cnt; ++i) + { + calc_model_->pvt_oil_array[i]->print (); + } + for (size_t i = 0, cnt = calc_model_->pvt_gas_array.size (); i < cnt; ++i) + { + calc_model_->pvt_gas_array[i]->print (); + } + } + + typedef boost::posix_time::ptime ptime_t; + inline void + iteration (const ptime_t ¤t_time, const ptime_t &next_time, const sp_event_base_list_t &event_list) + { + using namespace boost::posix_time; + BOSOUT (section::main_loop, level::high) << "\nTIMESTEP " << boost::posix_time::to_simple_string (current_time) << "\n" << bs_end; + + if (update_large_time_step_length (current_time, next_time)) + { + rs_->pre_large_step (event_list); + //trans_multipliers_.apply (); + rs_->on_large_step_start (); + + process_small_steps (); + well_data_printer ::print_prod (data_map_, reservoir_); + well_data_printer ::print_inj (data_map_, reservoir_); + well_data_printer ::print_total_prod (data_map_, reservoir_); + + time_step_end ((int)event_list.size ()); + } + } + + inline void + time_step_end (int total_number_of_time_steps) + { + save_data (); + + check_limits (); + + update_large_time_step_num (); + + static size_t iter_counter = 0; + iter_counter++; + //connection_data.save_acc ("con_data.ts.bs.%d.txt", calc_model_, dt_, reservoir_->get_facility_list ()->wells_begin (), reservoir_->get_facility_list ()->wells_end (), iter_counter, current_time_, jacobian_->get_jmatrix ()->get_solution (), jacobian_->get_jmatrix ()->get_rhs ()); + + well_data.copy_well_data_to_storage (calc_model_, dt_, reservoir_->get_facility_list ()->wells_begin (), reservoir_->get_facility_list ()->wells_end (), iter_counter, current_time_); + +#ifdef _HDF5 + reservoir_->write_step_to_hdf5 (calc_model_, mesh_, jacobian_->get_jmatrix (), number_of_large_time_steps, total_number_of_time_steps, current_time_); +#endif + + BOSOUT (section::main_loop, level::high) << "number_of_large_time_steps: " << number_of_large_time_steps << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_small_time_steps: " << number_of_small_time_steps << bs_end; + + BOSOUT (section::main_loop, level::high) << "number_of_newtonian_iterations: " << number_of_newtonian_iterations << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_linear_iterations: " << number_of_linear_iterations << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_restarts: " << number_of_restarts << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_max_iters_restarts: " << number_of_max_iters_restarts << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_fi_operator_restarts: " << number_of_fi_operator_restarts << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_close_wells_restarts: " << number_of_close_wells_restarts << bs_end; + } + + inline void + ready () + { + print_mesh_info (); + print_pvt_info (); + + fi_operator_cells (0); + trans_multipliers_.apply (); + + dt_ = get_first_ts (); + save_base_vars (); + +#ifdef _HDF5 + reservoir_->open_hdf5_file (path::join (path::dirname (rs_->model_filename ()), "results.h5")); + reservoir_->write_mesh_to_hdf5 (mesh_); + boost::gregorian::date start_date = rs_->keyword_manager_->get_starting_date ().date (); + boost::gregorian::date base_date (1900, 1, 1); + double starting_date = (start_date - base_date).days () + 2; + reservoir_->get_hdf5_file ()->write_array ("/initial_data", "starting_date", &starting_date, 1); +#endif + } + + inline void + go () + { + typename event_manager ::event_map::iterator it = event_manager_->event_list.begin (); + typename event_manager ::event_map::iterator e = event_manager_->event_list.end (); + + rs_->on_simulation_start (); + for (--e; it != e; ++it) + { + typename event_manager ::event_map::iterator it2 = it; + ++it2; + + iteration (it->first, it2->first, it->second); + } + } + + inline void + end () + { +#ifdef _HDF5 + reservoir_->close_hdf5_file (); +#endif + + BOSOUT (section::main_loop, level::high) << "TOTAL: " << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_large_time_steps: " << number_of_large_time_steps << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_small_time_steps: " << number_of_small_time_steps << bs_end; + + BOSOUT (section::main_loop, level::high) << "number_of_newtonian_iterations: " << number_of_newtonian_iterations << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_linear_iterations: " << number_of_linear_iterations << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_restarts: " << number_of_restarts << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_max_iters_restarts: " << number_of_max_iters_restarts << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_fi_operator_restarts: " << number_of_fi_operator_restarts << bs_end; + BOSOUT (section::main_loop, level::high) << "number_of_close_wells_restarts: " << number_of_close_wells_restarts << bs_end; + } + + inline void + reset_init_approx () + { + reservoir_->reset_init_approx (); + } + inline void + reset_wells () + { + reservoir_->reinit_wells (true); + } + +public: + // don't change line order. never. + sp_rs_t rs_; + sp_calc_model_t calc_model_; + sp_event_manager_t event_manager_; + sp_rock_grid_t rock_grid_prop_; + sp_storage_t facility_storage_; + sp_reservoir_t reservoir_; + sp_mesh_iface_t mesh_; + sp_jacobian_t jacobian_; + sp_fi_params_t params_; + sp_idata_t data_map_; + trans_multipliers_calc_t trans_multipliers_; + +public: + item_t height_; + item_t rho_; + item_t min_z_; + item_t max_z_; + + double dt_; + double current_time_; + + item_t large_time_step_length_; + item_t large_time_step_start_; + item_t large_time_step_end_; + + index_t num_last_newton_iters_; + index_t num_last_lin_iters_; + + index_t number_of_small_time_steps; + index_t number_of_large_time_steps; + + index_t number_of_newtonian_iterations; + index_t number_of_linear_iterations; + index_t number_of_restarts; + index_t number_of_max_iters_restarts; + index_t number_of_fi_operator_restarts; + index_t number_of_close_wells_restarts; + + bool do_calc_prev_fluid_volume_; + + save_connection_data connection_data; + save_well_data well_data; + }; + + +} // namespace blue_sky + +#include "generate_numeric_jacobian.h" +#include "compute_acc_rates.h" + +#endif // #ifndef BS_MAIN_LOOP_CALC_H_ + diff --git a/bs_bos_core/include/matrix_inverse.h b/bs_bos_core/include/matrix_inverse.h new file mode 100644 index 0000000..e43ba59 --- /dev/null +++ b/bs_bos_core/include/matrix_inverse.h @@ -0,0 +1,116 @@ +/** + * + * */ +#ifndef BS_CALC_INVERSE_MATRIX_H_ +#define BS_CALC_INVERSE_MATRIX_H_ + +namespace blue_sky + { + + /*! + * \brief calculate inverse matrix + * \param n -- size of matrix + * \param matrix -- original matrix + * \return 0 if success + -1 else + */ + template + inline void + calc_inverse_matrix (int n, matrix_t &matrix) + { + BS_ASSERT (false && "NOT IMPL YET"); + + int i, j, k, l1, l2, l3, l; + typename matrix_t::value_type temp; + int *is = 0, *js = 0; + + if (!(is = new int[n]) || !(js = new int[n])) + { + throw bs_exception ("calc_inverse_matrix", "can't allocate memory"); + } + + //first step + for (k = 0; k < n; k++) + { + temp = 0.; + + for (i = k; i < n; i++) + for (j = k, l1 = i * n + k; j < n; j++, l1++) + if (fabs (matrix[l1]) > temp) + { + temp = fabs (matrix[l1]); + is[k] = i; + js[k] = j; + } + + if (temp < EPS_DIFF) + { + delete [] is; + delete [] js; + + throw bs_exception ("calc_inverse_matrix", "can't find inverse matrix"); + } + + if (is[k] != k) + for (j = 0, l1 = k * n, l2 = is[k] * n; j < n; j++, l1++, l2++) + { + temp = matrix[l1]; + matrix[l1] = matrix[l2]; + matrix[l2] = temp; + } + + if (js[k] != k) + for (i = 0, l1 = k, l2 = js[k]; i < n; i++, l1 += n, l2 += n) + { + temp = matrix[l1]; + matrix[l1] = matrix[l2]; + matrix[l2] = temp; + } + + l = k * n + k; + matrix[l] = 1. / matrix[l]; + + for (j = 0, l1 = k * n; j < n; j++, l1++) + if (j != k) + matrix[l1] *= matrix[l]; + + for (i = 0, l2 = k; i < n; i++, l2 += n) + if (i != k) + for (j = 0, l1 = i * n, l3 = k * n; j < n; j++, l1++, l3++) + if (j != k) + matrix[l1] -= matrix[l2] * matrix[l3]; + + for (i = 0, l1 = k; i < n; i++, l1 += n) + if (i != k) + matrix[l1] *= - matrix[l]; + } + + //second step + for (k = n - 1; k > -1; k--) + { + if (js[k] != k) + for (j = 0, l1 = k * n, l2 = js[k] * n; j < n; j++, l1++, l2++) + { + temp = matrix[l1]; + matrix[l1] = matrix[l2]; + matrix[l2] = temp; + } + + if (is[k] != k) + for (i = 0, l1 = k, l2 = is[k]; i < n; i++, l1 += n, l2 += n) + { + temp = matrix[l1]; + matrix[l1] = matrix[l2]; + matrix[l2] = temp; + } + } + + delete [] is; + delete [] js; + } + +} // namespace blue_sky + +#endif // #ifndef BS_CALC_INVERSE_MATRIX_H_ + + diff --git a/bs_bos_core/include/matrix_vector_op.h b/bs_bos_core/include/matrix_vector_op.h new file mode 100644 index 0000000..141d076 --- /dev/null +++ b/bs_bos_core/include/matrix_vector_op.h @@ -0,0 +1,102 @@ +/** + * \file matrix_vector_op.h + * \brief + * \author Sergey Miryanov + * \date 08.10.2009 + * */ +#ifndef BS_BOS_CORE_MATRIX_VECTOR_OP_H_ +#define BS_BOS_CORE_MATRIX_VECTOR_OP_H_ + +namespace blue_sky { + + template + struct v_minus_vs_prod + { + }; + + template <> + struct v_minus_vs_prod <1> + { + template + static BS_FORCE_INLINE void + eliminate (const b_t &b, const c_t &c, a_t &a) + { + a[0] -= b[0] * c; + } + }; + + template <> + struct v_minus_vs_prod <2> + { + template + static BS_FORCE_INLINE void + eliminate (const b_t &b, const c_t &c, a_t &a) + { + a[0] -= b[0] * c; + a[1] -= b[1] * c; + } + }; + + template <> + struct v_minus_vs_prod <3> + { + template + static BS_FORCE_INLINE void + eliminate (const b_t &b, const c_t &c, a_t &a) + { + a[0] -= b[0] * c; + a[1] -= b[1] * c; + a[2] -= b[2] * c; + } + }; + + template + struct m_minus_vv_prod + { + }; + + template <> + struct m_minus_vv_prod <1> + { + template + static BS_FORCE_INLINE void + eliminate (const b_t &b, const c_t &c, a_t &a) + { + a[0] -= b[0] * c[0]; + } + }; + template <> + struct m_minus_vv_prod <2> + { + template + static BS_FORCE_INLINE void + eliminate (const b_t &b, const c_t &c, a_t &a) + { + a[0] -= b[0] * c[0]; + a[1] -= b[0] * c[1]; + a[2] -= b[1] * c[0]; + a[3] -= b[1] * c[1]; + } + }; + template <> + struct m_minus_vv_prod <3> + { + template + static BS_FORCE_INLINE void + eliminate (const b_t &b, const c_t &c, a_t &a) + { + a[0] -= b[0] * c[0]; + a[1] -= b[0] * c[1]; + a[2] -= b[0] * c[2]; + a[3] -= b[1] * c[0]; + a[4] -= b[1] * c[1]; + a[5] -= b[1] * c[2]; + a[6] -= b[2] * c[0]; + a[7] -= b[2] * c[1]; + a[8] -= b[2] * c[2]; + } + }; + +} // namespace blue_sky + +#endif // #ifndef BS_BOS_CORE_MATRIX_VECTOR_OP_H_ diff --git a/bs_bos_core/include/member_accessor.h b/bs_bos_core/include/member_accessor.h new file mode 100644 index 0000000..1ed60b5 --- /dev/null +++ b/bs_bos_core/include/member_accessor.h @@ -0,0 +1,71 @@ +/** + * \file member_accessor.h + * \brief helper to adapt vector of calc_model_data to do save via tools::save_seq_vector (only for debug purpose) + * \author Sergey Miryanov + * \date 31.10.2008 + * */ +#ifndef BS_TOOLS_MEMBER_ACCESSOR_H_ +#define BS_TOOLS_MEMBER_ACCESSOR_H_ + +namespace blue_sky + { + namespace tools + { + + template + struct member_accessor + { + typedef item_t value_type; + + member_accessor (const data_array_t &data_, const item_t *data_begin_, const item_t *data_offset_, size_t size_) + : data_ (data_) + , data_begin_ (data_begin_) + , data_offset_ (data_offset_) + , size_ (size_) + { + } + + size_t + size_i () const + { + return data_.size (); + } + + size_t + size_j () const + { + return size_; + } + + item_t + get (size_t i, size_t j) const + { + const item_t *data = (const item_t *)&data_[i]; + size_t count = data_offset_ - data_begin_; + return data [count + j]; + } + +private: + const data_array_t &data_; + const item_t *data_begin_; + const item_t *data_offset_; + size_t size_; + }; + + +// use like +// +//#define SAVE_BOOST_ARRAY(name) \ +// tools::save_seq_vector (BOOST_PP_CAT (BOOST_PP_STRINGIZE(name), ".bs.txt")) \ +// .save_via_fn (member_accessor (data, (item_t *)&data[0], &data[0].name[0], data[0].name.size ())); +// +//#define SAVE_ITEM(name) \ +// tools::save_seq_vector (BOOST_PP_CAT (BOOST_PP_STRINGIZE(name), ".bs.txt")) \ +// .save_via_fn (member_accessor (data, (item_t *)&data[0], &data[0].name, 1)); + + + } // namespace tools +} // namespace blue_sky + +#endif // #ifndef BS_TOOLS_MEMBER_ACCESSOR_H_ + diff --git a/bs_bos_core/include/noncopyable_ptr.h b/bs_bos_core/include/noncopyable_ptr.h new file mode 100644 index 0000000..ecee84c --- /dev/null +++ b/bs_bos_core/include/noncopyable_ptr.h @@ -0,0 +1,51 @@ +/** + * \file noncopyable_ptr.h + * \brief type that act as a pointer but disable copying of owned ptr + * \author Sergey Miryanov + * \date 12.02.2009 + * */ +#ifndef BS_NONCOPYABLE_PTR_H_ +#define BS_NONCOPYABLE_PTR_H_ + +namespace blue_sky { + + template + struct nc_ptr : boost::noncopyable + { + + explicit nc_ptr (T *ptr) + : ptr_ (ptr) + { + } + + T *operator-> () + { + return ptr_; + } + const T *operator-> () const + { + return ptr_; + } + + bool + operator ! () const + { + return !ptr_; + } + + T * + get () + { + return ptr_; + } + + private: + + T *ptr_; + }; + + +} // namespace blue_sky + +#endif // BS_NONCOPYABLE_PTR_H_ + diff --git a/bs_bos_core/include/norm_calc.h b/bs_bos_core/include/norm_calc.h new file mode 100644 index 0000000..0155564 --- /dev/null +++ b/bs_bos_core/include/norm_calc.h @@ -0,0 +1,87 @@ +/** + * @file norm_cacl.h + * @brief calculate norms + * @author Borschuk Oleg + * @date 2008-01-31 + */ +#ifndef NORM_CALC_H +#define NORM_CALC_H + +namespace blue_sky + { + namespace norms + { + + //! enumerate norms + enum norms_consts + { + C_CPV = 0, //!< C-norm normalized by cell pore volume + C_CPV_GAS, //!< Gas C-norm normalized by cell pore volume + C_CPV_WATER, //!< Water C-norm normalized by cell pore volume + C_CPV_OIL, //!< Oil C-norm normalized by cell pore volume + //========== + C_ACPV, //!< C-norm normalized by average cell pore volume + C_ACPV_GAS, //!< Gas C-norm normalized by average cell pore volume + C_ACPV_WATER, //!< Water C-norm normalized by average cell pore volume + C_ACPV_OIL, //!< Oil C-norm normalized by average cell pore volume + //========== + L2_CPV, //!< L_2-norm normalized by cell pore volume + L2_CPV_GAS, //!< Gas L_2-norm normalized by cell pore volume + L2_CPV_WATER, //!< Water L_2-norm normalized by cell pore volume + L2_CPV_OIL, //!< Oil L_2-norm normalized by cell pore volume + //========== + L2_ACPV, //!< L_2-norm normalized by average cell pore volume + L2_ACPV_GAS, //!< Gas L_2-norm normalized by average cell pore volume + L2_ACPV_WATER, //!< Water L_2-norm normalized by average cell pore volume + L2_ACPV_OIL, //!< Oil L_2-norm normalized by average cell pore volume + //========== + MB_ERR, //!< math balans error + MB_ERR_GAS, //!< math balans error for gas + MB_ERR_WATER, //!< math balans error for water + MB_ERR_OIL, //!< math balans error for oil + //=========== + S_RHS, //!< max abs value of sec_rhs + + //========== next constant should be the last one ==== + NORMS_COUNTER + }; + + } // namespace norms + + /*! + * \brief class for storing different norms + */ + template + class norms_storage + { + public: + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef seq_vector name_array_t; + + public: + // default constructor + norms_storage (); + // default destructor + ~norms_storage (); + // clear all norms + void clear (); + + // print norms + //void print (const sp_mesh_grdecl msh); + + norms_storage &operator= (const norms_storage &rhs); + + // -------------------------------------- + // VARIABLES + // -------------------------------------- + public: + name_array_t name; + item_array_t val; + boost::array idx; + boost::array p_flag; + }; + +} // ns bs + +#endif // NORM_CALC_H diff --git a/bs_bos_core/include/pp_index.h b/bs_bos_core/include/pp_index.h new file mode 100644 index 0000000..8c2f3ff --- /dev/null +++ b/bs_bos_core/include/pp_index.h @@ -0,0 +1,79 @@ +/** + * \file pp_index.h + * \brief + * \author Sergey Miryanov + * \date 15.10.2009 + * */ +#ifndef BS_BOS_CORE_PP_INDEX_H_ +#define BS_BOS_CORE_PP_INDEX_H_ + +namespace blue_sky { +namespace detail { + + template + struct pp_index + { + }; + + template + struct pp_index <1, is_w, is_g> + { + enum + { + gas_po = 0, + oil_po = 0, + wat_po = 0, + + gas_sg = -1, gas_so = -1, + oil_sg = -1, oil_so = -1, + wat_sg = -1, wat_so = -1, + }; + }; + + template <> + struct pp_index <2, true, false> + { + enum + { + oil_so = 0, + oil_po = 1, + wat_so = 2, + wat_po = 3, + + gas_sg = -1, gas_so = -1, gas_po = -1, + oil_sg = -1, + wat_sg = -1, + }; + }; + template <> + struct pp_index <2, false, true> + { + enum + { + gas_sg = 0, + gas_po = 1, + oil_sg = 2, + oil_po = 3, + gas_so = 4, + oil_so = 5, + + wat_sg = -1, wat_so = -1, wat_po = -1, + }; + }; + + template + struct pp_index <3, is_w, is_g> + { + enum + { + gas_sg = 0, gas_so = 1, gas_po = 2, + oil_sg = 3, oil_so = 4, oil_po = 5, + wat_sg = 6, wat_so = 7, wat_po = 8, + }; + }; + +} // namespace detail +} // namespace blue_sky + + +#endif // #ifndef BS_BOS_CORE_PP_INDEX_H_ diff --git a/bs_bos_core/include/prepare_fpu.h b/bs_bos_core/include/prepare_fpu.h new file mode 100644 index 0000000..fbfd22c --- /dev/null +++ b/bs_bos_core/include/prepare_fpu.h @@ -0,0 +1,20 @@ +/** + * \file prepare_fpu.h + * \brief prepare fpu to work (enable exception, etc) + * \author Sergey Miryanov + * \date 10.09.2009 + * */ + +namespace blue_sky { +namespace tools { + + struct prepare_fpu + { + static void + enable_exceptions (); + }; + + +} // namespace tools +} // namespace blue_sky + diff --git a/bs_bos_core/include/py_calc_model.h b/bs_bos_core/include/py_calc_model.h new file mode 100644 index 0000000..4f4b296 --- /dev/null +++ b/bs_bos_core/include/py_calc_model.h @@ -0,0 +1,230 @@ +#ifndef PY_CALC_MODEL_H +#define PY_CALC_MODEL_H + +#include BS_FORCE_PLUGIN_IMPORT () +#include "py_pvt.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + template + class calc_model; + + template + struct calc_model_data; + + namespace python + { + + template + struct py_calc_model_data : calc_model_data + { + typedef py_calc_model_data this_t; + typedef calc_model_data base_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::index_t index_t; + + py_calc_model_data () : base_t () {} + py_calc_model_data (const base_t &cm) : base_t (cm) {} + + item_array_t get_cap_pressure () const; + item_array_t get_s_deriv_cap_pressure () const; + + item_array_t get_relative_perm () const; + item_array_t get_s_deriv_relative_perm () const; + + //item_t get_gas_oil_ratio () const; + item_t get_p_deriv_gas_oil_ratio () const; + + item_array_t get_invers_fvf () const; + item_array_t get_p_deriv_invers_fvf () const; + item_t get_gor_deriv_invers_fvf () const; + + item_array_t get_invers_viscosity () const; + item_array_t get_p_deriv_invers_viscosity () const; + item_t get_gor_deriv_invers_viscosity () const; + + item_array_t get_invers_visc_fvf () const; + item_array_t get_p_deriv_invers_visc_fvf () const; + item_t get_gor_deriv_invers_visc_fvf () const; + + item_array_t get_density () const; + item_array_t get_p_deriv_density () const; + item_t get_gor_deriv_density () const; + + item_t get_porosity () const; + item_t get_p_deriv_porosity () const; + + item_t get_truns_mult () const; + item_t get_p_deriv_truns_mult () const; + + item_array_t get_mobility () const; + item_array_t get_p_deriv_mobility () const; + item_array_t get_s_deriv_mobility () const; + + item_array_t get_prev_fluid_volume () const; + }; + + template + class py_scal_3p; + + template + class py_idata; + + template + class py_calc_model : public py_objbase + { + public: + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::index_t index_t; + + typedef calc_model wrapped_t; + typedef smart_ptr sp_cm_t; + + typedef py_idata py_idata_t; + + typedef py_calc_model_data py_calc_model_data_t; + + typedef typename wrapped_t::sp_fi_params sp_fi_params_t; + + public: + + py_calc_model (); + py_calc_model(const sp_cm_t &); + ~py_calc_model () {} + + py_pvt_water > + get_pvt_water (index_t n_pvt_region) const; + + py_pvt_gas > + get_pvt_gas (index_t n_pvt_region) const; + + py_pvt_oil > + get_pvt_oil (index_t n_pvt_region) const; + + // methods + item_array_t get_saturation (); + item_array_t get_pressure(); + item_array_t get_gas_oil_ratio(); + index_t get_pvt_num(); + index_t get_sat_num(); + index_t get_fip_num(); + + item_array_t get_plane_flow_rate (); + item_array_t get_full_step_plane_flow_rate (); + + index_array_t get_pvt_regions (); + index_array_t get_sat_regions (); + index_array_t get_fip_regions (); + index_array_t get_rock_regions (); + + index_array_t get_bconn_mainvar (); + + item_array_t get_bconn_pressure (); + item_array_t get_bconn_saturation (); + item_array_t get_bconn_gor (); + + py_scal_3p + get_scal () const; + + py_calc_model_data_t get_data (index_t) const; + + index_t cmd_num () const; + index_t all_data_len () const; + + index_t cap_pressure_len () const; + item_t get_cap_pressure (index_t, index_t) const; + + index_t s_deriv_cap_pressure_len () const; + item_t get_s_deriv_cap_pressure (index_t, index_t) const; + + index_t relative_perm_len () const; + item_t get_relative_perm (index_t, index_t) const; + + index_t s_deriv_relative_perm_len () const; + item_t get_s_deriv_relative_perm (index_t, index_t) const; + + index_t p_deriv_gas_oil_ratio_len () const; + item_t get_p_deriv_gas_oil_ratio (index_t, index_t) const; + + index_t invers_fvf_len () const; + item_t get_invers_fvf (index_t, index_t) const; + + index_t p_deriv_invers_fvf_len () const; + item_t get_p_deriv_invers_fvf (index_t, index_t) const; + + index_t gor_deriv_invers_fvf_len () const; + item_t get_gor_deriv_invers_fvf (index_t, index_t) const; + + index_t invers_viscosity_len () const; + item_t get_invers_viscosity (index_t, index_t) const; + + index_t p_deriv_invers_viscosity_len () const; + item_t get_p_deriv_invers_viscosity (index_t, index_t) const; + + index_t gor_deriv_invers_viscosity_len () const; + item_t get_gor_deriv_invers_viscosity (index_t, index_t) const; + + index_t invers_visc_fvf_len () const; + item_t get_invers_visc_fvf (index_t, index_t) const; + + index_t p_deriv_invers_visc_fvf_len () const; + item_t get_p_deriv_invers_visc_fvf (index_t, index_t) const; + + index_t gor_deriv_invers_visc_fvf_len () const; + item_t get_gor_deriv_invers_visc_fvf (index_t, index_t) const; + + index_t density_len () const; + item_t get_density (index_t, index_t) const; + + index_t p_deriv_density_len () const; + item_t get_p_deriv_density (index_t, index_t) const; + + index_t gor_deriv_density_len () const; + item_t get_gor_deriv_density (index_t, index_t) const; + + index_t porosity_len () const; + item_t get_porosity (index_t, index_t) const; + + index_t p_deriv_porosity_len () const; + item_t get_p_deriv_porosity (index_t, index_t) const; + + index_t truns_mult_len () const; + item_t get_truns_mult (index_t, index_t) const; + + index_t p_deriv_truns_mult_len () const; + item_t get_p_deriv_truns_mult (index_t, index_t) const; + + index_t mobility_len () const; + item_t get_mobility (index_t, index_t) const; + + index_t p_deriv_mobility_len () const; + item_t get_p_deriv_mobility (index_t, index_t) const; + + index_t s_deriv_mobility_len () const; + item_t get_s_deriv_mobility (index_t, index_t) const; + + index_t prev_fluid_volume_len () const; + item_t get_prev_fluid_volume (index_t, index_t) const; + + void initialize_datas (); + + int get_n_phases () const; + bool is_water () const; + bool is_gas () const; + bool is_oil () const; + + sp_fi_params_t get_fi_params () const; + + private: + }; + + void py_export_calc_model (); + } +} + +#endif // PY_CALC_MODEL_H diff --git a/bs_bos_core/include/py_calc_well.h b/bs_bos_core/include/py_calc_well.h new file mode 100644 index 0000000..6c18b6c --- /dev/null +++ b/bs_bos_core/include/py_calc_well.h @@ -0,0 +1,177 @@ +/** + * \file py_calc_well.h + * \brief python wrapper for calc_well + * \author Sergey Miryanov + * \date 23.06.2008 + * */ +#ifndef PY_BS_CALC_WELL_H_ +#define PY_BS_CALC_WELL_H_ + +#ifdef BSPY_EXPORTING_PLUGIN +#include "calc_well.h" +#include "well_connection.h" +#include "well_iterator.h" +#include "calc_model.h" +#include "py_calc_well_detail.h" +#include "facility_manager.h" + +#include "export_python_wrapper.h" + + +namespace blue_sky { +namespace python { + + STRATEGY_CLASS_WRAPPER (wells::connection, py_connection) + { + public: + + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; + + typedef wells::connection wrapped_t; + + public: + + STRATEGY_CLASS_WRAPPER_DECL (py_connection); + + WRAPPER_METHOD (clear_data, void, 0, (empty_arg__)); + WRAPPER_METHOD_R (get_rw_value, array_ext , 0, (empty_arg__)); + WRAPPER_METHOD_R (get_wr_value, array_ext , 0, (empty_arg__)); + WRAPPER_METHOD_R (get_rr_value, array_ext , 0, (empty_arg__)); + WRAPPER_METHOD_R (get_ps_value, array_ext , 0, (empty_arg__)); + WRAPPER_METHOD_R (get_rate_value, array_ext , 0, (empty_arg__)); + }; + + STRATEGY_CLASS_WRAPPER (well, py_well) + { + public: + + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + + typedef smart_ptr , true > sp_calc_model_t; + typedef smart_ptr , true > sp_mesh_iface_t; + typedef smart_ptr , true > sp_jmatrix_t; + + typedef well wrapped_t; + + public: + + STRATEGY_CLASS_WRAPPER_DECL (py_well); + + WRAPPER_METHOD_R (get_ww_value, array_ext , 0, (empty_arg__)); + WRAPPER_METHOD_R (get_bw_value, array_ext , 0, (empty_arg__)); + WRAPPER_METHOD (eliminate, void, 5, (rhs_item_t *, index_t, index_t, item_t, index_t)); + WRAPPER_METHOD (process, void, 5, (int, double, const sp_calc_model_t &, const sp_mesh_iface_t &, sp_jmatrix_t &)); + WRAPPER_METHOD (process_newton, void, 4, (int, const sp_calc_model_t &, const sp_mesh_iface_t &, sp_jmatrix_t &)); + WRAPPER_METHOD (restore_solution, void, 4, (double, const item_array_t &, const item_array_t &, index_t)); + WRAPPER_METHOD (clear_data, void, 0, (empty_arg__)); + }; + + PY_EXPORTER (connection_exporter, default_exporter) + .def ("clear_data", &T::clear_data) + .add_property ("rw", &T::get_rw_value) + .add_property ("wr", &T::get_wr_value) + .add_property ("rr", &T::get_rr_value) + .add_property ("ps", &T::get_ps_value) + .add_property ("rate", &T::get_rate_value) + .add_property ("head_term", &T::get_head_term, &T::set_head_term) + .add_property ("cur_bhp", &T::get_cur_bhp, &T::set_cur_bhp) + .add_property ("connection_depth", &T::get_connection_depth, &T::set_connection_depth) + .add_property ("density", &T::get_density, make_function (detail::set_connection_density)) + .add_property ("bulkp", &T::get_bulkp, &T::set_bulkp) + .add_property ("n_block", &T::n_block) + .add_property ("i", &T::i_coord) + .add_property ("j", &T::j_coord) + .add_property ("k", &T::k_coord) + .add_property ("fact", &T::get_fact) + .add_property ("gw", &T::get_fact) + .add_property ("is_shut", &T::is_shut) + PY_EXPORTER_END; + + PY_EXPORTER (well_exporter, default_exporter) + //.def ("eliminate", &T::eliminate) + .def ("process", &T::process) + .def ("update", &T::restore_solution) + .def ("clear_data", &T::clear_data) + //.def ("get_connection", &T::get_connection) + .add_property ("ww", &T::get_ww_value) + .add_property ("bw", &T::get_bw_value) + .add_property ("name", make_function (&T::get_name, return_value_policy ()), &T::set_name) + .add_property ("i_coord", make_function (detail::get_well_i_coord), make_function (detail::set_well_i_coord)) + .add_property ("j_coord", make_function (detail::get_well_j_coord), make_function (detail::set_well_j_coord)) + .add_property ("bhp_depth", &T::get_bhp_depth, &T::set_bhp_depth) + .add_property ("exploitation_factor", make_function (detail::get_well_wefac), &T::set_exploitation_factor) + .add_property ("state", make_function (detail::get_well_state)) + .add_property ("bhp_rate", &T::bhp) + .add_property ("is_work", make_function (detail::get_well_is_work), make_function (detail::set_well_is_work)) + .add_property ("connections", &T::get_connections_count) + .add_property ("is_production", make_function (detail::well_is_production)) + PY_EXPORTER_END; + + //template + //class py_well_iterator + // : public std::iterator< + // std::forward_iterator_tag, + // py_well, ptrdiff_t, + // py_well, py_well > + // { + // friend class py_well ; + + // public: + // typedef py_well py_well_t; + + // typedef py_well_iterator this_t; + + // typedef std::iterator< + // std::forward_iterator_tag, + // //std::bidirectional_iterator_tag, + // py_well, ptrdiff_t, + // py_well, py_well > base_t; + + // typedef typename base_t::reference reference; + // typedef typename base_t::pointer pointer; + + // typedef facility_manager facility_manager_t; + // typedef smart_ptr sp_facility_t; + + // typedef this_t wrapped_t; + // typedef typename facility_manager_t::well_const_iterator_t well_const_iterator_t; + // typedef well well_t; + // typedef smart_ptr sp_well_t; + + // sp_facility_t mgr; + // well_const_iterator_t ins; + + // public: + // py_well_iterator(const py_well_iterator &src); + // py_well_iterator(const sp_facility_t &mgr); + // ~py_well_iterator(); + + // reference operator*() const; + // pointer operator->() const; + + // py_well_iterator& operator++(); + // py_well_iterator operator++(int); + + // py_well_t next (); + + // //py_well_iterator& operator--(); + // //py_well_iterator operator--(int); + + // bool operator ==(const py_well_iterator &ritr) const; + // bool operator !=(const py_well_iterator &ritr) const; + // const this_t &operator =(const this_t &ritr); + // }; + + void + py_export_calc_well (); + +} // namespace python +} // namespace blue_sky + +#endif // BSPY_EXPORTING_PLUGIN +#endif // #ifndef PY_BS_CALC_WELL_H_ diff --git a/bs_bos_core/include/py_calc_well_detail.h b/bs_bos_core/include/py_calc_well_detail.h new file mode 100644 index 0000000..1e37378 --- /dev/null +++ b/bs_bos_core/include/py_calc_well_detail.h @@ -0,0 +1,86 @@ +/** + * \file py_calc_well_detail.h + * \brief + * \author Sergey Miryanov + * \date 01.07.2009 + * */ +#ifndef BS_BOS_CORE_PY_CALC_WELL_DETAIL_H_ +#define BS_BOS_CORE_PY_CALC_WELL_DETAIL_H_ + +namespace blue_sky { +namespace python { +namespace detail { + + template + static void + set_connection_density (connection_t *c, double density) + { + c->density = density; + } + + template + static typename well_t::index_t + get_well_i_coord (const well_t *well) + { + return well->i_coord_; + } + template + static typename well_t::index_t + get_well_j_coord (const well_t *well) + { + return well->j_coord_; + } + template + static void + set_well_i_coord (well_t *well, typename well_t::index_t i) + { + well->i_coord_ = i; + } + template + static void + set_well_j_coord (well_t *well, typename well_t::index_t j) + { + well->j_coord_ = j; + } + + template + static typename well_t::item_t + get_well_wefac (const well_t *well) + { + return well->exploitation_factor_; + } + + template + static typename well_t::index_t + get_well_state (const well_t *well) + { + return well->well_state_.state; + } + + template + static bool + get_well_is_work (const well_t *well) + { + return well->well_state_.is_work; + } + template + static void + set_well_is_work (well_t *well, bool is_work) + { + well->well_state_.is_work = is_work; + } + template + static bool + well_is_production (const well_t *well) + { + return well->get_controller ()->is_production (); + } + +} // namespace detail +} // namespace python +} // namespace blue_sky + +#endif // #ifndef BS_BOS_CORE_PY_CALC_WELL_DETAIL_H_ + + + diff --git a/bs_bos_core/include/py_csr_ilu_cfl_prec.h b/bs_bos_core/include/py_csr_ilu_cfl_prec.h new file mode 100644 index 0000000..503fd5f --- /dev/null +++ b/bs_bos_core/include/py_csr_ilu_cfl_prec.h @@ -0,0 +1,28 @@ +/** + * \file py_csr_ilu_cfl_prec.h + * \brief Python wrapper for csr_ilu_cfl_prec + * \author Salimgareeva Elmira + * \date 28.09.2009 + */ + +#ifndef PY_CSR_ILU_CFL_PREC_H_ +#define PY_CSR_ILU_CFL_PREC_H_ + +#ifdef BSPY_EXPORTING_PLUGIN + +#include "csr_ilu_cfl.h" + +namespace blue_sky + { + namespace python + { + + //! export wrappers to python + void + py_export_csr_ilu_cfl_prec (); + + } // namespace python + } // namespace blue_sky +#endif // #ifdef BSPY_EXPORTING_PLUGIN + +#endif // #ifndef PY_CSR_ILU_CFL_PREC_H_ diff --git a/bs_bos_core/include/py_data_storage_interface.h b/bs_bos_core/include/py_data_storage_interface.h new file mode 100644 index 0000000..f14a97a --- /dev/null +++ b/bs_bos_core/include/py_data_storage_interface.h @@ -0,0 +1,97 @@ +/** + * \file py_data_storage_interface.h + * \brief python wrapper for + * \author Sergey Miryanov + * \date 23.07.2008 + * */ +#ifndef BS_PY_DATA_STORAGE_INTERFACE_H_ +#define BS_PY_DATA_STORAGE_INTERFACE_H_ + +#include "data_storage_interface.h" + +namespace blue_sky + { + namespace python + { + + + class BS_API_PLUGIN py_data_storage : public py_objbase + { + public: + + typedef py_objbase base_t; + + public: + + py_data_storage (PyObject *self); + virtual ~py_data_storage (); + + void save (const std::string &name, const std::string &value); + void save_default (const std::string &name, const std::string &value); + + private: + + PyObject *self_; + }; + + class BS_API_PLUGIN py_data_serializer : public py_objbase, public data_serializer + { + public: + + typedef data_serializer wrapped_t; + typedef py_objbase base_t; + + public: + + py_data_serializer (PyObject *self) + : base_t (this) + , self_ (self) + { + + } + + void save (const sp_storage_t &storage, const sp_obj &obj); + void save_impl (py_data_storage storage, py_objbase obj); + + private: + + PyObject *self_; + }; + + + class BS_API_PLUGIN py_data_storage_interface : public py_objbase + { + public: + + typedef data_storage_interface wrapped_t; + typedef py_objbase base_t; + + public: + + py_data_storage_interface () + : base_t (wrapped_t::bs_type ()) + { + + } + + + void save (const py_objbase &obj); + + // see py_data_serializer::save for explanation + //void register_serializer (py_data_serializer *serializer); + + void set_storage (const py_data_storage &storage); + }; + + bool + data_storage_proxy_register_type (const blue_sky::plugin_descriptor &pd); + + void + py_export_data_storage_interface (); + + } // namespace python +} // namespace blue_sky + + + +#endif // #ifndef BS_PY_DATA_STORAGE_INTERFACE_H_ diff --git a/bs_bos_core/include/py_default_wells.h b/bs_bos_core/include/py_default_wells.h new file mode 100644 index 0000000..01b494c --- /dev/null +++ b/bs_bos_core/include/py_default_wells.h @@ -0,0 +1,20 @@ +/** + * \file py_default_wells.h + * \brief + * \author Sergey Miryanov + * \date 22.05.2009 + * */ +#ifndef BS_BOS_CORE_PY_DEFAULT_WELLS_H_ +#define BS_BOS_CORE_PY_DEFAULT_WELLS_H_ + +namespace blue_sky { +namespace python { + + void + py_export_default_wells (); + +} +} // namespace blue_sky + + +#endif // #ifndef BS_BOS_CORE_PY_DEFAULT_WELLS_H_ diff --git a/bs_bos_core/include/py_event_base.h b/bs_bos_core/include/py_event_base.h new file mode 100644 index 0000000..57e8f1f --- /dev/null +++ b/bs_bos_core/include/py_event_base.h @@ -0,0 +1,217 @@ +#ifndef PY_EVENT_BASE_H +#define PY_EVENT_BASE_H + +#include "event_base.h" +#include "event_manager.h" + +#include "calc_model.h" +#include "reservoir.h" + +#include "export_python_wrapper.h" + +#include "py_reservoir.h" +#include "py_calc_model.h" + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +namespace blue_sky { +namespace python { + + STRATEGY_CLASS_WRAPPER (event_base, py_event_base) + { + public: + typedef rs_mesh_iface mesh_t; + typedef reservoir reservoir_t; + typedef py_calc_model py_calc_model_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_reservoir_t; + typedef event_base base_t; + + public: + MAKE_ME_HAPPY (py_event_base, py_event_base_base , "py_event_base"); + //WRAPPER_METHOD (apply, void, 3, (const sp_reservoir_t &, const py_mesh_iface_t &, const py_calc_model_t &)); + }; + + // template + // class BS_API_PLUGIN py_event_base : public py_event_base_pv_holder + // , public boost::python::wrapper< py_event_base_pv_holder > //objbase > + // { + // public: + // typedef event_base wrapped_t; + // //typedef py_named_pbase base_t; + // typedef smart_ptr < wrapped_t > sp_event_base_t; + // typedef py_event_base this_t; + + // typedef py_reservoir py_reservoir_t; + // typedef py_rs_mesh py_mesh_iface_t; + // typedef py_calc_model py_calc_model_t; + + // typedef smart_ptr < reservoir > sp_top_t; + // typedef smart_ptr < rs_mesh_iface > sp_mesh_iface_t; + // typedef smart_ptr < calc_model > sp_calc_model_t; + + // py_event_base (); + // py_event_base (const sp_obj &); + // py_event_base (const py_objbase &); + + // void init(const std::string & _params); + + // //virtual void parse(); + // void py_apply (const py_reservoir_t &top, + // const py_mesh_iface_t &mesh, + // const py_calc_model_t &calc_model); + + // void apply (const sp_top_t &top, + // const sp_mesh_iface_t &mesh, + // const sp_calc_model_t &calc_model); + + // void apply_from_py (const py_reservoir_t &top, + // const py_mesh_iface_t &mesh, + // const py_calc_model_t &calc_model); + + //void default_apply_from_py (const py_reservoir_t &top, + // const py_mesh_iface_t &mesh, + // const py_calc_model_t &calc_model); + // }; + + + template class py_el_pair; + + template + class py_event_base_iterator : public std::iterator< + std::bidirectional_iterator_tag, + py_event_base, ptrdiff_t, + py_event_base, py_event_base > + { + + public: + + typedef event_manager event_manager_t; + typedef typename event_manager_t::event_map em_t; + typedef typename em_t::iterator list_iterator_t; + typedef typename list_iterator_t::value_type value_t; + typedef typename value_t::second_type elist_t; + + typedef py_el_pair py_el_pair_t; + typedef typename elist_t::value_type sp_event_base_t; + typedef typename elist_t::iterator iterator_t; + typedef typename elist_t::const_iterator const_iterator_t; + + typedef py_event_base py_event_base_t; + typedef py_event_base_iterator this_t; + + typedef std::iterator, ptrdiff_t, + py_event_base, py_event_base > base_t; + + typedef typename base_t::reference reference; + typedef typename base_t::pointer pointer; + + py_event_base_iterator (const elist_t &events); + py_event_base_iterator (const this_t &iter); + + py_event_base_t *next (); + + reference operator*() const; + + this_t& operator++(); + this_t operator++(int); + + this_t& operator--(); + this_t operator--(int); + + bool operator ==(const this_t &ritr) const; + bool operator !=(const this_t &ritr) const; + const this_t &operator =(const this_t &ritr); + + protected: + elist_t events; + const_iterator_t iter; + }; + + template + class py_el_pair + { + public: + typedef py_el_pair this_t; + + typedef event_manager event_manager_t; + typedef typename event_manager_t::event_map em_t; + typedef typename em_t::const_iterator const_iterator_t; + typedef typename em_t::iterator iterator_t; + typedef typename iterator_t::value_type value_t; + typedef typename value_t::first_type first_t; // posix_time::ptime + typedef typename value_t::second_type second_t; // list < smart_ptr > + + typedef py_event_base_iterator py_event_base_iterator_t; + + py_el_pair (); + py_el_pair (const const_iterator_t &iter); + py_el_pair (const this_t &iter); + + py_event_base_iterator_t list_begin (); + + protected: + first_t first; + second_t second; + //iterator_t &iter; + }; + + template + class event_list_iterator : public std::iterator< + std::bidirectional_iterator_tag, + py_el_pair, ptrdiff_t, + py_el_pair, py_el_pair > + { + + public: + typedef event_list_iterator this_t; + + typedef event_manager event_manager_t; + typedef smart_ptr sp_event_manager_t; + typedef typename event_manager_t::event_map em_t; + typedef typename em_t::const_iterator const_iterator_t; + typedef typename em_t::iterator iterator_t; + typedef typename em_t::key_type first_t; + typedef typename em_t::value_type second_t; + typedef py_el_pair py_el_pair_t; + + typedef std::iterator, ptrdiff_t, + py_el_pair, py_el_pair > base_t; + + typedef typename base_t::reference reference; + typedef typename base_t::pointer pointer; + + + event_list_iterator (const sp_event_manager_t &); //iterator_t &iter); + event_list_iterator (const this_t &iter); + + reference operator*() const; + + this_t& operator++(); + this_t operator++(int); + + py_el_pair_t next (); + + this_t& operator--(); + this_t operator--(int); + + bool operator ==(const this_t &ritr) const; + bool operator !=(const this_t &ritr) const; + const this_t &operator =(const this_t &ritr); + + protected: + sp_event_manager_t evm; + const_iterator_t iter; + //py_el_pair_t pair_; + }; + + void py_export_events (); + +} // namespace python +} // namespace blue_sky + +#endif // PY_EVENT_BASE_H diff --git a/bs_bos_core/include/py_event_manager.h b/bs_bos_core/include/py_event_manager.h new file mode 100644 index 0000000..b2c3068 --- /dev/null +++ b/bs_bos_core/include/py_event_manager.h @@ -0,0 +1,70 @@ +/** + * @file well_event.h + * @brief declaration of well events + * @author Morozov Andrey + * @date 2008-06-07 + * */ + +#ifndef BS_PY_EVENT_MANAGER_H +#define BS_PY_EVENT_MANAGER_H + +#ifdef BSPY_EXPORTING_PLUGIN + +#include "py_event_base.h" +#include "event_manager.h" + +namespace blue_sky { +namespace python { + + template + class event_creater_base + { + public: + typedef py_event_base py_event_base_t; + + event_creater_base (boost::python::object &pobj); + + py_event_base_t *create (); + + protected: + boost::python::object &obj; + }; + + /** + * \brief python wrapper to export event_manager to python + * */ + template + class py_event_manager : public py_objbase + { + public: + typedef py_event_manager this_t; + typedef event_manager wrapped_t; + typedef smart_ptr sp_em_t; + typedef py_event_base py_event_base_t; + typedef event_creater_base event_creater_base_t; + + typedef event_list_iterator event_list_iterator_t; + + py_event_manager(); + py_event_manager(const sp_em_t &src); + py_event_manager(const this_t &src); + + ~py_event_manager (); + + py_event_base_t *create_event(const std::string &date, const std::string &event_name, const std::string &event_params); + + void factory_register(const std::string &name, const event_creater_base_t &creater); + + event_list_iterator_t el_begin (); + //event_list_iterator_t el_end (); + }; + + + void + py_export_event_manager (); + +} // namespace python +} // namespace blue_sky + +#endif //#ifdef BSPY_EXPORTING_PLUGIN +#endif //#ifndef BS_PY_EVENT_MANAGER_H diff --git a/bs_bos_core/include/py_facility_manager.h b/bs_bos_core/include/py_facility_manager.h new file mode 100644 index 0000000..c6c6845 --- /dev/null +++ b/bs_bos_core/include/py_facility_manager.h @@ -0,0 +1,17 @@ +#ifndef PY_FACILITY_MANAGER_H +#define PY_FACILITY_MANAGER_H + +#include "py_calc_well.h" +#include "facility_manager.h" + +namespace blue_sky { +namespace python { + + void + py_export_facility_manager(); + +} +} + +#endif // PY_FACILITY_MANAGER_H + diff --git a/bs_bos_core/include/py_jacobian.h b/bs_bos_core/include/py_jacobian.h new file mode 100644 index 0000000..df5e289 --- /dev/null +++ b/bs_bos_core/include/py_jacobian.h @@ -0,0 +1,21 @@ +/** + * \file py_jacobian.h + * \brief python exporting for jacobian + * \author Sergey Miryanov + * \date 12.05.2009 + * */ +#ifndef BS_PY_JACOBIAN_H_ +#define BS_PY_JACOBIAN_H_ + +namespace blue_sky { +namespace python { + + void + py_export_jacobian (); + +} // namespace python +} // namespace blue_sky + + +#endif // #ifndef BS_PY_JACOBIAN_H_ + diff --git a/bs_bos_core/include/py_keyword_manager.h b/bs_bos_core/include/py_keyword_manager.h new file mode 100644 index 0000000..9e03176 --- /dev/null +++ b/bs_bos_core/include/py_keyword_manager.h @@ -0,0 +1,21 @@ +/** + * \file py_keyword_manager.h + * \brief python wrapper for keyword manager + * \author Sergey Miryanov + * \date 28.10.2009 + * */ +#ifndef BS_BOS_CORE_PY_KEYWORD_MANAGER_H_ +#define BS_BOS_CORE_PY_KEYWORD_MANAGER_H_ + +namespace blue_sky { +namespace python { + + void + export_keyword_manager (); + +} // namespace python +} // namespace blue_sky + + +#endif // #ifndef BS_BOS_CORE_PY_KEYWORD_MANAGER_H_ + diff --git a/bs_bos_core/include/py_reservoir.h b/bs_bos_core/include/py_reservoir.h new file mode 100644 index 0000000..c231949 --- /dev/null +++ b/bs_bos_core/include/py_reservoir.h @@ -0,0 +1,18 @@ +#ifndef PY_RESERVOIR_H +#define PY_RESERVOIR_H + +#include "reservoir.h" +#include "facility_manager.h" +#include "well_connection.h" + +namespace blue_sky { +namespace python { + + void + py_export_reservoir(); + +} // namespace python +} // namespace blue_sky + +#endif // PY_RESERVOIR_H + diff --git a/bs_bos_core/include/py_reservoir_simulator.h b/bs_bos_core/include/py_reservoir_simulator.h new file mode 100644 index 0000000..e1b96d9 --- /dev/null +++ b/bs_bos_core/include/py_reservoir_simulator.h @@ -0,0 +1,22 @@ +#ifndef PY_RESERVOIR_SIMULATOR_H +#define PY_RESERVOIR_SIMULATOR_H + +#include "py_event_manager.h" +#include "py_calc_model.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "py_data_manager.h" +#include "py_jacobian_matrix.h" +#include "py_linear_solvers.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky { +namespace python { + + void + py_export_reservoir_simulator (); + +} // namespace python +} // namespace blue_sky + +#endif // PY_RESERVOIR_SIMULATOR_H diff --git a/bs_bos_core/include/py_table_2d_debug.h b/bs_bos_core/include/py_table_2d_debug.h new file mode 100644 index 0000000..1d53107 --- /dev/null +++ b/bs_bos_core/include/py_table_2d_debug.h @@ -0,0 +1,131 @@ +/** + * \file py_table_2d_debug.h + * \brief python wrapeps for table_2d. only for debug + * \author Miryanov Sergey + * \date 12.05.2008 + */ +#ifndef PY_BS_TABLE_2D_H_ +#define PY_BS_TABLE_2D_H_ + +#ifdef _DEBUG + +#include "table_2d.h" + +namespace blue_sky + { + namespace python + { + + template + class py_data_row + { + public: + typedef table::data_row data_row_t; + + py_data_row () + { + + } + + py_data_row (const data_row_t &r) + : row (r) + { + + } + + typename strategy_t::item_t get (int column_index) const + { + return row[column_index]; + } + + private: + + data_row_t row; + + }; + + template + class py_data_group + { + public: + typedef table::data_group data_group_t; + + py_data_group () + : group (0, 0, 0) + { + + } + + py_data_group (const data_group_t &g) + : group (g) + { + + } + + int get_rows_count () const + { + return group.get_rows_count (); + } + int get_columns_count () const + { + return group.get_columns_count (); + } + + py_data_row get_row (int row_index) const + { + return py_data_row (group.get_row (row_index)); + } + + private: + + + data_group_t group; + + }; + + template + class py_table_2d + { + public: + typedef table::table_2d table_2d_t; + + py_table_2d () + : data (0) + { + + } + + py_table_2d (const table_2d_t &d) + : data (d) + { + + } + + int get_groups_count () const + { + return data.get_groups_count (); + } + + py_data_group get_data_group (int group_index) + { + return py_data_group (data.get_data_group (group_index)); + } + + private: + + table_2d_t data; + + }; + + void + py_export_table_2d (); + + + } // namespace python +} // namespace blue_sky + + +#endif // #ifdef _DEBUG + + +#endif // #ifdef PY_BS_TABLE_2D_H_ diff --git a/bs_bos_core/include/py_two_stage_preconditioner.h b/bs_bos_core/include/py_two_stage_preconditioner.h new file mode 100644 index 0000000..c9beb33 --- /dev/null +++ b/bs_bos_core/include/py_two_stage_preconditioner.h @@ -0,0 +1,29 @@ +/** + * \file py_two_stage_preconditioner.h + * \brief Python wrapper for two_stage_preconditioner + * \author Miryanov Sergey + * \date 16.04.2008 + */ + +#ifndef BS_PY_TWO_STAGE_PRECONDITIONER_H_ +#define BS_PY_TWO_STAGE_PRECONDITIONER_H_ + +#ifdef BSPY_EXPORTING_PLUGIN +#include "two_stage_preconditioner.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "py_bcsr_matrix.h" +#include "py_linear_solvers.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky { +namespace python { + + //! export classes to python + void py_export_two_stage_prec (); + +} // namespace python +} // namespace blue_sky + +#endif // #ifdef BSPY_EXPORTING_PLUGIN +#endif // #ifndef BS_PY_TWO_STAGE_PRECONDITIONER_H_ diff --git a/bs_bos_core/include/py_well_factory.h b/bs_bos_core/include/py_well_factory.h new file mode 100644 index 0000000..ca63e19 --- /dev/null +++ b/bs_bos_core/include/py_well_factory.h @@ -0,0 +1,78 @@ +/** + * \file py_well_factory.h + * \brief + * \author Sergey Miryanov + * \date 21.05.2009 + * */ +#ifndef BS_BOS_CORE_PY_WELL_FACTORY_H_ +#define BS_BOS_CORE_PY_WELL_FACTORY_H_ + +#include "calc_well.h" +#include "well_controller.h" +#include "well_limit_operation.h" +#include "calc_model.h" +#include "export_python_wrapper.h" +#include "well_rate_control_interface.h" + + +namespace blue_sky { +namespace python { + + STRATEGY_CLASS_WRAPPER (well_factory, py_well_factory) + { + public: + typedef smart_ptr , true> sp_well_t; + typedef smart_ptr , true> sp_connection_t; + typedef well_factory wrapped_t; + public: + STRATEGY_CLASS_WRAPPER_DECL (py_well_factory); + WRAPPER_METHOD_R_CONST (create_well, sp_well_t, 2, (std::string, std::string)); + WRAPPER_METHOD_R_CONST (create_connection, sp_connection_t, 0, (empty_arg__)); + }; + + using namespace wells; + STRATEGY_CLASS_WRAPPER (well_controller_factory, py_well_controller_factory) + { + public: + typedef smart_ptr , true> sp_well_controller_t; + typedef smart_ptr , true> sp_well_control_t; + typedef smart_ptr , true> sp_calc_model_t; + typedef well_controller_factory wrapped_t; + + public: + STRATEGY_CLASS_WRAPPER_DECL (py_well_controller_factory); + WRAPPER_METHOD_R_CONST (create_controller, sp_well_controller_t, 0, (empty_arg__)); + WRAPPER_METHOD_R_CONST (create_control, sp_well_control_t, 3, (rate_control_type, bool, const sp_calc_model_t &)); + }; + + STRATEGY_CLASS_WRAPPER (well_rate_control_factory, py_well_rate_control_factory) + { + public: + typedef well_rate_control_interface well_rate_control_t; + typedef smart_ptr , true> sp_calc_model_t; + typedef smart_ptr sp_well_rate_control_t; + typedef well_rate_control_factory wrapped_t; + + public: + STRATEGY_CLASS_WRAPPER_DECL (py_well_rate_control_factory); + WRAPPER_METHOD_R (create_control, sp_well_rate_control_t, 4, (rate_control_type, bool, bool, const sp_calc_model_t &)); + }; + + CLASS_WRAPPER (well_limit_operation_factory, py_well_limit_operation_factory) + { + public: + typedef smart_ptr sp_well_limit_operation_t; + typedef well_limit_operation_factory wrapped_t; + public: + CLASS_WRAPPER_DECL (py_well_limit_operation_factory); + WRAPPER_METHOD_R (create_limit, sp_well_limit_operation_t, 1, (limit_operation_type)); + }; + + void py_export_well_factories (); + +} // namespace python +} // namespace blue_sky + + +#endif // #ifndef BS_BOS_CORE_PY_WELL_FACTORY_H_ + diff --git a/bs_bos_core/include/rate_control_type.h b/bs_bos_core/include/rate_control_type.h new file mode 100644 index 0000000..c5714a3 --- /dev/null +++ b/bs_bos_core/include/rate_control_type.h @@ -0,0 +1,93 @@ +/** + * \file rate_control_type.h + * \brief + * \author Sergey Miryanov + * \date 24.11.2008 + * */ +#ifndef BS_RATE_CONTROL_TYPE_H_ +#define BS_RATE_CONTROL_TYPE_H_ + +namespace blue_sky + { + namespace wells + { + + enum rate_control_type + { + null_control, //!< null control + bhp_control, //!< control by bhp + rate_control, //!< control by liquid injection rate + liquid_rate_control, //!< control by liquid rate + oil_rate_control, //!< control by oil rate + water_rate_control, //!< control by water rate + gas_rate_control, //!< control by gas rate + }; + + rate_control_type + rate_control_cast (int i); //!< cast int value to rate_control_type; if value is invalid it returns null_control + rate_control_type + rate_control_cast (const std::string &str); + + bool + is_bhp_control (rate_control_type type); + bool + is_rate_control (rate_control_type type); + + inline rate_control_type + rate_control_cast (int i) + { + if (i <= null_control && i > gas_rate_control) + { + BS_ASSERT (false && "UNSUPPORTED VALUE") (i); + return null_control; + } + + return static_cast (i); + } + inline rate_control_type + rate_control_cast (const std::string &str) + { + if (str == "BHP") + return bhp_control; + else if (str == "RATE") + return rate_control; + else if (str == "LRAT") + return liquid_rate_control; + else if (str == "ORAT") + return oil_rate_control; + else if (str == "WRAT") + return water_rate_control; + else if (str == "GRAT") + return gas_rate_control; + else if (str == "RESV") + { + BS_ASSERT (false && "Unsupported rate_control type") (str); + return null_control; + } + else if (str == "") + return null_control; + else + { + BS_ASSERT (false && "Unsuported rate_control type") (str); + throw bs_exception ("rate_control_cast", "Unsupported rate_control type"); + } + } + + inline bool + is_bhp_control (rate_control_type type) + { + return type == bhp_control; + } + inline bool + is_rate_control (rate_control_type type) + { + return type != bhp_control && type != null_control; + } + + + } // namespace wells +} // namespce blue_sky + + +#endif // #ifndef BS_RATE_CONTROL_TYPE_ + diff --git a/bs_bos_core/include/res_file_id.h b/bs_bos_core/include/res_file_id.h new file mode 100644 index 0000000..61bb27d --- /dev/null +++ b/bs_bos_core/include/res_file_id.h @@ -0,0 +1,474 @@ +#ifndef _RES_FILE_ID_H_ +#define _RES_FILE_ID_H_ + + +//! ids for classes +enum +{ + YS_ID_CATALOG = 0, + YS_ID_INIT, + YS_ID_CDATA, + YS_ID_RSV_STATUS, + YS_ID_GROUP_STATUS, + YS_ID_WELL_STATUS, + YS_ID_CONNECTION_STATUS, + YS_ID_MAPS, + YS_ID_PVT, + YS_ID_SPOF, + YS_ID_TIME_STEP, + YS_ID_GROUP, + YS_ID_WELL, + YS_ID_CONNECTION, + YS_ID_RATE, + YS_ID_FIP_DATA, + YS_ID_MESH, + YS_ID_INITIAL_FIP_DATA, + YS_ID_IMPES_PARAM, + YS_ID_WPIMUL, + YS_ID_FIX_PRESSURE, + YS_ID_STREAM_LINE, + YS_ID_FRACTURES, + YS_ID_STREAM_LINE_PARAMS, + YS_ID_W_TRAJECTORY, + YS_ID_FI_PARAMS, + YS_ID_SMART_ARRAY, + YS_ID_POOL, + YS_ID_COMP_IDATA, + YS_ID_WELL_RESULTS, + YS_ID_WDATA, + YS_ID_CONN_DATA, + YS_ID_SPFN, + YS_ID_SOF2, + YS_ID_SOF3, + YS_ID_FDATA, + YS_ID_FIP_RESULTS, + YS_ID_GCTRL_GECON, + YS_ID_GCTRL_SWITCH_TO_BHP +}; + + +//! ids for impes parameters +enum +{ + YS_ID_IMPES_PARAM_DOUBLE_VARIABLES = YS_ID_IMPES_PARAM << 16 +}; + +//! ids for maps data +enum +{ + YS_ID_MAPS_CURR_DT = YS_ID_MAPS << 16, + YS_ID_MAPS_P, + YS_ID_MAPS_SO, + YS_ID_MAPS_SW, + YS_ID_MAPS_TNK, + YS_ID_MAPS_PLANE_VALUE, + YS_ID_MAPS_MAIN_VARIABLE, + YS_ID_MAPS_GAS_OIL_RATIO, + YS_ID_MAPS_FLOW_RATES, + YS_ID_MAPS_XCP +}; + + +//! ids for initial fip data +enum +{ + YS_ID_INITIAL_FIP_DATA_OOIP = YS_ID_INITIAL_FIP_DATA << 16, + YS_ID_INITIAL_FIP_DATA_OWIP, + YS_ID_INITIAL_FIP_DATA_OGIP, + YS_ID_INITIAL_FIP_DATA_DHPV +}; + +//! ids for mesh class +enum +{ + YS_ID_MESH_MAIN_PROP_UINT = YS_ID_MESH << 16, + YS_ID_MESH_NODES, + YS_ID_MESH_NODE_BOUNDARY, + YS_ID_MESH_ORIGINAL_NODES, + YS_ID_MESH_ORIGINAL_NODES_NUM, + YS_ID_MESH_PLANES, + YS_ID_MESH_PLANE_BOUNDARY, + YS_ID_MESH_PLANE_ORIENTATION, + YS_ID_MESH_PLANE_PLUS, + YS_ID_MESH_PLANE_MINUS, + + YS_ID_MESH_ORIGINAL_PLANES, + YS_ID_MESH_ORIGINAL_PLANES_NUM, + YS_ID_MESH_ELEMENTS, + YS_ID_MESH_ELEMENT_PLANES, + YS_ID_MESH_ELEMENT_NEIGHBOUR, + YS_ID_MESH_ELEMENT_BOUNDARY, + YS_ID_MESH_ORIGINAL_ELEMENT_NUM, + YS_ID_MESH_ORIGINAL_ELEMENTS, + YS_ID_MESH_BOUNDARY_PLANES_ALL, + YS_ID_MESH_BOUNDARY_PLANES, + + YS_ID_MESH_CONNECTION_PLUS, + YS_ID_MESH_CONNECTION_MINUS, + YS_ID_MESH_ELEMENT_CONNECTIONS_IND, + YS_ID_MESH_ELEMENT_CONNECTIONS_PTR, + YS_ID_MESH_CONNECTION_TYPE +}; +//! ids for rsv status class +enum +{ + YS_ID_RSV_STATUS_GUI_VARS = YS_ID_RSV_STATUS << 16, + YS_ID_RSV_STATUS_CURRENT_RATE, + YS_ID_RSV_STATUS_TOTAL_RATE, + YS_ID_RSV_STATUS_CURRENT_INITIAL_RATE, + YS_ID_RSV_STATUS_TOTAL_INITIAL_RATE, + YS_ID_RSV_STATUS_GROUP_STATUS, + YS_ID_RSV_STATUS_WELL_STATUS, + + YS_ID_RSV_STATUS_FIP_REGIONS, + YS_ID_RSV_STATUS_FIP_DATA, + YS_ID_RSV_STATUS_CURRENT_DATE, + YS_ID_RSV_STATUS_FIX_PRESSURE, + YS_ID_RSV_STATUS_STREAM_LINE, + YS_ID_RSV_STATUS_INT_PARAMS +}; + +//! ids for well status class +enum +{ + YS_ID_GROUP_STATUS_PARENT = YS_ID_GROUP_STATUS << 16, + YS_ID_GROUP_STATUS_CURRENT_RATE, + YS_ID_GROUP_STATUS_TOTAL_RATE, + YS_ID_GROUP_STATUS_CURRENT_INITIAL_RATE, + YS_ID_GROUP_STATUS_TOTAL_INITIAL_RATE, + YS_ID_GROUP_STATUS_GUI_VARS, + YS_ID_GROUP_STATUS_WELL_STATUS, + YS_ID_GROUP_STATUS_DPARAMS, + YS_ID_GROUP_STATUS_IPARAMS, + YS_ID_GROUP_STATUS_BPARAMS + +}; +//! ids for well status class +enum +{ + YS_ID_WELL_STATUS_PARENT = YS_ID_WELL_STATUS << 16, + YS_ID_WELL_STATUS_CURRENT_STATUS, + YS_ID_WELL_STATUS_CURRENT_RATE, + YS_ID_WELL_STATUS_TOTAL_RATE, + YS_ID_WELL_STATUS_CURRENT_INITIAL_RATE, + YS_ID_WELL_STATUS_TOTAL_INITIAL_RATE, + YS_ID_WELL_STATUS_MAIN_PROP_DOUBLE, + YS_ID_WELL_STATUS_GUI_VARS, + YS_ID_WELL_STATUS_CONNECTION_STATUS +}; + +//! ids for connection status class +enum +{ + YS_ID_CONNECTION_STATUS_PARENT = YS_ID_CONNECTION_STATUS << 16, + YS_ID_CONNECTION_STATUS_RATE, + YS_ID_CONNECTION_STATUS_MAIN_PROP_DOUBLE, + YS_ID_CONNECTION_STATUS_COMMULATIVE_RATE, +}; + +//! ids for fip_data class +enum +{ + YS_ID_FIP_DATA_MAIN_PROP_DOUBLE = YS_ID_FIP_DATA << 16 +}; + +//! ids for rate class +enum +{ + YS_ID_CONNECTION_MAIN_PROP_DOUBLE = YS_ID_CONNECTION << 16, + YS_ID_CONNECTION_MAIN_PROP_INT, + YS_ID_CONNECTION_NAME, + YS_ID_CONNECTION_GROUPNAME, + YS_ID_CONNECTION_FLAG +}; + + +//! ids for rate class +enum +{ + YS_ID_RATE_MAIN_PROP_DOUBLE = YS_ID_RATE << 16 +}; +//! ids for well class +enum +{ + YS_ID_WELL_MAIN_PROP_DOUBLE = YS_ID_WELL << 16, + YS_ID_WELL_MAIN_PROP_INT, + YS_ID_WELL_INITIAL_RATES, + YS_ID_WELL_NAME, + YS_ID_WELL_GROUPNAME +}; +//! ids for group class +enum +{ + YS_ID_GROUP_COMPENSATION = YS_ID_GROUP << 16, + YS_ID_GROUP_COMPENSATION_TYPE, + YS_ID_GROUP_START_TIME, + YS_ID_GROUP_NAME +}; +//! ids for time_step class +enum +{ + YS_ID_TIME_STEP_MAIN_PROP_INT = YS_ID_TIME_STEP << 16, + YS_ID_TIME_STEP_MAIN_PROP_DOUBLE, + YS_ID_TIME_STEP_GROUP, + YS_ID_TIME_STEP_WELL, + YS_ID_TIME_STEP_CONNECTION, + YS_ID_TIME_STEP_IMPES_PARAM, + YS_ID_TIME_STEP_WPIMUL, + YS_ID_TIME_STEP_FIX_PRESSURE, + YS_ID_TIME_STEP_STREAM_LINE_PARAMS, + YS_ID_TIME_STEP_FI_TS_PARAMS +}; +//! ids for spof class +enum +{ + YS_ID_SPOF_TABLE_LEN = YS_ID_SPOF << 16, + YS_ID_SPOF_SATURATION, + YS_ID_SPOF_PHASE_PERM, + YS_ID_SPOF_OIL_PERM, + YS_ID_SPOF_P_CAP, + YS_ID_SPOF_MAIN_PROP +}; +//! ids for spfn class +enum +{ + YS_ID_SPFN_TABLE_LEN = YS_ID_SPFN << 16, + YS_ID_SPFN_SATURATION, + YS_ID_SPFN_PHASE_PERM, + YS_ID_SPFN_P_CAP, + YS_ID_SPFN_MAIN_PROP +}; +//! ids for sof2 class +enum +{ + YS_ID_SOF2_TABLE_LEN = YS_ID_SOF2 << 16, + YS_ID_SOF2_SATURATION, + YS_ID_SOF2_OIL_PERM +}; +//! ids for sof3 class +enum +{ + YS_ID_SOF3_TABLE_LEN = YS_ID_SOF3 << 16, + YS_ID_SOF3_SATURATION, + YS_ID_SOF3_OIL_PERM_IN_WATER, + YS_ID_SOF3_OIL_PERM_IN_GAS +}; +//! ids for pvt class +enum +{ + YS_ID_PVT_DENSITY = YS_ID_PVT << 16, + YS_ID_PVT_TABLE_LEN_AND_PVTO_FLAG, + YS_ID_PVT_PRESSURE, + YS_ID_PVT_FVF, + YS_ID_PVT_VISCOSITY, + YS_ID_PVT_GPR, + YS_ID_PVT_MOLAR_DENSITY, + YS_ID_PVT_COMPRESS_AND_P_REF, + YS_ID_PVT_DOUBLE_DATA, + YS_ID_PVT_INFO +}; + +//! ids for INIT +enum +{ + YS_ID_INIT_TITLE = YS_ID_INIT << 16, + YS_ID_INIT_MAIN_PROP, + YS_ID_INIT_DX, + YS_ID_INIT_DY, + YS_ID_INIT_DZ, + YS_ID_INIT_MULTX, + YS_ID_INIT_MULTY, + YS_ID_INIT_MULTZ, + YS_ID_INIT_TOPS, + YS_ID_INIT_PERMX, + YS_ID_INIT_PERMY, + YS_ID_INIT_PERMZ, + YS_ID_INIT_PORO, + YS_ID_INIT_NTG, + YS_ID_INIT_SOIL, + YS_ID_INIT_SWAT, + YS_ID_INIT_PRESSURE, + YS_ID_INIT_EQLNUM, + YS_ID_INIT_FIPNUM, + YS_ID_INIT_SATNUM, + YS_ID_INIT_PVTNUM, + YS_ID_INIT_BNDNUM, + YS_ID_INIT_ROCK, + YS_ID_INIT_PREF, + YS_ID_INIT_PVTO, + YS_ID_INIT_PVTW, + YS_ID_INIT_PVTG, + YS_ID_INIT_SWOF, + YS_ID_INIT_SGOF, + YS_ID_INIT_FIP, + YS_ID_INIT_TIME_STEP, + YS_ID_INIT_START_DATE, + YS_ID_INIT_COORD, + YS_ID_INIT_ZCORN, + YS_ID_INIT_DEPTH, + YS_ID_INIT_W_TRAJECTORY, + YS_ID_INIT_FRACTURES, + YS_ID_INIT_RS, + YS_ID_INIT_PBUB, + YS_ID_INIT_FI_PARAMS, + YS_ID_INIT_INT_POOL, + YS_ID_INIT_DOUBLE_POOL, + YS_ID_INIT_COMP_IDATA, + YS_ID_INIT_SWFN, + YS_ID_INIT_SGFN, + YS_ID_INIT_SOF2, + YS_ID_INIT_SOF3 +}; + +//! ids for wpimul class +enum +{ + YS_ID_WPIMUL_MAIN_PROP_INT = YS_ID_WPIMUL << 16, + YS_ID_WPIMUL_MAIN_PROP_DOUBLE, + YS_ID_WPIMUL_WELL_NAME +}; + +//! ids for stream_line class +enum +{ + YS_ID_STREAM_LINE_MAIN_PROP_INT = YS_ID_STREAM_LINE << 16, + YS_ID_STREAM_LINE_WELL_NAME, + YS_ID_STREAM_LINE_COORDS, + YS_ID_STREAM_LINE_INDEXES +}; +//! ids for stream_line_params class +enum +{ + YS_ID_STREAM_LINE_PARAMS_MAIN_PROP_INT = YS_ID_STREAM_LINE_PARAMS << 16, + YS_ID_STREAM_LINE_PARAMS_MAIN_PROP_DOUBLE +}; + +//! ids for fracture_list class +enum +{ + YS_ID_FRACTURES_MAIN_PROP_DOUBLE = YS_ID_FRACTURES << 16, + YS_ID_FRACTURES_MAIN_PROP_INT, + YS_ID_FRACTURES_WELL_NAME +}; + +enum +{ + YS_ID_W_TRAJECTORY_WELL_NAME = YS_ID_W_TRAJECTORY << 16, + YS_ID_W_TRAJECTORY_INT_PROP, + YS_ID_W_TRAJECTORY_TRAJECT +}; + +//! enumerate IDs for full implicit properties +enum +{ + YS_ID_FI_PARAMS_DOUBLE = YS_ID_FI_PARAMS << 16, + YS_ID_FI_PARAMS_INT, + YS_ID_FI_PARAMS_BOOLEAN +}; + +//! enumerate IDs for #smart_array class +enum +{ + YS_ID_SMART_ARRAY_INT_PROP = YS_ID_SMART_ARRAY << 16, + YS_ID_SMART_ARRAY_INIT_ARRAY, + YS_ID_SMART_ARRAY_VALUES +}; + +//! IF |a - b| < DIFF_EPSILON => a == b +#define DIFF_EPSILON 1.0e-12 + +enum +{ + YS_COMPARE_RESERVOIR = 1, + YS_COMPARE_GROUP, + YS_COMPARE_WELL, + YS_COMPARE_CONNECTION + // YS_COMPARE_RATES, +}; + +//! enumerate IDs for #array_pool class +//! DO NOT CHANGE IT, OR COMPATIBILITY WITH OLD RST-FILES WILL BE LOST !!!!!!!! +enum +{ + YS_ID_POOL_INT_PROP = YS_ID_POOL << 16, + YS_ID_POOL_ARRAYS // +}; + + +//! ids for COMP_IDATA +enum +{ + YS_ID_COMP_IDATA_MAIN_PROP = YS_ID_COMP_IDATA << 16, + YS_ID_COMP_IDATA_NAMES, + YS_ID_COMP_IDATA_EOS, + YS_ID_COMP_IDATA_EOSS, + YS_ID_COMP_IDATA_BIC, + YS_ID_COMP_IDATA_BICS, + YS_ID_COMP_IDATA_POOL +}; +//! ids for well_results class +enum +{ + YS_ID_WELL_RESULTS_WELL_NAME = YS_ID_WELL_RESULTS << 16, + YS_ID_WELL_RESULTS_WELL_DATA +}; +//! ids for well_data class +enum +{ + YS_ID_WDATA_DATES = YS_ID_WDATA << 16, + YS_ID_WDATA_DATES_LEN, + YS_ID_WDATA_DPARAMS_LEN, + YS_ID_WDATA_DPARAMS, + YS_ID_WDATA_IPARAMS_LEN, + YS_ID_WDATA_IPARAMS, + YS_ID_WDATA_CONN_CELL, + YS_ID_WDATA_CONN_DATA, + YS_ID_WDATA_GROUP_NAME, +}; + +//! ids for fip_results class +enum +{ + YS_ID_FDATA_DATES = YS_ID_FDATA << 16, + YS_ID_FDATA_DATES_LEN, + YS_ID_FDATA_DPARAMS_LEN, + YS_ID_FDATA_DPARAMS, +}; + +//! ids for fip_results class +enum +{ + YS_ID_FIP_RESULTS_FIP_REGNUM = YS_ID_FIP_RESULTS << 16, + YS_ID_FIP_RESULTS_FIP_DATA +}; + +//! ids for connection_results class +enum +{ + YS_ID_CONN_DATA_DATES = YS_ID_CONN_DATA << 16, + YS_ID_CONN_DATA_DATES_LEN, + YS_ID_CONN_DATA_DPARAMS_LEN, + YS_ID_CONN_DATA_DPARAMS, + YS_ID_CONN_DATA_IPARAMS_LEN, + YS_ID_CONN_DATA_IPARAMS, + YS_ID_CONN_DATA_CELL +}; + +//! ids for gctrl_gecon class +enum +{ + YS_ID_GCTRL_GECON_GNAME = YS_ID_GCTRL_GECON << 16, + YS_ID_GCTRL_GECON_DPARAMS, + YS_ID_GCTRL_GECON_IPARAMS, + YS_ID_GCTRL_GECON_BPARAMS +}; + +//! ids for gctrl_switch_to_bhp class +enum +{ + YS_ID_GCTRL_SWITCH_TO_BHP_GNAME = YS_ID_GCTRL_SWITCH_TO_BHP << 16, + YS_ID_GCTRL_SWITCH_TO_BHP_DPARAMS +}; + +#endif //_RES_FILE_ID_H_ + diff --git a/bs_bos_core/include/reservoir.h b/bs_bos_core/include/reservoir.h new file mode 100644 index 0000000..3637f83 --- /dev/null +++ b/bs_bos_core/include/reservoir.h @@ -0,0 +1,209 @@ +#ifndef BS_RESERVOIR_H_ +#define BS_RESERVOIR_H_ + +#include "calc_well.h" +#include "event_filter.h" +#include "jacobian.h" + +#ifdef _HDF5 +#include "bs_hdf5_storage.h" +#include "rs_smesh_iface.h" +#endif + +namespace blue_sky + { + + template + class calc_model; + + template + class reservoir_simulator; + + template + class facility_manager; + + template + class well; + + template + class well_factory; + + class data_storage_interface; + + class fi_params; + + namespace wells + { + template + class well_controller; + + template + class well_rate_control; + + template + class connection; + + template + class well_controller_factory; + + class well_limit_operation_factory; + + class well_limit_operation; + } + + template + class BS_API_PLUGIN reservoir : public objbase + { + public: + + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + + typedef facility_base facility_t; + typedef well well_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef wells::well_rate_control well_rate_control_t; + typedef wells::connection connection_t; + typedef facility_manager facility_manager_t; + typedef wells::well_controller_factory controller_factory_t; + typedef wells::well_limit_operation_factory limit_operation_factory_t; + typedef well_factory well_factory_t; + typedef calc_model calc_model_t; + typedef rs_mesh_iface mesh_iface_t; + typedef jacobian jacobian_t; + typedef jacobian_matrix jacobian_matrix_t; + + typedef reservoir_simulator reservoir_simulator_t; + typedef rate_data rate_data_t; + typedef typename rate_data_t::rate_data_inner rate_data_inner_t; + + typedef smart_ptr sp_top_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_rate_control_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_jacobian_t; + typedef smart_ptr sp_jacobian_matrix_t; + typedef smart_ptr sp_jmatrix_t; + + typedef smart_ptr sp_facility_manager_t; + typedef smart_ptr sp_storage_t; + + typedef smart_ptr sp_well_controller_factory_t; + typedef smart_ptr sp_well_limit_operation_factory_t; + typedef smart_ptr sp_well_factory_t; + + typedef smart_ptr sp_params_t; + typedef smart_ptr sp_event_filter_t; + +#ifdef _HDF5 + typedef smart_ptr sp_bs_hdf5_storage; +#endif + + public: + + BLUE_SKY_TYPE_DECL_T (reservoir ); + ~reservoir (); + + public: + + sp_well_t get_well (const std::string &group_name, const std::string &well_name) const; + sp_well_t get_well (const std::string &well_name) const; + + sp_well_t create_well (const std::string &group_name, const std::string &well_name); + sp_well_controller_t create_well_controller (const sp_well_t &owner_well); + sp_well_limit_operation_t create_well_limit_operation (const sp_well_t &owner_well, wells::limit_operation_type operation); + sp_connection_t create_connection (); + + sp_rate_control_t create_bhp_control (bool is_prod, const sp_calc_model_t &calc_model); + sp_rate_control_t create_rate_control (bool is_prod, wells::rate_control_type control_type, const sp_calc_model_t &calc_model); + + void save_data (const sp_storage_t &storage) const; + + item_t pressure () const; + + bool check_limits (const sp_params_t ¶ms) const; + + void pre_large_step (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh); + void pre_small_step (); + void pre_newton_step (); + void restart_small_step (); + void restart_newton_step (); + + void init_jacobian (const sp_jmatrix_t &jmx, index_t n_cells); + void end_jacobian (item_t dt, const sp_calc_model_t &calc_model, sp_jacobian_t &jacobian); + + void restore_wells_solution (double dt, const item_array_t &p_sol, const item_array_t &s_sol, index_t block_size); + + void calc_wells (int istart, double dt, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix); + void fill_rhs_wells (double dt, const sp_calc_model_t &calc_model, rhs_item_array_t &rhs, bool update_after_gauss_elimination) const; + + sp_facility_manager_t get_facility_list () const; + size_t get_connections_count () const; + + void add_filter_well (const std::string &well_name); + const sp_event_filter_t &get_event_filter () const; + + sp_well_factory_t get_well_factory () const; + sp_well_controller_factory_t get_well_controller_factory () const; + sp_well_limit_operation_factory_t get_well_limit_operation_factory () const; + + void set_well_factory (const sp_well_factory_t &factory); + void set_well_controller_factory (const sp_well_controller_factory_t &factory); + void set_well_limit_operation_factory (const sp_well_limit_operation_factory_t &factory); + +#ifdef _HDF5 + void open_hdf5_file (const std::string &filename) const; + void close_hdf5_file () const; + void write_step_to_hdf5 (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, const sp_jmatrix_t &jmx, int, int, item_t time) const; + void write_mesh_to_hdf5 (const smart_ptr , true> &mesh) const; + const smart_ptr get_hdf5_file () const {return hdf5;} +#endif + + const rate_data_t & + rate () const + { + return rate_; + } + + private: + void init_rows (index_array_t &rows) const; + + public: + + rate_data_t rate_; + rate_data_t rate_rc_; + rate_data_t rate_wefac_; + rate_data_t rate_rc_wefac_; + rate_data_t rate_initial_; + rate_data_t rate_total_; + + private: + + sp_facility_manager_t facility_list_; //!< manager for facilities (wells, unnamed wells and other) + sp_well_factory_t well_factory_; //!< factory for wells and connections + sp_well_controller_factory_t well_controller_factory_; //!< factory for well controllers + sp_well_limit_operation_factory_t well_limit_operation_factory_; //!< factory for well limit operations + + sp_event_filter_t event_filter_; + + index_array_t markers_; + +#ifdef _HDF5 + sp_bs_hdf5_storage hdf5; +#endif + }; + + +} // namespace blue_sky + +#endif // #ifndef BS_RESERVOIR_H_ + diff --git a/bs_bos_core/include/reservoir_simulator.h b/bs_bos_core/include/reservoir_simulator.h new file mode 100644 index 0000000..7f5f661 --- /dev/null +++ b/bs_bos_core/include/reservoir_simulator.h @@ -0,0 +1,170 @@ +/** + \file reservoir_simulator.h + \brief main reservoir simulator of bos core + \author Nikonov Max +*/ + +#ifndef RESERVOIR_SIMULATOR_H +#define RESERVOIR_SIMULATOR_H + +#include "simulator_events.h" +#include "data_manager.h" +#include "event_manager.h" +#include "jacobian.h" + +namespace blue_sky +{ + + template + class reservoir; + + template + class calc_model; + + template + class reservoir; + + template + struct BS_API_PLUGIN trans_multipliers_calc; + + template + struct main_loop_calc_base; + + class data_storage_interface; + + template + class keyword_manager; + + /** + \class reservoir_simulator + \brief main bos class for data and process manipulate + */ + template + class BS_API_PLUGIN reservoir_simulator : public bs_node + { + //private: + //struct mstatus_traits; //!< tree node sorting traits + + public: + // typedefs + typedef reservoir_simulator < strategy_t > this_t; //!< this type + typedef smart_ptr < this_t, true > sp_this_t; //!< smart pointer to this_t + + typedef data_manager < strategy_t > dm_t; //!< data_manager type + typedef smart_ptr < dm_t, true > sp_dm_t; //!< smart_ptr to data_manager type + + typedef rs_mesh_iface < strategy_t > mesh_iface_t; //!< rs_mesh_iface type + typedef smart_ptr < mesh_iface_t, true > sp_mesh_iface_t; //!< smart_ptr to rs_mesh_iface type + + typedef linear_solver_base < strategy_t > solver_t; //!< linear_solver type + typedef smart_ptr < solver_t, true> sp_solver_t; //!< smart_ptr to solver_t type + + typedef event_manager em_t; //!< event_manager type + typedef smart_ptr < em_t, true > sp_em_t; //!< smart_ptr to event_manager type + typedef typename em_t::sp_event_base_list sp_event_base_list_t; + + typedef calc_model < strategy_t > calc_model_t; //!< calc_model type + typedef smart_ptr < calc_model_t, true > sp_calc_model_t;//!< smart_ptr to calc_model type + + typedef reservoir reservoir_t; //!< short name + typedef smart_ptr sp_reservoir_t; //!< short name + + typedef data_storage_interface facility_storage_t; + typedef smart_ptr sp_facility_storage_t; + + typedef jacobian jacobian_t; //!< short name + typedef smart_ptr sp_jacobian_t; //!< short name + + typedef typename strategy_t::item_t item_t; //!< item type + typedef typename strategy_t::index_t index_t; //!< index type + typedef typename strategy_t::item_array_t item_array_t; //!< array of items type + typedef typename strategy_t::index_array_t index_array_t; //!< array of indexes type + + typedef trans_multipliers_calc trans_multipliers_calc_t; + typedef main_loop_calc_base main_loop_calc_t; + + typedef keyword_manager keyword_manager_t; + typedef smart_ptr sp_keyword_manager_t; + + typedef jacobian_matrix jmatrix_t; + typedef smart_ptr sp_jmatrix_t; + + // methods + void set_mesh (const sp_mesh_iface_t&); + const sp_dm_t &get_data_manager () const; + const sp_em_t &get_event_manager () const; + const sp_calc_model_t &get_calc_model () const; + const sp_mesh_iface_t &get_mesh () const; + const sp_jacobian_t &get_jacobian () const; + const sp_reservoir_t &get_reservoir () const; + + void init(); + + // main loop + void main_loop (); + + main_loop_calc_t * + get_main_loop (); + + //void main_loop_iteration (const typename event_manager::event_map::iterator & it); + + //! dtor + virtual ~reservoir_simulator(); + + void set_subnode_in_tree (const std::string &name, sp_obj obj) + { + bs_node::erase (name); + bs_node::insert (obj, name, false); + } + + void simulate (const std::string &path); + void read_keyword_file_and_init (const std::string &path); + + void + pre_large_step (const sp_event_base_list_t &event_list); + + std::string + model_filename () const; + + //! blue_sky class declarations + BLUE_SKY_TYPE_DECL_T(reservoir_simulator) + + typedef bs_array signal_params_t; + + DECLARE_EVENT_LIST (reservoir_simulator, + signal_params_t, + 12, + ((begin, (clock_t), 1) + , (newton_iter_fail, (), 0) + , (newton_iter_success, (), 0) + , (before_fi_operator, (), 0) + , (before_jacobian_setup, (), 0) + , (before_jacobian_solve, (), 0) + , (before_restore_solution, (), 0) + , (simulation_start, (), 0) + , (large_step_start, (), 0) + , (small_step_start, (), 0) + , (end, (clock_t), 1) + , (post_read, (), 0) + )); + + + //private: + sp_dm_t dm; + sp_em_t em; + sp_calc_model_t cm; + sp_mesh_iface_t mesh; + sp_reservoir_t reservoir_; + sp_facility_storage_t facility_storage_; + sp_jacobian_t jacobian_; + sp_keyword_manager_t keyword_manager_; + std::string model_filename_; + + smart_ptr mloop; + }; + + bool + reservoir_simulator_register_types (const plugin_descriptor &pd); +} + +#endif // RESERVOIR_SIMULATOR_H diff --git a/bs_bos_core/include/results_hdf5_writer.h b/bs_bos_core/include/results_hdf5_writer.h new file mode 100644 index 0000000..0a9f3a5 --- /dev/null +++ b/bs_bos_core/include/results_hdf5_writer.h @@ -0,0 +1,54 @@ +/** + * \file results_hdf5_writer.h + * \brief + * \author Sergey Miryanov + * \date 25.08.2009 + * */ +#ifndef BS_BOS_CORE_RESULTS_HDF5_WRITER_H_ +#define BS_BOS_CORE_RESULTS_HDF5_WRITER_H_ + +#ifdef _HDF5 +#include "bs_hdf5_storage.h" +#include "well_results_storage.h" +#include "fip_results_storage.h" +#include "rs_smesh_iface.h" + +namespace blue_sky + { + namespace hdf5 + { + + /** + * \brief write well_results_storage data to hdf5 file + * \param wres -- well_results_storage + * \param write_conn_data -- if true then connections data will be written to file + * \return 0 if success + */ + void write_well_results (const bs_hdf5_storage &hdf5, smart_ptr &well_res, bool write_conn_data); + + /** + * \brief write fip_results_storage data to hdf5 file + * \param fres -- fip_results_storage + * \return 0 if success + */ + void write_fip_results (const bs_hdf5_storage &hdf5, smart_ptr &fip_res); + + template + void write_mesh_to_hdf5 (const smart_ptr &hdf5, const smart_ptr , true> &mesh); + + namespace detail + { + template + void add_params (const bs_hdf5_storage &hdf5, const hid_t &hid, const std::string &name, const params_t ¶ms, size_t size); + + template + void add_dates (const bs_hdf5_storage &hdf5, const hid_t &hid, const dates_t &dates); + } //namespace detail + + } // namespace hdf5 +} // namespace blue_sky + +#endif // #ifdef _HDF5 + +#endif // #ifndef BS_BOS_CORE_RESULTS_HDF5_WRITER_H_ + diff --git a/bs_bos_core/include/rr_rw_wr_saver.h b/bs_bos_core/include/rr_rw_wr_saver.h new file mode 100644 index 0000000..0eea710 --- /dev/null +++ b/bs_bos_core/include/rr_rw_wr_saver.h @@ -0,0 +1,213 @@ +/** + * \file rr_rw_wr_saver.h + * \brief helper for save rr, rw and wr arrays of connections as one plain file. only for debug purpose. + * \author Sergey Miryanov + * \date 24.09.2008 + * */ +#ifndef BS_RR_RW_WR_SAVER_H_ +#define BS_RR_RW_WR_SAVER_H_ + +#include "facility_manager.h" + + +namespace blue_sky + { + namespace tools + { + + template + struct rr_rw_wr_saver + { + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef facility_manager facility_manager_t; + typedef wells::connection connection_t; + typedef typename facility_manager_t::well_iterator_t well_iterator_t; + typedef item_t value_type; + typedef array_type array_t; + + typedef smart_ptr sp_connection_t; + + rr_rw_wr_saver (well_iterator_t wb, well_iterator_t we, size_t connection_count) + : wb_ (wb) + , we_ (we) + , array_size_ (array_t::static_size) + , total_connection_count_ (connection_count) + , accessor_ (accessor_t ()) + , current_connection_ (0) + , current_connection_count_ (wb == we ? 0 : (*wb)->get_connection_list ().size ()) + , current_item_ (0) + , total_item_ (0) + { + } + + size_t + size () const + { + return array_size_ * total_connection_count_; + } + + value_type + operator [] (size_t i) const + { + if (current_item_ >= array_size_) + { + current_item_ = 0; + current_connection_ ++; + } + + if (current_connection_ >= current_connection_count_) + { + if (wb_ != we_) + { + ++wb_; + if (wb_ != we_) + { + current_connection_ = 0; + current_connection_count_ = (*wb_)->get_connection_list ().size (); + } + } + } + + total_item_++; + BS_ASSERT (total_item_ <= size ()) (total_item_) (size ()); + return accessor_ ((*wb_)->get_connection_list ()[current_connection_], current_item_++); + } + + mutable well_iterator_t wb_; + well_iterator_t we_; + size_t array_size_; + size_t total_connection_count_; + accessor_t accessor_; + + mutable size_t current_connection_; + mutable size_t current_connection_count_; + mutable size_t current_item_; + mutable size_t total_item_; + }; + + template + struct connection_member_saver + { + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + + typedef facility_manager facility_manager_t; + typedef wells::connection connection_t; + typedef typename facility_manager_t::well_iterator_t well_iterator_t; + + typedef item_t value_type; + + typedef smart_ptr sp_connection_t; + + connection_member_saver (well_iterator_t wb, well_iterator_t we, size_t array_size) + : wb_ (wb) + , we_ (we) + , array_size_ (array_size) + , accessor_ (accessor_t ()) + , current_connection_ (0) + , current_connection_count_ (wb == we ? 0 : (*wb)->get_connection_list ().size ()) + , last_value_ (0) + { + } + + size_t + size () const + { + return array_size_; + } + + value_type + operator[] (size_t i) const + { + if (wb_ == we_) + { + BS_ASSERT (wb_ != we_); + return last_value_; + } + + if (current_connection_ >= current_connection_count_) + { + ++wb_; + if (wb_ != we_) + { + current_connection_ = 0; + current_connection_count_ = (*wb_)->get_connection_list ().size (); + } + } + + if (wb_ == we_) + { + BS_ASSERT (wb_ != we_); + return last_value_; + } + + last_value_ = accessor_ ((*wb_)->get_connection_list ()[current_connection_++]); + return last_value_; + } + + mutable well_iterator_t wb_; + well_iterator_t we_; + size_t array_size_; + accessor_t accessor_; + + mutable size_t current_connection_; + mutable size_t current_connection_count_; + mutable item_t last_value_; + }; + + template + struct well_member_saver + { + typedef typename strategy_t::item_t item_t; + typedef facility_manager facility_manager_t; + typedef typename facility_manager_t::well_iterator_t well_iterator_t; + + typedef item_t value_type; + typedef well well_t; + + //typedef item_t (well_t::*accessor_t) () const; + + typedef function_t accessor_t; + + well_member_saver (well_iterator_t wb, well_iterator_t we) + : wb_ (wb) + , we_ (we) + , accessor_ (accessor_t ()) + , last_value_ (0) + { + } + + size_t + size () const + { + return std::distance (wb_, we_); + } + + value_type + operator[] (size_t i) const + { + if (wb_ == we_) + { + BS_ASSERT (wb_ != we_); + return last_value_; + } + + last_value_ = accessor_ (*wb_); + ++wb_; + return last_value_; + } + + mutable well_iterator_t wb_; + well_iterator_t we_; + accessor_t accessor_; + mutable item_t last_value_; + }; + + } // namespace tools +} // namespace blue_sky + + + +#endif // #ifndef BS_RR_RW_WR_SAVER_H_ + diff --git a/bs_bos_core/include/save_connection_data.h b/bs_bos_core/include/save_connection_data.h new file mode 100644 index 0000000..3196cf2 --- /dev/null +++ b/bs_bos_core/include/save_connection_data.h @@ -0,0 +1,223 @@ +/** + * \file save_connection_data.h + * \brief save connection data (for debug) + * \author Sergey Miryanov + * \date 15.12.2008 + * */ +#ifndef BS_WELLS_SAVE_CONNECTION_DATA_H_ +#define BS_WELLS_SAVE_CONNECTION_DATA_H_ + +#include "well_rate_control.h" +#include "apply_wefac.h" + +namespace blue_sky + { + + template + struct save_connection_data + { + typedef calc_model calc_model_t; + typedef typename strategy_t::index_t index_t; + + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::item_t item_t; + typedef typename calc_model_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + typedef typename calc_model_t::helper_t::item_rr_block_t item_rr_block_t; + typedef typename calc_model_t::helper_t::item_rw_block_t item_rw_block_t; + typedef typename calc_model_t::helper_t::item_wr_block_t item_wr_block_t; + typedef typename calc_model_t::connection_t connection_t; + typedef typename calc_model_t::well_t well_t; + typedef typename calc_model_t::reservoir_t::facility_manager_t::well_const_iterator_t well_iterator_t; + typedef typename calc_model_t::strategy_type strategy_type; + + typedef smart_ptr sp_calc_model_t; + typedef typename calc_model_t::sp_well_t sp_well_t; + typedef typename calc_model_t::sp_connection_t sp_connection_t; + + void + save (const char *filename, const sp_calc_model_t &calc_model, item_t dt, well_iterator_t wb, const well_iterator_t &we, size_t iter_counter, item_t time, const item_array_t &sol, const item_array_t &rhs) + { + FILE *con_data = fopen (tools::string_formater (filename, iter_counter).str, "wt"); + index_t n_phases = calc_model->n_phases; + bool is_o = calc_model->is_oil (); + bool is_w = calc_model->is_water (); + bool is_g = calc_model->is_gas (); + for (well_iterator_t it = wb; it != we; ++it) + { + sp_well_t well (it->second, bs_dynamic_cast ()); + item_t h = well->get_connection_list ().front ()->connection_depth; + item_t diff_h = 0; + item_t g = calc_model->internal_constants.gravity_constant; + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c = (well->get_connection_list ())[i]; + + index_t n_block = c->n_block (); + fprintf (con_data, "%d\n", n_block); + fprintf (con_data, "%10.20lf\n", apply_wefac (c->get_rate_value () [0], well->exploitation_factor_)); + fprintf (con_data, "%10.20lf\n", apply_wefac (c->get_rate_value () [1], well->exploitation_factor_)); + fprintf (con_data, "%10.20lf\n", apply_wefac (c->get_rate_value () [2], well->exploitation_factor_)); + fprintf (con_data, "%10.20lf\n", c->get_cur_bhp ()); + fprintf (con_data, "%10.20lf\n", calc_model->pressure [n_block]); + if (calc_model->n_phases > 1) + { + fprintf (con_data, "%10.20lf\n", calc_model->saturation_3p [n_block]); + } + else + { + fprintf (con_data, "0\n"); + } + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].mobility [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].mobility [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].mobility [2]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].relative_perm [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].relative_perm [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].relative_perm [2]); + fprintf (con_data, "%10.20lf\n", well->bhp ()); + fprintf (con_data, "%10.20lf\n", well->oil_rate ()); + fprintf (con_data, "%10.20lf\n", well->water_rate ()); + fprintf (con_data, "%10.20lf\n", well->gas_rate ()); + fprintf (con_data, "%10.20lf\n", well->get_well_controller ()->bhp ()); + fprintf (con_data, "%10.20lf\n", well->get_well_controller ()->oil_rate ()); + fprintf (con_data, "%10.20lf\n", well->get_well_controller ()->water_rate ()); + fprintf (con_data, "%10.20lf\n", well->get_well_controller ()->gas_rate ()); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_fvf [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_fvf [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_fvf [2]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].prev_fluid_volume [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].prev_fluid_volume [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].prev_fluid_volume [2]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].porosity); + fprintf (con_data, "%10.20lf\n", calc_model->rock_grid_prop->volume [n_block]); + + fprintf (con_data, "%10.20lf\n", well->acc_rate_prod.oil); + fprintf (con_data, "%10.20lf\n", well->acc_rate_prod.water); + fprintf (con_data, "%10.20lf\n", well->acc_rate_prod.gas); + fprintf (con_data, "%10.20lf\n", well->acc_rate_inj.oil); + fprintf (con_data, "%10.20lf\n", well->acc_rate_inj.water); + fprintf (con_data, "%10.20lf\n", well->acc_rate_inj.gas); + + fprintf (con_data, "%10.20lf\n", c->get_fact ()); + + using namespace wells; + if (well->is_shut ()) + { + fprintf (con_data, "%d\n", 0); + } + else if (well->get_well_controller ()->is_production ()) + { + if (well->is_bhp ()) + fprintf (con_data, "%d\n", -2); + else if (well->get_well_controller ()->get_control_type () == oil_rate_control) + fprintf (con_data, "%d\n", -4); + else if (well->get_well_controller ()->get_control_type () == water_rate_control) + fprintf (con_data, "%d\n", -3); + else if (well->get_well_controller ()->get_control_type () == liquid_rate_control) + fprintf (con_data, "%d\n", -1); + else + fprintf (con_data, "%d\n", -5); + } + else + { + if (well->is_bhp ()) + fprintf (con_data, "%d\n", 2); + else if (well->get_well_controller ()->injection () == injection_water) + fprintf (con_data, "%d\n", 1); + else + fprintf (con_data, "%d\n", 5); + } + + fprintf (con_data, "%10.20lf\n", well->exploitation_factor_.data ()); + fprintf (con_data, "%10.20lf\n", dt); + fprintf (con_data, "%10.20lf\n", time); + fprintf (con_data, "%10.20lf\n", well->bw_value); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_viscosity [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_viscosity [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_viscosity [2]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_visc_fvf [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_visc_fvf [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].invers_visc_fvf [2]); + + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_fvf [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_fvf [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_fvf [2]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_viscosity [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_viscosity [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_viscosity [2]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_visc_fvf [0]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_visc_fvf [1]); + fprintf (con_data, "%10.20lf\n", calc_model->data [n_block].p_deriv_invers_visc_fvf [2]); + + fprintf (con_data, "%10.20lf\n", well->rate_prod.oil); + fprintf (con_data, "%10.20lf\n", well->rate_prod.water); + fprintf (con_data, "%10.20lf\n", well->rate_prod.gas); + fprintf (con_data, "%10.20lf\n", well->rate_inj.oil); + fprintf (con_data, "%10.20lf\n", well->rate_inj.water); + fprintf (con_data, "%10.20lf\n", well->rate_inj.gas); + + diff_h = c->connection_depth - h; + h = c->connection_depth; + item_t Po = c->cur_bhp + (c->density * g * diff_h) - calc_model->pressure[c->n_block ()]; + item_t Pw = Po; + item_t Pg = Po; + + if (calc_model->is_water ()) + Pw += calc_model->data[n_block].cap_pressure[0]; + + if (calc_model->is_gas ()) + Pg += calc_model->data[n_block].cap_pressure[1]; + + fprintf (con_data, "%10.20lf\n", Po); + fprintf (con_data, "%10.20lf\n", Pw); + fprintf (con_data, "%10.20lf\n", Pg); + + fprintf (con_data, "%10.20lf\n", (double)c->density); + fprintf (con_data, "%10.20lf\n", (double)c->head_term); + fprintf (con_data, "%10.20lf\n", (double)c->connection_depth); + + fprintf (con_data, "%10.20lf\n", sol[n_block * n_phases]); + fprintf (con_data, "%10.20lf\n", sol[n_block * n_phases + 1]); + + fprintf (con_data, "%10.20lf\n", rhs[n_block * n_phases]); + fprintf (con_data, "%10.20lf\n", rhs[n_block * n_phases + 1]); + } + } + fclose (con_data); + } + + void + save_acc (const char *filename, const sp_calc_model_t &/*calc_model*/, item_t /*dt*/, well_iterator_t wb, const well_iterator_t &we, size_t iter_counter, item_t /*time*/, const item_array_t &/*sol*/, const rhs_item_array_t &/*rhs*/) + { + FILE *con_data = fopen (tools::string_formater (filename, iter_counter).str, "wt"); + for (well_iterator_t it = wb; it != we; ++it) + { + const sp_well_t &well = it->second; + fprintf (con_data, "well: %s\n", well->name ().c_str ()); + fprintf (con_data, "prod_oil: %10.20lf\n", well->acc_rate_prod.oil); + fprintf (con_data, "prod_water: %10.20lf\n", well->acc_rate_prod.water); + fprintf (con_data, "prod_gas: %10.20lf\n", well->acc_rate_prod.gas); + fprintf (con_data, "inj_oil: %10.20lf\n", well->acc_rate_inj.oil); + fprintf (con_data, "inj_water: %10.20lf\n", well->acc_rate_inj.water); + fprintf (con_data, "inj_gas: %10.20lf\n", well->acc_rate_inj.gas); + + //for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + // { + // const sp_connection_t &c = (well->get_connection_list ())[i]; + // index_t n_block = c->n_block (); + // fprintf (con_data, "n_block: %d\n", n_block); + // fprintf (con_data, "cur_bhp: %10.20lf\n", c->get_cur_bhp ()); + // } + } + + fclose (con_data); + } + }; + + +} // namespace blue_sky + + + +#endif // #ifndef BS_WELLS_SAVE_CONNECTION_DATA_H_ + diff --git a/bs_bos_core/include/simulator_events.h b/bs_bos_core/include/simulator_events.h new file mode 100644 index 0000000..34d2687 --- /dev/null +++ b/bs_bos_core/include/simulator_events.h @@ -0,0 +1,69 @@ +/** + * \file simulator_events.h + * \brief events that will be called while main calculation + * \author Sergey Miryanov + * \date 23.07.2008 + * */ +#ifndef BS_SIMULATOR_EVENTS_H_ +#define BS_SIMULATOR_EVENTS_H_ + +#include "pp_param_list.h" + + +#define PUSH_LIST(seq_, size_) BOOST_PP_CAT(PUSH_LIST_, size_) seq_ +#define PUSH_LIST_0 +#define PUSH_LIST_1(x) params->push_back(boost::lexical_cast (A1)); +#define PUSH_LIST_2(x) params->push_back(boost::lexical_cast (A2)); PUSH_LIST_1 +#define PUSH_LIST_3(x) params->push_back(boost::lexical_cast (A3)); PUSH_LIST_2 +#define PUSH_LIST_4(x) params->push_back(boost::lexical_cast (A4)); PUSH_LIST_3 + +#define DECL(type_, name_, t_, ts_) \ + void BOOST_PP_CAT(on_, name_) (PARAM_LIST_FOR_EACH(t_, ts_)) \ + { \ + smart_ptr params = BS_KERNEL.create_object (type_::bs_type ()); \ + PUSH_LIST (BOOST_PP_TUPLE_TO_SEQ(ts_, t_), ts_) \ + this->fire_signal (BOOST_PP_CAT(name_, _signal), params); \ + } + +#define UDECL_I(r, data, i, elem) \ + DECL(data, BOOST_PP_TUPLE_ELEM(3,0,elem), BOOST_PP_TUPLE_ELEM(3,1,elem), BOOST_PP_TUPLE_ELEM(3,2,elem)) + +#define DECLARE_SIGNAL_ENUM_I(r, data, i, elem) \ + BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3,0,elem), _signal), + +#define DECLARE_SIGNALS_ENUM(ts_, t_) \ + BLUE_SKY_SIGNALS_DECL_BEGIN(bs_node) \ + BOOST_PP_SEQ_FOR_EACH_I(DECLARE_SIGNAL_ENUM_I, _, BOOST_PP_TUPLE_TO_SEQ(ts_, t_)) \ + BLUE_SKY_SIGNALS_DECL_END + +#ifdef BSPY_EXPORTING_PLUGIN +#define EXPORT_SIGNAL_ENUM_I(r, data, i, elem) \ + .value (BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(3,0,elem)), data::BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3,0,elem), _signal)) + +#define EXPORT_SIGNALS_ENUM(name_, ts_, t_) \ + static void py_export_signals_enum () \ + { \ + using namespace boost::python; \ + enum_ (BOOST_PP_STRINGIZE(BOOST_PP_CAT(name_, _signals))) \ + BOOST_PP_SEQ_FOR_EACH_I(EXPORT_SIGNAL_ENUM_I, name_, BOOST_PP_TUPLE_TO_SEQ(ts_, t_)) \ + .export_values () \ + ; \ + } +#endif + +#ifdef BSPY_EXPORTING_PLUGIN +#define DECLARE_EVENT_LIST(name_, params_, ts_, t_) \ + public: \ + DECLARE_SIGNALS_ENUM(ts_, t_) \ + BOOST_PP_SEQ_FOR_EACH_I(UDECL_I, params_, BOOST_PP_TUPLE_TO_SEQ(ts_, t_)) \ + EXPORT_SIGNALS_ENUM(name_, ts_, t_) +#else +#define DECLARE_EVENT_LIST(name_, params_, ts_, t_) \ + public: \ + DECLARE_SIGNALS_ENUM(ts_, t_) \ + BOOST_PP_SEQ_FOR_EACH_I(UDECL_I, params_, BOOST_PP_TUPLE_TO_SEQ(ts_, t_)) +#endif + + + +#endif // #ifndef BS_SIMULATOR_EVENTS_H_ diff --git a/bs_bos_core/include/stdafx.h b/bs_bos_core/include/stdafx.h new file mode 100644 index 0000000..ccbf9cd --- /dev/null +++ b/bs_bos_core/include/stdafx.h @@ -0,0 +1,183 @@ +/** + * \file stdafx.h + * \brief precompiled header + * \author Sergey Miryanov + * */ +#ifndef BS_PRECOMPILED_HEADERS_H_ +#define BS_PRECOMPILED_HEADERS_H_ + +#ifndef UNIX +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//#include +//#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Handles broken standard libraries better than +#include +#include +// FIXES for broken compilers +#include + +#ifdef _OPENMP + #include +#endif // #ifdef _OPENMP + +#pragma intrinsic (memset, memcpy) + +#include "bs_common.h" +#include BS_FORCE_PLUGIN_IMPORT () +#include "smart_ptr.h" +#include "bs_kernel.h" +#include "bs_link.h" +#include "bs_object_base.h" +#include "bs_tree.h" +#include "bs_exception.h" +#include "bs_prop_base.h" +#include BS_STOP_PLUGIN_IMPORT () + +#ifdef BSPY_EXPORTING_PLUGIN + #include + #include + #include + #include + #include + #include + #include + #include + #include + +#include BS_FORCE_PLUGIN_IMPORT () + #include "bs_plugin_common.h" + #include "py_bs_object_base.h" + #include "py_bs_command.h" + #include "py_bs_tree.h" +#include BS_STOP_PLUGIN_IMPORT () +#endif + +#include BS_FORCE_PLUGIN_IMPORT () +#include "force_inline.h" + +#include "bs_assert.h" +#include "bos_report.h" +#include "auto_value.h" +#include "throw_exception.h" + +#include "memory_macroses.h" +#include "macroses.h" +#include "lu_decomposition.h" +#include "debug_macroses.h" +#include "matrix_macroses.h" + +#include "omp_tools.h" +#include "timers.h" +#include "mv_tools.h" + +#include "aligned_allocator.h" +#include "seq_vector.h" + +#ifdef _MPI + #include "mpi_type_t.h" + #include "mpi_vector.h" +#endif // #ifdef _MPI + +#include "strategies.h" + +#include "bos_map.h" +#include "noncopyable_ptr.h" +#include "constants.h" +#include "main_def.h" +#include "err_num_def.h" +#include "vector_assign.h" +#include "save_seq_vector.h" +#include "jacobian_matrix.h" + +#ifdef _HDF5 +//#include "bs_hdf5_storage.h" +#endif + +#include "property_base.h" +#include "named_pbase_access.h" + +#include "linear_solvers.h" +#include "print_process_memory_info.h" +#include "write_time_to_log.h" + +#include "pool.h" +#include "interpolation_macro.h" +#include "rs_mesh_iface.h" +#include "rs_smesh_iface.h" +#include "localization.h" +#include "arrays.h" +#include "arrays_tables.h" +#include "convert_units.h" + +#include "pvt_water.h" +#include "pvt_gas.h" +#include "pvt_oil.h" + +#include "scal_3p.h" +#include "scale_array_holder.h" +#include "scal_region_info.h" +#include "scal_region.h" +#include "scal_2p_data_holder.h" +#include "jfunction.h" + +#include "rock_grid.h" + +#ifdef BSPY_EXPROTING_PLUGIN +#include "py_matrix_base.h" +#include "py_bcsr_matrix.h" +#include "py_linear_solvers.h" +#include "py_jacobian_matrix.h" +#include "py_scal_wrapper.h" +#include "py_data_class.h" +#endif + +#include BS_STOP_PLUGIN_IMPORT () + +#endif // #ifndef BS_PRECOMPILED_HEADERS_H_ diff --git a/bs_bos_core/include/str_functor.h b/bs_bos_core/include/str_functor.h new file mode 100644 index 0000000..65563d4 --- /dev/null +++ b/bs_bos_core/include/str_functor.h @@ -0,0 +1,38 @@ +/** + * \file str_functor.h + * \brief functor that used in event_manager and event_base parse functions. it should be used instead std or boost function to avoid ICE under MSVS + * \author Morozov Andrey + * \date 06.08.2008 + * */ +#ifndef BS_STR_FUNCTOR_H_ +#define BS_STR_FUNCTOR_H_ + +namespace blue_sky + { + + //!functor for boost spirit string parsers handling + template + struct str_functor + { + typedef void (T::*method_t)(const char*, const char*); + typedef T self_t; + + str_functor (self_t *self, method_t method) + : self (self) + , method (method) + { + } + + void operator()(const char *first, const char *last) const + { + (self->*method)(first, last); + } + + self_t *self; + method_t method; + }; + +} // namespace blue_sky + +#endif // #ifndef BS_STR_FUNCTOR_H_ + diff --git a/bs_bos_core/include/string_formater.h b/bs_bos_core/include/string_formater.h new file mode 100644 index 0000000..79634db --- /dev/null +++ b/bs_bos_core/include/string_formater.h @@ -0,0 +1,46 @@ +/** + * \file string_formater.h + * \brief helper to format string (via ellipses) (for debug purpose only) + * \author Sergey Miryanov + * \date 31.10.2008 + * */ +#ifndef BS_TOOLS_STRING_FORMATER_H_ +#define BS_TOOLS_STRING_FORMATER_H_ + +namespace blue_sky + { + namespace tools + { + + struct string_formater + { + string_formater (const std::string &format, size_t i) + { + memset (str, 0, sizeof (str)); + sprintf (str, format.c_str (), i); + } + + string_formater (const char *format, double dt, double ct, int i) + { + memset (str, 0, sizeof (str)); + sprintf (str, format, dt, ct, i); + } + + string_formater (const char *format, const std::string &s) + { + memset (str, 0, sizeof (str)); + sprintf (str, format, s.c_str ()); + } + + char str[255]; + }; + + + + } // namespace tools +} // namespace blue_sky + + + +#endif // #ifndef BS_TOOLS_STRING_FORMATER_H_ + diff --git a/bs_bos_core/include/table_2d.h b/bs_bos_core/include/table_2d.h new file mode 100644 index 0000000..ff1b51f --- /dev/null +++ b/bs_bos_core/include/table_2d.h @@ -0,0 +1,389 @@ +/** + * \file table_2d.h + * \brief + * \author Miryanov Sergey + * \date 07.05.2008 + */ +#ifndef BS_TABLE_2D_H_ +#define BS_TABLE_2D_H_ + +#include "seq_vector.h" + +namespace blue_sky + { + namespace table + { + + template class data_group; + template class data_row; + template class table_2d; + template class data_row_push_back; + + template + class data_row + { + public: + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef data_row this_t; + + private: + friend class data_group ; + + data_row (item_t *data_ptr, int columns_count) + : data_ptr (data_ptr) + , columns_count (columns_count) + { + } + + public: + + data_row () + : data_ptr (0) + , columns_count (0) + { + } + + data_row (const this_t &row) + { + *this = row; + } + data_row &operator= (const this_t &row) + { + if (this != &row) + { + data_ptr = row.data_ptr; + columns_count = row.columns_count; + } + return *this; + } + + inline item_t &operator[] (int column_index) + { + BS_ASSERT (column_index < columns_count); + BS_ASSERT (column_index >= 0); + BS_ASSERT (data_ptr); +#ifdef _DEBUG + static item_t dummy = 0.0; + + if (column_index >= 0 && column_index < columns_count && data_ptr) + return data_ptr[column_index]; + + throw bs_exception ("data_row", "out of range"); + return dummy; +#else + return data_ptr[column_index]; +#endif + } + inline const item_t &operator[] (int column_index) const + { + BS_ASSERT (column_index < columns_count); + BS_ASSERT (column_index >= 0); + BS_ASSERT (data_ptr); +#ifdef _DEBUG + static item_t dummy = 0.0; + + if (column_index >= 0 && column_index < columns_count && data_ptr) + return data_ptr[column_index]; + + throw bs_exception ("data_row", "out of range"); + return dummy; +#else + return data_ptr[column_index]; +#endif + } + + private: + + item_t *data_ptr; + int columns_count; + + }; + + template + class data_group + { + public: + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef data_group this_t; + typedef data_row data_row_t; + + private: + + friend class table_2d ; + + public: + data_group (item_t *data_ptr = 0, int rows_count = 0, int columns_count = 0) + : data_ptr (data_ptr) + , rows_count (rows_count) + , columns_count (columns_count) + { + row_size = columns_count; + } + + inline void set_rows_count (int count) + { + rows_count = count; + } + inline void set_data_ptr (item_t *ptr) + { + data_ptr = ptr; + } + + public: + + data_group (const this_t & group) + { + *this = group; + } + this_t &operator= (const this_t &group) + { + if (this != &group) + { + data_ptr = group.data_ptr; + rows_count = group.rows_count; + columns_count = group.columns_count; + row_size = group.row_size; + } + + return *this; + } + + inline data_row_t get_row (int row_index) const + { +#ifdef _DEBUG + if (row_index >= 0 && row_index < rows_count) + return data_row_t (data_ptr + row_index * row_size, columns_count); + + throw bs_exception ("data_row", "out of range"); +#else + return data_row_t (data_ptr + row_index * row_size, columns_count); +#endif + } + + inline int get_rows_count () const + { + return rows_count; + } + inline int get_columns_count () const + { + return columns_count; + } + + inline void set_columns_count (int count) + { + columns_count = count; + row_size = columns_count; + } + + private: + + item_t *data_ptr; + int rows_count; + int columns_count; + int row_size; + + }; + + template + class data_row_push_back + { + public: + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef data_row_push_back this_t; + + private: + friend class table_2d ; + + data_row_push_back (item_t *data_ptr, int columns_count) + : data_ptr (data_ptr) + , columns_count (columns_count) + { + + } + + public: + + this_t &push_back (int column_index, item_t value) + { + BS_ASSERT (data_ptr); + BS_ASSERT (column_index < columns_count); + BS_ASSERT (column_index >= 0); + + if (column_index >= 0 && column_index < columns_count) + data_ptr[column_index] = value; + + return *this; + } + + private: + + + item_t *data_ptr; + int columns_count; + + }; + + template + class table_2d + { + public: + + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef typename strategy_t::item_t index_t; + + typedef data_group data_group_t; + typedef data_row_push_back data_row_push_back_t; + + table_2d (int group_count) + : rows_count (0) + { + for (int i = 0; i < group_count; ++i) + { + group_list.push_back (data_group_t (0, 0, 0)); + } + } + + inline void init_dependent (int dependent_rows_count) + { + BS_ASSERT (dependent_rows_count); + + int column_count = 0; + for (int i = 1, cnt = (int)group_list.size (); i < cnt; i++) + { + column_count += group_list[i].get_columns_count (); + } + + BS_ASSERT (column_count); + BS_ASSERT (data.size ()); + + if (data.empty ()) + { + // TODO: LOG + BS_ASSERT (false); + throw bs_exception ("", "data is empty"); + } + + data_t new_data; + new_data.resize (data.size () + column_count * dependent_rows_count); + + memset (&new_data[0], 0, sizeof (typename data_t::value_type) * new_data.size ()); + memcpy (&new_data[0], &data[0], sizeof (typename data_t::value_type) * data.size ()); + + data.swap (new_data); + item_t *data_ptr = &data[0]; + + int rows_count_ = rows_count; + for (int i = 0, cnt = (int)group_list.size (); i < cnt; i++) + { + data_group_t &group = group_list[i]; + + group.set_rows_count (rows_count_); + group.set_data_ptr (data_ptr); + + data_ptr += (rows_count_ * group.get_columns_count ()); + rows_count_ = dependent_rows_count; + } + +#ifdef _DEBUG + item_t *last_data = &data[0] + data.size (); + BS_ASSERT (data_ptr == last_data); +#endif + } + inline void clear () + { + data.clear (); + + for (int i = 0, cnt = (int)group_list.size (); i < cnt; i++) + { + data_group_t &group = group_list[i]; + + group.set_rows_count (0); + group.set_data_ptr (0); + } + } + + inline data_group_t &get_data_group (int group_index) + { + BS_ASSERT (group_index < (int)group_list.size ()); + BS_ASSERT (group_index >= 0); +#ifdef _DEBUG + static data_group_t dummy(0, 0, 0); + + if (group_index >= 0 && group_index < (int)group_list.size ()) + return group_list[group_index]; + + throw bs_exception ("data_row", "out of range"); +#else + return group_list[group_index]; +#endif + } + inline const data_group_t &get_data_group (int group_index) const + { + BS_ASSERT (group_index < (int)group_list.size ()); + BS_ASSERT (group_index >= 0); +#ifdef _DEBUG + static data_group_t dummy(0, 0, 0); + + if (group_index >= 0 && group_index < (int)group_list.size ()) + return group_list[group_index]; + + throw bs_exception ("data_row", "out of range"); +#else + return group_list[group_index]; +#endif + } + inline data_group_t get_initial_group () + { + data_group_t group (group_list[0]); + item_t *data_ptr = &data[0]; + + group.set_rows_count (rows_count); + group.set_data_ptr (data_ptr); + + return group; + } + + inline int get_groups_count () const + { + return (int)group_list.size (); + } + + inline int get_data_rows_count () const + { + return (int)rows_count; + } + + inline data_row_push_back_t add_row () + { + BS_ASSERT (group_list.size ()); + + rows_count += 1; + data.resize (rows_count * group_list[0].get_columns_count ()); + + return data_row_push_back_t (&data[0] + data.size () - group_list[0].get_columns_count (), group_list[0].get_columns_count ()); + } + + private: + + typedef item_array_t data_t; + typedef seq_vector group_list_t; + + data_t data; + group_list_t group_list; + index_t rows_count; + }; + + + } // namespace table +} // namespace blue_sky + + +#endif // #ifndef BS_TABLE_2D_H_ diff --git a/bs_bos_core/include/timers.h b/bs_bos_core/include/timers.h new file mode 100644 index 0000000..a1161b5 --- /dev/null +++ b/bs_bos_core/include/timers.h @@ -0,0 +1,15 @@ +/** + * \file timers.h + * \brief + * \author Sergey Miryanov + * \date 24.03.2009 + * */ +#ifndef BS_BOS_CORE_TIMERS_H_ +#define BS_BOS_CORE_TIMERS_H_ + +extern double csr_calc_lin_comb_timer; +extern double csr_matrix_vector_product_timer; +extern double gmres_setup_timer; + +#endif // #ifndef BS_BOS_CORE_TIMERS_H_ + diff --git a/bs_bos_core/include/trans_multipliers.h b/bs_bos_core/include/trans_multipliers.h new file mode 100644 index 0000000..5d3a0da --- /dev/null +++ b/bs_bos_core/include/trans_multipliers.h @@ -0,0 +1,42 @@ +/** + * + * */ +#ifndef BS_TRANS_MULTIPLIERS_HPP_ +#define BS_TRANS_MULTIPLIERS_HPP_ + +namespace blue_sky + { + + template + struct trans_multipliers_calc + { + //trans_multipliers_calc (const sp_mesh_iface_t &mesh, const item_array_t &trans_mult, item_array_t &planes_trans) + //: mesh (mesh) + //, trans_mult (trans_mult) + //, planes_trans (planes_trans) + //{ + //} + + trans_multipliers_calc () + { + } + + void apply () + { + BS_ASSERT (false && "NOT IMPL YET"); + } + void unapply () + { + BS_ASSERT (false && "NOT IMPL YET"); + } + +private: + //const sp_mesh_iface_t &mesh; + //const item_array_t &trans_mult; + //item_array_t &planes_trans; + }; + +} // namespace blue_sky + +#endif // #ifndef BS_RANS_MULTIPLIERS_HPP_ + diff --git a/bs_bos_core/include/two_stage_preconditioner.h b/bs_bos_core/include/two_stage_preconditioner.h new file mode 100644 index 0000000..0c088a2 --- /dev/null +++ b/bs_bos_core/include/two_stage_preconditioner.h @@ -0,0 +1,149 @@ +#ifndef TWO_STAGE_PREC_H__ +#define TWO_STAGE_PREC_H__ +/*! + * \file two_stage_preconditioner.h + * \brief class declaration for two stage preconditioner + * \author Borschuk Oleg + * \date 2006-07-26 + */ +#ifdef _MPI +#include "mpi_csr_matrix.h" +#endif //_MPI +#include "memory_macroses.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "linear_solvers.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + template + class BS_API_PLUGIN two_stage_preconditioner: public linear_solver_base + { + public: + typedef linear_solver_base base_t; ///< short name for base class + typedef two_stage_preconditioner this_t; ///< short name for this class + typedef typename strategy_t::matrix_t matrix_t; ///< short name for matrix type + typedef typename strategy_t::item_array_t item_array_t; ///< short name for array type + typedef typename strategy_t::item_t item_t; ///< short name for array item type + typedef typename strategy_t::rhs_item_t rhs_item_t; ///< short name for type of rhs + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; ///< short name for rhs array type + typedef typename strategy_t::index_t index_t; ///< short name for index type + typedef item_t fp_type; ///< short name for array item type + typedef index_t i_type; ///< short name for index type + typedef smart_ptr sp_base_t; ///< short name for smart pointer on base class + typedef smart_ptr sp_matrix_t; ///< short name for smart pointer on matrix + //----------------------------------------- + // METHODS + //----------------------------------------- + public: + //! destructor + virtual ~two_stage_preconditioner (); + + ////! solve preconditioner + //virtual int solve (matrix_t *matrix, item_array_t &rhs, item_array_t &sol); + //! solve + virtual int solve (matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &sol); + + virtual int solve_prec (matrix_t *matrix, item_array_t &rhs, item_array_t &sol); + + template + int + templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &sol); + + + //! setup preconditioner + virtual int setup (matrix_t *matrix); + + //! set first preconditioner + void set_prec_1 (const base_t *prec) + { + base_t::prec = prec; + set_subnode_in_tree ("prec", sp_base_t (prec)); + } + + //! set second preconditioner + void set_prec_2 (const base_t *prec) + { + prec_2 = prec; + set_subnode_in_tree ("prec_2", sp_base_t (prec)); + } + + //! get iteration from first preconditioner + int get_prec_1_iters () + { + return base_t::prec ? base_t::prec->get_prop ()->get_iters () : 0; + } + + //! get first preconditioner + sp_base_t get_prec_1 () const + { + return base_t::prec; + } + + //! get second preconditioner + sp_base_t get_prec_2 () const + { + return prec_2; + } + + ///** + // * \brief set sub node by their name + // * + // * \param[in] name The name of subnode + // * \param[in] obj The smart pointer to new object + // */ + //virtual void set_subnode (const std::string &name, sp_obj obj) + //{ + // if (name == "prec_2") + // { + // base_t::set_subnode_internal (name, obj, prec_2); + // } + // else + // { + // base_t::set_subnode (name, obj); + // } + //} + + BLUE_SKY_TYPE_DECL (two_stage_preconditioner); + + private: + //----------------------------------------- + // VARIABLES + //----------------------------------------- + //#ifdef _MPI + // mpi_vector mpi_r, mpi_w; + //#endif //_MPI + + public: + + private: + sp_base_t prec_2; + + item_array_t r_array; + item_array_t w_array; + }; + + //! register types into kernel + bool + two_stage_prec_register_type (const blue_sky::plugin_descriptor &pd); + +/* + template + int + solve_helper (solver_t *solver, typename solver_t::matrix_t *mx, seq_vector &rhs, typename solver_t::item_array_t &sol) + { + solver->solve (mx, rhs, sol); + } + + template + int + solve_helper (solver_t *solver, typename solver_t::matrix_t *mx, seq_vector &rhs, typename solver_t::item_array_t &sol) + { + solver->solve_prec (mx, rhs, sol); + } + +*/ +} // namespace blue_sky +#endif // TWO_STAGE_PREC_H__ diff --git a/bs_bos_core/include/well_connection.h b/bs_bos_core/include/well_connection.h new file mode 100644 index 0000000..26234b3 --- /dev/null +++ b/bs_bos_core/include/well_connection.h @@ -0,0 +1,238 @@ +/** + * \file well_connection.h + * \brief well connection class declaration + * \author Sergey Miryanov + * \date 06.08.2008 + * */ +#ifndef BS_WELL_CONNECTION_H_ +#define BS_WELL_CONNECTION_H_ + +#include "fi_params.h" +#include BS_FORCE_PLUGIN_IMPORT () +#include "convert_units.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "well_type_helper.h" +#include "wells_compute_connection_factors.h" +#include "array_ext.h" + +#include "well_controller.h" + + +namespace blue_sky + { + + template + class well; + + template + class calc_model; + + namespace wells + { + + /////////////////////////////////////////////////////////////////////////// + enum connection_type + { + CONNECTION_USUAL, + CONNECTION_GRP_PRIMARY, + CONNECTION_GRP_SECONDARY, + + CONNECTION_TOTAL, + }; + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + enum connection_direction_type + { + direction_x, + direction_y, + direction_z, + + direction_total, + }; + + connection_direction_type + connection_direction_cast (const std::string &str); + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + enum connection_status_type + { + connection_open, + connection_shut, + + connection_total, + }; + + connection_status_type + connection_status_cast (const std::string &str); + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + template + class BS_API_PLUGIN connection : public objbase + { + public: + + typedef connection this_t; + typedef smart_ptr sp_this_t; + + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; + typedef typename strategy_t::index_t index_t; + + typedef rate_data rate_data_t; + typedef typename rate_data_t::rate_data_inner rate_data_inner_t; + + typedef fi_params params_t; + typedef smart_ptr sp_params_t; + + typedef rs_mesh_iface mesh_iface_t; + typedef smart_ptr sp_mesh_iface_t; + + typedef connection connection_t; + typedef calc_model calc_model_t; + typedef well well_t; + + public: + + void compute_factors (const physical_constants &internal_contstants, + const sp_params_t ¶ms, + const sp_mesh_iface_t &mesh, + const item_array_t &perm, + const item_array_t &ntg, + bool ro_calc_flag = false); + + void mul_perm_mult (item_t mult); + + void set_half_length (item_t half_length); + void set_theta (item_t theta); + void set_skin (item_t skin); + void set_status (connection_status_type connection_status); + void set_factor (item_t factor); + void set_diameter (item_t diameter); + void set_Kh (item_t kh); + void set_direction (connection_direction_type direction); + void set_coord (index_t i, index_t j, index_t k, index_t n_block); + void set_connection_depth (const sp_mesh_iface_t &mesh); + + index_t n_block () const; + item_t get_fact () const; + + void set_bulkp (item_t bulkp); + void set_rate (item_t rate); + void set_head_term (item_t head_term); + void set_cur_bhp (item_t cur_bhp); + void set_mult (item_t mult); + void set_seg_number (const index_t &seg); + + bool is_shut () const; + + connection_status_type get_status () const + { + return status_; + } + + connection_direction_type get_dir () const + { + return dir_; + } + + item_t get_cur_bhp () const; + item_t get_density () const; + item_t get_connection_depth () const; + item_t get_bulkp () const; + + index_t i_coord () const; + index_t j_coord () const; + index_t k_coord () const; + + item_t mult () const; + + item_t get_head_term () const; + index_t get_seg_number () const; + + virtual void clear_data (); + virtual array_ext get_rw_value (); + virtual array_ext get_wr_value (); + virtual array_ext get_rr_value (); + virtual array_ext get_ps_value (); + virtual array_ext get_rate_value (); + + public: + auto_value head_term; + auto_value cur_bhp; + auto_value connection_depth; + auto_value density; + auto_value bulkp; + + rate_data_t rate_; + rate_data_t rate_rc_; + + const rate_data_t & + rate () const + { + return rate_; + } + + const rate_data_inner_t & + rate_prod () const + { + return rate_.prod; + } + + const rate_data_inner_t & + rate_inj () const + { + return rate_.inj; + } + + private: + + template + friend struct wells::compute_factors::peaceman_model; + + template + friend struct wells::compute_factors::baby_odeh_model; + + auto_value i_coord_; //!< i coord of connection + auto_value j_coord_; //!< j coord of connection + auto_value k_coord_; //!< k coord of connection + + auto_value + status_; //!< connection status + + // for compute factors. in the future this vars should be evolved to separate class + auto_value diam_; //!< Well diameter + auto_value kh_; //!< Effective Kh + auto_value skin_; //!< Well skin factor + auto_value mult_; //!< + auto_value fact_; //!< connection factor + auto_value R0_; //!< R0 + + auto_value fracture_half_length_; //!< half length of fracture + auto_value fracture_angle_; //!< angle of fracture in grid block to OX direction + auto_value fracture_perm_; //!< coefficient of "permeability" on fracture + + auto_value n_block_; //!< number of block in grid (n_block <-> (i, j, k)) + + auto_value + dir_; //!< direction + + auto_value + connection_type_; //!< connection type + + protected: + auto_value iseg_; + public: + BLUE_SKY_TYPE_DECL_T (connection ); + }; + + + } // namespace wells +} // namespace blue_sky + + +#endif // #ifndef BS_WELL_CONNECTION_H_ diff --git a/bs_bos_core/include/well_controller.h b/bs_bos_core/include/well_controller.h new file mode 100644 index 0000000..c624ac6 --- /dev/null +++ b/bs_bos_core/include/well_controller.h @@ -0,0 +1,309 @@ +/** + * \file well_controller.h + * \brief well_controller + * \author Sergey Miryanov + * \date 14.07.2008 + * */ +#ifndef BS_WELL_CONTROLLER_H_ +#define BS_WELL_CONTROLLER_H_ + +#include "well_type_helper.h" +#include "rate_control_type.h" +#include "well_rate_control_interface.h" + +namespace blue_sky + { + + template + class well; + + template + class calc_model; + + template + struct calc_model_data; + + template + struct rate_data + { + typedef typename strategy_t::item_t item_t; + + struct rate_data_inner + { + item_t oil; + item_t water; + item_t gas; + item_t liquid; + + rate_data_inner () + : oil (0) + , water (0) + , gas (0) + , liquid (0) + { + } + + void + operator= (item_t value) + { + oil = value; + water = value; + gas = value; + liquid = value; + } + + void + operator+= (const rate_data_inner &rhs) + { + oil += rhs.oil; + water += rhs.water; + gas += rhs.gas; + liquid += rhs.liquid; + } + + rate_data_inner + operator * (item_t mult) const + { + rate_data_inner r; + r.oil = mult * oil; + r.water = mult * water; + r.gas = mult * gas; + r.liquid = mult * liquid; + + return r; + } + }; + + rate_data () + : liquid_inner (0) + , free_gas (0) + , solution_gas (0) + { + } + + rate_data & + operator= (item_t value) + { + prod = value; + inj = value; + liquid_inner = value; + free_gas = value; + solution_gas = value; + + return *this; + } + + void + operator += (const rate_data &rhs) + { + prod += rhs.prod; + inj += rhs.inj; + liquid_inner += rhs.liquid_inner; + free_gas += rhs.free_gas; + solution_gas += rhs.solution_gas; + } + + rate_data + operator * (item_t mult) const + { + rate_data r; + r.prod = prod * mult; + r.inj = inj * mult; + r.liquid_inner = liquid_inner * mult; + r.free_gas = free_gas * mult; + r.solution_gas = solution_gas * mult; + + return r; + } + + rate_data_inner prod; + rate_data_inner inj; + + item_t liquid_inner; + item_t free_gas; + item_t solution_gas; + }; + + namespace wells + { + + template + class well_controller; + + template + class connection; + + template + class well_rate_control; + + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + enum rate_value_type + { + null_value = 0, //!< null value; means value not set + oil_rate_value = 1, //!< value for oil rate + water_rate_value = 2, //!< value for water rate + liquid_rate_value = 3, //!< value for liquid rate + gas_rate_value = 4, //!< value for gas rate + rate_value = 5, //!< rate value for injection well (actual rate selected by injection phase) + bhp_value = 8, //!< value of pressure on surface + liquid_inner_rate_value = 9, //!< value for liquid rate into bed + }; + bool is_oil_rate_value (rate_value_type type); + bool is_water_rate_value (rate_value_type type); + bool is_gas_rate_value (rate_value_type type); + bool is_liquid_rate_value (rate_value_type type); + + rate_value_type + rate_value_cast (const std::string &str); + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + enum injection_type + { + injection_none, + injection_water, + injection_gas, + injection_oil, + }; + + injection_type + injection_type_cast (const std::string &str); + /////////////////////////////////////////////////////////////////////////// + + template + class BS_API_PLUGIN well_controller : public objbase + { + public: + + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef well_rate_control well_rate_control_t; + typedef well well_t; + typedef connection connection_t; + typedef jacobian_matrix jacobian_matrix_t; + typedef well_controller this_t; + typedef calc_model calc_model_t; + + typedef rate_data rate_data_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_jmatrix_t; + typedef smart_ptr sp_well_t; + + typedef smart_ptr sp_rate_control_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_jacobian_matrix_t; + typedef smart_ptr sp_this_t; + + typedef wells::type_helper helper_t; + + typedef typename helper_t::item_rhs_block_t item_rhs_block_t; + typedef typename helper_t::item_ww_block_t item_ww_block_t; + typedef typename helper_t::item_q_rate_t item_q_rate_t; + typedef typename helper_t::item_q_rate_inflow_t item_q_rate_inflow_t; + typedef typename helper_t::item_gas_rate_t item_gas_rate_t; + + public: + virtual ~well_controller () {} + + void clear_rate (); + void set_rate (rate_value_type rate_value, item_t value); + void set_bhp (item_t value); + void set_bhp_history (item_t value); + void add_bhp_control (const sp_rate_control_t &bhp_control); + void add_rate_control (const sp_rate_control_t &rate_control); + void set_main_control (const sp_well_t &well, rate_control_type control); + void set_injection_type (injection_type type); + + const rate_data_t &rate () const; + const item_t &bhp () const; + const item_t &bhp_history () const; + + const injection_type &injection () const; + + bool is_bhp () const; + bool is_rate () const; + bool is_production () const; + bool is_valid_connection_bhp (item_t pressure, item_t bhp) const; + + void save_control (); + bool restore_control (); + void save_niter_control (); + bool restore_niter_control (); + + void switch_to_bhp (sp_well_t &well); + bool check (sp_well_t &well); + void calc_rate (const sp_calc_model_t &calc_model, sp_well_t &well, sp_jmatrix_t &jmatrix) const; + void calc_derivs (const sp_calc_model_t &calc_model, sp_well_t &well, sp_jmatrix_t &jmatrix) const; + + rate_control_type get_control_type () const; + + BLUE_SKY_TYPE_DECL_T (well_controller); + + public: + // TODO: + rate_data_t rate_; + + private: + item_t bhp_; //!< pw,ref; rate_value_type::pref_value + item_t bhp_history_; //!< + + injection_type injection_type_; //!< injection type (now only WATER) + + static sp_rate_control_t dummy_control_; + sp_rate_control_t bhp_control_; + sp_rate_control_t rate_control_; + + sp_rate_control_t current_control_; + sp_rate_control_t saved_control_; + sp_rate_control_t saved_niter_control_; + }; + + template + class BS_API_PLUGIN well_controller_factory : public objbase + { + public: + + typedef calc_model calc_model_t; + typedef well_controller well_controller_t; + typedef well_rate_control well_rate_control_t; + typedef well_rate_control_factory well_rate_control_factory_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_rate_control_t; + typedef smart_ptr sp_well_rate_control_factory_t; + + public: + + virtual ~well_controller_factory () {}; + + void set_rate_control_factory (const sp_well_rate_control_factory_t &rate_control_factory); + + virtual sp_well_controller_t create_controller () const; + virtual sp_rate_control_t create_control (rate_control_type rate_control, bool is_prod, const sp_calc_model_t &calc_model) const; + + BLUE_SKY_TYPE_DECL_T (well_controller_factory); + + private: + + sp_well_rate_control_factory_t well_rate_control_factory_; + }; + + bool + well_controller_register_type (const blue_sky::plugin_descriptor &pd); + + bool + well_controller_factory_register_type (const blue_sky::plugin_descriptor &pd); + + + } // namespace wells +} // namespace blue_sky + + +#endif // #ifnded BS_WELL_CONTROLLER_H_ + diff --git a/bs_bos_core/include/well_event_params_decl.h b/bs_bos_core/include/well_event_params_decl.h new file mode 100644 index 0000000..1e23159 --- /dev/null +++ b/bs_bos_core/include/well_event_params_decl.h @@ -0,0 +1,130 @@ +/** + * \file well_event_params_decl.h + * \brief + * \author Sergey Miryanov + * \date 15.07.2009 + * */ +#ifndef BS_BOS_CORE_WELL_EVENT_PARAMS_DECL_H_ +#define BS_BOS_CORE_WELL_EVENT_PARAMS_DECL_H_ + +#include +#include +#include +#include + +#include "named_pbase_type_helper.h" + +#define PARAMS_DECL_BLUE_SKY(type_t, base_t, type_name) \ + BLUE_SKY_TYPE_STD_CREATE_T_MEM (type_t) \ + BLUE_SKY_TYPE_STD_COPY_T_MEM (type_t) \ + BS_LOCK_THIS_DECL(type_t); \ + \ + friend class type_descriptor; \ + \ + static const type_descriptor & \ + td_maker (const std::string &stype_postfix) \ + { \ + static blue_sky::type_descriptor td(Loki::Type2Type () \ + , Loki::Type2Type () \ + , Loki::Int2Type () \ + , stype_postfix \ + , "" \ + , ""); \ + \ + return td; \ + } \ + \ + static blue_sky::type_descriptor bs_type() \ + { \ + return td_maker (std::string (type_name) + "_" + BOOST_CURRENT_FUNCTION); \ + } \ + virtual blue_sky::type_descriptor bs_resolve_type() const \ + { \ + return bs_type (); \ + } + + +#define PARAMS_DECLARE_CLASS_I(r, data, i, elem) \ + BOOST_PP_TUPLE_ELEM (3, 0, elem), + +#define PARAMS_DECLARE_CLASS_GETTERS_I(r, data, i, elem) \ + tools::named_pbase_value_type_helper ::type \ + BOOST_PP_CAT (get_, BOOST_PP_TUPLE_ELEM (3, 0, elem)) () const \ + { \ + idx_type index = BOOST_PP_TUPLE_ELEM (3, 0, elem); \ + return tools::named_pbase_value_type_helper ::get (this, index); \ + } \ + tools::named_pbase_value_type_helper ::type \ + BOOST_PP_CAT (get_, BOOST_PP_TUPLE_ELEM (3, 0, elem)) ( \ + const tools::named_pbase_value_type_helper ::type &def \ + ) const \ + { \ + idx_type index = BOOST_PP_TUPLE_ELEM (3, 0, elem); \ + return tools::named_pbase_value_type_helper ::get_d (this, index, def); \ + } \ + bool \ + BOOST_PP_CAT (check_, BOOST_PP_TUPLE_ELEM (3, 0, elem)) () const \ + { \ + idx_type index = BOOST_PP_TUPLE_ELEM (3, 0, elem); \ + return this->check_value (index); \ + } +#define PARAMS_DECLARE_CLASS_EREG_I(r, data, i, elem) \ + ereg (BOOST_PP_TUPLE_ELEM (3, 0, elem), \ + BOOST_PP_STRINGIZE (BOOST_PP_TUPLE_ELEM (3, 0, elem)), \ + BOOST_PP_TUPLE_ELEM (3, 1, elem), \ + BOOST_PP_TUPLE_ELEM (3, 2, elem)); + +#define MAIN_PARAMS_DECLARE_CLASS(class_name, seq) \ + struct BS_API_PLUGIN class_name : public named_pbase \ + { \ + PROP_BASE_IDX_DECL_BEGIN (class_name, named_pbase) \ + BOOST_PP_SEQ_FOR_EACH_I (PARAMS_DECLARE_CLASS_I, _, seq) \ + CLASS_NAME_TOTAL, \ + PROP_BASE_IDX_DECL_END \ + PBASE_ACCESS_MS (class_name); \ + BOOST_PP_SEQ_FOR_EACH_I (PARAMS_DECLARE_CLASS_GETTERS_I, _, seq) \ + ~class_name () {} \ + class_name (bs_type_ctor_param ) \ + : bs_refcounter (), named_pbase () \ + { \ + this->resize (CLASS_NAME_TOTAL); \ + BOOST_PP_SEQ_FOR_EACH_I (PARAMS_DECLARE_CLASS_EREG_I, class_name, seq) \ + } \ + class_name (const class_name &c) \ + : bs_refcounter (c), named_pbase () \ + { \ + this->resize (CLASS_NAME_TOTAL); \ + BOOST_PP_SEQ_FOR_EACH_I (PARAMS_DECLARE_CLASS_EREG_I, class_name, seq) \ + } \ + PARAMS_DECL_BLUE_SKY (class_name, named_pbase, BOOST_PP_STRINGIZE (class_name)) \ + }; + +#define MAIN_PARAMS(seq) \ + MAIN_PARAMS_DECLARE_CLASS (main_params_class, seq); \ + smart_ptr main_params_; \ + smart_ptr \ + main_params () const \ + { \ + return main_params_; \ + } + +#define NEXT_LINE_PARAMS(seq) \ + MAIN_PARAMS_DECLARE_CLASS (next_line_params_class, seq); \ + typedef smart_ptr sp_next_line_params_t; \ + seq_vector next_line_params_; \ + smart_ptr \ + add_next_line_params () \ + { \ + sp_next_line_params_t p = BS_KERNEL.create_object (next_line_params_class::bs_type ()); \ + if (!p) \ + { \ + bs_throw_exception ("Can't create next_line_params"); \ + } \ + next_line_params_.push_back (p); \ + return p; \ + } \ + bool is_multi_line () const { return true; } + + + +#endif // #ifndef BS_BOS_CORE_WELL_EVENT_PARAMS_DECL_H_ diff --git a/bs_bos_core/include/well_events.h b/bs_bos_core/include/well_events.h new file mode 100644 index 0000000..c62c5c8 --- /dev/null +++ b/bs_bos_core/include/well_events.h @@ -0,0 +1,840 @@ +/** +* @file well_event.h +* @brief declaration of well events +* @author Morozov Andrey +* @date 2008-06-07 +*/ +#ifndef WELL_EVENTS_H_ +#define WELL_EVENTS_H_ + +#include "event_base.h" +#include "well_event_params_decl.h" + +namespace blue_sky + { + + template + class well; + + template + class reservoir; + + template + class calc_model; + + namespace wells + { + template + class connection; + + template + class well_controller; + + class well_limit_operation; + } + + template + class BS_API_PLUGIN well_event : public event_base + { + public: + + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + public: + + virtual ~well_event () {} + virtual void apply (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + virtual std::string get_well_name () const; + virtual std::string get_group_name () const; + virtual std::string get_event_name () const; + + protected: + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + }; + +//============================================================================================ + //! WELLSPEC_event class. + /*! + WELLSPEC Introduces a new well 3 + This keyword introduces a new well, specifying the name and position of the well + head, the BHP reference depth and the separator used. + */ + template + class BS_API_PLUGIN WELSPECS_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WELSPECS_event); + public: + + MAIN_PARAMS ( + ((WELL_NAME, "Well name", PT_STR)) + ((WELL_GROUP_NAME, "Name of the group to which the well belongs", PT_STR)) + ((I, "I - location of well head or heel", PT_INT)) + ((J, "J - location of well head or heel", PT_INT)) + ((BHP_DEPTH, "", PT_FLOAT)) + ); + + //NEXT_LINE_PARAMS ( + // ((WELL_NAME, "Well name", PT_STR)) + // ((WELL_GROUP_NAME, "Name of the group to which the well belongs", PT_STR)) + // ((I, "I - location of well head or heel", PT_INT)) + // ((J, "J - location of well head or heel", PT_INT)) + // ((BHP_DEPTH, "", PT_FLOAT)) + //); + + //! destructor + virtual ~WELSPECS_event () {} + + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! WELLCON_event class. + /*! + Specifies the position and properties of one or more well completions. This must be + entered after the WELLSPEC keyword defining the appropriate well. + */ + template + class BS_API_PLUGIN WELLCON_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WELLCON_event); + public: + + MAIN_PARAMS ( + ((WELL_NAME, "Well name", PT_STR)) + ((WELL_GROUP_NAME, "Name of the group to which the well belongs", PT_STR)) + ((I, "I - location of well head or heel", PT_INT)) + ((J, "J - location of well head or heel", PT_INT)) + ((FIRST_LAYER, "First layer", PT_INT)) + ((LAST_LAYER, "Last layer", PT_INT)) + ((WELL_STATE, "Open/shut flag for the well", PT_STR)) + ((WELL_DIAMETER, "Well bore diameter at the connection", PT_FLOAT)) + ((SKIN, "Skin factor", PT_FLOAT)) + ((KH, "Effective Kh (permeability x thickness) value of the connection", PT_FLOAT)) + ((DIRECTION, "Direction in which the well penetrates the grid block", PT_STR)) + ); + + //! destructor + virtual ~WELLCON_event () {} + + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + //! COMPDAT_event class. + /*! + COMPDAT specifies the position and properties of one or more well completions. This + must be entered after the WELSPECS keyword defining the appropriate well. + */ + template + class BS_API_PLUGIN COMPDAT_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(COMPDAT_event); + public: + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((I, "I - location of well head or heel", PT_INT)) + ((J, "J - location of well head or heel", PT_INT)) + ((FIRST_LAYER, "K - location of upper connecting block in this set of data", PT_INT)) + ((LAST_LAYER, "K - location of lower connecting block in this set of data", PT_INT)) + ((PERFORATION_STATUS, "Open/shut flag for the well", PT_STR)) + ((PARAM7, "Well bore diameter at the connection", PT_INT)) + ((PERFORATION_FACTOR, "Transmissibility factor for the connection", PT_FLOAT)) + ((WELL_DIAMETER, "Well bore diameter at the connection", PT_FLOAT)) + ((KH, "Effective Kh (permeability x thickness) value of the connection", PT_FLOAT)) + ((SKIN, "Skin factor", PT_FLOAT)) + ((PARAM12, "", PT_STR)) + ((DIRECTION, "Direction in which the well penetrates the grid block", PT_STR)) + ((PARAM13, "", PT_STR)) + ((SEG_NUMBER, "Segment which contains this perforation", PT_INT)) + ); + + //! destructor + virtual ~COMPDAT_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! WCONPROD_event class. + /*! + WCONPROD Control data for production wells + */ + template + class BS_API_PLUGIN WCONPROD_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WCONPROD_event); + public: + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((WELL_STATE, "Open/shut flag for the well", PT_STR)) + ((WELL_CONTROL_MODE, "Control mode", PT_STR)) + ((OIL_RATE, "Oil rate target or upper limit", PT_FLOAT)) + ((WATER_RATE, "Water rate target or upper limit", PT_FLOAT)) + ((GAS_RATE, "Gas rate target or upper limit", PT_FLOAT)) + ((OUTER_RATE, "Liquid rate target or upper limit", PT_FLOAT)) + ((INNER_RATE, "Reservoir fluid volume rate target or upper limit", PT_FLOAT)) + ((BHP, "BHP target or lower limit", PT_FLOAT)) + ); + + //! destructor + virtual ~WCONPROD_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + + +//============================================================================================ + + //! WCONHIST_event class. + /*! + WCONHIST Observed rates for history matching + production wells + + This keyword is used in place of WCONPROD to declare production wells as special + history matching wells, and to enter their observed flow rates (and optionally their + measured BHP and THP values). The equivalent keyword for defining history + matching injection wells is WCONINJH. + */ + template + class BS_API_PLUGIN WCONHIST_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WCONHIST_event); + public: + + //TODO: check for one more param! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((WELL_STATE, "Open/shut flag for the well", PT_STR)) + ((WELL_CONTROL_MODE, "Control mode", PT_STR)) + ((OIL_RATE, "Observed oil production rate", PT_FLOAT)) + ((WATER_RATE, "Observed water production rate", PT_FLOAT)) + ((GAS_RATE, "Observed gas production rate", PT_FLOAT)) + ((PARAM7, "", PT_STR)) + ((PARAM8, "", PT_STR)) + ((PARAM9, "", PT_STR)) + ((BHP, "Observed bottom hole pressure (BHP)", PT_FLOAT)) + ); + + //! destructor + virtual ~WCONHIST_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + + +//============================================================================================ + + //! WCONINJE_event class. + /*! + Injection well control data, with no group + control + This keyword can be used to set individual control targets and limits for injection + wells, + */ + template + class BS_API_PLUGIN WCONINJE_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WCONINJE_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((INJECTOR_TYPE, "Injector type", PT_STR)) + ((WELL_STATE, "Open/shut flag for the well", PT_STR)) + ((WELL_CONTROL_MODE, "Control mode", PT_STR)) + ((OUTER_RATE, "Surface flow rate target or upper limit", PT_FLOAT)) + ((INNER_RATE, "Reservoir fluid volume rate target or upper limit", PT_FLOAT)) + ((BHP, "BHP target or lower limit", PT_FLOAT)) + ((PARAM1, "dummy for bug", PT_STR)) + ); + + //! destructor + virtual ~WCONINJE_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + //float def_outer_rate(){return 0;} + //float def_inner_rate(){return 0;} + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! WECON_event class. + /*! + Economic limit data for production wells + */ + template + class BS_API_PLUGIN WECON_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WECON_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((MIN_OIL_RATE, "Minimum oil production rate", PT_FLOAT)) + ((WATER_CUT, "Maximum water cut", PT_FLOAT)) + ((OPERATION, "Workover procedure on exceeding limit", PT_STR)) + ); + + //! destructor + virtual ~WECON_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! WECONINJ_event class. + /*! + Economic limit data for injection wells + */ + template + class BS_API_PLUGIN WECONINJ_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WECONINJ_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((MIN_RATE, "Minimum economic water injection rate", PT_FLOAT)) + ); + + //! destructor + virtual ~WECONINJ_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! WEFAC_event class. + /*! + Sets well efficiency factors (for downtime) + */ + template + class BS_API_PLUGIN WEFAC_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WEFAC_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((OPERATION_FACTOR, "Efficiency factor for the well", PT_FLOAT)) + ); + + //! destructor + virtual ~WEFAC_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! WELTARG_event class. + /*! + WELTARG Resets a well operating target or limit + This keyword can be used to reset a target or limit value for a well, without having to + re-specify all the other quantities required by the control keywords WCONPROD or + WCONINJE. These other quantities are left unchanged, including the open/shut status + of the well. + If the well has been declared a history matching well (see keywords WCONHIST and + WCONINJH) the WELTARG keyword may be used to modify its BHP limit, VFP table + number, and artificial lift quantity. The other quantities should not be modified with + this keyword. + */ + template + class BS_API_PLUGIN WELTARG_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WELTARG_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((WELL_CONTROL, "Definition of the control or constraint quantity to be changed", PT_STR)) + ((VALUE, "New value", PT_FLOAT)) + ); + + //! destructor + virtual ~WELTARG_event () {} + void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! WPIMULT_event class. + /*! + WPIMULT Multiplies well connection factors by a given + value + This keyword can be used to multiply the connection transmissibility factors of + selected well connections by a specified value. To multiply the transmissibility factors + of all the connections in a well, leave items 3 - 7 defaulted. To multiply the + transmissibility factors of a subset of connections in a well, you can identify the subset + by their I,J,K location (items 3 - 5). A subset of connections can also be identified by + their completion + */ + template + class BS_API_PLUGIN WPIMULT_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(WPIMULT_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((PERM_FACTOR, "Multiplier to act on the wells connection transmissibility factors and Kh values", PT_FLOAT)) + ((I, "I - location of connecting grid block(s)", PT_INT)) + ((J, "J - location of connecting grid block(s)", PT_INT)) + ((K, "K - location of connecting grid block(s)", PT_INT)) + ((Z1, "Number of first completion in range", PT_INT)) + ((Z2, "Number of last completion in range", PT_INT)) + ); + + //! destructor + virtual ~WPIMULT_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! COMPENSATION_event class. + /*! + COMPENSATION defines a compensation type and rate for well group + */ + template + class BS_API_PLUGIN COMPENSATION_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(COMPENSATION_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_GROUP, "Name of the group to which the well belongs", PT_STR)) + ((COMPENSATION_RATE, "Compensation rate", PT_FLOAT)) + ((COMPENSATION_TYPE, "Compensation type", PT_STR)) + ); + + //! destructor + virtual ~COMPENSATION_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! FRACTURE_event class. + /*! + Defines the fracture in well + */ + template + class BS_API_PLUGIN FRACTURE_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(FRACTURE_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((WELL_NAME, "Well name, well name root or well list name", PT_STR)) + ((I, "I - location", PT_INT)) + ((J, "J - location", PT_INT)) + ((KW1, "fracture head location", PT_INT)) + ((KW2, "fracture tail location", PT_INT)) + ((HALF_LENGHT, "Half of the fracture length", PT_FLOAT)) + ((TETTA, "the angle between fracture and positive OX direction", PT_FLOAT)) + ((SKIN, "Skin factor", PT_FLOAT)) + ((WELL_STATE, "Open/shut flag for the well", PT_STR)) + ((PARAM10, "", PT_STR)) + ((PARAM11, "", PT_STR)) + ); + //! destructor + virtual ~FRACTURE_event () {} + virtual void apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + protected: + virtual std::string get_well_name () const; + virtual std::string get_event_name () const; + }; + +//============================================================================================ + + //! PERMFRAC_event class. + /*! + Defines the fracture in cells + */ + template + class BS_API_PLUGIN PERMFRAC_event: public well_event + { + public: + typedef reservoir reservoir_t; + + typedef well well_t; + typedef wells::connection connection_t; + typedef wells::well_controller well_controller_t; + typedef wells::well_limit_operation well_limit_operation_t; + typedef rs_mesh_iface mesh_iface_t; + typedef rs_smesh_iface smesh_iface_t; + typedef calc_model calc_model_t; + + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_connection_t; + typedef smart_ptr sp_mesh_iface_t; + typedef smart_ptr sp_smesh_iface_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_well_limit_operation_t; + typedef smart_ptr sp_calc_model_t; + + typedef smart_ptr sp_top; + BLUE_SKY_TYPE_DECL(PERMFRAC_event); + public: + + //TODO: there are a number of additional params in eclipse ! + MAIN_PARAMS ( + ((I, "I - location", PT_INT)) + ((J, "J - location", PT_INT)) + ((KW1, "fracture head location", PT_INT)) + ((KW2, "fracture tail location", PT_INT)) + ((NUM_RIGHT, "Number of cell placed at right side of central fracture cell", PT_INT)) + ((NUM_LEFT, "Number of cell placed at left side of central fracture cell", PT_INT)) + ((FRAC_PERM, "Fracture permeability", PT_FLOAT)) + ((SKIN, "Skin factor", PT_FLOAT)) + ((FRACTURE_DIRECTION, "Fracture direction", PT_STR)) + ((PARAM10, "", PT_STR)) + ); + + //! destructor + virtual ~PERMFRAC_event () {} + + protected: + virtual std::string get_event_name () const; + }; + +}//namespace blue_sky + +#endif//WELL_EVENTS_H_ + diff --git a/bs_bos_core/include/well_iterator.h b/bs_bos_core/include/well_iterator.h new file mode 100644 index 0000000..77dabe9 --- /dev/null +++ b/bs_bos_core/include/well_iterator.h @@ -0,0 +1,52 @@ +///** +// * \file well_iterator.h +// * \brief class for iterate well in facility_manager +// * \author Sergey Miryanov +// * \date 08.08.2008 +// * */ +//#ifndef BS_WELL_ITERATOR_H_ +//#define BS_WELL_ITERATOR_H_ +// +//#include +// +//namespace blue_sky +// { +// +// template +// class facility_manager; +// +// template +// class well; +// +// template +// class BS_API_PLUGIN well_iterator : public std::iterator +// { +// public: +// +// typedef well_iterator this_t; +// typedef value_type_t value_type; +// +// public: +// well_iterator (const list_t &list, const iterator_t &it); +// +// bool operator == (const this_t &rhs) const; +// bool operator != (const this_t &rhs) const; +// +// const this_t &operator = (const this_t &src); +// +// value_type operator * () const; +// +// this_t& operator ++ (); +// this_t operator ++ (int); +// +// private: +// list_t list_; +// iterator_t it_; +// }; +// +// +// +//} // namespace blue_sky +// +//#endif // #ifndef BS_WELL_ITERATOR_H_ +// diff --git a/bs_bos_core/include/well_limit_operation.h b/bs_bos_core/include/well_limit_operation.h new file mode 100644 index 0000000..8f38754 --- /dev/null +++ b/bs_bos_core/include/well_limit_operation.h @@ -0,0 +1,80 @@ +/** + * \file well_limit_operation.h + * \brief well_limit_operation + * \author Sergey Miryanov + * \date 14.07.2008 + * */ +#ifndef BS_WELL_LIMIT_OPERATION_H_ +#define BS_WELL_LIMIT_OPERATION_H_ + +namespace blue_sky + { + namespace wells + { + + enum limit_operation_type + { + operation_none, + operation_con, + operation_well, + operation_total, + }; + + limit_operation_type + limit_operation_cast (const std::string &str); + + class BS_API_PLUGIN well_limit_operation : public objbase + { + public: + + typedef double item_t; + + public: + + void set_min_oil_rate (item_t min_oil_rate); + void set_max_water_cut (item_t max_water_cut); + void set_min_water_cut (item_t min_water_cut); + + void set_value (int value_type, item_t value); + + bool fi_check_limits () const; + + BLUE_SKY_TYPE_DECL (well_limit_operation); + + private: + + //friend class well_limit_operation; + + item_t min_oil_rate_; + item_t max_water_cut_; + item_t min_water_cut_; + + }; + + class BS_API_PLUGIN well_limit_operation_factory : public objbase + { + public: + + typedef smart_ptr sp_well_limit_operation_t; + + public: + + virtual ~well_limit_operation_factory () {} + + virtual sp_well_limit_operation_t create_limit (limit_operation_type type) const; + + BLUE_SKY_TYPE_DECL (well_limit_operation_factory); + }; + + bool + well_limit_operation_register_type (const blue_sky::plugin_descriptor &pd); + + bool + well_limit_operation_factory_register_type (const blue_sky::plugin_descriptor &pd); + + + } // namespace wells +} // namespace blue_sky + + +#endif // #ifndef BS_WELL_LIMIT_OPERATION_H_ diff --git a/bs_bos_core/include/well_rate_call_proxy.h b/bs_bos_core/include/well_rate_call_proxy.h new file mode 100644 index 0000000..b02d479 --- /dev/null +++ b/bs_bos_core/include/well_rate_call_proxy.h @@ -0,0 +1,84 @@ +/** + * \file well_rate_call_proxy.h + * \brief helper class to call functors in connection loop + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_CALL_PROXY_H_ +#define BS_WELLS_WELL_RATE_CONTROL_CALL_PROXY_H_ + +namespace blue_sky + { + + template + struct one_call_proxy + { + one_call_proxy (wrapped_t *wrapped, callee_t callee) + : wrapped_ (wrapped) + , callee_ (callee) + { + } + + template + void + operator () (const locked_connection_t &c, const data_t &data, params_t ¶ms) const + { + ((*wrapped_).*callee_) (c, data, params); + } + template + void + operator () (const locked_connection_t &c, const data_t &data) const + { + ((*wrapped_).*callee_) (c, data); + } + template + void + operator () (const locked_connection_t &c, params_t ¶ms) const + { + ((*wrapped_).*callee_) (c, params); + } + + wrapped_t *wrapped_; + callee_t callee_; + }; + + template + struct two_call_proxy + { + two_call_proxy (wrapped_t *wrapped, callee_t first_callee, callee_t second_callee) + : wrapped_ (wrapped) + , first_callee_ (first_callee) + , second_callee_ (second_callee) + { + } + + template + void + operator () (const locked_connection_t &c, const data_t &data, params_t ¶ms) const + { + ((*wrapped_).*first_callee_) (c, data, params); + ((*wrapped_).*second_callee_) (c, data, params); + } + + wrapped_t *wrapped_; + callee_t first_callee_; + callee_t second_callee_; + }; + + template + static one_call_proxy + one_call (this_t *this_, callee_t callee) + { + return one_call_proxy (this_, callee); + } + template + static two_call_proxy + two_call (this_t *this_, callee_t first_callee, callee_t second_callee) + { + return two_call_proxy (this_, first_callee, second_callee); + } + +} // namespace blue_sky + +#endif // #ifndef BS_WELL_WELL_RATE_CONTROL_CALL_PROXY_H_ + diff --git a/bs_bos_core/include/well_rate_compute_params.h b/bs_bos_core/include/well_rate_compute_params.h new file mode 100644 index 0000000..a20a3aa --- /dev/null +++ b/bs_bos_core/include/well_rate_compute_params.h @@ -0,0 +1,187 @@ +/** + * \file well_rate_compute_params.h + * \brief params for compute well derivs + * \author Sergey Miryanov + * \date 14.01.2009 + * */ +#ifndef BS_WELLS_WELL_RATE_COMPUTE_PARAMS_H_ +#define BS_WELLS_WELL_RATE_COMPUTE_PARAMS_H_ + +namespace blue_sky { + + template + struct compute_params + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::index_array_t index_array_t; + + typedef calc_model calc_model_t; + typedef well well_t; + typedef wells::well_controller well_controller_t; + typedef jacobian_matrix jmatrix_t; + + typedef typename calc_model_t::data_t data_t; + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::main_var_array_t main_var_array_t; + typedef typename calc_model_t::phase_d_t phase_d_t; + + typedef typename well_t::rate_data_t rate_data_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_jmatrix_t; + + typedef typename well_t::sp_connection_t sp_connection_t; + + struct inj_params + { + inj_params (wells::injection_type injection) + : is_o_ctrl (injection == wells::injection_oil), + is_w_ctrl (injection == wells::injection_water), + is_g_ctrl (injection == wells::injection_gas), + is_oil_injection (injection == wells::injection_oil), + is_water_injection (injection == wells::injection_water), + is_gas_injection (injection == wells::injection_gas) + { + } + + bool is_o_ctrl; + bool is_w_ctrl; + bool is_g_ctrl; + bool is_oil_injection; + bool is_water_injection; + bool is_gas_injection; + + item_t krow_tetaow; + item_t krp_tetap; + item_t krp_dtetap_dpp; + item_t dkrow_dsw_tetaow_krw_dtetaw_dsw; + item_t dkrog_dsg_tetaog_krg_dtetag_dsg; + }; + + struct prod_params + { + prod_params (wells::rate_control_type control) + : is_o_ctrl (control == wells::oil_rate_control || control == wells::liquid_rate_control), + is_w_ctrl (control == wells::water_rate_control || control == wells::liquid_rate_control), + is_g_ctrl (control == wells::gas_rate_control) + { + } + + bool is_o_ctrl; + bool is_w_ctrl; + bool is_g_ctrl; + }; + + compute_params (const sp_calc_model_t &calc_model, + sp_jmatrix_t &jmatrix, + sp_well_t &well, + const sp_well_controller_t &well_controller) + : calc_model_ (calc_model), + jmatrix_ (jmatrix), + well_ (well), + well_controller_ (well_controller), + main_vars (calc_model_->main_variable), + pressure (calc_model_->pressure), + gas_oil_ratio (calc_model_->gas_oil_ratio), + gravity (calc_model_->internal_constants.gravity_constant), + n_block (-1), + perf_bhp (0), + diff_depth (0), + depth (0), + rho (0), + main_var (FI_NULL), + data_array (calc_model_->data), + phase_d (calc_model_->phase_d), + n_phases (calc_model_->n_phases), + is_o (calc_model_->is_oil ()), + is_w (calc_model_->is_water ()), + is_g (calc_model_->is_gas ()), + bw_value (well_->get_bw_value ()), + ww_value (well_->get_ww_value ()), + rate (well_->rate_), + limit_rate (well_controller_->rate ()), + inj_params_ (inj_params (well_controller_->injection ())), + prod_params_ (prod_params (well_controller_->get_control_type ())), + is_prod (well_controller_->is_production ()), + Po (0), + Pw (0), + Pg (0), + gw (0) + { + } + + void + compute_perf_vars (const data_t &data, inj_params ¶ms) + { + params.krow_tetaow + = (is_o ? RELATIVE_PERM (data, phase_d, FI_PHASE_OIL) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL) : 0) + + (is_w ? RELATIVE_PERM (data, phase_d, FI_PHASE_WATER) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER) : 0); + + params.krp_tetap + = params.krow_tetaow + + (is_g ? RELATIVE_PERM (data, phase_d, FI_PHASE_GAS) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS) : 0); + + params.krp_dtetap_dpp + = (is_o ? RELATIVE_PERM (data, phase_d, FI_PHASE_OIL) * P_DERIV_INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL) : 0) + + (is_w ? RELATIVE_PERM (data, phase_d, FI_PHASE_WATER) * P_DERIV_INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER) : 0) + + (is_g ? RELATIVE_PERM (data, phase_d, FI_PHASE_GAS) * P_DERIV_INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS) : 0); + + params.dkrow_dsw_tetaow_krw_dtetaw_dsw + = (is_o && is_w ? S_DERIV_RELATIVE_PERM (data, phase_d, n_phases, FI_PHASE_OIL, FI_PHASE_WATER) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL) : 0) + + (is_w ? S_DERIV_RELATIVE_PERM (data, phase_d, n_phases, FI_PHASE_WATER, FI_PHASE_WATER) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER) : 0) + + (is_w ? RELATIVE_PERM (data, phase_d, FI_PHASE_WATER) * S_DERIV_INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER) * CAP_PRESSURE (data, phase_d, FI_PHASE_WATER) : 0) + - (is_w ? P_DERIV_INVERS_FVF (data, phase_d, FI_PHASE_WATER) * CAP_PRESSURE (data, phase_d, FI_PHASE_WATER) : 0) + ; + + params.dkrog_dsg_tetaog_krg_dtetag_dsg + = (is_o && is_g ? S_DERIV_RELATIVE_PERM (data, phase_d, n_phases, FI_PHASE_OIL, FI_PHASE_GAS) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL) : 0) + + (is_g ? S_DERIV_RELATIVE_PERM (data, phase_d, n_phases, FI_PHASE_GAS, FI_PHASE_GAS) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS) : 0) + + (is_g ? RELATIVE_PERM (data, phase_d, FI_PHASE_GAS) * S_DERIV_INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS) * CAP_PRESSURE (data, phase_d, FI_PHASE_GAS) : 0) + ; + } + +public: + const sp_calc_model_t &calc_model_; + sp_jmatrix_t &jmatrix_; + sp_well_t &well_; + const sp_well_controller_t &well_controller_; + const main_var_array_t &main_vars; + const item_array_t &pressure; + const item_array_t &gas_oil_ratio; + item_t gravity; + index_t n_block; + item_t perf_bhp; + item_t diff_depth; + item_t depth; + item_t rho; + main_var_type main_var; + const data_array_t &data_array; + const phase_d_t &phase_d; + index_t n_phases; + bool is_o; + bool is_w; + bool is_g; + array_ext bw_value; + array_ext ww_value; + rate_data_t &rate; + const rate_data_t &limit_rate; + inj_params inj_params_; + prod_params prod_params_; + bool is_prod; + + item_t Po; + item_t Pw; + item_t Pg; + item_t gw; + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_WELLS_WELL_RATE_COMPUTE_PARAMS_H_ + diff --git a/bs_bos_core/include/well_rate_compute_potentials.h b/bs_bos_core/include/well_rate_compute_potentials.h new file mode 100644 index 0000000..87ea932 --- /dev/null +++ b/bs_bos_core/include/well_rate_compute_potentials.h @@ -0,0 +1,55 @@ +/** + * \file well_rate_compute_potentials.h + * \brief compute perforation potential for well derivs computation + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_COMPUTE_POTENTIALS_H_ +#define BS_WELLS_WELL_RATE_CONTROL_COMPUTE_POTENTIALS_H_ + +namespace blue_sky +{ + + template + inline void + compute_potentials (const data_t &data, params_t ¶ms) + { + typedef typename params_t::item_t item_t; + + const item_t &bhp = params.perf_bhp; + const item_t &po = params.pressure[params.n_block]; + + //const item_t &ro = params.rho; + //const item_t &g = params.gravity; + //const item_t &h = params.diff_depth; + + params.Po = bhp /*+ (ro * g * h)*/ - po; + params.Pw = params.Po; + params.Pg = params.Po; + + if (params.is_w) + params.Pw -= CAP_PRESSURE (data, params.phase_d, FI_PHASE_WATER); + + if (params.is_g) + params.Pg -= CAP_PRESSURE (data, params.phase_d, FI_PHASE_GAS); + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%d]: bhp: %.10e, rho: %.10e, h: %.10e, pref: %.10e") % params.n_block % bhp % ro % h % po << bs_end; + BOSOUT (section::wells, level::debug) << boost::format ("[%d]: bhp: %.10e, pref: %.10e") % params.n_block % bhp % po << bs_end; + BOSOUT (section::wells, level::debug) << boost::format ("[%d]: pw: %.10e pg: %.10e po: %.10e") % params.n_block % params.Pw % params.Pg % params.Po << bs_end; +#endif + } + + template + inline bool + is_prod_potential (const params_t ¶ms) + { + return params.Po < typename params_t::item_t (0.0); + } + +} // namespace blue_sky + + + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_COMPUTE_POTENTIALS_H_ + diff --git a/bs_bos_core/include/well_rate_connection_loop.h b/bs_bos_core/include/well_rate_connection_loop.h new file mode 100644 index 0000000..7fb19be --- /dev/null +++ b/bs_bos_core/include/well_rate_connection_loop.h @@ -0,0 +1,132 @@ +/** + * \file well_rate_connection_loop.h + * \brief loop through connection for well derivs computations + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_CONNECTION_LOOP_H_ +#define BS_WELLS_WELL_RATE_CONTROL_CONNECTION_LOOP_H_ + +namespace blue_sky + { + + template + inline void + connection_loop (params_t ¶ms, const inj_inner_loop_t &inj_inner_loop, const prod_inner_loop_t &prod_inner_loop) + { + BS_ASSERT (!params.well_->is_shut ()) (params.well_->name ()); + if (!params.well_->get_connections_count ()) + { + BOSOUT (section::wells, level::debug) + << "[" << params.well_->name () << "] connection loop: connection list is empty" + << bs_end; + + return ; + } + + typedef typename params_t::sp_connection_t sp_connection_t; + typedef typename params_t::data_t data_t; + + params.depth = params.well_->get_connection (0)->connection_depth; + for (size_t i = 0, cnt = params.well_->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (params.well_->get_connection (i)); + if (c->is_shut ()) + { + params.depth = c->connection_depth; + continue; + } + + params.n_block = c->n_block (); + params.perf_bhp = c->cur_bhp; + params.diff_depth = c->connection_depth - params.depth; + params.depth = c->connection_depth; + params.rho = c->density; + params.gw = c->get_fact (); + params.main_var = params.main_vars[params.n_block]; + const data_t &data = params.data_array[params.n_block]; + + // + compute_potentials (data, params); + + // TODO: check crossflow + //if (params.is_prod) + if (is_prod_potential (params)) + { + prod_inner_loop (c, data, params); + } + else + { + params.compute_perf_vars (data, params.inj_params_); + inj_inner_loop (c, data, params); + } + } + } + + template + inline void + update_wr_connection_loop (params_t ¶ms, const inner_loop_t &inner_loop) + { + BS_ASSERT (!params.well_->is_shut ()) (params.well_->name ()); + if (!params.well_->get_connections_count ()) + { + BOSOUT (section::wells, level::debug) + << "[" << params.well_->name () << "] connection loop: connection list is empty" + << bs_end; + + return ; + } + + typedef typename params_t::sp_connection_t sp_connection_t; + typedef typename params_t::item_t item_t; + + //item_t ww = 1.0 / params.ww_value[0]; + item_t ww = params.ww_value[0]; + if (fabs (ww) >= 10e-16) + { + ww = 1.0 / ww; + } + + for (size_t i = 0, cnt = params.well_->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (params.well_->get_connection (i)); + if (c->is_shut ()) + continue; + + inner_loop (c, ww); + } + } + + template + inline void + apply_wefac_connection_loop (params_t ¶ms, const inner_loop_t &inner_loop) + { + BS_ASSERT (!params.well_->is_shut ()) (params.well_->name ()); + if (!params.well_->get_connections_count ()) + { + BOSOUT (section::wells, level::debug) + << "[" << params.well_->name () << "] connection loop: connection list is empty" + << bs_end; + + return ; + } + + typedef typename params_t::sp_connection_t sp_connection_t; + typedef typename params_t::item_t item_t; + + for (size_t i = 0, cnt = params.well_->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (params.well_->get_connection (i)); + if (c->is_shut ()) + continue; + + inner_loop (c, params); + } + + } + +} // namespace blue_sky + + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_CONNECTION_LOOP_H_ + diff --git a/bs_bos_core/include/well_rate_control.h b/bs_bos_core/include/well_rate_control.h new file mode 100644 index 0000000..3ec5061 --- /dev/null +++ b/bs_bos_core/include/well_rate_control.h @@ -0,0 +1,110 @@ +/** + * \file well_rate_control.h + * \brief well control impl + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_H_ +#define BS_WELLS_WELL_RATE_CONTROL_H_ + +#include "well_rate_control_interface.h" +#include "rate_control_type.h" + +namespace blue_sky + { + namespace wells + { + + template + class well_rate_control_interface; + + template + class BS_API_PLUGIN well_rate_control : public objbase + { + public: + typedef strategy_t strategy_type; + typedef well_rate_control this_t; + + typedef typename strategy_t::index_t index_t; + + typedef calc_model calc_model_t; + typedef jacobian_matrix jmatrix_t; + typedef well well_t; + typedef well_controller well_controller_t; + typedef well_rate_control_interface well_rate_control_impl_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_jmatrix_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_well_controller_t; + + typedef smart_ptr sp_well_rate_control_impl_t; + + public: + + bool + is_bhp () const + { + return is_bhp_; + } + bool + is_production () const + { + return is_prod_; + } + bool + is_rate () const + { + return !is_bhp_; + } + rate_control_type + get_control_type () const + { + return control_type_; + } + + void + set_is_bhp (bool f) + { + is_bhp_ = f; + } + void + set_is_prod (bool f) + { + is_prod_ = f; + } + void + set_control_type (rate_control_type control_type) + { + control_type_ = control_type; + } + void + set_impl (const sp_well_rate_control_impl_t &impl) + { + impl_ = impl; + } + void + compute_rate (const sp_calc_model_t &calc_model, sp_jmatrix_t &jmatrix, sp_well_t &well, const sp_well_controller_t &well_controller) const + { + impl_->compute_rate (calc_model, jmatrix, well, well_controller); + } + void + compute_derivs (const sp_calc_model_t &calc_model, sp_jmatrix_t &jmatrix, sp_well_t &well, const sp_well_controller_t &well_controller) const + { + impl_->compute_derivs (calc_model, jmatrix, well, well_controller); + } + + BLUE_SKY_TYPE_DECL_T (well_rate_control); + + private: + bool is_bhp_; + bool is_prod_; + auto_value control_type_; + sp_well_rate_control_impl_t impl_; + }; + + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_H_ + diff --git a/bs_bos_core/include/well_rate_control_bhp_deriv.h b/bs_bos_core/include/well_rate_control_bhp_deriv.h new file mode 100644 index 0000000..0bda72f --- /dev/null +++ b/bs_bos_core/include/well_rate_control_bhp_deriv.h @@ -0,0 +1,519 @@ +/** + * \file well_rate_control_bhp_deriv.h + * \brief compute well derivs for 3phase model + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_BHP_DERIV_H_ +#define BS_WELLS_WELL_RATE_CONTROL_BHP_DERIV_H_ + +#include "well_rate_control_deriv.h" +#include "well_rate_control_compute_deriv_typedef.h" + +namespace blue_sky + { + namespace wells + { + + template + struct compute_bhp_deriv_3p : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_bhp_deriv_3p (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + array_ext ps_block = c->get_ps_value (); + + ps_block [p3_oil] = base_t::compute_oil_sw_deriv (data, params); + rr_block [p3_oil_po] = base_t::compute_oil_po_deriv (data, params); + rr_block [p3_oil_so] = base_t::compute_oil_so_deriv (data, params); + rr_block [p3_oil_sg] = base_t::compute_oil_sg_deriv (data, params); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_water_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + array_ext ps_block = c->get_ps_value (); + + ps_block [p3_wat] = base_t::compute_water_sw_deriv (data, params); + rr_block [p3_wat_po] = base_t::compute_water_po_deriv (data, params); + rr_block [p3_wat_so] = base_t::compute_water_so_deriv (data, params); + rr_block [p3_wat_sg] = base_t::compute_water_sg_deriv (data, params); + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_gas_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + array_ext ps_block = c->get_ps_value (); + + ps_block [p3_gas] = base_t::compute_gas_sw_deriv (data, params); + rr_block [p3_gas_po] = base_t::compute_gas_po_deriv (data, params); + rr_block [p3_gas_so] = base_t::compute_gas_so_deriv (data, params); + rr_block [p3_gas_sg] = base_t::compute_gas_sg_deriv (data, params); + } + } + + void + update_rr (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + array_ext ps = c->get_ps_value (); + const rhs_item_t *sp = ¶ms.jmatrix_->get_sp_diagonal ()[params.n_block * params.n_phases]; + + M_MINUS_VV_PROD_3x3 (ps, sp, rr); + } + void + update_rhs_flux (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext ps = c->get_ps_value (); + const rhs_item_t *s_rhs_block = ¶ms.jmatrix_->get_sec_rhs ()[params.calc_model_->n_sec_vars * params.n_block]; + array_ext r_rhs_block = c->get_rate_value (); + + V_MINUS_VS_PROD_3x3 (ps, s_rhs_block, r_rhs_block); + } + + void + compute_bw_value (params_t ¶ms) const + { + params.bw_value[0] = 0; + + if (mobility_calc_t::is_o_ctrl (params) && mobility_calc_t::is_w_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += (params.rate.prod.oil + params.rate.prod.water) - this->mult * params.limit_rate.prod.liquid; + else + params.bw_value[0] += (params.rate.inj.oil + params.rate.inj.water) - this->mult * params.limit_rate.inj.liquid; + } + else + { + if (mobility_calc_t::is_o_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += params.rate.prod.oil - this->mult * params.limit_rate.prod.oil; + else + params.bw_value[0] += params.rate.inj.oil - this->mult * params.limit_rate.inj.oil; + } + + if (mobility_calc_t::is_w_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += params.rate.prod.water - this->mult * params.limit_rate.prod.water; + else + params.bw_value[0] += params.rate.inj.water - this->mult * params.limit_rate.inj.water; + } + + if (mobility_calc_t::is_g_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += params.rate.prod.gas - this->mult * params.limit_rate.prod.gas; + else + params.bw_value[0] += params.rate.inj.gas - this->mult * params.limit_rate.inj.gas; + } + } + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + item_t wefac = params.well_->exploitation_factor_; + + rr[0] = blue_sky::apply_wefac (rr[0], wefac); + rr[1] = blue_sky::apply_wefac (rr[1], wefac); + rr[2] = blue_sky::apply_wefac (rr[2], wefac); + rr[3] = blue_sky::apply_wefac (rr[3], wefac); + rr[4] = blue_sky::apply_wefac (rr[4], wefac); + rr[5] = blue_sky::apply_wefac (rr[5], wefac); + rr[6] = blue_sky::apply_wefac (rr[6], wefac); + rr[7] = blue_sky::apply_wefac (rr[7], wefac); + rr[8] = blue_sky::apply_wefac (rr[8], wefac); + } + }; + + template + struct compute_bhp_deriv_2p_ow : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_bhp_deriv_2p_ow (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + array_ext ps_block = c->get_ps_value (); + + ps_block [p2ow_oil] = base_t::compute_oil_sw_deriv (data, params); + rr_block [p2ow_oil_po] = base_t::compute_oil_po_deriv (data, params); + rr_block [p2ow_oil_so] = base_t::compute_oil_so_deriv (data, params); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_water_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + array_ext ps_block = c->get_ps_value (); + + ps_block [p2ow_wat] = base_t::compute_water_sw_deriv (data, params); + rr_block [p2ow_wat_po] = base_t::compute_water_po_deriv (data, params); + rr_block [p2ow_wat_so] = base_t::compute_water_so_deriv (data, params); + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + + void + update_rr (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + array_ext ps = c->get_ps_value (); + const rhs_item_t *sp = ¶ms.jmatrix_->get_sp_diagonal ()[params.n_block * params.n_phases]; + + M_MINUS_VV_PROD_2x2 (ps, sp, rr); + } + void + update_rhs_flux (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext ps = c->get_ps_value (); + const rhs_item_t *s_rhs_block = ¶ms.jmatrix_->get_sec_rhs ()[params.calc_model_->n_sec_vars * params.n_block]; + array_ext r_rhs_block = c->get_rate_value (); + + V_MINUS_VS_PROD_2x2 (ps, s_rhs_block, r_rhs_block); + } + void + compute_bw_value (params_t ¶ms) const + { + params.bw_value[0] = 0; + + if (mobility_calc_t::is_o_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += params.rate.prod.oil - this->mult * params.limit_rate.prod.oil; + else + params.bw_value[0] += params.rate.inj.oil - this->mult * params.limit_rate.inj.oil; + } + + if (mobility_calc_t::is_w_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += params.rate.prod.water - this->mult * params.limit_rate.prod.water; + else + params.bw_value[0] += params.rate.inj.water - this->mult * params.limit_rate.inj.water; + } + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + item_t wefac = params.well_->exploitation_factor_; + + rr[0] = blue_sky::apply_wefac (rr[0], wefac); + rr[1] = blue_sky::apply_wefac (rr[1], wefac); + rr[2] = blue_sky::apply_wefac (rr[2], wefac); + rr[3] = blue_sky::apply_wefac (rr[3], wefac); + } + }; + + template + struct compute_bhp_deriv_2p_og : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_bhp_deriv_2p_og (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + array_ext ps_block = c->get_ps_value (); + + ps_block [p2og_oil] = base_t::compute_oil_so_deriv (data, params); + rr_block [p2og_oil_po] = base_t::compute_oil_po_deriv (data, params); + rr_block [p2og_oil_sg] = base_t::compute_oil_sg_deriv (data, params); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_gas_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + array_ext ps_block = c->get_ps_value (); + + ps_block [p2og_gas] = base_t::compute_gas_so_deriv (data, params); + rr_block [p2og_gas_po] = base_t::compute_gas_po_deriv (data, params); + rr_block [p2og_gas_sg] = base_t::compute_gas_sg_deriv (data, params); + } + } + + void + update_rr (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + array_ext ps = c->get_ps_value (); + const rhs_item_t *sp = ¶ms.jmatrix_->get_sp_diagonal ()[params.n_block * params.n_phases]; + + M_MINUS_VV_PROD_2x2 (ps, sp, rr); + } + void + update_rhs_flux (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext ps = c->get_ps_value (); + const rhs_item_t *s_rhs_block = ¶ms.jmatrix_->get_sec_rhs ()[params.calc_model_->n_sec_vars * params.n_block]; + array_ext r_rhs_block = c->get_rate_value (); + + V_MINUS_VS_PROD_2x2 (ps, s_rhs_block, r_rhs_block); + } + void + compute_bw_value (params_t ¶ms) const + { + params.bw_value[0] = 0; + + if (mobility_calc_t::is_o_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += params.rate.prod.oil - this->mult * params.limit_rate.prod.oil; + else + params.bw_value[0] += params.rate.inj.oil - this->mult * params.limit_rate.inj.oil; + } + + if (mobility_calc_t::is_g_ctrl (params)) + { + if (params.is_prod) + params.bw_value[0] += params.rate.prod.gas - this->mult * params.limit_rate.prod.gas; + else + params.bw_value[0] += params.rate.inj.gas - this->mult * params.limit_rate.inj.gas; + } + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + item_t wefac = params.well_->exploitation_factor_; + + rr[0] = blue_sky::apply_wefac (rr[0], wefac); + rr[1] = blue_sky::apply_wefac (rr[1], wefac); + rr[2] = blue_sky::apply_wefac (rr[2], wefac); + rr[3] = blue_sky::apply_wefac (rr[3], wefac); + } + }; + + template + struct compute_bhp_deriv_1p_o : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_bhp_deriv_1p_o (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + rr_block [0] = base_t::compute_oil_po_deriv (data, params); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + + void + update_rr (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_rhs_flux (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext ps = c->get_ps_value (); + const rhs_item_t *s_rhs_block = ¶ms.jmatrix_->get_sec_rhs ()[params.calc_model_->n_sec_vars * params.n_block]; + array_ext r_rhs_block = c->get_rate_value (); + + V_MINUS_VS_PROD_1x1 (ps, s_rhs_block, r_rhs_block); + } + void + compute_bw_value (params_t ¶ms) const + { + BS_ASSERT (mobility_calc_t::is_o_ctrl (params)); + + if (params.is_prod) + params.bw_value[0] += params.rate.prod.oil - this->mult * params.limit_rate.prod.oil; + else + params.bw_value[0] += params.rate.inj.oil - this->mult * params.limit_rate.inj.oil; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + item_t wefac = params.well_->exploitation_factor_; + + rr[0] = blue_sky::apply_wefac (rr[0], wefac); + } + }; + template + struct compute_bhp_deriv_1p_w : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_bhp_deriv_1p_w (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_water_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + rr_block [0] = base_t::compute_water_po_deriv (data, params); + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + + void + update_rr (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_rhs_flux (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext ps = c->get_ps_value (); + const rhs_item_t *s_rhs_block = ¶ms.jmatrix_->get_sec_rhs ()[params.calc_model_->n_sec_vars * params.n_block]; + array_ext r_rhs_block = c->get_rate_value (); + + V_MINUS_VS_PROD_1x1 (ps, s_rhs_block, r_rhs_block); + } + void + compute_bw_value (params_t ¶ms) const + { + BS_ASSERT (mobility_calc_t::is_w_ctrl (params)); + + if (params.is_prod) + params.bw_value[0] += params.rate.prod.water - this->mult * params.limit_rate.prod.water; + else + params.bw_value[0] += params.rate.inj.water - this->mult * params.limit_rate.inj.water; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + item_t wefac = params.well_->exploitation_factor_; + + rr[0] = blue_sky::apply_wefac (rr[0], wefac); + } + }; + template + struct compute_bhp_deriv_1p_g : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_bhp_deriv_1p_g (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_gas_injection (params)) + { + array_ext rr_block = c->get_rr_value (); + rr_block [0] = base_t::compute_gas_po_deriv (data, params); + } + } + + void + update_rr (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_rhs_flux (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext ps = c->get_ps_value (); + const rhs_item_t *s_rhs_block = ¶ms.jmatrix_->get_sec_rhs ()[params.calc_model_->n_sec_vars * params.n_block]; + array_ext r_rhs_block = c->get_rate_value (); + + V_MINUS_VS_PROD_1x1 (ps, s_rhs_block, r_rhs_block); + } + void + compute_bw_value (params_t ¶ms) const + { + BS_ASSERT (mobility_calc_t::is_g_ctrl (params)); + + if (params.is_prod) + params.bw_value[0] += params.rate.prod.gas - this->mult * params.limit_rate.prod.gas; + else + params.bw_value[0] += params.rate.inj.gas - this->mult * params.limit_rate.inj.gas; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rr = c->get_rr_value (); + item_t wefac = params.well_->exploitation_factor_; + + rr[0] = blue_sky::apply_wefac (rr[0], wefac); + } + }; + + } // namespace wells +} // namespace blue_sky + + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_BHP_DERIV_H_ + diff --git a/bs_bos_core/include/well_rate_control_compute_deriv_typedef.h b/bs_bos_core/include/well_rate_control_compute_deriv_typedef.h new file mode 100644 index 0000000..936bb86 --- /dev/null +++ b/bs_bos_core/include/well_rate_control_compute_deriv_typedef.h @@ -0,0 +1,27 @@ +/** + * \file well_rate_control_deriv_typedef.h + * \brief + * \author Sergey Miryanov + * \date 24.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_DERIV_TYPEDEF_H_ +#define BS_WELLS_WELL_RATE_CONTROL_DERIV_TYPEDEF_H_ + +#define GET_COMPUTE_DERIV_BASE_TYPES \ + typedef compute_deriv base_t; \ + typedef typename base_t::data_t data_t; \ + typedef typename base_t::params_t params_t; \ + typedef typename base_t::item_t item_t; \ + typedef typename base_t::rhs_item_t rhs_item_t; \ + typedef typename base_t::item_q_rate_t item_q_rate_t; \ + typedef typename base_t::item_rhs_block_t item_rhs_block_t; \ + typedef typename base_t::item_rr_block_t item_rr_block_t; \ + typedef typename base_t::item_rw_block_t item_rw_block_t; \ + typedef typename base_t::item_wr_block_t item_wr_block_t; \ + typedef typename base_t::item_ps_block_t item_ps_block_t; \ + typedef typename base_t::sp_connection_t sp_connection_t; + + + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_DERIV_TYPEDEF_H_ + diff --git a/bs_bos_core/include/well_rate_control_deriv.h b/bs_bos_core/include/well_rate_control_deriv.h new file mode 100644 index 0000000..814a4bd --- /dev/null +++ b/bs_bos_core/include/well_rate_control_deriv.h @@ -0,0 +1,359 @@ +/** + * \file well_rate_control_deriv.h + * \brief + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_DERIV_H_ +#define BS_WELLS_WELL_RATE_CONTROL_DERIV_H_ + +#include "apply_wefac.h" + +namespace blue_sky + { + namespace wells + { + + template + struct compute_deriv + { + typedef typename mobility_calc_t::strategy_t strategy_t; + typedef mobility_calc_t mobility_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::rhs_item_t rhs_item_t; + typedef calc_model calc_model_t; + typedef well well_t; + typedef typename calc_model_t::data_t data_t; + typedef typename mobility_calc_t::params_t params_t; + typedef typename wells::type_helper type_helper_t; + typedef typename type_helper_t::item_rr_block_t item_rr_block_t; + typedef typename type_helper_t::item_rw_block_t item_rw_block_t; + typedef typename type_helper_t::item_wr_block_t item_wr_block_t; + typedef typename type_helper_t::item_q_rate_t item_q_rate_t; + typedef typename type_helper_t::item_rhs_block_t item_rhs_block_t; + typedef typename type_helper_t::item_ps_block_t item_ps_block_t; + + typedef typename well_t::sp_connection_t sp_connection_t; + +protected: + + compute_deriv (const mobility_calc_t &mobility_calc) + : mobility_calc_ (mobility_calc) + , mult (mobility_calc_t::mult) + { + } + + BS_FORCE_INLINE item_t + compute_oil_rate (const data_t &data, params_t ¶ms) const + { + const item_t &mo = mobility_calc_.get_oil_mobility (data, params); + const item_t &Po = params.Po; + const item_t &gw = params.gw; + +#ifdef _DEBUG + BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] qo (%.20e) gw: %.20e mo: %.20e po: %.20e") % params.well_->name ().c_str () % params.n_block % (gw * mo * Po) % gw % mo % Po << bs_end; +#endif + + item_t rate = gw * mo * Po; + return rate; + } + BS_FORCE_INLINE item_t + compute_oil_po_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmo_dpo = mobility_calc_.get_mo_po_deriv (data, params); + const item_t &mo = mobility_calc_.get_oil_mobility (data, params); + item_t gw = params.gw; + item_t Po = params.Po; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] oil_po: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * (dmo_dpo * Po - mo)) << bs_end; +#endif + + item_t po_deriv = -gw * (dmo_dpo * Po - mo); + return po_deriv; + } + + BS_FORCE_INLINE item_t + compute_oil_sw_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmo_dsw = mobility_calc_.get_mo_sw_deriv (data, params); + item_t gw = params.gw; + item_t Po = params.Po; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] oil_sw: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * dmo_dsw * Po) << bs_end; +#endif + + item_t sw_deriv = -gw * dmo_dsw * Po; + return sw_deriv; + } + BS_FORCE_INLINE item_t + compute_oil_so_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmo_dso = mobility_calc_.get_mo_so_deriv (data, params); + item_t gw = params.gw; + item_t Po = params.Po; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] oil_so: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * dmo_dso * Po) << bs_end; +#endif + + item_t so_deriv = -gw * dmo_dso * Po; + return so_deriv; + } + BS_FORCE_INLINE item_t + compute_oil_sg_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmo_dsg = mobility_calc_.get_mo_sg_deriv (data, params); + item_t gw = params.gw; + item_t Po = params.Po; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] oil_sg: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * dmo_dsg * Po) << bs_end; +#endif + + item_t sg_deriv = -gw * dmo_dsg * Po; + return sg_deriv; + } + BS_FORCE_INLINE item_t + compute_oil_pref_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &mo = mobility_calc_.get_oil_mobility (data, params); + const item_t &gw = params.gw; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] oil_pref: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * mo) << bs_end; +#endif + + item_t pref_deriv = -gw * mo; + return pref_deriv; + } + + BS_FORCE_INLINE item_t + compute_water_rate (const data_t &data, params_t ¶ms) const + { + const item_t &mw = mobility_calc_.get_water_mobility (data, params); + const item_t &Pw = params.Pw; + const item_t &gw = params.gw; + +#ifdef _DEBUG + BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] qw (%.20e) gw: %.20e mw: %.20e pw: %.20e") % params.well_->name ().c_str () % params.n_block % (gw * mw * Pw) % gw % mw % Pw << bs_end; +#endif + + item_t rate = gw * mw * Pw; + return rate; + } + BS_FORCE_INLINE item_t + compute_water_po_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmw_dpo = mobility_calc_.get_mw_po_deriv (data, params); + const item_t &mw = mobility_calc_.get_water_mobility (data, params); + item_t Pw = params.Pw; + item_t gw = params.gw; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] wat_po: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * (dmw_dpo * Pw - mw)) << bs_end; +#endif + + item_t po_deriv = -gw * (dmw_dpo * Pw - mw); + return po_deriv; + } + BS_FORCE_INLINE item_t + compute_water_sw_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmw_dsw = mobility_calc_.get_mw_sw_deriv (data, params); + const item_t &mw = mobility_calc_.get_water_mobility (data, params); + item_t gw = params.gw; + item_t Pw = params.Pw; + item_t dpcwo_dsw = S_DERIV_CAP_PRESSURE (data, params.phase_d, FI_PHASE_WATER); + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] wat_sw: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * (dmw_dsw * Pw - mw * dpcwo_dsw)) << bs_end; +#endif + + item_t sw_deriv = -gw * (dmw_dsw * Pw - mw * dpcwo_dsw); + return sw_deriv; + } + BS_FORCE_INLINE item_t + compute_water_so_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmw_dso = mobility_calc_.get_mw_so_deriv (data, params); + item_t gw = params.gw; + item_t Pw = params.Pw; + +#ifdef _DEBUG + //BOSOUT (section::wells, leve::debug) << boost::format ("[%s : %d] wat_so: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * dmw_dso * Pw) << bs_end; +#endif + + item_t so_deriv = -gw * dmw_dso * Pw; + return so_deriv; + } + BS_FORCE_INLINE item_t + compute_water_sg_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmw_dsg = mobility_calc_.get_mw_sg_deriv (data, params); + item_t gw = params.gw; + item_t Pw = params.Pw; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] wat_sg: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * dmw_dsg * Pw) << bs_end; +#endif + + item_t sg_deriv = -gw * dmw_dsg * Pw; + return sg_deriv; + } + BS_FORCE_INLINE item_t + compute_water_pref_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &mw = mobility_calc_.get_water_mobility (data, params); + const item_t &gw = params.gw; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] wat_pref: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * mw) << bs_end; +#endif + + item_t pref_deriv = -gw * mw; + return pref_deriv; + } + + BS_FORCE_INLINE item_t + compute_gas_rate (const data_t &data, params_t ¶ms) const + { + return mobility_calc_.get_gas_rate (data, params); + } + + BS_FORCE_INLINE item_t + compute_free_gas_rate (const data_t &data, params_t ¶ms) const + { + return mobility_calc_.get_free_gas_rate (data, params); + } + + BS_FORCE_INLINE item_t + compute_solution_gas_rate (const data_t &data, params_t ¶ms) const + { + return mobility_calc_.get_solution_gas_rate (data, params); + } + + BS_FORCE_INLINE item_t + compute_gas_po_deriv (const data_t &data, params_t ¶ms) const + { +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] gas_po: %.20e") % params.well_->name ().c_str () % params.n_block % mobility_calc_.get_gas_po_deriv (data, params) << bs_end; +#endif + + return mobility_calc_.get_gas_po_deriv (data, params); + } + BS_FORCE_INLINE item_t + compute_gas_sw_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmg_dsw = mobility_calc_.get_gas_sw_deriv (data, params);//get_mg_sw_deriv (data, params); + + item_t gw = params.gw; + //item_t Pg = params.Pg; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] gas_sw: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * dmg_dsw * Pg) << bs_end; +#endif + + item_t sw_deriv = -gw * dmg_dsw;// * Pg; + return sw_deriv; + } + BS_FORCE_INLINE item_t + compute_gas_so_deriv (const data_t &data, params_t ¶ms) const + { + const item_t &dmg_dso = mobility_calc_.get_gas_so_deriv (data, params);//get_mg_so_deriv (data, params); + item_t gw = params.gw; + //item_t Pg = params.Pg; + +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] gas_so: %.20e") % params.well_->name ().c_str () % params.n_block % (-gw * dmg_dso * Pg) << bs_end; +#endif + + item_t so_deriv = -gw * dmg_dso;// * Pg; + return so_deriv; + } + BS_FORCE_INLINE item_t + compute_gas_sg_deriv (const data_t &data, params_t ¶ms) const + { +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] gas_sg: %.20e") % params.well_->name ().c_str () % params.n_block % mobility_calc_.get_gas_sg_deriv (data, params) << bs_end; +#endif + + return mobility_calc_.get_gas_sg_deriv (data, params); + } + BS_FORCE_INLINE item_t + compute_gas_pref_deriv (const data_t &data, params_t ¶ms) const + { +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] gas_pref: %.20e") % params.well_->name ().c_str () % params.n_block % mobility_calc_.get_gas_pref_deriv (data, params) << bs_end; +#endif + + return mobility_calc_.get_gas_pref_deriv (data, params); + } + + const mobility_calc_t &mobility_calc_; + item_t mult; + }; + + template + struct dummy_deriv + { + typedef typename mobility_calc_t::strategy_t strategy_t; + typedef mobility_calc_t mobility_t; + typedef typename strategy_t::item_t item_t; + typedef calc_model calc_model_t; + typedef typename calc_model_t::data_t data_t; + typedef typename mobility_calc_t::params_t params_t; + typedef well well_t; + + typedef typename well_t::sp_connection_t sp_connection_t; + +public: + + dummy_deriv (const mobility_calc_t &) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_wr (const sp_connection_t &c, item_t ww) const + { + } + void + update_rr (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_rhs_flux (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + compute_bw_value (params_t ¶ms) const + { + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + } + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + } + }; + + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_DERIV_H_ + diff --git a/bs_bos_core/include/well_rate_control_impl.h b/bs_bos_core/include/well_rate_control_impl.h new file mode 100644 index 0000000..f7c94bb --- /dev/null +++ b/bs_bos_core/include/well_rate_control_impl.h @@ -0,0 +1,185 @@ +/** + * \file well_rate_control_impl.h + * \brief hidden impl of well_rate_control (pImpl idiome) + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_IMPL_H_ +#define BS_WELLS_WELL_RATE_CONTROL_IMPL_H_ + +#include "well_rate_control_interface.h" +#include "well_rate_compute_potentials.h" +#include "well_rate_call_proxy.h" +#include "well_rate_connection_loop.h" + +#include "well_rate_compute_params.h" + +namespace blue_sky + { + + template + class BS_API_PLUGIN well_rate_control_impl : public wells::well_rate_control_interface + { + public: + + template + struct impl; + + typedef typename impl_type_t::strategy_t strategy_t; + typedef impl inj_impl_t; + typedef impl prod_impl_t; + + typedef well_rate_control_impl this_t; + typedef wells::well_rate_control_interface base_t; + + typedef typename base_t::calc_model_t calc_model_t; + typedef typename calc_model_t::data_t data_t; + typedef compute_params compute_params_t; + + typedef typename base_t::sp_calc_model_t sp_calc_model_t; + typedef typename base_t::sp_jmatrix_t sp_jmatrix_t; + typedef typename base_t::sp_well_t sp_well_t; + typedef typename base_t::sp_well_controller_t sp_well_controller_t; + + typedef typename base_t::sp_connection_t sp_connection_t; + + typedef typename base_t::item_t item_t; + typedef typename base_t::index_t index_t; + + void + compute_rate (const sp_calc_model_t &calc_model, sp_jmatrix_t &jmatrix, sp_well_t &well, const sp_well_controller_t &well_controller) const + { + compute_params_t params (calc_model, jmatrix, well, well_controller); + connection_loop (params, + one_call (&inj_impl_, &inj_impl_t::compute_rate), + one_call (&prod_impl_, &prod_impl_t::compute_rate)); + + compute_bw_value (params); + if (params.well_->is_shut () || params.well_->exploitation_factor_ <= 0.0) + { + if (params.is_prod) + { + apply_wefac_connection_loop (params, one_call (&prod_impl_, &prod_impl_t::apply_wefac)); + } + else + { + apply_wefac_connection_loop (params, one_call (&inj_impl_, &inj_impl_t::apply_wefac)); + } + } + } + void + compute_derivs (const sp_calc_model_t &calc_model, sp_jmatrix_t &jmatrix, sp_well_t &well, const sp_well_controller_t &well_controller) const + { + compute_params_t params (calc_model, jmatrix, well, well_controller); + connection_loop (params, + two_call (&inj_impl_, &inj_impl_t::compute_bhp_derivs, &inj_impl_t::compute_rate_derivs), + two_call (&prod_impl_, &prod_impl_t::compute_bhp_derivs, &prod_impl_t::compute_rate_derivs)); + + if (params.is_prod) + { + update_wr_connection_loop (params, one_call (&prod_impl_, &prod_impl_t::update_wr)); + apply_wefac_connection_loop (params, one_call (&prod_impl_, &prod_impl_t::apply_wefac)); + apply_wefac_connection_loop (params, one_call (&prod_impl_, &prod_impl_t::update_rate)); + } + else + { + update_wr_connection_loop (params, one_call (&inj_impl_, &inj_impl_t::update_wr)); + apply_wefac_connection_loop (params, one_call (&inj_impl_, &inj_impl_t::apply_wefac)); + apply_wefac_connection_loop (params, one_call (&inj_impl_, &inj_impl_t::update_rate)); + } + } + + BLUE_SKY_TYPE_DECL_T (well_rate_control_impl); + + public: + + template + struct impl + { + typedef typename impl_t::mobility_t mobility_t; + typedef typename impl_t::rate_t rate_t; + typedef typename impl_t::bhp_deriv_t bhp_deriv_t; + typedef typename impl_t::rate_deriv_t rate_deriv_t; + typedef compute_params_t params_t; + + impl () + : rate_ (mobility_) + , bhp_deriv_ (mobility_) + , rate_deriv_ (mobility_) + { + + } + + void + compute_rate (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + rate_.oil_function (c, data, params); + rate_.water_function (c, data, params); + rate_.gas_function (c, data, params); + } + + void + compute_bhp_derivs (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + bhp_deriv_.oil_function (c, data, params); + bhp_deriv_.water_function (c, data, params); + bhp_deriv_.gas_function (c, data, params); + + bhp_deriv_.update_rr (c, data, params); + bhp_deriv_.update_rhs_flux (c, data, params); + } + void + compute_rate_derivs (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + rate_deriv_.oil_function (c, data, params); + rate_deriv_.water_function (c, data, params); + rate_deriv_.gas_function (c, data, params); + } + + void + update_wr (const sp_connection_t &c, item_t ww) const + { + rate_deriv_.update_wr (c, ww); + } + + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + bhp_deriv_.apply_wefac (c, params); + rate_deriv_.apply_wefac (c, params); + } + + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + rate_deriv_.update_rate (c, params); + } + + mobility_t mobility_; + rate_t rate_; + bhp_deriv_t bhp_deriv_; + rate_deriv_t rate_deriv_; + }; + + private: + + + void + compute_bw_value (compute_params_t ¶ms) const + { + params.is_prod + ? prod_impl_.bhp_deriv_.compute_bw_value (params) + : inj_impl_.bhp_deriv_.compute_bw_value (params) + ; + } + + inj_impl_t inj_impl_; + prod_impl_t prod_impl_; + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_IMPL_H + diff --git a/bs_bos_core/include/well_rate_control_impl_type.h b/bs_bos_core/include/well_rate_control_impl_type.h new file mode 100644 index 0000000..32b0802 --- /dev/null +++ b/bs_bos_core/include/well_rate_control_impl_type.h @@ -0,0 +1,156 @@ +/** + * \file well_rate_control_impl_type.h + * \brief types for parametrization well_rate_control_impl + * \author Sergey Miryanov + * \date 25.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_IMPL_TYPE_H_ +#define BS_WELLS_WELL_RATE_CONTROL_IMPL_TYPE_H_ + +namespace blue_sky +{ + namespace wells + { + template + struct compute_impl + { + typedef typename rate_type::strategy_t strategy_t; + typedef typename rate_type::mobility_t mobility_t; + typedef rate_type rate_t; + typedef bhp_deriv_type bhp_deriv_t; + typedef rate_deriv_type rate_deriv_t; + }; + + template + struct compute_dummy_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , dummy_deriv , dummy_deriv > inj_impl_t; + typedef compute_impl , dummy_deriv , dummy_deriv > prod_impl_t; + }; + + template + struct compute_bhp_3p_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_3p , dummy_deriv > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_3p , dummy_deriv > prod_impl_t; + }; + + template + struct compute_rate_3p_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_3p , compute_rate_deriv_3p > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_3p , compute_rate_deriv_3p > prod_impl_t; + }; + + template + struct compute_bhp_2p_ow_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_2p_ow , dummy_deriv > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_2p_ow , dummy_deriv > prod_impl_t; + }; + + template + struct compute_rate_2p_ow_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_2p_ow , compute_rate_deriv_2p_ow > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_2p_ow , compute_rate_deriv_2p_ow > prod_impl_t; + }; + + template + struct compute_bhp_2p_og_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_2p_og , dummy_deriv > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_2p_og , dummy_deriv > prod_impl_t; + }; + + template + struct compute_rate_2p_og_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_2p_og , compute_rate_deriv_2p_og > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_2p_og , compute_rate_deriv_2p_og > prod_impl_t; + }; + + template + struct compute_bhp_1p_o_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_1p_o , dummy_deriv > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_1p_o , dummy_deriv > prod_impl_t; + }; + + template + struct compute_rate_1p_o_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_1p_o , compute_rate_deriv_1p_o > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_1p_o , compute_rate_deriv_1p_o > prod_impl_t; + }; + template + struct compute_bhp_1p_w_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_1p_w , dummy_deriv > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_1p_w , dummy_deriv > prod_impl_t; + }; + + template + struct compute_rate_1p_w_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_1p_w , compute_rate_deriv_1p_w > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_1p_w , compute_rate_deriv_1p_w > prod_impl_t; + }; + template + struct compute_bhp_1p_g_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_1p_g , dummy_deriv > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_1p_g , dummy_deriv > prod_impl_t; + }; + + template + struct compute_rate_1p_g_type + { + typedef strategy_type strategy_t; + typedef mobility_calc_inj mobility_calc_inj_t; + typedef mobility_calc_prod mobility_calc_prod_t; + typedef compute_impl , compute_bhp_deriv_1p_g , compute_rate_deriv_1p_g > inj_impl_t; + typedef compute_impl , compute_bhp_deriv_1p_g , compute_rate_deriv_1p_g > prod_impl_t; + }; + } // namespace wells +} // namespace blue_sky + + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_TYPE_H_ + diff --git a/bs_bos_core/include/well_rate_control_inj_mobility.h b/bs_bos_core/include/well_rate_control_inj_mobility.h new file mode 100644 index 0000000..04ecbd7 --- /dev/null +++ b/bs_bos_core/include/well_rate_control_inj_mobility.h @@ -0,0 +1,372 @@ +/** + * \file well_rate_control_inj_mobility.h + * \brief mobility computation for injection wells + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_INJ_MOBILITY_H_ +#define BS_WELLS_WELL_RATE_INJ_MOBILITY_H_ + +#include "calc_model.h" +#include "calc_model_data_accessors.h" +#include "well_rate_compute_params.h" + +namespace blue_sky + { + namespace wells + { + + template + struct mobility_calc_inj + { +public: + typedef strategy_type strategy_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef calc_model calc_model_t; + typedef typename calc_model_t::data_t data_t; + typedef jacobian_matrix jmatrix_t; + typedef well well_t; + typedef well_controller well_controller_t; + typedef compute_params params_t; + + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::phase_d_t phase_d_t; + typedef typename calc_model_t::main_var_array_t main_var_array_t; + + typedef typename wells::type_helper type_helper_t; + typedef typename type_helper_t::item_rhs_block_t item_rhs_block_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_jmatrix_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_well_controller_t; + + enum { mult = 1, }; + enum { is_inj = 1, }; + +public: + + BS_FORCE_INLINE item_t + get_mult () const + { + return 1.0; + } + + static BS_FORCE_INLINE bool + is_oil_injection (const params_t ¶ms) + { + return params.inj_params_.is_oil_injection; + } + static BS_FORCE_INLINE bool + is_water_injection (const params_t ¶ms) + { + return params.inj_params_.is_water_injection; + } + static BS_FORCE_INLINE bool + is_gas_injection (const params_t ¶ms) + { + return params.inj_params_.is_gas_injection; + } + static BS_FORCE_INLINE bool + is_o_ctrl (const params_t ¶ms) + { + return params.inj_params_.is_o_ctrl; + } + static BS_FORCE_INLINE bool + is_w_ctrl (const params_t ¶ms) + { + return params.inj_params_.is_w_ctrl; + } + static BS_FORCE_INLINE bool + is_g_ctrl (const params_t ¶ms) + { + return params.inj_params_.is_g_ctrl; + } + + BS_FORCE_INLINE item_t + get_oil_mobility (const data_t &data, const params_t ¶ms) const + { + const item_t &krp_tetap = params.inj_params_.krp_tetap; + const item_t &bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + item_t mo = params.main_var == FI_SG_VAR ? bo * krp_tetap : bo * params.inj_params_.krow_tetaow; + return mo; + } + BS_FORCE_INLINE item_t + get_water_mobility (const data_t &data, const params_t ¶ms) const + { + item_t krp_tetap = params.inj_params_.krp_tetap; + item_t bw = INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + item_t mw = params.main_var == FI_SG_VAR ? bw * krp_tetap : bw * params.inj_params_.krow_tetaow; + return mw; + } + BS_FORCE_INLINE item_t + get_gas_mobility (const data_t &data, const params_t ¶ms) const + { + const item_t &krp_tetap = params.inj_params_.krp_tetap; + //const item_t &kow_tetaow = params.inj_params_.krow_tetaow; + const item_t &bg = INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + item_t mg = params.main_var == FI_SG_VAR ? bg * krp_tetap : bg * params.inj_params_.krow_tetaow; + return mg; + } + + BS_FORCE_INLINE item_t + get_mo_po_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &dbo_dpo = P_DERIV_INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + const item_t &krp_tetap = params.inj_params_.krp_tetap; + const item_t &krp_dtetap_dpp = params.inj_params_.krp_dtetap_dpp; + const item_t &bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + + return dbo_dpo * krp_tetap + bo * krp_dtetap_dpp; + } + + BS_FORCE_INLINE item_t + get_mo_sw_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + const item_t &x = params.inj_params_.dkrow_dsw_tetaow_krw_dtetaw_dsw; + + return bo * x; + } + + BS_FORCE_INLINE item_t + get_mo_so_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &dbo_dso = 0; + const item_t &krp_tetap = params.inj_params_.krp_tetap; + const item_t &bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + const item_t &dkro_dso = S_DERIV_RELATIVE_PERM (data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_OIL); + + return dbo_dso * krp_tetap + bo * dkro_dso; + } + + BS_FORCE_INLINE item_t + get_mo_sg_deriv (const data_t &data, const params_t ¶ms) const + { + if (params.main_var == FI_SG_VAR) + { + return get_mo_sg_deriv_sg_var (data, params); + } + else + { + return get_mo_sg_deriv_ro_var (data, params); + } + } + + BS_FORCE_INLINE item_t + get_mo_sg_deriv_sg_var (const data_t &data, const params_t ¶ms) const + { + item_t bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + item_t x = params.inj_params_.dkrog_dsg_tetaog_krg_dtetag_dsg; + + return bo * x; + } + BS_FORCE_INLINE item_t + get_mo_sg_deriv_ro_var (const data_t &data, const params_t ¶ms) const + { + item_t kro = RELATIVE_PERM (data, params.phase_d, FI_PHASE_OIL); + item_t bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + item_t dtetao_dro = GOR_DERIV_INVERS_VISCOSITY (data); + item_t tetao = INVERS_VISCOSITY (data, params.phase_d, FI_PHASE_OIL); + item_t dbo_dro = GOR_DERIV_INVERS_FVF (data); + + return kro * (bo * dtetao_dro + tetao * dbo_dro); + } + + BS_FORCE_INLINE item_t + get_mw_po_deriv (const data_t &data, const params_t ¶ms) const + { + return (RELATIVE_PERM_O * P_DERIV_INVERS_VISCOSITY_O + + RELATIVE_PERM_W * P_DERIV_INVERS_VISCOSITY_W) - + (INVERS_FVF_W * params.inj_params_.krp_tetap * P_DERIV_INVERS_FVF_W); + + //const item_t &dbw_dpw = P_DERIV_INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + //const item_t &krp_tetap = params.krp_tetap; + //const item_t &krp_dtetap_dpp = params.krp_dtetap_dpp; + //const item_t &bw = INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + + //return (dbw_dpw * krp_tetap + bw * krp_dtetap_dpp); + } + BS_FORCE_INLINE item_t + get_mw_sw_deriv (const data_t &data, const params_t ¶ms) const + { + return (S_DERIV_RELATIVE_PERM_WW * INVERS_VISCOSITY_W + + S_DERIV_RELATIVE_PERM_OW * INVERS_VISCOSITY_O + + RELATIVE_PERM_W * S_DERIV_INVERS_VISCOSITY_W) - + (INVERS_FVF_W * params.inj_params_.krp_tetap * P_DERIV_INVERS_FVF_W); + + //const item_t &dbw_dsw = S_DERIV_INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + //const item_t &krp_tetap = params.krp_tetap; + //const item_t &bw = INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + //const item_t &x = params.dkrow_dsw_tetaow_krw_dtetaw_dsw; + + //return (dbw_dsw * krp_tetap + bw * x); + } + BS_FORCE_INLINE item_t + get_mw_so_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_RELATIVE_PERM_OO * INVERS_VISCOSITY_O; + + //const item_t &bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + //const item_t &dkrw_dso = S_DERIV_RELATIVE_PERM (data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_OIL); + //return bo * dkrw_dso; + } + BS_FORCE_INLINE item_t + get_mw_sg_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &bw = INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + + if (params.main_var == FI_SG_VAR) + { + item_t x = params.inj_params_.dkrog_dsg_tetaog_krg_dtetag_dsg; + return bw * x; + } + else + { + item_t kro = RELATIVE_PERM (data, params.phase_d, FI_PHASE_OIL); + item_t dtetao_dro = GOR_DERIV_INVERS_VISCOSITY (data); + + return bw * kro * dtetao_dro; + } + } + + BS_FORCE_INLINE item_t + get_mg_po_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &dbg_dpg = P_DERIV_INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + const item_t &krp_tetap = params.krp_tetap; + const item_t &krp_dtetap_dpp = params.krp_dtetap_dpp; + const item_t &bg = INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + + return dbg_dpg * krp_tetap + bg * krp_dtetap_dpp; + } + BS_FORCE_INLINE item_t + get_gor_po_deriv (const data_t &data, const params_t ¶ms) const + { + return 0; + } + BS_FORCE_INLINE item_t + get_gor (const data_t &data, const params_t ¶ms) const + { + return 0; + } + + BS_FORCE_INLINE item_t + get_mg_sw_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &bg = INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + const item_t &x = params.inj_params_.dkrow_dsw_tetaow_krw_dtetaw_dsw; + + return bg * x; + } + BS_FORCE_INLINE item_t + get_mg_so_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &bo = INVERS_FVF (data, params.phase_d, FI_PHASE_OIL); + const item_t &dkrg_dso = S_DERIV_RELATIVE_PERM (data, params.phase_d, params.n_phases, FI_PHASE_GAS, FI_PHASE_OIL); + + return bo * dkrg_dso; + } + BS_FORCE_INLINE item_t + get_gas_sw_deriv (const data_t &data, const params_t ¶ms) const + { + return get_mg_sw_deriv (data, params) * params.Pg; + } + BS_FORCE_INLINE item_t + get_gas_so_deriv (const data_t &data, const params_t ¶ms) const + { + return get_mg_so_deriv (data, params) * params.Pg; + } + BS_FORCE_INLINE item_t + get_gas_po_deriv (const data_t &data, const params_t ¶ms) const + { + item_t dbg_dpg = P_DERIV_INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + item_t krp_tetap = params.inj_params_.krp_tetap; + item_t krp_dtetap_dpp = params.inj_params_.krp_dtetap_dpp; + item_t bg = INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + item_t mg = params.main_var == FI_SG_VAR ? bg * krp_tetap : bg * params.inj_params_.krow_tetaow; + item_t Pg = params.Pg; + item_t gw = params.gw; + + item_t po_deriv = -gw * ((dbg_dpg * krp_tetap + bg * krp_dtetap_dpp) * Pg - mg); + return po_deriv; + } + BS_FORCE_INLINE item_t + get_gas_sg_deriv (const data_t &data, const params_t ¶ms) const + { + item_t gw = params.gw; + item_t bg = INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + item_t Pg = params.Pg; + + if (params.main_var == FI_SG_VAR) + { + item_t dbg_dsg = S_DERIV_INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + item_t krp_tetap = params.inj_params_.krp_tetap; + item_t x = params.inj_params_.dkrog_dsg_tetaog_krg_dtetag_dsg; + item_t mg = bg * krp_tetap; + item_t dpcgo_dsg = S_DERIV_CAP_PRESSURE (data, params.phase_d, FI_PHASE_GAS); + + item_t sg_deriv = -gw * ((dbg_dsg * krp_tetap + bg * x) * Pg - mg * dpcgo_dsg); + return sg_deriv; + } + else + { + item_t kro = RELATIVE_PERM (data, params.phase_d, FI_PHASE_OIL); + item_t dtetao_dro = GOR_DERIV_INVERS_VISCOSITY (data); + + item_t ro_deriv = -gw * bg * kro * dtetao_dro * Pg; + return ro_deriv; + } + } + BS_FORCE_INLINE item_t + get_gas_pref_deriv (const data_t &data, const params_t ¶ms) const + { + const item_t &gw = params.gw; + const item_t &mg = get_gas_mobility (data, params); + + item_t pref_deriv = -gw * mg; + return pref_deriv; + } + BS_FORCE_INLINE item_t + get_gas_rate (const data_t &data, const params_t ¶ms) const + { + const item_t &Pg = params.Pg; + const item_t &gw = params.gw; + const item_t &mg = get_gas_mobility (data, params); + + //item_t Rso = GAS_OIL_RATIO (data); +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] qg (%.20e) gw: %.20e mg: %.20e pg: %.20e gor: %.20e") % params.well_->name ().c_str () % params.n_block % (gw * mg * Pg) % gw % mg % Pg % Rso << bs_end; +#endif + + item_t rate = gw * mg * Pg; + return rate; + } + + BS_FORCE_INLINE item_t + get_free_gas_rate (const data_t &data, const params_t ¶ms) const + { + const item_t &Pg = params.Pg; + const item_t &gw = params.gw; + const item_t &mg = get_gas_mobility (data, params); + + item_t rate = gw * mg * Pg; + return rate; + } + + BS_FORCE_INLINE item_t + get_solution_gas_rate (const data_t &data, const params_t ¶ms) const + { + return 0.0; + } + }; + + + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELLS_WELL_RATE_INJ_MOBILITY_H_ + diff --git a/bs_bos_core/include/well_rate_control_interface.h b/bs_bos_core/include/well_rate_control_interface.h new file mode 100644 index 0000000..32643ab --- /dev/null +++ b/bs_bos_core/include/well_rate_control_interface.h @@ -0,0 +1,89 @@ +/** + * \file well_rate_control_interface.h + * \brief interface for well_rate_control_impl + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_INTERFACE_H_ +#define BS_WELLS_WELL_RATE_CONTROL_INTERFACE_H_ + +#include "rate_control_type.h" +#include "make_me_happy.h" + +namespace blue_sky { + + template class calc_model; + template class BS_API_PLUGIN well; + + namespace wells { + + template class BS_API_PLUGIN connection; + template class BS_API_PLUGIN well_controller; + } + +} + +namespace blue_sky { +namespace wells { + + template + class well_rate_control_interface : public objbase + { + public: + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + + typedef calc_model calc_model_t; + typedef jacobian_matrix jmatrix_t; + typedef well well_t; + typedef wells::well_controller well_controller_t; + typedef wells::connection connection_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_jmatrix_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_well_controller_t; + typedef smart_ptr sp_connection_t; + + public: + virtual void compute_rate (const sp_calc_model_t &calc_model, sp_jmatrix_t &jmatrix, sp_well_t &well, const sp_well_controller_t &well_controller) const = 0; + virtual void compute_derivs (const sp_calc_model_t &calc_model, sp_jmatrix_t &jmatrix, sp_well_t &well, const sp_well_controller_t &well_controller) const = 0; + + virtual ~well_rate_control_interface () + { + } + }; + + template + class well_rate_control_factory : public objbase + { + public: + typedef calc_model calc_model_t; + typedef well_rate_control_interface well_rate_control_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_well_rate_control_t; + + public: + + MAKE_ME_HAPPY (well_rate_control_factory, objbase, "well_rate_control_factory"); + + virtual sp_well_rate_control_t + create_control (rate_control_type /*control_type*/, bool /*is_bhp*/, + bool /*is_production*/, const sp_calc_model_t & /*calc_model*/) + { + // we have a problem with exporting pure abstract classes to puthon. + bs_throw_exception ("PURE_CALL"); + } + + virtual ~well_rate_control_factory () + { + } + }; + +} // namespace wells +} // namespace blue_sky + + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_INTERFACE_H_ + diff --git a/bs_bos_core/include/well_rate_control_prod_mobility.h b/bs_bos_core/include/well_rate_control_prod_mobility.h new file mode 100644 index 0000000..adf39eb --- /dev/null +++ b/bs_bos_core/include/well_rate_control_prod_mobility.h @@ -0,0 +1,357 @@ +/** + * \file well_rate_control_prod_mobility.h + * \brief mobility computation for production wells + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_PROD_MOBILITY_H_ +#define BS_WELLS_WELL_RATE_PROD_MOBILITY_H_ + +#include "calc_model.h" +#include "calc_model_data_accessors.h" +#include "well_rate_compute_params.h" + +namespace blue_sky + { + namespace wells + { + + template + struct mobility_calc_prod + { +public: + typedef strategy_type strategy_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + + typedef calc_model calc_model_t; + typedef typename calc_model_t::data_t data_t; + typedef jacobian_matrix jmatrix_t; + typedef well well_t; + typedef well_controller well_controller_t; + typedef compute_params params_t; + + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::phase_d_t phase_d_t; + typedef typename calc_model_t::main_var_array_t main_var_array_t; + + typedef typename wells::type_helper type_helper_t; + typedef typename type_helper_t::item_rhs_block_t item_rhs_block_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_jmatrix_t; + typedef smart_ptr sp_well_t; + typedef smart_ptr sp_well_controller_t; + + enum { mult = -1, }; + enum { is_inj = 0, }; + +public: + + BS_FORCE_INLINE item_t + get_mult () const + { + return item_t (mult); + } + + static BS_FORCE_INLINE bool + is_oil_injection (const params_t ¶ms) + { + return true; + } + static BS_FORCE_INLINE bool + is_water_injection (const params_t ¶ms) + { + return true; + } + static BS_FORCE_INLINE bool + is_gas_injection (const params_t ¶ms) + { + return true; + } + static BS_FORCE_INLINE bool + is_o_ctrl (const params_t ¶ms) + { + return params.prod_params_.is_o_ctrl; + } + static BS_FORCE_INLINE bool + is_w_ctrl (const params_t ¶ms) + { + return params.prod_params_.is_w_ctrl; + } + static BS_FORCE_INLINE bool + is_g_ctrl (const params_t ¶ms) + { + return params.prod_params_.is_g_ctrl; + } + + BS_FORCE_INLINE item_t + get_oil_mobility (const data_t &data, const params_t ¶ms) const + { + return MOBILITY (data, params.phase_d, FI_PHASE_OIL); + } + BS_FORCE_INLINE item_t + get_water_mobility (const data_t &data, const params_t ¶ms) const + { + return MOBILITY (data, params.phase_d, FI_PHASE_WATER); + } + BS_FORCE_INLINE item_t + get_gas_mobility (const data_t &data, const params_t ¶ms) const + { + return MOBILITY (data, params.phase_d, FI_PHASE_GAS); + } + + BS_FORCE_INLINE item_t + get_mo_po_deriv (const data_t &data, const params_t ¶ms) const + { + return P_DERIV_MOBILITY_O; + + //const item_t &kro = RELATIVE_PERM (data, params.phase_d, FI_PHASE_OIL); + //const item_t &depso_dpo = P_DERIV_INVERS_VISC_FVF (data, params.phase_d, FI_PHASE_OIL); + + //return kro * depso_dpo; + } + + BS_FORCE_INLINE item_t + get_mo_sw_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_OW; + + //const item_t &dkro_dsw = S_DERIV_RELATIVE_PERM (data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_WATER); + //const item_t &epso = INVERS_VISC_FVF (data, params.phase_d, FI_PHASE_OIL); + + //return dkro_dsw * epso; + } + + BS_FORCE_INLINE item_t + get_mo_so_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_OO; + } + + BS_FORCE_INLINE item_t + get_mo_sg_deriv (const data_t &data, const params_t ¶ms) const + { + //return S_DERIV_MOBILITY_OG; + + if (params.main_var == FI_SG_VAR) + { + return get_mo_sg_deriv_sg_var (data, params); + } + else + { + return get_mo_sg_deriv_ro_var (data, params); + } + } + + BS_FORCE_INLINE item_t + get_mo_sg_deriv_sg_var (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_OG; + + item_t dkro_dsg = S_DERIV_RELATIVE_PERM (data, params.phase_d, params.n_phases, FI_PHASE_OIL, FI_PHASE_GAS); + item_t epso = INVERS_VISC_FVF (data, params.phase_d, FI_PHASE_OIL); + + return dkro_dsg * epso; + } + BS_FORCE_INLINE item_t + get_mo_sg_deriv_ro_var (const data_t &data, const params_t ¶ms) const + { + item_t kro = RELATIVE_PERM (data, params.phase_d, FI_PHASE_OIL); + item_t depso_dro = GOR_DERIV_INVERS_VISC_FVF (data); + + return kro * depso_dro; + } + + BS_FORCE_INLINE item_t + get_mw_po_deriv (const data_t &data, const params_t ¶ms) const + { + return P_DERIV_MOBILITY_W; + + //item_t krw = RELATIVE_PERM (data, params.phase_d, FI_PHASE_WATER); + //item_t depsw_dpo = P_DERIV_INVERS_VISC_FVF (data, params.phase_d, FI_PHASE_WATER); + + //return krw * depsw_dpo; + } + BS_FORCE_INLINE item_t + get_mw_sw_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_WW; + + //item_t dkrw_dsw = S_DERIV_RELATIVE_PERM (data, params.phase_d, params.n_phases, FI_PHASE_WATER, FI_PHASE_WATER); + //item_t epsw = INVERS_VISC_FVF (data, params.phase_d, FI_PHASE_WATER); + //item_t krw = RELATIVE_PERM (data, params.phase_d, FI_PHASE_WATER); + //item_t dbw_dsw = S_DERIV_INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + //item_t tetaw = INVERS_VISCOSITY (data, params.phase_d, FI_PHASE_WATER); + //item_t bw = INVERS_FVF (data, params.phase_d, FI_PHASE_WATER); + //item_t dtetaw_dsw = S_DERIV_INVERS_VISCOSITY (data, params.phase_d, FI_PHASE_WATER); + + //item_t sw_deriv = (dkrw_dsw * epsw + krw * (dbw_dsw * tetaw + bw * dtetaw_dsw)); + //return sw_deriv; + } + BS_FORCE_INLINE item_t + get_mw_so_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_WO; + } + BS_FORCE_INLINE item_t + get_mw_sg_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_WG; + } + + //BS_FORCE_INLINE item_t + //get_mg_sw_deriv (const data_t &data, const params_t ¶ms) const + //{ + // const item_t &Rso = GAS_OIL_RATIO (data); + // const item_t &dmo_dsw = S_DERIV_MOBILITY_OW; + + // return Rso * dmo_dsw; + //} + //BS_FORCE_INLINE item_t + //get_mg_so_deriv (const data_t &data, const params_t ¶ms) const + //{ + // return S_DERIV_MOBILITY_GO + S_DERIV_MOBILITY_OO * GAS_OIL_RATIO (data); + //} + + BS_FORCE_INLINE item_t + get_gas_sw_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_GW * params.Pg + S_DERIV_MOBILITY_OW * GAS_OIL_RATIO (data) * params.Po; + } + + BS_FORCE_INLINE item_t + get_gas_so_deriv (const data_t &data, const params_t ¶ms) const + { + return S_DERIV_MOBILITY_GO * params.Pg + S_DERIV_MOBILITY_OO * GAS_OIL_RATIO (data) * params.Po; + } + + BS_FORCE_INLINE item_t + get_gas_po_deriv (const data_t &data, const params_t ¶ms) const + { + item_t gw = params.gw; + item_t mo = MOBILITY (data, params.phase_d, FI_PHASE_OIL); + item_t Po = params.Po; + item_t dmo_dpo = P_DERIV_MOBILITY_O; + item_t Rso = GAS_OIL_RATIO (data); + item_t ro_deriv = Rso * (dmo_dpo * Po - mo); + + item_t po_deriv = 0; + if (params.main_var == FI_SG_VAR) + { + item_t dmg_dpo = P_DERIV_MOBILITY_G; + item_t Pg = params.Pg; + item_t mg = MOBILITY (data, params.phase_d, FI_PHASE_GAS); + item_t dRso_dpo = P_DERIV_GAS_OIL_RATIO (data); + + po_deriv = -gw * (dmg_dpo * Pg - mg + dRso_dpo * mo * Po + ro_deriv); + } + else + { + po_deriv = -gw * ro_deriv; + } + return po_deriv; + } + BS_FORCE_INLINE item_t + get_gas_sg_deriv (const data_t &data, const params_t ¶ms) const + { + if (params.main_var == FI_SG_VAR) + { + item_t gw = params.gw; + item_t Pg = params.Pg; + item_t Po = params.Po; + + //item_t dkrg_dsg = S_DERIV_RELATIVE_PERM_GG; + //item_t dkro_dsg = S_DERIV_RELATIVE_PERM_OG; + + //item_t epsg = INVERS_VISC_FVF_G; + //item_t epso = INVERS_VISC_FVF_O; + + item_t dpcgo_dsg = S_DERIV_CAP_PRESSURE_G; + item_t Rso = GAS_OIL_RATIO (data); + item_t mg = MOBILITY_G; + item_t dmg_dsg = S_DERIV_MOBILITY_GG; + item_t dmo_dsg = S_DERIV_MOBILITY_OG; + + return -gw * (dmg_dsg * Pg - mg * dpcgo_dsg + Rso * dmo_dsg * Po); + } + else + { + item_t gw = params.gw; + item_t Po = params.Po; + item_t Ro = GAS_OIL_RATIO (data); + item_t mo = MOBILITY_O; + item_t dmo_dsg = S_DERIV_MOBILITY_OG; + + item_t ro_deriv = -gw * (mo + Ro * dmo_dsg) * Po; + return ro_deriv; + } + } + BS_FORCE_INLINE item_t + get_gas_pref_deriv (const data_t &data, const params_t ¶ms) const + { + if (params.main_var == FI_SG_VAR) + { + item_t gw = params.gw; + item_t mg = MOBILITY (data, params.phase_d, FI_PHASE_GAS); + item_t mo = MOBILITY (data, params.phase_d, FI_PHASE_OIL); + item_t Rso = GAS_OIL_RATIO (data); + + item_t pref_deriv = -gw * (mg + Rso * mo); + return pref_deriv; + } + else + { + item_t gw = params.gw; + item_t Ro = GAS_OIL_RATIO (data); + item_t mo = MOBILITY (data, params.phase_d, FI_PHASE_OIL); + + item_t pref_deriv = -gw * Ro * mo; + return pref_deriv; + } + } + BS_FORCE_INLINE item_t + get_gas_rate (const data_t &data, const params_t ¶ms) const + { + const item_t &gw = params.gw; + const item_t &Pg = params.Pg; + const item_t &Po = params.Po; + const item_t &mg = MOBILITY (data, params.phase_d, FI_PHASE_GAS); + const item_t &mo = MOBILITY (data, params.phase_d, FI_PHASE_OIL); + const item_t &Rso = GAS_OIL_RATIO (data); + +#ifdef _DEBUG + BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] qg (%.20e) gw: %.20e mg: %.20e pg: %.20e gor: %.20e") % params.well_->name ().c_str () % params.n_block % (gw * (mg * Pg + Rso * mo * Po)) % gw % mg % Pg % Rso << bs_end; +#endif + + return gw * (mg * Pg + Rso * mo * Po); + } + + BS_FORCE_INLINE item_t + get_free_gas_rate (const data_t &data, const params_t ¶ms) const + { + const item_t &gw = params.gw; + const item_t &Pg = params.Pg; + const item_t &mg = MOBILITY (data, params.phase_d, FI_PHASE_GAS); + + return gw * mg * Pg; + } + + BS_FORCE_INLINE item_t + get_solution_gas_rate (const data_t &data, const params_t ¶ms) const + { + const item_t &gw = params.gw; + const item_t &Po = params.Po; + const item_t &mo = MOBILITY (data, params.phase_d, FI_PHASE_OIL); + const item_t &Rso = GAS_OIL_RATIO (data); + + return gw * Rso * mo * Po; + } + }; + + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELLS_WELL_RATE_PROD_MOBILITY_H_ + diff --git a/bs_bos_core/include/well_rate_control_rate.h b/bs_bos_core/include/well_rate_control_rate.h new file mode 100644 index 0000000..a1bc81a --- /dev/null +++ b/bs_bos_core/include/well_rate_control_rate.h @@ -0,0 +1,449 @@ +/** + * \file well_rate_control_rate.h + * \brief + * \author Sergey Miryanov + * \date 24.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_RATE_H_ +#define BS_WELLS_WELL_RATE_CONTROL_RATE_H_ + +#include "well_rate_control_deriv.h" +#include "well_rate_control_compute_deriv_typedef.h" + +namespace blue_sky + { + namespace wells + { + + + template + struct compute_rate_3p : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_3p (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + c->get_rate_value () [p3_oil] = base_t::compute_oil_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.oil = c->get_rate_value () [p3_oil]; + c->rate_.prod.liquid = c->get_rate_value () [p3_oil]; + params.rate.prod.oil += c->get_rate_value () [p3_oil]; + params.rate.prod.liquid += c->get_rate_value () [p3_oil]; + + c->rate_rc_.prod.oil = c->rate_.prod.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.prod.liquid = c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.oil += c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.liquid += c->rate_rc_.prod.oil; + } + else + { + c->rate_.inj.oil = c->get_rate_value () [p3_oil]; + c->rate_.inj.liquid = c->get_rate_value () [p3_oil]; + params.rate.inj.oil += c->get_rate_value () [p3_oil]; + params.rate.inj.liquid += c->get_rate_value () [p3_oil]; + + c->rate_rc_.inj.oil = c->rate_.inj.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.inj.liquid = c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.oil += c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.liquid += c->rate_rc_.inj.oil; + } + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_water_injection (params)) + { + c->get_rate_value () [p3_wat] = base_t::compute_water_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.water = c->get_rate_value () [p3_wat]; + c->rate_.prod.liquid = c->get_rate_value () [p3_wat]; + params.rate.prod.water += c->get_rate_value () [p3_wat]; + params.rate.prod.liquid += c->get_rate_value () [p3_wat]; + + c->rate_rc_.prod.water = c->rate_.prod.water / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_WATER]]; + c->rate_rc_.prod.liquid = c->rate_rc_.prod.water; + params.well_->rate_rc_.prod.water += c->rate_rc_.prod.water; + params.well_->rate_rc_.prod.liquid += c->rate_rc_.prod.water; + } + else + { + c->rate_.inj.water = c->get_rate_value () [p3_wat]; + c->rate_.inj.liquid = c->get_rate_value () [p3_wat]; + params.rate.inj.water += c->get_rate_value () [p3_wat]; + params.rate.inj.liquid += c->get_rate_value () [p3_wat]; + + c->rate_rc_.inj.water = c->rate_.inj.water / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_WATER]]; + c->rate_rc_.inj.liquid = c->rate_rc_.inj.water; + params.well_->rate_rc_.inj.water += c->rate_rc_.inj.water; + params.well_->rate_rc_.inj.liquid += c->rate_rc_.inj.water; + } + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_gas_injection (params)) + { + c->get_rate_value () [p3_gas] = base_t::compute_gas_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.gas = c->get_rate_value () [p3_gas]; + c->rate_.free_gas = base_t::compute_free_gas_rate (data, params); + c->rate_.solution_gas = base_t::compute_solution_gas_rate (data, params); + params.rate.prod.gas += c->get_rate_value () [p3_gas]; + params.rate.free_gas += c->rate_.free_gas; + params.rate.solution_gas += c->rate_.solution_gas; + params.well_->gor_ = params.rate.solution_gas / params.rate.prod.oil; + + c->rate_rc_.free_gas = c->rate_.free_gas / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_GAS]]; + c->rate_rc_.solution_gas = c->rate_.solution_gas; + c->rate_rc_.prod.gas = c->rate_.free_gas + c->rate_.solution_gas / INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + params.well_->rate_rc_.prod.gas += c->rate_rc_.prod.gas; + params.well_->rate_rc_.free_gas += c->rate_rc_.free_gas; + } + else + { + c->rate_.inj.gas = c->get_rate_value () [p3_gas]; + params.rate.inj.gas += c->get_rate_value () [p3_gas]; + + c->rate_rc_.inj.gas = base_t::compute_free_gas_rate (data, params) / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_GAS]]; + params.well_->rate_rc_.inj.gas += c->rate_rc_.inj.gas; + } + } + } + }; + + template + struct compute_rate_2p_ow : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_2p_ow (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + c->get_rate_value () [p2ow_oil] = base_t::compute_oil_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.oil = c->get_rate_value () [p2ow_oil]; + c->rate_.prod.liquid = c->get_rate_value () [p2ow_oil]; + params.rate.prod.oil += c->get_rate_value () [p2ow_oil]; + params.rate.prod.liquid += c->get_rate_value () [p2ow_oil]; + + c->rate_rc_.prod.oil = c->rate_.prod.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.prod.liquid = c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.oil += c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.liquid += c->rate_rc_.prod.oil; + } + else + { + c->rate_.inj.oil = c->get_rate_value () [p2ow_oil]; + c->rate_.inj.liquid = c->get_rate_value () [p2ow_oil]; + params.rate.inj.oil += c->get_rate_value () [p2ow_oil]; + params.rate.inj.liquid += c->get_rate_value () [p2ow_oil]; + + c->rate_rc_.inj.oil = c->rate_.inj.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.inj.liquid = c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.oil += c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.liquid += c->rate_rc_.inj.oil; + } + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_water_injection (params)) + { + c->get_rate_value () [p2ow_wat] = base_t::compute_water_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.water = c->get_rate_value () [p2ow_wat]; + c->rate_.prod.liquid = c->get_rate_value () [p2ow_wat]; + params.rate.prod.water += c->get_rate_value () [p2ow_wat]; + params.rate.prod.liquid += c->get_rate_value () [p2ow_wat]; + + c->rate_rc_.prod.water = c->rate_.prod.water / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_WATER]]; + c->rate_rc_.prod.liquid = c->rate_rc_.prod.water; + params.well_->rate_rc_.prod.water += c->rate_rc_.prod.water; + params.well_->rate_rc_.prod.liquid += c->rate_rc_.prod.water; + } + else + { + c->rate_.inj.water = c->get_rate_value () [p2ow_wat]; + c->rate_.inj.liquid = c->get_rate_value () [p2ow_wat]; + params.rate.inj.water += c->get_rate_value () [p2ow_wat]; + params.rate.inj.liquid += c->get_rate_value () [p2ow_wat]; + + c->rate_rc_.inj.water = c->rate_.inj.water / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_WATER]]; + c->rate_rc_.inj.liquid = c->rate_rc_.inj.water; + params.well_->rate_rc_.inj.water += c->rate_rc_.inj.water; + params.well_->rate_rc_.inj.liquid += c->rate_rc_.inj.water; + } + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + }; + + template + struct compute_rate_2p_og : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_2p_og (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + c->get_rate_value () [p2og_oil] = base_t::compute_oil_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.oil = c->get_rate_value () [p2og_oil]; + c->rate_.prod.liquid = c->get_rate_value () [p2og_oil]; + params.rate.prod.oil += c->get_rate_value () [p2og_oil]; + params.rate.prod.liquid += c->get_rate_value () [p2og_oil]; + + c->rate_rc_.prod.oil = c->rate_.prod.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.prod.liquid = c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.oil += c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.liquid += c->rate_rc_.prod.oil; + } + else + { + c->rate_.inj.oil = c->get_rate_value () [p2og_oil]; + c->rate_.inj.liquid = c->get_rate_value () [p2og_oil]; + params.rate.inj.oil += c->get_rate_value () [p2og_oil]; + params.rate.inj.liquid += c->get_rate_value () [p2og_oil]; + + c->rate_rc_.inj.oil = c->rate_.inj.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.inj.liquid = c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.oil += c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.liquid += c->rate_rc_.inj.oil; + } + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_gas_injection (params)) + { + c->get_rate_value () [p2og_gas] = base_t::compute_gas_rate (data, params); + c->rate_.free_gas = base_t::compute_free_gas_rate (data, params) / INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + if (params.is_prod) + { + c->rate_.prod.gas = c->get_rate_value () [p2og_gas]; + params.rate.prod.gas += c->get_rate_value () [p2og_gas]; + + c->rate_.free_gas = base_t::compute_free_gas_rate (data, params); + c->rate_.solution_gas = base_t::compute_solution_gas_rate (data, params); + + params.rate.free_gas += c->rate_.free_gas; + params.rate.solution_gas += c->rate_.solution_gas; + params.well_->gor_ = params.rate.solution_gas / params.rate.prod.oil; + + c->rate_rc_.free_gas = c->rate_.free_gas / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_GAS]]; + c->rate_rc_.solution_gas = c->rate_.solution_gas; + c->rate_rc_.prod.gas = c->rate_.free_gas + c->rate_.solution_gas / INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + params.well_->rate_rc_.prod.gas += c->rate_rc_.prod.gas; + params.well_->rate_rc_.free_gas += c->rate_rc_.free_gas; + } + else + { + c->rate_.inj.gas = c->get_rate_value () [p2og_gas]; + params.rate.inj.gas += c->get_rate_value () [p2og_gas]; + + c->rate_rc_.inj.gas = base_t::compute_free_gas_rate (data, params) / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_GAS]]; + params.well_->rate_rc_.inj.gas += c->rate_rc_.inj.gas; + } + } + } + }; + + template + struct compute_rate_1p_o : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_1p_o (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_oil_injection (params)) + { + c->get_rate_value () [0] = base_t::compute_oil_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.oil = c->get_rate_value () [0]; + c->rate_.prod.liquid = c->get_rate_value () [0]; + params.rate.prod.oil += c->get_rate_value () [0]; + params.rate.prod.liquid += c->get_rate_value () [0]; + + c->rate_rc_.prod.oil = c->rate_.prod.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.prod.liquid = c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.oil += c->rate_rc_.prod.oil; + params.well_->rate_rc_.prod.liquid += c->rate_rc_.prod.oil; + } + else + { + c->rate_.inj.oil = c->get_rate_value () [0]; + c->rate_.inj.liquid = c->get_rate_value () [0]; + params.rate.inj.oil += c->get_rate_value () [0]; + params.rate.inj.liquid += c->get_rate_value () [0]; + + c->rate_rc_.inj.oil = c->rate_.inj.oil / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_OIL]]; + c->rate_rc_.inj.liquid = c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.oil += c->rate_rc_.inj.oil; + params.well_->rate_rc_.inj.liquid += c->rate_rc_.inj.oil; + } + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + }; + template + struct compute_rate_1p_w : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_1p_w (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_water_injection (params)) + { + c->get_rate_value () [0] = base_t::compute_water_rate (data, params); + if (params.is_prod) + { + c->rate_.prod.water = c->get_rate_value () [0]; + c->rate_.prod.liquid = c->get_rate_value () [0]; + params.rate.prod.water += c->get_rate_value () [0]; + params.rate.prod.liquid += c->get_rate_value () [0]; + + c->rate_rc_.prod.water = c->rate_.prod.water / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_WATER]]; + c->rate_rc_.prod.liquid = c->rate_rc_.prod.water; + params.well_->rate_rc_.prod.water += c->rate_rc_.prod.water; + params.well_->rate_rc_.prod.liquid += c->rate_rc_.prod.water; + } + else + { + c->rate_.inj.water = c->get_rate_value () [0]; + c->rate_.inj.liquid = c->get_rate_value () [0]; + params.rate.inj.water += c->get_rate_value () [0]; + params.rate.inj.liquid += c->get_rate_value () [0]; + + c->rate_rc_.inj.water = c->rate_.inj.water / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_WATER]]; + c->rate_rc_.inj.liquid = c->rate_rc_.inj.water; + params.well_->rate_rc_.inj.water += c->rate_rc_.inj.water; + params.well_->rate_rc_.inj.liquid += c->rate_rc_.inj.water; + } + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + }; + template + struct compute_rate_1p_g : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_1p_g (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + if (mobility_calc_t::is_gas_injection (params)) + { + c->get_rate_value () [0] = base_t::compute_gas_rate (data, params); + c->rate_.free_gas = base_t::compute_free_gas_rate (data, params) / INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + if (params.is_prod) + { + c->rate_.prod.gas = c->get_rate_value () [0]; + c->rate_.free_gas = base_t::compute_free_gas_rate (data, params); + c->rate_.solution_gas = base_t::compute_solution_gas_rate (data, params); + params.rate.prod.gas += c->get_rate_value () [0]; + params.rate.free_gas += c->rate_.free_gas; + params.rate.solution_gas += c->rate_.solution_gas; + params.well_->gor_ = params.rate.solution_gas / params.rate.prod.oil; + + c->rate_rc_.free_gas = c->rate_.free_gas / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_GAS]]; + c->rate_rc_.solution_gas = c->rate_.solution_gas; + c->rate_rc_.prod.gas = c->rate_.free_gas + c->rate_.solution_gas / INVERS_FVF (data, params.phase_d, FI_PHASE_GAS); + params.well_->rate_rc_.prod.gas += c->rate_rc_.prod.gas; + params.well_->rate_rc_.free_gas += c->rate_rc_.free_gas; + } + else + { + c->rate_.inj.gas = c->get_rate_value () [0]; + params.rate.inj.gas += c->get_rate_value () [0]; + + c->rate_rc_.inj.gas = base_t::compute_free_gas_rate (data, params) / params.calc_model_->invers_fvf_average[params.phase_d[FI_PHASE_GAS]]; + params.well_->rate_rc_.inj.gas += c->rate_rc_.inj.gas; + } + } + } + }; + + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_RATE_H_ + diff --git a/bs_bos_core/include/well_rate_control_rate_deriv.h b/bs_bos_core/include/well_rate_control_rate_deriv.h new file mode 100644 index 0000000..f872513 --- /dev/null +++ b/bs_bos_core/include/well_rate_control_rate_deriv.h @@ -0,0 +1,462 @@ +/** + * \file well_rate_control_rate_deriv.h + * \brief + * \author Sergey Miryanov + * \date 24.11.2008 + * */ +#ifndef BS_WELLS_WELL_RATE_CONTROL_RATE_DERIV_H_ +#define BS_WELLS_WELL_RATE_CONTROL_RATE_DERIV_H_ + +#include "well_rate_control_deriv.h" +#include "well_rate_control_compute_deriv_typedef.h" + +namespace blue_sky + { + namespace wells + { + + template + struct compute_rate_deriv_3p : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_deriv_3p (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_oil_injection (params)) + { + rw = rw_block [p3_oil] = /*this->mult * */base_t::compute_oil_pref_deriv (data, params); + } + if (mobility_calc_t::is_o_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[p3_oil * 3 + 0]/* * this->mult*/); + wr_block[1] += (rr_block[p3_oil * 3 + 1]/* * this->mult*/); + wr_block[2] += (rr_block[p3_oil * 3 + 2]/* * this->mult*/); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_water_injection (params)) + { + rw = rw_block [p3_wat] = /*this->mult * */base_t::compute_water_pref_deriv (data, params); +#ifdef _DEBUG + //BOSOUT (section::wells, level::debug) << boost::format ("[%s : %d] rw: %.20e") % params.well_->name ().c_str () % params.n_block % rw << bs_end; +#endif + } + if (mobility_calc_t::is_w_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[p3_wat * 3 + 0]/* * this->mult*/); + wr_block[1] += (rr_block[p3_wat * 3 + 1]/* * this->mult*/); + wr_block[2] += (rr_block[p3_wat * 3 + 2]/* * this->mult*/); + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_gas_injection (params)) + { + rw = rw_block [p3_gas] = /*this->mult * */base_t::compute_gas_pref_deriv (data, params); + } + if (mobility_calc_t::is_g_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[p3_gas * 3 + 0]/* * this->mult*/); + wr_block[1] += (rr_block[p3_gas * 3 + 1]/* * this->mult*/); + wr_block[2] += (rr_block[p3_gas * 3 + 2]/* * this->mult*/); + } + } + void + update_wr (const sp_connection_t &c, item_t ww) const + { + c->get_wr_value ()[0] *= ww; + c->get_wr_value ()[1] *= ww; + c->get_wr_value ()[2] *= ww; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rw = c->get_rw_value (); + item_t wefac = params.well_->exploitation_factor_; + + rw[0] = blue_sky::apply_wefac (rw[0], wefac); + rw[1] = blue_sky::apply_wefac (rw[1], wefac); + rw[2] = blue_sky::apply_wefac (rw[2], wefac); + } + + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + item_t ww_bw = (params.bw_value[0] / params.ww_value[0]); + + c->get_rate_value ()[0] -= c->get_rw_value () [0] * ww_bw; + c->get_rate_value ()[1] -= c->get_rw_value () [1] * ww_bw; + c->get_rate_value ()[2] -= c->get_rw_value () [2] * ww_bw; + } + }; + + template + struct compute_rate_deriv_2p_ow : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_deriv_2p_ow (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_oil_injection (params)) + { + rw = rw_block [p2ow_oil] = /*this->mult * */base_t::compute_oil_pref_deriv (data, params); + } + if (mobility_calc_t::is_o_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[p2ow_oil * 2 + 0]/* * this->mult*/); + wr_block[1] += (rr_block[p2ow_oil * 2 + 1]/* * this->mult*/); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_water_injection (params)) + { + rw = rw_block [p2ow_wat] = /*this->mult * */base_t::compute_water_pref_deriv (data, params); + } + if (mobility_calc_t::is_w_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[p2ow_wat * 2 + 0]/* * this->mult*/); + wr_block[1] += (rr_block[p2ow_wat * 2 + 1]/* * this->mult*/); + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_wr (const sp_connection_t &c, item_t ww) const + { + c->get_wr_value ()[0] *= ww; + c->get_wr_value ()[1] *= ww; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rw = c->get_rw_value (); + item_t wefac = params.well_->exploitation_factor_; + + rw[0] = blue_sky::apply_wefac (rw[0], wefac); + rw[1] = blue_sky::apply_wefac (rw[1], wefac); + } + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + item_t ww_bw = (params.bw_value[0] / params.ww_value[0]); + + c->get_rate_value ()[0] -= c->get_rw_value () [0] * ww_bw; + c->get_rate_value ()[1] -= c->get_rw_value () [1] * ww_bw; + } + }; + + template + struct compute_rate_deriv_2p_og : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_deriv_2p_og (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_oil_injection (params)) + { + rw = rw_block [p2og_oil] = /*this->mult * */base_t::compute_oil_pref_deriv (data, params); + } + if (mobility_calc_t::is_o_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[p2og_oil * 2 + 0]/* * this->mult*/); + wr_block[1] += (rr_block[p2og_oil * 2 + 1]/* * this->mult*/); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_gas_injection (params)) + { + rw = rw_block [p2og_gas] = /*this->mult * */base_t::compute_gas_pref_deriv (data, params); + } + if (mobility_calc_t::is_g_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[p2og_gas * 2 + 0]/* * this->mult*/); + wr_block[1] += (rr_block[p2og_gas * 2 + 1]/* * this->mult*/); + } + } + void + update_wr (const sp_connection_t &c, item_t ww) const + { + c->get_wr_value ()[0] *= ww; + c->get_wr_value ()[1] *= ww; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rw = c->get_rw_value (); + item_t wefac = params.well_->exploitation_factor_; + + rw[0] = blue_sky::apply_wefac (rw[0], wefac); + rw[1] = blue_sky::apply_wefac (rw[1], wefac); + } + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + item_t ww_bw = (params.bw_value[0] / params.ww_value[0]); + + c->get_rate_value ()[0] -= c->get_rw_value () [0] * ww_bw; + c->get_rate_value ()[1] -= c->get_rw_value () [1] * ww_bw; + } + }; + + template + struct compute_rate_deriv_1p_o : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_deriv_1p_o (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_oil_injection (params)) + { + rw = rw_block [0] = /*this->mult * */base_t::compute_oil_pref_deriv (data, params); + } + if (mobility_calc_t::is_o_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[0]/* * this->mult*/); + } + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_wr (const sp_connection_t &c, item_t ww) const + { + c->get_wr_value ()[0] *= ww; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rw = c->get_rw_value (); + item_t wefac = params.well_->exploitation_factor_; + + rw[0] = blue_sky::apply_wefac (rw[0], wefac); + } + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + item_t ww_bw = (params.bw_value[0] / params.ww_value[0]); + + c->get_rate_value ()[0] -= c->get_rw_value () [0] * ww_bw; + } + }; + template + struct compute_rate_deriv_1p_w : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_deriv_1p_w (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_water_injection (params)) + { + rw = rw_block [0] = /*this->mult * */base_t::compute_water_pref_deriv (data, params); + } + if (mobility_calc_t::is_w_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[0]/* * this->mult*/); + } + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + update_wr (const sp_connection_t &c, item_t ww) const + { + c->get_wr_value ()[0] *= ww; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rw = c->get_rw_value (); + item_t wefac = params.well_->exploitation_factor_; + + rw[0] = blue_sky::apply_wefac (rw[0], wefac); + } + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + item_t ww_bw = (params.bw_value[0] / params.ww_value[0]); + + c->get_rate_value ()[0] -= c->get_rw_value () [0] * ww_bw; + } + }; + template + struct compute_rate_deriv_1p_g : public compute_deriv + { + GET_COMPUTE_DERIV_BASE_TYPES; + + compute_rate_deriv_1p_g (const mobility_calc_t &mobility_calc) + : base_t (mobility_calc) + { + } + + void + oil_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + water_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + } + void + gas_function (const sp_connection_t &c, const data_t &data, params_t ¶ms) const + { + array_ext rw_block = c->get_rw_value (); + array_ext wr_block = c->get_wr_value (); + array_ext rr_block = c->get_rr_value (); + array_ext ww_value = params.ww_value; + item_t rw = 0; + + if (mobility_calc_t::is_gas_injection (params)) + { + rw = rw_block [0] = /*this->mult * */base_t::compute_gas_pref_deriv (data, params); + } + if (mobility_calc_t::is_g_ctrl (params)) + { + ww_value[0] += rw/* * this->mult*/; + wr_block[0] += (rr_block[0]/* * this->mult*/); + } + } + void + update_wr (const sp_connection_t &c, item_t ww) const + { + c->get_wr_value ()[0] *= ww; + } + void + apply_wefac (const sp_connection_t &c, params_t ¶ms) const + { + array_ext rw = c->get_rw_value (); + item_t wefac = params.well_->exploitation_factor_; + + rw[0] = blue_sky::apply_wefac (rw[0], wefac); + } + void + update_rate (const sp_connection_t &c, params_t ¶ms) const + { + item_t ww_bw = (params.bw_value[0] / params.ww_value[0]); + + c->get_rate_value ()[0] -= c->get_rw_value () [0] * ww_bw; + } + }; + + + + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELLS_WELL_RATE_CONTROL_RATE_DERIV_H_ + diff --git a/bs_bos_core/include/well_reporter.h b/bs_bos_core/include/well_reporter.h new file mode 100644 index 0000000..d980f7b --- /dev/null +++ b/bs_bos_core/include/well_reporter.h @@ -0,0 +1,33 @@ +/** + * \file well_reporter.h + * \brief + * \date 01.10.2009 + * \author Sergey Miryanov + * */ +#ifndef BS_BOS_CORE_WELL_REPORTER_H_ +#define BS_BOS_CORE_WELL_REPORTER_H_ + +#include BS_FORCE_PLUGIN_IMPORT () +#include "data_class.h" +#include BS_STOP_PLUGIN_IMPORT () +#include "reservoir.h" + +namespace blue_sky { + + template + struct BS_API_PLUGIN well_data_printer + { + static void + print_prod (const smart_ptr &data, const smart_ptr , true> &rs); + static void + print_inj (const smart_ptr &data, const smart_ptr , true> &rs); + static void + print_total_prod (const smart_ptr &data, const smart_ptr , true> &rs); + }; + + +} // namespace blue_sky + + +#endif // #ifndef BS_BOS_CORE_WELL_REPORTER_H_ + diff --git a/bs_bos_core/include/well_results_storage.h b/bs_bos_core/include/well_results_storage.h new file mode 100644 index 0000000..68746b7 --- /dev/null +++ b/bs_bos_core/include/well_results_storage.h @@ -0,0 +1,360 @@ +/** + * \file well_results_storage.cpp + * \brief Storage for well and connection results + * \author Ilshat Sayfullin + * \date 25.09.2009 + * */ +#ifndef __BS_WELL_RESULTS_STORAGE_H +#define __BS_WELL_RESULTS_STORAGE_H + +#include "well_rate_control.h" +#include "apply_wefac.h" +#include "rate_control_type.h" +#include "fi_params.h" +//#include "well_connection.h" + +namespace blue_sky + { + + enum well_d_params + { + WELL_D_PARAM_COR = 0, //0 - current oil rate + WELL_D_PARAM_CWR, //1 - current water rate + WELL_D_PARAM_CGR, //2 - current gas rate + WELL_D_PARAM_CLR, //3 - current liquid rate + WELL_D_PARAM_COI, //4 - current oil injection + WELL_D_PARAM_CWI, //5 - current water injection + WELL_D_PARAM_CGI, //6 - current gas injection + + WELL_D_PARAM_HCOR, //7 - current history oil rate + WELL_D_PARAM_HCWR, //8 - current history water rate + WELL_D_PARAM_HCGR, //9 - current history gas rate + WELL_D_PARAM_HCLR, //10- current history liquid rate + WELL_D_PARAM_HCOI, //11- current history oil injection + WELL_D_PARAM_HCWI, //12- current history water injection + WELL_D_PARAM_HCGI, //13- current history gas injection + + WELL_D_PARAM_CBHP, //14- BHP for connection + WELL_D_PARAM_HBHP, //15- BHP defined for well + + WELL_D_PARAM_TOR, //16- total oil rate + WELL_D_PARAM_TWR, //17- total water rate + WELL_D_PARAM_TGR, //18- total gas rate + WELL_D_PARAM_TLR, //19- total liquid rate + WELL_D_PARAM_TOI, //20- total oil injection + WELL_D_PARAM_TWI, //21- total water injection + WELL_D_PARAM_TGI, //22- total gas injection + + WELL_D_PARAM_HTOR, //23- total history oil rate + WELL_D_PARAM_HTWR, //24- total history water rate + WELL_D_PARAM_HTGR, //25- total history gas rate + WELL_D_PARAM_HTLR, //26- total history liquid rate + WELL_D_PARAM_HTOI, //27- total history oil injection + WELL_D_PARAM_HTWI, //28- total history water injection + WELL_D_PARAM_HTGI, //29- total history gas injection + WELL_D_PARAM_WEFAC, //30- wefac (effectivity of well) + WELL_D_PARAM_WBP1, //31- average well's pressure for 1 block + WELL_D_PARAM_WBP4, //32- average well's pressure for 4 block + WELL_D_PARAM_WBP5, //33- average well's pressure for 5 block + WELL_D_PARAM_WBP9, //34- average well's pressure for 9 block + + // should be the last + WELL_D_PARAM_COUNT + }; + + enum conn_d_params + { + CONN_D_PARAM_COR = 0, //0 - current oil rate + CONN_D_PARAM_CWR, //1 - current water rate + CONN_D_PARAM_CGR, //2 - current gas rate + CONN_D_PARAM_CLR, //3 - current liquid rate + CONN_D_PARAM_COI, //4 - current oil injection + CONN_D_PARAM_CWI, //5 - current water injection + CONN_D_PARAM_CGI, //6 - current gas injection + CONN_D_PARAM_BHP, //7 - BHP for connection + CONN_D_PARAM_BULKP, //8 - bulk pressure + CONN_D_PARAM_TOR, //9 - total oil rate + CONN_D_PARAM_TWR, //10- total water rate + CONN_D_PARAM_TGR, //11- total gas rate + CONN_D_PARAM_TLR, //12- total liquid rate + CONN_D_PARAM_TOI, //13- total oil injection + CONN_D_PARAM_TWI, //14- total water injection + CONN_D_PARAM_TGI, //15- total gas injection + CONN_D_PARAM_FACTOR, //16- connection factor + CONN_D_PARAM_DEPTH, //17- connection depth + + // should be the last + CONN_D_PARAM_COUNT + }; + + enum conn_i_params + { + CONN_I_PARAM_STATUS = 0, //0 - state of connection: 0 - close, 1 - open + CONN_I_PARAM_GRP_STATUS, //1 - type of connection: 0 - usual, 1 - grp_primary, 2 - grp_secondary + CONN_I_PARAM_I, //2 - index of connection block by X axes in mesh + CONN_I_PARAM_J, //3 - index of connection block by Y axes in mesh + CONN_I_PARAM_K1, //4 - start layer index of connection block by Z + CONN_I_PARAM_K2, //5 - end layer index of connection block by Z + CONN_I_PARAM_NBLOCK, //6 - block number in mesh + + // should be the last + CONN_I_PARAM_COUNT + }; + + enum well_i_params + { + WELL_I_PARAM_HSTATUS = 0, + WELL_I_PARAM_STATUS, + + // should be the last + WELL_I_PARAM_COUNT + }; + + class BS_API_PLUGIN connection_results + { + // methods + public: + connection_results (); + ~connection_results (); + + void + clear (); + + // variables + public: + typedef std::vector dates_type; + typedef std::vector d_params_internal_type; + typedef std::vector d_params_type; + typedef std::vector i_params_internal_type; + typedef std::vector i_params_type; + + dates_type dates; //!< dates array + d_params_type d_params; //!< set of float parameter arrays + i_params_type i_params; //!< set of int parameter arrays + }; + + class BS_API_PLUGIN well_results + { + // methods + public: + well_results (); + ~well_results (); + + void + clear (); + + // variables + public: + typedef std::vector dates_type; + typedef std::vector d_params_internal_type; + typedef std::vector d_params_type; + typedef std::vector i_params_internal_type; + typedef std::vector i_params_type; + typedef std::map conn_type; + typedef std::pair conn_pair_type; + + conn_type connections; + dates_type dates; + d_params_type d_params; + i_params_type i_params; + std::string group; + }; + + class BS_API_PLUGIN well_results_storage : public objbase + { + BLUE_SKY_TYPE_DECL (well_results_storage); + // methods + public: + ~well_results_storage (); + + // variables + public: + typedef std::map wells_type; + typedef std::pair wells_pair_type; + wells_type wells; + }; + + + template + struct save_well_data + { + typedef calc_model calc_model_t; + typedef typename strategy_t::index_t index_t; + + typedef typename calc_model_t::data_array_t data_array_t; + typedef typename calc_model_t::item_t item_t; + typedef typename calc_model_t::helper_t::item_rr_block_t item_rr_block_t; + typedef typename calc_model_t::helper_t::item_rw_block_t item_rw_block_t; + typedef typename calc_model_t::helper_t::item_wr_block_t item_wr_block_t; + typedef typename calc_model_t::connection_t connection_t; + typedef typename calc_model_t::well_t well_t; + typedef typename calc_model_t::reservoir_t::facility_manager_t::well_const_iterator_t well_iterator_t; + typedef typename calc_model_t::strategy_type strategy_type; + + typedef smart_ptr sp_calc_model_t; + typedef typename calc_model_t::sp_well_t sp_well_t; + typedef typename calc_model_t::sp_connection_t sp_connection_t; + typedef smart_ptr sp_well_results_storage; + + void + copy_well_data_to_storage (sp_calc_model_t &calc_model, item_t /*dt*/, well_iterator_t wb, const well_iterator_t &we, size_t /*iter_counter*/, item_t time) + { + const sp_well_results_storage &w_res (calc_model->well_res); + + //TODO: groups + for (well_iterator_t well = wb; well != we; ++well) + { + sp_well_t ws (well->second, bs_dynamic_cast ()); + well_results &wr = w_res->wells[ws->get_name ()]; + + wr.group = std::string ("FIELD");//TODO ws->get_group_name () + // add time value + wr.dates.push_back (time); + + // add current rates + wr.d_params[WELL_D_PARAM_COR].push_back (-(float)ws->rate ().prod.oil); + wr.d_params[WELL_D_PARAM_CWR].push_back (-(float)ws->rate ().prod.water); + wr.d_params[WELL_D_PARAM_CGR].push_back (-(float)ws->rate ().prod.gas); + wr.d_params[WELL_D_PARAM_CLR].push_back (-(float)ws->rate ().prod.liquid); + wr.d_params[WELL_D_PARAM_COI].push_back ((float)ws->rate ().inj.oil); + wr.d_params[WELL_D_PARAM_CWI].push_back ((float)ws->rate ().inj.water); + wr.d_params[WELL_D_PARAM_CGI].push_back ((float)ws->rate ().inj.gas); + + + // add initial rates + wr.d_params[WELL_D_PARAM_HCOR].push_back (0); + wr.d_params[WELL_D_PARAM_HCWR].push_back (0); + wr.d_params[WELL_D_PARAM_HCGR].push_back (0); + wr.d_params[WELL_D_PARAM_HCLR].push_back (0); + wr.d_params[WELL_D_PARAM_HCOI].push_back (0); + wr.d_params[WELL_D_PARAM_HCWI].push_back (0); + wr.d_params[WELL_D_PARAM_HCGI].push_back (0); + + wr.d_params[WELL_D_PARAM_TOR].push_back (-(float)ws->rate_total ().prod.oil); + wr.d_params[WELL_D_PARAM_TWR].push_back (-(float)ws->rate_total ().prod.water); + wr.d_params[WELL_D_PARAM_TGR].push_back (-(float)ws->rate_total ().prod.gas); + wr.d_params[WELL_D_PARAM_TLR].push_back (-(float)ws->rate_total ().prod.liquid); + wr.d_params[WELL_D_PARAM_TOI].push_back ((float)ws->rate_total ().inj.oil); + wr.d_params[WELL_D_PARAM_TWI].push_back ((float)ws->rate_total ().inj.water); + wr.d_params[WELL_D_PARAM_TGI].push_back ((float)ws->rate_total ().inj.gas); + + /* //TODO + wr.d_params[WELL_D_PARAM_HTOR].push_back (-(float)ws->total_initial_rate.oil); + wr.d_params[WELL_D_PARAM_HTWR].push_back (-(float)ws->total_initial_rate.water); + wr.d_params[WELL_D_PARAM_HTGR].push_back (-(float)ws->total_initial_rate.gas); + wr.d_params[WELL_D_PARAM_HTLR].push_back ((float)ws->total_initial_rate.liquid); + wr.d_params[WELL_D_PARAM_HTOI].push_back ((float)ws->total_initial_rate.oil_inj); + wr.d_params[WELL_D_PARAM_HTWI].push_back ((float)ws->total_initial_rate.water_inj); + wr.d_params[WELL_D_PARAM_HTGI].push_back ((float)ws->total_initial_rate.gas_inj); + wr.d_params[WELL_D_PARAM_WEFAC].push_back ((float)ws->wefac); + */ + + wr.d_params[WELL_D_PARAM_CBHP].push_back ((float)ws->get_well_controller ()->bhp ()); + wr.d_params[WELL_D_PARAM_HBHP].push_back ((float)ws->get_well_controller ()->bhp_history ()); + + // add integer information + using namespace wells; + int status = -999, producer = 0; + if (ws->get_well_controller ()->is_production ()) + producer = 1; + rate_control_type control_type = ws->get_well_controller ()->get_control_type (); + if (!ws->is_open ()) + { + status = 0; + } + else if (control_type == bhp_control) + { + if (producer) + status = -2; + else + status = 2; + } + else if (control_type == oil_rate_control) // (assume is producer) + { + status = -4; + } + else if (control_type == water_rate_control) + { + if (producer) + status = -3; + else + status = 1; + } + else if (control_type == gas_rate_control) // (assume is producer) + { + status = -5; + } + else if (control_type == rate_control) // (assume is injector) + { + status = 3; + } + else if (control_type == liquid_rate_control)// (assume is producer) + { + status = -1; + } + + wr.i_params[WELL_I_PARAM_HSTATUS].push_back (0);//TODO + wr.i_params[WELL_I_PARAM_STATUS].push_back (status); + + if (calc_model->ts_params->get_bool (fi_params::WRITE_CONN_RESULTS_TO_HDF5)) + { + for (size_t i = 0, cnt = ws->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &ci = ws->get_connection (i); + int cell = ci->n_block (); + connection_results &cr = wr.connections[cell]; + cr.dates.push_back (time); + + if (!ci->is_shut ()) + {/* + //TODO + cr.d_params[CONN_D_PARAM_COR].push_back (-(float)ci->second.rate.water); + cr.d_params[CONN_D_PARAM_CWR].push_back (-(float)ci->second.rate.water); + cr.d_params[CONN_D_PARAM_CGR].push_back (-(float)ci->second.rate.gas); + cr.d_params[CONN_D_PARAM_CLR].push_back (-(float)ci->second.rate.liquid); + cr.d_params[CONN_D_PARAM_COI].push_back ((float)ci->second.rate.oil_inj); + cr.d_params[CONN_D_PARAM_CWI].push_back ((float)ci->second.rate.water_inj); + cr.d_params[CONN_D_PARAM_CGI].push_back ((float)ci->second.rate.gas_inj); + */ + } + else + { + cr.d_params[CONN_D_PARAM_COR].push_back (0); + cr.d_params[CONN_D_PARAM_CWR].push_back (0); + cr.d_params[CONN_D_PARAM_CGR].push_back (0); + cr.d_params[CONN_D_PARAM_CLR].push_back (0); + cr.d_params[CONN_D_PARAM_COI].push_back (0); + cr.d_params[CONN_D_PARAM_CWI].push_back (0); + cr.d_params[CONN_D_PARAM_CGI].push_back (0); + } + + cr.d_params[CONN_D_PARAM_FACTOR].push_back ((float)ci->get_fact ()); + cr.d_params[CONN_D_PARAM_BHP].push_back ((float)ci->get_cur_bhp ()); + cr.d_params[CONN_D_PARAM_BULKP].push_back ((float)ci->get_bulkp ()); + cr.d_params[CONN_D_PARAM_DEPTH].push_back ((float)ci->connection_depth); + + cr.i_params[CONN_I_PARAM_STATUS].push_back (ci->get_status ()); + cr.i_params[CONN_I_PARAM_GRP_STATUS].push_back (0);//TODO + cr.i_params[CONN_I_PARAM_I].push_back (ci->i_coord ()); + cr.i_params[CONN_I_PARAM_J].push_back (ci->j_coord ()); + cr.i_params[CONN_I_PARAM_K1].push_back (ci->k_coord ()); + cr.i_params[CONN_I_PARAM_K2].push_back (ci->k_coord ()); + + /* //TODO + cr.d_params[CONN_D_PARAM_TOR].push_back (-(float)ci->second.commulative_rate.oil); + cr.d_params[CONN_D_PARAM_TWR].push_back (-(float)ci->second.commulative_rate.water); + cr.d_params[CONN_D_PARAM_TGR].push_back (-(float)ci->second.commulative_rate.gas); + cr.d_params[CONN_D_PARAM_TLR].push_back (-(float)ci->second.commulative_rate.liquid); + cr.d_params[CONN_D_PARAM_TOI].push_back ((float)ci->second.commulative_rate.oil_inj); + cr.d_params[CONN_D_PARAM_TWI].push_back ((float)ci->second.commulative_rate.water_inj); + cr.d_params[CONN_D_PARAM_TGI].push_back ((float)ci->second.commulative_rate.gas_inj); + */ + } + + } + } + } + }; + +} //blue_sky +#endif //__BS_WELL_RESULTS_STORAGE_H diff --git a/bs_bos_core/include/well_serializer.h b/bs_bos_core/include/well_serializer.h new file mode 100644 index 0000000..972aa49 --- /dev/null +++ b/bs_bos_core/include/well_serializer.h @@ -0,0 +1,45 @@ +/** + * \file well_serializer.h + * \brief class for serialize well data + * \author Sergey Miryanov + * \date 21.07.2008 + * */ +#ifndef BS_WELL_SERIALIZER_H_ +#define BS_WELL_SERIALIZER_H_ + +#include "data_storage_interface.h" + +namespace blue_sky + { + + template + class well; + + namespace wells + { + + template + class BS_API_PLUGIN well_serializer : public data_serializer + { + public: + + typedef well well_t; + typedef smart_ptr sp_well_t; + + virtual ~well_serializer () {} + + virtual void save (const sp_storage_t &storage, const sp_obj &obj) const; + + BLUE_SKY_TYPE_DECL_T (well_serializer); + }; + + ////////////////////////////////////////////////////////////////////////// + bool + well_serializer_register_type (const plugin_descriptor &pd); + + + } // namespace wells +} // namespace blue_sky + + +#endif // #ifndef BS_WELL_SERIALIZER_H_ diff --git a/bs_bos_core/include/well_type_helper.h b/bs_bos_core/include/well_type_helper.h new file mode 100644 index 0000000..b865033 --- /dev/null +++ b/bs_bos_core/include/well_type_helper.h @@ -0,0 +1,50 @@ +/** + * + * */ +#ifndef BS_WELL_TYPE_HELPER_H_ +#define BS_WELL_TYPE_HELPER_H_ + +#include BS_FORCE_PLUGIN_IMPORT () +#include "constants.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + namespace wells + { + + template + struct type_helper + { + typedef strategy_type strategy_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + + typedef boost::array phase_d_t; + typedef boost::array sat_d_t; + + typedef item_t item_ww_block_t; + typedef boost::array + item_rr_block_t; + + typedef boost::array item_wr_block_t; + typedef boost::array item_rw_block_t; + typedef boost::array item_rhs_block_t; + typedef boost::array item_ps_block_t; + typedef boost::array item_sp_block_t; + + typedef boost::array item_q_rate_t; + typedef boost::array item_q_rate_inflow_t; + typedef boost::array item_gas_rate_t; + + typedef boost::array invers_fvf_avgerage_t; + + typedef boost::array initial_rate_t; + }; + + + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELL_TYPE_HELPER_H_ + diff --git a/bs_bos_core/include/wellbore_density_calc.h b/bs_bos_core/include/wellbore_density_calc.h new file mode 100644 index 0000000..6a4091b --- /dev/null +++ b/bs_bos_core/include/wellbore_density_calc.h @@ -0,0 +1,45 @@ +/** + * \file wellbore_density_calc.h + * \brief perforation's density calculation (like as wellbore_density_calc in old code) + * \author Sergey Miryanov + * \date 18.11.2008 + * */ +#ifndef BS_WELLBORE_DENSITY_CALC_H_ +#define BS_WELLBORE_DENSITY_CALC_H_ + +#include "calc_perf_density_base.h" + +namespace blue_sky + { + + template + class BS_API_PLUGIN wellbore_density_calc : public calc_perf_density_base + { + public: + + typedef calc_perf_density_base base_t; + typedef wellbore_density_calc this_t; + + typedef typename base_t::item_t item_t; + typedef typename base_t::sp_well_t sp_well_t; + typedef typename base_t::sp_calc_model_t sp_calc_model_t; + + public: + + void + calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const; + + BLUE_SKY_TYPE_DECL_T (wellbore_density_calc); + + protected: + + bool + density_calc (sp_well_t &well, const sp_calc_model_t &calc_model, item_t bhp) const; + + }; + +} // namespace blue_sky + + +#endif // #ifndef BS_WELLBORE_DENSITY_CALC_H_ + diff --git a/bs_bos_core/include/wells_common_const.h b/bs_bos_core/include/wells_common_const.h new file mode 100644 index 0000000..561f955 --- /dev/null +++ b/bs_bos_core/include/wells_common_const.h @@ -0,0 +1,32 @@ +/** + * \file wells_common_const.h + * \brief wells common consts holder + * \author Sergey Miryanov + * \date 07.07.2008 + * */ +#ifndef BS_WELLS_COMMON_CONST_H_ +#define BS_WELLS_COMMON_CONST_H_ + +namespace blue_sky + { + +#ifndef MIN_ZERO_DIFF +#define MIN_ZERO_DIFF 1.0e-14 +#endif + +#ifndef DIFF_EPSILON +#define DIFF_EPSILON 1.0e-12 +#endif + +#ifndef PI +#define PI 3.141592653589793238463 +#endif + +#ifndef MIN_FRACTURE_MULT_CORR +#define MIN_FRACTURE_MULT_CORR 0.001 +#endif + +} + + +#endif // #ifndef BS_WELLS_COMMON_CONST_H_ diff --git a/bs_bos_core/include/wells_compute_connection_factors.h b/bs_bos_core/include/wells_compute_connection_factors.h new file mode 100644 index 0000000..b743e8f --- /dev/null +++ b/bs_bos_core/include/wells_compute_connection_factors.h @@ -0,0 +1,61 @@ +/** + * \file wells_compute_connection_factors.h + * \brief compute connection factors + * \author Sergey Miryanov + * \date 07.07.2008 + * */ +#ifndef BS_WELLS_COMPUTE_CONNECTION_FACTORS_H_ +#define BS_WELLS_COMPUTE_CONNECTION_FACTORS_H_ + +#include "calc_well.h" + +namespace blue_sky + { + namespace wells + { + namespace compute_factors + { + + template + struct peaceman_model + { + + typedef connection connection_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef smart_ptr sp_params_t; + + typedef rs_mesh_iface mesh_iface_t; + typedef smart_ptr sp_mesh_iface_t; + + static void compute (connection_t &connection, + const physical_constants &internal_constants, + const sp_params_t ¶ms, + const sp_mesh_iface_t &mesh, + const item_array_t &perm, + const item_array_t &ntg, + bool ro_calc_flag); + + static item_t compute_grp_pi_mult (connection_t &connection); + }; + + //struct baby_odeh_model + //{ + // static void compute (well::connection &connection, physical_constants *internal_constants, + // item_t d1, item_t d2, item_t d3, + // item_t perm1, item_t perm2, item_t perm3, + // const well::item_array_t &ntg, + // bool ro_calc_flag); + + //private: + + // static item_t F_table (item_t L, item_t d, item_t y_mid, int arg_type); + //}; + + } // namespace compute_factors + } // namespace wells +} // namespace blue_sky + +#endif // #ifndef BS_WELLS_COMPUTE_CONNECTION_FACTORS_H_ + diff --git a/bs_bos_core/src/calc_equil.cpp b/bs_bos_core/src/calc_equil.cpp new file mode 100644 index 0000000..d0ed829 --- /dev/null +++ b/bs_bos_core/src/calc_equil.cpp @@ -0,0 +1,884 @@ +/** +* @file calc_equil.cpp +* @brief calculating capillary equilibration +* @author Kamaltinova A. +* @date 2008-11-26 +*/ +#include "stdafx.h" + +#include "calc_model.h" +#include "jacobian.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "data_class.h" +#include "scal_3p.h" +#include "scale_array_holder.h" +#include "rock_grid.h" +#include "scal_region_info.h" +#include "scal_region.h" +#include "scal_2p_data_holder.h" +#include "pvt_dead_oil.h" +#include "pvt_water.h" +#include "pvt_gas.h" +#include "plane_orientation.h" +#include "jfunction.h" +#include BS_STOP_PLUGIN_IMPORT () + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +namespace blue_sky + { + + //! calc pressure on current depth + template + int + calc_model::equil_calc_pressure (item_t prev_press, item_t cur_d, item_t h, index_t phase, index_t i_pvt, + double rs_type, item_t depth_goc, item_t rs_dat, + val_vs_depth *rsvd, val_vs_depth *pbvd, + /*output*/ item_t &p, item_t *rs) + { + item_t p0, p1, rho, pb; + item_t invers_fvf = 0; + item_t rs_max; + index_t is_g = FI_CHK_GAS (phases); + + if (phase == FI_PHASE_OIL && is_g) + { + if (!rs) + return -1; + + *rs = rs_dat; + } + + p0 = 0.; + p1 = prev_press; + while (fabs (p1 - p0) > EPS_DIFF) + { + p0 = p1; + + if (phase == FI_PHASE_WATER) //water phase + { + pvt_water_array[i_pvt]->calc (0.5 * (prev_press + p0), &invers_fvf, 0, 0, 0, 0, 0); + rho = pvt_water_array[i_pvt]->get_surface_density () * invers_fvf; + } + else if (phase == FI_PHASE_GAS) //gas phase + { + pvt_gas_array[i_pvt]->calc (0.5 * (prev_press + p0), &invers_fvf, 0, 0, 0, 0, 0); + rho = pvt_gas_array[i_pvt]->get_surface_density () * invers_fvf; + } + else //oil phase + { + pvt_oil_array[i_pvt]->calc (is_g, !is_g || (cur_d - 0.5 * h < depth_goc) ? FI_SG_VAR : FI_RO_VAR, + 0.5 * (prev_press + p0), rs ? *rs : 0, &invers_fvf, + 0, 0, 0, 0, 0, 0, 0, 0, + &rs_max, 0); + + rho = pvt_oil_array[i_pvt]->get_surface_density () * invers_fvf; + + //calc Rs if gas phase is present + if (is_g) + { + //------------------------------- calc Rs ------------------------------------------ + // this is undersaturated oil case under the gas-oil contact + if (cur_d > depth_goc) + { + if (rs_type > 0) + { + if (rsvd) + *rs = rsvd->interpolate_linear (cur_d); + else if (pbvd) + { + // bubble-point pressure + pb = pbvd->interpolate_linear (cur_d); + // calculate Rs which corresponds to Pbub for undersaturated case + *rs = pvt_oil_array[i_pvt]->interpolate_and_fix (pb); + } + else + { + BOSERR (section::init_data, level::warning) + << "Error: you should specify either RSVD or PBVD keyword to use option 7 in keyword EQUIL." << bs_end; + return -1; + } + // Rs calculated by RSVD or PBVD keywords should be less than saturated RS value at the local pressure + if (*rs > rs_max) + *rs = rs_max; + } + // the dissolved gas concentration in undersaturated oil equal to the saturated Rs value at the gas-oil contact. + else + *rs = rs_dat; + } + // this is saturated oil case + else + // use Rs value for saturated oil at the local pressure above the gas-oil contact + *rs = rs_max; + //---------------------------------------------------------------------------------- + + rho += *rs * pvt_gas_array[i_pvt]->get_surface_density () * invers_fvf; + } + } + + p1 = prev_press + rho * internal_constants.gravity_constant * h; + } + + p = (p0 + p1) * 0.5; + + return 0; + } + + // initialize initial conditions + template + int + calc_model::calc_equil (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh) + { + typedef std::vector vector_t; + + const sp_idata_t &l_idata(input_data); + const sp_mesh_iface_t &l_mesh(mesh); + + const index_t n_depth = 100, n_layer = 10; + index_t i_depth; + index_t i_eql, i_pvt, i_sat = 0, n_eql; + index_t i_cell, n_cells; + index_array_t eqlnum; + item_array_t min_depth, max_depth; + item_t d_depth, h; + item_t depth_dat, press_dat, rs_dat, depth_woc, press_woc, depth_goc, press_goc; + index_t il, iu, im; + item_t prev_d, prev_p, cur_d; + index_t is_w, is_g, is_o, d_w, d_g, d_o, ds_w, ds_g; + index_t main_phase; + item_array_t depth, press, rs; // array of depthes, phases pressure, gas oil ratios + item_t p_oil, p_water, p_gas; + item_t p_p[3], s_p[2], pc_limit[2], dcoef; + + const item_array_t &perm = rock_grid_prop->permeability; + const item_array_t &poro = rock_grid_prop->porosity_p_ref; + typename sp_idata_t::pointed_t::vval_vs_depth &rsvd = l_idata->get_rsvd (); + typename sp_idata_t::pointed_t::vval_vs_depth &pbvd = l_idata->get_pbvd (); + typename sp_idata_t::pointed_t::vec_i equil_regions = l_idata->equil_regions; + const index_t N_equil = 2; + + BS_ASSERT (equil_regions.size ()); + BS_ASSERT ((*l_idata->i_map).contain (EQLNUM)); + + is_w = FI_CHK_WATER (phases); + is_g = FI_CHK_GAS (phases); + is_o = FI_CHK_OIL (phases); + d_w = phase_d[FI_PHASE_WATER]; + d_o = phase_d[FI_PHASE_OIL]; + d_g = phase_d[FI_PHASE_GAS]; + ds_w = sat_d[FI_PHASE_WATER]; + ds_g = sat_d[FI_PHASE_GAS]; + + index_t i_original_cell, i_layer; + item_t depth_top, depth_bottom, depth_center; + item_t depth_step, layer_center; + item_t s_water, s_gas; + item_array_t press_w, press_g, press_o; + array_float16_t swatinit; + item_array_t pcw; + bool is_swatinit = false; + + //get num of eql regions + n_eql = l_idata->eql_region; + //get num of elements + n_cells = l_mesh->get_n_active_elements(); + + //get eqlnum array + eqlnum.resize(n_cells); + //todo: if zero array + convert_arrays (mesh->get_n_active_elements (), mesh->get_int_to_ext (), eqlnum, (*l_idata->i_map)[EQLNUM].array); + + min_depth.resize(n_eql, 0); + max_depth.resize(n_eql, 0); + depth.resize(n_eql * n_depth, 0); + press.resize(n_eql * n_phases * n_depth, 0); + + if (is_o && is_g) + rs.resize(n_eql * n_depth, 0); + + //set min and max to datum depth + for (i_eql = 0; i_eql < n_eql; i_eql++) + min_depth[i_eql] = max_depth[i_eql] = l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_DAT_DEPTH]; + + const item_array_t &cell_depths = l_mesh->get_depths (); + + //get min and max depth in each of eql regions + for (i_cell = 0; i_cell < n_cells; i_cell++) + { + item_t top_depth = 0., bottom_depth = 0.; + i_eql = eqlnum[i_cell] - 1; + + top_depth = cell_depths[i_cell] - 0.5 * l_mesh->get_element_dim3_size (i_cell); + bottom_depth = cell_depths[i_cell] + 0.5 * l_mesh->get_element_dim3_size (i_cell); + + if (top_depth < min_depth[i_eql]) + min_depth[i_eql] = top_depth; + if (bottom_depth > max_depth[i_eql]) + max_depth[i_eql] = bottom_depth; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////// CALCULATE Pp AND Rs BY DEPTH ///////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + + //loop through all eql regions + for (i_eql = 0; i_eql < n_eql; i_eql++) + { + i_pvt = equil_regions[N_equil * i_eql + 1]; // pvt region for current equil region + + depth_dat = l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_DAT_DEPTH]; + depth_woc = l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_WOC_DEPTH]; + depth_goc = l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_GOC_DEPTH]; + press_dat = l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_DAT_PRESS]; + + //set main_phase + main_phase = FI_PHASE_OIL; + if (n_phases > 1 || is_o) + main_phase = FI_PHASE_OIL; + else if (is_w) + main_phase = FI_PHASE_WATER; + else if (is_g) + main_phase = FI_PHASE_GAS; + if (n_phases > 1) + { + if (is_w && (depth_dat > depth_woc)) + main_phase = FI_PHASE_WATER; + else if (is_g && (depth_dat < depth_goc)) + main_phase = FI_PHASE_GAS; + } + + //set depth step + d_depth = (max_depth[i_eql] - min_depth[i_eql]) / (item_t)(n_depth - 1); + + //set dep array values + for (i_depth = 0; i_depth < n_depth; i_depth++) + depth[i_depth + i_eql * n_depth] = min_depth[i_eql] + i_depth * d_depth; + + // calc Rs at datum pressure from PVTO table + rs_dat = 0.; + if (is_o && is_g) + rs_dat = pvt_oil_array[i_pvt]->interpolate_and_fix (press_dat); + + // search Ddat in dep[] array + // Ddat can't exceed [Dmin; Dmax] + BINARY_SEARCH (&depth[i_eql * n_depth], depth_dat, n_depth, iu, im, il); + if (il == 0) + iu = 1; + else + { + iu = il; + il--; + } + + //---- calc pressure table of main phase --------- + for (index_t up_down = -1; up_down < 2; up_down += 2) + { + //up_down = -1 - go up from datum depth + //up_down = 1 - go down from datum depth + if (up_down < 0) + i_depth = il; + else + i_depth = iu; + + prev_d = depth_dat; + prev_p = press_dat; + + while (i_depth >= 0 && i_depth < n_depth) + { + cur_d = depth[i_depth + i_eql * n_depth]; + h = cur_d - prev_d; + + if (equil_calc_pressure (prev_p, cur_d, h, main_phase, i_pvt, + is_g ? l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_RS_TYPE] : 0, + is_g ? depth_goc : 0, is_g ? rs_dat : 0, + (is_g && rsvd.size ()) ? &rsvd[i_eql] : 0, (is_g && pbvd.size ()) ? &pbvd[i_eql] : 0, + press[i_depth + (i_eql * n_phases + phase_d[main_phase]) * n_depth], + rs.size () ? &rs[i_depth + i_eql * n_depth] : 0)) + return -1; + + prev_p = press[i_depth + (i_eql * n_phases + phase_d[main_phase]) * n_depth]; + prev_d = cur_d; + + i_depth += up_down; + } + } + + if (n_phases > 1) + { + item_t p_temp, d_temp, rs_temp; + + if (main_phase != FI_PHASE_OIL) + { + //calc oil pressure + if (main_phase == FI_PHASE_WATER) + d_temp = depth_woc; + else + d_temp = depth_goc; + + //search d_temp in depth array + //Dwoc/Dgoc can exceed [Dmin; Dmax] + if (d_temp < min_depth[i_eql] || d_temp > max_depth[i_eql]) + { + //calc water/gas pressure at WOC/GOC + if (d_temp < min_depth[i_eql]) + { + //get first values from tables + prev_d = min_depth[i_eql]; + prev_p = press[0 + (i_eql * n_phases + phase_d[main_phase]) * n_depth]; + + il = -1; + iu = 0; + } + else + { + //get last values from tables + prev_d = max_depth[i_eql]; + prev_p = press[n_depth - 1 + (i_eql * n_phases + phase_d[main_phase]) * n_depth]; + + il = n_depth - 1; + iu = n_depth; + } + + h = d_temp - prev_d; + + if (equil_calc_pressure (prev_p, d_temp, h, main_phase, i_pvt, + 0, 0, 0, 0, 0, + p_temp)) + return -1; + + } + else + { + // search Dwoc/Dgoc in dep[] array and interpolate pressure of main phase + BINARY_SEARCH (&depth[i_eql * n_depth], d_temp, n_depth, iu, im, il); + INTERNAL_INTERPOLATION (&depth[i_eql * n_depth], &press[(i_eql * n_phases + phase_d[main_phase]) * n_depth], + d_temp, p_temp, n_depth); + + if (il == 0) + iu = 1; + else + { + iu = il; + il--; + } + } + + //oil pressure at WOC/GOC + if (main_phase == FI_PHASE_WATER) + p_temp += l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_WOC_PRESS]; + else + p_temp -= l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_GOC_PRESS]; + + //---- calc pressure table of oil ----- + for (index_t up_down = -1; up_down < 2; up_down += 2) + { + //up_down = -1 - go up from datum depth + //up_down = 1 - go down from datum depth + if (up_down < 0) + i_depth = il; + else + i_depth = iu; + + prev_d = d_temp; + prev_p = p_temp; + + while (i_depth >= 0 && i_depth < n_depth) + { + cur_d = depth[i_depth + i_eql * n_depth]; + h = cur_d - prev_d; + + if (equil_calc_pressure (prev_p, cur_d, h, FI_PHASE_OIL, i_pvt, + is_g ? l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_RS_TYPE] : 0, + is_g ? depth_goc : 0, is_g ? rs_dat : 0, + (is_g && rsvd.size ()) ? &rsvd[i_eql] : 0, (is_g && pbvd.size ()) ? &pbvd[i_eql] : 0, + press[i_depth + (i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth], + rs.size () ? &rs[i_depth + i_eql * n_depth] : 0)) + return -1; + + prev_p = press[i_depth + (i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth]; + prev_d = cur_d; + + i_depth += up_down; + } + } + } + + if (is_w && main_phase != FI_PHASE_WATER) + { + //calc water pressure + + //search depth_woc in depth array + //Dwoc can exceed [Dmin; Dmax] + if (depth_woc < min_depth[i_eql] || depth_woc > max_depth[i_eql]) + { + //calc Po at WOC + if (depth_woc < min_depth[i_eql]) + { + //get first values from tables + prev_d = min_depth[i_eql]; + prev_p = press[0 + (i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth]; + + il = -1; + iu = 0; + } + else + { + //get last values from tables + prev_d = max_depth[i_eql]; + prev_p = press[n_depth - 1 + (i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth]; + + il = n_depth - 1; + iu = n_depth; + } + + h = depth_woc - prev_d; + + //calc oil pressure at WOC + if (equil_calc_pressure (prev_p, depth_woc, h, FI_PHASE_OIL, i_pvt, + is_g ? l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_RS_TYPE] : 0, + is_g ? depth_goc : 0, is_g ? rs_dat : 0, + (is_g && rsvd.size ()) ? &rsvd[i_eql] : 0, (is_g && pbvd.size ()) ? &pbvd[i_eql] : 0, + press_woc, &rs_temp)) + return -1; + + } + else + { + // search Dwoc in dep[] array and interpolate oil pressure + BINARY_SEARCH (&depth[i_eql * n_depth], depth_woc, n_depth, iu, im, il); + INTERNAL_INTERPOLATION (&depth[i_eql * n_depth], &press[(i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth], + depth_woc, press_woc, n_depth); + + if (il == 0) + iu = 1; + else + { + iu = il; + il--; + } + } + + //water pressure at WOC + press_woc -= l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_WOC_PRESS]; + + //---- calc pressure table of water ----- + for (index_t up_down = -1; up_down < 2; up_down += 2) + { + //up_down = -1 - go up from datum depth + //up_down = 1 - go down from datum depth + if (up_down < 0) + i_depth = il; + else + i_depth = iu; + + prev_d = depth_woc; + prev_p = press_woc; + + while (i_depth >= 0 && i_depth < n_depth) + { + cur_d = depth[i_depth + i_eql * n_depth]; + h = cur_d - prev_d; + + if (equil_calc_pressure (prev_p, cur_d, h, FI_PHASE_WATER, i_pvt, + 0, 0, 0, 0, 0, + press[i_depth + (i_eql * n_phases + phase_d[FI_PHASE_WATER]) * n_depth])) + return -1; + + prev_p = press[i_depth + (i_eql * n_phases + phase_d[FI_PHASE_WATER]) * n_depth]; + prev_d = cur_d; + + i_depth += up_down; + } + } + } + + if (is_g && main_phase != FI_PHASE_GAS) + { + //calc gas pressure + + //search depth_goc in depth array + //Dgoc can exceed [Dmin; Dmax] + if (depth_goc < min_depth[i_eql] || depth_goc > max_depth[i_eql]) + { + //calc Po at WOC + if (depth_goc < min_depth[i_eql]) + { + //get first values from tables + prev_d = min_depth[i_eql]; + prev_p = press[0 + (i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth]; + + il = -1; + iu = 0; + } + else + { + //get last values from tables + prev_d = max_depth[i_eql]; + prev_p = press[n_depth - 1 + (i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth]; + + il = n_depth - 1; + iu = n_depth; + } + + h = depth_goc - prev_d; + + //calc oil pressure at GOC + if (equil_calc_pressure (prev_p, depth_goc, h, FI_PHASE_OIL, i_pvt, + is_g ? l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_RS_TYPE] : 0, + is_g ? depth_goc : 0, is_g ? rs_dat : 0, + (is_g && rsvd.size ()) ? &rsvd[i_eql] : 0, (is_g && pbvd.size ()) ? &pbvd[i_eql] : 0, + press_goc, &rs_temp)) + return -1; + + } + else + { + // search Dgoc in dep[] array and interpolate pressure of oil phase + BINARY_SEARCH (&depth[i_eql * n_depth], depth_goc, n_depth, iu, im, il); + INTERNAL_INTERPOLATION (&depth[i_eql * n_depth], &press[(i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth], + depth_goc, press_goc, n_depth); + + if (il == 0) + iu = 1; + else + { + iu = il; + il--; + } + } + + //gas pressure at GOC + press_goc += l_idata->equil[EQUIL_TOTAL * i_eql + EQUIL_GOC_PRESS]; + + //---- calc pressure table of gas ----- + for (index_t up_down = -1; up_down < 2; up_down += 2) + { + //up_down = -1 - go up from datum depth + //up_down = 1 - go down from datum depth + if (up_down < 0) + i_depth = il; + else + i_depth = iu; + + prev_d = depth_goc; + prev_p = press_goc; + + while (i_depth >= 0 && i_depth < n_depth) + { + cur_d = depth[i_depth + i_eql * n_depth]; + h = cur_d - prev_d; + + if (equil_calc_pressure (prev_p, cur_d, h, FI_PHASE_GAS, i_pvt, + 0, 0, 0, 0, 0, + press[i_depth + (i_eql * n_phases + phase_d[FI_PHASE_GAS]) * n_depth])) + return -1; + + prev_p = press[i_depth + (i_eql * n_phases + phase_d[FI_PHASE_GAS]) * n_depth]; + prev_d = cur_d; + + i_depth += up_down; + } + } + } + } + } //end of loop for equilibration regions + +#if 0 + tools::save_seq_vector ("equil_depth_bs.txt").save (depth); + tools::save_seq_vector ("equil_pressure_bs.txt").save (press); +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////// CALCULATE Pp, Sp AND Rs IN CELLS ///////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + //check SWATINIT, JFUNC and PCW + if (n_phases > 1 && is_w) + { + if ((*l_idata->d_map).contain (SWATINIT)) + { + is_swatinit = true; + swatinit = (*l_idata->d_map)[SWATINIT].array; + + scal_prop->get_water_jfunction ()->set_valid (false); + scal_prop->get_water_scale ()->remove_pcp (); + pcw.resize (n_cells, 0); + } + else if (scal_prop->get_water_jfunction ()->valid ()) + scal_prop->get_water_scale ()->remove_pcp (); + } + + //------------------------------- loop through active cells ---------------------- + for (i_cell = 0; i_cell < n_cells; i_cell++) + { + p_oil = 0.; + p_water = 0.; + p_gas = 0.; + if (n_phases > 1 && is_w) + pc_limit[ds_w] = 0.; + if (n_phases > 1 && is_g) + pc_limit[ds_g] = 0.; + + i_original_cell = l_mesh->get_element_int_to_ext (i_cell); + i_eql = eqlnum[i_cell] - 1; + if (n_phases > 1) + i_sat = sat_regions[i_cell]; + + item_t gor = 0; + item_t *rs_reg = 0; + if (is_o && is_g) + { + gas_oil_ratio [i_cell] = 0; + rs_reg = &rs[i_eql * n_depth]; + } + + if (is_o) + press_o.assign (&press[(i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth], + &press[(i_eql * n_phases + phase_d[FI_PHASE_OIL]) * n_depth] + n_depth); + if (is_w) + press_w.assign (&press[(i_eql * n_phases + phase_d[FI_PHASE_WATER]) * n_depth], + &press[(i_eql * n_phases + phase_d[FI_PHASE_WATER]) * n_depth] + n_depth); + if (is_g) + press_g.assign (&press[(i_eql * n_phases + phase_d[FI_PHASE_GAS]) * n_depth], + &press[(i_eql * n_phases + phase_d[FI_PHASE_GAS]) * n_depth] + n_depth); + + depth_center = cell_depths[i_cell]; + depth_top = depth_center - 0.5 * l_mesh->get_element_dim3_size (i_cell); + depth_bottom = depth_center + 0.5 * l_mesh->get_element_dim3_size (i_cell); + + //calc average values + depth_step = (depth_bottom - depth_top) / (item_t)n_layer; + layer_center = depth_top - 0.5 * depth_step; + + s_water = 0.; + s_gas = 0.; + + for (i_layer = 0; i_layer < n_layer; i_layer++) + { + layer_center += depth_step; + + //interpolate oil and phases pressure in layer + BINARY_SEARCH (&depth[i_eql * n_depth], layer_center, n_depth, iu, im, il); + if (il == 0) + { + if (is_o) + { + p_p[d_o] = press_o[0]; + if (is_g) + { + gor = rs_reg[0]; + } + } + if (is_w) + p_p[d_w] = press_w[0]; + if (is_g) + p_p[d_g] = press_g[0]; + } + else if (il == n_depth) + { + if (is_o) + { + + p_p[d_o] = press_o[n_depth - 1]; + if (is_g) + { + gor = rs_reg[n_depth - 1]; + } + } + if (is_w) + p_p[d_w] = press_w[n_depth - 1]; + if (is_g) + p_p[d_g] = press_g[n_depth - 1]; + } + else + { + iu = il; + il--; + + dcoef = (depth[il + i_eql * n_depth] - layer_center) / (depth[il + i_eql * n_depth] - depth[iu + i_eql * n_depth]); + if (is_o) + { + p_p[d_o] = press_o[il] + dcoef * (press_o[iu] - press_o[il]); + if (is_g) + { + gor = rs_reg[il] + dcoef * (rs_reg[iu] - rs_reg[il]); + } + } + if (is_w) + p_p[d_w] = press_w[il] + dcoef * (press_w[iu] - press_w[il]); + if (is_g) + p_p[d_g] = press_g[il] + dcoef * (press_g[iu] - press_g[il]); + } + + //calc saturation + if (n_phases > 1) + { + scal_prop->process_init (i_cell, p_p, i_sat, &perm[i_cell * PLANE_ORIENTATION_TOTAL], poro[i_cell], s_p, pc_limit); + } + + if (is_o) + { + p_oil += p_p[d_o]; + if (is_g) + { + gas_oil_ratio[i_cell] += gor; + } + } + if (is_w) + p_water += p_p[d_w]; + if (is_g) + p_gas += p_p[d_g]; + if (n_phases > 1) + { + if (is_w) + s_water += s_p[ds_w]; + if (is_g) + s_gas += s_p[ds_g]; + } + } + + if (is_o) + { + p_oil /= (item_t)n_layer; + if (is_g) + { + gas_oil_ratio[i_cell] /= (item_t)n_layer; + } + } + if (is_w) + p_water /= (item_t)n_layer; + if (is_g) + p_gas /= (item_t)n_layer; + if (n_phases > 1) + { + if (is_w) + s_water /= (item_t)n_layer; + if (is_g) + s_gas /= (item_t)n_layer; + } + + item_t smin = 0, smax = 0, pmax_table = 0; + if (n_phases > 1 && is_w && is_swatinit) + { + scal_region scal_water_data = scal_prop->get_water_data ()->get_region (i_sat); + smin = scal_water_data.get_phase_sat_min (); + smin = scal_prop->get_water_scale ()->get_sl (smin)[i_cell]; + smax = scal_water_data.get_phase_sat_max (); + smax = scal_prop->get_water_scale ()->get_su (smax)[i_cell]; + pmax_table = scal_water_data.get_pcp_max (); + } + + if (n_phases > 1 && is_w && is_swatinit && (p_oil - p_water > 0) && pmax_table > EPS_DIFF/*todo*/) + { + if (swatinit[i_original_cell] < smin) + s_water = smin; + else if (swatinit[i_original_cell] > smax) + s_water = smax; + else + { + s_water = swatinit[i_original_cell]; + + //calc pcw + scal_prop->calc_pcp (i_cell, swatinit[i_original_cell], i_sat, p_water - p_oil, pcw[i_cell]); + } + //recalc gas saturation + if (n_phases == 3 && (s_water + s_gas > 1.0)) + s_gas = (1.0 - s_water > 0.) ? 1.0 - s_water : 0.; + } + //check sum + else if (n_phases == 3 && (s_water + s_gas > 1.0)) + scal_prop->calc_gas_water_zone (i_cell, i_sat, &perm[i_cell * PLANE_ORIENTATION_TOTAL], poro[i_cell], + p_gas - p_water, s_water, s_gas); + + //check pressures + if (n_phases > 1) + { + if (is_w && (p_oil - p_water) < pc_limit[ds_w]) + p_oil = p_water + pc_limit[ds_w]; + if (is_g && (p_gas - p_oil) > pc_limit[ds_g]) + p_oil = p_gas - pc_limit[ds_g]; + } + + //set pressure + if (n_phases > 1 || is_o) + pressure[i_cell] = p_oil; + else if (is_w) + pressure[i_cell] = p_water; + else + pressure[i_cell] = p_gas; + + //set saturation + if (n_phases > 1) + { + if (is_w) + { + if (fabs (s_water - (item_t) 1.0) < (item_t) 0.001) + { + s_water = 0.999f; + } + saturation_3p[n_phases * i_cell + d_w] = (float)s_water; + } + if (is_g) + saturation_3p[n_phases * i_cell + d_g] = (float)s_gas; + + saturation_3p[n_phases * i_cell + d_o] = 1. - (float)s_water - (float)s_gas; + } + + //set Rs by new pressure and set main_variable + if (is_o && is_g) + { + if (saturation_3p[n_phases * i_cell + d_g] < EPS_DIFF && saturation_3p[n_phases * i_cell + d_o] < EPS_DIFF) + { + //gas_oil_ratio[i_cell] = 0; + main_variable[i_cell] = FI_MOMG_VAR; + } + else + { + i_pvt = pvt_regions[i_cell]; + //gas_oil_ratio[i_cell] = pvt_oil_array[i_pvt]->interpolate_and_fix (pressure[i_cell]); + + if (saturation_3p[n_phases * i_cell + d_g] > EPS_DIFF) + main_variable[i_cell] = FI_SG_VAR; + else + main_variable[i_cell] = FI_RO_VAR; + } + } + } + + if (pcw.size ()) + scal_prop->get_water_scale ()->insert_pcp (pcw); + + return 0; + } + + template int + calc_model::calc_equil (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + template int + calc_model::calc_equil (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + template int + calc_model::calc_equil (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh); + + template int + calc_model::equil_calc_pressure (item_t prev_press, item_t cur_d, item_t h, index_t phase, index_t i_pvt, + double rs_type, item_t depth_goc, item_t rs_dat, + val_vs_depth *rsvd, val_vs_depth *pbvd, + item_t &p, item_t *rs); + + template int + calc_model::equil_calc_pressure (item_t prev_press, item_t cur_d, item_t h, index_t phase, index_t i_pvt, + double rs_type, item_t depth_goc, item_t rs_dat, + val_vs_depth *rsvd, val_vs_depth *pbvd, + item_t &p, item_t *rs); + + template int + calc_model::equil_calc_pressure (item_t prev_press, item_t cur_d, item_t h, index_t phase, index_t i_pvt, + double rs_type, item_t depth_goc, item_t rs_dat, + val_vs_depth *rsvd, val_vs_depth *pbvd, + item_t &p, item_t *rs); + + +}//ns bs diff --git a/bs_bos_core/src/calc_model.cpp b/bs_bos_core/src/calc_model.cpp new file mode 100644 index 0000000..9275c38 --- /dev/null +++ b/bs_bos_core/src/calc_model.cpp @@ -0,0 +1,1812 @@ +#include "stdafx.h" + +#include "calc_model.h" +#include "fi_params.h" +#include "jacobian.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "scal_3p.h" +#include "scale_array_holder.h" +#include "scal_region_info.h" +#include "scal_region.h" +#include "scal_2p_data_holder.h" +#include "rock_grid.h" +#include "norm_calc.h" +#include "data_class.h" +#include "pvt_base.h" +#include "pvt_oil.h" +#include "pvt_dead_oil.h" +#include "pvt_water.h" +#include "pvt_gas.h" +#include "jfunction.h" +#include "rs_mesh_iface.h" +#include "jacobian_matrix.h" +#include "save_seq_vector.h" +#include "string_formater.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "well_results_storage.h" +#include "fip_results_storage.h" + +///////////////////////////////////////////////////////////////////////////// +//! if ORI < NEW than ORI = NEW +#define IF_LE_REPLACE(ORI,NEW,C,V) if ((ORI) > (NEW)) {(ORI) = (NEW);(C) = (V);} + +template +BS_FORCE_INLINE void +CHECK_VALUE (item_t X, item_t DX, item_t MIN, item_t MAX, item_t DMAX, item_t &M) +{ + if (fabs (DX) > DMAX) + { + M = (std::min) (M, DMAX / fabs (DX)); + } + if ((X + DX) < MIN) + { + M = (std::min) (M, (MIN - X) / DX); + } + if ((X + DX) > MAX) + { + M = (std::min) (M, (MAX - X) / DX); + } +} + +namespace blue_sky +{ + + template + calc_model::calc_model (bs_type_ctor_param /*param*/) + : bs_refcounter(), bs_node(bs_node::create_node()) + , scal_prop (BS_KERNEL.create_object (scal_3p_t::bs_type ())) + , well_res(BS_KERNEL.create_object(well_results_storage::bs_type())) + { + init(); + } + + template + calc_model::calc_model (const this_t & /*src*/) + : bs_refcounter(), bs_node(bs_node::create_node()) + , scal_prop (BS_KERNEL.create_object (scal_3p_t::bs_type ())) + , well_res(BS_KERNEL.create_object(well_results_storage::bs_type())) + { + //*this = src; + } + + template + calc_model::~calc_model() + { + } + + + + + template + void calc_model::init() + { + n_comps = 0; + n_phases = 0; + phases = FI_PHASE_NULL; + n_HCcomps = 0; + n_HCphases = 0; + n_pri = 0; + n_sec = 0; + n_vars = 0; + + assign (phase_d, 0); + assign (sat_d, 0); + + n_pvt_regions = 0; + n_sat_regions = 0; + n_fip_regions = 0; + + rpo_model = RPO_DEFAULT_MODEL; + + last_c_norm = 0; + approx_flag = 0; + + rock_grid_prop = BS_KERNEL.create_object (rock_grid< strategy_t >::bs_type ()); + ts_params = BS_KERNEL.create_object (fi_params::bs_type ()); + } + + // initialize main arrays + template + int calc_model::init_main_arrays (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh) + { +#ifdef _DEBUG + BOSOUT (section::init_data, level::debug) << "FI DEBUG: begin of init_main_arrays method" << bs_end; +#endif // _DEBUG + + + BS_ASSERT(input_data); + + // set up phases + this->n_phases = 0; + this->phases = static_cast ((int)input_data->fi_phases); // TODO: BUG: bad cast + + for (int i = 0; i < FI_PHASE_TOT; ++i) + { + if (phases & (1 << i)) + phase_d[i] = n_phases++; + else + phase_d[i] = -1; + } + if (n_phases > 1) + n_sec_vars = 1; + + for (int i = 0, sat_counter = 0; i < FI_PHASE_TOT; ++i) + { + if ((this->phases & (1 << i)) && (sat_counter < this->n_phases - 1)) + this->sat_d[i] = sat_counter++; + else + this->sat_d[i] = -1; + } + + if (this->n_phases < 1 || this->n_phases != input_data->fi_n_phase) + { + BOSERR (section::init_data, level::warning) + << "phases for full implicit not specified. Use keywords: OIL, WATER, GAS, ..." + << bs_end; + return -3; + } + + // set number of components and variables + this->n_comps = this->n_phases; + this->n_pri = this->n_phases; + this->n_sec = 0; + this->n_vars = this->n_pri + this->n_sec; + + int is_w = FI_CHK_WATER (this->phases); + int is_g = FI_CHK_GAS (this->phases); + int is_o = FI_CHK_OIL (this->phases); + + // fill indexes values + if (this->n_phases == 1) + { + if (is_w) + b_w_p = 0; + else if (is_g) + b_g_p = 0; + else if (is_o) + b_o_p = 0; + } + else if (this->n_phases == 2) + { + if (is_w && is_o) + { + b_w_w = 0; + b_w_p = 1; + b_o_w = 2; + b_o_p = 3; + } + else if (is_g && is_o) + { + b_g_g = 0; + b_g_p = 1; + b_o_g = 2; + b_o_p = 3; + } + } + else + { + b_w_w = 0; + b_w_g = 1; + b_w_p = 2; + b_g_w = 3; + b_g_g = 4; + b_g_p = 5; + b_o_w = 6; + b_o_g = 7; + b_o_p = 8; + } + + main_variable.resize(mesh->get_n_active_elements()); + old_data_.main_var.resize(mesh->get_n_active_elements()); + prev_niter_data_.main_var.resize(mesh->get_n_active_elements()); + assign (max_norm_counter, mesh->get_n_active_elements(), 0); + +//#ifndef _DEBUG +// data.reserve (mesh->get_n_active_elements ()); +// for (size_t i = 0, cnt = mesh->get_n_active_elements (); i < cnt; ++i) +// { +// data.push_back (data_t (n_phases)); +// } +//#else + data.resize (mesh->get_n_active_elements ()); +//#endif + + this->fip_regions.resize(mesh->get_n_active_elements()); + this->sat_regions.resize(mesh->get_n_active_elements()); + this->pvt_regions.resize(mesh->get_n_active_elements()); + + pressure.resize(mesh->get_n_active_elements()); + old_data_.pressure.resize(mesh->get_n_active_elements()); + prev_niter_data_.pressure.resize(mesh->get_n_active_elements()); + + if (this->n_phases > 1) + { + saturation_3p.resize(mesh->get_n_active_elements() * this->n_phases); + old_data_.saturation_3p.resize(mesh->get_n_active_elements() * this->n_phases); + prev_niter_data_.saturation_3p.resize(mesh->get_n_active_elements() * this->n_phases); + + //initialize gas-oil ratio array + if (FI_CHK_OIL_GAS(this->phases)) + { + gas_oil_ratio.resize(mesh->get_n_active_elements()); + old_data_.gas_oil_ratio.resize(mesh->get_n_active_elements()); + prev_niter_data_.gas_oil_ratio.resize(mesh->get_n_active_elements()); + } + } + + if (input_data->rock_region > 0) + { + this->rock_regions.resize(mesh->get_n_active_elements()); + + if (input_data->i_map->contain(ROCKNUM)) + { + convert_arrays(mesh->get_n_active_elements (), mesh->get_int_to_ext (), this->rock_regions, (*input_data->i_map)[ROCKNUM].array); //SP_AMAP_GET(input_data->i_map,ROCKNUM,amap_strategy_ii)); + FI_DECR_ARRAY (this->rock_regions, 0, mesh->get_n_active_elements(), 1); + } + else + assign (rock_regions, mesh->get_n_active_elements(), 0); + this->rocktab = input_data->rocktab; + } + + // initialize fip regions + this->n_fip_regions = input_data->fip_region; + + if (!this->n_fip_regions) + { + this->n_fip_regions = 1; + } + if (input_data->i_map->contain(FIPNUM)) + { + convert_arrays(mesh->get_n_active_elements (), mesh->get_int_to_ext (), this->fip_regions, (*input_data->i_map)[FIPNUM].array); //SP_AMAP_GET(input_data->i_map,FIPNUM,amap_strategy_ii)); + FI_DECR_ARRAY (this->fip_regions, 0, mesh->get_n_active_elements(), 1); + } + else + FI_FILL_ARRAY (this->fip_regions, 0, mesh->get_n_active_elements(), 0); + + // initialize pvt regions + this->n_pvt_regions = input_data->pvt_region; + + if (!this->n_pvt_regions) + { + this->n_pvt_regions = 1; + } + if (input_data->i_map->contain(PVTNUM)) + { + convert_arrays(mesh->get_n_active_elements (), mesh->get_int_to_ext (), this->pvt_regions,(*input_data->i_map)[PVTNUM].array); //SP_AMAP_GET(input_data->i_map,PVTNUM,amap_strategy_ii)); + FI_DECR_ARRAY (this->pvt_regions, 0, mesh->get_n_active_elements(), 1); + } + else + FI_FILL_ARRAY (this->pvt_regions, 0, mesh->get_n_active_elements(), 0); + + // initialize sat regions + this->n_sat_regions = input_data->sat_region; + + if (!this->n_sat_regions) + { + this->n_sat_regions = 1; + } + if (input_data->i_map->contain(SATNUM)) + { + convert_arrays(mesh->get_n_active_elements (), mesh->get_int_to_ext (), this->sat_regions,(*input_data->i_map)[SATNUM].array); //SP_AMAP_GET(input_data->i_map,SATNUM,amap_strategy_ii)); + FI_DECR_ARRAY (this->sat_regions, 0, mesh->get_n_active_elements(), 1); + } + else + FI_FILL_ARRAY (this->sat_regions, 0, mesh->get_n_active_elements(), 0); + + // initialize rpo_model + this->rpo_model = (RPO_MODEL_ENUM)input_data->rpo_model; + + // allocate rock grid data storage + this->rock_grid_prop->init(input_data, mesh->get_n_active_elements(), this->n_pvt_regions); + + //initialize pvt + this->init_pvt_arrays(this->pvt_oil_array, + this->pvt_gas_array, + this->pvt_water_array, + input_data); + + // initialize scale arrays + const sp_scale_array_holder_t &gas_scale_ = scal_prop->get_gas_scale (); + const sp_scale_array_holder_t &water_scale_ = scal_prop->get_water_scale (); + + gas_scale_->insert_socr ((*input_data->d_map)[SOGCR].array); + gas_scale_->insert_scr ((*input_data->d_map)[SGCR].array); + gas_scale_->insert_su ((*input_data->d_map)[SGU].array); + gas_scale_->insert_sl ((*input_data->d_map)[SGL].array); + + water_scale_->insert_socr ((*input_data->d_map)[SOWCR].array); + water_scale_->insert_scr ((*input_data->d_map)[SWCR].array); + water_scale_->insert_su ((*input_data->d_map)[SWU].array); + water_scale_->insert_sl ((*input_data->d_map)[SWL].array); + water_scale_->insert_pcp ((*input_data->d_map)[PCW].array); + + init_scal (); + + // initialize rock grid data + this->rock_grid_prop->init_data(mesh->get_n_active_elements (), mesh->get_int_to_ext (), input_data); + + set_initial_data (input_data, mesh); + +#if 0 + tools::save_seq_vector ("pressure_bs.txt").save (pressure); + if (n_phases > 1) + tools::save_seq_vector ("saturation_bs.txt").save (saturation_3p); + if (FI_CHK_OIL_GAS (phases)) + tools::save_seq_vector ("rs_bs.txt").save (gas_oil_ratio); + + tools::save_seq_vector ("cells_bs.txt").save (mesh->get_int_to_ext ()); +#endif + + return 0; + } + + // initialize initial conditions + template + int calc_model::set_initial_data (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh) + { + if (input_data->init_section) + { + //init by equlibrium calculation + if (calc_equil (input_data, mesh)) + return -1; + } + else + { + //explicit initialization + //pressure + if (init_pressure (input_data, mesh)) + return -1; + + //saturations if need + if (n_phases > 1 && init_saturation (input_data, mesh)) + return -1; + + if (FI_CHK_OIL_GAS (phases) && init_rs (input_data, mesh)) + return -1; + } + + return 0; + } + + // initialize saturation array + template + int calc_model::init_saturation (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh) + { + const index_t d_w = phase_d[FI_PHASE_WATER]; + const index_t d_o = phase_d[FI_PHASE_OIL]; + const index_t d_g = phase_d[FI_PHASE_GAS]; + + int flag = this->ts_params->get_bool(fi_params::FIX_SOIL_BUG); + + // check number of phases + if (this->n_phases < 2) + return 0; + + saturation_3p.resize(mesh->get_n_active_elements() * this->n_phases); + + if (!input_data) + { + bs_throw_exception ("idata is not initialized"); + } + + if (!mesh) + { + bs_throw_exception ("mesh is not initialized"); + return -1; + } + + const index_array_t &original_element_num = mesh->get_int_to_ext(); + index_t n = mesh->get_n_active_elements(); + + // check number of unknowns + int un_counter = 0; + if (FI_CHK_WATER (this->phases) && !input_data->d_map->contain(SWAT)) + ++un_counter; + if (FI_CHK_OIL (this->phases) && !input_data->d_map->contain(SOIL)) + ++un_counter; + if (FI_CHK_GAS (this->phases) && !input_data->d_map->contain(SGAS)) + ++un_counter; + + array_float16_t soil = (*input_data->d_map)[SOIL].array; + array_float16_t swat = (*input_data->d_map)[SWAT].array; + array_float16_t sgas = (*input_data->d_map)[SGAS].array; + + if (un_counter > 1) + { + bs_throw_exception ("Not enought phases saturations specified"); + } + + // 2ph water oil + if (this->n_phases == 2 && FI_CHK_WATER (this->phases) && FI_CHK_OIL (this->phases)) + { + if (soil.size () && swat.size ()) + { + BOSWARN (section::init_data, level::warning) + << "Oil saturation will ignored in 2 phase water-oil system." << bs_end; + } + else if (!swat.size () && !soil.size ()) + { + bs_throw_exception ("Water or oil saturation has not been specified"); + } + + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + if (swat.size ()) + { + if (swat[blk_i] > (item_t)1.0 + EPS_DIFF || swat[blk_i] < -EPS_DIFF) + { + BOSWARN (section::init_data, level::warning) << "Water saturation is out of range" << bs_end; + //saturation[i] = (item_t)1.0; + saturation_3p[i * n_phases + d_w] = (item_t)1.0; + saturation_3p[i * n_phases + d_o] = (item_t)0; + } + else + { + //saturation[i] = (*swat)[blk_i]; + saturation_3p[i * n_phases + d_w] = swat[blk_i]; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - swat[blk_i]; + } + } + else if (soil.size ()) + { + if (soil[blk_i] > (item_t)1.0 + EPS_DIFF || soil[blk_i] < -EPS_DIFF) + { + BOSWARN (section::init_data, level::warning) << "Oil saturation is out of range" << bs_end; + //saturation[i] = (item_t)1.0; + saturation_3p[i * n_phases + d_w] = (item_t)0; + saturation_3p[i * n_phases + d_o] = (item_t)1.0; + } + else + { + //saturation[i] = (item_t)1. - (*swat)[blk_i]; + saturation_3p[i * n_phases + d_w] = (item_t)1.0 - soil[blk_i]; + saturation_3p[i * n_phases + d_o] = soil[blk_i]; + } + } + } + } + // 2ph water gas system + else if (this->n_phases == 2 && FI_CHK_WATER (this->phases) && FI_CHK_GAS(this->phases)) + { + if (swat.size () && sgas.size ()) + { + BOSWARN (section::init_data, level::warning) + << "Gas saturation will be ignored in 2 phase water-gas system." << bs_end; + } + if (!swat.size () && !sgas.size ()) + { + bs_throw_exception ("Water or gas saturation has not been specified"); + } + + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + if (swat.size ()) + { + if (swat[blk_i] > (item_t)1.0 + EPS_DIFF || swat[blk_i] < -EPS_DIFF) + { + BOSWARN (section::init_data, level::warning) + << "Water saturation is out of range." << bs_end; + //saturation[i] = (item_t)1.0; + saturation_3p[i * n_phases + d_w] = (item_t)1.0; + saturation_3p[i * n_phases + d_g] = (item_t)0; + } + else + { + //saturation[i] = (*swat)[blk_i]; + saturation_3p[i * n_phases + d_w] = swat[blk_i]; + saturation_3p[i * n_phases + d_g] = (item_t)1.0 - swat[blk_i]; + } + } + else if (sgas.size ()) + { + if (sgas[blk_i] > (item_t)1.0 + EPS_DIFF || sgas[blk_i] < -EPS_DIFF) + { + BOSWARN (section::init_data, level::warning) + << "Gas saturation is out of range." << bs_end; + //saturation[i] = (item_t)1.0; + saturation_3p[i * n_phases + d_w] = (item_t)0; + saturation_3p[i * n_phases + d_g] = (item_t)1.0; + } + else + { + //saturation[i] = (item_t)1. - (*sgas)[blk_i]; + saturation_3p[i * n_phases + d_g] = sgas[blk_i]; + saturation_3p[i * n_phases + d_w] = (item_t)1.0 - sgas[blk_i]; + } + } + } + } + // 2ph oil gas system + else if (this->n_phases == 2 && FI_CHK_OIL (this->phases) && FI_CHK_GAS (this->phases)) + { + if (soil.size () && sgas.size ()) + { + BOSWARN (section::init_data, level::warning) + << "Oil saturation will be ignored in 2 phase gas-oil system." << bs_end; + } + else if (!soil.size () && !sgas.size ()) + { + bs_throw_exception ("Gas or oil saturation has not been specified"); + } + + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + if (soil.size ()) + { + if (soil[blk_i] > (item_t) + EPS_DIFF || soil[blk_i] < -EPS_DIFF) + { + BOSWARN (section::init_data, level::warning) + << "Oil saturation is out of range." << bs_end; + //saturation[i] = (item_t)0.0; + saturation_3p[i * n_phases + d_g] = (item_t)0; + saturation_3p[i * n_phases + d_o] = (item_t)1.0; + } + else + { + //saturation[i] = (item_t)1.0 - (*soil)[blk_i]; + saturation_3p[i * n_phases + d_g] = (item_t)1.0 - soil[blk_i]; + saturation_3p[i * n_phases + d_o] = soil[blk_i]; + } + } + else if (sgas.size ()) + { + if (sgas[blk_i] > (item_t)1.0 + EPS_DIFF || sgas[blk_i] < -EPS_DIFF) + { + BOSWARN (section::init_data, level::warning) + << "Gas saturation is out of range." << bs_end; + //saturation[i] = (item_t)1.0; + saturation_3p[i * n_phases + d_g] = (item_t)1.0; + saturation_3p[i * n_phases + d_o] = (item_t)0; + } + else + { + //saturation[i] = (*sgas)[blk_i]; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - sgas[blk_i]; + saturation_3p[i * n_phases + d_g] = sgas[blk_i]; + } + } + } + } + // 3ph water oil gas system + else if (this->n_phases == 3) + { + if (swat.size () && soil.size () && sgas.size ()) + { + BOSWARN (section::init_data, level::warning) + << "Oil saturation will be ignored in 3 phase water-gas-oil system." << bs_end; + } + + if (swat.size () && sgas.size ()) + { + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + item_t sw = swat[blk_i]; + item_t sg = sgas[blk_i]; + if ((sw + sg) < -EPS_DIFF || (sw + sg) > 1 + EPS_DIFF) + { + bs_throw_exception ("Gas saturation plus water saturation is out of range"); + } + if (flag && fabs (sw - (item_t)1.0) < (item_t)0.01) + { + sw = static_cast (0.99); + } + + saturation_3p[i * n_phases + d_w] = sw; + saturation_3p[i * n_phases + d_g] = sg; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - sw - sg; + } + } + + else if (swat.size () && soil.size ()) + { + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + item_t sw = swat[blk_i]; + item_t sg = (item_t)1.0 - sw - soil[blk_i]; + if (sg < -EPS_DIFF || sg > 1 + EPS_DIFF) + { + bs_throw_exception ("Oil saturation plus water saturation is out of range"); + } + if (flag && fabs(sw - (item_t)1.0) < (item_t)0.001) + { + sw = 0.999f; + } + + saturation_3p[i * n_phases + d_w] = sw; + saturation_3p[i * n_phases + d_g] = sg; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - sw - sg; + } + } + + else if (sgas.size () && soil.size ()) + { + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + item_t sg = sgas[blk_i]; + item_t sw = (item_t)1.0 - sg - soil[blk_i]; + if (sw < -EPS_DIFF || sw > 1 + EPS_DIFF) + { + bs_throw_exception ("Oil saturation plus gas saturation is out of range"); + } + if (flag && fabs(sw - (item_t)1.0) < (item_t)0.01) + { + sw = static_cast (0.99); + } + + saturation_3p[i * n_phases + d_w] = sw; + saturation_3p[i * n_phases + d_g] = sg; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - sw - sg; + } + } + else if (swat.size ()) + { + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + item_t sw = swat[blk_i]; + item_t sg = (item_t)0.0; + if (sw > 1 + EPS_DIFF || sw < -EPS_DIFF) + { + bs_throw_exception ("Water saturation is out of range"); + } + if (flag && fabs(sw - (item_t)1.0) < (item_t)0.01) + { + sw = static_cast (0.99); + } + + saturation_3p[i * n_phases + d_w] = sw; + saturation_3p[i * n_phases + d_g] = sg; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - sw - sg; + } + } + + else if (soil.size ()) + { + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + item_t sw = (item_t)1.0 - soil[blk_i]; + item_t sg = (item_t)0.0; + if (soil[blk_i] > 1 + EPS_DIFF || soil[blk_i] < -EPS_DIFF) + { + bs_throw_exception ("Oil saturation is out of range"); + } + if (flag && fabs(sw - (item_t)1.0) < (item_t)0.01) + { + sw = static_cast (0.99); + } + + saturation_3p[i * n_phases + d_w] = sw; + saturation_3p[i * n_phases + d_g] = sg; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - sw - sg; + } + } + + else if (sgas.size ()) + { + for (index_t i = 0; i < n; ++i) + { + index_t blk_i = original_element_num[i]; + item_t sw = (item_t)1.0 - sgas[blk_i]; + item_t sg = sgas[blk_i]; + if (sg > 1 + EPS_DIFF || sg < -EPS_DIFF) + { + bs_throw_exception ("Gas saturation is out of range"); + } + if (flag && fabs(sw - (item_t)1.0) < (item_t)0.01) + { + sw = static_cast (0.99); + } + + saturation_3p[i * n_phases + d_w] = sw; + saturation_3p[i * n_phases + d_g] = sg; + saturation_3p[i * n_phases + d_o] = (item_t)1.0 - sw - sg; + } + } + else + { + bs_throw_exception ("None of saturation specified"); + } + } + + return 0; + } + + // initialize saturation array + template + int calc_model::init_pressure (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh) + { + if (input_data->prvd.size()) + { + const item_array_t &depths = mesh->get_depths (); + index_t n_cells = mesh->get_n_active_elements(); + if (!input_data->i_map->contain (EQLNUM)) + { + input_data->i_map->create_item (EQLNUM, &i_pool_sizes[ARRAY_POOL_TOTAL * EQLNUM], i_pool_default_values[EQLNUM]); + array_uint8_t eqlnum = tools::get_non_empty ((*input_data->i_map)[EQLNUM].array); + eqlnum.assign (1); + } + array_uint8_t eqlnum = tools::get_non_empty ((*input_data->i_map)[EQLNUM].array); + + //interpolate by depth + for (index_t i = 0; i < n_cells; ++i) + { + index_t i_orig = mesh->get_int_to_ext ()[i]; + index_t i_eql = eqlnum[i_orig] - 1; + pressure[i] = input_data->prvd[i_eql].interpolate_linear (depths[i]); + } + } + else if (input_data->d_map->contain (PRESSURE)) + { + convert_arrays (mesh->get_n_active_elements (), mesh->get_int_to_ext (), pressure, (*input_data->d_map)[PRESSURE].array); + } + else + { + bs_throw_exception ("Initial pressure has not been specified"); + } + + return 0; + } + + // initialize arrays for calculation process + template + int calc_model::init_calcul_arrays (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh) + { + + // trans mult + //this->truns_mult.resize(mesh->get_n_active_elements()); + //this->p_deriv_truns_mult.resize(mesh->get_n_active_elements()); + + // workspace : 3 phase or 2 phase oil-gas system + if (FI_CHK_OIL_GAS(this->phases)) + workspace.resize(mesh->get_n_active_elements() * (this->n_phases + 1)); + else // one phase or only water-oil system + workspace.resize(mesh->get_n_active_elements() * this->n_phases); + + // well storage +// FI_FREE (new_fwell_storage); +// new_fwell_storage = new t_well_storage; +// if (!new_fwell_storage) +// r_code = -1; + +// if (new_fwell_storage->init (get_mesh()->n_elements, ADD_WELLS, ADD_WELLS, n_phases)) +// // Error message already output +// return -1; + + if (this->ts_params->get_bool(fi_params::STORE_PANE_FLOW_RATES)) + { + //TODO: n_planes + this->plane_flow_rate.resize(mesh->get_n_active_elements() * this->n_phases); + this->full_step_plane_flow_rate.resize(mesh->get_n_active_elements() * this->n_phases); + } + + iwksp.resize(mesh->get_n_active_elements()); + +// FI_DOUBLE_ARRAY_REALLOCATOR (bconn_pressure, get_mesh()->n_boundary_connections, r_code); +// FI_DOUBLE_ARRAY_REALLOCATOR (bconn_saturation, get_mesh()->n_boundary_connections * (n_phases - 1), r_code); +// if (FI_CHK_OIL_GAS (phases)) { +// FI_DOUBLE_ARRAY_REALLOCATOR (bconn_gor, get_mesh()->n_boundary_connections, r_code); +// FI_INT_ARRAY_REALLOCATOR (bconn_mainvar, get_mesh()->n_boundary_connections, r_code); +// } + + init_boundary_connections (input_data, mesh); + + return 0; + } + + template + void + calc_model ::init_jacobian (const sp_jacobian_t &jacobian, const sp_mesh_iface_t &mesh) + { + const sp_jacobian_matrix_t &locked_jmatrix (jacobian->get_jmatrix ()); + +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + this->jacobian_->init_jacobian (input_data->get_mesh(), this->n_phases, this->ts_params, mpi_decomp); +#else //_MPI + locked_jmatrix->init (mesh->get_n_active_elements (), n_phases, 3, 0, n_sec_vars); +#endif //_MPI + } + + template + void + calc_model ::init_boundary_connections (const sp_idata_t & /*input_data*/, const sp_mesh_iface_t & /*mesh*/) + { + // initialize boundary connections + // for (int i = 0; i < get_mesh()->n_boundary_connections; ++i) { +// int i_block; +// i_block = get_mesh()->boundary_connection_element[i]; +// if (TEST_BITS_UINT (get_mesh()->boundary_connection_type_p, i, 1) == FI_MESH_BCONN_FIX_PRESSURE) +// { +// bconn_pressure[i] = pressure[i_block]; +// if (n_phases == 2) +// { +// bconn_saturation[i] = saturation[i_block]; +// } +// else if (n_phases == 3) +// { +// bconn_saturation[i * (n_phases - 1) + 0] = saturation[i_block * (n_phases - 1) + 0]; +// bconn_saturation[i * (n_phases - 1) + 1] = saturation[i_block * (n_phases - 1) + 1]; +// } +// if (FI_CHK_OIL_GAS (phases)) +// { +// bconn_gor[i] = gas_oil_ratio[i_block]; +// bconn_mainvar[i] = main_variable[i_block]; +// } + +// if (scal_prop.sowcr) +// scal_prop.bconn_sowcr[i] = scal_prop.sowcr[i_block]; +// if (scal_prop.swcr) +// scal_prop.bconn_swcr[i] = scal_prop.swcr[i_block]; +// if (scal_prop.swl) +// scal_prop.bconn_swl[i] = scal_prop.swl[i_block]; +// if (scal_prop.swu) +// scal_prop.bconn_swu[i] = scal_prop.swu[i_block]; +// if (scal_prop.pcw) +// scal_prop.bconn_pcw[i] = scal_prop.pcw[i_block]; +// if (scal_prop.sogcr) +// scal_prop.bconn_sogcr[i] = scal_prop.sogcr[i_block]; +// if (scal_prop.sgcr) +// scal_prop.bconn_sgcr[i] = scal_prop.sgcr[i_block]; +// if (scal_prop.sgl) +// scal_prop.bconn_sgl[i] = scal_prop.sgl[i_block]; +// if (scal_prop.sgu) +// scal_prop.bconn_sgu[i] = scal_prop.sgu[i_block]; +// } +// } + } + + // initialize phases variables (rs) and select number of phases + template + int calc_model::init_rs (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh) + { + array_float16_t init_pbub = (*input_data->d_map)[PBUB].array; + array_float16_t init_rs = (*input_data->d_map)[RS].array; + if (!init_pbub.size () && !init_rs.size ()) + { + bs_throw_exception ("Should be specified init_pbub or init_rs"); + } + + // main loop through all cells + item_t cell_pbub = 0; + for (index_t i = 0, cell_count = mesh->get_n_active_elements(); i < cell_count; ++i) + { + // calculate index of gas saturation and oil PVT prop + index_t i_g = FI_PH_IND (i, phase_d[FI_PHASE_GAS], n_phases); + index_t i_o = FI_PH_IND (i, phase_d[FI_PHASE_OIL], n_phases); + // get cell PVT region index + index_t reg = this->pvt_regions[i]; + + // get PVTO for cell + sp_pvt_t pvto = pvt_oil_array[reg]; + if (!pvto) + continue; + + // get cell index in original arrays + index_t cell_i = mesh->get_int_to_ext()[i]; + + if (saturation_3p[i_g] < EPS_DIFF && saturation_3p[i_o] < EPS_DIFF) + { + gas_oil_ratio[i] = 0; + main_variable[i] = FI_MOMG_VAR; + } + // if S_g > 0 --- main var is S_g and system include 3 phases + // P_bub = P and Rs = Rs (P_bub) + else if (saturation_3p[i_g] > EPS_DIFF) + { + if (init_pbub.size () && init_pbub[cell_i] < this->pressure[i]) + cell_pbub = init_pbub[cell_i]; + else + cell_pbub = this->pressure[i]; + + gas_oil_ratio[i] = pvto->interpolate_and_fix (cell_pbub); + + // set main variable to GAS saturation + main_variable[i] = FI_SG_VAR; + } + else + { + // if S_g == 0 --- main variable is Rs, + // if user specify initial bubble point (PBUB) + if (init_pbub.size ()) + { + // initial bubble point can not be greater than cell pressure + if (init_pbub[cell_i] < this->pressure[i]) + cell_pbub = init_pbub[cell_i]; + else + cell_pbub = this->pressure[i]; + + gas_oil_ratio[i] = pvto->interpolate_and_fix (cell_pbub); + } + // if user specify initial RS + else if (init_rs.size ()) + { + gas_oil_ratio[i] = init_rs[cell_i]; + } + else + { + BS_ASSERT (false && "init_pbub and init_rs is not specified"); + } + + // set main variable to RS + main_variable[i] = FI_RO_VAR; + } + } + + return 0; + } + + template + const calc_model &calc_model::operator=(const this_t &src) + { + n_comps = src.n_comps; + n_phases = src.n_phases; + phases = src.phases; + n_HCcomps = src.n_HCcomps; + n_HCphases = src.n_HCphases; + n_pri = src.n_pri; + n_sec = src.n_sec; + n_vars = src.n_vars; + + std::copy (src.phase_d.begin (), src.phase_d.end (), phase_d.begin ()); + std::copy (src.sat_d.begin (), src.sat_d.end (), sat_d.begin ()); + + n_pvt_regions = src.n_pvt_regions; + n_sat_regions = src.n_sat_regions; + n_fip_regions = n_fip_regions; + + rpo_model = src.rpo_model; + + last_c_norm = src.last_c_norm; + approx_flag = src.approx_flag; + + pvt_regions.assign (src.pvt_regions.begin (), src.pvt_regions.end ()); + sat_regions.assign (src.sat_regions.begin (), src.sat_regions.end ()); + fip_regions.assign (src.fip_regions.begin (), src.fip_regions.end ()); + rock_regions.assign (src.rock_regions.begin (), src.rock_regions.end ()); + + plane_flow_rate.assign(src.plane_flow_rate.begin(),src.plane_flow_rate.end()); + full_step_plane_flow_rate.assign(src.full_step_plane_flow_rate.begin(),src.full_step_plane_flow_rate.end()); + //truns_mult.assign(src.truns_mult.begin(),src.truns_mult.end()); + //p_deriv_truns_mult.assign(src.p_deriv_truns_mult.begin(),src.p_deriv_truns_mult.end()); + + //scal_prop = give_kernel::Instance().create_object_copy(src.scal_prop); + rock_grid_prop = give_kernel::Instance().create_object_copy(src.rock_grid_prop); + + ts_params = give_kernel::Instance().create_object_copy(src.ts_params); + + mat = give_kernel::Instance().create_object_copy(src.mat); + return *this; + } + + struct pvt_helper + { + template + static void + set_array (const pvt_array_t &pvt, const pvt_vector_t &v) + { + for (size_t i = 0; i < v.size(); ++i) + { + const typename pvt_array_t::value_type &pvt__(pvt[i]); + + const typename pvt_vector_t::value_type &p = v[i]; + pvt__->insert_vector(p.main_data_); + if (p.has_density_) + { + pvt__->set_density (p.density_, p.molar_density_); + } + } + } + }; + + template + void + calc_model::init_scal () + { + scal_prop->set_water_jfunction (BS_KERNEL.create_object (scal_3p_t::jfunction_t::bs_type ())); + scal_prop->set_gas_jfunction (BS_KERNEL.create_object (scal_3p_t::jfunction_t::bs_type ())); + scal_prop->init (is_water (), is_gas (), is_oil (), phase_d, sat_d, rpo_model); + scal_prop->update_gas_data (); + } + + template + void calc_model::init_pvt_arrays (sp_pvt_oil_array_t &pvto, + sp_pvt_gas_array_t &pvtg, + sp_pvt_water_array_t &pvtw, + const sp_idata_t &idata) + { + typedef typename idata_t::pvt_vector pvt_vector; + typedef typename idata_t::pvt_info pvt_info; + + pvto.resize(this->n_pvt_regions); + pvtg.resize(this->n_pvt_regions); + pvtw.resize(this->n_pvt_regions); + + for (int i = 0; in_pvt_regions; i++) + { + BS_ASSERT (idata->pvto.size ()); + if (idata->pvto.back ().main_data_.empty ()) + { + pvto[i] = BS_KERNEL.create_object (pvt_dead_oil_t::bs_type()); + } + else + { + pvto[i] = BS_KERNEL.create_object (pvt_oil_t::bs_type()); + } + + pvtg[i] = BS_KERNEL.create_object (pvt_gas_t::bs_type()); + pvtw[i] = BS_KERNEL.create_object (pvt_water_t::bs_type()); + } + + BS_ASSERT (idata->pvto.size ()); + if (idata->pvto.back ().main_data_.empty ()) + { + pvt_helper::set_array (pvto, idata->pvtdo); + } + else + { + pvt_helper::set_array (pvto, idata->pvto); + } + + pvt_helper::set_array (pvtg, idata->pvtg); + pvt_helper::set_array (pvtw, idata->pvtw); + + //const sp_fi_params &l_tsp (this->ts_params); + + float atm_p = this->internal_constants.atmospheric_pressure; + float min_p = this->ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MIN); + float max_p = this->ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MAX); + int n_intervals = this->ts_params->get_int (fi_params::PVT_INTERP_POINTS); + + for (int i = 0; in_pvt_regions; i++) + { + if (is_oil ()) + pvto[i]->build (atm_p, min_p, max_p, n_intervals); + + if (is_gas ()) + pvtg[i]->build (atm_p, min_p, max_p, n_intervals); + + if (is_water ()) + pvtw[i]->build (atm_p, min_p, max_p, n_intervals); + } + + } + + template + typename strategy_t::item_t + calc_model::get_initial_rho (item_t height) const + { + BS_ASSERT (!pvt_oil_array.empty ()); + + const double gravity = internal_constants.gravity_constant; + const double density = 1.5 * pvt_oil_array.front ()->get_surface_density (); + + return density * gravity * height; + } + + template + void + calc_model::update_min_pressure_range (item_t min_range) + { + this->ts_params->set_float (fi_params::PVT_PRESSURE_RANGE_MIN, min_range); + } + + template + void + calc_model::update_max_pressure_range (item_t max_range) + { + this->ts_params->set_float (fi_params::PVT_PRESSURE_RANGE_MAX, max_range); + } + + template + restore_solution_return_type + calc_model::restore_solution (const sp_mesh_iface_t &mesh, const sp_jacobian_matrix_t &jacobian) + { + return apply_newton_correction (1.0, 0, mesh, jacobian); + } + + /** + * @brief apply newton correction, and multiply it by given #mult (default 1.0) + * + * @param mult -- mult cofficient + * @param istart_line_search -- flag + * + * @return return 0 if success, < 0 if error occur, > 0 if newton process should be restarted + */ + template + restore_solution_return_type + calc_model::apply_newton_correction (item_t mult, index_t istart_line_search, const sp_mesh_iface_t &mesh, const sp_jacobian_matrix_t &jacobian) + { + //int ret_code = 0; + static double mult_out = 1.0; // TODO: WTF + + if (!istart_line_search) // calculate multiplier first time only + { + mult_out = new_simple_get_cell_solution_mult_2 (mesh, jacobian); + //mult_out = new_simple_get_cell_solution_mult (mesh, jacobian); + + //if (fabs (mult_out - mult_out_x) > 0.0) + // { + // BOSOUT (section::iters, level::debug) << "MULT_OUT_DIFF: " << mult_out << " - " << mult_out_x << ": " << mult_out - mult_out_x << bs_end; + // } + + if (mult_out < 0.2) + { + mult_out = 0.2; + } + } + else + { + // calculate total mult from internal and external mult + mult_out *= mult; + } + + BOSOUT (section::iters, level::low) << "Solution MULT: " << mult_out << bs_end; + // restore solution + if (new_simple_get_cell_solution (mult_out, istart_line_search, mesh, jacobian)) + { + BOSERR (section::iters, level::error) << "apply_newton_correction: Couldn't apply newton correction for cells" << bs_end; + return SMALL_TIME_STEP_FAIL; + } + + return SMALL_TIME_STEP_OK; + } + +//! if ORI < NEW than ORI = NEW +#define IF_LE_REPLACE(ORI,NEW,C,V) if ((ORI) > (NEW)) {(ORI) = (NEW);(C) = (V);} + + template + typename strategy_t::item_t + calc_model ::new_simple_get_cell_solution_mult_2 (const sp_mesh_iface_t &msh, const sp_jacobian_matrix_t &jmatrix) const + { + BS_ASSERT (msh); + BS_ASSERT (jmatrix); + BS_ASSERT (!pressure.empty ()); + if (n_phases > 1) + { + BS_ASSERT (!saturation_3p.empty ()); + } + + item_t mult = 1.0; + const item_t max_p = (item_t) ts_params->get_float (fi_params::MAX_P_CORRECTION); + const item_t max_s = (item_t) ts_params->get_float (fi_params::MAX_S_CORRECTION); + const item_t minimal_pressure = (item_t) ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MIN); + const item_t maximal_pressure = (item_t) ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MAX); + const item_t max_rs = (item_t) ts_params->get_float (fi_params::MAX_RS_CORRECTION); + const bool is_w = FI_CHK_WATER (phases); + const bool is_oil_gas = FI_CHK_OIL_GAS (phases); + const int d_w = phase_d[FI_PHASE_WATER]; + const int d_g = phase_d[FI_PHASE_GAS]; + int condition = 0; + index_t n = msh->get_n_active_elements (); + const item_array_t &x_sol = jmatrix->get_solution (); + item_t d = 0.0; + item_t t_mult = 0.0; + +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + index_t n_left = mpi_decomp->get_recv_l (); + index_t n_right = msh->n_elements - mpi_decomp->get_recv_r (); +#endif //_MPI + + +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + // calc only internal cells + for (index_t i = n_left; i < n_right; ++i) +#else //_MPI + // loop through all cells + for (index_t i = 0; i < n; ++i) +#endif //_MPI + { + // check water saturation + if (is_w && n_phases > 1) + { + +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + index_t jj = (i - n_left) * n_phases + d_w; +#else //_MPI + index_t jj = i * n_phases + d_w; +#endif //_MPI + + if (fabs (x_sol[jj]) > max_s) + { + t_mult = max_s / fabs (x_sol[jj]); + IF_LE_REPLACE (mult, t_mult, condition, 1); + } + } +#if 1 + if (is_oil_gas) + { + index_t jj = i * n_phases + d_g; + // check gas saturation + if (main_variable[i] == FI_SG_VAR) + { + if (fabs (x_sol[jj]) > max_s) + { + t_mult = max_s / fabs (x_sol[jj]); + IF_LE_REPLACE (mult, t_mult, condition, 2); + } + } + // check gas oil ratio + else + { +#ifdef _DEBUG + //if (fabs (x_sol[jj]) > max_rs) + // { + // printf ("CELL %d, Sw_old %lf, Sg_old %lf, P_old %lf, Rs_old %lf, M_old %d\n", + // i, saturation[i * (n_phases - 1)], saturation[i * (n_phases - 1) + 1], + // pressure[i], gas_oil_ratio[i], main_variable[i]); + // printf ("\tdSw %lf, dSg %lf, dP %lf, dRs %lf\n", + // x_sol[i * n_phases], + // (main_variable[i] == FI_SG_VAR) ? x_sol[i * n_phases + 1] : 0, + // x_sol[i * n_phases + 2], + // (main_variable[i] != FI_SG_VAR) ? x_sol[i * n_phases + 1] : 0); + // } +#endif +#if 1 + if (fabs (x_sol[jj]) > max_rs) + { + t_mult = max_rs / fabs (x_sol[jj]); + IF_LE_REPLACE (mult, t_mult, condition, 3); + } + if (gas_oil_ratio[i] + x_sol[jj] < 0) + { + t_mult = gas_oil_ratio[i] / (-x_sol[jj]); + IF_LE_REPLACE (mult, t_mult, condition, 4); + } +#endif //0 + } + } +#endif + // check pressure +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + index_t jj = (i + 1 - n_left) * n_phases - 1; +#else //_MPI + index_t jj = (i + 1) * n_phases - 1; +#endif //_MPI + d = pressure[i] + x_sol[jj]; + if (d < minimal_pressure) + { +#ifdef _DEBUG + //printf ("MIN P %d %lf %lf\n", i, pressure[i], x_sol[jj]); +#endif + t_mult = (pressure[i] - minimal_pressure) / (-x_sol[jj]); + IF_LE_REPLACE (mult, t_mult, condition, 5); + } + if (maximal_pressure < d) + { + t_mult = (pressure[i] - maximal_pressure + 5) / (-x_sol[jj]); + IF_LE_REPLACE (mult, t_mult, condition, 7); + } + if (fabs (x_sol[jj]) > max_p) + { + t_mult = max_p / fabs (x_sol[jj]); + IF_LE_REPLACE (mult, t_mult, condition, 6); + } + } +#ifdef _MPI + if (!mpi_decomp->get_proc_num ()) +#endif +#ifdef _DEBUG + //BOSOUT (section::iters, level::debug) << boost::format ("MULT CONDITION %d") % condition << bs_end; +#endif + return mult; + } + + /** + * @brief calculate multiplier (m) for newton correction vector (J(x0) * w = -F(x0), x1 = x0 + m * w) + * + * @return multiplier (m) + */ + template + typename calc_model::item_t + calc_model::new_simple_get_cell_solution_mult (const sp_mesh_iface_t &msh, + const sp_jacobian_matrix_t &jacobian) + { + BS_ASSERT (msh); + BS_ASSERT (jacobian); + + BS_ASSERT (pressure.size ()); + + if (n_phases > 1) + { + BS_ASSERT (saturation_3p.size ()); + } + + const item_t max_p = (item_t) ts_params->get_float (fi_params::MAX_P_CORRECTION); + const item_t max_s = (item_t) ts_params->get_float (fi_params::MAX_S_CORRECTION); + const item_t minimal_pressure = (item_t) ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MIN); + const item_t maximal_pressure = (item_t) ts_params->get_float (fi_params::PVT_PRESSURE_RANGE_MAX); + const item_t max_rs = (item_t) ts_params->get_float (fi_params::MAX_RS_CORRECTION); + + const index_t is_w = (index_t) FI_CHK_WATER (phases); + const index_t is_o = (index_t) FI_CHK_OIL (phases); + const index_t is_g = (index_t) FI_CHK_GAS (phases); + + const index_t d_w = (index_t) phase_d[FI_PHASE_WATER]; + const index_t d_g = (index_t) phase_d[FI_PHASE_GAS]; + const index_t d_o = (index_t) phase_d[FI_PHASE_OIL]; + + item_t mult = 1.0; + index_t n = msh->get_n_active_elements (); + const item_array_t &x_sol = jacobian->get_solution (); + const item_array_t &sec_sol = jacobian->get_sec_solution (); + +#ifdef _MPI + BS_ASSERT (false && "NOT IMPL YET"); + index_t n_left = 0;/// = mpi_decomp->get_recv_l (); + index_t n_right = n;/// = msh->n_elements - mpi_decomp->get_recv_r (); +#else + index_t n_left = 0; + index_t n_right = n; +#endif //_MPI + + // calc only internal cells + for (index_t i = n_left; i < n_right; ++i) + { + item_t dsw = 0; + item_t dpo = 0; + item_t dsg = 0; + item_t dro = 0; + item_t dso = 0; + + index_t jj = (i - n_left); + if (n_phases == 3) + { + dsw = sec_sol[jj]; + dpo = x_sol[jj * n_phases + p3_po]; + dsg = 0; + dro = 0; + dso = 0; + if (main_variable[i] == FI_SG_VAR) + { + dsg = x_sol[jj * n_phases + p3_sg]; + dso = x_sol[jj * n_phases + p3_so]; + } + else if (main_variable[i] == FI_RO_VAR) + { + dro = x_sol[jj * n_phases + p3_sg]; + dso = x_sol[jj * n_phases + p3_so]; + } + CHECK_VALUE (saturation_3p[i * n_phases + d_w], dsw, -0.1f, 1.1f, max_s, mult); + CHECK_VALUE (pressure[i], dpo, minimal_pressure, maximal_pressure, max_p, mult); + CHECK_VALUE (saturation_3p[i * n_phases + d_g], dsg, -0.1f, 1.1f, max_s, mult); + CHECK_VALUE (saturation_3p[i * n_phases + d_o], dso, -0.1f, 1.1f, max_s, mult); + CHECK_VALUE (gas_oil_ratio[i], dro, 0, 10000000, max_rs, mult); + } + else if (is_w && is_o) + { + dsw = sec_sol[jj]; + dso = x_sol[jj * n_phases + p2ow_so]; + dpo = x_sol[jj * n_phases + p2ow_po]; + + CHECK_VALUE (saturation_3p[i * n_phases + d_w], dsw, -0.1f, 1.1f, max_s, mult); + CHECK_VALUE (saturation_3p[i * n_phases + d_o], dso, -0.1f, 1.1f, max_s, mult); + CHECK_VALUE (pressure[i], dpo, minimal_pressure, maximal_pressure, max_p, mult); + } + else if (is_g && is_o) + { + dpo = x_sol[jj * n_phases + p2og_po]; + dsg = 0; + dro = 0; + dso = 0; + if (main_variable[i] == FI_SG_VAR) + { + dso = sec_sol[jj]; + dsg = x_sol[jj * n_phases + p2og_sg]; + } + else if (main_variable[i] == FI_RO_VAR) + { + dso = sec_sol[jj]; + dro = x_sol[jj * n_phases + p2og_sg]; + } + CHECK_VALUE (pressure[i], dpo, minimal_pressure, maximal_pressure, max_p, mult); + CHECK_VALUE (saturation_3p[i * n_phases + d_g], dsg, -0.1f, 1.1f, max_s, mult); + CHECK_VALUE (saturation_3p[i * n_phases + d_o], dso, -0.1f, 1.1f, max_s, mult); + CHECK_VALUE (gas_oil_ratio[i], dro, 0, 10000000, max_rs, mult); + } + else + { + dpo = x_sol[jj]; + + CHECK_VALUE (pressure[i], dpo, minimal_pressure, maximal_pressure, max_p, mult); + } + } + return mult; + return 1.0;//mult; + } + + //! new get solution from jacobian + /** + * @brief restore solution from Jacobian, using #mult if #istart_linear_search != 0 + * + * @param mult -- x^n = x^(n-1) + mult * dx + * @param istart_linear_search -- use mult if != 0 + * + * @return 0 if success + */ + template + int + calc_model::new_simple_get_cell_solution (const double mult, int istart_linear_search, + const sp_mesh_iface_t &msh, + const sp_jacobian_matrix_t &jacobian) + { + BS_ASSERT (msh); + BS_ASSERT (jacobian); + + BS_ASSERT (pressure.size ()); + if (n_phases > 1) + { + BS_ASSERT (saturation_3p.size ()); + } + + const int is_w = FI_CHK_WATER (phases); + const int is_o = FI_CHK_OIL (phases); + const int is_g = FI_CHK_GAS (phases); + //const int is_oil_gas = FI_CHK_OIL_GAS (phases); + + const int d_w = phase_d[FI_PHASE_WATER]; + const int d_g = phase_d[FI_PHASE_GAS]; + const int d_o = phase_d[FI_PHASE_OIL]; + + const double minimal_pressure = ts_params->get_float_d (fi_params::PVT_PRESSURE_RANGE_MIN); + const double maximal_pressure = ts_params->get_float_d (fi_params::PVT_PRESSURE_RANGE_MAX); + const double max_p = ts_params->get_float_d (fi_params::MAX_P_CORRECTION); + //const double max_s = ts_params->get_float_d (fi_params::MAX_S_CORRECTION); + //const double max_rs = ts_params->get_float_d (fi_params::MAX_RS_CORRECTION); + //const int clamp_pres = ts_params->get_bool_d (fi_params::CLAMP_PRESSURE); + //const double appl_perc = ts_params->get_float_d (fi_params::APPL_CHOP_PERC); + //const double appl_bnd = ts_params->get_float_d (fi_params::APPL_CHOP_BND); + + item_t *sol_pressure = 0; + item_t *sol_saturation_3p = 0; + item_t *sol_gas_oil_ratio = 0; + main_var_type *sol_main_variable = 0; + + if (!istart_linear_search) + { + sol_pressure = &pressure[0]; + sol_main_variable = &main_variable[0]; + + if (n_phases>1) + { + sol_saturation_3p = &saturation_3p[0]; + if (is_g) + { + sol_gas_oil_ratio = &gas_oil_ratio[0]; + } + } + } + else + { +#ifdef _DEBUG + BOSOUT (section::iters, level::debug) << ("istart_linear_search") << bs_end; +#endif + sol_pressure = &prev_niter_data_.pressure[0]; + sol_main_variable = &prev_niter_data_.main_var[0]; + + if (n_phases>1) + { + sol_saturation_3p = &prev_niter_data_.saturation_3p[0]; + if (is_g) + { + sol_gas_oil_ratio = &prev_niter_data_.gas_oil_ratio[0]; + } + } + } + + index_t n = msh->get_n_active_elements (); + const item_array_t &x_sol = jacobian->get_solution (); + const item_array_t &sec_sol = jacobian->get_sec_solution (); + +#ifdef _MPI + BS_ASSERT (false && "MPI: NOT IMPL YET"); + index_t n_left = 0;/// = mpi_decomp->get_recv_l (); + index_t n_right = n;/// = msh->n_elements - mpi_decomp->get_recv_r (); +#else + index_t n_left = 0; + index_t n_right = n; +#endif //_MPI + + // calc only internal cells + for (index_t i = n_left; i < n_right; ++i) + { + item_t dsw = 0; + item_t dpo = 0; + item_t dsg = 0; + item_t dro = 0; + item_t dso = 0; + + index_t jj = (i - n_left); + if (n_phases == 3) + { + dsw = sec_sol[jj]; + dpo = x_sol[jj * n_phases + p3_po]; + dsg = 0; + dro = 0; + dso = 0; + if (sol_main_variable[i] == FI_SG_VAR) + { + dsg = x_sol[jj * n_phases + p3_sg]; + dso = x_sol[jj * n_phases + p3_so]; + } + else if (sol_main_variable[i] == FI_RO_VAR) + { + dro = x_sol[jj * n_phases + p3_sg]; + dso = x_sol[jj * n_phases + p3_so]; + } + else if (sol_main_variable[i] == FI_MOMG_VAR) + { + calc_approx_so_sg_ro (x_sol[jj * n_phases + p3_so], + x_sol[jj * n_phases + p3_sg], + data[i].porosity, data[i].invers_fvf[d_o], + data[i].invers_fvf[d_g], sol_gas_oil_ratio[i], + dso, dsg, + dro, main_variable[i]); + } + + saturation_3p[i * n_phases + d_w] = sol_saturation_3p[i * n_phases + d_w] + dsw * mult; + saturation_3p[i * n_phases + d_o] = sol_saturation_3p[i * n_phases + d_o] + dso * mult; + saturation_3p[i * n_phases + d_g] = sol_saturation_3p[i * n_phases + d_g] + dsg * mult; + + if (saturation_3p[i * n_phases + d_w] < 0) + saturation_3p[i * n_phases + d_w] = 0; + if (saturation_3p[i * n_phases + d_w] > 1) + saturation_3p[i * n_phases + d_w] = 1; + if (saturation_3p[i * n_phases + d_o] < 0) + saturation_3p[i * n_phases + d_o] = 0; + if (saturation_3p[i * n_phases + d_o] > 1) + saturation_3p[i * n_phases + d_o] = 1; + + //int fix_soil_bug = this->ts_params->get_bool(fi_params::FIX_SOIL_BUG); + //if (fix_soil_bug) + // { + // if (fabs (saturation_3p[i * n_phases + d_o]) < EPS_DIFF) + // { + // saturation_3p[i * n_phases + d_o] = 1.0 - 0.001; + // } + // } + + if (saturation_3p[i * n_phases + d_g] > 1) + saturation_3p[i * n_phases + d_g] = 1; + + gas_oil_ratio[i] = sol_gas_oil_ratio[i] + dro * mult; + if (gas_oil_ratio[i] < 0) + gas_oil_ratio[i] = 0; + +#ifdef _DEBUG + if (main_variable[i] != sol_main_variable[i]) + { + BOSOUT (section::iters, level::debug) << boost::format ("restore main_var {%d} [%d] -> [%d] (ro == %d)") % i % main_variable[i] % sol_main_variable[i] % FI_RO_VAR << bs_end; + } + else + { + //BOSOUT (section::iters, level::debug) << boost::format ("keep main_var {%d} [%d] -> [%d] (ro == %d)") % i % main_variable[i] % sol_main_variable[i] % FI_RO_VAR << bs_end; + } +#endif + main_variable[i] = sol_main_variable[i]; + } + else if (is_w && is_o) + { + dsw = sec_sol[jj]; + dso = x_sol[jj * n_phases + p2ow_so]; + dpo = x_sol[jj * n_phases + p2ow_po]; + + saturation_3p[i * n_phases + d_w] = sol_saturation_3p[i * n_phases + d_w] + + dsw * mult; + saturation_3p[i * n_phases + d_o] = sol_saturation_3p[i * n_phases + d_o] + + dso * mult; + + if (saturation_3p[i * n_phases + d_w] < 0) + saturation_3p[i * n_phases + d_w] = 0; + if (saturation_3p[i * n_phases + d_w] > 1) + saturation_3p[i * n_phases + d_w] = 1; + if (saturation_3p[i * n_phases + d_o] < 0) + saturation_3p[i * n_phases + d_o] = 0; + if (saturation_3p[i * n_phases + d_o] > 1) + saturation_3p[i * n_phases + d_o] = 1; + } + else if (is_g && is_o) + { + dpo = x_sol[jj * n_phases + p2og_po]; + dsg = 0; + dro = 0; + dso = 0; + if (sol_main_variable[i] == FI_SG_VAR) + { + dsg = x_sol[jj * n_phases + p2og_sg]; + dso = sec_sol[jj]; + } + else if (sol_main_variable[i] == FI_RO_VAR) + { + dro = x_sol[jj * n_phases + p2og_sg]; + dso = sec_sol[jj]; + } + else if (sol_main_variable[i] == FI_MOMG_VAR) + { + calc_approx_so_sg_ro (sec_sol[jj], + x_sol[jj * n_phases + p2og_sg], + data[i].porosity, data[i].invers_fvf[d_o], + data[i].invers_fvf[d_g], sol_gas_oil_ratio [i], + dso, dsg, + dro, main_variable[i]); + } + saturation_3p[i * n_phases + d_o] = sol_saturation_3p[i * n_phases + d_o] + + dso * mult; + saturation_3p[i * n_phases + d_g] = sol_saturation_3p[i * n_phases + d_g] + + dsg * mult; + if (saturation_3p[i * n_phases + d_o] < 0) + saturation_3p[i * n_phases + d_o] = 0; + if (saturation_3p[i * n_phases + d_o] > 1) + saturation_3p[i * n_phases + d_o] = 1; + if (saturation_3p[i * n_phases + d_g] > 1) + saturation_3p[i * n_phases + d_g] = 1; + + gas_oil_ratio[i] = sol_gas_oil_ratio[i] + dro * mult; + if (gas_oil_ratio[i] < 0) + gas_oil_ratio[i] = 0; + } + else + { + dpo = x_sol[jj]; + } + +#ifdef _DEBUG + //BOSOUT (section::iters, level::debug) << "pressure_mult: " << mult << bs_end; + //BOSOUT (section::iters, level::debug) << "pressure_dpo_mult: " << dpo * mult << bs_end; +#endif + + item_t dpo_mult = dpo * mult; + if (dpo_mult > max_p) + dpo_mult = max_p; + else if (dpo_mult < -max_p) + dpo_mult = -max_p; + + pressure[i] = sol_pressure[i] + dpo_mult; + if (pressure[i] > maximal_pressure) + pressure[i] = maximal_pressure - 5; + if (pressure[i] < minimal_pressure) + pressure[i] = minimal_pressure + 5; + } + + //static int iter_counter = 0; + //iter_counter++; + //tools::save_seq_vector (tools::string_formater ("sat_3p.s.bs.%d.txt", iter_counter).str).save (saturation_3p); + return 0; + } + + //! calculate approximal value of So, Sg, Ro from full mass of gas (mg_in) and oil (mo_in) + template + int + calc_model::calc_approx_so_sg_ro (const item_t mo_in, const item_t mg_in, const item_t poro, + const item_t ifvf_o, const item_t ifvf_g, const item_t max_ro, + // results + item_t &so, item_t &sg, item_t &ro, + main_var_type &m_var) + { + double d; + const double delta_mo = 1.0e-5; + const double delta_mg = 1.0e-5; + double mo, mg; + + if (poro > EPS_DIV) + { + mo = mo_in / poro; + mg = mg_in / poro; + } + else + { + mo = 0; + mg = 0; + } + + if (mo > delta_mo && mg > delta_mg) + { + // step 1: calculate So + if (ifvf_o > EPS_DIV) + so = mo / ifvf_o; + else + so = (item_t) 0.1; + + // step 2: calculate Sg, Ro + d = mg / mo; + if (d > max_ro) + { + // Sg > 0 + if (ifvf_g > EPS_DIV) + sg = (mg - mo * max_ro) / ifvf_g; + else + sg = (item_t) 0.1; + + m_var = FI_SG_VAR; + ro = max_ro; + } + else + { + m_var = FI_RO_VAR; + sg = 0; + ro = d; + } + } + else if (mo > delta_mo) + { + // step 1: calculate So + if (ifvf_o > EPS_DIV) + so = mo / ifvf_o; + else + so = (item_t) 0.1; + + m_var = FI_RO_VAR; + sg = 0; + ro = 0; + } + else if (mg > delta_mg) + { + // step 1: calculate So + if (ifvf_g > EPS_DIV) + sg = mg / ifvf_g; + else + sg = (item_t) 0.1; + + m_var = FI_SG_VAR; + so = 0; + ro = max_ro; + } + return 0; + } + + template + bool + calc_model ::is_water () const + { + return FI_CHK_WATER (phases); + } + template + bool + calc_model ::is_gas () const + { + return FI_CHK_GAS (phases); + } + template + bool + calc_model ::is_oil () const + { + return FI_CHK_OIL (phases); + } + template + typename calc_model::index_t + calc_model ::water_shift () const + { + return phase_d[FI_PHASE_WATER]; + } + template + typename calc_model::index_t + calc_model ::gas_shift () const + { + return phase_d[FI_PHASE_GAS]; + } + template + typename calc_model::index_t + calc_model ::oil_shift () const + { + return phase_d[FI_PHASE_OIL]; + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF(calc_model, (class)); //(class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(calc_model, (class)); //(class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (calc_model) , 1, (bs_node), "calc_model_fi", "calc_model_base-float-int", "Calc_model_base with float items and integer indexes", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (calc_model) , 1, (bs_node), "calc_model_di", "calc_model_base-double-int", "Calc_model_base with double items and integer indexes", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (calc_model) , 1, (bs_node), "calc_model_mixi", "calc_model_base-mix-int", "Calc_model_base with double items and integer indexes", false); +} diff --git a/bs_bos_core/src/calc_model_data_tmp_holder.cpp b/bs_bos_core/src/calc_model_data_tmp_holder.cpp new file mode 100644 index 0000000..255559e --- /dev/null +++ b/bs_bos_core/src/calc_model_data_tmp_holder.cpp @@ -0,0 +1,47 @@ +/** + * + * */ +#include "stdafx.h" +#include "calc_model.h" + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +namespace blue_sky + { + + template + void + calc_model_data_tmp_holder::save (const sp_calc_model_t &cm) + { + pressure.assign (cm->pressure.begin (), cm->pressure.end ()); + saturation_3p.assign (cm->saturation_3p.begin (), cm->saturation_3p.end ()); + + if (cm->is_gas ()) + { + gas_oil_ratio.assign (cm->gas_oil_ratio.begin (), cm->gas_oil_ratio.end ()); + main_var.assign (cm->main_variable.begin (), cm->main_variable.end ()); + } + } + + template + void + calc_model_data_tmp_holder::restore (sp_calc_model_t &cm) + { + cm->pressure.assign (pressure.begin (), pressure.end ()); + cm->saturation_3p.assign (saturation_3p.begin (), saturation_3p.end ()); + + if (cm->is_gas ()) + { + cm->gas_oil_ratio.assign (gas_oil_ratio.begin (), gas_oil_ratio.end ()); + cm->main_variable.assign (main_var.begin (), main_var.end ()); + } + } + + template struct calc_model_data_tmp_holder; + template struct calc_model_data_tmp_holder; + template struct calc_model_data_tmp_holder; + +} // namespace blue_sky + diff --git a/bs_bos_core/src/calc_perf_bhp.cpp b/bs_bos_core/src/calc_perf_bhp.cpp new file mode 100644 index 0000000..f3c2af2 --- /dev/null +++ b/bs_bos_core/src/calc_perf_bhp.cpp @@ -0,0 +1,101 @@ +/** + * \file calc_perf_bhp.h + * \brief impl of + * \author Sergey Miryanov + * \date 18.11.2008 + * */ +#include "stdafx.h" + +#include "calc_perf_bhp.h" +#include "calc_model.h" +#include "calc_well.h" +#include "well_connection.h" +#include "reservoir.h" +#include "facility_manager.h" + +namespace blue_sky + { + + template + calc_perf_bhp ::calc_perf_bhp(bs_type_ctor_param /*param = NULL */) + { + + } + template + calc_perf_bhp::calc_perf_bhp(const calc_perf_bhp & /*x*/) + : bs_refcounter () + { + + } + + template + void + calc_perf_bhp ::calculate (sp_well_t &well, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) const + { + BS_ASSERT (!well->is_shut ()) (well->name ()); + + typedef typename base_t::well_t::connection_t connection_t; + typedef typename base_t::well_t::sp_connection_t sp_connection_t; + typedef typename base_t::calc_model_t::sat_d_t sat_d_t; + typedef typename base_t::calc_model_t::phase_d_t phase_d_t; + typedef typename base_t::calc_model_t::data_t calc_model_data_t; + + if (well->get_connections_count () == 0) + { + BOSOUT (section::wells, level::debug) + << "[" << well->name () << "] calc_perf_bhp: connection list is empty" + << bs_end; + + return ; + } + + item_t gravity = calc_model->internal_constants.gravity_constant; + item_t ptop = well->bhp (); + item_t dtop = well->get_reference_depth (mesh); + + BOSOUT (section::wells, level::low) + << "[" << well->name () << "] calc_perf_bhp: ptop: " + << ptop + << " dtop: " << dtop << bs_end; + + sp_connection_t prev_connection; + const typename base_t::calc_model_t::item_array_t &pressure = calc_model->pressure; + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (well->get_connection (i)); + + if (!c->is_shut ()) + { + if (prev_connection) + { + c->set_head_term (prev_connection->head_term + 0.5 * (prev_connection->density + c->density) * gravity * (c->connection_depth - prev_connection->connection_depth)); + } + else + { + c->set_head_term (c->density * gravity * (c->connection_depth - dtop)); + } + c->set_cur_bhp (ptop + c->head_term); + c->set_bulkp (pressure[c->n_block ()]); +#ifdef _DEBUG + BOSOUT (section::wells, level::low) + << "[" << well->name () << " : " << c->n_block () << "] calc_perf_bhp: density: " + << c->density + << " connection_depth: " << c->connection_depth + << " head_term: " << c->head_term + << " cur_bhp: " << c->cur_bhp + << bs_end; +#endif + } + + prev_connection = c; + } + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (calc_perf_bhp, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (calc_perf_bhp, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_perf_bhp ), 1, (objbase), "calc_perf_bhp_fi", "calc_perf_bhp_fi", "calc_perf_bhp_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_perf_bhp ), 1, (objbase), "calc_perf_bhp_di", "calc_perf_bhp_di", "calc_perf_bhp_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_perf_bhp ), 1, (objbase), "calc_perf_bhp_mixi", "calc_perf_bhp_mixi", "calc_perf_bhp_mixi", false); + +} // namespace blue_sky + diff --git a/bs_bos_core/src/calc_rho.cpp b/bs_bos_core/src/calc_rho.cpp new file mode 100644 index 0000000..0c5428c --- /dev/null +++ b/bs_bos_core/src/calc_rho.cpp @@ -0,0 +1,113 @@ +/** + * + * */ +#include "stdafx.h" + +#include "calc_rho.h" +#include "calc_model.h" +#include "calc_well.h" +#include "well_connection.h" +#include "calc_model_data_accessors.h" +#include "reservoir.h" +#include "facility_manager.h" + +namespace blue_sky + { + + template + calc_total_average_rho ::calc_total_average_rho (bs_type_ctor_param /* param = NULL */) + { + } + + template + calc_total_average_rho ::calc_total_average_rho (const calc_total_average_rho &rhs) + : bs_refcounter () + { + *this = rhs; + } + + template + void + calc_total_average_rho::calculate (const sp_well_t &well, const sp_calc_model_t &calc_model, + const sp_mesh_iface_t & /*mesh*/) const + { + BS_ASSERT (!well->is_shut ()) (well->name ()); + BS_ASSERT (well->get_connections_count ()) (well->name ()); + + typedef typename well_t::connection_t connection_t; + typedef typename well_t::sp_connection_t sp_connection_t; + typedef typename calc_model_t::data_t calc_model_data_t; + typedef typename calc_model_t::phase_d_t phase_d_t; + + const phase_d_t &phase_d = calc_model->phase_d; + const item_array_t &saturation = calc_model->saturation_3p; + + bool is_w = calc_model->is_water (); + bool is_g = calc_model->is_gas (); + bool is_o = calc_model->is_oil (); + + item_t rhop_satp = 0; + item_t sat = 0; + + index_t i_w = phase_d[FI_PHASE_WATER]; + index_t i_g = phase_d[FI_PHASE_GAS]; + index_t i_o = phase_d[FI_PHASE_OIL]; + + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c = well->get_connection (i); + if (c->is_shut ()) + continue; + + index_t n_block = c->n_block (); + const calc_model_data_t &data = calc_model->get_data (n_block); + + if (is_w) + { + rhop_satp += DENSITY (data, phase_d, FI_PHASE_WATER) * saturation[i_w]; + sat += saturation[i_w]; + } + if (is_g) + { + rhop_satp += DENSITY (data, phase_d, FI_PHASE_GAS) * saturation[i_g]; + sat += saturation[i_g]; + } + if (is_o) + { + rhop_satp += DENSITY (data, phase_d, FI_PHASE_OIL) * saturation[i_o]; + sat += saturation[i_o]; + } + } + + BS_ASSERT (sat != 0); + item_t rho = rhop_satp / sat; + + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (well->get_connection (i)); + if (!c->is_shut ()) + c->density = rho; + } + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (calc_total_average_rho, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (calc_total_average_rho, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_total_average_rho), 1, (objbase), "calc_total_average_fi", "calc_total_average_fi", "calc_total_average_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_total_average_rho), 1, (objbase), "calc_total_average_di", "calc_total_average_di", "calc_total_average_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_total_average_rho), 1, (objbase), "calc_total_average_mixi", "calc_total_average_mixi", "calc_total_average_mixi", false); + + bool + calc_rho_register_types (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, calc_total_average_rho ::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, calc_total_average_rho ::bs_type ()); + BS_ASSERT (res); + + return res; + } + +} // namespace blue_sky + diff --git a/bs_bos_core/src/calc_well.cpp b/bs_bos_core/src/calc_well.cpp new file mode 100644 index 0000000..8934a1d --- /dev/null +++ b/bs_bos_core/src/calc_well.cpp @@ -0,0 +1,712 @@ +/** + * \file calc_well.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 23.06.2008 + * */ +#include "stdafx.h" +#include "calc_well.h" + +#include "well_connection.h" +#include "well_controller.h" + +#include "calc_model.h" + +#include "calc_model_type_helper.h" + +#include "reservoir.h" +#include "facility_manager.h" + +#include "matrix_inverse.h" + +#include "calc_well_pressure.h" +#include "calc_rho.h" +#include "wellbore_density_calc.h" +#include "calc_perf_bhp.h" + +#include "well_rate_control.h" + +#include "exp_temp_mx.h" +#include "apply_wefac.h" +#include "default_rr_eliminator.h" + +namespace blue_sky + { + + /////////////////////////////////////////////////////////////////////////// + well_state_type + well_state_cast (const std::string &str) + { + if (str == "OPEN") + return well_open; + else if (str == "SHUT") + return well_shut; + else if (str == "") + return well_shut; + else + { + BS_ASSERT (false && "Unsupported value of well state") (str); + throw bs_exception ("well_state_cast", "Unsupported value of well state"); + } + } + /////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////// + template + well::~well () + { + + } + + template + well::well (bs_type_ctor_param /*param = NULL */) + : calc_well_pressure_ (BS_KERNEL.create_object (calc_well_pressure ::bs_type (), true)) + , calc_rho_ (BS_KERNEL.create_object (calc_total_average_rho ::bs_type (), true)) + , calc_perf_density_ (BS_KERNEL.create_object (wellbore_density_calc ::bs_type (), true)) + , calc_perf_bhp_ (BS_KERNEL.create_object (calc_perf_bhp ::bs_type (), true)) + { + clear_data (); + bhp_ = 0; + } + + template + well ::well (const std::string &well_name) + : calc_well_pressure_ (BS_KERNEL.create_object (calc_well_pressure ::bs_type (), true)) + , calc_rho_ (BS_KERNEL.create_object (calc_total_average_rho ::bs_type (), true)) + , calc_perf_density_ (BS_KERNEL.create_object (wellbore_density_calc ::bs_type (), true)) + , calc_perf_bhp_ (BS_KERNEL.create_object (calc_perf_bhp ::bs_type (), true)) + { + set_name (well_name); + + clear_data (); + bhp_ = 0; + } + + template + well::well (const well &w) + : bs_refcounter () + { + *this = w; + } + + //namespace wells { + + // template + // struct sort_connection_list : std::binary_function , true> &, const smart_ptr , true> &, bool> + // { + // bool + // operator () (const smart_ptr , true> &lhs, const smart_ptr , true> &rhs) const + // { + // return lhs->n_block () < rhs->n_block (); + // } + // }; + //} // namespace wells + + //template + //void + //well::add_connection (const sp_connection_t &connection) + //{ + // if (connection->n_block () < 0) + // throw bs_exception ("well::add_connection", "invalid connection n_block value"); + + // connection_list_.push_back (connection); + // std::sort (connection_list_.begin (), connection_list_.end (), wells::sort_connection_list ()); + // connection_map_.insert (std::make_pair (connection->n_block (), (index_t)connection_list_.size () - 1)); + //} + + template + array_ext + well ::get_ww_value () + { + return array_ext (0, 0); + } + template + array_ext + well ::get_bw_value () + { + return array_ext (0, 0); + } + + template + const std::string & + well ::name () const + { + return name_; + } + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + template + void + well::set_coord (index_t i_coord, index_t j_coord) + { + i_coord_ = i_coord; + j_coord_ = j_coord; + } + template + void + well::set_bhp_depth (item_t bhp_depth) + { + bhp_depth_ = bhp_depth; + } + template + void + well::set_state (well_state_type state, const sp_calc_model_t &calc_model) + { + well_state_.state = state; + if (state == well_shut) + { + rate_ = 0; + shut_well (calc_model); + } + +#ifdef _DEBUG + if (state == well_shut) + { + BOSOUT (section::wells, level::debug) << "[" << name () << "] " << "well shut" << bs_end; + } + else + { + BOSOUT (section::wells, level::debug) << "[" << name () << "] " << "well open" << bs_end; + } +#endif + + check_shut (calc_model); + } + template + void + well::set_exploitation_factor (item_t exploitation_factor) + { + exploitation_factor_ = exploitation_factor; + } + + template + void + well::set_controller (sp_well_controller_t controller) + { + well_controller_ = controller; + } + template + void + well::set_limit_operation (sp_well_limit_operation_t limit_operation) + { + well_limit_operation_ = limit_operation; + } + template + typename well::sp_well_controller_t + well::get_controller () const + { + return well_controller_; + } + template + typename well::sp_well_limit_operation_t + well::get_limit_operation () const + { + return well_limit_operation_; + } +#if 0 + template + typename well::ijk_filter_t + well::filter_connections (index_t /*i_coord*/, index_t /*j_coord*/, index_t /*k*/, + index_t /*z1*/, index_t /*z2*/) + { + return ijk_filter_t (connection_list_, ijk_pred_t (0)); // TODO: + } + template + typename well::ijk1k2_filter_t + well::filter_connections (index_t /*i_coord*/, index_t /*j_coord*/, index_t /*kw1*/, + index_t /*kw2*/) + { + return ijk1k2_filter_t (connection_list_, ijk1k2_pred_t (0)); // TODO: + } +#endif //0 + template + const std::string & + well::get_name () const + { + return name_; + } + template + void + well::set_name (const std::string &name) + { + name_ = name; + } + +// template +// typename well ::sp_connection_t +// well ::get_connection (index_t n_block) const +// { +// typename connection_map_t::const_iterator it = connection_map_.find (n_block); +// if (it == connection_map_.end ()) +// return 0; +// +// if (it->second >= (int)connection_list_.size ()) +// { +//#ifdef _DEBUG +// typename connection_map_t::const_iterator i = connection_map_.begin (), e = connection_map_.end (); +// for (; i != e; ++i) +// { +// BOSOUT (section::wells, level::debug) << boost::format ("[%d: %d]") % i->first % i->second << bs_end; +// } +//#endif +// bs_throw_exception (boost::format ("Connection map has an invalid value ([%s]: %d - %d, %d, %d)") % name_ % n_block % it->second % connection_list_.size () % connection_map_.size ()); +// } +// +// return connection_list_[it->second]; +// } + + template + void + well::compute_connection_factor (const physical_constants &internal_constants, + const sp_params_t ¶ms, + const sp_mesh_iface_t &mesh, + const item_array_t &perm, + const item_array_t &ntg, + bool ro_calc_flag) + { + BS_ASSERT (get_connections_count ()) (name ()); + + for (size_t i = 0, cnt = get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (get_connection (i)); + + if (!c->is_shut ()) + c->compute_factors (internal_constants, params, mesh, perm, ntg, ro_calc_flag); + } + } + + template + bool + well::fi_check_limits () const + { + BS_ASSERT (well_limit_operation_); + if (!well_limit_operation_) + { + return false; + //throw bs_exception ("well::fi_check_limits", "well_limit_operation is null"); + } + + return well_limit_operation_->fi_check_limits (); + } + + template + bool + well ::check_connections_bhp (const item_array_t &pressure) const + { + BS_ASSERT (!is_shut ()) (name ()); + if (get_connections_count () == 0) + { + BOSOUT (section::wells, level::debug) + << "[" << name_ << "] check_connections_bhp: connection list is empty" + << bs_end; + + return false; + } + + for (size_t i = 0, cnt = get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (get_connection (i)); + if (c->is_shut ()) + continue; + +#ifdef _DEBUG + index_t n_block = c->n_block (); + BOSOUT (section::wells, level::debug) << "[" << name_ << ": " << n_block << "] " << "bulkp: " << c->bulkp << " cur_bhp: " << c->cur_bhp << bs_end; +#endif + if (well_controller_->is_valid_connection_bhp (c->bulkp, c->cur_bhp)) + { + BOSOUT (section::wells, level::low) << "[" << name_ << "] " << " (work)" << bs_end; + return true; + } + } + + BOSOUT (section::wells, level::low) << "[" << name_ << "] " << " (doesn't work)" << bs_end; + return false; + } + + template + void + well::shut_well (const sp_calc_model_t &calc_model) + { +#ifdef _DEBUG + BOSOUT (section::wells, level::debug) << boost::format ("[%s]: shut") % name () << bs_end; +#endif + + well_state_.state = well_shut; + rate_ = 0; + + const item_array_t &pressure = calc_model->pressure; + for (size_t i = 0, cnt = get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (get_connection (i)); + index_t n_block = c->n_block (); + item_t bulkp = pressure[n_block]; + + c->set_cur_bhp (bulkp); + c->set_bulkp (bulkp); + } + } + + template + bool + well ::check_shut (const sp_calc_model_t &/*calc_model*/) + { + open_connections_.clear (); + open_connections_.reserve (get_connections_count ()); + if (is_shut ()) + { + return true; + } + + for (index_t i = 0, cnt = (index_t)get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (get_connection (i)); + + if (!c->is_shut ()) + { + open_connections_.push_back (i); + } + } + + return false; + } + + template + bool + well ::is_shut () const + { + return well_state_.state == well_shut; + } + + template + typename well::item_t + well::get_reference_depth (const sp_mesh_iface_t &mesh) const + { + BS_ASSERT (get_connections_count ()) (name ()); + + wells::connection_direction_type dir = get_connection (0)->get_dir (); + item_t dtop = 0; + if (dir == wells::direction_x || dir == wells::direction_y) + { + dtop = get_connection (0)->get_connection_depth (); + } + else + { + dtop = mesh->get_element_dtop (get_connection (0)->n_block ()); + } + + return input_reference_depth_ > 0 ? input_reference_depth_ : dtop; + } + + template + typename well::item_t + well::get_reference_pressure () const + { + return bhp_; + } + + template + void + well::set_bhp (item_t bhp) + { + bhp_ = bhp; + } + + template + bool + well::is_bhp () const + { + BS_ASSERT (well_controller_); + return well_controller_->is_bhp (); + } + template + bool + well::is_rate () const + { + BS_ASSERT (well_controller_); + return well_controller_->is_rate (); + } + + template + const typename well::sp_well_controller_t & + well::get_well_controller () const + { + return well_controller_; + } + + ////////////////////////////////////////////////////////////////////////// + + template + typename well::item_t + well ::get_input_rate () const + { + BS_ASSERT (well_controller_); + using namespace wells; + rate_control_type control_type = well_controller_->get_control_type (); + injection_type inj_type = well_controller_->injection (); + bool is_prod = well_controller_->is_production (); + + if (is_prod) + { + if (control_type == liquid_rate_control) + return -well_controller_->rate_.prod.liquid; + else if (control_type == water_rate_control) + return -well_controller_->rate_.prod.water; + else if (control_type == gas_rate_control) + return -well_controller_->rate_.prod.gas; + else if (control_type == oil_rate_control) + return -well_controller_->rate_.prod.oil; + } + else + { + if (is_rate ()) + { + if (inj_type == injection_water) + return well_controller_->rate_.inj.water; + else if (inj_type == injection_gas) + return well_controller_->rate_.inj.gas; + else if (inj_type == injection_oil) + return well_controller_->rate_.inj.oil; + } + else + return 0; + } + + BS_ASSERT (false && "get_input_rate: return 0") (is_prod) (control_type) (inj_type); + return 0; + } + + template + void + well ::reset_init_approx () + { + init_approx_is_calc_ = false; + } + + template + void + well ::eliminate (rhs_item_t * /*array*/, index_t /*rw_index*/, index_t /*wr_index*/, double /*dt*/, index_t /*block_size*/) const + { + bs_throw_exception ("PURE CALL"); + } + template + void + well::process (bool /*is_start*/, double /*dt*/, const sp_calc_model_t &/*calc_model*/, const sp_mesh_iface_t &/*mesh*/, sp_jmatrix_t &/*jmatrix*/) + { + bs_throw_exception ("PURE_CALL"); + } + template + void + well ::clear_data () + { + rate_ = 0; + rate_rc_ = 0; + gor_ = 0; + } + + template + void + well ::fill_rows (index_array_t &rows) const + { + for (index_t j = 0, jcnt = (index_t)open_connections_.size (); j < jcnt; ++j) + { + index_t con_index = open_connections_[j]; + BS_ASSERT (get_connection (con_index)->is_shut () == false) (j); + index_t n_block = get_connection (con_index)->n_block (); + index_t k = rows[n_block + 1] != 0; + rows[n_block + 1] += jcnt - k; + } + } + + template + void + well ::fill_jacobian (double dt, index_t block_size, const index_array_t &rows, index_array_t &cols, rhs_item_array_t &values, index_array_t &markers) const + { + index_t b_sqr = block_size * block_size; + for (index_t j = 0, jcnt = (index_t)open_connections_.size (); j < jcnt; ++j) + { + index_t rw_index = open_connections_[j]; + BS_ASSERT (get_connection (rw_index)->is_shut () == false) (j); + + index_t n_block = get_connection (rw_index)->n_block (); + index_t l = rows[n_block]; + + if (markers[n_block] == 0) + { + markers[n_block] = 1; + } + + for (index_t k = 0, kcnt = jcnt; k < kcnt; ++k) + { + index_t index = l; + index_t wr_index = open_connections_[k]; + if (j == k) + { + BS_ASSERT (cols[l] == -1) (cols[l]) (n_block); + cols[l] = n_block; + + BS_ASSERT (l * b_sqr < (index_t)values.size ()) (l) (values.size ()); + eliminate (&values[l * b_sqr], rw_index, wr_index, dt, block_size); + } + else + { + BS_ASSERT (cols[l + markers[n_block]] == -1) (cols[l + markers[n_block]]) (get_connection (wr_index)->n_block ()); + index = l + markers[n_block]; + cols[index] = get_connection (wr_index)->n_block (); + markers[n_block]++; + + BS_ASSERT (index * b_sqr < (index_t)values.size ()) (index) (b_sqr) (values.size ()); + eliminate (&values[index * b_sqr], rw_index, wr_index, dt, block_size); + } + } + } + } + + template + void + well ::fill_rhs (double dt, index_t n_phases, bool is_g, bool is_o, bool is_w, rhs_item_array_t &rhs) const + { + item_t wefac = exploitation_factor_ > 0 ? exploitation_factor_ * dt : dt; + + for (index_t j = 0, jcnt = (index_t)open_connections_.size (); j < jcnt; ++j) + { + index_t con_index = open_connections_[j]; + BS_ASSERT (get_connection (con_index)->is_shut () == false) (j); + + const sp_connection_t &c = get_connection (con_index); + int n_block = c->n_block (); + int index = n_block * n_phases; + const array_ext &c_rate = c->get_rate_value (); + + if (n_phases == 3) + { + rhs[index + p3_gas] += wefac * c_rate[p3_gas]; + rhs[index + p3_oil] += wefac * c_rate[p3_oil]; + rhs[index + p3_wat] += wefac * c_rate[p3_wat]; + } + else if (n_phases == 2) + { + if (is_w) + { + rhs[index + p2ow_oil] += wefac * c_rate[p2ow_oil]; + rhs[index + p2ow_wat] += wefac * c_rate[p2ow_wat]; + } + else if (is_g) + { + rhs[index + p2og_gas] += wefac * c_rate[p2og_gas]; + rhs[index + p2og_oil] += wefac * c_rate[p2og_oil]; + } + } + else + { + if (is_w) + rhs[index] += wefac * c_rate[0]; + else if (is_g) + rhs[index] += wefac * c_rate[0]; + else + { + BS_ASSERT (is_o); + rhs[index] += wefac * c_rate[0]; + } + } + } + } + + template + void + well ::restore_solution (double /*dt*/, const item_array_t &/*p_sol*/, const item_array_t &/*s_sol*/, index_t /*block_size*/) + { + bs_throw_exception ("PURE CALL"); + } + + template + void + well ::custom_init (const sp_calc_model_t &/*mdl*/) + { + } + + template + void + well ::pre_large_step (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) + { + compute_connection_factor (calc_model->internal_constants, + calc_model->ts_params, + mesh, + calc_model->rock_grid_prop->permeability, + calc_model->rock_grid_prop->net_to_gros, + false); + + reset_init_approx (); + check_shut (calc_model); + custom_init (calc_model); + } + template + void + well::pre_small_step () + { + BS_ASSERT (well_controller_); + + saved_well_state_ = well_state_; + well_controller_->save_control (); + } + template + void + well::pre_newton_step () + { + BS_ASSERT (well_controller_); + + saved_niter_well_state_ = well_state_; + well_controller_->save_niter_control (); + } + template + void + well::restart_small_step () + { + BS_ASSERT (well_controller_); + + well_state_ = saved_well_state_; + init_approx_is_calc_ = well_controller_->restore_control (); + } + template + void + well::restart_newton_step () + { + BS_ASSERT (well_controller_); + + well_state_ = saved_niter_well_state_; + init_approx_is_calc_ = well_controller_->restore_niter_control (); + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF (well, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (well, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well), 1, (facility_base), "well_seq_fi", "well_seq_fi", "well_seq_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well), 1, (facility_base), "well_seq_di", "well_seq_di", "well_seq_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well), 1, (facility_base), "well_seq_mixi", "well_seq_mixi", "well_seq_mixi", false); + ////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////// + bool + calc_well_register_types (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, wells::connection::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, wells::connection::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, wells::connection::bs_type ()); + BS_ASSERT (res); + + res &= BS_KERNEL.register_type (pd, well::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well::bs_type ()); + BS_ASSERT (res); + + return res; + } + +} // namespace blue_sky diff --git a/bs_bos_core/src/calc_well_pressure.cpp b/bs_bos_core/src/calc_well_pressure.cpp new file mode 100644 index 0000000..28376d5 --- /dev/null +++ b/bs_bos_core/src/calc_well_pressure.cpp @@ -0,0 +1,318 @@ +/** + * \file calc_well_pressure.cpp + * \brief + * \author Sergey Miryanov + * \date 26.09.2008 + * */ +#include "stdafx.h" +#include "calc_well_pressure.h" +#include "calc_model.h" +#include "calc_well.h" +#include "well_connection.h" +#include "well_rate_control.h" +#include "calc_model_data_accessors.h" +#include "reservoir.h" +#include "facility_manager.h" + +namespace blue_sky + { + + template + calc_well_pressure ::calc_well_pressure (bs_type_ctor_param /*param = NULL */) + { + } + + template + calc_well_pressure ::calc_well_pressure (const calc_well_pressure &rhs) + : bs_refcounter () + { + *this = rhs; + } + + template + bool + calc_well_pressure::calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const + { + BS_ASSERT (!well->is_shut ()) (well->name ()); + + if (well->is_rate ()) + { + return calculate_for_rate (well, calc_model); + } + else + { + return false; + } + } + + template + struct calc_for_rate + { + typedef typename calc_well_pressure_t::item_t item_t; + typedef typename calc_well_pressure_t::index_t index_t; + typedef typename calc_well_pressure_t::item_array_t item_array_t; + typedef typename calc_well_pressure_t::calc_model_t calc_model_t; + typedef typename calc_model_t::data_t calc_model_data_t; + typedef typename calc_model_t::sat_d_t sat_d_t; + typedef typename calc_model_t::phase_d_t phase_d_t; + + typedef typename calc_well_pressure_t::sp_well_t sp_well_t; + + + calc_for_rate (const sp_well_t &well, const phase_d_t &phase_d, const sat_d_t &sat_d, index_t n_phases, const item_array_t &gas_oil_ratio) + : is_prod (well->get_well_controller ()->is_production ()) + , phase_d (phase_d) + , sat_d (sat_d) + , n_phases (n_phases) + , n_block (0) + , gas_oil_ratio (gas_oil_ratio) + { + // TODO: BAD DESIGN + if (is_prod) + { + using namespace wells; + rate_control_type control_type = well->get_well_controller ()->get_control_type (); + is_w = control_type == water_rate_control || control_type == liquid_rate_control; + is_g = control_type == gas_rate_control; + is_o = control_type == oil_rate_control || control_type == liquid_rate_control; + } + else + { + using namespace wells; + injection_type injection = well->get_well_controller ()->injection (); + + is_w = injection == injection_water; + is_g = injection == injection_gas; + is_o = injection == injection_oil; + } + + // TODO: HACK + is_w = phase_d[FI_PHASE_WATER] != -1 && is_w; + is_g = phase_d[FI_PHASE_GAS] != -1 && is_g; + is_o = phase_d[FI_PHASE_OIL] != -1 && is_o; + } + + void + calc_prod (const calc_model_data_t &data, item_t &denom, item_t &numer) + { + if (is_w) + { + const item_t &mw = MOBILITY (data, phase_d, FI_PHASE_WATER); + item_t pcwo = n_phases == 1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_WATER); + item_t y = gw * mw; + item_t z = y * (H - po - pcwo); + + denom += y; + numer += z; + } + if (is_g) + { + const item_t &mg = MOBILITY (data, phase_d, FI_PHASE_GAS); + item_t mo = phase_d[FI_PHASE_OIL] == -1 ? 0 : MOBILITY (data, phase_d, FI_PHASE_OIL); + item_t gor = phase_d[FI_PHASE_OIL] == -1 ? 0 : gas_oil_ratio [n_block]; + item_t pcgo = n_phases == 1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_GAS); + item_t Po = (H - po); + item_t Pg = (Po - pcgo); + item_t y = gw * (mg + gor * mo); + item_t z = gw * (mg * Pg + gor * mo * Po); + + denom += y; + numer += z; + } + if (is_o) + { + item_t mo = MOBILITY (data, phase_d, FI_PHASE_OIL); + item_t y = gw * mo; + item_t z = y * (H - po); + + denom += y; + numer += z; + } + } + + void + calc_inj (const calc_model_data_t &data, item_t &denom, item_t &numer) + { + item_t mw = 0; + item_t mg = 0; + item_t mo = 0; + item_t pcwo = 0; + item_t pcgo = 0; + + if (n_phases == 1) + { + mw = phase_d[FI_PHASE_WATER] == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER); + mg = phase_d[FI_PHASE_GAS] == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS); + mo = phase_d[FI_PHASE_OIL] == -1 ? 0 : INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL); + } + else + { + mw = phase_d[FI_PHASE_WATER] == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_WATER) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_WATER)); + mg = phase_d[FI_PHASE_GAS] == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_GAS) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_GAS)); + mo = phase_d[FI_PHASE_OIL] == -1 ? 0 : (RELATIVE_PERM (data, phase_d, FI_PHASE_OIL) * INVERS_VISCOSITY (data, phase_d, FI_PHASE_OIL)); + pcwo = phase_d[FI_PHASE_WATER] == -1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_WATER); + pcgo = phase_d[FI_PHASE_GAS] == -1 ? 0 : CAP_PRESSURE (data, phase_d, FI_PHASE_GAS); + } + + if (is_w) + { + item_t bw = INVERS_FVF (data, phase_d, FI_PHASE_WATER); + mw = mw * bw; + mg = mg * bw; + mo = mo * bw; + + item_t y = gw * (mw + mg + mo); + item_t z = y * (H - po - pcwo); + + denom += y; + numer += z; + } + else if (is_g) + { + item_t bg = INVERS_FVF (data, phase_d, FI_PHASE_GAS); + mw = mw * bg; + mg = mg * bg; + mo = mo * bg; + + item_t y = gw * (mw + mg + mo); + item_t z = y * (H - po - pcgo); + + denom += y; + numer += z; + } + else if (is_o) + { + item_t bo = INVERS_FVF (data, phase_d, FI_PHASE_OIL); + mw = mw * bo; + mg = mg * bo; + mo = mo * bo; + + item_t y = gw * (mw + mg + mo); + item_t z = y * (H - po); + + denom += y; + numer += z; + } + } + +public: + + bool is_prod; + bool is_w, is_g, is_o; + + auto_value gw; + auto_value po; + auto_value H; + + const phase_d_t &phase_d; + const sat_d_t &sat_d; + + index_t n_phases; + index_t n_block; + + const item_array_t &gas_oil_ratio; + }; + + template + bool + calc_well_pressure ::calculate_for_rate (sp_well_t &well, const sp_calc_model_t &calc_model) const + { + BS_ASSERT (!well->is_shut ()) (well->name ()); + + typedef typename base_t::well_t::connection_t connection_t; + typedef typename base_t::well_t::sp_connection_t sp_connection_t; + + typedef typename base_t::calc_model_t::sat_d_t sat_d_t; + typedef typename base_t::calc_model_t::phase_d_t phase_d_t; + + typedef typename base_t::calc_model_t::data_t calc_model_data_t; + + if (well->get_connections_count () == 0) + { + return false; + } + + item_t gravity = calc_model->internal_constants.gravity_constant; + item_t numer = 0; + item_t denom = 0; + item_t prev_depth = well->get_connection (0)->connection_depth; + + calc_for_rate calc (well, calc_model->phase_d, calc_model->sat_d, calc_model->n_phases, calc_model->gas_oil_ratio); + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c = well->get_connection (i); + if (c->is_shut ()) + { + prev_depth = c->connection_depth; + continue; + } + + calc.n_block = c->n_block (); + const calc_model_data_t &data = calc_model->get_data (calc.n_block); + main_var_type main_var = calc_model->main_variable[calc.n_block]; + + item_t rho = c->density; + item_t diff_h = c->connection_depth - prev_depth; + prev_depth = c->connection_depth; + calc.gw = c->get_fact (); + calc.po = calc_model->pressure[calc.n_block]; + calc.H = rho * gravity * diff_h; + + BS_ASSERT (main_var != FI_NULL) (main_var); + + if (calc.is_prod) + { + calc.calc_prod (data, denom, numer); + } + else + { + calc.calc_inj (data, denom, numer); + } + } + + item_t q_rate = well->get_input_rate (); + item_t bhp = (q_rate - numer) / denom; + bool switched_to_bhp = false; + + BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: q_rate: " << q_rate << " numer: " << numer << " denom: " << denom << " bhp: " << bhp << bs_end; + if ((fabs (denom) < 1e-10) || (bhp < 1.0 || bhp > 1000.0)) + { + BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: switched to bhp" << bs_end; + + well->get_well_controller ()->switch_to_bhp (well); + switched_to_bhp = true; + } + else + { + BOSOUT (section::wells, level::low) << "[" << well->name () << "] calc_well_pressure: none" << bs_end; + + well->set_bhp (bhp); + } + + return switched_to_bhp; + } + + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (calc_well_pressure, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (calc_well_pressure, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_well_pressure), 1, (objbase), "calc_well_pressure_fi", "calc_well_pressure_fi", "calc_well_pressure_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_well_pressure), 1, (objbase), "calc_well_pressure_di", "calc_well_pressure_di", "calc_well_pressure_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (calc_well_pressure), 1, (objbase), "calc_well_pressure_mixi", "calc_well_pressure_mixi", "calc_well_pressure_mixi", false); + + bool + calc_well_pressure_register_types (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, calc_well_pressure ::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, calc_well_pressure ::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, calc_well_pressure ::bs_type ()); + BS_ASSERT (res); + + return res; + } + +} // namespace blue_sky + diff --git a/bs_bos_core/src/csr_ilu_cfl.cpp b/bs_bos_core/src/csr_ilu_cfl.cpp new file mode 100644 index 0000000..c595ea4 --- /dev/null +++ b/bs_bos_core/src/csr_ilu_cfl.cpp @@ -0,0 +1,171 @@ +/*! +* \file csr_ilu_cfl.cpp +* \brief child for class csr_ilu (for adaptive cpr) +* \author Salimgareeva Elmira +* \date 11.05.09 +*/ +#include "stdafx.h" +#include "csr_ilu_cfl.h" + +namespace blue_sky +{ + /*! + brief constructor + */ + template + csr_ilu_cfl_prec::csr_ilu_cfl_prec (bs_type_ctor_param param /* = NULL */) + : csr_ilu_prec(param), + sp_ilu_cfl_(BS_KERNEL.create_object(bcsr_matrix_t::bs_type())) + { + } + + template + csr_ilu_cfl_prec::csr_ilu_cfl_prec(const csr_ilu_cfl_prec& solver) + : bs_refcounter (solver), + csr_ilu_prec (solver) + { + if (&solver != this) + *this = solver; + } + + /*! + * \brief destructor + */ + template + csr_ilu_cfl_prec::~csr_ilu_cfl_prec () + { + } + + template int + csr_ilu_cfl_prec::solve (matrix_t * /*matrix*/, rhs_item_array_t &rhs, item_array_t &sol) + { + return this->csr_ilu_prec_t::solve (sp_ilu_cfl_.lock (), rhs, sol); + } + + template int + csr_ilu_cfl_prec::solve_prec (matrix_t * /*matrix*/, item_array_t &rhs, item_array_t &sol) + { + return this->csr_ilu_prec_t::solve_prec (sp_ilu_cfl_.lock (), rhs, sol); + } + + + template + typename csr_ilu_cfl_prec::sp_bcsr_matrix_t + csr_ilu_cfl_prec::create_merged_matrix_for_ilu (jmatrix_t *matrix, const rhs_item_array_t &cfl_vector) + { + if (!matrix) + { + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "Passed matrix is null"); + } + + + BS_ASSERT (sp_ilu_cfl_); + sp_bcsr_matrix_t locked_regular (matrix->get_regular_matrix ()); + sp_bcsr_matrix_t locked_irregular (matrix->get_irregular_matrix ()); + + if (!locked_regular) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "Regular matrix is null"); + + if (!locked_irregular) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "Irregular matrix is null"); + + //---------------------------------------------------------------------------- + + bcsr_matrix_t ®ular_matrix = *locked_regular; + bcsr_matrix_t &irregular_matrix = *locked_irregular; + const rhs_item_array_t ®ular_acc_diag = matrix->get_regular_acc_diag (); + + irregular_matrix.init_diag_ind (); + + index_array_t ®_rows = regular_matrix.get_rows_ptr (); + index_array_t &irreg_rows = irregular_matrix.get_rows_ptr (); + //--------------------------------------------------------------------------- + + // if !condition then print message about error and values of variables + BS_ASSERT (regular_matrix.n_rows == irregular_matrix.n_rows) (regular_matrix.n_rows) (irregular_matrix.n_rows); + + if (regular_matrix.n_rows != irregular_matrix.n_rows) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "Number of rows in regular matrix is not the same as in irregular"); + + if (regular_matrix.n_block_size != irregular_matrix.n_block_size) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "Size of block in regular matrix is not the same as in irregular"); + + //---------------------------------------------------------------------------- + + + bcsr_matrix_t &new_matrix = *sp_ilu_cfl_; + + if (new_matrix.init (1, 1, regular_matrix.n_block_size, 1)) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "can't init merged_reg_irreg_matrix"); + + + //bool ok = false; + if (reg_rows.empty () || irreg_rows.empty ()) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "Reg rows or irreg rows is empty"); + + + if (new_matrix.merge (®ular_matrix, &irregular_matrix, 1, cfl_vector)) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "can't merge regular and irregular matricies"); + + if (new_matrix.init_diag_ind ()) + throw bs_exception ("csr_ilu_cfl: create_merge_matrix_for_ilu", "can't init merged reg and irreg matricies diag ind's"); + + index_t n_block_size = regular_matrix.n_block_size; // size of block in matrix + index_t b_sqr = n_block_size*n_block_size; + + rhs_item_array_t &new_vals = new_matrix.get_values (); + + index_array_t &new_rows = new_matrix.get_rows_ptr (); + index_array_t &new_cols = new_matrix.get_cols_ind (); + + for (index_t i = 0, n_rows = regular_matrix.n_rows; i < n_rows; ++i) + { + index_t l = new_rows[i]; + BS_ASSERT (new_cols[l] == i) (new_cols[l]) (i); + for (index_t k = 0; k < b_sqr; ++k) + { + new_vals[l * b_sqr + k] += regular_acc_diag[i * b_sqr + k]; + } + } + + new_matrix.n_rows = regular_matrix.n_rows; + new_matrix.n_cols = regular_matrix.n_cols; + new_matrix.n_block_size = regular_matrix.n_block_size; + + return sp_ilu_cfl_;//locked_new_matrix; + } + + + template int + csr_ilu_cfl_prec::setup (matrix_t *matrix_) + { + BS_ASSERT (matrix_); + if (!matrix_) + throw bs_exception ("csr_ilu_cfl::setup", "Passed matrix is null"); + + jacobian_matrix *jmx = dynamic_cast *> (matrix_); + BS_ASSERT (jmx) (bs::type_name (*matrix_)); + if (jmx) + { + sp_ilu_cfl_ = create_merged_matrix_for_ilu (jmx, jmx->get_cfl_vector ()); + return csr_ilu_prec_t::setup_internal (sp_ilu_cfl_); + } + else + { + return csr_ilu_prec_t::setup_internal (dynamic_cast (matrix_)); + } + } + + +////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF(csr_ilu_cfl_prec, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(csr_ilu_cfl_prec, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (csr_ilu_cfl_prec) , 1, (linear_solver_base), "csr_ilu_cfl_prec_seq_fi", "CSR ILU Preconditioner", "CSR ILU Preconditioner", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (csr_ilu_cfl_prec) , 1, (linear_solver_base), "csr_ilu_cfl_prec_seq_di", "CSR ILU Preconditioner", "CSR ILU Preconditioner", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (csr_ilu_cfl_prec) , 1, (linear_solver_base), "csr_ilu_cfl_prec_seq_mixi", "CSR ILU Preconditioner", "CSR ILU Preconditioner", false); + +////////////////////////////////////////////////////////////////////////// + + +} diff --git a/bs_bos_core/src/data_storage_interface.cpp b/bs_bos_core/src/data_storage_interface.cpp new file mode 100644 index 0000000..688e2bd --- /dev/null +++ b/bs_bos_core/src/data_storage_interface.cpp @@ -0,0 +1,176 @@ +/** + * \file data_storage_interface.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 21.07.2008 + * */ +#include "stdafx.h" + +#include "data_storage_interface.h" + +#ifdef _DEBUG +#include "well_serializer.h" +#endif + + +namespace blue_sky + { + + BLUE_SKY_TYPE_IMPL_T_EXT (2, (bos_val_table >), 1, (objbase), "bos_map ", "bos_map ", "bos_map ", false); + + data_storage::data_storage (bs_type_ctor_param /*param = NULL */) + { + + } + data_storage::data_storage (const data_storage & /*ds*/) + : bs_refcounter (), objbase () + { + + } + + data_storage & + data_storage::save (const std::string &name, const std::string &value) + { + BS_ASSERT (false && "BASE METHOD CALL") (name) (value); + return *this; + } + + + data_serializer::data_serializer (bs_type_ctor_param /*param = NULL */) + { + + } + data_serializer::data_serializer (const data_serializer& ds) + : bs_refcounter (), objbase () + { + handled_type_ = ds.handled_type (); + } + + void + data_serializer::save (const sp_storage_t &storage, const sp_obj &obj) const + { + BS_ASSERT (storage); + BS_ASSERT (obj); + + const sp_storage_t &locked_storage (storage); + data_storage &st = *locked_storage; + + BS_ASSERT (false && "BASE METHOD CALL") (storage->bs_resolve_type ().stype_) (obj->bs_resolve_type ().stype_); + st.save ("base method call", "---"); + } + + const type_descriptor & + data_serializer::handled_type () const + { + return handled_type_; + } + + + data_storage_interface::data_storage_interface (bs_type_ctor_param /*param = NULL */) + { + serializer_list_ = BS_KERNEL.create_object (serializer_list_t::bs_type ()); + BS_ASSERT (serializer_list_); + +#ifdef _DEBUG + register_serializer (BS_KERNEL.create_object (wells::well_serializer ::bs_type ())); + register_serializer (BS_KERNEL.create_object (wells::well_serializer ::bs_type ())); +#endif + } + data_storage_interface::data_storage_interface (const data_storage_interface& dsi) + : bs_refcounter (), objbase () + { + storage_ = dsi.storage_; + serializer_list_ = dsi.serializer_list_; + + BS_ASSERT (serializer_list_); + } + + void + data_storage_interface::save (const sp_obj &obj) const + { + BS_ASSERT (storage_); + if (!storage_) + return ; + + BS_ASSERT (obj); + const type_descriptor &td = obj->bs_resolve_type (); + + serializer_list_t::const_iterator it = serializer_list_->find (td.stype_); + BS_ASSERT (it != serializer_list_->end ()) (td.stype_); + + if (it != serializer_list_->end ()) + it->second->save (storage_, obj); + } + + void + data_storage_interface::register_serializer (const sp_serializer_t &serializer) + { + BS_ASSERT (serializer); + BS_ASSERT (serializer->bs_resolve_type ().stype_.length ()); + + const type_descriptor &td = serializer->handled_type (); + BS_ASSERT (td.stype_.length ()) (serializer->bs_resolve_type ().stype_); + + const sp_serializer_list_t &locked_list (serializer_list_); + serializer_list_t::iterator it = locked_list->find (td.stype_); + BS_ASSERT (it == locked_list->end ()); + + if (it == locked_list->end ()) + locked_list->insert (make_pair (td.stype_, serializer)); + else + it->second = serializer; + } + + void + data_storage_interface::set_storage (const sp_storage_t &storage) + { + storage_ = storage; + + BS_ASSERT (storage_); + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE (data_storage); + BLUE_SKY_TYPE_STD_COPY (data_storage); + BLUE_SKY_TYPE_IMPL (data_storage, objbase, "data_storage", "data_storage", "data_storage"); + + BLUE_SKY_TYPE_STD_CREATE (data_serializer); + BLUE_SKY_TYPE_STD_COPY (data_serializer); + BLUE_SKY_TYPE_IMPL (data_serializer, objbase, "data_serializer", "data_serializer", "data_serializer"); + + BLUE_SKY_TYPE_STD_CREATE (data_storage_interface); + BLUE_SKY_TYPE_STD_COPY (data_storage_interface); + BLUE_SKY_TYPE_IMPL (data_storage_interface, objbase, "data_storage_interface", "data_storage_interface", "data_storage_interface"); + + ////////////////////////////////////////////////////////////////////////// + bool + data_storage_register_type (const plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, data_storage::bs_type ()); + BS_ASSERT (res); + + return res; + } + bool + data_serializer_register_type (const plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, data_serializer::bs_type ()); + BS_ASSERT (res); + + return res; + } + bool + data_storage_interface_register_type (const plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, data_storage_interface::bs_type ()); + BS_ASSERT (res); + + return res; + } +} // namespace blue_sky diff --git a/bs_bos_core/src/debug_tools.cpp b/bs_bos_core/src/debug_tools.cpp new file mode 100644 index 0000000..957b5dc --- /dev/null +++ b/bs_bos_core/src/debug_tools.cpp @@ -0,0 +1,84 @@ +/*! +* \file debug_tools.cpp +* \brief usefull tools for debug +* \author Borschuk Oleg +* \date 2006-06-19 +*/ +#include "stdafx.h" + +#ifdef _MPI +#include +#endif + +#include +#include +#include +#include + +#ifndef UNIX +#include +#include +#endif //UNIX + +#include "debug_tools.h" +#include "debug_macroses.h" + +using namespace std; + +//! This function summons a MessageBox window with errormessage specified +//! by the parameters of the function and exits the whole program with code -1 +/*! + \brief Error messager + \param *filename + \param linenum + \param *errormessage +*/ +int +write_vector_to_file (const char *file_name, double *vector, const int n) +{ + //FILE *fp = 0; + int i; + + CH_PTR (vector); + + //fp = fopen (file_name, "w"); + ofstream fp(file_name); + if (!fp) + //TODO: write error message + return -1; + for (i = 0; i < n; ++i) + //fprintf (fp, "%.20lf\n", vector[i]); + fp << setprecision(20) << vector[i] << endl; + + //fclose (fp); + fp.close(); + + return 0; +} + +int +write_int_vector_to_file (const char *file_name, int* vector, const int n) +{ + //FILE *fp = 0; + int i; + + CH_PTR (vector); + + //fp = fopen (file_name, "w"); + ofstream fp(file_name); + + if (!fp) + //TODO: write error message + return -1; + + for (i = 0; i < n; ++i) + //fprintf (fp, "%d\n", vector[i]); + fp << vector[i] << endl; + + //fclose (fp); + fp.close(); + + return 0; +} + + diff --git a/bs_bos_core/src/default_connection.cpp b/bs_bos_core/src/default_connection.cpp new file mode 100644 index 0000000..7c66c19 --- /dev/null +++ b/bs_bos_core/src/default_connection.cpp @@ -0,0 +1,81 @@ +/** + * \file default_connection.h + * \brief impl of + * \author Sergey Miryanov + * \date 20.05.2009 + * */ +#include "stdafx.h" +#include "default_connection.h" + +namespace blue_sky { +namespace wells { + + template + default_connection ::default_connection (bs_type_ctor_param param /* = NULL */) + : base_t (param) + { + clear_data (); + } + template + default_connection ::default_connection (const default_connection &c) + : bs_refcounter (), connection () + { + *this = c; + } + + template + array_ext ::item_t> + default_connection ::get_rw_value () + { + return array_ext (&rw_value[0], rw_value.size ()); + } + template + array_ext ::item_t> + default_connection ::get_wr_value () + { + return array_ext (&wr_value[0], wr_value.size ()); + } + template + array_ext ::item_t> + default_connection ::get_rr_value () + { + return array_ext (&rr_value[0], rr_value.size ()); + } + template + array_ext ::item_t> + default_connection ::get_ps_value () + { + return array_ext (&ps_value[0], ps_value.size ()); + } + template + array_ext ::rhs_item_t> + default_connection ::get_rate_value () + { + return array_ext (&rate_value[0], rate_value.size ()); + } + + template + void + default_connection ::clear_data () + { + assign (mobility_value, 0); + assign (rate_value, 0); + assign (ps_value, 0); + assign (rr_value, 0); + assign (rw_value, 0); + assign (wr_value, 0); + + base_t::clear_data (); + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF (default_connection, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (default_connection, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_connection), 1, (connection), "default_connection_seq_fi", "default_connection_seq_fi", "default_connection_seq_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_connection), 1, (connection), "default_connection_seq_di", "default_connection_seq_di", "default_connection_seq_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_connection), 1, (connection), "default_connection_seq_mixi", "default_connection_seq_mixi", "default_connection_seq_mixi", false); + ////////////////////////////////////////////////////////////////////////// + +} //namespace wells +} //namespace blue_sky + diff --git a/bs_bos_core/src/default_well.cpp b/bs_bos_core/src/default_well.cpp new file mode 100644 index 0000000..4634d6f --- /dev/null +++ b/bs_bos_core/src/default_well.cpp @@ -0,0 +1,504 @@ +/** + * \file default_well.cpp + * \brief + * \author Sergey Miryanov + * \date 20.05.2009 + * */ +#include "stdafx.h" +#include "default_well.h" +#include "default_rr_eliminator.h" +#include "default_connection.h" +#include "calc_model.h" + + +// TODO: +#include "well_rate_control_deriv.h" +#include "default_well_calc_rate.h" + +namespace blue_sky { +namespace wells { + + template + default_well ::default_well (bs_type_ctor_param param /* = NULL */) + : base_t (param) + , ww_value (0) + , bw_value (0) + { + } + + template + default_well ::default_well (const std::string &well_name) + : base_t (well_name) + , ww_value (0) + , bw_value (0) + { + + } + + template + default_well ::default_well (const default_well &w) + : bs_refcounter (), well < strategy_t> () + { + *this = w; + } + + namespace detail { + + template + struct sort_connection_list : std::binary_function + { + bool + operator () (const connection_t &lhs, const connection_t &rhs) const + { + return lhs->n_block () < rhs->n_block (); + } + }; + } // namespace wells + + template + typename default_well ::sp_connection_t + default_well ::add_connection (index_t i_coord, index_t j_coord, index_t k_coord, index_t n_block) + { + if (n_block < 0) + bs_throw_exception ("Invalid connection n_block value"); + + sp_default_connection_t connection = BS_KERNEL.create_object (default_connection_t::bs_type (), true); + if (!connection) + bs_throw_exception ("Can't create connection"); + + connection->set_coord (i_coord, j_coord, k_coord, n_block); + connection_list_.push_back (connection); + std::sort (connection_list_.begin (), connection_list_.end (), detail::sort_connection_list ()); + connection_map_.insert (std::make_pair (connection->n_block (), (index_t)connection_list_.size () - 1)); + + return connection; + } + + template + typename default_well ::sp_connection_t + default_well ::get_connection (index_t idx) const + { + BS_ASSERT (idx < connection_list_.size ()) (base_t::name ()) (idx) (connection_list_.size ()); + return connection_list_[idx]; + } + template + typename default_well ::sp_connection_t + default_well ::get_connection_map (index_t n_block) const + { + for (size_t i = 0, cnt = connection_list_.size (); i < cnt; ++i) + { + if (connection_list_[i]->n_block () == n_block) + return connection_list_[i]; + } + + return 0; +// typename connection_map_t::const_iterator it = connection_map_.find (n_block); +// if (it == connection_map_.end ()) +// return 0; +// +// if (it->second >= (int)connection_list_.size ()) +// { +//#ifdef _DEBUG +// typename connection_map_t::const_iterator i = connection_map_.begin (), e = connection_map_.end (); +// for (; i != e; ++i) +// { +// BOSOUT (section::wells, level::debug) << boost::format ("[%d: %d]") % i->first % i->second << bs_end; +// } +//#endif +// bs_throw_exception (boost::format ("Connection map has an invalid value ([%s]: %d - %d, %d, %d)") % base_t::name_ % n_block % it->second % connection_list_.size () % connection_map_.size ()); +// } +// +// return connection_list_[it->second]; + } + + template + size_t + default_well ::get_connections_count () const + { + return connection_list_.size (); + } + + + template + void + default_well ::restore_solution (double /*dt*/, const item_array_t &p_sol, + const item_array_t & /*s_sol*/, index_t block_size) + { + BS_ASSERT (get_connections_count ()) (base_t::name ()); + + typedef array_ext item_wr_block_t; + typedef array_ext item_xr_block_t; + + // TODO: may be we can not check is_work flag + if (!base_t::well_state_.is_work) + return ; + + if (!base_t::well_controller_->is_rate ()) + return ; + + item_t xw = 0; + item_t ww_bw = (1.0 / ww_value) * bw_value; + + for (index_t j = 0, jcnt = (index_t)base_t::open_connections_.size (); j < jcnt; ++j) + { + index_t con_index = base_t::open_connections_[j]; + BS_ASSERT (connection_list_[con_index]->is_shut () == false) (j); + + const sp_connection_t &c = connection_list_[con_index]; + const item_wr_block_t &wr = c->get_wr_value (); + const item_xr_block_t &xr = item_xr_block_t (&p_sol[c->n_block () * block_size], block_size); + + item_t wr_xr = 0; + for (index_t j = 0; j < block_size; ++j) + { + wr_xr += wr[j] * xr[j]; + } + + xw += ww_bw - wr_xr; + } + + BOSOUT (section::wells, level::low) << "[" << base_t::name_ << boost::format ("] Restore solution: change bhp from %f to %f (bw: %f, ww: %f)") % base_t::bhp_ % (base_t::bhp_ + xw) % bw_value % ww_value << bs_end; + base_t::bhp_ += xw; + } + template + void + default_well ::eliminate (rhs_item_t *res, index_t rw_index, index_t wr_index, double dt, index_t block_size) const + { + BS_ASSERT (!base_t::is_shut ()) (base_t::name ()); + BS_ASSERT (get_connections_count ()) (base_t::name ()); + BS_ASSERT (res); + + if (block_size > 3 && block_size < 1) + bs_throw_exception ("block_size invalid"); + + const sp_connection_t &rw_con = connection_list_[rw_index]; + const sp_connection_t &wr_con = connection_list_[wr_index]; + + const array_ext &rw = rw_con->get_rw_value (); + const array_ext &wr = wr_con->get_wr_value (); + const array_ext &rr = wr_con->get_rr_value (); + + BS_ASSERT (rw.size () == (size_t)block_size) (rw.size ()) (block_size); + BS_ASSERT (wr.size () == (size_t)block_size) (wr.size ()) (block_size); + BS_ASSERT (rr.size () == (size_t)block_size * block_size) (rr.size ()) (block_size); + + if (rw_index == wr_index) + { + if (well_t::well_controller_->is_rate ()) + { + if (block_size == 3) + default_rr_eliminator <3>::process_diag_rate (res, rr, rw, wr, dt); + else if (block_size == 2) + default_rr_eliminator <2>::process_diag_rate (res, rr, rw, wr, dt); + else if (block_size == 1) + default_rr_eliminator <1>::process_diag_rate (res, rr, rw, wr, dt); + } + else + { + if (block_size == 3) + default_rr_eliminator <3>::process_diag_bhp (res, rr, dt); + else if (block_size == 2) + default_rr_eliminator <2>::process_diag_bhp (res, rr, dt); + else if (block_size == 1) + default_rr_eliminator <1>::process_diag_bhp (res, rr, dt); + } + } + else + { + if (well_t::well_controller_->is_rate ()) + { + if (block_size == 3) + default_rr_eliminator <3>::process_rate (res, rw, wr, dt); + else if (block_size == 2) + default_rr_eliminator <2>::process_rate (res, rw, wr, dt); + else if (block_size == 1) + default_rr_eliminator <1>::process_rate (res, rw, wr, dt); + } + } + } + + template + template + void + default_well ::calc_rate_and_derivs (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix) + { + if (calc_model->n_phases == 3) + { + calc_rate_and_derivs_concrete (calc_model, mesh, jmatrix); + } + else if (calc_model->is_water () && calc_model->is_oil ()) + { + calc_rate_and_derivs_concrete (calc_model, mesh, jmatrix); + } + else if (calc_model->is_gas () && calc_model->is_oil ()) + { + calc_rate_and_derivs_concrete (calc_model, mesh, jmatrix); + } + else if (calc_model->is_water ()) + { + calc_rate_and_derivs_concrete (calc_model, mesh, jmatrix); + } + else if (calc_model->is_gas ()) + { + calc_rate_and_derivs_concrete (calc_model, mesh, jmatrix); + } + else + { + calc_rate_and_derivs_concrete (calc_model, mesh, jmatrix); + } + } + + template + void + print (const T &t) + { + std::cout << "block[" << t->n_block () << "]:" << std::endl; + //std::cout << "\tprod: " << std::endl; + //std::cout << "\t\tw = " << t->rate_.prod.water << "\n\t\tg = " << t->rate_.prod.gas << "\n\t\to = " << t->rate_.prod.oil << std::endl; + //std::cout << "\tinj: " << std::endl; + //std::cout << "\t\tw = " << t->rate_.inj.water << "\n\t\tg = " << t->rate_.inj.gas << "\n\t\to = " << t->rate_.inj.oil << std::endl; + //std::cout << "\tmob: " << std::endl; + //std::cout << "\t\tw = " << t->mobility_value[0] << "\n\t\tg = " << t->mobility_value[1] << "\n\t\to = " << t->mobility_value[2] << std::endl; + for (size_t i = 0, cnt = t->get_rr_value ().size (); i < cnt; ++i) + { + printf ("rr[%d] = %10.15f\n", i, t->get_rr_value ()[i]); + } + for (size_t i = 0, cnt = t->get_ps_value ().size (); i < cnt; ++i) + { + printf ("ps[%d] = %10.15f\n", i, t->get_ps_value ()[i]); + } + for (size_t i = 0, cnt = t->get_rw_value ().size (); i < cnt; ++i) + { + printf ("rw[%d] = %10.15f\n", i, t->get_rw_value ()[i]); + } + for (size_t i = 0, cnt = t->get_wr_value ().size (); i < cnt; ++i) + { + printf ("wr[%d] = %10.15f\n", i, t->get_wr_value ()[i]); + } + } + template + void + print_rate (const T &t) + { + std::cout << "block[" << t->n_block () << "]:" << std::endl; + std::cout << "\tprod: " << std::endl; + std::cout << "\t\tw = " << t->rate_.prod.water << "\n\t\tg = " << t->rate_.prod.gas << "\n\t\to = " << t->rate_.prod.oil << std::endl; + std::cout << "\tinj: " << std::endl; + std::cout << "\t\tw = " << t->rate_.inj.water << "\n\t\tg = " << t->rate_.inj.gas << "\n\t\to = " << t->rate_.inj.oil << std::endl; + //std::cout << "\tmob: " << std::endl; + //std::cout << "\t\tw = " << t->mobility_value[0] << "\n\t\tg = " << t->mobility_value[1] << "\n\t\to = " << t->mobility_value[2] << std::endl; + } + + template + template + void + default_well ::calc_rate_and_derivs_concrete (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix) + { + + calc_rate_and_derivs_t calc_ (calc_model, jmatrix, this, this->connection_list_); + + //clear_data (); + //for (size_t i = 0; i < 10000; ++i) + // { + // calc_.calc_rate (this); + // //base_t::well_controller_->calc_rate (calc_model, sp_this, jmatrix); + // } + + smart_ptr sp_this (this); + + clear_data (); + calc_.calc_rate (this); + //base_t::well_controller_->calc_rate (calc_model, sp_this, jmatrix); + //for (size_t i = 0, cnt = connection_list_.size (); i < cnt; ++i) + // { + // print_rate (connection_list_[i]); + // } + + if (base_t::well_controller_->check (sp_this)) + { + base_t::calc_perf_bhp_->calculate (sp_this, calc_model, mesh); + base_t::well_state_.is_work = check_connections_bhp (calc_model->pressure); + if (!base_t::well_state_.is_work) + { + BOSOUT (section::wells, level::medium) << "[" << base_t::name_ << "] well does not work (2)" << bs_end; + //init_approx_is_calc_ = false; + return ; + } + + clear_data (); + calc_.calc_rate (this); + //base_t::well_controller_->calc_rate (calc_model, sp_this, jmatrix); + //for (size_t i = 0, cnt = connection_list_.size (); i < cnt; ++i) + // { + // print_rate (connection_list_[i]); + // } + } + + calc_.calc_derivs (this, base_t::is_rate ()); + //base_t::well_controller_->calc_derivs (calc_model, sp_this, jmatrix); + //for (size_t i = 0, cnt = connection_list_.size (); i < cnt; ++i) + // { + // print (connection_list_[i]); + // } + } + + + template + void + default_well ::process_internal (bool is_start, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix) + { + BS_ASSERT (!base_t::is_shut ()) (base_t::name ()); + + smart_ptr sp_this (this); + + if (is_start) + { + BS_ASSERT (base_t::calc_perf_density_); + base_t::calc_perf_density_->calculate (sp_this, calc_model); + } + clear_data (); + + if (!base_t::init_approx_is_calc_) + { + BS_ASSERT (base_t::calc_rho_); + BS_ASSERT (base_t::calc_well_pressure_); + + bool switched_to_bhp = base_t::calc_well_pressure_->calculate (sp_this, calc_model); + if (switched_to_bhp) + { + base_t::calc_perf_density_->calculate (sp_this, calc_model); + } + + base_t::init_approx_is_calc_ = true; + } + + BS_ASSERT (base_t::calc_perf_bhp_); + base_t::calc_perf_bhp_->calculate (sp_this, calc_model, mesh); + base_t::well_state_.is_work = check_connections_bhp (calc_model->pressure); + if (!base_t::well_state_.is_work) + { + BOSOUT (section::wells, level::medium) << "[" << base_t::name_ << "] well does not work" << bs_end; + //init_approx_is_calc_ = false; + return ; + } + + if (base_t::well_controller_->is_production ()) + { + calc_rate_and_derivs (calc_model, mesh, jmatrix); + } + else + { + calc_rate_and_derivs (calc_model, mesh, jmatrix); + } + } + + template + void + default_well ::process (bool is_start, double /*dt*/, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix) + { + if (base_t::is_shut ()) + { + BOSOUT (section::wells, level::debug) << "[" << base_t::name () << "] is_shut" << bs_end; + return ; + } + +#ifdef _DEBUG + if (!base_t::is_shut () && connection_list_.empty ()) + { + bs_throw_exception (boost::format ("[%s]: not shut but connection list is empty") % base_t::name ()); + } +#endif + + process_internal (is_start, calc_model, mesh, jmatrix); + + if (base_t::is_rate ()) + { + BOSOUT (section::wells, level::low) << "[" << this->name_ << "] start newton iterations" << bs_end; + + static index_t bw_iter_max = 20; + static item_t bw_eps = 1.0e-7f; + item_t prev_bw_value = bw_value; + + for (index_t bw_iter = 0; bw_iter < bw_iter_max; ++bw_iter) + { + if (fabs (bw_value) <= bw_eps) + { +#ifdef _DEBUG + BOSOUT (section::wells, level::debug) << "[" << base_t::name_ << "] bw_value (" << bw_value << ") smaller than eps" << bs_end; +#endif + break; + } + + ww_value += bw_eps; + prev_bw_value = bw_value; + item_t bw_ww_dx = bw_value / ww_value; +#ifdef _DEBUG + BOSOUT (section::wells, level::debug) << "[" << this->name_ << "] bw: " << bw_value << bs_end; + BOSOUT (section::wells, level::debug) << "[" << this->name_ << "] ww: " << ww_value << bs_end; +#endif + base_t::bhp_ += bw_ww_dx; + + process_internal (false, calc_model, mesh, jmatrix); + if (!base_t::is_rate ()) + break; + } + + BOSOUT (section::wells, level::low) << "[" << this->name_ << "] end newton iterations" << bs_end; + } + } + + template + void + default_well ::clear_data () + { + for (size_t i = 0, cnt = connection_list_.size (); i < cnt; ++i) + { + connection_list_ [i]->clear_data (); + } + + ww_value = 0; + bw_value = 0; + + base_t::clear_data (); + } + + template + array_ext ::item_t> + default_well ::get_ww_value () + { + return array_ext (&ww_value, 1); + } + template + array_ext ::item_t> + default_well ::get_bw_value () + { + return array_ext (&bw_value, 1); + } + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF (default_well, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (default_well, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_well), 1, (well), "default_well_seq_fi", "default_well_seq_fi", "default_well_seq_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_well), 1, (well), "default_well_seq_di", "default_well_seq_di", "default_well_seq_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_well), 1, (well), "default_well_seq_mixi", "default_well_seq_mixi", "default_well_seq_mixi", false); + ////////////////////////////////////////////////////////////////////////// + + bool + default_well_register_types (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, default_connection::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, default_connection::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, default_connection::bs_type ()); BS_ASSERT (res); + + res &= BS_KERNEL.register_type (pd, default_well::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, default_well::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, default_well::bs_type ()); BS_ASSERT (res); + + return res; + } + +} // namespace wells +} // namespace blue_sky + + diff --git a/bs_bos_core/src/default_well_calc_rate.h b/bs_bos_core/src/default_well_calc_rate.h new file mode 100644 index 0000000..e5a329d --- /dev/null +++ b/bs_bos_core/src/default_well_calc_rate.h @@ -0,0 +1,877 @@ +/** + * \file default_well_calc_rate.h + * \brief calculate rates for default_well + * \author Sergey Miryanov + * \date 13.10.2009 + * */ +#ifndef BS_BOS_CORE_DEFAULT_WELL_CALC_RATE_H_ +#define BS_BOS_CORE_DEFAULT_WELL_CALC_RATE_H_ + +#include "matrix_vector_op.h" +#include "pp_index.h" + +#define RELATIVE_PERM_W data.relative_perm[d_w] +#define RELATIVE_PERM_G data.relative_perm[d_g] +#define RELATIVE_PERM_O data.relative_perm[d_o] +#define P_DERIV_INVERS_VISC_W data.p_deriv_invers_viscosity[d_w] +#define P_DERIV_INVERS_VISC_G data.p_deriv_invers_viscosity[d_g] +#define P_DERIV_INVERS_VISC_O data.p_deriv_invers_viscosity[d_o] +#define S_DERIV_RELATIVE_PERM_WW data.s_deriv_relative_perm[d_w * n_phases + d_w] +#define S_DERIV_RELATIVE_PERM_GG data.s_deriv_relative_perm[d_g * n_phases + d_g] +#define S_DERIV_RELATIVE_PERM_GO data.s_deriv_relative_perm[d_g * n_phases + d_o] +#define S_DERIV_RELATIVE_PERM_OW data.s_deriv_relative_perm[d_o * n_phases + d_w] +#define S_DERIV_RELATIVE_PERM_OG data.s_deriv_relative_perm[d_o * n_phases + d_g] +#define S_DERIV_RELATIVE_PERM_OO data.s_deriv_relative_perm[d_o * n_phases + d_o] +#define S_DERIV_CAP_PRESSURE_W data.s_deriv_cap_pressure[d_w] +#define S_DERIV_CAP_PRESSURE_G data.s_deriv_cap_pressure[d_g] +#define INVERS_VISC_W data.invers_viscosity[d_w] +#define INVERS_VISC_G data.invers_viscosity[d_g] +#define INVERS_VISC_O data.invers_viscosity[d_o] +#define GOR_DERIV_INVERS_VISC data.gor_deriv_invers_viscosity +#define P_DERIV_INVERS_FVF_W data.p_deriv_invers_fvf[d_w] +#define P_DERIV_INVERS_FVF_G data.p_deriv_invers_fvf[d_g] +#define P_DERIV_INVERS_FVF_O data.p_deriv_invers_fvf[d_o] +#define INVERS_FVF_W data.invers_fvf[d_w] +#define INVERS_FVF_G data.invers_fvf[d_g] +#define INVERS_FVF_O data.invers_fvf[d_o] +#define S_DERIV_INVERS_FVF_W data.p_deriv_invers_fvf[d_w] * data.s_deriv_cap_pressure[d_w] +#define S_DERIV_INVERS_FVF_G data.p_deriv_invers_fvf[d_g] * data.s_deriv_cap_pressure[d_g] +#define S_DERIV_INVERS_VISC_W data.p_deriv_invers_viscosity[d_w] * data.s_deriv_cap_pressure[d_w] +#define S_DERIV_INVERS_VISC_G data.p_deriv_invers_viscosity[d_g] * data.s_deriv_cap_pressure[d_g] +#define CAP_PRESSURE_W data.cap_pressure[d_w] +#define CAP_PRESSURE_G data.cap_pressure[d_g] + +namespace blue_sky { +namespace wells { + + namespace detail { + template + struct rate_data + { + }; + + template <> + struct rate_data + { + template + static typename T::rate_data_inner & + get (T &t) + { + return t.prod; + } + }; + template <> + struct rate_data + { + template + static typename T::rate_data_inner & + get (T &t) + { + return t.inj; + } + }; + + template + struct mobility + { + }; + + template + struct mobility + { + template + static typename data_t::item_t + water (const data_t &data, index_t d_w, T *) + { + return data.mobility[d_w]; + } + template + static typename data_t::item_t + oil (const data_t &data, index_t d_o, T *) + { + return data.mobility[d_o]; + } + template + static typename data_t::item_t + gas (const data_t &, index_t, T *) + { + return 0; + } + }; + + template + struct mobility + { + template + static typename data_t::item_t + get_mobility (const data_t &data, index_t d, T *t) + { + if (main_var == FI_SG_VAR) + { + return data.invers_fvf[d] * t->krp_tetap; + } + else + { + return data.invers_fvf[d] * t->krow_tetaow; + } + } + + template + static typename data_t::item_t + water (const data_t &data, index_t d_w, T *t) + { + return get_mobility (data, d_w, t); + } + template + static typename data_t::item_t + oil (const data_t &data, index_t d_o, T *t) + { + return get_mobility (data, d_o, t); + } + template + static typename data_t::item_t + gas (const data_t &data, index_t d_g, T *t) + { + return get_mobility (data, d_g, t); + } + }; + } + + template + struct calc_rate_and_derivs_t + { + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + typedef typename strategy_t::rhs_item_array_t rhs_item_array_t; + + typedef default_well well_t; + typedef default_connection connection_t; + typedef typename well_t::connection_list_t connection_list_t; + typedef typename well_t::base_t::rate_data_t rate_data_t; + typedef typename rate_data_t::rate_data_inner rate_data_inner_t; + typedef calc_model calc_model_t; + typedef calc_model_data calc_model_data_t; + typedef typename calc_model_t::data_array_t cell_data_t; + typedef typename calc_model_t::main_var_array_t main_vars_t; + typedef typename main_vars_t::value_type main_var_t; + typedef jacobian_matrix jmatrix_t; + + typedef smart_ptr sp_calc_model_t; + typedef smart_ptr sp_jmatrix_t; + + enum + { + n_phases = is_w + is_g + is_o, + b_sqr = n_phases * n_phases, + }; + + enum + { + is_1p = n_phases == 1, + is_2p = n_phases == 2, + is_3p = n_phases == 3, + }; + + enum + { + gas_sg = blue_sky::detail::pp_index ::gas_sg, + gas_so = blue_sky::detail::pp_index ::gas_so, + gas_po = blue_sky::detail::pp_index ::gas_po, + oil_sg = blue_sky::detail::pp_index ::oil_sg, + oil_so = blue_sky::detail::pp_index ::oil_so, + oil_po = blue_sky::detail::pp_index ::oil_po, + wat_sg = blue_sky::detail::pp_index ::wat_sg, + wat_so = blue_sky::detail::pp_index ::wat_so, + wat_po = blue_sky::detail::pp_index ::wat_po, + }; + + enum + { + gas_idx = 0, + oil_idx = is_g, + wat_idx = is_g + is_o, + + gas_sw = !is_1p ? b_sqr + gas_idx : -1, + oil_sw = !is_1p ? b_sqr + oil_idx : -1, + wat_sw = !is_1p ? b_sqr + wat_idx : -1, + }; + + calc_rate_and_derivs_t (const sp_calc_model_t &calc_model, const sp_jmatrix_t &jmatrix, well_t *well, connection_list_t &list_) + : cell_data_ (calc_model->data) + , main_vars_ (calc_model->main_variable) + , pressure_ (calc_model->pressure) + , gas_oil_ratio_ (calc_model->gas_oil_ratio) + , invers_fvf_average_ (calc_model->invers_fvf_average) + , well_rate_ (well->rate_) + , well_rate_rc_ (well->rate_rc_) + , gor_ (well->gor_) + , d_w (0) + , d_g (0) + , d_o (0) + , list_ (list_) + , injection_type_ (well->get_well_controller ()->injection ()) + , control_type_ (well->get_well_controller ()->get_control_type ()) + , sp_diagonal_ (jmatrix->get_sp_diagonal ()) + , sec_rhs_ (jmatrix->get_sec_rhs ()) + , n_sec_vars_ (calc_model->n_sec_vars) + , ww (well->ww_value) + , wefac (well->exploitation_factor_) + { + if (is_w) d_w = calc_model->phase_d[FI_PHASE_WATER]; + if (is_g) d_g = calc_model->phase_d[FI_PHASE_GAS]; + if (is_o) d_o = calc_model->phase_d[FI_PHASE_OIL]; + } + + const cell_data_t &cell_data_; + const main_vars_t main_vars_; + const item_array_t &pressure_; + const item_array_t &gas_oil_ratio_; + const typename calc_model_t::invers_fvf_avgerage_t &invers_fvf_average_; + rate_data_t &well_rate_; + rate_data_t &well_rate_rc_; + item_t &gor_; + index_t d_w; + index_t d_g; + index_t d_o; + bool is_production; + connection_list_t &list_; + wells::injection_type injection_type_; + wells::rate_control_type control_type_; + + const rhs_item_array_t &sp_diagonal_; + const rhs_item_array_t &sec_rhs_; + int n_sec_vars_; + + item_t krow_tetaow; + item_t krp_tetap; + item_t sw_part; + item_t po_part; + item_t sg_part; + + item_t &ww; + item_t wefac; + + void + calc_rate (well_t *well) + { + connection_loop (well); + if (is_production_well) + { + compute_bw (well->bw_value, well->rate_.prod, well->get_well_controller ()->rate ().prod); + } + else + { + compute_bw (well->bw_value, well->rate_.inj, well->get_well_controller ()->rate ().inj); + } + } + + void + calc_derivs (well_t *well, bool is_rate) + { + if (is_rate) + { + connection_loop (well); + update_loop (well); + } + else + { + connection_loop (well); + } + } + + private: + + template + void + connection_loop (well_t *well) + { + if (list_.empty ()) + { + BOSOUT (section::wells, level::debug) + << "[" << well->name () << "] connection loop: connection list is empty" + << bs_end; + + return ; + } + + for (size_t i = 0, cnt = list_.size (); i < cnt; ++i) + { + typename well_t::sp_default_connection_t &c (list_[i]); + if (c->is_shut ()) + { + continue; + } + + index_t n_block = c->n_block (); + item_t Po = c->cur_bhp - pressure_[n_block]; + if (Po < item_t (0.0)) + { + connection_loop_main_var (c, cell_data_[n_block], main_vars_[n_block], Po); + } + else + { + connection_loop_main_var (c, cell_data_[n_block], main_vars_[n_block], Po); + } + } + } + + template + void + connection_loop_main_var (connection_t *c, const calc_model_data_t &data, main_var_t main_var, item_t Po) + { + if (main_var == FI_SG_VAR) + connection_loop_injection (c, data, Po); + else if (main_var == FI_RO_VAR) + connection_loop_injection (c, data, Po); + else if (main_var == FI_MOMG_VAR) + connection_loop_injection (c, data, Po); + } + + template + void + connection_loop_injection (connection_t *c, const calc_model_data_t &data, item_t Po) + { + if (is_water_injection () && is_gas_injection () && is_oil_injection ()) + { + connection_loop_concrete (c, data, Po); + } + else if (is_water_injection () && is_oil_injection ()) + { + connection_loop_concrete (c, data, Po); + } + else if (is_gas_injection () && is_oil_injection ()) + { + connection_loop_concrete (c, data, Po); + } + else if (is_water_injection ()) + { + connection_loop_concrete (c, data, Po); + } + else if (is_gas_injection ()) + { + connection_loop_concrete (c, data, Po); + } + else if (is_oil_injection ()) + { + connection_loop_concrete (c, data, Po); + } + } + + template + void + connection_loop_concrete (connection_t *c, const calc_model_data_t &data, item_t Po) + { + if (is_rate_loop) + { + calc_rate (c, data, Po); + } + else + { + calc_derivs (c, data, Po); + } + } + + + void + update_loop (well_t *well) + { + if (list_.empty ()) + { + BOSOUT (section::wells, level::debug) + << "[" << well->name () << "] connection loop: connection list is empty" + << bs_end; + + return ; + } + + item_t inv_ww = 1.0; + if (fabs (ww) >= 10e-16) + { + inv_ww = 1.0 / ww; + } + item_t ww_bw = well->bw_value * inv_ww; + + for (size_t i = 0, cnt = list_.size (); i < cnt; ++i) + { + typename well_t::sp_default_connection_t &c (list_[i]); + if (c->is_shut ()) + { + continue; + } + + update_wr (c, inv_ww); + update_rate (c, ww_bw); + } + } + + template + void + calc_rate (connection_t *c, const calc_model_data_t &data, item_t Po) + { + index_t n_block = c->n_block (); + item_t gw = c->get_fact (); + item_t Pw = Po; + item_t Pg = Po; + item_t wat = 0, gas = 0, oil = 0, free_gas = 0, solution_gas = 0; + + if (is_w_inj) + Pw -= data.cap_pressure [d_w]; + if (is_g_inj) + Pg -= data.cap_pressure[d_g]; + + if (!is_prod) + { + krow_tetaow = 0; + krp_tetap = 0; + + if (is_w) krow_tetaow += RELATIVE_PERM_W * INVERS_VISC_W; + if (is_o) krow_tetaow += RELATIVE_PERM_O * INVERS_VISC_O; + krp_tetap += krow_tetaow; + if (is_g) krp_tetap += RELATIVE_PERM_G * INVERS_VISC_G; + } + + if (is_g_inj) + { + if (is_prod) + { + free_gas = data.mobility[d_g]; + solution_gas = data.mobility[d_o] * gas_oil_ratio_[n_block]; + + if (main_var == FI_SG_VAR) + { + c->mobility_value[gas_idx] = free_gas + solution_gas; + } + else + { + c->mobility_value[gas_idx] = solution_gas; + } + + free_gas = gw * Pg * free_gas; + solution_gas = gw * Po * solution_gas; + gas = free_gas + solution_gas; + } + else + { + gas = detail::mobility ::gas (data, d_g, this); + c->mobility_value[gas_idx]= gas; + gas = gw * Pg * gas; + } + } + if (is_o_inj) + { + oil = detail::mobility ::oil (data, d_o, this); + c->mobility_value[oil_idx] = oil; + oil = gw * Po * oil; + } + if (is_w_inj) + { + wat = detail::mobility ::water (data, d_w, this); + c->mobility_value[wat_idx] = wat; + wat = gw * Pw * wat; + } + + if (is_g_inj) c->rate_value[gas_idx] = gas; + if (is_o_inj) c->rate_value[oil_idx] = oil; + if (is_w_inj) c->rate_value[wat_idx] = wat; + + rate_data_inner_t &rate = detail::rate_data ::get (c->rate_); + if (is_g_inj) rate.gas = gas; + if (is_o_inj) rate.oil = oil; + if (is_w_inj) rate.water = wat; + if (is_w_inj || is_o_inj) rate.liquid = wat + oil; + + if (is_prod && is_g_inj) + { + c->rate_.free_gas = free_gas; + c->rate_.solution_gas = solution_gas; + } + + rate_data_inner_t &rate_rc = detail::rate_data ::get (c->rate_rc_); + if (is_prod && is_g_inj) + { + rate_rc.gas = c->rate_.free_gas + c->rate_.solution_gas / data.invers_fvf[d_g]; + c->rate_rc_.free_gas = c->rate_.free_gas / invers_fvf_average_ [d_g]; + c->rate_rc_.solution_gas = c->rate_.solution_gas; + } + else if (!is_prod && is_g_inj) + { + rate_rc.gas = c->rate_.free_gas / invers_fvf_average_ [d_g]; + } + if (is_w_inj) rate_rc.water = wat / invers_fvf_average_ [d_w]; + if (is_o_inj) rate_rc.oil = oil / invers_fvf_average_ [d_o]; + if (is_w_inj || is_o_inj) rate_rc.liquid = rate_rc.water + rate_rc.oil; + + rate_data_inner_t &well_rate = detail::rate_data ::get (well_rate_); + if (is_g_inj) well_rate.gas += gas; + if (is_o_inj) well_rate.oil += oil; + if (is_w_inj) well_rate.water += wat; + if (is_w_inj || is_o_inj) + well_rate.liquid += wat + oil; + + if (is_prod) + { + well_rate_.free_gas += c->rate_.free_gas; + well_rate_.solution_gas += c->rate_.solution_gas; + } + + rate_data_inner_t &well_rate_rc = detail::rate_data ::get (well_rate_rc_); + if (is_g_inj) well_rate_rc.gas += rate_rc.gas; + if (is_o_inj) well_rate_rc.oil += rate_rc.oil; + if (is_w_inj) well_rate_rc.water += rate_rc.water; + if (is_w_inj || is_o_inj) + well_rate_rc.liquid += rate_rc.water + rate_rc.oil; + + if (is_prod) + { + well_rate_rc_.free_gas += c->rate_rc_.free_gas; + gor_ = well_rate_.solution_gas / rate.oil; + } + } + + template + void + wat_deriv (connection_t *c, const calc_model_data_t &data, const boost::array &mobility, item_t gw, item_t Pw) + { + if (is_w) + { + item_t sw_deriv = 0, po_deriv = 0, so_deriv = 0, sg_deriv = 0; + + if (is_prod) + { + if (is_g) sg_deriv = data.s_deriv_mobility[d_w * n_phases + d_g]; + if (is_o) so_deriv = data.s_deriv_mobility[d_w * n_phases + d_o]; + po_deriv = data.p_deriv_mobility[d_w]; + if (!is_1p) sw_deriv = data.s_deriv_mobility[d_w * n_phases + d_w]; + } + else + { + if (is_g && main_var == FI_SG_VAR) sg_deriv = INVERS_FVF_W * sg_part; + if (is_g && main_var != FI_SG_VAR) sg_deriv = INVERS_FVF_W * RELATIVE_PERM_O * GOR_DERIV_INVERS_VISC; + if (is_o) so_deriv = S_DERIV_RELATIVE_PERM_OO * INVERS_VISC_O; + item_t common = INVERS_FVF_W * krp_tetap * P_DERIV_INVERS_FVF_W; + po_deriv = (RELATIVE_PERM_O * P_DERIV_INVERS_VISC_O + + RELATIVE_PERM_W * P_DERIV_INVERS_VISC_W + - common); + if (!is_1p) sw_deriv = (S_DERIV_RELATIVE_PERM_WW * INVERS_VISC_W + + S_DERIV_RELATIVE_PERM_OW * INVERS_VISC_O + + RELATIVE_PERM_W * P_DERIV_INVERS_VISC_W * S_DERIV_CAP_PRESSURE_W + - common); + } + + + if (is_g) c->rr_value[wat_sg] = -gw * (Pw * sg_deriv); + if (is_o) c->rr_value[wat_so] = -gw * (Pw * so_deriv); + if (is_w) c->rr_value[wat_po] = -gw * (Pw * po_deriv - mobility[wat_idx]); + if (!is_1p) c->rr_value[wat_sw] = -gw * (Pw * sw_deriv - mobility[wat_idx] * S_DERIV_CAP_PRESSURE_W); + } + } + + template + void + gas_deriv (connection_t *c, const calc_model_data_t &data, const boost::array &mobility, item_t gw, item_t Pg, item_t Po, index_t n_block) + { + if (is_g) + { + item_t sw_deriv = 0, po_deriv = 0, so_deriv = 0, sg_deriv = 0; + if (is_prod) + { + if (!is_1p && main_var == FI_SG_VAR) sg_deriv = Pg * data.s_deriv_mobility[d_g * n_phases + d_g] + - data.mobility[d_g] * data.s_deriv_cap_pressure[d_g] + + gas_oil_ratio_[n_block] * data.s_deriv_mobility[d_o * n_phases + d_g] * Po; + if (!is_1p && main_var != FI_SG_VAR) sg_deriv = Po * (data.mobility[d_o] + gas_oil_ratio_[n_block] * data.s_deriv_mobility[d_o * n_phases + d_g]); + if (is_o) so_deriv = Pg * data.s_deriv_mobility[d_g * n_phases + d_o] + Po * data.s_deriv_mobility[d_o * n_phases + d_o] * gas_oil_ratio_[n_block]; + po_deriv = gas_oil_ratio_[n_block] * (data.p_deriv_mobility[d_o] * Po - data.mobility[d_o]); + if (main_var == FI_SG_VAR) po_deriv += data.p_deriv_mobility[d_g] * Pg - data.mobility[d_g] + data.p_deriv_gas_oil_ratio * data.mobility[d_o] * Po; + if (is_w) sw_deriv = Pg * data.s_deriv_mobility[d_g * n_phases + d_w] + Po * data.s_deriv_mobility[d_o * n_phases + d_w] * gas_oil_ratio_[n_block]; + } + else + { + if (!is_1p && main_var == FI_SG_VAR) sg_deriv = Pg * (S_DERIV_INVERS_FVF_G * krp_tetap + INVERS_FVF_G * sg_part) - mobility[gas_idx] * S_DERIV_CAP_PRESSURE_G; + if (!is_1p && main_var != FI_SG_VAR) sg_deriv = Pg * INVERS_FVF_G * RELATIVE_PERM_O * data.gor_deriv_invers_viscosity; + if (is_o) so_deriv = Pg * INVERS_FVF_G * S_DERIV_RELATIVE_PERM_GO; + if (main_var == FI_SG_VAR) po_deriv = Pg * (P_DERIV_INVERS_FVF_G * krp_tetap + INVERS_FVF_G * po_part) - INVERS_FVF_G * krp_tetap; + if (main_var != FI_SG_VAR) po_deriv = Pg * (P_DERIV_INVERS_FVF_G * krp_tetap + INVERS_FVF_G * po_part) - INVERS_FVF_G * krow_tetaow; + if (is_w) sw_deriv = Pg * INVERS_FVF_G * sw_part; + } + + if (!is_1p) c->rr_value[gas_sg] = -gw * sg_deriv; + if (is_o) c->rr_value[gas_so] = -gw * so_deriv; + if (is_g) c->rr_value[gas_po] = -gw * po_deriv; + if (is_w) c->rr_value[gas_sw] = -gw * sw_deriv; + } + } + + template + void + oil_deriv (connection_t *c, const calc_model_data_t &data, const boost::array &mobility, item_t gw, item_t Po) + { + if (is_o) + { + item_t sw_deriv = 0, po_deriv = 0, so_deriv = 0, sg_deriv = 0; + + if (is_prod) + { + if (is_g && main_var == FI_SG_VAR) sg_deriv = data.s_deriv_mobility[d_o * n_phases + d_g]; + if (is_g && main_var != FI_SG_VAR) sg_deriv = data.relative_perm[d_o] * data.gor_deriv_invers_visc_fvf; + if (!is_1p) so_deriv = data.s_deriv_mobility[d_o * n_phases + d_o]; + po_deriv = data.p_deriv_mobility[d_o]; + if (is_w) sw_deriv = data.s_deriv_mobility[d_o * n_phases + d_w]; + } + else + { + if (is_g && main_var == FI_SG_VAR) sg_deriv = INVERS_FVF_O * sg_part; + if (is_g && main_var != FI_SG_VAR) sg_deriv = RELATIVE_PERM_O * (INVERS_FVF_O * data.gor_deriv_invers_viscosity + INVERS_VISC_O * data.gor_deriv_invers_fvf); + if (!is_1p) so_deriv = INVERS_FVF_O * S_DERIV_RELATIVE_PERM_OO; + po_deriv = P_DERIV_INVERS_FVF_O * krp_tetap + INVERS_FVF_O * po_part; + if (is_w) sw_deriv = INVERS_FVF_O * sw_part; + } + + if (is_g) c->rr_value[oil_sg] = -gw * (Po * sg_deriv); + if (!is_1p) c->rr_value[oil_so] = -gw * (Po * so_deriv); + if (is_o) c->rr_value[oil_po] = -gw * (Po * po_deriv - mobility[oil_idx]); + if (is_w) c->rr_value[oil_sw] = -gw * (Po * sw_deriv); + } + } + + template + void + calc_derivs (connection_t *c, const calc_model_data_t &data, item_t Po) + { + index_t n_block = c->n_block (); + item_t gw = c->get_fact (); + item_t Pw = Po; + item_t Pg = Po; + + if (is_w) + Pw -= data.cap_pressure [d_w]; + if (is_g) + Pg -= data.cap_pressure[d_g]; + + if (!is_prod) + { + sw_part = 0; + po_part = 0; + sg_part = 0; + + if (is_g) sg_part += S_DERIV_RELATIVE_PERM_GG * INVERS_VISC_G; + if (is_g) sg_part += RELATIVE_PERM_G * S_DERIV_INVERS_VISC_G * CAP_PRESSURE_G; + if (is_g && is_o) sg_part += S_DERIV_RELATIVE_PERM_OG * INVERS_VISC_O; + + if (is_g) po_part += RELATIVE_PERM_G * P_DERIV_INVERS_VISC_G; + if (is_o) po_part += RELATIVE_PERM_O * P_DERIV_INVERS_VISC_O; + if (is_w) po_part += RELATIVE_PERM_W * P_DERIV_INVERS_VISC_W; + + if (is_w && is_o) sw_part += S_DERIV_RELATIVE_PERM_OW * INVERS_VISC_O; + if (is_w) sw_part += S_DERIV_RELATIVE_PERM_WW * INVERS_VISC_W; + if (is_w) sw_part += RELATIVE_PERM_W * S_DERIV_INVERS_VISC_W * CAP_PRESSURE_W; + if (is_w) sw_part -= P_DERIV_INVERS_FVF_W * CAP_PRESSURE_W; + + + } + + if (is_g && is_g_inj) gas_deriv (c, data, c->mobility_value, gw, Pg, Po, n_block); + if (is_o && is_o_inj) oil_deriv (c, data, c->mobility_value, gw, Po); + if (is_w && is_w_inj) wat_deriv (c, data, c->mobility_value, gw, Pw); + + m_minus_vv_prod ::eliminate (&c->rr_value[b_sqr], &sp_diagonal_[n_block * n_phases], c->rr_value); + + if (is_rate) + { + if (is_w && is_water_control ()) + { + if (n_phases > 0) c->wr_value[0] += c->rr_value [wat_idx * n_phases + 0]; + if (n_phases > 1) c->wr_value[1] += c->rr_value [wat_idx * n_phases + 1]; + if (n_phases > 2) c->wr_value[2] += c->rr_value [wat_idx * n_phases + 2]; + } + if (is_g && is_gas_control ()) + { + if (n_phases > 0) c->wr_value[0] += c->rr_value [gas_idx * n_phases + 0]; + if (n_phases > 1) c->wr_value[1] += c->rr_value [gas_idx * n_phases + 1]; + if (n_phases > 2) c->wr_value[2] += c->rr_value [gas_idx * n_phases + 2]; + } + if (is_o && is_oil_control ()) + { + if (n_phases > 0) c->wr_value[0] += c->rr_value [oil_idx * n_phases + 0]; + if (n_phases > 1) c->wr_value[1] += c->rr_value [oil_idx * n_phases + 1]; + if (n_phases > 2) c->wr_value[2] += c->rr_value [oil_idx * n_phases + 2]; + } + + item_t rw_wat = 0, rw_gas = 0, rw_oil = 0; + + if (is_w && is_water_injection ()) rw_wat = c->rw_value[wat_idx] = -gw * c->mobility_value[wat_idx]; + if (is_g && is_gas_injection ()) rw_gas = c->rw_value[gas_idx] = -gw * c->mobility_value[gas_idx]; + if (is_o && is_oil_injection ()) rw_oil = c->rw_value[oil_idx] = -gw * c->mobility_value[oil_idx]; + + if (is_w && is_water_control ()) ww += rw_wat; + if (is_g && is_gas_control ()) ww += rw_gas; + if (is_o && is_oil_control ()) ww += rw_oil; + } + + if (wefac > 0.0) + { + if (n_phases > 0) c->rr_value[0] = wefac * c->rr_value[0]; + if (n_phases > 1) c->rr_value[1] = wefac * c->rr_value[1]; + if (n_phases > 1) c->rr_value[2] = wefac * c->rr_value[2]; + if (n_phases > 1) c->rr_value[3] = wefac * c->rr_value[3]; + if (n_phases > 2) c->rr_value[4] = wefac * c->rr_value[4]; + if (n_phases > 2) c->rr_value[5] = wefac * c->rr_value[5]; + if (n_phases > 2) c->rr_value[6] = wefac * c->rr_value[6]; + if (n_phases > 2) c->rr_value[7] = wefac * c->rr_value[7]; + if (n_phases > 2) c->rr_value[8] = wefac * c->rr_value[8]; + + if (is_rate) + { + if (n_phases > 0) c->rw_value[0] = wefac * c->rw_value[0]; + if (n_phases > 1) c->rw_value[1] = wefac * c->rw_value[1]; + if (n_phases > 2) c->rw_value[2] = wefac * c->rw_value[2]; + } + } + + v_minus_vs_prod ::eliminate (&c->rr_value[b_sqr], sec_rhs_[n_sec_vars_ * n_block], c->rate_value); + //c->ps_value[0] = c->rr_value[b_sqr + 0]; + //c->ps_value[1] = c->rr_value[b_sqr + 1]; + //c->ps_value[2] = c->rr_value[b_sqr + 2]; + //c->rr_value[b_sqr + 0] = 0; + //c->rr_value[b_sqr + 1] = 0; + //c->rr_value[b_sqr + 2] = 0; + } + + void + compute_bw (item_t &bw, const rate_data_inner_t &rate, const rate_data_inner_t &limit) + { + bw = 0; + item_t mult = is_production_well ? -1.0 : 1.0; + if (is_o && is_w && (is_oil_control () && is_water_control () || is_liquid_control ())) + { + bw += (rate.oil + rate.water) - mult * limit.liquid; + } + else if (is_o && (is_oil_control () || is_liquid_control ())) + { + bw += (rate.oil) - mult * limit.oil; + } + else if (is_w && (is_water_control () || is_liquid_control ())) + { + bw += (rate.water) - mult * limit.water; + } + else if (is_g && is_gas_control ()) + { + bw += (rate.gas) - mult * limit.gas; + } + } + + void + update_wr (connection_t *c, item_t inv_ww) + { + if (n_phases > 0) c->wr_value[0] *= inv_ww; + if (n_phases > 1) c->wr_value[1] *= inv_ww; + if (n_phases > 2) c->wr_value[2] *= inv_ww; + } + + void + update_rate (connection_t *c, item_t ww_bw) + { + if (n_phases > 0) c->rate_value[0] -= c->rw_value[0] * ww_bw; + if (n_phases > 1) c->rate_value[1] -= c->rw_value[1] * ww_bw; + if (n_phases > 2) c->rate_value[2] -= c->rw_value[2] * ww_bw; + } + + template + bool + is_liquid_control () const + { + if (is_prod) + { + return control_type_ == wells::liquid_rate_control; + } + else + { + return injection_type_ == wells::injection_oil || injection_type_ == wells::injection_water; + } + } + template + bool + is_oil_control () const + { + if (is_prod) + { + return is_o && (control_type_ == wells::oil_rate_control || control_type_ == wells::liquid_rate_control); + } + else + { + return is_o && injection_type_ == wells::injection_oil; + } + } + template + bool + is_water_control () const + { + if (is_prod) + { + return is_w && (control_type_ == wells::water_rate_control || control_type_ == wells::liquid_rate_control); + } + else + { + return is_w && injection_type_ == wells::injection_water; + } + } + template + bool + is_gas_control () const + { + if (is_prod) + { + return is_g && control_type_ == wells::gas_rate_control; + } + else + { + return is_g && injection_type_ == wells::injection_gas; + } + } + template + bool + is_water_injection () const + { + if (is_prod) + { + return is_w; + } + else + { + return is_w && injection_type_ == wells::injection_water; + } + } + template + bool + is_gas_injection () const + { + if (is_prod) + { + return is_g; + } + else + { + return is_g && injection_type_ == wells::injection_gas; + } + } + template + bool + is_oil_injection () const + { + if (is_prod) + { + return is_o; + } + else + { + return is_o && injection_type_ == wells::injection_oil; + } + } + }; + +} // namespace wells +} // namespace blue_sky + + +#endif // #ifndef BS_BOS_CORE_DEFAULT_WELL_CALC_RATE_H_ + diff --git a/bs_bos_core/src/default_well_rate_control_factory.cpp b/bs_bos_core/src/default_well_rate_control_factory.cpp new file mode 100644 index 0000000..e33da59 --- /dev/null +++ b/bs_bos_core/src/default_well_rate_control_factory.cpp @@ -0,0 +1,119 @@ +/** + * \file default_well_rate_control_factory.cpp + * \brief + * \author Sergey Miryanov + * \date 21.05.2009 + * */ +#include "stdafx.h" +#include "default_well_rate_control_factory.h" + +#include "calc_well.h" +#include "well_controller.h" +#include "well_connection.h" + +#include "calc_model_data_accessors.h" + +#include "well_rate_control.h" +#include "well_rate_control_impl.h" + +#include "well_rate_control_prod_mobility.h" +#include "well_rate_control_inj_mobility.h" + +#include "well_rate_control_rate.h" +#include "well_rate_control_bhp_deriv.h" +#include "well_rate_control_rate_deriv.h" + +#include "well_rate_control_impl_type.h" +#include "reservoir.h" +#include "facility_manager.h" + +namespace blue_sky { +namespace wells { + + template + default_well_rate_control_factory ::default_well_rate_control_factory (bs_type_ctor_param param) + : base_t (param) + { + } + template + default_well_rate_control_factory ::default_well_rate_control_factory (const default_well_rate_control_factory &f) + : bs_refcounter (), base_t (f) + { + } + + template + typename default_well_rate_control_factory ::sp_well_rate_control_t + default_well_rate_control_factory ::create_control (rate_control_type control_type, bool is_bhp, + bool /*is_production*/, + const sp_calc_model_t &calc_model) + { + typedef typename strategy_t::index_t index_t; + + if (control_type == null_control) + { + return BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true); + } + + + index_t n_phases = calc_model->n_phases; + bool is_o = calc_model->is_oil (); + bool is_w = calc_model->is_water (); + bool is_g = calc_model->is_gas (); + + if (n_phases == 3) + { + return is_bhp + ? BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + : BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + ; + } + else if (is_o && is_w) + { + return is_bhp + ? BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + : BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + ; + } + else if (is_o && is_g) + { + return is_bhp + ? BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + : BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + ; + } + else if (is_o) + { + return is_bhp + ? BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + : BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + ; + } + else if (is_w) + { + return is_bhp + ? BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + : BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + ; + } + else if (is_g) + { + return is_bhp + ? BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + : BS_KERNEL.create_object (well_rate_control_impl >::bs_type (), true) + ; + } + else + { + bs_throw_exception ("can't create well_rate_control_impl"); + } + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (default_well_rate_control_factory, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (default_well_rate_control_factory, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_well_rate_control_factory ), 1, (objbase), "default_well_rate_control_fi", "Default factory for well_rate_control", "Default factory for well_rate_control", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_well_rate_control_factory ), 1, (objbase), "default_well_rate_control_di", "Default factory for well_rate_control", "Default factory for well_rate_control", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (default_well_rate_control_factory ), 1, (objbase), "default_well_rate_control_mixi", "Default factory for well_rate_control", "Default factory for well_rate_control", false); + +} // namespace wells +} // namespace blue_sky + diff --git a/bs_bos_core/src/event_base.cpp b/bs_bos_core/src/event_base.cpp new file mode 100644 index 0000000..a201d6a --- /dev/null +++ b/bs_bos_core/src/event_base.cpp @@ -0,0 +1,239 @@ +/** + * @file event_base.h + * @brief cpp file for event base + * @author Morozov Andrey + * @date 2008-06-07 + * */ +#include "stdafx.h" +#include +#include +//#include + +#include "event_base.h" +#include "str_functor.h" + +using namespace boost::spirit; + +namespace blue_sky { + + namespace detail { + + template + struct str_functor + { + typedef smart_ptr sp_named_pbase; + typedef void (T::*method_t)(const sp_named_pbase ¶ms_, const char*, const char*); + typedef T self_t; + + str_functor (self_t *self, const sp_named_pbase ¶ms, method_t method) + : self (self) + , params_ (params) + , method (method) + { + } + + void operator() (const char *first, const char *last) const + { + (self->*method) (params_, first, last); + } + + self_t *self; + sp_named_pbase params_; + method_t method; + }; + + template + struct char_functor + { + typedef smart_ptr sp_named_pbase; + typedef void (T::*method_t)(const sp_named_pbase ¶ms_, const char); + typedef T self_t; + + char_functor (self_t *self, const sp_named_pbase ¶ms, method_t method) + : self (self) + , params_ (params) + , method (method) + { + } + + void operator() (const char c) const + { + (self->*method) (params_, c); + } + + self_t *self; + sp_named_pbase params_; + method_t method; + }; + } + + + template + event_base::~event_base () + { + + } + + //constructors + template + event_base::event_base(bs_type_ctor_param /*param*/) + { + num = 1; + index = 1; + } + template + event_base::event_base(const event_base& src) + : bs_refcounter (src), objbase (src) + { + *this = src; + } + + template + void + event_base::init (const std::string &event_name, const std::string & params) + { +#ifdef _DEBUG + debug_data_.params = params; +#endif + + parse (params, main_params ()); + if (!no_error_) + { + BOSWARN (section::read_data, level::warning) << + boost::format ("Warnings exist while processing keyword %s") % event_name + << bs_end; + } + } + + template + void + event_base ::add_next_line (const std::string &event_name, const std::string ¶ms) + { + const sp_named_pbase &next_line_params = add_next_line_params (); + if (!next_line_params) + { + bs_throw_exception ("Can't create next_line_params"); + } + + parse (params, next_line_params); + if (!no_error_) + { + BOSWARN (section::read_data, level::warning) << + boost::format ("Warnings exist while processing keyword %s") % event_name + << bs_end; + } + } + + template + void + event_base::save_value(const sp_named_pbase ¶ms_, char const* first, char const* last) //< save a string value + { + std::string str (first, last); + + for (int c = 0; c < num; ++c, ++index) + { + no_error_ = params_->set_value (index, str) && no_error_; + } + } + + + template + void + event_base::save_def (const sp_named_pbase ¶ms_, const char /*c*/) //< paste a default value + { + if (index + num > (int)params_->size ()) + { + BOSERR (section::schedule, level::error) << "Event params parser: too many parameters (" << index << ", " << main_params ()->size () << ")" << bs_end; + return ; + } + + index += num; + } + + template + void + event_base ::clear_num (const sp_named_pbase &, const char *, const char *) + { + num = 1; + } + + template + void + event_base::parse(const std::string ¶ms_str, const sp_named_pbase ¶ms) + { + BS_ASSERT (params); + + detail::char_functor save_def_ (this, params, &self_t::save_def); + detail::str_functor clear_num_ (this, params, &self_t::clear_num); + detail::str_functor save_value_ (this, params, &self_t::save_value); + + // matches to tabs and/or spaces repeated one or more times + rule<> delimeter_p = +(space_p); + + // matches to any type value + rule<> value_p = confix_p ("\"", (+anychar_p)[save_value_], "\"") + | confix_p ("'", (+anychar_p)[save_value_], "'") + | (+graph_p)[save_value_]; + + // matches to * (default value) + rule<> default_value_p = ch_p ('*') [save_def_]; + + // handled N*A constructions - repeat A value N times + rule<> wrap_p = int_p[assign_a (num)] >> ch_p ('*') >> value_p; + + // handled N* constructions - repeat default value N times + rule<> wrap_default_p = int_p[assign_a (num)] >> ch_p ('*') [save_def_]; + + // matches to parameter + rule <> param_p = wrap_p + | wrap_default_p + | (*anychar_p)[clear_num_] >> nothing_p + | default_value_p + | value_p + ; + + rule <> event_p = param_p >> *(delimeter_p >> param_p); //main parser with delimiters + + index = 1; + num = 1; + no_error_ = true; + boost::spirit::parse (params_str.c_str(), event_p).full; //Go! Go! Go! + + num = (int) params->size()-index; + //if number of values in parameter string is + //less then the number of prescribed parameters + //we skip rest as defaults + save_def (params); + } + + template + void + event_base::apply (const sp_top &/*top*/, const sp_mesh_iface_t &/*mesh*/, const sp_calc_model_t &/*calc_model*/) const + { + BS_ASSERT (false && "BASE METHOD CALL"); + } + + //bs stuff + BLUE_SKY_TYPE_STD_CREATE_T_DEF (event_base, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (event_base, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (event_base), 1, (property_base), "BOS_Core event_base class (seq fi)", "BOS_Core event_base class", "BOS_Core event_base class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (event_base), 1, (property_base), "BOS_Core event_base class (seq di)", "BOS_Core event_base class", "BOS_Core event_base class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (event_base), 1, (property_base), "BOS_Core event_base class (seq mixi)", "BOS_Core event_base class", "BOS_Core event_base class", false) + + + bool + event_base_register_types (const plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, event_base ::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, event_base ::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, event_base ::bs_type ()); + BS_ASSERT (res); + + return true; + } +}//ns bs + diff --git a/bs_bos_core/src/event_filter.cpp b/bs_bos_core/src/event_filter.cpp new file mode 100644 index 0000000..fb6138f --- /dev/null +++ b/bs_bos_core/src/event_filter.cpp @@ -0,0 +1,60 @@ +/** + * \file event_filter.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 15.12.2008 + * */ +#include "stdafx.h" +#include "event_filter.h" + +namespace blue_sky + { + + event_filter::event_filter(bs_type_ctor_param /*param = NULL */) + { + } + event_filter::event_filter(const event_filter &x) + : bs_refcounter (x), objbase (x) + { + + } + + bool + event_filter::accept_well (const std::string &well_name) const + { + if (reject_all_) + return false; + + well_name_list_t::const_iterator it = std::find (well_name_list_.begin (), well_name_list_.end (), well_name); + if (it != well_name_list_.end ()) + return false; + + return true; + } + + void + event_filter::add_filter_well (const std::string &well_name) + { + well_name_list_t::iterator it = std::find (well_name_list_.begin (), well_name_list_.end (), well_name); + if (it == well_name_list_.end ()) + { + well_name_list_.push_back (well_name); + } + else + { + BS_ASSERT (false && "well_name already in list") (well_name); + } + } + + void + event_filter::set_reject_all (bool reject_all) + { + reject_all_ = reject_all; + } + + BLUE_SKY_TYPE_STD_CREATE (event_filter); + BLUE_SKY_TYPE_STD_COPY (event_filter); + BLUE_SKY_TYPE_IMPL_SHORT (event_filter, objbase, "event_filter"); + +} // namespace blue_sky + diff --git a/bs_bos_core/src/event_manager.cpp b/bs_bos_core/src/event_manager.cpp new file mode 100644 index 0000000..8b8174a --- /dev/null +++ b/bs_bos_core/src/event_manager.cpp @@ -0,0 +1,151 @@ +/** + * @file well_event.h + * @brief event manager functions + * @author Morozov Andrey + * @date 2008-06-07 + */ +#include "stdafx.h" + +#include "event_manager.h" +#include "well_events.h" + +#include +#include "strategy_name.h" + +//using namespace boost::spirit; +//using namespace boost::gregorian; + +namespace blue_sky + { + + template + event_manager::~event_manager () + { + + } + + template + event_manager::event_manager(bs_type_ctor_param /*param*/) + { + } + + template + event_manager::event_manager(const event_manager& src) + : bs_refcounter (src), objbase (src) + { + *this = src; + } + + template + void + event_manager ::process_event (const date_t &date, const std::string &event_name, const std::string &event_params) + { + if (current_event_) + { + current_event_->add_next_line (event_name, event_params); + } + else + { + current_event_ = create_event (date, event_name, event_params); + if (!current_event_->is_multi_line ()) + { + current_event_ = 0; + } + } + } + template + void + event_manager ::end_event () + { + current_event_ = 0; + } + + template + typename event_manager::sp_event_base + event_manager::create_event (const boost::posix_time::ptime &date, const std::string & event_name, const std::string & event_params) + { + boost::regex re_check_type (event_name + "(.*)_" + tools::strategy_name ::name ()); + + sp_obj event_object; + + const std::vector &types = BS_KERNEL.registered_types (); + for (size_t i = 0, cnt = types.size (); i < cnt; ++i) + { + const type_descriptor &td = types[i].td_; + + if (boost::regex_match (td.stype_.c_str (), re_check_type)) + { + event_object = BS_KERNEL.create_object (td); + break; + } + } + if (!event_object) + { + bs_throw_exception (boost::format ("Type (%s) not registered (params: %s)") % event_name % event_params); + } + + sp_event_base event (event_object, bs_static_cast ()); + if (!event) + { + bs_throw_exception (boost::format ("Created object for type (%s) can't be casted to event_base (params: %s)") % event_name % event_params); + } + + event_list[date].push_back (event); // TODO: posix_time::ptime + event->init (event_name, event_params); + return event; + } + + +#define EVENT_LIST_REGISTRATION(WHERE, strategy_t) \ + REG_EVENT_IN_##WHERE(WELSPECS, strategy_t) \ + REG_EVENT_IN_##WHERE(WELLCON, strategy_t) \ + REG_EVENT_IN_##WHERE(COMPDAT, strategy_t) \ + REG_EVENT_IN_##WHERE(WCONPROD, strategy_t) \ + REG_EVENT_IN_##WHERE(WCONHIST, strategy_t) \ + REG_EVENT_IN_##WHERE(WCONINJE, strategy_t) \ + REG_EVENT_IN_##WHERE(WECON, strategy_t) \ + REG_EVENT_IN_##WHERE(WECONINJ, strategy_t) \ + REG_EVENT_IN_##WHERE(WEFAC, strategy_t) \ + REG_EVENT_IN_##WHERE(WELTARG, strategy_t) \ + REG_EVENT_IN_##WHERE(WPIMULT, strategy_t) \ + REG_EVENT_IN_##WHERE(COMPENSATION, strategy_t) \ + REG_EVENT_IN_##WHERE(FRACTURE, strategy_t) \ + REG_EVENT_IN_##WHERE(PERMFRAC, strategy_t) + +#define REG_EVENT_IN_FACTORY(NAME, strategy_t)\ + factory_register > (#NAME); + +#define REG_EVENT_IN_KERNEL(NAME, strategy_t)\ + res &= BS_KERNEL.register_type (pd, NAME##_event::bs_type ()); BS_ASSERT (res); + + //bs stuff + BLUE_SKY_TYPE_STD_CREATE_T_DEF (event_manager, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (event_manager, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (event_manager ), 1, (objbase), "event_manager_seq_fi", "BOS_Core event_manager class", "BOS_Core event_manager class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (event_manager ), 1, (objbase), "event_manager_seq_di", "BOS_Core event_manager class", "BOS_Core event_manager class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (event_manager ), 1, (objbase), "event_manager_seq_mixi", "BOS_Core event_manager class", "BOS_Core event_manager class", false) + + bool + well_events_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + EVENT_LIST_REGISTRATION(KERNEL, base_strategy_fi); + EVENT_LIST_REGISTRATION(KERNEL, base_strategy_di); + EVENT_LIST_REGISTRATION(KERNEL, base_strategy_mixi); + return res; + } + + bool + event_manager_register_types (const plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, event_manager ::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, event_manager ::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, event_manager ::bs_type ()); BS_ASSERT (res); + + return true; + } + +}//ns bs + diff --git a/bs_bos_core/src/facility_manager.cpp b/bs_bos_core/src/facility_manager.cpp new file mode 100644 index 0000000..1c30da5 --- /dev/null +++ b/bs_bos_core/src/facility_manager.cpp @@ -0,0 +1,152 @@ +/** + * \file facility_manager.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 17.07.2008 + * */ +#include "stdafx.h" + +#include "facility_manager.h" +#include "data_storage_interface.h" +#include "calc_well.h" +#include "well_connection.h" +#include "reservoir.h" +#include "facility_manager.h" + +namespace blue_sky + { + + BLUE_SKY_TYPE_IMPL_T_EXT (2, (bos_val_table ::sp_facility_t>), 1, (objbase), "bos_map_seq_fi", "map of str and facility", "map of str and facility", false); + BLUE_SKY_TYPE_IMPL_T_EXT (2, (bos_val_table ::sp_facility_t>), 1, (objbase), "bos_map_seq_di", "map of str and facility", "map of str and facility", false); + BLUE_SKY_TYPE_IMPL_T_EXT (2, (bos_val_table ::sp_facility_t>), 1, (objbase), "bos_map_seq_mixi", "map of str and facility", "map of str and facility", false); + + template + facility_manager::facility_manager (bs_type_ctor_param /* param = NULL */) + : facility_list_ (BS_KERNEL.create_object (facility_map_t::bs_type ())) + { + + } + + template + facility_manager::facility_manager (const facility_manager &fs) + : bs_refcounter (fs), objbase (fs), facility_list_ (fs.facility_list_) + { + + } + + template + typename facility_manager::sp_well_t + facility_manager::get_well (const std::string &/*group_name*/, const std::string &well_name) const + { + typename facility_map_t::const_iterator it = facility_list_->find (well_name); + if (it == facility_list_->end ()) + { + return 0; + } + + sp_well_t w (it->second, bs_dynamic_cast ()); + BS_ASSERT (w) (well_name); + + return w; + } + + template + typename facility_manager::sp_well_t + facility_manager::get_well (const std::string &well_name) const + { + typename facility_map_t::const_iterator it = facility_list_->find (well_name); + if (it == facility_list_->end ()) + { + BS_ASSERT (false && "Can't find well") (well_name); + return 0; + } + + sp_well_t w (it->second, bs_dynamic_cast ()); + return w; + } + + template + void + facility_manager::add_well (const sp_well_t &w) + { + BS_ASSERT (w); + BS_ASSERT (w->get_name ().size ()); + + facility_list_->insert (std::make_pair (w->get_name (), w)); + BOSOUT (section::wells, level::low) << "Inserted " << w->get_name () << bs_end; + } + + template + void + facility_manager::save_data (const sp_storage_t &storage) const + { + typename facility_map_t::const_iterator it = facility_list_->begin (), e = facility_list_->end (); + for (; it != e; ++it) + { + storage->save (it->second); + } + } + + template + typename facility_manager::well_const_iterator_t + facility_manager::wells_begin () const + { + return facility_list_->begin (); + //const sp_facility_map_t &locked_list (facility_list_); + //return well_iterator_t (locked_list, locked_list->begin ()); + } + template + typename facility_manager::well_const_iterator_t + facility_manager::wells_end () const + { + return facility_list_->end (); + //const sp_facility_map_t &locked_list (facility_list_); + //return well_iterator_t (locked_list, locked_list->end ()); + } + //template + //typename facility_manager::well_iterator_t + //facility_manager::wells_begin () + // { + // return facility_list_->begin (); + // //const sp_facility_map_t &locked_list (facility_list_); + // //return well_iterator_t (locked_list, locked_list->begin ()); + // } + //template + //typename facility_manager::well_iterator_t + //facility_manager::wells_end () + // { + // return facility_list_->end (); + // //const sp_facility_map_t &locked_list (facility_list_); + // //return well_iterator_t (locked_list, locked_list->end ()); + // } + + /*template + unsigned int + facility_manager::wells_size () const { + return facility_list_.size (); + }*/ + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF (facility_manager, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (facility_manager, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (facility_manager), 1, (objbase), "facility_manager_seq_fi", "facility_manager_seq_fi", "facility_manager_seq_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (facility_manager), 1, (objbase), "facility_manager_seq_di", "facility_manager_seq_di", "facility_manager_seq_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (facility_manager), 1, (objbase), "facility_manager_seq_mixi", "facility_manager_seq_mixi", "facility_manager_seq_mixi", false); + ////////////////////////////////////////////////////////////////////////// + + bool + facility_manager_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, facility_manager::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, facility_manager::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, facility_manager::bs_type ()); + BS_ASSERT (res); + + return res; + } + +} // namespace blue_sky diff --git a/bs_bos_core/src/fi_params.cpp b/bs_bos_core/src/fi_params.cpp new file mode 100644 index 0000000..d5e4725 --- /dev/null +++ b/bs_bos_core/src/fi_params.cpp @@ -0,0 +1,459 @@ +/*! \file fi_params.cpp + \brief fi_params class implementations + \author Nikonov Max +*/ +#include "stdafx.h" +#include "fi_params.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "read_class.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + void fi_params::set_default_values () + { + physical_constants ph_const; + + this->params_names.resize(fi_params::FI_PARAMS_TOTAL+1); + ereg (PVT_PRESSURE_RANGE_MAX, "PVT_PRESSURE_MAX", "PVT tables maximum pressure"); + ereg (PVT_PRESSURE_RANGE_MIN, "PVT_PRESSURE_MIN", "PVT tables minimal pressure"); + ereg (PVTO_RS_RANGE_MAX, "PVTO_RS_MAX", "PVTO maximum RS for slop table"); + ereg (PVTO_RS_RANGE_MIN, "PVTO_RS_MIN", "PVTO minimum RS for slop table"); + ereg (MAX_TS, "TS_MAX", "maximum allowed time step length"); + ereg (MIN_TS, "TS_MIN", "minimum allowed time step length"); + ereg (FIRST_TS, "TS_FIRST", "first simulation time step length"); + ereg (LIN_SOLV_RESIDUAL, "LITERS_RESID", "tolerance for linear solver"); + ereg (NEWTON_RESIDUAL, "NITERS_RESID", "tolerance for newton process"); + ereg (TS_INC_MULT, "TS_INC_MULT", "multiplier for incrementing time step length"); + ereg (TS_DEC_MULT, "TS_DEC_MULT", "multiplier for decrementing time step length"); + ereg (OVERDRAFT, "TS_OVERDRAFT", "overdraft factor (any time step could be multiplied by this factor to achieve end of report time step)"); + ereg (MAX_P_CORRECTION, "P_CORR_MAX", "maximum allowed newton correction for pressure"); + ereg (MAX_S_CORRECTION, "S_CORR_MAX", "maximum allowed newton correction for saturation"); + ereg (MAX_RS_CORRECTION, "RS_CORR_MAX", "maximum allowed newton correction for gas oil ratio"); + ereg (MAX_P_WELL_CORRECTION, "WELL_P_CORR__MAX", "maximum allowed newton correction for well pressure"); + EREG(fi_params,WAT_ROW_MULT,"multiplier for water equation in Jacobian"); + EREG(fi_params,GAS_ROW_MULT,"multiplier for gas equation in Jacobian"); + EREG(fi_params,OIL_ROW_MULT,"multiplier for oil equation in Jacobian"); + ereg (PRESSURE_COL_MULT, "P_COL_MULT", "multiplier for pressure derivates column in Jacobian"); + EREG(fi_params,TS_OMEGA,"omega coef in time step controling"); + EREG(fi_params,TS_DP,"pressure change for time step controling"); + EREG(fi_params,TS_DS,"saturation change for time step controling"); + EREG(fi_params,DP_MIN_CHOP,"minimum pressure chop"); + EREG(fi_params,DS_MIN_CHOP,"minimum saturation chop"); + ereg (MAX_ALLOWED_LIN_SOLV_RESID, "LITERS_MAX_RESID", "maximum allowed residual"); + EREG(fi_params,AMG_RESID,"tolerance for AMG preconditioner"); + EREG(fi_params,TS_DRS,"Rs change for time step controling"); + EREG(fi_params,MAX_NORM_ON_TS,"if norm on time step is greater than this value restart occur"); + EREG(fi_params,DRSDT,"Maximum rate of increase of solution GOR"); + EREG(fi_params,GAS_NORM_MULT,"multiplier for gas norm"); + // compositional + /*EREG(fi_params,COMP_PARAMS_D_MASS_BALANCE,"Scaled mass balance equation residuals. Equations are scaled by the accumulation terms (component mass dividing timestep size)."); + EREG(fi_params,COMP_PARAMS_D_PHASE_EQUIL,"Scaled phase equilibrium relation residuals. These are scaled by the component fugacities in the gas phase"); + EREG(fi_params,COMP_PARAMS_D_WELL_RATE,"Scaled well equation residuals, scaled by well input rate"); + EREG(fi_params,COMP_PARAMS_D_MAX_DP,"The maximum scaled pressure change (absolute pressure change divided by the average reservoir pressure)"); + EREG(fi_params,COMP_PARAMS_D_MAX_DS,"The maximum absolute saturation change"); + EREG(fi_params,COMP_PARAMS_D_MAX_DXCP,"The maximum absolute component mole fraction change"); + EREG(fi_params,COMP_PARAMS_D_TS_DP,"time step controling pressure change"); + EREG(fi_params,COMP_PARAMS_D_TS_DS,"time step controling saturation change"); + EREG(fi_params,COMP_PARAMS_D_TS_DXCP,"time step controling mole fraction change"); + EREG(fi_params,COMP_PARAMS_D_MAX_P_CORRECTION,"maximum allowed newton correction for pressure"); + EREG(fi_params,COMP_PARAMS_D_MAX_S_CORRECTION,"maximum allowed newton correction for saturation"); + EREG(fi_params,COMP_PARAMS_D_MAX_XCP_CORRECTION,"maximum allowed newton correction for mole fraction");*/ + // black oil + EREG(fi_params,MASS_BALANS_ERROR,"maximum allowed mass balans error"); + EREG(fi_params,MAX_NORM_ON_FIRST_N,"maximum allowed norm on first newton iteration"); + EREG(fi_params,P_DIMENSION_LESS_SCALE_FACTOR,"scale factor for dimension less pressure"); + EREG(fi_params,APPL_CHOP_PERC,"APPL_CHOP_PERC"); + EREG(fi_params,APPL_CHOP_BND,"APPL_CHOP_BND"); + EREG(fi_params,LIN_SOLV_MATBAL_RESIDUAL,"mat. balans tolerance for linear solver"); + EREG(fi_params,D_TOTAL,"all parameters should be before this item"); + + //! indexes for integer parameters + EREG(fi_params,PVT_INTERP_POINTS,"number of interpolation points"); + ereg (NEWTON_ITERS_NUM, "NITERS_NUM", "maximum allowed newton iterations number"); + ereg (LIN_ITERS_NUM, "LITERS_NUM", "maximum allowed linear iterations number"); + ereg (NEWTON_ITERS_INC, "NITERS_INC", "number of newton iterations to increment step length"); + ereg (NEWTON_ITERS_AMG, "NITERS_AMG", "number of newton iterations to build full amg setup"); + EREG(fi_params,APPROX_STEPS,"number of approximation steps"); + EREG(fi_params,SELECT_SOL_STEPS,"number of steps to select newton correction force term"); + ereg (LIN_SOLVER_TYPE, "LSOLV_TYPE", "type of linear solver"); + EREG(fi_params,GMRES_ORTONORM_VLEN,"number of vectors in GMRES to ortonorm"); + ereg (AMG_LIN_ITERS_NUM, "AMG_LITERS_NUM", "maximum allowed AMG solver iterations"); + ereg (WELL_NEWTON_ITERS_NUM, "WELL_NITERS_NUM", "maximum number of well internal newton iterations"); + EREG(fi_params,PREC_TYPE,"type of the preconditioner for linear solver"); + ereg (PREC_TYPE_ONE_PHASE, "1PHASE_PREC_TYPE", "type of the preconditioner for linear solver for 1 phase problem"); + EREG(fi_params,MIN_CELLS_IN_REGION,"minimum allowed cells in region for ACTNUM = 1"); + EREG(fi_params,SAVE_STEP_DATA_PERIOD,"save step data every n step"); + EREG(fi_params,I_TOTAL,"all parameters should be before this item"); + + //! indexes for boolian parameters + EREG(fi_params,PRINT_PVTO_TABLE,"if this item is set print PVTO to LOG file"); + EREG(fi_params,PRINT_PVTW_TABLE,"print pvtw interpolation table"); + EREG(fi_params,PRINT_PVTG_TABLE,"print pvtg interpolation table"); + EREG(fi_params,STORE_PANE_FLOW_RATES,"boolean store pane flow rates"); + ereg (NEW_TS_SELECTION_ALGORITHM, "NEW_TS_SELECTION", "use new algorithm for ts selection"); + EREG(fi_params,SAVE_STEP_MAPS,"save maps on time step in the rst file"); + EREG(fi_params,SAVE_INITIAL_DATA,"save initial data in the rst file"); + EREG(fi_params,SAVE_RESTART_DATA,"save restart information"); + EREG(fi_params,NEWTRANS,"correct transmissibility calculation between cells"); + ereg (CHECKS_FOR_MULTI_CONN, "CHECK_FOR_MULTY_CONN", "check for multi connections in one cell"); + EREG(fi_params,USE_TIMESTEP_FILE,"save time steps into *tsl file"); + EREG(fi_params,SIMPLE_GET_CELL_SOLUTION,"enable simple solution restore algorithm"); + EREG(fi_params,USE_LOW_SKIN_TRANS_MULT,"if this item is set use calculation of trans mults for low skin"); + EREG(fi_params,SAVE_MESH_DATA,"save initial data in the rst file"); + EREG(fi_params,SAVE_CALC_DATA,"save solution vector at each large time step into .dmp file"); + EREG(fi_params,LOAD_CALC_DATA,"load initial guesses for Newton iterations from .dmp file"); + EREG(fi_params,SAVE_NORM_DATA,"save cells norms to .cel file"); + EREG(fi_params,DENS_JAC_SCALE,"enable densities based multiplier's for gas and oil equation's in Jacobian "); + EREG(fi_params,NEWTON_TUNING,"newton tuning"); + EREG(fi_params,SAVE_CROSSFLOW,"save crossflow"); + EREG(fi_params,G_FRACTURE,"g fracture"); + EREG(fi_params,CLAMP_PRESSURE,"clamp pressure values at each Newton iteration between possible min and max"); + EREG(fi_params,G_FRACTURE_FINAL,"g fracture final"); + EREG(fi_params,SAVE_CONN_DATA,"save connection rates to rst file"); + EREG(fi_params,DISABLE_FRACTURE_CHECK,"disable fracture check"); + EREG(fi_params,COMPRESS_IRR,"compress irregular matrix"); + EREG(fi_params,REMOVE_ISOLATED_REGIONS,"make isolated regions with out wells inactive"); + EREG(fi_params,SAVE_WRATES_TO_ASCII_FILE,"save well rates to ascii file"); + EREG(fi_params,CREATE_HDF5_FILE,"create hdf5 file"); + EREG(fi_params,WRITE_PRESSURE_TO_HDF5,"write pressure to hdf5"); + EREG(fi_params,WRITE_SATURATION_TO_HDF5,"write saturation to hdf5"); + EREG(fi_params,FIX_SOIL_BUG,"fix soil bug"); + EREG(fi_params,DISABLE_CROSSFLOW,"disable crossflow"); + EREG(fi_params, WRITE_PRESSURE_TO_HDF5,"write pressure values to hdf5 file"); + EREG(fi_params, WRITE_SATURATION_TO_HDF5,"write saturation values to hdf5 file"); + EREG(fi_params, WRITE_GAS_OIL_RATIO_TO_HDF5,"write gas-oil ratio values to hdf5 file"); + EREG(fi_params, WRITE_FIP_RESULTS_TO_HDF5,"write data by fip regions to hdf5 file"); + EREG(fi_params, WRITE_WELL_RESULTS_TO_HDF5,"write well data to hdf5 file"); + EREG(fi_params, WRITE_CONN_RESULTS_TO_HDF5,"write connection data to hdf5 file"); + EREG(fi_params, USE_CFL, "compute CFL in fi_operator and use csr_ilu_cfl_prec, used only if BS_BOS_CORE_USE_CSR_ILU_CFL_PREC defined"); + EREG(fi_params, WRITE_CFL_TO_HDF5, "write CFL vector to HDF5, used only if BS_BOS_CORE_USE_CSR_ILU_CFL_PREC defined and USE_CFL turned on"); + EREG(fi_params,B_TOTAL,"all parameters should be before this item"); + EREG(fi_params,fi_params::FI_PARAMS_TOTAL,"size of parameters array"); + + resize(fi_params::FI_PARAMS_TOTAL); // to resize names table and table of properties + + set_bool (PRINT_PVTO_TABLE, 1); // print PVTO table by default + set_bool (PRINT_PVTW_TABLE, 1); // print PVTW table by default + set_bool (PRINT_PVTG_TABLE, 1); // print PVTW table by default + set_bool (STORE_PANE_FLOW_RATES, 0); // do not store flow rates by default + set_bool (NEW_TS_SELECTION_ALGORITHM, 1); // use old algorithm + set_bool (SAVE_STEP_MAPS, 1); // save step maps on time step in the rst file + set_bool (SAVE_RESTART_DATA, 1); // save restart data + set_bool (SAVE_INITIAL_DATA, 1); // save initial data + set_bool (NEWTRANS, 1); // use NEWTRAN option + set_bool (CHECKS_FOR_MULTI_CONN, 1); // check for + set_bool (SIMPLE_GET_CELL_SOLUTION, 1); // read all time steps from *tsl file +#ifndef COMPOSITIONAL + set_bool (USE_TIMESTEP_FILE, 0); // read all time steps from *tsl file +#else + set_bool (USE_TIMESTEP_FILE, 0); // read all time steps from *tsl file +#endif + set_bool (USE_LOW_SKIN_TRANS_MULT, 1); // use calculation of multipliers for low skin-factor + set_bool (SAVE_MESH_DATA, 1); // save mesh data + set_bool (SAVE_CALC_DATA, 0); // save calc data + set_bool (LOAD_CALC_DATA, 0); // load calc data + set_bool (SAVE_NORM_DATA, 0); // save cells norms + set_bool (DENS_JAC_SCALE, 1); // scale Jacobian equations + set_bool (SAVE_CROSSFLOW, 0); + set_bool (NEWTON_TUNING, 0); + set_bool (G_FRACTURE, 0); + set_bool (CLAMP_PRESSURE, 0); + set_bool (G_FRACTURE_FINAL, 0); + set_bool (SAVE_CONN_DATA, 1); // save connection data + set_bool (DISABLE_FRACTURE_CHECK, 0); + set_bool (COMPRESS_IRR, 0); + set_bool (REMOVE_ISOLATED_REGIONS, 0); // remove regions by default + set_bool (SAVE_WRATES_TO_ASCII_FILE, 1); // save well rates to ascii file by default + set_bool (CREATE_HDF5_FILE, 1); // create hdf5 file + set_bool (WRITE_PRESSURE_TO_HDF5, 1); // write pressure to hdf5 + set_bool (WRITE_SATURATION_TO_HDF5, 0); // write saturation to hdf5 + set_bool (FIX_SOIL_BUG, 1);//0); + set_bool (DISABLE_CROSSFLOW, 0); + set_bool (WRITE_PRESSURE_TO_HDF5, 1); + set_bool (WRITE_SATURATION_TO_HDF5, 1); + set_bool (WRITE_GAS_OIL_RATIO_TO_HDF5, 1); + set_bool (WRITE_PLANE_FLOW_RATES_TO_HDF5, 0); + set_bool (WRITE_FIP_RESULTS_TO_HDF5, 1); + set_bool (WRITE_WELL_RESULTS_TO_HDF5, 1); + set_bool (WRITE_CONN_RESULTS_TO_HDF5, 0); + set_bool (USE_CFL, 0); + set_bool (WRITE_CFL_TO_HDF5, 0); + + // default value for integer params + set_int (PVT_INTERP_POINTS, 20); // number of interpolation points for PVT tables + set_int (LIN_ITERS_NUM, 30); // max number of linear iteration + set_int (NEWTON_ITERS_NUM, 12); // max number of newtonian iteration + set_int (NEWTON_ITERS_INC, 6); // if niters < maxniters - niters_inc increase ts + set_int (NEWTON_ITERS_AMG, 20); // if niters < niters_amg build full amg setup + set_int (APPROX_STEPS, 0); // number of approximation steps + set_int (SELECT_SOL_STEPS, 2); // number of steps produced to select force term in newton correction (0 -- no selection) + set_int (LIN_SOLVER_TYPE, FI_LIN_SOLVER_GMRES); // linear solver type + set_int (GMRES_ORTONORM_VLEN, 10); // number of ortonorm vectors in GMRES + set_int (AMG_LIN_ITERS_NUM, 10); // maximum number of AMG iterations + set_int (WELL_NEWTON_ITERS_NUM, 1/*20*/); // maximum number of well internal newton iterations + set_int (PREC_TYPE, FI_LIN_PREC_CPR); // preconditioner type for linear solver + set_int (PREC_TYPE_ONE_PHASE, FI_LIN_PREC_ILU); // preconditioner type for linear solver (1-phase problem) + set_int (MIN_CELLS_IN_REGION, 0); + set_int (SAVE_STEP_DATA_PERIOD, 1); // by default save step data at all steps + + // default value for floating points params + set_float (PVT_PRESSURE_RANGE_MAX, (ph_const.atmospheric_pressure * 1000)); // default max pressure in reservoir (atm.) + set_float (PVT_PRESSURE_RANGE_MIN, (ph_const.atmospheric_pressure * 1)); // default min pressure in reservoir (atm.) + set_float (PVTO_RS_RANGE_MIN, 1); // default min RS + set_float (PVTO_RS_RANGE_MAX, 400); // default max RS + set_float (NEWTON_RESIDUAL, (1.0e-2)); // residual value + set_float (LIN_SOLV_RESIDUAL, (1.0e-4)); // residual value + set_float (LIN_SOLV_MATBAL_RESIDUAL, (-1)); // matbal residual value + set_float (MAX_ALLOWED_LIN_SOLV_RESID, 0.05); // maximum allowed residual value + set_float (AMG_RESID, (1.0e-1)); // AMG preconditioner solver tolerance + set_float (MAX_TS, 100); // maximum allowed time step + set_float (MIN_TS, (5e-6)); // minimum allowed time step + set_float (FIRST_TS, 1); + set_float (TS_INC_MULT, 2); // increment multiplier + set_float (TS_DEC_MULT, 0.5); // decrement multiplier + set_float (OVERDRAFT, 1.4); // overdraft multiplier + set_float (MAX_P_CORRECTION, 300);//00); // pressure correction on newton iteration should be < + set_float (MAX_S_CORRECTION, 1); // saturation correction on newton iteration should be < + set_float (MAX_RS_CORRECTION, 1000); // Rs correction on newton iteration should be < + set_float (MAX_P_WELL_CORRECTION, 3000); // well pressure correction on newton iteration should be < + set_float (PRESSURE_COL_MULT, 1.0); // mult for pressue column in Jacobian + set_float (WAT_ROW_MULT, 1); // mult for water row in Jacobian (do not change) + set_float (GAS_ROW_MULT, 1); // mult for gas row in Jacobian + set_float (OIL_ROW_MULT, 1); // mult for oil row in Jacobian + set_float (TS_OMEGA, 0.5); // time step controling omega param + set_float (TS_DP, 60); // time step controling pressure change + set_float (TS_DS, 0.05); // time step controling saturation change + set_float (TS_DRS, 10); // time step controling Rs change + set_float (DP_MIN_CHOP, (1e-5)); // minimum chop in pressure change + set_float (DS_MIN_CHOP, (1e-7)); // minimum chop in saturation change + set_float (MAX_NORM_ON_TS, 10); + set_float (DRSDT, (-1)); // Maximum rate of increase of solution GOR + set_float (GAS_NORM_MULT, 1); // default gas norm multiplier + + // default parameters for compositional model + // newton converge parameters + //set_param(COMP_PARAMS_D_MASS_BALANCE, 0.1); // Scaled mass balance equation residuals. Equations are scaled by the accumulation terms (component mass dividing timestep size). + //set_param(COMP_PARAMS_D_PHASE_EQUIL, 0.02); // Scaled phase equilibrium relation residuals. These are scaled by the component fugacities in the gas phase + //set_param(COMP_PARAMS_D_WELL_RATE, 0.001); // Scaled well equation residuals, scaled by well input rate + //set_param(COMP_PARAMS_D_MAX_DP, 0.05); // The maximum scaled pressure change (absolute pressure change divided by the average reservoir pressure) + //set_param(COMP_PARAMS_D_MAX_DS, 0.005); // The maximum absolute saturation change + //set_param(COMP_PARAMS_D_MAX_DXCP, 0.001); // The maximum absolute component mole fraction change + //set_param(COMP_PARAMS_D_TS_DP, 20); // time step controling pressure change + //set_param(COMP_PARAMS_D_TS_DS, 0.2); // time step controling saturation change + //set_param(COMP_PARAMS_D_TS_DXCP, 0.02); // time step controling mole fraction change + //set_param(COMP_PARAMS_D_MAX_P_CORRECTION, 200); // pressure correction on newton iteration should be < + //set_param(COMP_PARAMS_D_MAX_S_CORRECTION, 0.5); // saturation correction on newton iteration should be < + //set_param(COMP_PARAMS_D_MAX_XCP_CORRECTION, 0.2); // mole fraction correction on newton iteration should be < + + set_float (MASS_BALANS_ERROR, (1.0e-5)); // maximum allowed mass balans error + set_float (MAX_NORM_ON_FIRST_N, 1); + set_float (P_DIMENSION_LESS_SCALE_FACTOR, 0.001); // scale factor for making pressure dimension less + } + + const std::string & fi_params::get_params_name (idx_type idx) + { + return params_names[idx].name; + } + + // And special blue-sky objbase class implementations + + fi_params::fi_params (bs_type_ctor_param /*param*/) + : bs_refcounter(), named_pbase() + { + set_default_values (); + } + + fi_params::fi_params (const fi_params& prop) + : bs_refcounter(prop), named_pbase(prop) + { + if (&prop != this) + *this = prop; + + set_default_values (); + } + + fi_params::~fi_params () + { + set_default_values (); + } + + const fi_params &fi_params::operator=(const fi_params &src) + { + if (&src == this) + return *this; + + named_pbase::operator=(src); + return *this; + } + + const fi_params &fi_params::operator+=(const fi_params &src) + { + if (&src == this) + return *this; + + named_pbase::operator+=(src); + return *this; + } + + /*! + * \brief read params from keyword file in format + * ------------------------------------------------------- + * D_PARAM_NAME D_VALUE + * ... + * I_PARAM_NAME I_VALUE + * ... + * B_PARAM_NAME B_VALUE + * ... + * / + * where D_PARAM_NAME specified in d_param_name_table, I_PARAM_NAME specified in i_param_name_table, + * B_PARAM_NAME specified in b_param_name_table, D_VALUE -- floating point value, + * I_VALUE -- integer value, B_VALUE -- should be word "ON" or word "OFF" + * list of params should be finished by "/" + * \param r -- pointer to file master class + */ + void fi_params::read_from_keyword_data_file (sp_reader_t r) + { + char key[CHAR_BUF_LEN]; + char key1[CHAR_BUF_LEN]; + char buf[CHAR_BUF_LEN]; + int len, i; + char *strt, *end_ptr; + double d_tmp; + int i_tmp; + int flag; + std::ostringstream out_s; + const sp_reader_t &lreader (r); + + + //BSOUT << priority (sn::read, lev::med) << "Process params:" << bs_end; + for (;;) + { + len = lreader->read_line (buf, CHAR_BUF_LEN); + if (len == YS_EOF) + return; + if (len < 0) // break if EOF + { + switch (len) + { + case YS_NOTHING_TO_READ: + break; + default: + return; + } + break; + } + /* End of list */ + if (buf[0] == '/') + break; + + // Read connection info + unwrap (buf, 2); + //if ((current_error_num = lreader->) != YS_SUCCESS) + // { + // out_s << "Error in " << lreader->get_prefix() << ": bad string " << buf; + // BS_ASSERT(false) (out_s.str()); + // throw bs_exception("fi_params class",out_s.str().c_str()); + // BOSERR (section::read_data, level::error) << out_s << bs_end; + // } + strt = buf; + scanf_s (strt, &end_ptr, key); + //if (lreader-> != YS_SUCCESS) + // { + // out_s << "Error in " << lreader->get_prefix() << ": can't read parameter name from " << strt; + // BS_ASSERT(false) (out_s.str()); + // throw bs_exception("fi_params class",out_s.str().c_str()); + // BOSERR (section::read_data, level::error) << out_s << bs_end; + // } + strt = end_ptr; + flag = 1; + + for (i = FI_PARAMS_START+1; i < D_TOTAL && flag; ++i) + { + if (!COMPARE_KEYWORD (key, this->get_name((named_pbase::idx_type)i).c_str())) + { + // read value + scanf_d (strt, &end_ptr, &d_tmp); + //if (lreader-> != YS_SUCCESS) + // { + // out_s << "Error in " <get_prefix() << ": can't read value for parameter " << key + // << " from " << strt; + // BS_ASSERT(false) (out_s.str()); + // throw bs_exception("fi_params class",out_s.str().c_str()); + // BOSERR (section::read_data, level::error) << out_s << bs_end; + // } + BOSOUT (section::read_data, level::medium) << key << " = " << d_tmp << bs_end; + + this->set_float ((idx_type)i, d_tmp); + flag = 0; + } + + } + // loop through integer params + for (i = D_TOTAL+1; i < I_TOTAL && flag; ++i) + { + if (!COMPARE_KEYWORD (key, this->get_name((named_pbase::idx_type)i).c_str())) + { + // read value + scanf_u (strt, &end_ptr, &i_tmp); + //if (lreader-> != YS_SUCCESS) + // { + // out_s << "Error in " <get_prefix() << ": can't read value for parameter " << key + // << " from " << strt; + // BS_ASSERT(false) (out_s.str()); + // throw bs_exception("fi_params class",out_s.str().c_str()); + // BOSERR (section::read_data, level::error) << out_s.str() << bs_end; + // } + BOSOUT (section::read_data, level::medium) << key << " = " << i_tmp << bs_end; + + this->set_int ((idx_type)i, i_tmp); + flag = 0; + } + } + // loop through boolian params + for (i = I_TOTAL; i < B_TOTAL && flag; ++i) + { + if (!COMPARE_KEYWORD (key, this->get_name((named_pbase::idx_type)i).c_str())) + { + // read value + scanf_s (strt, &end_ptr, key1); + //if (lreader-> != YS_SUCCESS) + // { + // out_s << "Error in " << lreader->get_prefix() << ": can't read value for parameter " << key + // << " from " << strt << " value should be \'ON\' or \'OFF\' or \'YES\' or \'NO\'"; + // BS_ASSERT(false) (out_s.str()); + // throw bs_exception("fi_params class",out_s.str().c_str()); + // BOSERR (section::read_data, level::error) << out_s.str() << bs_end; + // } + if (!strcmp (key1, "ON") || !strcmp (key1, "YES") || !strcmp (key1, "1")) + { + BOSOUT (section::read_data, level::medium) << key << " = " << key1 << bs_end; + this->set_param ((idx_type)i, 1); + } + else if (!strcmp (key1, "OFF") || !strcmp (key1, "NO") || !strcmp (key1, "0")) + { + BOSOUT (section::read_data, level::medium) << key << " = " << key1 << bs_end; + this->set_param ((idx_type)i, 0); + } + else + { + out_s << "Error in " << lreader->get_prefix() << ": can't read value for parameter " << key + << " from " << strt << " value should be \'ON\' or \'OFF\' or \'YES\' or \'NO\'"; + BS_ASSERT(false) (out_s.str()); + throw bs_exception("fi_params class",out_s.str().c_str()); + BOSERR (section::read_data, level::error) << out_s << bs_end; + } + flag = 0; + } + } + + } + } + + + BLUE_SKY_TYPE_STD_CREATE(fi_params) + BLUE_SKY_TYPE_STD_COPY(fi_params) + BLUE_SKY_TYPE_IMPL_SHORT(fi_params, objbase, "fi_params class") +} diff --git a/bs_bos_core/src/fip_results_storage.cpp b/bs_bos_core/src/fip_results_storage.cpp new file mode 100644 index 0000000..fdc8b7a --- /dev/null +++ b/bs_bos_core/src/fip_results_storage.cpp @@ -0,0 +1,52 @@ +/** + * @file fip_results_storage.cpp + * @brief fip results storage + * @author Sayfullin Ilshat + * @date 2009-02-05 + */ +#include "stdafx.h" +#include "fip_results_storage.h" + +// WTF?? +#include "well_results_storage.h" +namespace blue_sky + { + + + /** + * @brief constructor + */ + fip_results::fip_results () + { + d_params.resize (FIP_D_PARAM_COUNT); + } + + /** + * @brief destructor + */ + fip_results::~fip_results () + {} + + /** + * @brief constructor + */ + fip_results_storage::fip_results_storage (bs_type_ctor_param /* = NULL */) + {} + fip_results_storage::fip_results_storage (const fip_results_storage& src) + : bs_refcounter (src), objbase (src) + { + *this = src; + } + /** + * @brief destructor + */ + fip_results_storage::~fip_results_storage () + {} + + class fip_results; + + BLUE_SKY_TYPE_STD_CREATE (fip_results_storage) + BLUE_SKY_TYPE_STD_COPY (fip_results_storage) + BLUE_SKY_TYPE_IMPL_SHORT (fip_results_storage, objbase, "fip_results_storage") +} //blue_sky + diff --git a/bs_bos_core/src/fracture.cpp b/bs_bos_core/src/fracture.cpp new file mode 100644 index 0000000..46cedbe --- /dev/null +++ b/bs_bos_core/src/fracture.cpp @@ -0,0 +1,78 @@ +#include "stdafx.h" +#include "fracture.h" + +namespace blue_sky + { + fracture::fracture() + { + init(); + } + + fracture::fracture(const fracture &src) + { + *this = src; + } + + fracture::~fracture() + { + init(); + } + + fracture &fracture::operator=(const fracture &src) + { + name = src.name; + + dim[0] = src.dim[0]; + dim[1] = src.dim[0]; + dim[2] = src.dim[0]; + dim[3] = src.dim[0]; + frac_flag = src.frac_flag; + frac_len = src.frac_len; + frac_angle = src.frac_angle; + frac_skin = src.frac_skin; + frac_perm = src.frac_perm; + frac_width = src.frac_width; + + connection_type = src.connection_type; + start_time = src.start_time; + is_activated = src.is_activated; + ignore_fracture = src.ignore_fracture; + + return *this; + } + + void fracture::init() + { + name = ""; + + dim[0] = 0; + dim[1] = 0; + dim[2] = 0; + dim[3] = 0; + frac_flag = 0; + frac_len = 0.0; + frac_angle = 0.0; + frac_skin = 0.0; + frac_perm = 0.0; + frac_width = 0.0; + + connection_type = 0; + start_time = -1; + is_activated = 0; + ignore_fracture = 0; + } + + std::string &fracture::tname() + { + return name; + } + + int fracture::check_data() const + { + if (dim[0] < 0 || dim[1] < 0 || dim[2] < 0 || dim[3] < 0) + return -2; + if (frac_len < 0 || frac_perm < 0 || frac_width < 0) + return -3; + return 0; + } +} diff --git a/bs_bos_core/src/jacobian.cpp b/bs_bos_core/src/jacobian.cpp new file mode 100644 index 0000000..b06eedf --- /dev/null +++ b/bs_bos_core/src/jacobian.cpp @@ -0,0 +1,335 @@ +/*! \file jacobian.cpp + \brief jacobian class implementations + \author Nikonov Max +*/ +#include "stdafx.h" + +#include "jacobian.h" +#include BS_FORCE_PLUGIN_IMPORT () +#include "setup_preconditioner.h" +#include BS_STOP_PLUGIN_IMPORT () +#include "two_stage_preconditioner.h" + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +namespace blue_sky + { + + template + jacobian::jacobian (bs_type_ctor_param /*param*/) + : bs_node(bs_node::create_node(new jacob_traits)) + , jm (give_kernel::Instance().create_object(jacobian_matrix::bs_type())) + { + } + + template + jacobian::jacobian (const jacobian& src) + : bs_refcounter (src), bs_node(src) + , jm(src.jm) + { + *this = src; + } + + //template + //void + //jacobian ::create_solver (int n_phases, const sp_fi_params &ts_params) + //{ + // int p = ts_params->get_int (fi_params::LIN_SOLVER_TYPE); + + // if (n_phases > 1) + // { + // if (p == FI_LIN_SOLVER_BICGSTAB) + // { + // solver = BS_KERNEL.create_object (bicgstab_solver::bs_type()); + // solver_is_gmres_flag = 0; + // } + // else + // { + // #ifdef _MPI + // BS_ASSERT (false && "MPI: NOT IMPL YET"); + // //!solver = give_kernel::Instance().create_object(mpi_gmres_solver::bs_type()); + // #else //_MPI + // solver = BS_KERNEL.create_object (gmres_solver2::bs_type()); + // #endif //_MPI + // solver_is_gmres_flag = 1; + // } + // } + // else + // { + // solver = BS_KERNEL.create_object (amg_solver ::bs_type ()); + // smart_ptr > amg (solver, bs_static_cast ()); + // + // amg->amg_prop = BS_KERNEL.create_object (amg_properties::bs_type ()); + // amg->set_coarse(BS_KERNEL.create_object (coarse_pmis_2 ::bs_type ()),true); + // amg->set_interpolator(BS_KERNEL.create_object (interpolator_standart_2 ::bs_type ()),true); + + // BS_ASSERT (amg->amg_prop); + // amg->amg_prop->set_int (amg_properties::I_ADAPTIVE_TRESHOLD, 0); + // amg->amg_prop->set_int (amg_properties::I_UPDATE, 0); + // amg->amg_prop->set_float (amg_properties::FP_STRENGHT_THRESHOLD, 0.75); + // } + + // if (!solver) + // { + // bs_throw_exception ("Can't create solver"); + // } + //} + +// template +// void +// jacobian ::create_preconditioner (well_model_type model_type, int n_phases, const sp_fi_params &ts_params) +// { +// if (n_phases > 1) +// { +// int p = ts_params->get_int (fi_params::PREC_TYPE); +// if (p == FI_LIN_PREC_ILU) +// { +//#ifdef _MPI +// BS_ASSERT (false && "MPI: NOT IMPL YET"); +// //!preconditioner = give_kernel::Instance().create_object(mpi_csr_ilu_prec::bs_type()); +//#else //_MPI +//#ifdef ILU_PREC_PARALLEL +// preconditioner = give_kernel::Instance().create_object(csr_pilu_prec::bs_type()); +//#else //ILU_PREC_PARALLEL +// preconditioner = give_kernel::Instance().create_object(csr_ilu_prec::bs_type()); +// //preconditioner = give_kernel::Instance().create_object(csr_ilu_cfl_prec::bs_type()); +//#endif //ILU_PREC_PARALLEL +//#endif //_MPI +// prec_is_cpr_flag = 0; +// } // if (p == FI_LIN_PREC_ILU) +// else if (p == FI_LIN_PREC_CPR_SOR) +// { +// preconditioner = give_kernel::Instance().create_object(two_stage_preconditioner::bs_type()); +// if (!preconditioner) +// { +// bs_throw_exception ("Can't create preconditioner"); +// } +// +// prec_is_cpr_flag = 1; +//#ifdef _MPI +// BS_ASSERT (false && "MPI: NOT IMPL YET"); +// if (model_type == BLACK_OIL) +// { +// //!static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner)-> +// //!set_prec_1 (give_kernel::Instance().create_object(mpi_cpr_preconditioner::bs_type())); +// } +// else +// { +// throw bs_exception ("jacobian::create_preconditioner", "model type not supported"); +// } +// //!static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner)-> +// //!set_prec_2 (give_kernel::Instance().create_object(mpi_csr_ilu_prec::bs_type())); +//#else // _MPI +// if ((model_type == BLACK_OIL) || (model_type == COMPOSIT)) +// { +// sp_obj cpr_prec_raw (give_kernel::Instance().create_object(cpr_preconditioner::bs_type())); +// smart_ptr > cpr_prec (cpr_prec_raw, bs_dynamic_cast ()); +// smart_ptr > prec (preconditioner, bs_dynamic_cast ()); +// prec->set_prec_1 (cpr_prec.get ()); +// } +// else +// { +// bs_throw_exception ("Model type not supported"); +// } +// //////////!!!!!!!!!!!!!!!!!!!!!! sor_prec need for mpi_vector +// //static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner)-> +// //set_prec_2 (give_kernel::Instance().create_object(sor_prec::bs_type())); +//#endif // _MPI +// } // if (p == FI_LIN_PREC_CPR_SOR) +// else +// { +// BOSOUT (section::solvers, level::debug) << "create preconditioner" << bs_end; +// preconditioner = give_kernel::Instance().create_object(two_stage_preconditioner::bs_type()); +// if (!preconditioner) +// { +// bs_throw_exception ("Can't create preconditioner"); +// } +// +// prec_is_cpr_flag = 1; +// smart_ptr > prec (preconditioner, bs_dynamic_cast ()); +// +//#ifdef _MPI +// BS_ASSERT (false && "MPI: NOT IMPL YET"); +// if (model_type == BLACK_OIL) +// { +// //!static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner)-> +// //!set_prec_1 (give_kernel::Instance().create_object(mpi_cpr_preconditioner::bs_type())); +// } +// else +// { +// throw bs_exception ("jacobian::create_preconditioner", "model type not supported"); +// } +// //!static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner)-> +// //!set_prec_2 (give_kernel::Instance().create_object(mpi_csr_ilu_prec::bs_type())); +//#else // _MPI +// sp_obj cpr_prec_raw (give_kernel::Instance().create_object(cpr_preconditioner::bs_type())); +// smart_ptr > cpr_prec (cpr_prec_raw, bs_static_cast ()); +// BS_ASSERT (cpr_prec_raw); +// BS_ASSERT (cpr_prec); +// +// prec->set_prec_1 (cpr_prec.get ()); +//#ifdef ILU_PREC_PARALLEL +// static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner)-> +// set_prec_2 (give_kernel::Instance().create_object(csr_pilu_prec::bs_type())); +//#else // ILU_PREC_PARALLEL +//#ifdef BS_BOS_CORE_USE_CSR_ILU_CFL_PREC +// sp_obj csr_prec_raw (give_kernel::Instance().create_object(csr_ilu_cfl_prec::bs_type())); +// smart_ptr > csr_prec (csr_prec_raw, bs_static_cast ()); +//#else +// sp_obj csr_prec_raw (BS_KERNEL.create_object (csr_ilu_prec ::bs_type ())); +// smart_ptr > csr_prec (csr_prec_raw, bs_static_cast ()); +//#endif +// BS_ASSERT (csr_prec_raw); +// BS_ASSERT (csr_prec); +// +// prec->set_prec_2 (csr_prec.get ()); +//#endif // ILU_PREC_PARALLEL +//#endif // _MPI +// } +// } +// else // if (n_phases > 1) - pressure system +// { +// int p = ts_params->get_int(fi_params::PREC_TYPE_ONE_PHASE); +// if (p == FI_LIN_PREC_ILU) +// { +//#ifdef _MPI +// BS_ASSERT (false && "MPI: NOT IMPL YET"); +// //!preconditioner = give_kernel::Instance().create_object(mpi_csr_ilu_prec::bs_type()); +//#else // _MPI +//#ifdef ILU_PREC_PARALLEL +// preconditioner = give_kernel::Instance().create_object(csr_pilu_prec::bs_type()); +//#else // ILU_PREC_PARALLEL +// preconditioner = give_kernel::Instance().create_object(csr_ilu_prec::bs_type()); +//#endif // ILU_PREC_PARALLEL +//#endif // _MPI +// prec_is_cpr_flag = 0; +// } +// else if (p == FI_LIN_PREC_AMG) +// { +//#ifdef _MPI +// BS_ASSERT (false && "MPI: NOT IMPL YET"); +// //!preconditioner = give_kernel::Instance().create_object(mpi_amg_solver::bs_type()); +//#else // _MPI +// preconditioner = give_kernel::Instance().create_object(amg_solver::bs_type()); +// +//#endif // _MPI +// } +// else +// { +// throw bs_exception ("jacobian::create_preconditioner", "this preconditioner not supported for 1 phase model"); +// } +// } +// } + + template + void + jacobian ::setup_solver (const sp_fi_params &ts_params) + { + solver->get_prop()->set_max_iters(ts_params->get_int(fi_params::LIN_ITERS_NUM)); + solver->get_prop()->set_tolerance(ts_params->get_float(fi_params::LIN_SOLV_RESIDUAL)); + //solver->get_prop()->set_matbal_tolerance(ts_params->get_float(fi_params::LIN_SOLV_MATBAL_RESIDUAL)); + } + + template + void + jacobian ::setup_preconditioner (const sp_fi_params &ts_params) + { +// //set up preconditioner +// if (prec_is_cpr_flag) +// { +//#ifdef _MPI +// BS_ASSERT (false && "MPI: NOT IMPL YET"); +// smart_ptr< /*!mpi_*/cpr_preconditioner > cpr = ((static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner))->get_prec_1()); +//#else // _MPI +// smart_ptr< cpr_preconditioner > cpr = ((static_cast< smart_ptr< two_stage_preconditioner > >(preconditioner))->get_prec_1()); +//#endif // _MPI +// +// BS_ASSERT (cpr); +// BS_ASSERT (cpr->get_prop ()); +// +// cpr->get_prop()->set_max_iters(ts_params->get_int(fi_params::AMG_LIN_ITERS_NUM)); +// cpr->get_prop()->set_matbal_tolerance(ts_params->get_float(fi_params::AMG_RESID)); +// } + } + + template + int jacobian::setup_solver_params (well_model_type model_type, int n_phases, const sp_fi_params &ts_params) + { + + if (!ts_params) + { + throw bs_exception("Jacobian::setup_solver_params", "ts_params is not inited!"); + } + + //if (ts_params->check_value (fi_params::LIN_SOLVER_TYPE) && !solver) + // { + // create_solver (n_phases, ts_params); + // } + + //if (ts_params->check_value (fi_params::PREC_TYPE) && !preconditioner) + // { + // create_preconditioner (model_type, n_phases, ts_params); + // } + + if (!solver) + { + bs_throw_exception ("Solver is null"); + } + if (!preconditioner) + { + bs_throw_exception ("Preconditioner is null"); + } + + if (solver_is_gmres_flag) + { + static_cast< smart_ptr< gmres_solver2 > >(solver)->m + = ts_params->get_int(fi_params::GMRES_ORTONORM_VLEN); + } + + setup_solver (ts_params); + setup_preconditioner (ts_params); + + solver->set_prec(preconditioner); + return 0; + } + + template + const typename jacobian ::sp_lsolver & + jacobian ::get_solver () const + { + return solver; + } + template + const typename jacobian ::sp_lsolver & + jacobian ::get_prec () const + { + return preconditioner; + } + + //DEPRICATED + template + void + jacobian::begin () + { + //this->get_jmatrix()->regular_matrix + BS_ASSERT (false && "NOT IMPL YET"); + } + //DEPRICATED + template + void + jacobian::end () + { + BS_ASSERT (false && "NOT IMPL YET"); + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF(jacobian, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(jacobian, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (jacobian) , 1, (objbase), "jacobian_fi", "Jacobian-float-int", "Jacobian with float items and integer indexes", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (jacobian) , 1, (objbase), "jacobian_di", "Jacobian-double-int", "Jacobian with double items and integer indexes", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (jacobian) , 1, (objbase), "jacobian_mixi", "Jacobian-mixi", "Jacobian mixi", false); + +}; + diff --git a/bs_bos_core/src/keyword_manager.cpp b/bs_bos_core/src/keyword_manager.cpp new file mode 100644 index 0000000..f9c2550 --- /dev/null +++ b/bs_bos_core/src/keyword_manager.cpp @@ -0,0 +1,150 @@ +/** +* @file keywords.h +* @brief keyword handler methods +* @author Morozov Andrey +* @date 2008-07-02 +*/ +#include "stdafx.h" + +#include "keyword_manager.h" + +namespace blue_sky + { + //constructors + template + keyword_manager::keyword_manager(bs_type_ctor_param /*param*/) + { + } + + template + keyword_manager::keyword_manager(const keyword_manager & src) + : bs_refcounter (src) + { + //*this = src; + } + + template + bool + keyword_manager ::is_keyword_supported (const std::string &keyword, keyword_params_t ¶ms) const + { + sp_reader_t reader (params.reader, bs_dynamic_cast ()); + + typename supported_keywords_t::const_iterator sup_it = supported_keywords.find (keyword); + if (sup_it == supported_keywords.end ()) + { + BOSWARN (section::keywords, level::warning) << (boost::format ("Keyword %s wasn't registered (%s)") % keyword % reader->get_prefix ()) << bs_end; + return false; + } + else + { + std::list::const_iterator i; + BOSWARN (section::keywords, level::warning) << (boost::format ("Keyword %s is supported, but inactive now (%s). This keyword is supported by:") % keyword % reader->get_prefix ()) << bs_end; + for (i = sup_it->second.begin(); i != sup_it->second.end(); ++i) + BOSWARN (section::keywords, level::warning) << *i << bs_end; + + return true; + } + } + + template + bool + keyword_manager ::is_keyword_activated (const std::string &keyword, keyword_params_t ¶ms) const + { + return handlers.find(keyword) != handlers.end (); + } + + template + void keyword_manager::handle_keyword (const std::string &keyword, keyword_params_t ¶ms) + { + typename handlers_t::iterator it = handlers.find(keyword); + sp_reader_t reader (params.reader, bs_dynamic_cast ()); + if (it == handlers.end ()) + { + is_keyword_supported (keyword, params); + } + else + { + keyword_handler &handler = it->second; + if (handler.handle_function) + { + (*(handler.handle_function)) (keyword, params); + } + else if (handler.handle_object) + { + handler.handle_object->handler (keyword, params); + } + } + } + + template + void keyword_manager::register_keyword(const std::string &keyword, keyword_handler handler) + { + typename handlers_t::iterator it = handlers.find(keyword); + if (it != handlers.end()) + { + bs_throw_exception(boost::format ("Keyword [%s] registration failed, keyword is already registered") % keyword); + } + switch (handler.index_in_pool) + { + case (-1) : handler.handle_function = &this_t::int_array_handler; break; + case (-2) : handler.handle_function = &this_t::float_array_handler; break; + default : break; + } + + handlers.insert (std::make_pair (keyword, handler)); + BOSOUT (section::keywords, level::low) << boost::format ("Keyword [%s] registered") % keyword << bs_end; + } + + template + void + keyword_manager ::register_keyword (const std::string &keyword, const shared_handler_t &handler) + { + typename handlers_t::iterator it = handlers.find (keyword); + if (it != handlers.end ()) + { + bs_throw_exception(boost::format ("Keyword [%s] registration failed, keyword is already registered") % keyword); + } + + handlers.insert (std::make_pair (keyword, keyword_handler (handler))); + BOSOUT (section::keywords, level::low) << boost::format ("Keyword [%s] registered") % keyword << bs_end; + } + + template + void keyword_manager::register_supported_keyword(const std::string &keyword, const std::string &provider) + { + supported_keywords.insert (std::make_pair (keyword, std::list ())).first->second.push_back(provider); + BOSOUT (section::keywords, level::low) << boost::format ("Keyword [%s] supported") % keyword << bs_end; + } + + /*template + const typename keyword_manager::sp_event_manager_t & keyword_manager::get_event_manager() + { + return top->em; + }*/ + + //bs stuff + BLUE_SKY_TYPE_STD_CREATE_T_DEF(keyword_manager, (class)) + //BLUE_SKY_TYPE_STD_COPY_T_DEF(keyword_manager, (class)) + + template + blue_sky::objbase* + keyword_manager ::bs_create_copy (bs_type_cpy_ctor_param src) + { + const keyword_manager *src_ptr = dynamic_cast *> (src.get ()); + if (!src_ptr) + bs_throw_exception ("Can't cast to keyword_manager"); + + return new keyword_manager (src_ptr); + } + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (keyword_manager ) , 1, (objbase), "keyword_manager_fi", "BOS_Core keyword_manager class", "BOS_Core keyword_manager class", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (keyword_manager ) , 1, (objbase), "keyword_manager_di", "BOS_Core keyword_manager class", "BOS_Core keyword_manager class", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (keyword_manager ) , 1, (objbase), "keyword_manager_mixi", "BOS_Core keyword_manager class", "BOS_Core keyword_manager class", false); + + + //!TODO: kill next string after debug + //template class keyword_manager ; + //template class keyword_manager ; + + +}//ns_bs diff --git a/bs_bos_core/src/keywords_handlers.cpp b/bs_bos_core/src/keywords_handlers.cpp new file mode 100644 index 0000000..8ee9e8f --- /dev/null +++ b/bs_bos_core/src/keywords_handlers.cpp @@ -0,0 +1,1610 @@ +/** +* @file keywords.h +* @brief functions - keyword handlers +* @author Morozov Andrey +* @date 2008-07-02 +*/ +#include "stdafx.h" + +#include "event_base.h" +#include "event_manager.h" +#include "fi_params.h" +#include "keyword_manager.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "scal_3p.h" +#include "scale_array_holder.h" +#include "scal_region_info.h" +#include "scal_region.h" +#include "scal_2p_data_holder.h" +#include "data_class.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + //BS_TYPE_IMPL_T_MEM(bos_array, amap_strategy_fi::item_array_t) + //BS_TYPE_IMPL_T_MEM(bos_array, amap_strategy_ii::item_array_t) + +//! macro for defining of common variables +#define KH_READER_DEF \ + sp_reader_t reader (params.reader, bs_dynamic_cast ()); \ + size_t len; \ + len = 0; + + template + keyword_manager::~keyword_manager () + { + + } + + template + void keyword_manager::int_array_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_this_t km (params.km, bs_dynamic_cast ()); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + index_t* dimens, def_value; + //!TODO: check sp! + array_uint8_t this_arr; + int arr_index = km->handlers[keyword].index_in_pool; + + if (arr_index >= 0) + { + dimens = &i_pool_sizes[ARRAY_POOL_TOTAL*arr_index]; + def_value = i_pool_default_values[arr_index]; + if (!idata->i_map->contain(arr_index)) + { + idata->i_map->create_item (arr_index, dimens, def_value); + } + } + else + { + if (arr_index != -1) + { + bs_throw_exception (boost::format ("Wrong handler (%d) invoked for pool keyword %s") + % arr_index % keyword); + } + arr_index = ARR_TOTAL_INT; + while (idata->i_map->contain(arr_index)) + { + arr_index++; + } + def_value = km->handlers[keyword].int_def_value; + dimens = km->handlers[keyword].dimens; + idata->i_map->create_item (arr_index, dimens, def_value); + idata->ahelper.add_correspondence_i (keyword, arr_index); + } + + + this_arr = tools::get_non_empty ((*idata->i_map)[arr_index].array); + + index_t nx = 0, ny = 0, nz = 0, ndim = 0; + idata->i_map->get_dimens (arr_index, nx, ny, nz, ndim); + if ((len = reader->read_array (keyword, this_arr)) != (size_t)ndim) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") % reader->get_prefix () % keyword); + } + + // Check array validity: all elements should be in 1...eql_region + if (!COMPARE_KEYWORD (keyword.c_str(), "ROCKNUM")) + for (index_t i = 0; i < ndim; i++) + { + if (this_arr[i] < 1 || this_arr[i] > idata->rock_region) + { + bs_throw_exception (boost::format ("Error in %s: value %f of element %d of array %s is out of range") + % reader->get_prefix () % this_arr[i] % i % keyword); + } + } + // Check array validity: all elements should be in 1...eql_region + if (!COMPARE_KEYWORD (keyword.c_str(), "EQLNUM")) + for (index_t i = 0; i < ndim; i++) + { + if (this_arr[i] < 1 || this_arr[i] > idata->eql_region) + { + bs_throw_exception (boost::format ("Error in %s: value %f of element %d of array %s is out of range") + % reader->get_prefix () % this_arr[i] % i % keyword); + } + } + // Check array validity: all elements should be in 1...sat_region + if (!COMPARE_KEYWORD (keyword.c_str(), "SATNUM")) + for (index_t i = 0; i < ndim; i++) + { + if (this_arr[i] < 1 || this_arr[i] > idata->sat_region) + { + bs_throw_exception (boost::format ("Error in %s: value %f of element %d of array %s is out of range") + % reader->get_prefix () % this_arr[i] % i % keyword); + } + } + // Check array validity: all elements should be in 1...pvt_region + if (!COMPARE_KEYWORD (keyword.c_str(),"PVTNUM")) + for (index_t i = 0; i < ndim; i++) + { + if (this_arr[i] < 1 || this_arr[i] > idata->pvt_region) + { + bs_throw_exception (boost::format ("Error in %s: value %f of element %d of array %s is out of range") + % reader->get_prefix () % this_arr[i] % i % keyword); + } + } + // Check array validity: all elements should be 0 or 1 + if (!COMPARE_KEYWORD (keyword.c_str(), "ACTNUM")) + for (index_t i = 0; i < ndim; i++) + { + if (this_arr[i] != 0) + this_arr[i] = 1; + } + // Check array validity: all elements should be in 1...fip_region + if (!COMPARE_KEYWORD (keyword.c_str(), "FIPNUM")) + for (index_t i = 0; i < ndim; i++) + { + if (this_arr[i] < 1 || this_arr[i] > idata->fip_region) + { + bs_throw_exception (boost::format ("Error in %s: value %f of element %d of array %s is out of range") + % reader->get_prefix () % this_arr[i] % i % keyword); + } + } + // Check array validity: all elements should be 1 first type, 2 second type or 3 read from file + if (!COMPARE_KEYWORD (keyword.c_str(), "BNDNUM")) + for (index_t i = 0; i < ndim; i++) + { + if (this_arr[i] < 1 && this_arr[i] > 3) + { + index_t i_c, j_c, k_c; + index_t c_n = i; + k_c = c_n / (idata->nx * idata->ny); + c_n -= k_c * (idata->nx * idata->ny); + j_c = c_n / idata->nx; + i_c = c_n - j_c * idata->nx; + + BOSWARN (section::read_data, level::warning) << "Warning: unknown boundary condition in cell [" + << i_c << " , " << j_c << " , " << k_c << "]" << bs_end; + this_arr[i] = 2; + } + } + BOSOUT (section::read_data, level::medium) + << "Keyword: " << keyword << "\n" + << "ndim = " << ndim << bs_end; + // launch second handler if any + if (km->handlers[keyword].second_handle_function) + km->handlers[keyword].second_handle_function (keyword, params); + } + + template + void keyword_manager::float_array_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_this_t km (params.km, bs_dynamic_cast ()); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + //!TODO: check sp! + array_float16_t this_arr; + int arr_index = km->handlers[keyword].index_in_pool; + index_t* dimens; + item_t def_value; + + if (arr_index >= 0) + { + dimens = &d_pool_sizes[ARRAY_POOL_TOTAL*arr_index]; + def_value = d_pool_default_values[arr_index]; + BOSOUT (section::read_data, level::debug) << + boost::format ("[%s] default values: %f\n\tdimens: [%d, %d, %d, %d, %d, %d]") + % keyword % def_value + % dimens[0] % dimens[1] %dimens[2] + % dimens[3] % dimens[4] %dimens[5] + << bs_end; + + if (!dimens) + { + BOSOUT (section::read_data, level::debug) << + "dimens is null" << bs_end; + } + + if (!idata->d_map->contain(arr_index)) + { + idata->d_map->create_item (arr_index, dimens, def_value); + } + else + { + BOSOUT (section::read_data, level::debug) << + boost::format ("Keyword %s alread in pool") % keyword << bs_end; + } + } + else + { + if (arr_index != -2) + { + bs_throw_exception (boost::format ("Wrong handler (%d) invoked for pool keyword %s") + % arr_index % keyword); + } + arr_index = ARR_TOTAL_DOUBLE; + while (idata->d_map->contain(arr_index)) + { + arr_index++; + } + def_value = km->handlers[keyword].float_def_value; + dimens = km->handlers[keyword].dimens; + idata->d_map->create_item (arr_index, dimens, def_value); + idata->ahelper.add_correspondence_d (keyword, arr_index); + } + + this_arr = tools::get_non_empty ((*idata->d_map)[arr_index].array); + + index_t nx = 0, ny = 0, nz = 0, ndim = 0; + idata->d_map->get_dimens (arr_index, nx, ny, nz, ndim); + + if ((len = reader->read_array (keyword.c_str(), this_arr)) != (size_t)ndim) + { + bs_throw_exception ((boost::format ("Error in %s: not enough valid arguments for keyword %s") % reader->get_prefix() % keyword).str ()); + } + BOSOUT (section::read_data, level::medium) << "Keyword: " << keyword << bs_end; + BOSOUT (section::read_data, level::medium) << "ndim = " << ndim << bs_end; + + // launch second handler if any + if (km->handlers[keyword].second_handle_function) + km->handlers[keyword].second_handle_function (keyword, params); + } + + template + void keyword_manager::event_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + char key1[CHAR_BUF_LEN] = {0}; + typedef smart_ptr , true> sp_event_manager_t; + sp_event_manager_t em (params.em, bs_dynamic_cast ()); + sp_this_t km (params.km, bs_dynamic_cast ()); + + + for (;;) + { + reader->read_line (buf, CHAR_BUF_LEN); + if (sscanf (buf, "%s", key1) != 1) + { + bs_throw_exception (boost::format ("Error in %s: bad string (%s)") + % reader->get_prefix() % buf); + } + if (key1[0] == '/') + { + em->end_event (); + break; + } + + em->process_event (km->current_date, keyword, std::string (buf)); + } + } + + template + void keyword_manager::TITLE_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + reader->read_line (buf, CHAR_BUF_LEN); + idata->title = std::string(buf); // TODO: , len) + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::OIL_handler(const std::string &keyword, keyword_params_t ¶ms) + { + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (!(idata->fi_phases & (1 << FI_PHASE_OIL))) + ++idata->fi_n_phase; + idata->fi_phases |= 1 << FI_PHASE_OIL; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::WATER_handler(const std::string &keyword, keyword_params_t ¶ms) + { + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (!(idata->fi_phases & (1 << FI_PHASE_WATER))) + ++idata->fi_n_phase; + idata->fi_phases |= 1 << FI_PHASE_WATER; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::GAS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (!(idata->fi_phases & (1 << FI_PHASE_GAS))) + ++idata->fi_n_phase; + idata->fi_phases |= 1 << FI_PHASE_GAS; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::PROCESS_PARAMS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + + try + { + smart_ptr fi_params (params.fi_params, bs_dynamic_cast ()); + fi_params->read_from_keyword_data_file (reader); + } + catch (const bs_exception&) + { + throw; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::REPORTS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + char key1[CHAR_BUF_LEN] = {0}; + char *strt = 0, *end_ptr = 0; + + + for (;;) + { + reader->read_line (buf, CHAR_BUF_LEN); + if (sscanf (buf, "%s", key1) != 1) + { + bs_throw_exception (boost::format ("Error in %s: bad string (%s)") + % reader->get_prefix() % buf); + } + if (key1[0] == '/') + break; + + strt = buf; + scanf_s (strt, &end_ptr, key1); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << ": can't read report type for keyword " << keyword << " from " << strt; + // //BOSERR (section::read_data, level::error) << out_s << bs_end; + // KH_ASSERT_EXCEPTION + // } + strt = end_ptr; + int section_level = level::warning; + if (COMPARE_KEYWORD (key1, "ALL") && COMPARE_KEYWORD (key1, "NO")) + { + scanf_u (strt, &end_ptr, §ion_level); + } + //if (COMPARE_KEYWORD (key1, "ALL") + // && COMPARE_KEYWORD (key1, "NO") + // && scanf_u (strt, &end_ptr, itmp)) + // { + // out_s << "Error in " << reader->get_prefix() << ": can't read report level for type " << key1 << " for keyword " << keyword << " from " << strt; + // //BOSERR (section::read_data, level::error) << out_s << bs_end; + // KH_ASSERT_EXCEPTION + // } + + // TODO: check section_level value + if (log::detail::set_section_level_by_name (key1, section_level + level::warning)) + { + if (std::string (key1) == "ITERS") + { + BOSOUT.set_priority (section::solvers, section_level + level::warning); + } + } + else if (!COMPARE_KEYWORD (key1, "ALL")) + { + for (int i = section::section_begin; i < section::section_end; ++i) + { + BOSOUT.set_priority (i, level::low); + } + } + else if (!COMPARE_KEYWORD (key1, "NO")) + { + for (int i = section::section_begin; i < section::section_end; ++i) + { + BOSOUT.set_priority (i, level::warning); + } + } + else + { + bs_throw_exception (boost::format ("Error in %s: unknown section name %s for keyword %s") + % reader->get_prefix () % key1 % keyword); + } + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::REPORTFILE_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + char key1[CHAR_BUF_LEN] = {0}; + char key2[CHAR_BUF_LEN] = {0}; + + + for (;;) + { + reader->read_line (buf, CHAR_BUF_LEN); + if (buf[0] == '/') + { + BOSOUT (section::read_data, level::debug) << "End of REPORT_FILE section" << bs_end; + break; + } + if (sscanf (buf, "%s %s", key1, key2) != 2) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + + int priority = log::detail::get_log_level_by_name (key2); + if (priority == -1) + { + bs_throw_exception (boost::format ("Error in %s: unknown ('%s') log level (priority) specified for keyword %s") + % reader->get_prefix () % key2 % keyword); + } + + if (!log::detail::set_section_level_by_name (key1, priority, BOSOUT.get_channel ()->get_stream ("FILE"))) + { + bs_throw_exception (boost::format ("Error in %s: unknown ('%s') section name specified for keyword %s") + %reader->get_prefix () % key1 % keyword); + } + } + } + + template + void keyword_manager::REPORTSCREEN_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + char key1[CHAR_BUF_LEN] = {0}; + char key2[CHAR_BUF_LEN] = {0}; + + + for (;;) + { + reader->read_line (buf, CHAR_BUF_LEN); + if (buf[0] == '/') + { + BOSOUT (section::read_data, level::debug) << "End of REPORT_SCREEN section" << bs_end; + break; + } + if (sscanf (buf, "%s %s", key1, key2) != 2) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + + int priority = log::detail::get_log_level_by_name (key2); + if (priority == -1) + { + bs_throw_exception (boost::format ("Error in %s: unknown ('%s') log level (priority) specified for keyword %s") + % reader->get_prefix () % key2 % keyword); + } + + if (!log::detail::set_section_level_by_name (key1, priority, BOSOUT.get_channel ()->get_stream ("COUT"))) + { + bs_throw_exception (boost::format ("Error in %s: unknown ('%s') section name specified for keyword %s") + %reader->get_prefix () % key1 % keyword); + } + } + } + + template + void keyword_manager::STONE1_handler(const std::string &keyword, keyword_params_t ¶ms) + { + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + idata->rpo_model = STONE1_MODEL; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::STONE2_handler(const std::string &keyword, keyword_params_t ¶ms) + { + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + idata->rpo_model = STONE2_MODEL; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::RELATIVE_PERM_DEFAULT_handler(const std::string &keyword, keyword_params_t ¶ms) + { + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + idata->rpo_model = RPO_DEFAULT_MODEL; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::UNITS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + char key1[CHAR_BUF_LEN] = {0}; + char key2[CHAR_BUF_LEN] = {0}; + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + reader->read_line (buf, CHAR_BUF_LEN); + // Read and convert UNITS to data + if (sscanf (buf, "%s", key1) != 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + + int units_in = UNITS_INPUT_DEFAULT; + if (!COMPARE_KEYWORD (key1, "SI")) + units_in = UNITS_SI; + else if (!COMPARE_KEYWORD (key1, "METRIC")) + units_in = UNITS_METRIC; + else if (!COMPARE_KEYWORD (key1, "FIELD")) + units_in = UNITS_FIELD; + else if (!COMPARE_KEYWORD (key1, "LAB")) + units_in = UNITS_LAB; + else + { + bs_throw_exception (boost::format ("Error in %s: unknown argument %s for keyword %s") + % reader->get_prefix () % key1 % keyword); + } + // Make output units being equal to input by default + int units_out = units_in; + if (sscanf (buf, "%s%s", key1, key2) == 2) + { + // two units specified + if (!COMPARE_KEYWORD (key2, "SI")) + units_out = UNITS_SI; + else if (!COMPARE_KEYWORD (key2, "METRIC")) + units_out = UNITS_METRIC; + else if (!COMPARE_KEYWORD (key2, "FIELD")) + units_out = UNITS_FIELD; + else if (!COMPARE_KEYWORD (key2, "LAB")) + units_out = UNITS_LAB; + else + { + BOSOUT (section::read_data, level::warning) << "Warning in " << reader->get_prefix() + << ": trailing garbage " << key2 + << " is ignored for keyword " << keyword << bs_end; + } + } + + idata->input_units_converter.set_input_units (units_in); + idata->input_units_converter.set_output_units (UNITS_INTERNAL_DEFAULT); + idata->output_units_converter.set_input_units (UNITS_INTERNAL_DEFAULT); + idata->output_units_converter.set_output_units (units_out); + + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::ROCKCOMP_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + char key1[CHAR_BUF_LEN] = {0}; + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + reader->read_line (buf, CHAR_BUF_LEN); + // Read and convert UNITS to data + if (sscanf (buf, "%s %d", key1, &idata->rock_region.data ()) != 2) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + // check read data + if (idata->rock_region < 1) + { + bs_throw_exception (boost::format ("Error in %s: number of rock regions should be greater than 0 for keyword %s") + % reader->get_prefix () % keyword); + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::REGNUM_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + seq_vector itmp; + itmp.resize(4); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if ((len = reader->read_array (keyword, itmp)) != 4) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + + idata->set_region(itmp[0],itmp[1],itmp[2],itmp[3]); + + BOSOUT (section::read_data, level::medium) << + "Keyword " << keyword << ":(" << + idata->pvt_region << ", " << idata->sat_region << ", " << + idata->eql_region << ", " << idata->fip_region << ")" << bs_end; + + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::REGDIMS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + seq_vector itmp; + itmp.resize(4); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + + if ((len = reader->read_array (keyword, itmp)) != 4) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + + idata->set_region(itmp[3],itmp[1],itmp[2],itmp[0]); + + BOSOUT (section::read_data, level::medium) << + "Keyword " << reader->get_prefix() << ": reading of (" << + idata->pvt_region << ", " << idata->sat_region << ", " << + idata->eql_region << ", " << idata->fip_region << ") is successfully" << bs_end; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::EQLDIMS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + seq_vector itmp; + itmp.resize(1); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + + if ((len = reader->read_array (keyword, itmp)) != 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + idata->eql_region=itmp[0]; + if (idata->eql_region <= 0) + { + bs_throw_exception (boost::format ("Error in %s: number of equilibrium regions in %s must be positive") + % reader->get_prefix () % keyword); + } + + idata->equil.resize(EQUIL_TOTAL * idata->eql_region); //!TODO:EQUIL_TOTAL instead of 3 + + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::TABDIMS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + char *strt = 0, *end_ptr = 0; + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + reader->read_line (buf, CHAR_BUF_LEN); + // read number of saturation tables + strt = buf; + scanf_u (strt, &end_ptr, &idata->sat_region.data ()); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << ": can't read number of saturation tables from " << strt; + // //BOSERR (section::read_data, level::error) << out_s << bs_end; + // KH_ASSERT_EXCEPTION + // } + + strt=end_ptr; + // read number of PVT tables + scanf_u (strt, &end_ptr, &idata->pvt_region.data ()); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << ": can't read number of PVT tables from " << strt; + // //BOSERR (section::read_data, level::error) << out_s << bs_end; + // KH_ASSERT_EXCEPTION + // } + strt=end_ptr; + //skip two currently unesed parameters + skip_u (strt, &end_ptr, 2); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << ": can't skip currently used parameters from " << strt; + // //BOSERR (section::read_data, level::error) << out_s << bs_end; + // KH_ASSERT_EXCEPTION + // } + strt = end_ptr; + // read number of FIP regions + scanf_u (strt, &end_ptr, &idata->fip_region.data ()); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << ": can't read the maximum number of FIP regions from " << strt; + // //BOSERR (section::read_data, level::error) << out_s << bs_end; + // KH_ASSERT_EXCEPTION + // } + + // Allocate memory for TABDIMS + if (idata->eql_region < 1) + idata->eql_region = 1; + + idata->set_region (idata->pvt_region, idata->fip_region, idata->sat_region, idata->eql_region); + + BOSOUT (section::read_data, level::medium) << + "Keyword " << reader->get_prefix() << ": reading of (" << + idata->pvt_region << ", " << idata->sat_region << ", " << + idata->eql_region << ", " << idata->fip_region << ") is successfully" << bs_end; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::MINPV_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + seq_vector tmp; + tmp.resize(1); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + + if ((len = reader->read_array (keyword, tmp, 0)) != 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + idata->minimal_pore_volume=tmp[0]; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::MINSV_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + seq_vector tmp; + tmp.resize(1); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if ((len = reader->read_array (keyword, tmp, 0)) != 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix() % keyword); + } + idata->minimal_splice_volume=tmp[0]; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::DENSITY_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + seq_vector density; + + density.resize (idata->pvt_region*3); + + for (index_t i = 0; i < (int) idata->pvt_region; i++) + { + if ((len = reader->read_array (keyword, density, 3*i, 3)) != 3) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + } + + try + { + idata -> set_density(density); + } + catch (const bs_exception& e) + { + bs_throw_exception (boost::format ("Error in %s: %s for keyword %s") + % reader->get_prefix () % e.what () % keyword); + } + + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::ROCKTAB_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (idata->rock_region < 1) + { + bs_throw_exception (boost::format ("Error in %s: keyword ROCKCOMP should be used before keyword %s") + % reader->get_prefix () % keyword); + } + + idata->rocktab.resize (idata->rock_region); + + // Read table for each of region + seq_vector dbuf; + for (index_t i = 0; i < idata->rock_region; i++) + { + std::vector &p_col = idata->rocktab[i].get_column (0); + std::vector &pvm_col = idata->rocktab[i].get_column (1); + std::vector &tm_col = idata->rocktab[i].get_column (2); + + if ((len = reader->read_table (keyword, dbuf, 3)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + idata->rocktab[i].set_num_rows (index_t (len)); + for (size_t j = 0; j < len; ++j) + { + p_col[j] = dbuf[j * 3 + 0]; + pvm_col[j] = dbuf[j * 3 + 1]; + tm_col[j] = dbuf[j * 3 + 2]; + } + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::PVTO_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + int i; + int j; + int lj = 0; + double dbuf[DOUB_BUF_LEN] = {0}; + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (!idata->pvto.size()) + { + bs_throw_exception (boost::format ("Error in %s: PVT table for oil has not been initialized yet (keyword: %s)") + % reader->get_prefix () % keyword); + } + + // Read table for each of region + for (i = 0; i < (int) idata->pvt_region; i++) + { + lj = 0; + char buf[CHAR_BUF_LEN] = {0}; + if (reader->read_line (buf, CHAR_BUF_LEN) <= 0) + { + bs_throw_exception (boost::format ("Error in %s: can't read argument for keyword %s") + % reader->get_prefix () % keyword); + } + + if (sscanf (buf, "%lf%lf%lf%lf", &dbuf[lj * 4], + &dbuf[lj * 4 + 1], &dbuf[lj * 4 + 2], + &dbuf[lj * 4 + 3]) != 4) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + for (lj = 1;; ++lj) + { + if (reader->read_line (buf, CHAR_BUF_LEN) <= 0) + { + bs_throw_exception (boost::format ("Error in %s: can't read arguments for keyword %s") + % reader->get_prefix () % keyword); + } + if (buf[0] == '/') + { + idata->pvto[i].main_data_.resize(lj*4); + break; + } + + if ((len = sscanf (buf, "%lf%lf%lf%lf", &dbuf[lj * 4], + &dbuf[lj * 4 + 1], &dbuf[lj * 4 + 2], + &dbuf[lj * 4 + 3])) != 4) + { + if (len == 3) + { + // 3 values table + dbuf[lj * 4 + 3] = dbuf[lj * 4 + 2]; + dbuf[lj * 4 + 2] = dbuf[lj * 4 + 1]; + dbuf[lj * 4 + 1] = dbuf[lj * 4]; + dbuf[lj * 4] = -1.0; //dbuf[(lj - 1) * 4]; // previous + } + else + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + } + } + + // Rows infill + for (j = 0; j < lj*4; j++) + { + idata->pvto[i].main_data_[j] = dbuf[j]; + } + + BOSOUT (section::read_data, level::medium) << "lj=" << lj << " i=" << i << bs_end; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::PVDO_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (!idata->pvtdo.size()) + { + bs_throw_exception (boost::format ("Error in %s: PVT table for dead oil has not been initialized yet (keyword: %s)") + % reader->get_prefix () % keyword); + } + + // Read table for each of region + for (index_t i = 0; i < idata->pvt_region; i++) + { + if ((len = reader->read_table (keyword, idata->pvtdo[i].main_data_, 3)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + + BOSOUT (section::read_data, level::medium) << "len=" << len << " i=" << i << bs_end; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::PVTW_handler(const std::string &keyword, keyword_params_t ¶ms)/********************************/ + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (!idata->pvtw.size()) + { + bs_throw_exception (boost::format ("Error in %s: PVT table for water has not been initialized yet (keyword: %s)") + % reader->get_prefix () % keyword); + } + + // Read table for each of region + for (index_t i = 0; i < idata->pvt_region; i++) + { + //idata->pvtw[i].main_data_.resize(4); + if ((len = reader->read_table (keyword, idata->pvtw[i].main_data_, 4)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + if (len != 1) + { + bs_throw_exception (boost::format ("Error in %s: you can specify only 4 arguments for keyword %s") + % reader->get_prefix () % keyword); + } + } + + BOSOUT (section::read_data, level::medium) << "pvt_region=" << idata->pvt_region << bs_end; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::PVDG_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + // Read table for each of region + for (index_t i = 0; i < idata->pvt_region; i++) + { + //idata->pvtg[i].main_data_.resize(DOUB_BUF_LEN); + if ((len = reader->read_table (keyword, idata->pvtg[i].main_data_, 3)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + + + // Rows infill + BOSOUT (section::read_data, level::medium) << "len=" << len << " i=" << i << bs_end; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::ROCK_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + boost::array dbuf; + + // Compressibility of rock + for (index_t i = 0; i < idata->pvt_region; ++i) + { + if ((len = reader->read_array (keyword, dbuf)) != 2) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + idata->p_ref[i] = dbuf[0]; + idata->rock[i] = dbuf[1]; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::SWOF_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + typename strategy_t::item_array_t swof; + typedef smart_ptr , true> sp_scal_3p_t; + sp_scal_3p_t scal_3p (params.scal_3p); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + // Read table for each of region + for (index_t i = 0; i < idata->sat_region; ++i) + { + if ((len = reader->read_table (keyword, swof, 4)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + + scal_3p->get_water_data()->add_spof (swof, true); + swof.clear (); + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::SGOF_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + typename strategy_t::item_array_t sgof; + typedef smart_ptr , true> sp_scal_3p_t; + sp_scal_3p_t scal_3p (params.scal_3p); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + // Read table for each of region + for (index_t i = 0; i < idata->sat_region; ++i) + { + if ((len = reader->read_table (keyword, sgof, 4)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + + scal_3p->get_gas_data()->add_spof (sgof, false); + sgof.clear (); + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::SWFN_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + + typename strategy_t::item_array_t swfn; + typedef smart_ptr , true> sp_scal_3p_t; + sp_scal_3p_t scal_3p (params.scal_3p); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + // Read table for each of region + for (index_t i = 0; i < idata->sat_region; ++i) + { + if ((len = reader->read_table (keyword, swfn, 3)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + + scal_3p->get_water_data()->add_spfn (swfn, i, true); + swfn.clear (); + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::SGFN_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + typename strategy_t::item_array_t sgfn; + typedef smart_ptr , true> sp_scal_3p_t; + sp_scal_3p_t scal_3p (params.scal_3p); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + // Read table for each of region + for (index_t i = 0; i < idata->sat_region; ++i) + { + if ((len = reader->read_table (keyword, sgfn, 3)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + + scal_3p->get_gas_data()->add_spfn (sgfn, i, false); + sgfn.clear (); + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::SOF3_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + typename strategy_t::item_array_t sof3; + typedef smart_ptr , true> sp_scal_3p_t; + sp_scal_3p_t scal_3p (params.scal_3p); + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + // Read table for each of region + for (index_t i = 0; i < idata->sat_region; ++i) + { + if ((len = reader->read_table (keyword, sof3, 3)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid argument for keyword %s") + % reader->get_prefix () % keyword); + } + + scal_3p->get_water_data()->add_sof3 (sof3, i, true); + scal_3p->get_gas_data()->add_sof3 (sof3, i, false); + sof3.clear (); + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::SOF2_handler(const std::string &/*keyword*/, keyword_params_t &/*params*/) + { + bs_throw_exception ("SOF2 not implemented yet!"); + } + + template + void keyword_manager::EQUIL_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + double dbuf[DOUB_BUF_LEN] = {0}; + char *strt = 0, *end_ptr = 0; + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + //! EQUIL keyword enumerated params + + int i,ii; + + if (!idata->pvto.size()) + { + bs_throw_exception (boost::format ("Error in %s: PVT table for oil has not been initialized yet (keyword: %s") + % reader->get_prefix () % keyword); + } + if (!idata->pvtw.size()) + { + bs_throw_exception (boost::format ("Error in %s: PVT table for water has not been initialized yet (keyword: %s") + % reader->get_prefix () % keyword); + } + if (!idata->pvtg.size()) + { + bs_throw_exception (boost::format ("Error in %s: PVT table for gas has not been initialized yet (keyword: %s") + % reader->get_prefix () % keyword); + } + if (!idata->rock.size()) + { + bs_throw_exception (boost::format ("Error in %s: rock properties have not been initialized yet (keyword: %s") + % reader->get_prefix () % keyword); + } + /*if (!(idata->swof.size() && data->sgof.size()) && + !(idata->swfn.size() && idata->sgfn.size() && idata->sof3.size())) + { + out_s << "Error in " << reader->get_prefix() << + ": SCAL tables has not been initialized yet in keyword " + << keyword; + KH_ASSERT_EXCEPTION + }*/ + if (!idata->equil.size()) + { + bs_throw_exception (boost::format ("Error in %s: EQUIL table has not been initialized yet (keyword: %s") + % reader->get_prefix () % keyword); + } + + if (idata->eql_region == 0) + idata->eql_region = 1; + + for (i = 0; i < (int) idata->eql_region; ++i) + { + reader->read_line (buf, CHAR_BUF_LEN); + if (buf[0] == '/') + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix () % keyword); + } + unwrap (buf); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": not valid string format: " << buf; + // KH_ASSERT_EXCEPTION + // } + + // Values by default + dbuf[EQUIL_DAT_DEPTH] = -1.0; //Ddat + dbuf[EQUIL_DAT_PRESS] = 0.0; //Pdat + dbuf[EQUIL_WOC_DEPTH] = -1.0; //Dwoc + dbuf[EQUIL_WOC_PRESS] = 0.0; //Pwoc + dbuf[EQUIL_GOC_DEPTH] = 0.0; // Dgoc + dbuf[EQUIL_GOC_PRESS] = 0.0; // Pgoc + dbuf[EQUIL_RS_TYPE] = 0; // RS type initialization + dbuf[EQUIL_RV_TYPE] = 0; // RV type initialization + dbuf[EQUIL_NUM_SEC] = 100; // number of points + dbuf[EQUIL_COMP_TYPE] = 0; // composition type initialization + dbuf[EQUIL_COMP_ARG] = 0; // composition argument initialization + + strt = buf; + scanf_d (strt, &end_ptr, &dbuf[EQUIL_DAT_DEPTH]); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": can't read datum depth " << strt; + // KH_ASSERT_EXCEPTION + // } + if (dbuf[EQUIL_DAT_DEPTH] < 0) // Ddat + { + bs_throw_exception (boost::format ("Error in %s: incorrect value of datum depth %f") + % reader->get_prefix () % dbuf[EQUIL_DAT_DEPTH]); + } + strt = end_ptr; + scanf_d (strt, &end_ptr, &dbuf[EQUIL_DAT_PRESS]); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": can't read pressure at datum depth " << strt; + // KH_ASSERT_EXCEPTION + // } + if (dbuf[EQUIL_DAT_PRESS] < 0) //Pdat + { + bs_throw_exception (boost::format ("Error in %s: incorrect pressure value at datum depth %f") + % reader->get_prefix () % dbuf[EQUIL_DAT_PRESS]); + } + strt = end_ptr; + scanf_d (strt, &end_ptr, &dbuf[EQUIL_WOC_DEPTH]); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": can't read WOC depth " << strt; + // KH_ASSERT_EXCEPTION + // } + if (dbuf[EQUIL_WOC_DEPTH] < 0) + { + bs_throw_exception (boost::format ("Error in %s: incorrect value of WOC depth %f") + % reader->get_prefix () % dbuf[EQUIL_WOC_DEPTH]); + } + strt = end_ptr; + scanf_d (strt, &end_ptr, &dbuf[EQUIL_WOC_PRESS]); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": can't read pressure at WOC depth " << strt; + // KH_ASSERT_EXCEPTION + // } + strt = end_ptr; + scanf_d (strt, &end_ptr, &dbuf[EQUIL_GOC_DEPTH]); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": can't read GOC depth " << strt; + // KH_ASSERT_EXCEPTION + // } + if (dbuf[EQUIL_GOC_DEPTH] < 0) + { + // rep->print (LOG_READ_SECTION, LOG_ERR, + // GET_TEXT ("Error in %s: incorrect value of GOC depth %lf\n"), r.get_prefix (), dbuf[4]); + // return -8; + dbuf[EQUIL_GOC_DEPTH] = 0; + } + strt = end_ptr; + scanf_d (strt, &end_ptr, &dbuf[EQUIL_GOC_PRESS]); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": can't read pressure at GOC depth " << strt; + // KH_ASSERT_EXCEPTION + // } + strt = end_ptr; + scanf_d (strt, &end_ptr, &dbuf[EQUIL_RS_TYPE]); + //if (reader->) + // { + // out_s << "Error in " << reader->get_prefix() << + // ": can't read RS initialization type at GOC depth " << strt; + // KH_ASSERT_EXCEPTION + // } +#if 1 + for (ii = 0; ii < EQUIL_TOTAL; ++ii) + idata->equil[EQUIL_TOTAL * i + ii] = dbuf[ii]; +#else + idata->equil[EQUIL_TOTAL * i + EQUIL_DAT_DEPTH] = dbuf[0]; //Ddat + idata->equil[EQUIL_TOTAL * i + EQUIL_DAT_PRESS] = dbuf[1]; //Pdat + idata->equil[EQUIL_TOTAL * i + EQUIL_WOC_DEPTH] = dbuf[2]; //Dwoc + idata->equil[EQUIL_TOTAL * i + EQUIL_WOC_PRESS] = dbuf[3]; //Pwoc + idata->equil[EQUIL_TOTAL * i + EQUIL_GOC_DEPTH] = dbuf[4]; //Dgoc + idata->equil[EQUIL_TOTAL * i + EQUIL_GOC_PRESS] = dbuf[5]; //Pgoc +#endif + } + if (idata->prvd.size()) + idata->prvd.resize(0); + if (idata->rsvd.size()) + idata->rsvd.resize(0); + if (idata->pbvd.size()) + idata->pbvd.resize(0); + + idata->init_section = 1; // flag indicating init section + + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::PRVD_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (idata->eql_region == 0) + idata->eql_region = 1; + + // allocate memory for prvd + idata->prvd.resize(idata->eql_region); + + // Read table for each of region + seq_vector dbuf; + for (index_t i = 0; i < idata->eql_region; ++i) + { + if ((len =reader->read_table (keyword, dbuf, 2)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix () % keyword); + } + + idata->prvd[i].set_table_len (index_t (len)); + + std::vector &dpt = idata->prvd[i].tdepth(); + std::vector &prs = idata->prvd[i].tvalues(); + // Rows infill + for (size_t j = 0; j < len; ++j) + { + dpt[j] = dbuf[j * 2]; + prs[j] = dbuf[j * 2 + 1]; + } + + BOSOUT (section::read_data, level::medium) << "len=" << len << " i=" << i << bs_end; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::RSVD_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (idata->eql_region == 0) + idata->eql_region = 1; + + // allocate memory for rsvd + idata->rsvd.resize(idata->eql_region); + + // Read table for each of region + seq_vector dbuf; + for (index_t i = 0; i < idata->eql_region; ++i) + { + if ((len =reader->read_table (keyword, dbuf, 2)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix () % keyword); + } + + idata->rsvd[i].set_table_len (index_t (len)); + + std::vector &dpt = idata->rsvd[i].tdepth(); + std::vector &prs = idata->rsvd[i].tvalues(); + + dpt.assign (len, 0); + prs.assign (len, 0); + for (size_t j = 0; j < len; ++j) + { + dpt[j] = dbuf[j * 2 + 0]; + prs[j] = dbuf[j * 2 + 1]; + } + + BOSOUT (section::read_data, level::medium) << "len=" << len << " i=" << i << bs_end; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::PBVD_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + sp_idata_t idata (params.data, bs_dynamic_cast ()); + + if (idata->eql_region == 0) + idata->eql_region = 1; + + // allocate memory for rsvd + idata->pbvd.resize(idata->eql_region); + + // Read table for each of region + seq_vector dbuf; + for (index_t i = 0; i < idata->eql_region; ++i) + { + if ((len =reader->read_table (keyword, dbuf, 2)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix () % keyword); + } + + idata->pbvd[i].set_table_len (index_t (len)); + + std::vector &dpt = idata->pbvd[i].tdepth(); + std::vector &prs = idata->pbvd[i].tvalues(); + + dpt.assign (len, 0); + prs.assign (len, 0); + for (size_t j = 0; j < len; ++j) + { + dpt[j] = dbuf[j * 2 + 0]; + prs[j] = dbuf[j * 2 + 1]; + } + + BOSOUT (section::read_data, level::medium) << "len=" << len << " i=" << i << bs_end; + } + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::START_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + sp_this_t km (params.km, bs_dynamic_cast ()); + + if ((reader->read_line (buf, CHAR_BUF_LEN)) <= 0) + { + bs_throw_exception (boost::format ("Error in %s: can't read arguments for keyword %s") + % reader->get_prefix () % keyword); + } + boost::gregorian::date start=reader->read_date(std::string(buf)); + km->starting_date = boost::posix_time::ptime(start); // set starting date + + // Current date + km->current_date = boost::posix_time::ptime(start);; + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + + template + void keyword_manager::DATE_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + char buf[CHAR_BUF_LEN] = {0}; + typedef event_manager event_manager_t; + typedef smart_ptr sp_event_manager_t; + sp_event_manager_t em (params.em, bs_dynamic_cast ()); + sp_this_t km (params.km, bs_dynamic_cast ()); + + if ((reader->read_line (buf, CHAR_BUF_LEN)) <= 0) + { + bs_throw_exception (boost::format ("Error in %s: can't read arguments for keyword %s") + % reader->get_prefix () % keyword); + } + + km->current_date=boost::posix_time::ptime(reader->read_date (std::string(buf))); + if (em->event_list.find (km->current_date)==em->event_list.end ()) + { + std::list tl; + em->event_list.insert (std::make_pair (km->current_date, tl)); + } + + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::DATES_handler(const std::string &keyword, keyword_params_t ¶ms) + { + DATE_handler(keyword, params); + } + + template + void keyword_manager::TSTEP_handler(const std::string &keyword, keyword_params_t ¶ms) + { + KH_READER_DEF + seq_vector dtmp; + dtmp.resize(MAX_TIME_STEPS_DEF); + typedef event_manager event_manager_t; + typedef smart_ptr sp_event_manager_t; + sp_event_manager_t em (params.em, bs_dynamic_cast ()); + sp_this_t km (params.km, bs_dynamic_cast ()); + + if ((len = reader->read_array (keyword, dtmp)) < 1) + { + bs_throw_exception (boost::format ("Error in %s: not enough valid arguments for keyword %s") + % reader->get_prefix () % keyword); + } + + //! + //! dtmp[0] <- days + //! dtmp[0]*24*60*60 <-seconds + //! dtmp[0]*24*60*60*1000 <-millisecs + + for (size_t i = 0; i < (size_t) len; ++i) + { + km->current_date += boost::posix_time::millisec (dtmp[i]*24*60*60*1000); + + if (em->event_list.find (km->current_date) == em->event_list.end ()) + { + std::list tl; + em->event_list.insert (std::make_pair (km->current_date, tl)); + } + } + + BOSOUT (section::read_data, level::medium) << keyword << bs_end; + } + + template + void keyword_manager::TSTEPS_handler(const std::string &keyword, keyword_params_t ¶ms) + { + TSTEP_handler(keyword, params); + } + +//bs stuff +#define KH_SPEC(NAME)\ + template void keyword_manager ::NAME (const std::string &keyword, keyword_params_t ¶ms);\ + template void keyword_manager ::NAME (const std::string &keyword, keyword_params_t ¶ms);\ + template void keyword_manager ::NAME (const std::string &keyword, keyword_params_t ¶ms); + + template keyword_manager::~keyword_manager (); + template keyword_manager::~keyword_manager (); + template keyword_manager::~keyword_manager (); + + KH_SPEC(int_array_handler) + KH_SPEC(float_array_handler) + KH_SPEC(event_handler) + KH_SPEC(TITLE_handler) + KH_SPEC(OIL_handler) + KH_SPEC(WATER_handler) + KH_SPEC(GAS_handler) + KH_SPEC(PROCESS_PARAMS_handler) + KH_SPEC(RESTART_handler) + KH_SPEC(REPORTS_handler) + KH_SPEC(REPORTFILE_handler) + KH_SPEC(REPORTSCREEN_handler) + KH_SPEC(STONE1_handler) + KH_SPEC(STONE2_handler) + KH_SPEC(RELATIVE_PERM_DEFAULT_handler) + KH_SPEC(UNITS_handler) + //KH_SPEC(DIMENS_handler) + KH_SPEC(ROCKCOMP_handler) + KH_SPEC(REGDIMS_handler) + KH_SPEC(REGNUM_handler) + KH_SPEC(EQLDIMS_handler) + KH_SPEC(TABDIMS_handler) + //KH_SPEC(COORD_handler) + //KH_SPEC(ZCORN_handler) + KH_SPEC(MINPV_handler) + KH_SPEC(MINSV_handler) + KH_SPEC(DENSITY_handler) + KH_SPEC(ROCKTAB_handler) + KH_SPEC(PVTO_handler) + KH_SPEC(PVDO_handler) + KH_SPEC(PVTW_handler) + KH_SPEC(PVDG_handler) + KH_SPEC(ROCK_handler) + KH_SPEC(SWOF_handler) + KH_SPEC(SGOF_handler) + KH_SPEC(SWFN_handler) + KH_SPEC(SGFN_handler) + KH_SPEC(SOF3_handler) + KH_SPEC(SOF2_handler) + KH_SPEC(EQUIL_handler) + KH_SPEC(PRVD_handler) + KH_SPEC(RSVD_handler) + KH_SPEC(PBVD_handler) + KH_SPEC(START_handler) + KH_SPEC(DATE_handler) + KH_SPEC(DATES_handler) + KH_SPEC(TSTEP_handler) + KH_SPEC(TSTEPS_handler) + KH_SPEC(WELLDIMS_handler) + + //!TODO: kill next string after debug + //template class keyword_manager ; + //template class keyword_manager ; + +}//nsbs diff --git a/bs_bos_core/src/keywords_registration.cpp b/bs_bos_core/src/keywords_registration.cpp new file mode 100644 index 0000000..f47295e --- /dev/null +++ b/bs_bos_core/src/keywords_registration.cpp @@ -0,0 +1,189 @@ +/** +* @file keywords.h +* @brief keyword registration +* @author Morozov Andrey +* @date 2008-07-02 +*/ +#include "stdafx.h" + +#include "event_base.h" +#include "event_manager.h" +#include "keyword_manager.h" +#include "keyword_info_base.h" +#include "strategy_name.h" + +namespace blue_sky + { + //!TODO: may be use one variable instead of handler_blahblahblah +#define REG_KEYWORD_EXT(KWRD,HNDL) \ + register_keywyfgord(#KWRD, keyword_handler (&this_t::HNDL)); + +#define REG_KEYWORD(KWRD) \ + register_keyword(#KWRD, keyword_handler (&this_t::KWRD##_handler)); + +#define REG_ARRAY_KEYWORD(KWRD,T) \ + register_keyword(#KWRD, keyword_handler (&this_t::T##_array_handler, KWRD)); + +#define REG_INT_ARRAY_KEYWORD(KWRD) \ + REG_ARRAY_KEYWORD(KWRD,int); + +#define REG_FLOAT_ARRAY_KEYWORD(KWRD) \ + REG_ARRAY_KEYWORD(KWRD,float); + + + + template + void keyword_manager::register_keywords()//const sp_event_manager_t &em) + { + //Keywords + REG_KEYWORD(TITLE); + REG_KEYWORD(OIL); + REG_KEYWORD(WATER); + REG_KEYWORD(GAS); + REG_KEYWORD(PROCESS_PARAMS); + REG_KEYWORD(RESTART); + REG_KEYWORD(REPORTS); + REG_KEYWORD(REPORTFILE); + REG_KEYWORD(REPORTSCREEN); + //REG_KEYWORD(ARITHMETIC); + REG_KEYWORD(STONE1); + REG_KEYWORD(STONE2); + REG_KEYWORD(RELATIVE_PERM_DEFAULT); + REG_KEYWORD(UNITS); + //REG_KEYWORD(DIMENS); + REG_KEYWORD(ROCKCOMP); + REG_KEYWORD(REGDIMS); + REG_KEYWORD(REGNUM); + REG_KEYWORD(EQLDIMS); + REG_KEYWORD(TABDIMS); + //REG_KEYWORD(COORD); + //REG_KEYWORD(ZCORN); + REG_KEYWORD(MINPV); + REG_KEYWORD(MINSV); + REG_KEYWORD(DENSITY); + REG_KEYWORD(ROCKTAB); + REG_KEYWORD(PVTO); + REG_KEYWORD(PVDO); + REG_KEYWORD(PVTW); + REG_KEYWORD(PVDG); + REG_KEYWORD(ROCK); + REG_KEYWORD(SWOF); + REG_KEYWORD(SGOF); + REG_KEYWORD(SWFN); + REG_KEYWORD(SGFN); + REG_KEYWORD(SOF2); + REG_KEYWORD(EQUIL); + REG_KEYWORD(PRVD); + REG_KEYWORD(RSVD); + REG_KEYWORD(PBVD); + REG_KEYWORD(START); + REG_KEYWORD(DATE); + REG_KEYWORD(DATES); + REG_KEYWORD(TSTEP); + REG_KEYWORD(TSTEPS); + REG_KEYWORD(WELLDIMS); + + //Pool array + //int + REG_INT_ARRAY_KEYWORD(MPFANUM); + REG_INT_ARRAY_KEYWORD(EQLNUM); + REG_INT_ARRAY_KEYWORD(SATNUM); + REG_INT_ARRAY_KEYWORD(PVTNUM); + //REG_INT_ARRAY_KEYWORD(ACTNUM); + REG_INT_ARRAY_KEYWORD(FIPNUM); + REG_INT_ARRAY_KEYWORD(BNDNUM); + REG_INT_ARRAY_KEYWORD(EOSNUM); + REG_INT_ARRAY_KEYWORD(ROCKNUM); + //double + //REG_FLOAT_ARRAY_KEYWORD(PERMXY); + //REG_FLOAT_ARRAY_KEYWORD(PERMYZ); + //REG_FLOAT_ARRAY_KEYWORD(PERMZX); + //REG_FLOAT_ARRAY_KEYWORD(PERMX); + //REG_FLOAT_ARRAY_KEYWORD(PERMY); + //REG_FLOAT_ARRAY_KEYWORD(PERMZ); + //REG_FLOAT_ARRAY_KEYWORD(PORO); + //REG_FLOAT_ARRAY_KEYWORD(NTG); + REG_FLOAT_ARRAY_KEYWORD(SGL); + REG_FLOAT_ARRAY_KEYWORD(SGU); + REG_FLOAT_ARRAY_KEYWORD(SOGCR); + REG_FLOAT_ARRAY_KEYWORD(SGCR); + REG_FLOAT_ARRAY_KEYWORD(SWL); + REG_FLOAT_ARRAY_KEYWORD(SWU); + REG_FLOAT_ARRAY_KEYWORD(SOWCR); + REG_FLOAT_ARRAY_KEYWORD(SWCR); + REG_FLOAT_ARRAY_KEYWORD(PBUB); + REG_FLOAT_ARRAY_KEYWORD(RS); + REG_FLOAT_ARRAY_KEYWORD(PCW); + REG_FLOAT_ARRAY_KEYWORD(SWATINIT); + REG_FLOAT_ARRAY_KEYWORD(SOIL); + REG_FLOAT_ARRAY_KEYWORD(SWAT); + REG_FLOAT_ARRAY_KEYWORD(PRESSURE); + //REG_FLOAT_ARRAY_KEYWORD(DX); + //REG_FLOAT_ARRAY_KEYWORD(DY); + //REG_FLOAT_ARRAY_KEYWORD(DZ); + //REG_FLOAT_ARRAY_KEYWORD(MULTX); + //REG_FLOAT_ARRAY_KEYWORD(MULTY); + //REG_FLOAT_ARRAY_KEYWORD(MULTZ); + //REG_FLOAT_ARRAY_KEYWORD(TOPS); + //REG_FLOAT_ARRAY_KEYWORD(MULTPV); + REG_FLOAT_ARRAY_KEYWORD(SGAS); + + //BS_ASSERT (em); + + const type_descriptor &event_td = event_base ::bs_type (); + const std::vector &types = BS_KERNEL.registered_types (); + for (size_t i = 0, cnt = types.size (); i < cnt; ++i) + { + const type_descriptor &td = types[i].td_; + type_descriptor parent_td = td.parent_td (); + while (!parent_td.is_nil ()) + { + if (parent_td.stype_ == event_td.stype_) + { + register_keyword (td.short_descr_, keyword_handler (&this_t::event_handler)); + break; + } + + parent_td = parent_td.parent_td (); + } + } + } + + template + void keyword_manager::register_plugin_keywords() + { + const std::vector &types = BS_KERNEL.registered_types (); + sp_keyword_info_base_t keywords; + const type_descriptor &keyword_info_td = keyword_info_base ::bs_type (); + sp_objbase keyword_manager (this); + + for (size_t i = 0, cnt = types.size (); i < cnt; ++i) + { + const type_descriptor &td = types[i].td_; + type_descriptor parent_td = td; + while (!parent_td.is_nil ()) + { + if (parent_td.stype_ == keyword_info_td.stype_) + { + keywords = BS_KERNEL.create_object (td); + BOSOUT (section::keywords, level::low) << boost::format ("Loading keywords from [%s]...") % td.short_descr_ << bs_end; + keywords->register_keywords (keyword_manager); + + break; + } + + parent_td = parent_td.parent_td (); + } + } + } + + //!TODO: kill next string after debug + template void keyword_manager ::register_keywords();//const sp_event_manager_t &em); + template void keyword_manager ::register_keywords();//const sp_event_manager_t &em); + template void keyword_manager ::register_keywords();//const sp_event_manager_t &em); + + template void keyword_manager ::register_plugin_keywords(); + template void keyword_manager ::register_plugin_keywords(); + template void keyword_manager ::register_plugin_keywords(); + +}//ns_bs diff --git a/bs_bos_core/src/main.cpp b/bs_bos_core/src/main.cpp new file mode 100644 index 0000000..d09e5d7 --- /dev/null +++ b/bs_bos_core/src/main.cpp @@ -0,0 +1,477 @@ +#include "stdafx.h" + +//#ifdef _MPI +//#include "mpi_csr_comm.h" +//#include "mpi_csr_matrix.h" +//#endif // #ifdef _MPI + +#ifdef _MPI_MY +#include "mpi_mesh_grdecl.h" +#endif + +//#include "bs_import_common.h" + +#include "jacobian.h" +#include "calc_model.h" + +//#include "py_mpi_vector.h" +//#include "py_mpi_csr_matrix.h" + +#include "two_stage_preconditioner.h" +#include "py_two_stage_preconditioner.h" + +#include "event_manager.h" +#include "py_event_manager.h" +#include "keyword_manager.h" +#include "py_keyword_manager.h" + +#include "reservoir_simulator.h" +#include "py_reservoir_simulator.h" + +#include "py_calc_model.h" + +#include "data_storage_interface.h" +#include "py_data_storage_interface.h" + +#include "calc_well.h" +#include "py_calc_well.h" +#include "facility_manager.h" + +#include "well_controller.h" +#include "well_limit_operation.h" + +#include "calc_rho.h" +#include "calc_well_pressure.h" + +#include "py_event_base.h" + +#include "py_facility_manager.h" +#include "py_reservoir.h" + +#include "py_jacobian.h" +#include "default_well.h" +#include "py_well_factory.h" +#include "py_default_wells.h" + +#include "fi_params.h" + +#include "prepare_fpu.h" + +#include "csr_ilu_cfl.h" +#include "py_csr_ilu_cfl_prec.h" + +#include + + + + +using namespace blue_sky; +using namespace blue_sky::python; +using namespace boost::python; + +namespace blue_sky +{ + BLUE_SKY_PLUGIN_DESCRIPTOR_EXT ("bs_bos_core", "1.0.0", "Blue Sky BOS Core Plugin", "Blue Sky realization of Black Oil Simulator", "bs_bos_core") + +// struct BS_API_PLUGIN test_y; +// +// struct BS_API_PLUGIN test_i +// { +// virtual void method () = 0; +// +// virtual ~test_i () {} +// }; +// +// struct BS_API_PLUGIN test_x : test_i +// { +// virtual ~test_x () +// { +// printf ("~test_x\n"); +// } +// virtual void method () +// { +// printf ("test_x::method\n"); +// } +// +// virtual void m (test_y *) +// { +// printf ("test_x::m\n"); +// } +// }; +// struct BS_API_PLUGIN test_z : public test_x +// { +// virtual ~test_z () +// { +// printf ("~test_z\n"); +// } +// virtual void method () +// { +// printf ("test_z::method\n"); +// } +// +// virtual void m (test_y *) +// { +// printf ("test_z::m\n"); +// } +// }; +// +// template +// struct BS_API_PLUGIN test_wrapper : T, wrapper +// { +// ~test_wrapper () +// { +// printf ("~test_wrapper\n"); +// } +// +// test_wrapper (T *t) +// :t_ (t) +// { +// +// } +// +// void method () +// { +// if (override f = this->get_override ("method")) +// { +// f (); +// } +// else +// { +// t_->method (); +// } +// } +// void method_default () +// { +// printf ("method_default\n"); +// } +// +// void m (test_y *y) +// { +// if (override f = this->get_override ("m")) +// { +// f (*y); +// } +// else +// { +// t_->m (y); +// } +// } +// +// T *t_; +// }; +// +// template +// static +// smart_ptr , false> +// make_test_x_wrapper () +// { +// printf ("make_test_x_wrapper\n"); +// return new test_wrapper (); +// } +// +// template +// static +// smart_ptr , false> +// make_test_x_wrapper_2 (T *i) +// { +// printf ("make_test_x_wrapper_2\n"); +// return new test_wrapper (i); +// } +// +// struct BS_API_PLUGIN test_y +// { +// virtual ~test_y () +// { +// printf ("~test_y\n"); +// } +// virtual void method (test_x *x) +// { +// printf ("test_y_x::method\n"); +// x->method (); +// } +// virtual void mz (test_z *x) +// { +// printf ("test_y_z::method\n"); +// x->method (); +// } +// virtual void mi (test_i *x) +// { +// printf ("test_y_i::method\n"); +// x->method (); +// } +// virtual void m2 (const smart_ptr , false> &x) +// { +// printf ("test_y::m2\n"); +// x->method (); +// } +// +// virtual void m3 (smart_ptr , false> &x) +// { +// printf ("test_y::m3\n"); +// x->method (); +// } +// }; +// +// +// template inline T * get_pointer(smart_ptr const & p) +// { +// return const_cast (p.get()); +// } +// +// using namespace boost::python; +// +// template +// object init__ (object py_obj) +// { +// printf ("init__\n"); +// object return_value = call_method(py_obj.ptr(), "__cons__"); +// initialize_wrapper (py_obj.ptr (), extract *> (py_obj)); +// return return_value; +// } +// +// template +// object init__2 (object py_obj, T *i) +// { +// printf ("init__\n"); +// object return_value = call_method(py_obj.ptr(), "__cons__", i); +// initialize_wrapper (py_obj.ptr (), extract *> (py_obj)); +// return return_value; +// } +// +// void +// py_export_test_x () +// { +// class_ ("test_i", no_init) +// ; +// +// class_ */, bases /*, boost::noncopyable*/> ("test_x"/*, boost::python::no_init*/) +// .def ("method", &test_x::method)//, &test_wrapper::method_default) +// .def ("m", &test_x::m)//, &test_wrapper::method_default) +// //.def ("__cons__", make_constructor (make_test_x_wrapper )) +// //.def ("__init__", init__ ) +// ; +// class_ */, bases */ >/*, boost::noncopyable*/> ("test_z"/*, boost::python::no_init*/) +// //.def ("__cons__", make_constructor (make_test_x_wrapper )) +// //.def ("__init__", init__ ) +//// .def ("m", &test_z::method)//, &test_wrapper ::method_default) +// //.def ("method", &test_z::method)//, &test_wrapper ::method_default) +// ; +// +// class_ , bases , boost::noncopyable> ("test_x_wrapper", boost::python::no_init) +// .def ("__cons__", make_constructor (make_test_x_wrapper_2 )) +// .def ("__init__", init__2 ) +// .def ("method", &test_wrapper ::method)//, &test_wrapper ::method_default) +// .def ("m", &test_wrapper ::m)//, &test_wrapper ::method_default) +// ; +// +// class_ , bases , boost::noncopyable> ("test_z_wrapper", boost::python::no_init) +// .def ("__cons__", make_constructor (make_test_x_wrapper_2 )) +// .def ("__init__", init__2 ) +// .def ("method", &test_wrapper ::method)//, &test_wrapper ::method_default) +// .def ("m", &test_wrapper ::m)//, &test_wrapper ::method_default) +// ; +// +// class_ ("test_y") +// .def ("method", &test_y::method) +// //.def ("method", &test_y::mz) +// .def ("mz", &test_y::mz) +// .def ("mi", &test_y::mi) +// .def ("m2", &test_y::m2) +// .def ("m3", &test_y::m3) +// ; +// +// typedef smart_ptr test_x_t; +// typedef smart_ptr , false> test_x_wrapper_t; +// register_ptr_to_python(); +// register_ptr_to_python(); +// +// typedef smart_ptr test_z_t; +// typedef smart_ptr , false> test_z_wrapper_t; +// register_ptr_to_python(); +// register_ptr_to_python(); +// +// register_ptr_to_python(); +// register_ptr_to_python(); +// register_ptr_to_python >(); +// } + + + BLUE_SKY_REGISTER_PLUGIN_FUN + { + + //bool res = true; + const plugin_descriptor & pd = *bs_init.pd_; + + bool res = true; + + //////////////////////////////Events///////////////////////////////////////////// + res &= event_base_register_types (pd); + res &= event_manager_register_types (pd); + + res &= blue_sky::well_events_register_type (pd); + BS_ASSERT (res); + //////////////////////////////Keywords///////////////////////////////////////////// + res &= blue_sky::give_kernel::Instance().register_type(*bs_init.pd_, keyword_manager::bs_type()); + BS_ASSERT (res); + res &= blue_sky::give_kernel::Instance().register_type(*bs_init.pd_, keyword_manager::bs_type()); + BS_ASSERT (res); + + //////////////////////////////Linear Solver/////////////////////////////// + res &= blue_sky::two_stage_prec_register_type (pd); + BS_ASSERT (res); + +#ifdef BS_BOS_CORE_USE_CSR_ILU_CFL_PREC + res &= blue_sky::give_kernel::Instance().register_type(*bs_init.pd_, csr_ilu_cfl_prec::bs_type()); + BS_ASSERT (res); + res &= blue_sky::give_kernel::Instance().register_type(*bs_init.pd_, csr_ilu_cfl_prec::bs_type()); + BS_ASSERT (res); + res &= blue_sky::give_kernel::Instance().register_type(*bs_init.pd_, csr_ilu_cfl_prec::bs_type()); + BS_ASSERT (res); +#endif + + +//#ifdef _MPI +// res &= blue_sky::mpi_csr_matrix_register_type (pd); +// BS_ASSERT (res); +// res &= blue_sky::mpi_csr_comm_register_type (pd); +// BS_ASSERT (res); +//#endif + + res &= calc_rho_register_types (pd); BS_ASSERT (res); + res &= calc_well_pressure_register_types (pd); BS_ASSERT (res); + res &= calc_well_register_types (pd); BS_ASSERT (res); + res &= wells::default_well_register_types (pd); BS_ASSERT (res); + + res &= facility_manager_register_type (pd); + BS_ASSERT (res); + res &= well_factory_register_type (pd); + BS_ASSERT (res); + res &= wells::well_controller_factory_register_type (pd); + BS_ASSERT (res); + res &= wells::well_limit_operation_factory_register_type (pd); + BS_ASSERT (res); + + res &= data_storage_proxy_register_type (pd); + BS_ASSERT (res); + res &= data_storage_register_type (pd); + BS_ASSERT (res); + res &= data_serializer_register_type (pd); + BS_ASSERT (res); + res &= data_storage_interface_register_type (pd); + BS_ASSERT (res); + + res &= reservoir_simulator_register_types (pd); + BS_ASSERT (res); + + return res; + } +}//bs +// +//namespace blue_sky { +// template +// void +// convert_double_to_float (bcsr_d *bcsr_mx_d, bcsr_f *bcsr_mx_f) +// { +// //typedef typename mx_t::i_type_t i_type; +// //typedef typename mx_t::fp_type_t fp_type; +// +// typedef typename bcsr_d::index_t index_t; +// typedef typename bcsr_d::item_t item_t; +// typedef typename bcsr_d::item_array_t item_array_t; +// typedef typename bcsr_d::index_array_t index_array_t; +// +// //typedef typename bcsr_d::index_t index_t; +// typedef typename bcsr_f::item_t rhs_item_t; +// +// const index_t *rows_d = &bcsr_mx_d->get_rows_ptr ()[0]; +// const index_t *cols_d = &bcsr_mx_d->get_cols_ind ()[0]; +// const item_t *val_d = &bcsr_mx_d->get_values ()[0]; +// +// index_t *rows_f = &bcsr_mx_f->get_rows_ptr ()[0]; +// index_t *cols_f = &bcsr_mx_f->get_cols_ind ()[0]; +// rhs_item_t *val_f = &bcsr_mx_f->get_values ()[0]; +// +// typedef typename bcsr_d::i_type_t i_type; +// +// bcsr_mx_f->alloc_rows_ptr (bcsr_mx_d->n_rows, 0); +// bcsr_mx_f->alloc_cols_ind_and_values (bcsr_mx_d->get_n_non_zeros ()); +// +// bcsr_mx_f->get_rows_ptr ().assign (bcsr_mx_d->get_rows_ptr ().begin (), bcsr_mx_d->get_rows_ptr ().end ()); +// bcsr_mx_f->get_diag_ind ().assign (bcsr_mx_d->get_diag_ind ().begin (), bcsr_mx_d->get_diag_ind ().end ()); +// bcsr_mx_f->get_cols_ind ().assign (bcsr_mx_d->get_cols_ind ().begin (), bcsr_mx_d->get_cols_ind ().end ()); +// bcsr_mx_f->get_values ().assign (bcsr_mx_d->get_values ().begin (), bcsr_mx_d->get_values ().end ()); +// +// bcsr_mx_f->n_rows = bcsr_mx_d->n_rows; +// bcsr_mx_f->n_cols = bcsr_mx_d->n_cols; +// bcsr_mx_f->n_block_size = bcsr_mx_d->n_block_size; +// +// index_array_t tmp_rows_ptr, tmp_diag_ind, tmp_cols_ind; +// item_array_t tmp_values; +// std::swap (bcsr_mx_d->get_rows_ptr (), tmp_rows_ptr); +// std::swap (bcsr_mx_d->get_diag_ind (), tmp_diag_ind); +// std::swap (bcsr_mx_d->get_cols_ind (), tmp_cols_ind); +// std::swap (bcsr_mx_d->get_values (), tmp_values); +// } +// +// template +// void +// py_convert_double_to_float (py_bcsr_d &bcsr_d, py_bcsr_f &bcsr_f) +// { +// convert_double_to_float (&(*bcsr_d.template get_lspx ()), +// &(*bcsr_f.template get_lspx ())); +// } +//} + +#ifdef BSPY_EXPORTING_PLUGIN +BLUE_SKY_INIT_PY_FUN +{ + using namespace boost::python; + + py_export_fi_params (); + +//#ifdef _MPI +// python::py_export_mpi_vector (); +// python::py_export_mpi_csr_matrix (); +//#endif + + + py_export_two_stage_prec (); + + //python::py_export_events (); + //py_export_event_manager(); + + python::py_export_reservoir_simulator (); + python::py_export_calc_model (); + // we should export enum only for one instance of reservoir simulator + //reservoir_simulator::py_export_signals_enum (); //!TODO: + + python::py_export_calc_well (); + + python::py_export_data_storage_interface (); + + reservoir_simulator ::py_export_signals_enum(); + reservoir_simulator ::py_export_signals_enum(); + + python::py_export_jacobian (); + + python::py_export_facility_manager (); + python::py_export_reservoir (); + + python::py_export_well_factories (); + +#ifdef BS_BOS_CORE_USE_CSR_ILU_CFL_PREC + python::py_export_csr_ilu_cfl_prec (); +#endif + + python::py_export_default_wells (); + + def ("enable_fpu_exceptions", blue_sky::tools::prepare_fpu::enable_exceptions); + + python::export_keyword_manager (); + + + //def ("convert_double_to_float", py_convert_double_to_float , python::py_bcsr_matrix >); + + //py_export_test_x (); +} +#endif //BSPY_EXPORT_PLUGIN diff --git a/bs_bos_core/src/norm_calc.cpp b/bs_bos_core/src/norm_calc.cpp new file mode 100644 index 0000000..6d285c8 --- /dev/null +++ b/bs_bos_core/src/norm_calc.cpp @@ -0,0 +1,119 @@ +/** + * @file norm_cacl.cpp + * @brief calculate norms + * @author Borschuk Oleg + * @date 2008-01-31 + */ +#include "stdafx.h" +#include "norm_calc.h" + +namespace blue_sky + { + +#ifdef _MPI +//#define _MPI_DEBUG_NORM +#endif //_MPI + + using namespace norms; + +#define SET_VALUE(name_idx, value, descr, flag) \ + val[name_idx] = value; \ + name[name_idx] = descr; \ + p_flag[name_idx] = flag; + +//! default constructor + template + norms_storage ::norms_storage () + { + val.resize (NORMS_COUNTER); + name.resize (NORMS_COUNTER); + clear (); + + SET_VALUE (C_CPV, 0.0, "C-norm", 1); + SET_VALUE (C_CPV_GAS, 0.0, "C-norm (gas)", 1); + SET_VALUE (C_CPV_WATER, 0.0, "C-norm (water)", 1); + SET_VALUE (C_CPV_OIL, 0.0, "C-norm (oil)", 1); + + SET_VALUE (C_ACPV, 0.0, "C-norm average", 0); + SET_VALUE (C_ACPV_GAS, 0.0, "C-norm average (gas)", 0); + SET_VALUE (C_ACPV_WATER, 0.0, "C-norm average (water)", 1); + SET_VALUE (C_ACPV_OIL, 0.0, "C-norm average (oil)", 1); + + SET_VALUE (L2_CPV, 0.0, "L2-norm", 0); + SET_VALUE (L2_CPV_GAS, 0.0, "L2-norm (gas)", 0); + SET_VALUE (L2_CPV_WATER, 0.0, "L2-norm (water)", 0); + SET_VALUE (L2_CPV_OIL, 0.0, "L2-norm (oil)", 0); + + SET_VALUE (L2_ACPV, 0.0, "L2-norm average", 0); + SET_VALUE (L2_ACPV_GAS, 0.0, "L2-norm average (gas)", 0); + SET_VALUE (L2_ACPV_WATER, 0.0, "L2-norm average (water)", 0); + SET_VALUE (L2_ACPV_OIL, 0.0, "L2-norm average (oil)", 0); + + SET_VALUE (MB_ERR, 0.0, "Mat. Balance error", 1); + SET_VALUE (MB_ERR_GAS, 0.0, "Mat. Balance error (gas)", 0); + SET_VALUE (MB_ERR_WATER, 0.0, "Mat. Balance error (water)", 0); + SET_VALUE (MB_ERR_OIL, 0.0, "Mat. Balance error (oil)", 0); + +#ifdef _MPI_DEBUG_NORM //all norms will be printed + memset (p_flag, -1, NORMS_COUNTER * sizeof (int)); +#endif //_MPI + } + +//! default constructor + template + norms_storage::~norms_storage () + { + } + +//! clear all norms + template + void + norms_storage::clear () + { + val.assign (val.size (), 0); + idx.assign (0); + } + +//! print norms + /*void + norms_storage::print (const fi_mesh *msh) + { + int n = val.size (); + unsigned int i, j, k; + + rep->print (LOG_CHECK_SECTION, LOG_ERR, "========== NORM TYPE ==========|= RESIDUAL =|= CELL ==|=== I, J, K ===|\n", NORMS_COUNTER); + for (int l = 0; l < n; ++l) + { + if (!p_flag[l]) + continue; + msh->convert_num_to_block_coord (idx[l], i, j, k); + #ifdef _MPI_DEBUG_NORM + rep->switch_to_collective_print(); + rep->fflush_and_wait(); + #endif + rep->print (LOG_CHECK_SECTION, LOG_ERR, "%30s |%11.2le |%8d |%4d,%4d,%4d |\n", + val[l].second.c_str (), val[l].first, idx[l], i + 1, j + 1, k + 1); + #ifdef _MPI_DEBUG_NORM + rep->switch_to_root_print(); + rep->fflush_and_wait(); + #endif + } + rep->print (LOG_CHECK_SECTION, LOG_ERR, "===============================|============|=========|===============|\n"); + }*/ + + + template + norms_storage & + norms_storage::operator= (const norms_storage &rhs) + { + val = rhs.val; + //memcpy (idx, rhs.idx, sizeof (int) * NORMS_COUNTER); + std::copy (rhs.idx.begin(),rhs.idx.end(), idx.begin()); + return *this; + } + + template class norms_storage ; + template class norms_storage ; + template class norms_storage ; + +} //ns bs diff --git a/bs_bos_core/src/prepare_fpu_unix.cpp b/bs_bos_core/src/prepare_fpu_unix.cpp new file mode 100644 index 0000000..bb9d382 --- /dev/null +++ b/bs_bos_core/src/prepare_fpu_unix.cpp @@ -0,0 +1,55 @@ +/** + * \file prepare_fpu_unix.cpp + * \brief prepare fpu to work (enable exception, etc) + * \author Sergey Miryanov + * \date 10.09.2009 + * */ +#include "stdafx.h" +#include "prepare_fpu.h" + +#ifdef UNIX +#include +#include + +#include "bs_kernel_tools.h" + +namespace blue_sky { +namespace tools { + + namespace detail { + + void + set_fpu (unsigned int mode) + { + asm ("fldcw %0" : : "m" (*&mode)); + } + + void + fpe_handler (int sig_num) + { + bs_throw_exception ("FPU exception occured"); + // << kernel_tools::get_backtrace (72) + // << bs_end; + + //signal (SIGFPE, SIG_DFL); + //raise (sig_num); + } + + } // namespace detail + + void + prepare_fpu::enable_exceptions () + { + //detail::set_fpu (0x27F); + //feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); + +#ifdef BS_BOS_CORE_USE_FPE_HANDLER + //signal (SIGFPE, detail::fpe_handler); +#endif + } + +} // namespace tools +} // namespace blue_sky + +#endif // #ifndef UNIX + diff --git a/bs_bos_core/src/prepare_fpu_win.cpp b/bs_bos_core/src/prepare_fpu_win.cpp new file mode 100644 index 0000000..724b4d9 --- /dev/null +++ b/bs_bos_core/src/prepare_fpu_win.cpp @@ -0,0 +1,34 @@ +/** + * \file prepare_fpu_win.cpp + * \brief prepare fpu to work (enable exception, etc) + * \author Sergey Miryanov + * \date 10.09.2009 + * */ +#include "stdafx.h" +#include "prepare_fpu.h" + +#ifndef UNIX +#include + +namespace blue_sky { +namespace tools { + + void + prepare_fpu::enable_exceptions () + { + _clearfp (); + + unsigned int cw = _controlfp (0, 0); + cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID); + unsigned int original = _controlfp (cw, MCW_EM); + + // to restore call + // _controlfp (original, MCW_EM) + } + +} // namespace tools +} // namespace blue_sky + + +#endif // #ifndef UNIX + diff --git a/bs_bos_core/src/py_calc_model.cpp b/bs_bos_core/src/py_calc_model.cpp new file mode 100644 index 0000000..326115b --- /dev/null +++ b/bs_bos_core/src/py_calc_model.cpp @@ -0,0 +1,1023 @@ +#include "stdafx.h" + +#include "calc_model.h" +#include "py_calc_model.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "py_scal_wrapper.h" +#include "py_data_class.h" +#include BS_STOP_PLUGIN_IMPORT () + +// WTF?? +#include "well_results_storage.h" +#include "fip_results_storage.h" + +#include "export_python_wrapper.h" + +using namespace boost::python; + +namespace blue_sky + { + namespace python + { + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_cap_pressure () const + { + item_array_t t; + t.insert(t.end(), this->cap_pressure.begin(), this->cap_pressure.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_s_deriv_cap_pressure () const + { + item_array_t t; + t.insert(t.end(), this->s_deriv_cap_pressure.begin(), this->s_deriv_cap_pressure.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_relative_perm () const + { + item_array_t t; + t.insert(t.end(), this->relative_perm.begin(), this->relative_perm.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_s_deriv_relative_perm () const + { + item_array_t t; + t.insert(t.end(), this->s_deriv_relative_perm.begin(), this->s_deriv_relative_perm.end()); + return t; + } + + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_gas_oil_ratio () + { + return this->get_spx ()->gas_oil_ratio; + } + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_p_deriv_gas_oil_ratio () const + { + return this->p_deriv_gas_oil_ratio; + } + + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_invers_fvf () const + { + item_array_t t; + t.insert(t.end(), this->invers_fvf.begin(), this->invers_fvf.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_p_deriv_invers_fvf () const + { + item_array_t t; + t.insert(t.end(), this->p_deriv_invers_fvf.begin(), this->p_deriv_invers_fvf.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_gor_deriv_invers_fvf () const + { + return this->gor_deriv_invers_fvf; + } + + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_invers_viscosity () const + { + item_array_t t; + t.insert(t.end(), this->invers_viscosity.begin(), this->invers_viscosity.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_p_deriv_invers_viscosity () const + { + item_array_t t; + t.insert(t.end(), this->p_deriv_invers_viscosity.begin(), this->p_deriv_invers_viscosity.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_gor_deriv_invers_viscosity () const + { + return this->gor_deriv_invers_viscosity; + } + + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_invers_visc_fvf () const + { + item_array_t t; + t.insert(t.end(), this->invers_visc_fvf.begin(), this->invers_visc_fvf.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_p_deriv_invers_visc_fvf () const + { + item_array_t t; + t.insert(t.end(), this->p_deriv_invers_visc_fvf.begin(), this->p_deriv_invers_visc_fvf.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_gor_deriv_invers_visc_fvf () const + { + return this->gor_deriv_invers_visc_fvf; + } + + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_density () const + { + item_array_t t; + t.insert(t.end(), this->density.begin(), this->density.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_p_deriv_density () const + { + item_array_t t; + t.insert(t.end(), this->p_deriv_density.begin(), this->p_deriv_density.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_gor_deriv_density () const + { + return this->gor_deriv_density; + } + + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_porosity () const + { + return this->porosity; + } + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_p_deriv_porosity () const + { + return this->p_deriv_porosity; + } + + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_truns_mult () const + { + return this->truns_mult; + } + + template < class strategy_t > + typename py_calc_model_data::item_t + py_calc_model_data::get_p_deriv_truns_mult () const + { + return this->p_deriv_truns_mult; + } + + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_mobility () const + { + item_array_t t; + t.insert(t.end(), this->mobility.begin(), this->mobility.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_p_deriv_mobility () const + { + item_array_t t; + t.insert(t.end(), this->p_deriv_mobility.begin(), this->p_deriv_mobility.end()); + return t; + } + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_s_deriv_mobility () const + { + item_array_t t; + t.insert(t.end(), this->s_deriv_mobility.begin(), this->s_deriv_mobility.end()); + return t; + } + + + template < class strategy_t > + typename py_calc_model_data::item_array_t + py_calc_model_data::get_prev_fluid_volume () const + { + item_array_t t; + t.insert(t.end(), this->prev_fluid_volume.begin(), this->prev_fluid_volume.end()); + return t; + } + + template < class strategy_t > + py_calc_model::py_calc_model() + : py_objbase(wrapped_t::bs_type()) + {} + + template + py_calc_model::py_calc_model(const sp_cm_t &src) + : py_objbase(src) + { + } + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_saturation () + { + return this->get_spx ()->saturation_3p; + } + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_pressure () + { + return this->get_spx ()->pressure; + } + + /*******************************************************/ + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_plane_flow_rate () + { + return this->get_spx ()->plane_flow_rate; + } + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_full_step_plane_flow_rate () + { + return this->get_spx ()->full_step_plane_flow_rate; + } + + template < class strategy_t > + typename py_calc_model::index_array_t + py_calc_model::get_pvt_regions () + { + return this->get_spx ()->pvt_regions; + } + + template < class strategy_t > + typename py_calc_model::index_array_t + py_calc_model::get_sat_regions () + { + return this->get_spx ()->sat_regions; + } + + template < class strategy_t > + typename py_calc_model::index_array_t + py_calc_model::get_fip_regions () + { + return this->get_spx ()->fip_regions; + } + + template < class strategy_t > + typename py_calc_model::index_array_t + py_calc_model::get_rock_regions () + { + return this->get_spx ()->rock_regions; + } + + template < class strategy_t > + typename py_calc_model::index_array_t + py_calc_model::get_bconn_mainvar () + { + return this->get_spx ()->bconn_mainvar; + } + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_bconn_pressure () + { + return this->get_spx ()->bconn_pressure; + } + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_bconn_saturation () + { + return this->get_spx ()->bconn_saturation; + } + + template < class strategy_t > + typename py_calc_model::item_array_t + py_calc_model::get_bconn_gor () + { + return this->get_spx ()->bconn_gor; + } + + /*******************************************************/ + + template < class strategy_t > + typename py_calc_model::index_t + py_calc_model::get_pvt_num () + { + return this->get_spx ()->n_pvt_regions; + } + + template < class strategy_t > + typename py_calc_model::index_t + py_calc_model::get_sat_num () + { + return this->get_spx ()->n_sat_regions; + } + + template < class strategy_t > + typename py_calc_model::index_t + py_calc_model::get_fip_num () + { + return this->get_spx ()->n_fip_regions; + } + + template + py_scal_3p + py_calc_model::get_scal () const + { + return py_scal_3p (this->get_spx ()->scal_prop); + } + + template + typename py_calc_model::py_calc_model_data_t + py_calc_model::get_data (index_t index) const + { + return py_calc_model_data_t (this->get_spx ()->get_data (index)); + } + + + /*******************************************************/ + + template + typename py_calc_model::index_t + py_calc_model::cmd_num () const + { + return (index_t)this->get_spx ()->data.size (); + } + + template + typename py_calc_model::index_t + py_calc_model::all_data_len () const + { + return 0; + } + + template + typename py_calc_model::index_t + py_calc_model::cap_pressure_len () const + { + return this->get_spx ()->data[0].cap_pressure.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_cap_pressure (index_t i, index_t j) const + { + return this->get_spx ()->data[j].cap_pressure[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::s_deriv_cap_pressure_len () const + { + return this->get_spx ()->data[0].s_deriv_cap_pressure.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_s_deriv_cap_pressure (index_t i, index_t j) const + { + return this->get_spx ()->data[j].s_deriv_cap_pressure[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::relative_perm_len () const + { + return this->get_spx ()->data[0].relative_perm.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_relative_perm (index_t i, index_t j) const + { + return this->get_spx ()->data[j].relative_perm[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::s_deriv_relative_perm_len () const + { + return this->get_spx ()->data[0].s_deriv_relative_perm.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_s_deriv_relative_perm (index_t i, index_t j) const + { + return this->get_spx ()->data[j].s_deriv_relative_perm[i]; + } + + //template + //typename py_calc_model::index_t + //py_calc_model::gas_oil_ratio_len () const { + // return 1; + //} + //template + //typename py_calc_model::item_t + //py_calc_model::get_gas_oil_ratio (index_t i, index_t j) const { + // return this->get_spx ()->gas_oil_ratio[j]; + //} + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_gas_oil_ratio_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_gas_oil_ratio (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_gas_oil_ratio; + } + + template + typename py_calc_model::index_t + py_calc_model::invers_fvf_len () const + { + return this->get_spx ()->data[0].invers_fvf.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_invers_fvf (index_t i, index_t j) const + { + return this->get_spx ()->data[j].invers_fvf[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_invers_fvf_len () const + { + return this->get_spx ()->data[0].p_deriv_invers_fvf.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_invers_fvf (index_t i, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_invers_fvf[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::gor_deriv_invers_fvf_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_gor_deriv_invers_fvf (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].gor_deriv_invers_fvf; + } + + template + typename py_calc_model::index_t + py_calc_model::invers_viscosity_len () const + { + return this->get_spx ()->data[0].invers_viscosity.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_invers_viscosity (index_t i, index_t j) const + { + return this->get_spx ()->data[j].invers_viscosity[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_invers_viscosity_len () const + { + return this->get_spx ()->data[0].p_deriv_invers_viscosity.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_invers_viscosity (index_t i, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_invers_viscosity[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::gor_deriv_invers_viscosity_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_gor_deriv_invers_viscosity (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].gor_deriv_invers_viscosity; + } + + template + typename py_calc_model::index_t + py_calc_model::invers_visc_fvf_len () const + { + return this->get_spx ()->data[0].invers_visc_fvf.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_invers_visc_fvf (index_t i, index_t j) const + { + return this->get_spx ()->data[j].invers_visc_fvf[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_invers_visc_fvf_len () const + { + return this->get_spx ()->data[0].p_deriv_invers_visc_fvf.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_invers_visc_fvf (index_t i, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_invers_visc_fvf[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::gor_deriv_invers_visc_fvf_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_gor_deriv_invers_visc_fvf (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].gor_deriv_invers_visc_fvf; + } + + template + typename py_calc_model::index_t + py_calc_model::density_len () const + { + return this->get_spx ()->data[0].density.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_density (index_t i, index_t j) const + { + return this->get_spx ()->data[j].density[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_density_len () const + { + return this->get_spx ()->data[0].p_deriv_density.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_density (index_t i, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_density[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::gor_deriv_density_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_gor_deriv_density (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].gor_deriv_density; + } + + template + typename py_calc_model::index_t + py_calc_model::porosity_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_porosity (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].porosity; + } + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_porosity_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_porosity (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_porosity; + } + + template + typename py_calc_model::index_t + py_calc_model::truns_mult_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_truns_mult (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].truns_mult; + } + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_truns_mult_len () const + { + return 1; + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_truns_mult (index_t /*i*/, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_truns_mult; + } + + template + typename py_calc_model::index_t + py_calc_model::mobility_len () const + { + return this->get_spx ()->data[0].mobility.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_mobility (index_t i, index_t j) const + { + return this->get_spx ()->data[j].mobility[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::p_deriv_mobility_len () const + { + return this->get_spx ()->data[0].p_deriv_mobility.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_p_deriv_mobility (index_t i, index_t j) const + { + return this->get_spx ()->data[j].p_deriv_mobility[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::s_deriv_mobility_len () const + { + return this->get_spx ()->data[0].s_deriv_mobility.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_s_deriv_mobility (index_t i, index_t j) const + { + return this->get_spx ()->data[j].s_deriv_mobility[i]; + } + + template + typename py_calc_model::index_t + py_calc_model::prev_fluid_volume_len () const + { + return this->get_spx ()->data[0].prev_fluid_volume.size (); + } + template + typename py_calc_model::item_t + py_calc_model::get_prev_fluid_volume (index_t i, index_t j) const + { + return this->get_spx ()->data[j].prev_fluid_volume[i]; + } + + template + void py_calc_model::initialize_datas () + { + int data_size = 3; + this->get_spx () ->data.resize (data_size); + + for (int j = 0; j < data_size; ++j) + { + BOSOUT (section::init_data, level::low) << "cap_pressure len = " << cap_pressure_len () << ", initialization: "; + for (int i = 0; i < cap_pressure_len (); ++i) + { + BOSOUT (section::init_data, level::low) << (item_t)(j+i) << " "; + this->get_spx () ->data[j].cap_pressure[i] = (item_t)(j+i); + } + BOSOUT (section::init_data, level::low) << bs_end; + + BOSOUT (section::init_data, level::low) << "s_deriv_relative_perm len = " << s_deriv_relative_perm_len () << ", initialization: "; + for (int i = 0; i < s_deriv_relative_perm_len (); ++i) + { + BOSOUT (section::init_data, level::low) << (item_t)(j+i) << " "; + this->get_spx () ->data[j].s_deriv_relative_perm[i] = (item_t)(j+i); + } + BOSOUT (section::init_data, level::low) << bs_end; + + BOSOUT (section::init_data, level::low) << "p_deriv_truns_mult len = " << p_deriv_truns_mult_len () << ", initialization: "; + for (int i = 0; i < p_deriv_truns_mult_len (); ++i) + { + BOSOUT (section::init_data, level::low) << (item_t)(j+i) << " "; + this->get_spx () ->data[j].p_deriv_truns_mult = (item_t)(j+i); + } + BOSOUT (section::init_data, level::low) << bs_end; + } + } + + template + py_pvt_water > + py_calc_model ::get_pvt_water (index_t n_pvt_region) const + { + return py_pvt_water > (get_spx (this)->pvt_water_array [n_pvt_region]); + } + template + py_pvt_gas > + py_calc_model ::get_pvt_gas (index_t n_pvt_region) const + { + return py_pvt_gas > (get_spx (this)->pvt_gas_array [n_pvt_region]); + } + template + py_pvt_oil > + py_calc_model ::get_pvt_oil (index_t n_pvt_region) const + { + return py_pvt_oil > (get_spx (this)->pvt_oil_array [n_pvt_region]); + } + + template + int + py_calc_model ::get_n_phases () const + { + return get_spx (this)->n_phases; + } + + template + bool + py_calc_model ::is_water () const + { + return get_spx (this)->is_water (); + } + template + bool + py_calc_model ::is_gas () const + { + return get_spx (this)->is_gas (); + } + template + bool + py_calc_model ::is_oil () const + { + return get_spx (this)->is_oil (); + } + + template + typename py_calc_model ::sp_fi_params_t + py_calc_model ::get_fi_params () const + { + return get_spx (this)->ts_params; + } + + /*********************************************/ + + + + template + void py_export_calc_model_data_t(const char *name) + { + class_< py_calc_model_data >(name) + .def("get_cap_pressure",&py_calc_model_data::get_cap_pressure) + .def("get_s_deriv_cap_pressure",&py_calc_model_data::get_s_deriv_cap_pressure) + + .def("get_relative_perm",&py_calc_model_data::get_relative_perm) + .def("get_s_deriv_relative_perm",&py_calc_model_data::get_s_deriv_relative_perm) + + //.def("get_gas_oil_ratio",&py_calc_model_data::get_gas_oil_ratio) + .def("get_p_deriv_gas_oil_ratio",&py_calc_model_data::get_p_deriv_gas_oil_ratio) + + .def("get_invers_fvf",&py_calc_model_data::get_invers_fvf) + .def("get_p_deriv_invers_fvf",&py_calc_model_data::get_p_deriv_invers_fvf) + .def("get_gor_deriv_invers_fvf",&py_calc_model_data::get_gor_deriv_invers_fvf) + + .def("get_invers_viscosity",&py_calc_model_data::get_invers_viscosity) + .def("get_p_deriv_invers_viscosity",&py_calc_model_data::get_p_deriv_invers_viscosity) + .def("get_gor_deriv_invers_viscosity",&py_calc_model_data::get_gor_deriv_invers_viscosity) + + .def("get_invers_visc_fvf",&py_calc_model_data::get_invers_visc_fvf) + .def("get_p_deriv_invers_visc_fvf",&py_calc_model_data::get_p_deriv_invers_visc_fvf) + .def("get_gor_deriv_invers_visc_fvf",&py_calc_model_data::get_gor_deriv_invers_visc_fvf) + + .def("get_density",&py_calc_model_data::get_density) + .def("get_p_deriv_density",&py_calc_model_data::get_p_deriv_density) + .def("get_gor_deriv_density",&py_calc_model_data::get_gor_deriv_density) + + .def("get_porosity",&py_calc_model_data::get_porosity) + .def("get_p_deriv_porosity",&py_calc_model_data::get_p_deriv_porosity) + + .def("get_truns_mult",&py_calc_model_data::get_truns_mult) + .def("get_p_deriv_truns_mult",&py_calc_model_data::get_p_deriv_truns_mult) + + .def("get_mobility",&py_calc_model_data::get_mobility) + .def("get_p_deriv_mobility",&py_calc_model_data::get_p_deriv_mobility) + .def("get_s_deriv_mobility",&py_calc_model_data::get_s_deriv_mobility) + + .def("get_prev_fluid_volume",&py_calc_model_data::get_prev_fluid_volume) + ; + } + + template + void py_export_calc_model_t(const char *name) + { + typedef py_calc_model py_calc_model_t; + + class_, bases >(name) + .def("get_saturation",&py_calc_model::get_saturation) + .def("get_pressure",&py_calc_model::get_pressure) + .def("get_pvt_num",&py_calc_model::get_pvt_num) + .def("get_sat_num",&py_calc_model::get_sat_num) + .def("get_fip_num",&py_calc_model::get_fip_num) + .def("get_scal", &py_calc_model::get_scal) + .add_property ("scal", make_function (&py_calc_model ::get_scal)) + .def("get_plane_flow_rate",&py_calc_model::get_plane_flow_rate) + .def("get_full_step_plane_flow_rate",&py_calc_model::get_full_step_plane_flow_rate) + .def("get_pvt_regions",&py_calc_model::get_pvt_regions) + .def("get_sat_regions",&py_calc_model::get_sat_regions) + .def("get_fip_regions",&py_calc_model::get_fip_regions) + .def("get_rock_regions",&py_calc_model::get_rock_regions) + .def("get_bconn_mainvar",&py_calc_model::get_bconn_mainvar) + .def("get_bconn_pressure",&py_calc_model::get_bconn_pressure) + .def("get_bconn_saturation",&py_calc_model::get_bconn_saturation) + .def("get_bconn_gor",&py_calc_model::get_bconn_gor) + .def("get_data",&py_calc_model::get_data) + + .def("cmd_num",&py_calc_model::cmd_num) + .def("all_data_len",&py_calc_model::all_data_len) + + .def("cap_pressure_len",&py_calc_model::cap_pressure_len) + .def("get_cap_pressure",&py_calc_model::get_cap_pressure) + + .def("s_deriv_cap_pressure_len",&py_calc_model::s_deriv_cap_pressure_len) + .def("get_s_deriv_cap_pressure",&py_calc_model::get_s_deriv_cap_pressure) + + .def("relative_perm_len",&py_calc_model::relative_perm_len) + .def("get_relative_perm",&py_calc_model::get_relative_perm) + + .def("s_deriv_relative_perm_len",&py_calc_model::s_deriv_relative_perm_len) + .def("get_s_deriv_relative_perm",&py_calc_model::get_s_deriv_relative_perm) + + //.def("gas_oil_ratio_len",&py_calc_model::gas_oil_ratio_len) + .def("get_gas_oil_ratio",&py_calc_model::get_gas_oil_ratio) + + .def("p_deriv_gas_oil_ratio_len",&py_calc_model::p_deriv_gas_oil_ratio_len) + .def("get_p_deriv_gas_oil_ratio",&py_calc_model::get_p_deriv_gas_oil_ratio) + + .def("invers_fvf_len",&py_calc_model::invers_fvf_len) + .def("get_invers_fvf",&py_calc_model::get_invers_fvf) + + .def("p_deriv_invers_fvf_len",&py_calc_model::p_deriv_invers_fvf_len) + .def("get_p_deriv_invers_fvf",&py_calc_model::get_p_deriv_invers_fvf) + + .def("gor_deriv_invers_fvf_len",&py_calc_model::gor_deriv_invers_fvf_len) + .def("get_gor_deriv_invers_fvf",&py_calc_model::get_gor_deriv_invers_fvf) + + .def("invers_viscosity_len",&py_calc_model::invers_viscosity_len) + .def("get_invers_viscosity",&py_calc_model::get_invers_viscosity) + + .def("p_deriv_invers_viscosity_len",&py_calc_model::p_deriv_invers_viscosity_len) + .def("get_p_deriv_invers_viscosity",&py_calc_model::get_p_deriv_invers_viscosity) + + .def("gor_deriv_invers_viscosity_len",&py_calc_model::gor_deriv_invers_viscosity_len) + .def("get_gor_deriv_invers_viscosity",&py_calc_model::get_gor_deriv_invers_viscosity) + + .def("invers_visc_fvf_len",&py_calc_model::invers_visc_fvf_len) + .def("get_invers_visc_fvf",&py_calc_model::get_invers_visc_fvf) + + .def("p_deriv_invers_visc_fvf_len",&py_calc_model::p_deriv_invers_visc_fvf_len) + .def("get_p_deriv_invers_visc_fvf",&py_calc_model::get_p_deriv_invers_visc_fvf) + + .def("gor_deriv_invers_visc_fvf_len",&py_calc_model::gor_deriv_invers_visc_fvf_len) + .def("get_gor_deriv_invers_visc_fvf",&py_calc_model::get_gor_deriv_invers_visc_fvf) + + .def("density_len",&py_calc_model::density_len) + .def("get_density",&py_calc_model::get_density) + + .def("p_deriv_density_len",&py_calc_model::p_deriv_density_len) + .def("get_p_deriv_density",&py_calc_model::get_p_deriv_density) + + .def("gor_deriv_density_len",&py_calc_model::gor_deriv_density_len) + .def("get_gor_deriv_density",&py_calc_model::get_gor_deriv_density) + + .def("porosity_len",&py_calc_model::porosity_len) + .def("get_porosity",&py_calc_model::get_porosity) + + .def("p_deriv_porosity_len",&py_calc_model::p_deriv_porosity_len) + .def("get_p_deriv_porosity",&py_calc_model::get_p_deriv_porosity) + + .def("truns_mult_len",&py_calc_model::truns_mult_len) + .def("get_truns_mult",&py_calc_model::get_truns_mult) + + .def("p_deriv_truns_mult_len",&py_calc_model::p_deriv_truns_mult_len) + .def("get_p_deriv_truns_mult",&py_calc_model::get_p_deriv_truns_mult) + + .def("mobility_len",&py_calc_model::mobility_len) + .def("get_mobility",&py_calc_model::get_mobility) + + .def("p_deriv_mobility_len",&py_calc_model::p_deriv_mobility_len) + .def("get_p_deriv_mobility",&py_calc_model::get_p_deriv_mobility) + + .def("s_deriv_mobility_len",&py_calc_model::s_deriv_mobility_len) + .def("get_s_deriv_mobility",&py_calc_model::get_s_deriv_mobility) + + .def("prev_fluid_volume_len",&py_calc_model::prev_fluid_volume_len) + .def("get_prev_fluid_volume",&py_calc_model::get_prev_fluid_volume) + .def("initialize_datas",&py_calc_model::initialize_datas) + + .def ("get_pvt_water", &py_calc_model_t::get_pvt_water) + .def ("get_pvt_gas", &py_calc_model_t::get_pvt_gas) + .def ("get_pvt_oil", &py_calc_model_t::get_pvt_oil) + + .add_property ("n_phases", &py_calc_model_t::get_n_phases) + .add_property ("is_water", &py_calc_model_t::is_water) + .add_property ("is_gas", &py_calc_model_t::is_gas) + .add_property ("is_oil", &py_calc_model_t::is_oil) + .add_property ("params", &py_calc_model_t::get_fi_params) + ; + } + + template int get_n_phases (T *t) { return t->n_phases; } + template bool get_is_water (T *t) { return t->is_water (); } + template bool get_is_gas (T *t) { return t->is_gas (); } + template bool get_is_oil (T *t) { return t->is_oil (); } + + template + smart_ptr + get_params (T *t) + { + return t->ts_params; + } + + PY_EXPORTER (calc_model_exporter, default_exporter) + .add_property ("n_phases", get_n_phases ) + .add_property ("is_water", get_is_water ) + .add_property ("is_gas", get_is_gas ) + .add_property ("is_oil", get_is_oil ) + .add_property ("params", get_params ) + PY_EXPORTER_END; + + void py_export_calc_model() + { + py_export_calc_model_data_t("calc_model_data_d"); + py_export_calc_model_data_t("calc_model_data_f"); + py_export_calc_model_data_t("calc_model_data_m"); + + strategy_exporter::export_base ("calc_model"); + //py_export_calc_model_t("calc_model_d"); + //py_export_calc_model_t("calc_model_f"); + //py_export_calc_model_t("calc_model_m"); + } + + template class py_calc_model; + template class py_calc_model; + template class py_calc_model; + } //ns python +} //ns bs + diff --git a/bs_bos_core/src/py_calc_well.cpp b/bs_bos_core/src/py_calc_well.cpp new file mode 100644 index 0000000..72fb716 --- /dev/null +++ b/bs_bos_core/src/py_calc_well.cpp @@ -0,0 +1,157 @@ +/** + * \file py_calc_well.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 23.06.2008 + * */ +#include "stdafx.h" + +#ifdef BSPY_EXPORTING_PLUGIN + +#include "py_calc_well.h" +#include "reservoir.h" +#include "facility_manager.h" + +namespace blue_sky { +namespace python { + + ////////////////////////////////////////////////////////////////////////// + //template + //py_well_iterator::py_well_iterator(const this_t &src) + // : mgr(src.mgr), ins(src.ins) //,endi(src.endi) + //{ + //} + + //template + //py_well_iterator::py_well_iterator(const sp_facility_t &mgr) //const well_iterator_t &src, get_end fn) + // : mgr(mgr), ins(mgr->wells_begin ()) //ins(src),endi(fn) + //{ + //} + + //template + //py_well_iterator::~py_well_iterator() {} + + //template + //typename py_well_iterator::reference + //py_well_iterator::operator*() const + // { + // if (ins != mgr->wells_end ()) + // { + // py_well_t w(sp_well_t (ins->second, bs_dynamic_cast ())); + // return w; + // } + // return py_well_t(NULL); + // } + + //template + //typename py_well_iterator::pointer + //py_well_iterator::operator->() const + // { + // if (ins != mgr->wells_end ()) + // { + // py_well_t w(sp_well_t (ins->second, bs_dynamic_cast ())); + // return w; + // } + // return py_well_t(NULL); + // } + + //template + //typename py_well_iterator::this_t& + //py_well_iterator::operator++() + //{ + // ++ins; + // return *this; + //} + + //template + //typename py_well_iterator::this_t + //py_well_iterator::operator++(int) + //{ + // py_well_iterator tmp(*this); + // ++ins; + // return tmp; + //} + + //template + //typename py_well_iterator::py_well_t + //py_well_iterator::next() + //{ + // if (ins == mgr->wells_end ()) + // { + // PyErr_SetString(PyExc_StopIteration, "No more data."); + // boost::python::throw_error_already_set(); + // } + + // py_well_iterator tmp(*this); + + // (*this)++; + + // return *tmp; + //} + + //template + //bool + //py_well_iterator::operator ==(const this_t &ritr) const + // { + // return (ins == ritr.ins); + // } + + //template + //bool + //py_well_iterator::operator !=(const this_t &ritr) const + // { + // return (!(ins == ritr.ins)); + // } + + //template + //const typename py_well_iterator::this_t& + //py_well_iterator::operator =(const this_t &ritr) + //{ + // ins = ritr.ins; + // mgr = ritr.mgr; + // return *this; + //} + + /*********************************************************************/ + template + void py_export_well_iterator (const char *name) + { + using namespace boost::python; + + class_ ::well_const_iterator_t> (name, no_init) + .def ("__iter__",pass_through) + //.def ("next", &py_well_iterator ::next) + ; + } + + void + py_export_calc_well () + { + strategy_exporter::export_base ("well_seq"); + strategy_exporter::export_base ("connection_seq"); + + strategy_exporter::export_class ("py_well_seq"); + strategy_exporter::export_class ("py_connection_seq"); + + //using namespace boost::python; + //class_ < py_well_storage::py_well_list_t> ("vector_well_seq_fi") + // .def (vector_indexing_suite < py_well_storage::py_well_list_t> ()) + // ; + //using namespace boost::python; + //class_ < py_well_storage::py_well_list_t> ("vector_well_seq_di") + // .def (vector_indexing_suite < py_well_storage::py_well_list_t> ()) + // ; + + py_export_well_iterator ("well_iterator_f"); + py_export_well_iterator ("well_iterator_d"); + py_export_well_iterator ("well_iterator_m"); + } + + //template class py_well_iterator ; + //template class py_well_iterator ; + //template class py_well_iterator ; + +#endif // #ifdef BSPY_EXPORTING_PLUGIN +} // namespace python +} // namespace blue_sky + diff --git a/bs_bos_core/src/py_csr_ilu_cfl_prec.cpp b/bs_bos_core/src/py_csr_ilu_cfl_prec.cpp new file mode 100644 index 0000000..de6ea9d --- /dev/null +++ b/bs_bos_core/src/py_csr_ilu_cfl_prec.cpp @@ -0,0 +1,31 @@ +/** + * \file py_csr_ilu_cfl_prec.cpp + * \brief Python wrappers for csr_ilu_cfl_prec + * \author Salimgareeva Elmira + * \date 28.09.2009 + */ +#include "stdafx.h" +#include "py_csr_ilu_cfl_prec.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "py_linear_solvers.h" +#include BS_STOP_PLUGIN_IMPORT () + +#ifdef BSPY_EXPORTING_PLUGIN + +namespace blue_sky { +namespace python { + + + //! export wrappers to python + void + py_export_csr_ilu_cfl_prec () + { + strategy_exporter::export_class ("csr_ilu_cfl_prec_seq"); + } + +} // namespace python +} // namespace blue_sky + +#endif // #ifdef BSPY_EXPORTING_PLUGIN + diff --git a/bs_bos_core/src/py_data_storage_interface.cpp b/bs_bos_core/src/py_data_storage_interface.cpp new file mode 100644 index 0000000..4d8c775 --- /dev/null +++ b/bs_bos_core/src/py_data_storage_interface.cpp @@ -0,0 +1,144 @@ +/** + * \file py_data_storage_interface.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 23.07.2008 + * */ +#include "stdafx.h" + +#include "py_data_storage_interface.h" + +namespace blue_sky + { + namespace python + { + + ////////////////////////////////////////////////////////////////////////// + struct BS_API_PLUGIN data_storage_proxy : public data_storage + { + typedef py_data_storage py_impl_t; + typedef smart_ptr sp_impl_t; + typedef data_storage ds_t; + + BLUE_SKY_TYPE_DECL (data_storage_proxy); + + virtual ~data_storage_proxy () {} + + ds_t &save (const std::string &name, const std::string &value); + void set_impl (const sp_impl_t &impl); + +private: + + sp_impl_t impl_; + }; + + data_storage_proxy::data_storage_proxy (bs_type_ctor_param /*param = NULL */) + { + + } + data_storage_proxy::data_storage_proxy (const data_storage_proxy &p) + : bs_refcounter (p), data_storage (p), impl_ (p.impl_) + { + + } + data_storage & + data_storage_proxy::save (const std::string &name, const std::string &value) + { + BS_ASSERT (impl_) (name) (value); + + impl_->save (name, value); + return *this; + } + void + data_storage_proxy::set_impl (const sp_impl_t &impl) + { + impl_ = impl; + } + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + py_data_storage::py_data_storage (PyObject *self) + : base_t (data_storage_proxy::bs_type ()) + , self_ (self) + { + Py_INCREF (self_); + get_spx ()->set_impl (this); + } + + py_data_storage::~py_data_storage () + { + Py_DECREF (self_); + } + + void + py_data_storage::save (const std::string &name, const std::string &value) + { + using namespace boost::python; + call_method (self_, "save", name, value); + } + + void + py_data_storage::save_default (const std::string &/*name*/, const std::string &/*value*/) + { + BS_ASSERT (false && "PURE CALL"); + } + + void + py_data_serializer::save (const sp_storage_t &/*storage*/, const sp_obj &/*obj*/) + { + //Sergey Miryanov: + // today (23.07.2008) we haven't any way to convert sp_obj + // to corresponding python wrapper + // in future - if we build table between such types we can + // convert python wrappers to objects and vice versa + } + + //void + //py_data_storage_interface::register_serializer (py_data_serializer serializer) + //{ + // get_lspx (this)->register_serializer (serializer.get_spx ()); + //} + void + py_data_storage_interface::set_storage (const py_data_storage &storage) + { + get_spx (this)->set_storage (storage.get_spx ()); + } + void + py_data_storage_interface::save (const py_objbase &obj) + { + get_spx (this)->save (obj.get_sp ()); + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE (data_storage_proxy); + BLUE_SKY_TYPE_STD_COPY (data_storage_proxy); + BLUE_SKY_TYPE_IMPL (data_storage_proxy, data_storage, "py_data_storage::data_storage_proxy", "py_data_storage::data_storage_proxy", "py_data_storage::data_storage_proxy"); + + bool + data_storage_proxy_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + res &= BS_KERNEL.register_type (pd, data_storage_proxy::bs_type ()); + BS_ASSERT (res); + + return res; + } + + ////////////////////////////////////////////////////////////////////////// + void + py_export_data_storage_interface () + { + using namespace boost::python; + + class_ , py_data_storage, boost::noncopyable> ("data_storage"/*, init ()*/) + .def ("save", &py_data_storage::save_default) + ; + + class_ > ("ds_interface") + .def ("set_storage", &py_data_storage_interface::set_storage) + .def ("save", &py_data_storage_interface::save) + ; + } + + } // namespace python +} // namespace blue_sky diff --git a/bs_bos_core/src/py_default_wells.cpp b/bs_bos_core/src/py_default_wells.cpp new file mode 100644 index 0000000..2f872c3 --- /dev/null +++ b/bs_bos_core/src/py_default_wells.cpp @@ -0,0 +1,28 @@ +/** + * \file py_default_wells.cpp + * \brief + * \author Sergey Miryanov + * \date 22.05.2009 + * */ +#include "stdafx.h" +#include "py_default_wells.h" +#include "export_python_wrapper.h" +#include "default_well.h" +#include "default_connection.h" +#include "py_calc_well.h" + +using namespace blue_sky::wells; + +namespace blue_sky { +namespace python { + + void + py_export_default_wells () + { + strategy_exporter::export_class ("default_well"); + strategy_exporter::export_class ("default_connection"); + } + +} // namespace python +} // namespace blue_sky + diff --git a/bs_bos_core/src/py_event_base.cpp b/bs_bos_core/src/py_event_base.cpp new file mode 100644 index 0000000..9584340 --- /dev/null +++ b/bs_bos_core/src/py_event_base.cpp @@ -0,0 +1,312 @@ +#include "stdafx.h" + +#include "calc_model.h" +#include "reservoir.h" + +#include "py_event_base.h" + +//#include "py_reservoir.h" +//#include "py_calc_model.h" + +//#include "facility_manager.h" +//#include "calc_model_types.h" +//#include "well_connection.h" + +//#include BS_FORCE_PLUGIN_IMPORT () +//#include "py_rs_mesh.h" +//#include BS_STOP_PLUGIN_IMPORT () + +using namespace boost::python; + +namespace blue_sky + { + namespace python + { + + template + py_event_base_iterator::py_event_base_iterator (const elist_t &events1) + { + events.resize (0); + events.assign (events1.begin (), events1.end ()); + iter = events.begin (); + } + + template + py_event_base_iterator::py_event_base_iterator (const this_t &iter1) +// : events (iter.events) +// , iter (iter.iter) + { + events.resize (0); + events.assign (iter1.events.begin (), iter1.events.end ()); + for (const_iterator_t i = events.begin (); i != events.end (); ++i) + if (*iter1.iter == *i) + { + iter = i; + break; + } + } + + template + typename py_event_base_iterator::py_event_base_t * + py_event_base_iterator::next () + { + if (!events.size () || iter == events.end ()) + { + PyErr_SetString(PyExc_StopIteration, "No more data."); + boost::python::throw_error_already_set(); + } + + py_event_base_t *tmp = new py_event_base_t (**this); + + (*this)++; + + return tmp; + } + + template + typename py_event_base_iterator::reference + py_event_base_iterator::operator*() const + { + if (iter == events.end () || !events.size ()) + { + BOSWARN (section::schedule, level::debug) << "end of the list" << bs_end; + return py_event_base_t (NULL); + } + return py_event_base_t (*iter); + } + + template + typename py_event_base_iterator::this_t& + py_event_base_iterator::operator++() + { + ++iter; + return *this; + } + + template + typename py_event_base_iterator::this_t + py_event_base_iterator::operator++(int) + { + this_t tmp (*this); + ++iter; + return tmp; + } + + template + typename py_event_base_iterator::this_t& + py_event_base_iterator::operator--() + { + --iter; + return *this; + } + + template + typename py_event_base_iterator::this_t + py_event_base_iterator::operator--(int) + { + this_t tmp (*this); + --iter; + return tmp; + } + + template + bool + py_event_base_iterator::operator ==(const this_t &ritr) const + { + return (iter == ritr.iter); + } + + template + bool + py_event_base_iterator::operator !=(const this_t &ritr) const + { + return (iter != ritr.iter); + } + + template + const typename py_event_base_iterator::this_t& + py_event_base_iterator::operator =(const this_t &ritr) + { + events = ritr.events; + iter = ritr.iter; + return *this; + } + + template + py_el_pair::py_el_pair () + {} + + template + py_el_pair::py_el_pair (const const_iterator_t &iter) + : first (iter->first) + , second (iter->second) + {} + + template + py_el_pair::py_el_pair (const this_t &iter) + : first (iter.first) + , second (iter.second) + {} + + template + typename py_el_pair::py_event_base_iterator_t + py_el_pair::list_begin () + { + return py_event_base_iterator_t (second); + } + + + template + event_list_iterator ::event_list_iterator (const sp_event_manager_t &evm) //iterator_t &iter) + : evm (evm) + , iter (evm->event_list.begin ()) + //, pair_ (iter) + { + } + + template + event_list_iterator ::event_list_iterator (const this_t &iter1) + : evm (iter1.evm) + , iter (iter1.iter) + //, pair_ (iter.iter) + { + /*for (const_iterator_t i = evm->event_list.begin (); i != evm->event_list.end (); ++i) + if (*i == *(iter1.iter)) { + iter = const_iterator_t (i); + break; + }*/ + } + + template + typename event_list_iterator ::reference + event_list_iterator ::operator*() const + { + py_el_pair_t elp(iter); + return elp; + } + + template + typename event_list_iterator ::this_t & + event_list_iterator ::operator++() + { + ++iter; + return *this; + } + + template + typename event_list_iterator ::this_t + event_list_iterator ::operator++(int) + { + this_t tmp (*this); + ++iter; + return tmp; + } + + template + typename event_list_iterator ::py_el_pair_t + event_list_iterator ::next () + { + if (iter == evm->event_list.end ()) + { + BOSWARN (section::schedule, level::debug) << "Stop map" << bs_end; + PyErr_SetString(PyExc_StopIteration, "No more data."); + boost::python::throw_error_already_set(); + } + + py_el_pair_t tmp(iter); + + (*this)++; + //++iter; + + return tmp; + + } + + template + typename event_list_iterator ::this_t & + event_list_iterator ::operator--() + { + --iter; + return *this; + } + + template + typename event_list_iterator ::this_t + event_list_iterator ::operator--(int) + { + this_t tmp (*this); + --iter; + return *this; + } + + template + bool + event_list_iterator ::operator ==(const this_t &ritr) const + { + return (iter == ritr.iter); + } + + template + bool + event_list_iterator ::operator !=(const this_t &ritr) const + { + return (iter != ritr.iter); + } + + template + const typename event_list_iterator ::this_t & + event_list_iterator ::operator =(const this_t &ritr) + { + iter = ritr.iter; + evm = ritr.evm; + return *this; + } + + + template + void export_py_event_base (const char *name) + { + class_< py_el_pair > (std::string (std::string (name) + "_pair").c_str (), init <> ()) + .def ("list_begin", &py_el_pair::list_begin) + ; + + class_< event_list_iterator > (std::string (std::string (name) + "_iterator").c_str (), no_init) + .def ("__iter__",pass_through) + .def ("next", &event_list_iterator ::next) + ; + + class_< py_event_base_iterator > (std::string (std::string (name) + "_iterator2").c_str (), no_init) + .def ("__iter__",pass_through) + .def ("next", &py_event_base_iterator ::next, return_value_policy ()) + ; + } + + //PYTHON_EXPORT_WRAPPER (py_export_event_base, event_base, py_event_base, 1, (apply)); + + PY_EXPORTER (event_base_exporter, default_exporter) + .def ("apply", &T::apply) + PY_EXPORTER_END; + + void py_export_events () + { + strategy_exporter::export_class ("event_base"); + + export_py_event_base ("event_base_f"); + export_py_event_base ("event_base_d"); + export_py_event_base ("event_base_m"); + } + + template class py_el_pair ; + template class py_el_pair ; + template class py_el_pair ; + + template class event_list_iterator ; + template class event_list_iterator ; + template class event_list_iterator ; + + template class py_event_base_iterator ; + template class py_event_base_iterator ; + template class py_event_base_iterator ; + +} // namespace python +} // namespace blue_sky diff --git a/bs_bos_core/src/py_event_manager.cpp b/bs_bos_core/src/py_event_manager.cpp new file mode 100644 index 0000000..631ac34 --- /dev/null +++ b/bs_bos_core/src/py_event_manager.cpp @@ -0,0 +1,98 @@ +#include "stdafx.h" + +#include "event_manager.h" +#include "py_event_manager.h" + +#include "reservoir.h" +#include "facility_manager.h" +#include "well_connection.h" +#include "calc_model.h" + +using namespace boost; +using namespace boost::posix_time; + +namespace blue_sky { +namespace python { + + template + py_event_manager::~py_event_manager () + { + + } + + template + py_event_manager::py_event_manager() + : py_objbase(wrapped_t::bs_type()) + { + } + + template + py_event_manager::py_event_manager (const sp_em_t &src) + : py_objbase (src) + { + } + + template + py_event_manager::py_event_manager(const this_t &src) + : py_objbase (src.get_spx ()) + {} + + template + typename py_event_manager::py_event_base_t * + py_event_manager::create_event (const std::string &date, const std::string &event_name, const std::string &event_params) + { + return new py_event_base_t (this->template get_spx ()->create_event (boost::posix_time::ptime (time_from_string (date)), event_name, event_params)); + } + + template + void py_event_manager::factory_register(const std::string &/*name*/, const event_creater_base_t &/*creater*/) + { + BS_ASSERT (false && "NOT_IMPL_YET"); + } + + template + event_creater_base::event_creater_base (boost::python::object &pobj) + : obj (pobj) + {} + + template + typename py_event_manager::event_list_iterator_t + py_event_manager::el_begin () + { + return event_list_iterator_t (this->get_spx ()); + } + + //event_list_iterator_t el_end (); + + template + typename event_creater_base::py_event_base_t * + event_creater_base::create () + { + // CALL PYTHON IMPL (pure virtual) + } + + + template + void py_export_event_manager_ (const char *name) + { + using namespace boost::python; + class_, bases >(name) + .def ("create_event", &py_event_manager ::create_event, return_value_policy ()) + .def ("el_begin", &py_event_manager ::el_begin) + ; + } + + void + py_export_event_manager () + { + py_export_event_manager_ ("event_manager_seq_fi"); + py_export_event_manager_ ("event_manager_seq_di"); + py_export_event_manager_ ("event_manager_seq_mixi"); + } + + template class py_event_manager ; + template class py_event_manager ; + template class py_event_manager ; +} // namespace python +} // namespace blue_sky + diff --git a/bs_bos_core/src/py_facility_manager.cpp b/bs_bos_core/src/py_facility_manager.cpp new file mode 100644 index 0000000..3f63f65 --- /dev/null +++ b/bs_bos_core/src/py_facility_manager.cpp @@ -0,0 +1,40 @@ +#include "stdafx.h" + +#include "py_facility_manager.h" +#include "reservoir.h" +#include "facility_manager.h" + +#include "export_python_wrapper.h" + +using namespace boost::python; + +namespace blue_sky { +namespace python { + + //template + //void py_export_facility_manager_t(const char *name) + //{ + // class_, bases >(name) + // //.def("__iter__", range(&py_facility_manager::wells_begin, + // // &py_facility_manager::wells_end)) + // .def("add_well", &py_facility_manager::add_well) + // .def("wells", &py_facility_manager::wells_begin) + // .def("wells_end", &py_facility_manager::wells_end) + // //.def("__iter__", pass_throught) // boost::python::iterator< py_facility_manager >()) + // //.def("next", &py_facility_manager::next) + // ; + //} + + PY_EXPORTER (facility_manager_exporter, default_exporter) + .def ("add_well", &T::add_well) + .def ("wells", &T::wells_begin) + .def ("wells_end", &T::wells_end) + PY_EXPORTER_END; + + void py_export_facility_manager() + { + strategy_exporter::export_base ("facility_manager"); + } + +} // namespace python +} // namespace blue_sky diff --git a/bs_bos_core/src/py_jacobian.cpp b/bs_bos_core/src/py_jacobian.cpp new file mode 100644 index 0000000..5484492 --- /dev/null +++ b/bs_bos_core/src/py_jacobian.cpp @@ -0,0 +1,46 @@ +/** + * \file py_jacobian.cpp + * \brief + * \author Sergey Miryanov + * \date 12.05.2009 + * */ +#include "stdafx.h" +#include "py_jacobian.h" +#include "jacobian.h" + +#include "construct_python_object.h" + +namespace blue_sky { +namespace python { + + template + void + export_jacobian (const char *name) + { + using namespace boost::python; + + class_ (name, no_init) + .def ("__cons__", make_constructor (construct_python_object )) + .def ("__init__", make_function (init_python_object )) + .add_property ("solver", make_function (&jacobian_t::get_solver, return_value_policy ()), make_function (&jacobian_t::set_solver)) + .add_property ("prec", make_function (&jacobian_t::get_prec, return_value_policy ()), make_function (&jacobian_t::set_prec)) + .add_property ("jmx", make_function (&jacobian_t::get_jmatrix, return_value_policy ()), make_function (&jacobian_t::set_jmatrix)) + ; + } + + void + py_export_jacobian () + { + export_jacobian > ("jacobian_fi"); + export_jacobian > ("jacobian_di"); + export_jacobian > ("jacobian_mixi"); + + boost::python::register_ptr_to_python , true> > (); + boost::python::register_ptr_to_python , true> > (); + boost::python::register_ptr_to_python , true> > (); + } + + +} // namespace python +} // namespace blue_sky + diff --git a/bs_bos_core/src/py_keyword_manager.cpp b/bs_bos_core/src/py_keyword_manager.cpp new file mode 100644 index 0000000..aa1d6e4 --- /dev/null +++ b/bs_bos_core/src/py_keyword_manager.cpp @@ -0,0 +1,144 @@ +/** + * \file py_keyword_manager.cpp + * \brief + * \author Sergey Miryanov + * \date 28.10.2009 + * */ +#include "stdafx.h" +#include "py_keyword_manager.h" +#include "keyword_manager.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "read_class.h" +#include "data_class.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include "export_python_wrapper.h" + +namespace blue_sky { +namespace python { + + template + struct py_keyword_handler_iface_base : keyword_handler_iface + { + typedef keyword_params keyword_params_t; + + void + handler (const std::string &, keyword_params_t &) + { + bs_throw_exception ("PURE CALL FROM PYTHON"); + } + }; + template + struct py_keyword_handler_iface : py_keyword_handler_iface_base , boost::python::wrapper > + { + typedef keyword_params keyword_params_t; + + py_keyword_handler_iface () + { + } + py_keyword_handler_iface (const py_keyword_handler_iface_base &) + { + } + + WRAP_PURE_METHOD (handler, void, 2, (const std::string &, keyword_params_t &)); + }; + + template + void + register_keyword (T *t, const std::string &keyword, const typename T::shared_handler_t &handler) + { + t->register_keyword (keyword, handler); + } + + template + smart_ptr + get_reader (T *t) + { + typedef smart_ptr sp_reader_t; + sp_reader_t reader (t->reader, bs_dynamic_cast ()); + + if (!reader) + { + bs_throw_exception (boost::format ("Can't cast params->reader to sp_reader_t (%s)") % t->reader->bs_resolve_type ().stype_); + } + + return reader; + } + + template + smart_ptr + get_data (T *t) + { + typedef smart_ptr sp_idata_t; + sp_idata_t data (t->data, bs_dynamic_cast ()); + + if (!data) + { + bs_throw_exception (boost::format ("Can't cast params->data to sp_idata_t (%s)") % t->data->bs_resolve_type ().stype_); + } + + return data; + } + + template + smart_ptr , true> + get_mesh (T *t) + { + typedef smart_ptr , true> sp_mesh_t; + sp_mesh_t mesh (t->mesh, bs_dynamic_cast ()); + + if (!mesh) + { + bs_throw_exception (boost::format ("Can't cast params->mesh to sp_mesh_t (%s)") % t->mesh->bs_resolve_type ().stype_); + } + + return mesh; + } + + template + smart_ptr , true> + get_keyword_manager (T *t) + { + typedef smart_ptr , true> sp_keyword_manager_t; + sp_keyword_manager_t km (t->km, bs_dynamic_cast ()); + + if (!km) + { + bs_throw_exception (boost::format ("Can't cast params->km to sp_keyword_manager_t (%s)") % t->km->bs_resolve_type ().stype_); + } + + return km; + } + + PY_EXPORTER (keyword_manager_exporter, default_exporter) + .def ("register_keyword", register_keyword ) + .def ("is_keyword_supported", &T::is_keyword_supported) + .def ("is_keyword_activated", &T::is_keyword_activated) + PY_EXPORTER_END; + + PY_EXPORTER (keyword_params_exporter, empty_exporter) + .add_property ("reader", make_function (get_reader )) + .add_property ("data", make_function (get_data )) + .add_property ("mesh", make_function (get_mesh )) + .add_property ("keyword_manager", make_function (get_keyword_manager )) + PY_EXPORTER_END; + + PY_EXPORTER (keyword_handler_iface_exporter, empty_exporter) + .def ("handler", &T::handler) + PY_EXPORTER_END; + + void + export_keyword_manager () + { + using namespace boost::python; + + strategy_exporter::export_base_ext ("keyword_params"); + strategy_exporter::export_base_ext ("keyword_handler_iface"); + strategy_exporter::export_class_ext ("py_keyword_handler_iface"); + strategy_exporter::export_base ("keyword_manager"); + } + +} // namespace python +} // namespace blue_sky + diff --git a/bs_bos_core/src/py_reservoir.cpp b/bs_bos_core/src/py_reservoir.cpp new file mode 100644 index 0000000..76165ec --- /dev/null +++ b/bs_bos_core/src/py_reservoir.cpp @@ -0,0 +1,27 @@ +#include "stdafx.h" + +#include "py_reservoir.h" +#include "reservoir.h" +#include "well_connection.h" +#include "py_facility_manager.h" + +using namespace boost::python; + +namespace blue_sky { +namespace python { + + PY_EXPORTER (reservoir_exporter, default_exporter) + .def ("add_filter_well", &T::add_filter_well) + .add_property ("facility_list", &T::get_facility_list) + .add_property ("well_factory", make_function (&T::get_well_factory), make_function (&T::set_well_factory)) + .add_property ("well_controller_factory", make_function (&T::get_well_controller_factory), make_function (&T::set_well_controller_factory)) + .add_property ("well_limit_operation_factory", make_function (&T::get_well_limit_operation_factory), make_function (&T::set_well_limit_operation_factory)) + PY_EXPORTER_END; + + void py_export_reservoir() + { + strategy_exporter::export_base ("reservoir"); + } + +} // namespace python +} // namespace blue_sky diff --git a/bs_bos_core/src/py_reservoir_simulator.cpp b/bs_bos_core/src/py_reservoir_simulator.cpp new file mode 100644 index 0000000..d0cfcdd --- /dev/null +++ b/bs_bos_core/src/py_reservoir_simulator.cpp @@ -0,0 +1,73 @@ +#include "stdafx.h" + +#include "py_reservoir_simulator.h" +#include "reservoir_simulator.h" + +#include "calc_model.h" +#include "jacobian.h" +#include "reservoir.h" +#include "facility_manager.h" +#include "data_storage_interface.h" + +#include "py_reservoir.h" +#include "py_facility_manager.h" +#include "keyword_manager.h" +#include "well_connection.h" + +#include "export_python_wrapper.h" +#include + +using namespace boost::python; + +namespace blue_sky { +namespace python { + + template + typename T::sp_jmatrix_t + get_jmatrix (T *t) + { + return t->jacobian_->get_jmatrix (); + } + + template + typename T::reservoir_t::sp_facility_manager_t + get_facility_list (T *t) + { + return t->reservoir_->get_facility_list (); + } + + template + bool + subscribe (T *t, int signal_code, const python_slot &slot) + { + bool result = t->subscribe (signal_code, slot.spslot); + result &= t->subscribe (objbase::on_delete, new blue_sky::tools::py_object_handler (boost::python::detail::wrapper_base_::get_owner (slot))); + + return result; + } + + PY_EXPORTER (reservoir_simulator_exporter, default_exporter) + .def ("init", &T::read_keyword_file_and_init) + .def ("simulate", &T::main_loop) + .def ("simulate", &T::simulate) + .def ("subscribe", subscribe ) + .add_property ("facility_list", make_function (get_facility_list )) + .add_property ("jmatrix", make_function (get_jmatrix )) + .add_property ("calc_model", make_getter (&T::cm, return_value_policy ())) + .add_property ("reservoir", make_getter (&T::reservoir_, return_value_policy ())) + .add_property ("mesh", make_getter (&T::mesh, return_value_policy ())) + .add_property ("event_manager", make_getter (&T::em, return_value_policy ())) + .add_property ("data_manager", make_getter (&T::dm, return_value_policy ())) + .add_property ("jacobian", make_getter (&T::jacobian_, return_value_policy ())) + .add_property ("keyword_manager", make_getter (&T::keyword_manager_, return_value_policy ())) + PY_EXPORTER_END; + + void + py_export_reservoir_simulator() + { + strategy_exporter::export_base ("reservoir_simulator"); + } + +} // namespace python +} // namespace blue_sky + diff --git a/bs_bos_core/src/py_table_2d_debug.cpp b/bs_bos_core/src/py_table_2d_debug.cpp new file mode 100644 index 0000000..19d0e0f --- /dev/null +++ b/bs_bos_core/src/py_table_2d_debug.cpp @@ -0,0 +1,66 @@ +/** + * \file py_table_2d_debug.cpp + * \brief python wrappers for table_2d. debug only + * \author Miryanov Sergey + * \date 12.05.2008 + */ +#include "stdafx.h" + +#ifdef _DEBUG + +#include "py_table_2d_debug.h" + +namespace blue_sky + { + namespace python + { + + using namespace boost::python; + + template + void export_py_data_row (const char *name) + { + class_ < py_data_row > (name) + .def ("get", &py_data_row ::get) + ; + } + + template + void export_py_data_group (const char *name) + { + class_ < py_data_group > (name) + .def ("get_rows_count", &py_data_group ::get_rows_count) + .def ("get_columns_count", &py_data_group ::get_columns_count) + .def ("get_row", &py_data_group ::get_row) + ; + } + + template + void export_py_table_2d (const char *name) + { + class_ < py_table_2d > (name) + .def ("get_groups_count", &py_table_2d ::get_groups_count) + .def ("get_data_group", &py_table_2d ::get_data_group) + ; + } + + void + py_export_table_2d () + { + + export_py_data_row ("data_row_fi"); + export_py_data_row ("data_row_di"); + + export_py_data_group ("data_group_fi"); + export_py_data_group ("data_group_di"); + + export_py_table_2d ("table_2d_fi"); + export_py_table_2d ("table_2d_di"); + } + + + } +} + + +#endif // #ifdef _DEBUG diff --git a/bs_bos_core/src/py_two_stage_preconditioner.cpp b/bs_bos_core/src/py_two_stage_preconditioner.cpp new file mode 100644 index 0000000..42bc6bc --- /dev/null +++ b/bs_bos_core/src/py_two_stage_preconditioner.cpp @@ -0,0 +1,48 @@ +/** + * \file py_two_stage_preconditioner.cpp + * \brief Python wrapper for two_stage_preconditioner + * \author Miryanov Sergey + * \date 16.04.2008 + */ +#include "stdafx.h" + +#include "py_two_stage_preconditioner.h" + +#ifdef BSPY_EXPORTING_PLUGIN + +namespace blue_sky + { + namespace python + { + + template + struct two_stage_prec_exporter + { + template + static class_t & + export_class (class_t &class__) + { + using namespace boost::python; + + solver_exporter ::export_class (class__) + .def ("set_prec_1", &solver_t::set_prec_1) + .def ("set_prec_2", &solver_t::set_prec_2) + .add_property ("prec_1", &solver_t::get_prec_1, &solver_t::set_prec_1) + .add_property ("prec_2", &solver_t::get_prec_2, &solver_t::set_prec_2) + ; + + return class__; + } + }; + + //! export classes to python + void py_export_two_stage_prec () + { + strategy_exporter::export_class ("two_stage_prec_seq"); + } + + + } // namespace python +} // namespace blue_sky + +#endif // #ifdef BSPY_EXPORTING_PLUGIN diff --git a/bs_bos_core/src/py_well_factory.cpp b/bs_bos_core/src/py_well_factory.cpp new file mode 100644 index 0000000..f385fc9 --- /dev/null +++ b/bs_bos_core/src/py_well_factory.cpp @@ -0,0 +1,49 @@ +/** + * \file py_well_factory.cpp + * \brief + * \author Sergey Miryanov + * \date 21.05.2009 + * */ +#include "stdafx.h" +#include "py_well_factory.h" +#include "well_connection.h" + +namespace blue_sky { +namespace python { + + PY_EXPORTER (well_factory_exporter, default_exporter) + .def ("create_well", &T::create_well) + .def ("create_connection", &T::create_connection) + PY_EXPORTER_END; + + PY_EXPORTER (well_controller_factory_exporter, default_exporter) + .def ("create_controller", &T::create_controller) + .def ("create_control", &T::create_control) + .def ("set_rate_control_factory", &T::set_rate_control_factory) + PY_EXPORTER_END; + + PY_EXPORTER (well_rate_control_factory_exporter, default_exporter) + .def ("create_control", &T::create_control) + PY_EXPORTER_END; + + //PYTHON_EXPORT_WRAPPER (py_export_well_factory, well_factory, py_well_factory, 2, (create_well, create_connection)); + //PYTHON_EXPORT_WRAPPER (py_export_well_controller_factory, well_controller_factory, py_well_controller_factory, 3, (create_controller, create_control, set_rate_control_factory)); + ////PYTHON_EXPORT_WRAPPER (py_export_well_limit_operation_factory, well_limit_operation_factory, py_well_limit_operation_factory, 1, (create_limit)); + + //PYTHON_EXPORT_WRAPPER (py_export_well_rate_control_factory, well_rate_control_factory, py_well_rate_control_factory, 1, (create_control)); + + void + py_export_well_factories () + { + strategy_exporter::export_base ("well_factory"); + strategy_exporter::export_base ("well_controller_factory"); + strategy_exporter::export_base ("well_rate_control_factory"); + + strategy_exporter::export_class ("py_well_factory"); + strategy_exporter::export_class ("py_well_controller_factory"); + strategy_exporter::export_class ("py_well_rate_control_factory"); + } + +} // namespace python +} // namespace blue_sky + diff --git a/bs_bos_core/src/reservoir.cpp b/bs_bos_core/src/reservoir.cpp new file mode 100644 index 0000000..3c4475a --- /dev/null +++ b/bs_bos_core/src/reservoir.cpp @@ -0,0 +1,518 @@ +/** + * \file reservoir.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 16.07.2008 + * */ +#include "stdafx.h" + +#include "reservoir.h" +#include "well_connection.h" +#include "facility_manager.h" +#include "jacobian.h" +#include "well_rate_control.h" +#include "calc_model.h" +#include "event_filter.h" + +#ifdef _HDF5 +#include "bs_hdf5_storage.h" +#include "results_hdf5_writer.h" +#endif + +#include "closure.h" +#include "for_each_well.h" + +#include BS_FORCE_PLUGIN_IMPORT () +#include "scal_3p.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + template + reservoir::~reservoir () + { + + } + + //! constructor + template + reservoir ::reservoir(const reservoir & cl) + : bs_refcounter (cl), objbase (cl) + { + if (&cl != this) + *this = cl; + } + + + template + reservoir ::reservoir (bs_type_ctor_param /*param*/) + { + facility_list_ = BS_KERNEL.create_object(facility_manager_t::bs_type(), true); + well_factory_ = BS_KERNEL.create_object(well_factory_t::bs_type(), true); + well_controller_factory_ = BS_KERNEL.create_object(controller_factory_t::bs_type(), true); + well_limit_operation_factory_ = BS_KERNEL.create_object(limit_operation_factory_t::bs_type(), true); + event_filter_ = BS_KERNEL.create_object (event_filter::bs_type (), true); +#ifdef _HDF5 + hdf5 = BS_KERNEL.create_object (bs_hdf5_storage::bs_type (), true); +#endif + } + + template + typename reservoir::sp_well_t + reservoir::get_well (const std::string &group_name, const std::string &well_name) const + { + return facility_list_->get_well (group_name, well_name); + } + + template + typename reservoir::sp_well_t + reservoir::get_well (const std::string &well_name) const + { + return facility_list_->get_well (well_name); + } + + + template + typename reservoir::sp_well_t + reservoir::create_well (const std::string &group_name, const std::string &well_name) + { + sp_well_t w = well_factory_->create_well (group_name, well_name); + BS_ASSERT (w) (group_name) (well_name); + + if (w) + { + facility_list_->add_well (w); + } + + return w; + } + + + template + typename reservoir::sp_well_controller_t + reservoir::create_well_controller (const sp_well_t &owner_well) + { + BS_ASSERT (owner_well); + + sp_well_controller_t wc = well_controller_factory_->create_controller (); + BS_ASSERT (wc) (owner_well->get_name ()); + + if (wc) + owner_well->set_controller (wc); + + return wc; + } + + template + typename reservoir::sp_rate_control_t + reservoir::create_bhp_control (bool is_prod, const sp_calc_model_t &calc_model) + { + return well_controller_factory_->create_control (wells::bhp_control, is_prod, calc_model); + } + + template + typename reservoir::sp_rate_control_t + reservoir::create_rate_control (bool is_prod, wells::rate_control_type control_type, const sp_calc_model_t &calc_model) + { + return well_controller_factory_->create_control ((wells::is_rate_control (control_type) ? control_type : wells::liquid_rate_control), is_prod, calc_model); + } + + + template + typename reservoir::sp_well_limit_operation_t + reservoir::create_well_limit_operation (const sp_well_t &owner_well, wells::limit_operation_type operation) + { + BS_ASSERT (owner_well); + + sp_well_limit_operation_t wlo = well_limit_operation_factory_->create_limit (operation); + BS_ASSERT (wlo) (operation) (owner_well->get_name ()); + + if (wlo) + owner_well->set_limit_operation (wlo); + + return wlo; + } + + + template + typename reservoir::sp_connection_t + reservoir::create_connection () + { + sp_connection_t con = well_factory_->create_connection (); + + if (!con) + throw bs_exception ("reservoir::create_connection", "can't create connection"); + + return con; + } + + template + void + reservoir::save_data (const sp_storage_t &storage) const + { + BS_ASSERT (facility_list_); + facility_list_->save_data (storage); + } + + template + typename reservoir::item_t + reservoir::pressure () const + { + BS_ASSERT (false && "NOT IMPL YET"); + return 0; + } + + template + bool + reservoir::check_limits (const sp_params_t &/*params*/) const + { + BS_ASSERT (false && "NOT IMPL YET"); + return false; + } + + template + void + reservoir::pre_small_step () + { + for_each_facility (*facility_list_, closure (&facility_t::pre_small_step)); + } + template + void + reservoir::restart_small_step () + { + for_each_facility (*facility_list_, closure (&facility_t::restart_small_step)); + } + template + void + reservoir ::pre_newton_step () + { + for_each_facility (*facility_list_, closure (&facility_t::pre_newton_step)); + } + template + void + reservoir ::restart_newton_step () + { + for_each_facility (*facility_list_, closure (&facility_t::restart_newton_step)); + } + + template + void + reservoir::init_rows (index_array_t &rows) const + { + for_each_facility (*facility_list_, closure (&facility_t::fill_rows, rows)); + + // correct rows values + for (index_t i = 0, cnt = (index_t)rows.size () - 1; i < cnt; ++i) + { + rows[i + 1] += rows[i]; + } + } + + template + size_t + reservoir::get_connections_count () const + { + return for_each_well_acc (*facility_list_, closure (&well_t::get_connections_count)); + } + + template + void + reservoir::init_jacobian (const sp_jmatrix_t &jmx, index_t n_cells) + { + index_array_t &rows = jmx->get_irregular_matrix ()->get_rows_ptr (); + + assign (rows, n_cells + 1, 0); + init_rows (rows); + } + + template + void + reservoir::end_jacobian (item_t dt, const sp_calc_model_t &calc_model, sp_jacobian_t &jacobian) + { + const sp_jacobian_matrix_t &jmx (jacobian->get_jmatrix ()); + + const index_array_t &rows = jmx->get_irregular_matrix ()->get_rows_ptr (); + index_array_t &cols = jmx->get_irregular_matrix ()->get_cols_ind (); + rhs_item_array_t &values = jmx->get_irregular_matrix ()->get_values (); + + if (rows.empty ()) + return ; + + index_t block_size = calc_model->n_phases; + index_t b_sqr = block_size * block_size; + cols.assign (rows.back (), -1); + values.assign (rows.back () * b_sqr, 0); + markers_.assign (rows.size (), 0); + + jmx->get_irregular_matrix ()->n_block_size = calc_model->n_phases; + jmx->get_irregular_matrix ()->n_rows = (index_t) rows.size () - 1; + jmx->get_irregular_matrix ()->n_cols = (index_t) cols.size (); + + for_each_facility (*facility_list_, closure (&facility_t::fill_jacobian, + dt, block_size, rows, cols, values, markers_)); + +#ifdef _DEBUG + for (size_t i = 0, cnt = cols.size (); i < cnt; ++i) + { + if (cols[i] == -1) + { + bs_throw_exception ("Cols i is negative"); + } + } +#endif + } + + template + void + reservoir::calc_wells (int istart, double dt, const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh, sp_jmatrix_t &jmatrix) + { + for_each_facility (*facility_list_, closure (&facility_t::process, + istart, dt, calc_model, mesh, jmatrix)); + } + + template + void + reservoir ::fill_rhs_wells (double dt, const sp_calc_model_t &calc_model, rhs_item_array_t &rhs, bool update_after_gauss_elimination) const + { + for_each_facility (*facility_list_, closure (&facility_t::fill_rhs, + dt, calc_model->n_phases, calc_model->is_gas (), calc_model->is_oil (), calc_model->is_water (), rhs)); + } + + template + typename reservoir::sp_facility_manager_t + reservoir::get_facility_list () const + { + return facility_list_; + } + + template + void + reservoir ::restore_wells_solution (double dt, const item_array_t &p_sol, const item_array_t &s_sol, index_t block_size) + { + for_each_facility (*facility_list_, closure (&facility_t::restore_solution, dt, p_sol, s_sol, block_size)); + } + + template + void + reservoir ::pre_large_step (const sp_calc_model_t &calc_model, const sp_mesh_iface_t &mesh) + { + typename facility_manager_t::well_const_iterator_t wb = facility_list_->wells_begin (); + typename facility_manager_t::well_const_iterator_t we = facility_list_->wells_end (); + for (; wb != we; ++wb) + { + wb->second->pre_large_step (calc_model, mesh); + } + //for_each_facility (*facility_list_, closure (&facility_t::pre_large_step, calc_model, mesh)); + } + + + template + void + reservoir ::add_filter_well (const std::string &well_name) + { + event_filter_->add_filter_well (well_name); + } + template + const typename reservoir ::sp_event_filter_t & + reservoir ::get_event_filter () const + { + return event_filter_; + } + +#ifdef _HDF5 + template + void + reservoir::write_mesh_to_hdf5 (const smart_ptr , true> &mesh) const + { + smart_ptr , true> smesh (mesh, bs_dynamic_cast ()); + hdf5::write_mesh_to_hdf5 (hdf5, smesh); + } + + template + void + reservoir::open_hdf5_file (const std::string &filename) const + { + hdf5->lock ()->open (filename.c_str ()); + } + + template + void + reservoir::close_hdf5_file () const + { + hdf5->lock ()->close (); + } + + template + void + reservoir::write_step_to_hdf5 (const sp_calc_model_t &calc_model, + const sp_mesh_iface_t &mesh, + const sp_jmatrix_t &jmx, + int l_time_step_num, int total_ts_count, + item_t time) const + { +#ifdef _MPI + int n_elem_global = mesh->mpi_decomp->mpi_global_n_active_elmts; + int n_elem_local = mesh->mpi_decomp->get_n_local_own (); //local number of active elments without ghost cells + int mpi_offset = mesh->mpi_decomp->get_elem_own_displ (); //offset in file + int mpi_start = mesh->mpi_decomp->get_recv_l (); //offset in array-starting with first own element +#else + int n_elem_global = mesh->get_n_active_elements (); + int n_elem_local = n_elem_global; + int mpi_offset = 0; + int mpi_start = 0; +#endif + + hdf5::write_well_results (*hdf5, calc_model->well_res, calc_model->ts_params->get_bool (fi_params::WRITE_CONN_RESULTS_TO_HDF5)); + hdf5::write_fip_results (*hdf5, calc_model->fip_res); + + int n_phases = calc_model->n_phases; + // temporary storage for values, need to extract saturations + // and converting to float if need. + seq_vector tmp_buf (n_elem_local); + seq_vector main_var_tmp (n_elem_local); + //tmp_buf.resize (n_elem_local); + + if ((l_time_step_num % calc_model->ts_params->get_int (fi_params::SAVE_STEP_DATA_PERIOD) == 0) + || l_time_step_num == total_ts_count + || l_time_step_num == 1) + { + + if (calc_model->ts_params->get_bool (fi_params::WRITE_PRESSURE_TO_HDF5)) + { + copy_to (&calc_model->pressure[mpi_start], &tmp_buf[0], n_elem_local); + hdf5->add_to_results ("/results/pressure", &tmp_buf[0], n_elem_global, n_elem_local, mpi_offset, time); + } + + if (calc_model->ts_params->get_bool (fi_params::WRITE_GAS_OIL_RATIO_TO_HDF5)) + { + if (FI_CHK_GAS (calc_model->phases) && FI_CHK_OIL (calc_model->phases)) + { + copy_to (&calc_model->gas_oil_ratio[mpi_start], &tmp_buf[0], n_elem_local); + hdf5->add_to_results ("/results/gor", &tmp_buf[0], n_elem_global, n_elem_local, mpi_offset, time); + } + } + + copy_to (&calc_model->main_variable[mpi_start], &main_var_tmp[0], n_elem_local); + hdf5->add_to_results ("/results/mainvar", &main_var_tmp[0], n_elem_global, n_elem_local, mpi_offset, time); + + if (calc_model->ts_params->get_bool (fi_params::WRITE_SATURATION_TO_HDF5)) + { + // for 1-phase no saturations + if (calc_model->n_phases > 1) + { + int d_w = calc_model->phase_d[FI_PHASE_WATER]; + int d_g = calc_model->phase_d[FI_PHASE_GAS]; + + if (FI_CHK_GAS (calc_model->phases)) + { + copy_to (&calc_model->saturation_3p[n_phases * mpi_start], &tmp_buf[0], n_phases * n_elem_local, n_phases/*stride*/, d_g/*start*/); + hdf5->add_to_results ("/results/sgas", &tmp_buf[0], n_elem_global, n_elem_local, mpi_offset, time); + } + if (FI_CHK_WATER (calc_model->phases)) + { + copy_to (&calc_model->saturation_3p[n_phases * mpi_start], &tmp_buf[0], n_phases * n_elem_local, n_phases /*stride*/, d_w/*start*/); + hdf5->add_to_results ("/results/swat", &tmp_buf[0], n_elem_global, n_elem_local, mpi_offset, time); + } + } + }//saturation + +#ifdef BS_BOS_CORE_USE_CSR_ILU_CFL_PREC + if (calc_model->ts_params->get_bool (fi_params::WRITE_CFL_TO_HDF5) && + calc_model->ts_params->get_bool (fi_params::USE_CFL)) + { + if (jmx->get_cfl_vector ().empty ()) + { + jmx->get_cfl_vector ().assign (n_elem_local, 0); + } + + copy_to (&jmx->get_cfl_vector ()[0], &tmp_buf[0], n_elem_local); + hdf5->add_to_results ("/results/cfl", &tmp_buf[0], n_elem_global, n_elem_local, mpi_offset, time); + } +#endif + +#if 0 //TODO: mesh->n_planes + //if (model->ts_params.get_b_param (FI_PARAMS_B_WRITE_PLANE_FLOW_RATES_TO_HDF5)) + { + tmp_buf.resize (mesh->n_planes); + + // parse plane_flow_rates, separating data for each direction of plane and phase + // data layout: {X_oil X_water X_gas Y_oil Y_water Y_gas Z_oil Z_water Z_gas}, so stride is 3*model->n_phases. + int d_w = calc_model->phase_d[FI_PHASE_WATER]; + int d_g = calc_model->phase_d[FI_PHASE_GAS]; + int d_o = calc_model->phase_d[FI_PHASE_OIL]; + + //create group. open-close else + hid_t group_planes = hdf5->begin_object (hdf5->get_file_id (), "/results/plane_flow_rate"); + H5Gclose (group_planes); + + if (FI_CHK_OIL (calc_model->phases)) + { + copy_to_float (calc_model->full_step_plane_flow_rate + d_o * mesh->n_planes, &tmp_buf[0], mesh->n_planes); + hdf5->add_to_results ("/results/plane_flow_rate/oil", &tmp_buf[0], mesh->n_planes, mesh->n_planes, 0, time); + } + if (FI_CHK_GAS (calc_model->phases)) + { + copy_to_float (calc_model->full_step_plane_flow_rate + d_g * mesh->n_planes, &tmp_buf[0], mesh->n_planes); + hdf5->add_to_results ("/results/plane_flow_rate/gas", &tmp_buf[0], mesh->n_planes, mesh->n_planes, 0, time); + } + if (FI_CHK_WATER (calc_model->phases)) + { + copy_to_float (calc_model->full_step_plane_flow_rate + d_w * mesh->n_planes, &tmp_buf[0], mesh->n_planes); + hdf5->add_to_results ("/results/plane_flow_rate/wat", &tmp_buf[0], mesh->n_planes, mesh->n_planes, 0, time); + } + } +#endif + } + } +#endif // #ifdef HDF5 + + + template + typename reservoir ::sp_well_factory_t + reservoir ::get_well_factory () const + { + return well_factory_; + } + template + typename reservoir ::sp_well_controller_factory_t + reservoir ::get_well_controller_factory () const + { + return well_controller_factory_; + } + template + typename reservoir ::sp_well_limit_operation_factory_t + reservoir ::get_well_limit_operation_factory () const + { + return well_limit_operation_factory_; + } + + template + void + reservoir ::set_well_factory (const sp_well_factory_t &factory) + { + well_factory_ = factory; + } + template + void + reservoir ::set_well_controller_factory (const sp_well_controller_factory_t &factory) + { + well_controller_factory_ = factory; + } + template + void + reservoir ::set_well_limit_operation_factory (const sp_well_limit_operation_factory_t &factory) + { + well_limit_operation_factory_ = factory; + } + + //bs stuff + BLUE_SKY_TYPE_STD_CREATE_T_DEF (reservoir, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (reservoir, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (reservoir ), 1, (objbase), "reservior_seq_fi", "", "", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (reservoir ), 1, (objbase), "reservior_seq_di", "", "", false) + + BLUE_SKY_TYPE_IMPL_T_EXT (1, (reservoir ), 1, (objbase), "reservior_seq_mixi", "", "", false) + +} // namespace blue_sky + diff --git a/bs_bos_core/src/reservoir_simulator.cpp b/bs_bos_core/src/reservoir_simulator.cpp new file mode 100644 index 0000000..76ba60d --- /dev/null +++ b/bs_bos_core/src/reservoir_simulator.cpp @@ -0,0 +1,855 @@ +/** + \file reservoir_simulator.h + \brief main reservoir simulator of bos core implementations + \author Nikonov Max +*/ +#include "stdafx.h" + +#include "event_base.h" +#include "event_manager.h" +#include "reservoir_simulator.h" +#include "reservoir.h" +#include "data_storage_interface.h" +#include "jacobian.h" +#include "trans_multipliers.h" +#include "main_loop_calc.h" +#include "facility_manager.h" +#include "keyword_manager.h" +#include "strategy_name.h" + +#define DM_ASSERT_EXCEPTION \ + BS_ASSERT(false) (out_s.str());\ + throw bs_exception("Data manager class",out_s.str().c_str()); + + +namespace blue_sky +{ + + template + reservoir_simulator::reservoir_simulator (bs_type_ctor_param) + : bs_refcounter () + , bs_node (bs_node::create_node()) //new typename this_t::mstatus_traits ())) + , dm (give_kernel::Instance().create_object (dm_t::bs_type ())) + , em (give_kernel::Instance().create_object (em_t::bs_type ())) + , cm (give_kernel::Instance().create_object (calc_model_t::bs_type ())) + , mesh (0) + , reservoir_ (give_kernel::Instance().create_object (reservoir_t::bs_type ())) + , facility_storage_ (give_kernel::Instance().create_object (facility_storage_t::bs_type ())) + , jacobian_ (give_kernel::Instance().create_object (jacobian_t::bs_type ())) + , keyword_manager_ (BS_KERNEL.create_object (keyword_manager_t::bs_type ())) + , mloop (0) + { + this->add_signal (BS_SIGNAL_RANGE (reservoir_simulator)); + keyword_manager_->init ();//em); + + //bs_node::insert (bs_link::create (dm, "data_manager"), false); + //bs_node::insert (bs_link::create (em, "event_manager"), false); + //bs_node::insert (bs_link::create (cm, "calc_model"), false); + + //bs_node::insert (bs_link::create (reservoir_, "reservoir"), false); + //bs_node::insert (bs_link::create (jacobian_, "jacobian"), false); + //bs_node::insert (bs_link::create (facility_storage_, "facility_storage"), false); + } + + template + reservoir_simulator::reservoir_simulator (const this_t &src) + : bs_refcounter () + , bs_node (src) + , dm (src.dm) + , em (src.em) + , cm (src.cm) + , mesh (src.mesh) + , reservoir_ (src.reservoir_) + , facility_storage_ (src.facility_storage_) + , jacobian_ (src.jacobian_) + , mloop (0) + { + } + + template + reservoir_simulator::~reservoir_simulator () + { + } + + template + void reservoir_simulator::set_mesh (const sp_mesh_iface_t &src) + { + this->mesh = src; + } + + template + void + pre_read (const sp_em_t &/*em*/) + { + } + + template + void + post_read (const smart_ptr &em) + { + //if last element of event list contains events we add another empty element with date 30 days later than previous + if (em->event_list.size ()) + { + if (!(*(--em->event_list.end())).second.empty()) + { + std::list tl; + em->event_list.insert(std::make_pair((*(--em->event_list.end())).first + boost::posix_time::hours(30*24),tl)); + } + } + else + { + // TODO: BUG: + BS_ASSERT (false && "em->event_list.empty () == true"); + + std::list tl; + em->event_list.insert(std::make_pair(boost::gregorian::from_us_string ("01-01-1970"), tl)); + em->event_list.insert(std::make_pair(boost::gregorian::from_us_string ("01-02-1970"), tl)); + } + } + template + void + read_keyword_file (const std::string &filename, const smart_ptr &key_handlers, typename keyword_manager_t::keyword_params_t ¶ms) + { + const typename keyword_manager_t::sp_reader_t &l_reader (params.reader); + typedef event_manager event_manager_t; + typedef smart_ptr sp_event_manager_t; + sp_event_manager_t em (params.em); + + char buf[CHAR_BUF_LEN]; + char key[CHAR_BUF_LEN]; + int flag; + int len; + + l_reader->init (filename, filename); + + // start of loop for data file reading + flag = 1; + + for (; flag;) + { + // reading keyword + len = l_reader->read_line (buf, CHAR_BUF_LEN); + if (len < 0) // break if EOF + { + switch (len) + { + case YS_NOTHING_TO_READ: + break; + default: + return; + } + //rep->print (LOG_READ_SECTION, LOG_DEBUG, "Finish reading\n"); + BOSOUT (section::read_data, level::low) << "Finish reading" << bs_end; + break; + } + if (sscanf (buf, "%s", key) != 1) // look from buffer keyword + continue; + + std::string keywrd(key); + + if (key[0] == '/') + { + continue; + } + + if (std::string (key) == "END") + { + BOSOUT (section::read_data, level::low) << "Finish reading with END keyword" << bs_end; + break; + } + + key_handlers->handle_keyword (keywrd, params); + } + } + + template + void reservoir_simulator::simulate (const std::string &path) + { + read_keyword_file_and_init (path); + main_loop(); + } + + template + void + reservoir_simulator ::read_keyword_file_and_init (const std::string &path) + { + write_time_to_log init_time ("read model and init reservoir simulator", ""); + + keyword_params params (keyword_manager_, dm->reader, dm->data, em, mesh, cm->ts_params, cm->scal_prop); + model_filename_ = path; + pre_read (em); + read_keyword_file(path, keyword_manager_, params); + post_read (em); + on_post_read (); + //TODO: make keyword handlers able to change pointers on created objects (like mesh) + mesh = sp_mesh_iface_t (params.mesh, bs_dynamic_cast ()); + if (!mesh) + { + bs_throw_exception ("Can't down cast params.mesh"); + } + init(); + } + + template + const typename reservoir_simulator::sp_dm_t & + reservoir_simulator::get_data_manager () const + { + return dm; + } + + template + const typename reservoir_simulator::sp_em_t & + reservoir_simulator::get_event_manager () const + { + return em; + } + + template + const typename reservoir_simulator::sp_calc_model_t & + reservoir_simulator::get_calc_model () const + { + return cm; + } + + template + const typename reservoir_simulator::sp_mesh_iface_t & + reservoir_simulator::get_mesh() const + { + return mesh; + } + + template + const typename reservoir_simulator::sp_jacobian_t & + reservoir_simulator::get_jacobian () const + { + return jacobian_; + } + + template + const typename reservoir_simulator ::sp_reservoir_t & + reservoir_simulator ::get_reservoir () const + { + return reservoir_; + } + + /*! + \brief checking saturation + \return if success 0 + \return if one of nx, ny, nz == 0 -1 + \return if soil[i] is out of range -2 + \return if swat[i] is out of range -3 + \return if error in swof -4 + \return if error in sgof -5 + */ + template + void + check_sat (const smart_ptr , true> &mesh, const smart_ptr &data) + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::item_array_t item_array_t; + + std::ostringstream out_s; + + index_t nb = mesh->get_n_active_elements (); + const index_array_t &original_element_num = mesh->get_int_to_ext(); + + if (!data->init_section) + { + if (!(*data->d_map)[PRESSURE].array.size ()) + { + bs_throw_exception ("check_sat: Initial pressure is not specified"); + } + if (!(*data->d_map)[SWAT].array.size ()) + { + bs_throw_exception ("check_sat: Initial saturation is not specified"); + } + if (!(*data->d_map)[SOIL].array.size ()) + { + BOSWARN (section::check_data, level::warning) << "SOIL is not initialized" << bs_end; + } + } + + if (!data->init_section) + { + array_float16_t swat = ((*data->d_map)[SWAT].array); + array_float16_t soil = ((*data->d_map)[SOIL].array); + + for (index_t i = 0; i < nb; ++i) + { + index_t i_m = original_element_num[i]; + + if (soil.size () && (soil[i_m] < -1.e-12 || soil[i_m] > 1 + 1.e-5)) + { + bs_throw_exception (boost::format ("soil[%d] = %f is out of range") % i_m % soil[i_m]); + } + if (swat.size () && (swat[i_m] < -1.e-12 || swat[i_m]> 1 + 1.e-5)) + { + bs_throw_exception (boost::format ("swat[%d] = %f is out of range") % i_m % swat[i_m]); + } + if (soil.size () && swat.size () && (soil[i_m] + swat[i_m] > 1 + 1.e-5)) + { + bs_throw_exception (boost::format ("Sum of water saturation and oil saturation for cell %d = %f is out of range") + % i_m % (soil[i_m] + swat[i_m])); + } + } + } + } + + /*! + \brief checking permx, permy, permz + \return if success 0 + \return if one of nx, ny, nz == 0 -1 + \return if bad pointer permx, permy, permz -10 + \return if value of permx[i], permy[i], permz[i] == 0 -11 + */ + template + void + check_perm (const smart_ptr , true> &mesh, const smart_ptr &data) + { + typedef typename strategy_t::index_t index_t; + + const smart_ptr &ldata (data); + std::ostringstream out_s; + index_t nb = mesh->get_n_active_elements (); + + if (!nb) + { + bs_throw_exception ("All dimensions should be greate than 0. Number of active elements = 0."); + } + if (!ldata->contain ("PERMX") || !ldata->contain ("PERMY") || !ldata->contain ("PERMZ")) + { + if (!ldata->contain ("PERMX")) + { + BOSERR (section::check_data, level::error) << "PERMX is not specified" << bs_end; + } + if (!ldata->contain ("PERMY")) + { + BOSERR (section::check_data, level::error) << "PERMY is not specified" << bs_end; + } + if (!ldata->contain ("PERMZ")) + { + BOSERR (section::check_data, level::error) << "PERMZ is not specified" << bs_end; + } + + bs_throw_exception ("PERMX, PERMY or PERMZ are not specified"); + } + } + + template + void + check_poro_ntg_multpv (const smart_ptr , true> &mesh, const smart_ptr &data) + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::item_array_t item_array_t; + + const index_array_t &original_element_num = mesh->get_int_to_ext(); + index_t nb = mesh->get_n_active_elements (); + if (!nb) + { + bs_throw_exception ("All dimensions should be greate than 0. Number of active elements = 0."); + } + + array_float16_t poro = data->get_float_non_empty_array ("PORO"); + array_float16_t ntg = data->get_float_non_empty_array ("NTG"); + array_float16_t multpv = data->get_float_array ("MULTPV"); + + for (index_t i = 0; i < nb; ++i) + { + index_t i_m = original_element_num[i]; + + if (poro[i_m] < (item_t) -COMP_EPSILON || poro[i_m] > (item_t) (1 + COMP_EPSILON)) + { + bs_throw_exception (boost::format ("PORO for node [%d] = %f is out of range") + % i % poro[i_m]); + } + + if (poro[i_m] < float16_t (COMP_EPSILON)) + { + BOSWARN (section::check_data, level::warning) + << boost::format ("PORO for node [%d] = %f is too small") % i % poro[i_m] + << bs_end; + poro[i_m] = float16_t (COMP_EPSILON); + } + + if (ntg[i_m] < float16_t (-COMP_EPSILON)) + { + bs_throw_exception (boost::format ("NTG for node [%d] = %f is out of range") + % i % ntg[i_m]); + } + + if (ntg[i_m] < float16_t (COMP_EPSILON)) + { + BOSWARN (section::check_data, level::warning) + << boost::format ("NTG for node [%d] = %f is too small") % i % ntg[i_m] + << bs_end; + ntg[i_m] = float16_t (COMP_EPSILON); + } + + if (multpv.size ()) + { + if (multpv[i_m] < float16_t (-COMP_EPSILON)) + { + bs_throw_exception (boost::format ("MULTPV for node [%d] = %f is out of range") + % i % multpv[i_m]); + } + + if (multpv[i_m] < float16_t (COMP_EPSILON)) + { + BOSWARN (section::check_data, level::warning) + << boost::format ("MULTPV for node [%d] = %f is too small") % i % multpv[i_m] + << bs_end; + multpv[i_m] = float16_t (COMP_EPSILON); + } + } + + } + } + + template + void + check_num (const smart_ptr , true> &mesh, const smart_ptr &data) + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::index_array_t index_array_t; + + index_t nb = mesh->get_n_active_elements (); + + //Check equil regions number + if (data->i_map->contain(EQLNUM)) + { + const array_uint8_t &eqlnum = ((*data->i_map)[EQLNUM].array); + + if (eqlnum.size ()) + { + for (index_t i = 0; i < nb; ++i) + { + index_t i_m = mesh->get_int_to_ext()[i]; + if (eqlnum[i_m] <= 0 || eqlnum[i_m] > data->eql_region) + { + bs_throw_exception (boost::format ("Equlibrium region number for node [%d] = %d is out of range") + % i % eqlnum [i_m]); + } + } + } + } + + //Check saturation regions number + if (data->i_map->contain(SATNUM)) + { + const array_uint8_t &satnum = tools::get_non_empty (((*data->i_map)[SATNUM].array)); + + for (index_t i = 0; i < nb; ++i) + { + index_t i_m = mesh->get_int_to_ext()[i]; + if (satnum[i_m] <= 0 || satnum[i_m] > data->sat_region) + { + bs_throw_exception (boost::format ("Saturation region number for node [%d] = %d is out of range") + % i % satnum [i_m]); + } + } + } + + //Check pvt regions number + if (data->i_map->contain(PVTNUM)) + { + const array_uint8_t &pvtnum = tools::get_non_empty (((*data->i_map)[PVTNUM].array)); + + for (index_t i = 0; i < nb; ++i) + { + index_t i_m = mesh->get_int_to_ext()[i]; + if (pvtnum[i_m] <= 0 || pvtnum[i_m] > data->pvt_region) + { + bs_throw_exception (boost::format ("PVT region number for node [%d] = %d is out of range") + % i % pvtnum [i_m]); + } + } + } + + //Check fip regions number + if (data->i_map->contain(FIPNUM)) + { + const array_uint8_t &fipnum = tools::get_non_empty ((*data->i_map)[FIPNUM].array); + + for (index_t i = 0; i < nb; ++i) + { + index_t i_m = mesh->get_int_to_ext()[i]; + if (fipnum[i_m] <= 0 || fipnum[i_m] > data->fip_region) + { + bs_throw_exception (boost::format ("FIP region number for node [%d] = %d is out of range") + % i % fipnum [i_m]); + } + } + } + + } + + template + void + check_rock (const smart_ptr &data) + { + typedef typename strategy_t::index_t index_t; + std::ostringstream out_s; + if (!data->rock.size ()) + { + bs_throw_exception ("ROCK is not specified"); + } + + for (index_t i = 0; i < data->pvt_region; ++i) + { + if (data->rock[i] < 0) + { + bs_throw_exception (boost::format ("Rock compressibility in region %d = %f is out of range") + % (i + 1) % data->rock [i]); + } + if (data->p_ref[i] <= 1.e-14) + { + bs_throw_exception (boost::format ("Reference pressure for rock compressibility in region %d = %f is out of range") + % (i + 1) % data->p_ref[i]); + } + // Both compressibilities (rock and water) cannot be 0 both + if (data->rock[i] < COMP_EPSILON && data->pvtw[i].main_data_[2] < COMP_EPSILON) // 2 = DATA_GPR in pvt_water + { + // TODO: BUG: data->pvtw[i].main_data_[2] + bs_throw_exception (boost::format ("In region %d rock compressibility = %f and water compressibility = %f are both about 0") + % (i + 1) % data->rock[i] % data->pvtw[i].main_data_[2]); + } + } + } + + + template + void + check_geometry (const smart_ptr , true> &mesh, const smart_ptr &data) + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_array_t index_array_t; + typedef typename strategy_t::item_array_t item_array_t; + + std::ostringstream out_s; + + index_t nb = data->nx * data->ny * data->nz; + + if (!nb) + { + bs_throw_exception ("All dimensions should be greater than 0. Number of active elements = 0."); + } + + + + /* + // In case of restart we got all geometry from mesh restored from + // the restart file. So we skip this test. + if (data->restart) + return; + */ + + mesh->check_data(); + } + + template + void + check_equil (const smart_ptr , true> &mesh, const smart_ptr &data) + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + typedef typename strategy_t::index_array_t index_array_t; + + std::ostringstream out_s; + index_t N_eq = 2; // number of regions (eql + pvt = 2) + index_t nb = mesh->get_n_active_elements (); + + index_t eq_reg = N_eq * data->eql_region; + data->equil_regions.resize (eq_reg, 0); + + array_uint8_t eqlnum; + array_uint8_t pvtnum; + if (!data->i_map->contain(EQLNUM)) + { + data->i_map->create_item (EQLNUM, &i_pool_sizes[ARRAY_POOL_TOTAL * EQLNUM], i_pool_default_values[EQLNUM]); + eqlnum = tools::get_non_empty ((*data->i_map)[EQLNUM].array); + eqlnum.assign (i_pool_default_values[EQLNUM] + 1); + } + if (!data->i_map->contain(PVTNUM)) + { + data->i_map->create_item(PVTNUM, &i_pool_sizes[ARRAY_POOL_TOTAL * PVTNUM], i_pool_default_values[PVTNUM]); + pvtnum = tools::get_non_empty ((*data->i_map)[PVTNUM].array); + pvtnum.assign (i_pool_default_values[PVTNUM] + 1); + } + + eqlnum = tools::get_non_empty ((*data->i_map)[EQLNUM].array); + pvtnum = tools::get_non_empty ((*data->i_map)[PVTNUM].array); + + //check correspondence of pvt-regions to eql-regions: + //one eql-region must contain only one pvt-region + for (index_t i = 0; i < nb; ++i) + { + index_t i_m = mesh->get_int_to_ext ()[i]; + eq_reg = (eqlnum[i_m] - 1) * N_eq; + if (data->equil_regions[eq_reg] == 0) + { + // set values of regions for current equil region + data->equil_regions[eq_reg] = 1; + data->equil_regions[eq_reg + 1] = pvtnum[i_m] - 1; // set pvt region for equil region + } + else + { + if (pvtnum[i_m] != data->equil_regions[eq_reg + 1] + 1) + { + bs_throw_exception (boost::format ("Incorrect PVT region %d for equilibrium region %d in grid block %d") + % pvtnum [i_m] % eqlnum [i_m] % i_m); + } + } + } + } + + template + void + check_volume (const smart_ptr , true> &mesh, const smart_ptr &/*data*/) + { + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_array_t item_array_t; + const smart_ptr , true> s_mesh(mesh, bs_dynamic_cast ()); + std::ostringstream out_s; + index_t x, y, z; + + const item_array_t &mesh_volumes = mesh->get_volumes (); + for (index_t i = 0, cnt = mesh->get_n_active_elements(); i < cnt; ++i) + { + if (mesh_volumes[i] < COMP_EPSILON) + { + //TODO: wrap mesh element identification to single function for all mesh types + s_mesh->get_element_int_to_ijk (i, x, y, z); + + bs_throw_exception (boost::format ("Volume for grid block [%d: %d, %d, %d] = %f is too small") + % i % x % y % z % mesh_volumes[i]); + } + } + } + + + template + bool + check5 (T function, const sp_idata_t &ldata, const sp_mesh_iface_t &mesh, const char *description, bool check_init) + { + try + { + BOSOUT (section::check_data, level::medium) << description << bs_end; + if (check_init && !ldata->init_section) + { + BOSOUT (section::check_data, level::medium) << " ...[ NOT INITED ]" << bs_end; + } + else + { + function (mesh, ldata); + return true; + } + } + catch (bs_exception &e) + { + BOSOUT (section::check_data, level::medium) << " ...[FAIL]" << bs_end; + BOSERR (section::check_data, level::error) << e.what () << bs_end; + } + + return false; + } + + template + bool + check3 (T function, const sp_idata_t &ldata, const char *description) + { + try + { + BOSOUT (section::check_data, level::medium) << description << bs_end; + + function (ldata); + return true; + } + catch (bs_exception &e) + { + BOSOUT (section::check_data, level::medium) << " ...[FAIL]" << bs_end; + BOSERR (section::check_data, level::error) << e.what () << bs_end; + } + + return false; + } + + template + void + check_data (const smart_ptr , true> &mesh, const smart_ptr &data) + { + std::ostringstream out_s; + + BOSOUT (section::check_data, level::medium) + << "\n***************************************************************\n" + << " CHECK INPUT DATA\n" + << "***************************************************************" << bs_end; + + size_t count = 0; + count += check5 (check_num , data, mesh, "Region numbers check... ", true); + count += check5 (check_sat , data, mesh, "Saturation check... ", false); + count += check5 (check_geometry , data, mesh, "Geometry check... ", false); + count += check5 (check_perm , data, mesh, "Permability check... ", false); + count += check5 (check_poro_ntg_multpv , data, mesh, "Porosity and NTG, MULTPV check check... ", false); + count += check5 (check_equil , data, mesh, "Equil region numbers check... ", true); + count += check5 (check_volume , data, mesh, "Volume check... ", false); + count += check3 (check_rock , data, "Rock check... "); + + //BOSOUT (section::check_data, level::medium) << "Well data check... "; + //if (!(r = check_wfrictn_keyword_connection_data (msh))) + //BOSOUT (section::check_data, level::medium) << " ...[ OK ]" << bs_end; + //else + //BOSOUT (section::check_data, level::medium) << " ...[FAIL] - error: " << r << bs_end; + + //if (count < 8) + // throw bs_exception ("data_manager", "one of check failed"); + + // TODO: + //BOSOUT << output_time; + } + + template + void reservoir_simulator::init () + { + std::ostringstream out_s; + + const typename calc_model_t::sp_jacobian_matrix_t &jmatrix (jacobian_->get_jmatrix ()); + + dm->check_arrays_for_inactive_blocks(); + + mesh->init_props (dm->data); + mesh->set_darcy (cm->internal_constants.darcy_constant); + + //!TODO:output init_ext_to_int(splicing) + mesh->init_ext_to_int(); + + if (mesh->get_n_active_elements() <= 0) + { + bs_throw_exception ("Error: No active cells!"); + } + + ////////////////////////////////////// + // Check input data before units conversion for correct reporting + // of user errors + check_data (mesh, dm->data); + + cm->init_main_arrays(dm->data, mesh); + cm->init_calcul_arrays (dm->data, mesh); + cm->init_jacobian (jacobian_, mesh); + + // calculate planes geometric transmissibility + cm->rock_grid_prop->init_planes_trans (mesh->get_n_active_elements (), mesh->get_volumes (), cm->ts_params, cm->internal_constants); + + typename mesh_iface_t::index_array_t boundary_array; + std::string flux_conn_name = "bs_flux_connections_" + tools::strategy_name ::name (); + typename mesh_iface_t::sp_flux_conn_iface_t flux_conn (BS_KERNEL.create_object(flux_conn_name), bs_dynamic_cast ()); + if (!flux_conn) + { + bs_throw_exception (boost::format ("Can`t create %s!") % flux_conn_name); + } + + index_t N_block_size = cm->n_phases; + index_t N_blocks = mesh->get_n_active_elements (); + + mesh->build_jacobian_and_flux_connections (jmatrix->get_regular_matrix(), flux_conn, boundary_array); + jmatrix->get_regular_matrix()->init_values(N_block_size); + assign (jmatrix->get_regular_matrix ()->get_values(), N_block_size * N_block_size * (2* mesh->get_n_connections() + mesh->get_n_active_elements()), item_t (0)); + jmatrix->m_array = flux_conn->get_matrix_block_idx_minus(); + jmatrix->p_array = flux_conn->get_matrix_block_idx_plus (); + jmatrix->trns_matrix = flux_conn->get_conn_trans(); + + jmatrix->get_irregular_matrix ()->init (N_blocks, N_blocks, N_block_size, 0); + } + + template + typename reservoir_simulator ::main_loop_calc_t * + reservoir_simulator ::get_main_loop () + { + if (cm->n_phases == 3) + return new main_loop_calc (this); + else if (cm->is_water () && cm->is_oil ()) + return new main_loop_calc (this); + else if (cm->is_gas () && cm->is_oil ()) + return new main_loop_calc (this); + else if (cm->is_water ()) + return new main_loop_calc (this); + else if (cm->is_gas ()) + return new main_loop_calc (this); + else if (cm->is_oil ()) + return new main_loop_calc (this); + else + bs_throw_exception ("Unknown phase model"); + } + + template + void + reservoir_simulator::main_loop () + { + on_begin (clock ()); + write_time_to_log lllll("main loop time","tss"); + + mloop = get_main_loop (); + if (!mloop) + { + bs_throw_exception ("Can't create main_loop_calc"); + } + + try + { + mloop->ready (); + mloop->go (); + mloop->end (); + mloop = 0; + + on_end (clock ()); + } + catch (...) + { + mloop = 0; + + throw; + } + } + + template + void + reservoir_simulator ::pre_large_step (const sp_event_base_list_t &event_list) + { + mloop->apply_events (event_list); + reservoir_->pre_large_step (cm, mesh); + } + + template + std::string + reservoir_simulator ::model_filename () const + { + return model_filename_; + } + + // create object + BLUE_SKY_TYPE_STD_CREATE_T_DEF (reservoir_simulator, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (reservoir_simulator, (class)) + + // array map implementation + BLUE_SKY_TYPE_IMPL_T_EXT (1, (reservoir_simulator ), 1, (bs_node), "reservoir_simulator_fi", "Reservoir simulator fi", "Reservoir simulator float", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (reservoir_simulator ), 1, (bs_node), "reservoir_simulator_di", "Reservoir simulator di", "Reservoir simulator double", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (reservoir_simulator ), 1, (bs_node), "reservoir_simulator_mixi", "Reservoir simulator mixi", "Reservoir simulator mix", false); + + + + bool + reservoir_simulator_register_types (const plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, reservoir_simulator::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, reservoir_simulator::bs_type ()); BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, reservoir_simulator::bs_type ()); BS_ASSERT (res); + + return res; + } +} diff --git a/bs_bos_core/src/results_hdf5_writer.cpp b/bs_bos_core/src/results_hdf5_writer.cpp new file mode 100644 index 0000000..3918e47 --- /dev/null +++ b/bs_bos_core/src/results_hdf5_writer.cpp @@ -0,0 +1,308 @@ +/** + * \file fip_results_hdf5_writer.cpp + * \brief + * \author Sergey Miryanov + * \date 25.08.2009 + * */ +#include "stdafx.h" +#include "results_hdf5_writer.h" + +#ifdef _HDF5 + +namespace blue_sky + { + namespace hdf5 + { + + void + write_fip_results (const bs_hdf5_storage &hdf5, smart_ptr &fres) + { + if (!fres) + { + BOSWARN (section::save_data, level::warning) << "Fip results storage is null" << bs_end; + return ; + } + + hid_t group_fip = hdf5.begin_object ("fip"); + + fip_results_storage::fip_type::iterator iter, e; + for (iter = fres->fip.begin (), e = fres->fip.end (); iter != e; ++iter) + { + char group_name[100]; + sprintf (group_name, "%d", (*iter).first); + + // group for fip: check if exist, then open, create else + hid_t group = hdf5.begin_object (group_fip, group_name); + + // write data for the current fip_results + int dates_size = (int) iter->second.dates.size(); + if (dates_size > 0) + { + detail::add_dates (hdf5, group, iter->second.dates); + detail::add_params (hdf5, group, "d_params", iter->second.d_params, dates_size); + } + H5Gclose (group); + } + + H5Gclose (group_fip); + } + + void + write_well_results (const bs_hdf5_storage &hdf5, smart_ptr &wres, bool write_conn_data) + { + if (!wres) + { + BOSWARN (section::save_data, level::warning) << "Well results storage is null" << bs_end; + return ; + } + + hid_t group_wells, group_well; + hid_t group_connections, group_connection; + +#ifdef _MPI + //MPI: each process writes wells/conns to own file + file = &indiv_file; + group_wells = *file; +#else + // check if exist, then open, create else + group_wells = hdf5.begin_object ("wells"); +#endif + well_results_storage::wells_type::iterator iter, e; + for (iter = wres->wells.begin(), e = wres->wells.end(); iter != e; ++iter) + { +#ifdef _MPI + // in mpi decomposition we operate with global mesh in each proc + // therefore all wells are present in each proc + // but because other processor's domains are inactive + // connections of wells, which are in those domains not exists + // for writing only own wells we use [well.connections.size() > 0] condition + // but own wells with no connections will be skipped too :( + // we also send param i_need_write to methods for writing connections, + // but it's not neccessary, because loop will be empty ;) + if (!iter->second.connections.size()) + { + continue; + } +#endif + + group_well = hdf5.begin_object (group_wells, iter->first); + + // write well's group name + hdf5.write_string_to_hdf5 (group_well, "group", iter->second.group); + + int dates_size = (int) iter->second.dates.size(); + if (dates_size > 0) + { + detail::add_dates (hdf5, group_well, iter->second.dates); + detail::add_params (hdf5, group_well, "d_params", iter->second.d_params, dates_size); + detail::add_params (hdf5, group_well, "i_params", iter->second.i_params, dates_size); + + iter->second.clear (); + } + + // write connections data + if (write_conn_data) + { + // group for connection: check if exist, then open, create else + group_connections = hdf5.begin_object (group_well, "connections"); + + // write connections + char connection_name[100]; + well_results::conn_type::iterator iter_conn; + for (iter_conn = iter->second.connections.begin(); iter_conn != iter->second.connections.end(); ++iter_conn) + { + // create group for connection + sprintf (connection_name, "%d", iter_conn->first); + + // group for connection: check if exist, then open, create else + group_connection = hdf5.begin_object (group_connections, connection_name); + + int cdates_size = (int) iter_conn->second.dates.size(); + if (cdates_size > 0) + { + detail::add_dates (hdf5, group_connection, iter_conn->second.dates); + detail::add_params (hdf5, group_connection, "d_params", iter_conn->second.d_params, cdates_size); + detail::add_params (hdf5, group_connection, "i_params", iter_conn->second.i_params, cdates_size); + + iter_conn->second.clear (); + } + H5Gclose (group_connection); + } // conn loop + } // if (write_conn_data) + H5Gclose (group_well); + }//wells loop +#ifndef _MPI + H5Gclose (group_wells); +#endif + } + + template + void write_mesh_to_hdf5 (const smart_ptr &hdf5, const smart_ptr , true> &mesh) + { + const int INITIAL_DATA_SIZE = 5; + int values[INITIAL_DATA_SIZE]; + + typename rs_smesh_iface::index_point3d_t dims = mesh->get_dimens (); + + values[0] = dims[0]; + values[1] = dims[1]; + values[2] = dims[2]; + values[3] = mesh->get_n_active_elements (); + values[4] = mesh->get_n_active_elements ();//mesh->n_planes + + hdf5->write_array ("/mesh","initial_data", values, 5); + hdf5->write_array ("/mesh","original_elements", &(mesh->get_ext_to_int())[0], (int)mesh->get_ext_to_int().size()); + hdf5->write_array ("/mesh","original_planes", &(mesh->get_ext_to_int())[0], (int)mesh->get_ext_to_int().size());//TODO + } + + namespace detail + { + + template + void + add_dates (const bs_hdf5_storage &hdf5, const hid_t &hid, const dates_t &dates) + { + hid_t dataset; + if (!hdf5.is_object_exists (hid, "dates")) + { + // creating dataset_dates + hsize_t dims[] = {0}; + hsize_t dims_max[] = {H5S_UNLIMITED}; + + hid_t plist = H5Pcreate(H5P_DATASET_CREATE); + hid_t dataspace = H5Screate_simple(1, dims, dims_max); + + // set the dataset to be chunked + hsize_t chunk_dims = 1; + H5Pset_chunk(plist, 1, &chunk_dims); + + dataset = H5Dcreate(hid, "dates", get_hdf5_type (dates), dataspace, plist); + H5Pclose(plist); + H5Sclose(dataspace); + } + else + { + dataset = hdf5.open_dataset (hid, "dates"); + } + + // determine new dims of dataset_dates and extend it + hsize_t dims_old; + hsize_t dims_memory = dates.size(); + + hid_t fspace = H5Dget_space(dataset); + H5Sget_simple_extent_dims(fspace, &dims_old, NULL); + hsize_t dims_new = dims_old + dims_memory; + H5Dextend(dataset, &dims_new); + + // creating dataspaces + hid_t mspace = H5Screate_simple(1, &dims_memory, NULL); + fspace = H5Dget_space(dataset); + + hsize_t count = dims_memory; + hsize_t start = dims_old; + H5Sselect_hyperslab(fspace, H5S_SELECT_SET, &start, NULL, &count, NULL); + + // writing + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + htri_t status = H5Dwrite(dataset, get_hdf5_type (dates), mspace, fspace, plist, &dates[0]); + status; + H5Pclose(plist); + + H5Sclose(mspace); + H5Sclose(fspace); + H5Dclose(dataset); + } + + template + void + add_params (const bs_hdf5_storage &hdf5, const hid_t &hid, const std::string &name, const params_t ¶ms, size_t size) + { + hid_t dataset; + if (!hdf5.is_object_exists (hid, name)) + { + // creating dataset_d_params + hsize_t dims[] = {params.size(), 0}; + hsize_t dims_max[] = {params.size(), H5S_UNLIMITED}; + hid_t dataspace = H5Screate_simple(2, dims, dims_max); + + // set the dataset to be chunked + hid_t plist = H5Pcreate(H5P_DATASET_CREATE); + hsize_t chunk_dims[] = {params.size(), 1}; + H5Pset_chunk(plist, 2, chunk_dims); + dataset = H5Dcreate(hid, name.c_str (), get_hdf5_type (), dataspace, plist); + H5Pclose(plist); + H5Sclose(dataspace); + } + else + { + dataset = hdf5.open_dataset (hid, name.c_str ()); + } + + // determine new dims of dataset_d_params and extend it + hsize_t dims_old[2] = + { + 0 + }; + hsize_t dims_memory[] = + { + params.size() + }; + + hid_t fspace = H5Dget_space(dataset); + H5Sget_simple_extent_dims(fspace, dims_old, NULL); + H5Sclose(fspace); + + hsize_t dims_new[] = + { + params.size(), dims_old[1] + size + }; + + H5Dextend(dataset, dims_new); + + // creating dataspaces + hid_t mspace = H5Screate_simple(1, dims_memory, NULL); + fspace = H5Dget_space(dataset); + hsize_t count[] = + { + params.size(), 1 + }; + + // writing + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + typename params_t::value_type buffer; + buffer.resize(params.size()); + + for (size_t i = 0; i < size; i++) + { + for (size_t j = 0; j < params.size(); j++) + { + typename params_t::value_type::value_type b = 0; + if (params[j].size () > i) + b = params[j][i]; + + buffer[j] = b; + } + + hsize_t start[2] = {0, dims_old[1] + i}; + H5Sselect_hyperslab(fspace, H5S_SELECT_SET, start, NULL, count, NULL); + htri_t status = H5Dwrite(dataset, get_hdf5_type (), mspace, fspace, plist, &buffer[0]); + status; + } + + H5Pclose(plist); + H5Sclose(mspace); + H5Sclose(fspace); + H5Dclose(dataset); + } + + } // namespace detail + + template void write_mesh_to_hdf5 (const smart_ptr &hdf5, const smart_ptr , true> &mesh); + template void write_mesh_to_hdf5 (const smart_ptr &hdf5, const smart_ptr , true> &mesh); + template void write_mesh_to_hdf5 (const smart_ptr &hdf5, const smart_ptr , true> &mesh); + + } // namespace hdf5 +} // namespace blue_sky + +#endif //#ifdef _HDF5 + diff --git a/bs_bos_core/src/results_storage_hdf5_tools.h b/bs_bos_core/src/results_storage_hdf5_tools.h new file mode 100644 index 0000000..67836ba --- /dev/null +++ b/bs_bos_core/src/results_storage_hdf5_tools.h @@ -0,0 +1,183 @@ +/** + * \file results_storage_hdf5_tools.h + * \brief + * \author Sergey Miryanov + * \date 25.08.2009 + * */ +#ifndef BS_BOS_CORE_RESULTS_STORAGE_HDF5_TOOLS_H_ +#define BS_BOS_CORE_RESULTS_STORAGE_HDF5_TOOLS_H_ + +#ifdef _HDF5 + +namespace blue_sky { +namespace hdf5 { +namespace detail { + + template + inline void + add_dates (bs_hdf5_storage &hdf5, const hid_t &hid, const dates_t &dates) + { + hid_t dataset; + if (!hdf5.is_object_exists (hid, "dates")) + { + // creating dataset_dates + hsize_t dims[] = {0}; + hsize_t dims_max[] = {H5S_UNLIMITED}; + + hid_t plist = H5Pcreate(H5P_DATASET_CREATE); + hid_t dataspace = H5Screate_simple(1, dims, dims_max); + + // set the dataset to be chunked + hsize_t chunk_dims = 1; + H5Pset_chunk(plist, 1, &chunk_dims); + + dataset = H5Dcreate(hid, "dates", H5T_NATIVE_DOUBLE, dataspace, plist); + H5Pclose(plist); + H5Sclose(dataspace); + } + else + { + dataset = hdf5.open_dataset (hid, "dates"); + } + + // determine new dims of dataset_dates and extend it + hsize_t dims_old; + hsize_t dims_memory = dates.size(); + + hid_t fspace = H5Dget_space(dataset); + H5Sget_simple_extent_dims(fspace, &dims_old, NULL); + hsize_t dims_new = dims_old + dims_memory; + H5Dextend(dataset, &dims_new); + + // creating dataspaces + hid_t mspace = H5Screate_simple(1, &dims_memory, NULL); + fspace = H5Dget_space(dataset); + + hsize_t count = dims_memory; + hsize_t start = dims_old; + H5Sselect_hyperslab(fspace, H5S_SELECT_SET, &start, NULL, &count, NULL); + + // writing + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + htri_t status = H5Dwrite(dataset, H5T_NATIVE_DOUBLE, mspace, fspace, plist, &dates[0]); + H5Pclose(plist); + + H5Sclose(mspace); + H5Sclose(fspace); + H5Dclose(dataset); + } + + template + inline void + add_params (bs_hdf5_storage &hdf5, const hid_t &hid, const std::string &name, const params_t ¶ms, size_t size) + { + hid_t dataset; + if (!hdf5.is_object_exists (hid, name)) + { + // creating dataset_d_params + hsize_t dims[] = {params.size(), 0}; + hsize_t dims_max[] = {params.size(), H5S_UNLIMITED}; + hid_t dataspace = H5Screate_simple(2, dims, dims_max); + + // set the dataset to be chunked + hid_t plist = H5Pcreate(H5P_DATASET_CREATE); + hsize_t chunk_dims[] = {params.size(), 1}; + H5Pset_chunk(plist, 2, chunk_dims); + dataset = H5Dcreate(hid, name.c_str (), get_hdf5_type (), dataspace, plist); + H5Pclose(plist); + H5Sclose(dataspace); + } + else + { + dataset = hdf5.open_dataset (hid, name.c_str ()); + } + + // determine new dims of dataset_d_params and extend it + hsize_t dims_old[2] = {0}; + hsize_t dims_memory[] = {params.size()}; + + hid_t fspace = H5Dget_space(dataset); + H5Sget_simple_extent_dims(fspace, dims_old, NULL); + H5Sclose(fspace); + + hsize_t dims_new[] = + { + params.size() + , dims_old[1] + size + }; + + H5Dextend(dataset, dims_new); + + // creating dataspaces + hid_t mspace = H5Screate_simple(1, dims_memory, NULL); + fspace = H5Dget_space(dataset); + hsize_t count[] = + { + params.size(), 1 + }; + + // writing + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + typename params_t::value_type buffer; + buffer.resize(params.size()); + + for (size_t i = 0; i < size; i++) + { + for (size_t j = 0; j < params.size(); j++) + { + typename params_t::value_type::value_type b = 0; + if (params[j].size () > i) + b = params[j][i]; + + buffer[j] = b; + } + + hsize_t start[2] = {0, dims_old[1] + i}; + H5Sselect_hyperslab(fspace, H5S_SELECT_SET, start, NULL, count, NULL); + htri_t status = H5Dwrite(dataset, get_hdf5_type (), mspace, fspace, plist, &buffer[0]); + } + + H5Pclose(plist); + H5Sclose(mspace); + H5Sclose(fspace); + H5Dclose(dataset); + } + + inline void + create_group (bs_hdf5_storage &hdf5, const hid_t &hid, const std::string &name, const std::string &sub_name) + { + // write data for the current well + hid_t dataspace_group = H5Screate(H5S_SCALAR); + hid_t datatype_group = H5Tcopy (H5T_C_S1); // create string of given length + htri_t status = H5Tset_size (datatype_group, sub_name.length()); + if (status < 0) + { + bs_throw_exception (boost::format ("Can't set size for datatype of group, sub_name [%s]") % sub_name); + } + hid_t dataset_group = H5Dcreate(hid, name.c_str (), datatype_group, dataspace_group, H5P_DEFAULT); + if (dataset_group >= 0)//succesfully created + { + hid_t fspace = H5Dget_space(dataset_group); + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + status = H5Dwrite(dataset_group, datatype_group, dataspace_group, fspace, plist, &sub_name[0]); + + H5Pclose(plist); + H5Sclose(fspace); + H5Dclose(dataset_group); + } + else + { + bs_throw_exception ("Can't create dataset_group"); + } + + H5Tclose(datatype_group); + } + +} // namespace detail +} // namespace hdf5 +} // namespace blue_sky + +#endif // #ifdef _HDF5 + +#endif // #ifdef BS_BOS_CORE_RESULTS_STORAGE_HDF5_TOOLS_H_ + diff --git a/bs_bos_core/src/stdafx.cpp b/bs_bos_core/src/stdafx.cpp new file mode 100644 index 0000000..1577c4e --- /dev/null +++ b/bs_bos_core/src/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.h" \ No newline at end of file diff --git a/bs_bos_core/src/timers.cpp b/bs_bos_core/src/timers.cpp new file mode 100644 index 0000000..1c0c387 --- /dev/null +++ b/bs_bos_core/src/timers.cpp @@ -0,0 +1,12 @@ +/** + * \file timers.cpp + * \brief + * \author Sergey Miryanov + * \date 24.03.2009 + * */ +#include "stdafx.h" + +double csr_calc_lin_comb_timer = 0; +double csr_matrix_vector_product_timer = 0; +double gmres_setup_timer = 0; + diff --git a/bs_bos_core/src/two_stage_preconditioner.cpp b/bs_bos_core/src/two_stage_preconditioner.cpp new file mode 100644 index 0000000..9f5f219 --- /dev/null +++ b/bs_bos_core/src/two_stage_preconditioner.cpp @@ -0,0 +1,144 @@ +/*! + * \file two_stage_preconditioner.cpp + * \brief implementation of tow stage preconditioner + * \author Borschuk Oleg + * \date 2006-08-04 + */ +#include "stdafx.h" +#include "two_stage_preconditioner.h" +#include "solve_helper.h" + +namespace blue_sky + { + //! constructor + template + two_stage_preconditioner::two_stage_preconditioner (bs_type_ctor_param param) + : linear_solver_base (param) + { + //sp_link prec_2_link = bs_link::create (bs_node::create_node (), "prec_2"); + + //bs_node::insert (prec_2_link, false); + } + + //! copy constructor + template + two_stage_preconditioner::two_stage_preconditioner (const two_stage_preconditioner &prec) + : bs_refcounter (prec), linear_solver_base (prec) + { + if (this != &prec) + *this = prec; + } + + //! destructor + template + two_stage_preconditioner::~two_stage_preconditioner () + { + } + + template int + two_stage_preconditioner::solve(matrix_t *matrix, rhs_item_array_t &rhs, item_array_t &sol) + { + return templ_solve (matrix, rhs, sol); + } + + template int + two_stage_preconditioner::solve_prec(matrix_t *matrix, item_array_t &rhs, item_array_t &sol) + { + return templ_solve (matrix, rhs, sol); + } + + + //! solve preconditioner + template template int + two_stage_preconditioner::templ_solve (matrix_t *matrix, rhs_t &rhs, item_array_t &sol) + { + BS_ASSERT (matrix); + BS_ASSERT (rhs.size ()) (rhs.size ()); + BS_ASSERT (sol.size ()) (sol.size ()); + BS_ASSERT (rhs.size () == sol.size ()) (rhs.size ()) (sol.size ()); + BS_ASSERT (base_t::prec); + BS_ASSERT (prec_2); + + index_t n = matrix->n_rows * matrix->n_block_size; + BS_ASSERT ((size_t)n == rhs.size ()) (n) (rhs.size ()); + + if (solve_helper (&(*base_t::prec), matrix, rhs, sol)) + { + bs_throw_exception ("TWO_STAGE: PREC 1 failed"); + } + + if ((index_t)r_array.size () != n) + { + r_array.assign (n, 0); + w_array.assign (n, 0); + } + BS_ASSERT (r_array.size () == w_array.size ()) (r_array.size ()) (w_array.size ()); + + //r_array = rhs - sol - new rhs - step 5 in Olegs book + matrix->calc_lin_comb (-1.0, 1.0, sol, rhs, r_array); + + // solve system with ILU - step 6 + if (prec_2->solve_prec (matrix, r_array, w_array)) + { + bs_throw_exception ("TWO_STAGE: PREC 2 failed"); + } + + // Then we make a correction of our solution x = x + w - step 7 + index_t i = 0; + index_t n2 = n - (n % 4); + for (; i < n2; i+=4) + { + sol[i] += w_array[i]; + sol[i+1] += w_array[i+1]; + sol[i+2] += w_array[i+2]; + sol[i+3] += w_array[i+3]; + } + + for (; i < n; i++) + { + sol[i] += w_array[i]; + } + + return 0; + } + + //! setup preconditioner + template int + two_stage_preconditioner::setup (matrix_t *matrix) + { + if (!matrix) + { + bs_throw_exception ("TWO_STAGE: Passed matrix is null"); + } + + BS_ASSERT (base_t::prec); + BS_ASSERT (prec_2); + + base_t::prec->setup (matrix); + prec_2->setup (matrix); + + return 0; + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF(two_stage_preconditioner, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF(two_stage_preconditioner, (class)); + + BLUE_SKY_TYPE_IMPL_T_EXT(1, (two_stage_preconditioner) , 1, (linear_solver_base), "two_stage_prec_seq_fi", "Two stage Preconditioner", "Two stage Preconditioner", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (two_stage_preconditioner) , 1, (linear_solver_base), "two_stage_prec_seq_di", "Two stage Preconditioner", "Two stage Preconditioner", false); + BLUE_SKY_TYPE_IMPL_T_EXT(1, (two_stage_preconditioner) , 1, (linear_solver_base), "two_stage_prec_seq_mixi", "Two stage Preconditioner", "Two stage Preconditioner", false); + + bool two_stage_prec_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, two_stage_preconditioner::bs_type ()); + res &= BS_KERNEL.register_type (pd, two_stage_preconditioner::bs_type ()); + res &= BS_KERNEL.register_type (pd, two_stage_preconditioner::bs_type ()); + + return res; + } + + + +} // namespace blue_sky diff --git a/bs_bos_core/src/well_connection.cpp b/bs_bos_core/src/well_connection.cpp new file mode 100644 index 0000000..4eb1f47 --- /dev/null +++ b/bs_bos_core/src/well_connection.cpp @@ -0,0 +1,350 @@ +/** + * \file well_connection.cpp + * \brief impl of wells::connection + * \author Sergey Miryanov + * \date 15.07.2008 + * */ +#include "stdafx.h" + +#include "calc_well.h" +#include "wells_compute_connection_factors.h" +#include "well_connection.h" +#include "calc_model.h" + +#define HORIZ_WELL_MODEL_PEACEMAN 1 + +namespace blue_sky + { + namespace wells + { + + /////////////////////////////////////////////////////////////////////////// + connection_direction_type + connection_direction_cast (const std::string &str) + { + if (str == "X" || str == "x") + return direction_x; + else if (str == "Y" || str == "y") + return direction_y; + else if (str == "Z" || str == "z") + return direction_z; + else if (str == "") + return direction_z; + else + { + BS_ASSERT (false && "Unsupported value of direction") (str); + throw bs_exception ("connection_direction_cast", "Unsupported value of direction"); + } + } + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + connection_status_type + connection_status_cast (const std::string &str) + { + if (str == "OPEN") + return connection_open; + else if (str == "SHUT") + return connection_shut; + else if (str == "") + return connection_shut; + else + { + BS_ASSERT (false && "Unsupported value of connection status") (str); + throw bs_exception ("connection_status_cast", "Unsupported value of connection"); + } + } + /////////////////////////////////////////////////////////////////////////// + + template + connection::connection (blue_sky::bs_type_ctor_param param /* = NULL */) + : n_block_ (-1) + { + } + template + connection::connection (const connection_t &c) + : bs_refcounter (c), objbase (c) + { + *this = c; + } + + template + array_ext + connection::get_rw_value () + { + return array_ext (0, 0); + } + template + array_ext + connection::get_wr_value () + { + return array_ext (0, 0); + } + template + array_ext + connection::get_rr_value () + { + return array_ext (0, 0); + } + template + array_ext + connection::get_ps_value () + { + return array_ext (0, 0); + } + template + array_ext + connection::get_rate_value () + { + return array_ext (0, 0); + } + + template + typename connection::item_t + connection::get_cur_bhp () const + { + return cur_bhp; + } + template + typename connection::item_t + connection::get_density () const + { + return density; + } + template + typename connection::item_t + connection::get_connection_depth () const + { + return connection_depth; + } + template + typename connection::item_t + connection::get_bulkp () const + { + return bulkp; + } + + ////////////////////////////////////////////////////////////////////////// + + template + void + connection::compute_factors (const physical_constants &internal_contstants, + const sp_params_t ¶ms, + const sp_mesh_iface_t &mesh, + const item_array_t &perm, + const item_array_t &ntg, + bool ro_calc_flag) + { + BS_ASSERT (n_block_ >= 0) (n_block_); + if (n_block_ < 0) + throw bs_exception ("connection::compute_factors_by_peaceman_model", "Invalid block number"); + + using namespace wells::compute_factors; + + if (HORIZ_WELL_MODEL_PEACEMAN || dir_ == direction_z /* || !wfrictn_keyword_active*/) + { + peaceman_model::compute (*this, internal_contstants, params, mesh, perm, ntg, ro_calc_flag); + } + //else + // baby_odeh_model::compute (*this, internal_contstants, d1, d2, d3, perm1, perm2, perm3, ntg, ro_calc_flag); + } + + template + void + connection::mul_perm_mult (item_t mult) + { + //BOSOUT (section::wells, level::debug) + // << "WPIMULT: " << (*it)->n_block () + // << " before: " << (*it)->mult () + // << " after: " << (*it)->mult () * perm_mult + // << bs_end; + + mult_ *= mult; + } + template + void + connection::set_half_length (item_t half_length) + { + fracture_half_length_ = half_length; + } + template + void + connection::set_theta (item_t angle) + { + fracture_angle_ = angle; + } + template + void + connection::set_skin (item_t skin) + { + skin_ = skin; + } + template + void + connection::set_status (connection_status_type connection_status) + { + status_ = connection_status; + } + template + void + connection::set_factor (item_t factor) + { + fact_ = factor; + } + template + void + connection::set_diameter (item_t diameter) + { + diam_ = diameter; + } + template + void + connection::set_Kh (item_t kh) + { + kh_ = kh; + } + template + void + connection::set_direction (connection_direction_type direction) + { + dir_ = direction; + } + template + void + connection::set_coord (index_t i, index_t j, index_t k, index_t nb) + { + BS_ASSERT (i >= 0) (i); + BS_ASSERT (j >= 0) (j); + BS_ASSERT (k >= 0) (k); + BS_ASSERT (nb >= 0) (nb); + + i_coord_ = i; + j_coord_ = j; + k_coord_ = k; + n_block_ = nb; + } + template + void + connection::set_seg_number (const index_t &seg) + { + iseg_ = seg; + } + + template + typename connection::index_t + connection::n_block () const + { + return n_block_; + } + template + typename connection::index_t + connection::i_coord () const + { + return i_coord_; + } + template + typename connection::index_t + connection::j_coord () const + { + return j_coord_; + } + template + typename connection::index_t + connection::k_coord () const + { + return k_coord_; + } + template + typename connection::item_t + connection::mult () const + { + return mult_; + } + + template + typename connection ::item_t + connection ::get_head_term () const + { + return head_term; + } + template + typename connection ::index_t + connection ::get_seg_number () const + { + return iseg_; + } + + template + typename strategy_t::item_t + connection::get_fact () const + { + return fact_; + } + + template + void + connection::set_cur_bhp (item_t bhp) + { + cur_bhp = bhp; + } + template + void + connection::set_bulkp (item_t b) + { + bulkp = b; + } + template + void + connection::set_rate (item_t rate) + { + BS_ASSERT (false && "NOT IMPL YET"); + } + template + void + connection::set_head_term (item_t term) + { + head_term = term; + } + template + void + connection ::set_mult (item_t mult) + { + mult_ = mult; + } + + template + bool + connection ::is_shut () const + { + return status_ == connection_shut; + } + + template + void + connection::clear_data () + { + rate_ = 0; + rate_rc_ = 0; + } + + template + void + connection::set_connection_depth (const sp_mesh_iface_t &mesh) + { + BS_ASSERT (i_coord_ != -1 && j_coord_ != -1 && k_coord_ != -1) (i_coord_) (j_coord_) (k_coord_); + BS_ASSERT (n_block_ != -1) (n_block_); + connection_depth = mesh->get_element_depth (n_block_); + //BOSOUT (section::wells, level::debug) << "[xxx : " << n_block_ << "] set_connection_depth: " << (index_t)i_coord_ << " " << (index_t)j_coord_ << " " << (index_t)k_coord_ + // << " = " << connection_depth + // << bs_end; + } + + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (connection, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (connection, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (connection ), 1, (objbase), "well_connection_seq_fi", "BOS_Core well connection class", "BOS_Core well connection class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (connection ), 1, (objbase), "well_connection_seq_di", "BOS_Core well connection class", "BOS_Core well connection class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (connection ), 1, (objbase), "well_connection_seq_mixi", "BOS_Core well connection class", "BOS_Core well connection class", false) + + } // namespace wells +} // namespace blue_sky diff --git a/bs_bos_core/src/well_controller.cpp b/bs_bos_core/src/well_controller.cpp new file mode 100644 index 0000000..78bc76b --- /dev/null +++ b/bs_bos_core/src/well_controller.cpp @@ -0,0 +1,585 @@ +/** + * \file well_controller.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 16.07.2008 + * */ +#include "stdafx.h" +#include "well_controller.h" +#include "calc_well.h" +#include "calc_model.h" +#include "well_connection.h" + +#include "well_rate_control.h" + +#include "reservoir.h" +#include "facility_manager.h" +#include "default_well_rate_control_factory.h" +#define WELL_ACCUMULATION_TERM 1e-6 + +namespace blue_sky + { + namespace wells + { + + /////////////////////////////////////////////////////////////////////////// + bool + is_oil_rate_value (rate_value_type type) + { + return (type & oil_rate_value) == oil_rate_value; + } + bool + is_water_rate_value (rate_value_type type) + { + return (type & water_rate_value) == water_rate_value; + } + bool + is_gas_rate_value (rate_value_type type) + { + return (type & gas_rate_value) == gas_rate_value; + } + bool + is_liquid_rate_value (rate_value_type type) + { + return (type & liquid_rate_value) == liquid_rate_value; + } + rate_value_type + rate_value_cast (const std::string &str) + { + if (str == "ORAT") + return oil_rate_value; + else if (str == "WRAT") + return water_rate_value; + else if (str == "GRAT") + return gas_rate_value; + else if (str == "BHP") + return bhp_value; + else if (str == "LRAT") + return liquid_rate_value; + else if (str == "RESV") + { + BS_ASSERT (false && "Unsupported rate_value type") (str); + throw bs_exception ("rate_value_cast", "Unsupported rate_value type"); + } + else if (str == "THP") + { + BS_ASSERT (false && "Unsupported rate_value type") (str); + throw bs_exception ("rate_value_cast", "Unsupported rate_value type"); + } + else + { + BS_ASSERT (false && "Unsupported rate_value type") (str); + throw bs_exception ("rate_value_cast", "Unsupported rate_value type"); + } + } + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + injection_type + injection_type_cast (const std::string &str) + { + if (str == "WATER") + return injection_water; + else if (str == "GAS") + return injection_gas; + else if (str == "OIL") + return injection_oil; + else if (str == "NONE") + return injection_none; + else + { + BS_ASSERT (false && "Unsupported injection type") (str); + throw bs_exception ("injection_type_cast", "Unsupported injection type"); + } + } + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + + template + typename well_controller::sp_rate_control_t well_controller::dummy_control_ = 0; + + template + well_controller::well_controller (bs_type_ctor_param param /* = NULL */) + : bhp_ (0) + , bhp_history_ (0) + , injection_type_ (injection_none) + { + current_control_ = 0; + } + + template + well_controller::well_controller (const well_controller &controller) + : bs_refcounter (controller), objbase (controller) + { + if (this != &controller) + { + *this = controller; + //this_ = this; + } + } + + template + const typename well_controller::rate_data_t & + well_controller::rate () const + { + return rate_; + } + template + const typename well_controller::item_t & + well_controller::bhp () const + { + return bhp_; + } + template + const typename well_controller::item_t & + well_controller::bhp_history () const + { + return bhp_history_; + } + /////////////////////////////////////////////////////////////////////////// + template + void + well_controller::add_bhp_control (const sp_rate_control_t &control) + { + BS_ASSERT (control); + bhp_control_ = control; + } + template + void + well_controller::add_rate_control (const sp_rate_control_t &control) + { + BS_ASSERT (control); + rate_control_ = control; + } + + template + void + well_controller::set_main_control (const sp_well_t &well, rate_control_type type) + { + current_control_ = 0; + BS_ASSERT (bhp_control_); + BS_ASSERT (rate_control_); + + if (is_bhp_control (type)) + { + BOSOUT (section::wells, level::low) << "[" << well->name () << "] set control to bhp" << bs_end; + + current_control_ = bhp_control_; + well->set_bhp (bhp_); + } + else if (is_rate_control (type)) + { + BOSOUT (section::wells, level::low) << "[" << well->name () << "] set control to rate" << bs_end; + + current_control_ = rate_control_; + } + + if (!current_control_) + { + bs_throw_exception ("Current control is null"); + } + } + + /////////////////////////////////////////////////////////////////////////// + template + void + well_controller ::set_bhp (item_t value) + { + bhp_ = value; + } + template + void + well_controller ::set_bhp_history (item_t value) + { + bhp_history_ = value; + } + template + void + well_controller ::clear_rate () + { + rate_ = 0; + } + template + void + well_controller::set_rate (rate_value_type type, item_t value) + { + if (!is_production ()) + { + BS_ASSERT (injection_type_ != injection_none); + + if (type == rate_value) + { + if (injection_type_ == injection_oil) + { + rate_.inj.oil = value; + rate_.inj.liquid = rate_.inj.oil + rate_.inj.water; + } + else if (injection_type_ == injection_water) + { + rate_.inj.water = value; + rate_.inj.liquid = rate_.inj.oil + rate_.inj.water; + } + else if (injection_type_ == injection_gas) + { + rate_.inj.gas = value; + } + } + else if (type == liquid_inner_rate_value) + { + rate_.liquid_inner = value; + } + else + { + throw bs_exception ("well_controller::set_rate", "invalid control value type"); + } + } + else + { + switch (type) + { + case oil_rate_value: + rate_.prod.oil = value; + rate_.prod.liquid = rate_.prod.oil + rate_.prod.water; + break; + case water_rate_value: + rate_.prod.water = value; + rate_.prod.liquid = rate_.prod.oil + rate_.prod.water; + break; + case gas_rate_value: + rate_.prod.gas = value; + break; + case liquid_rate_value: + rate_.prod.liquid = value; + break; + case liquid_inner_rate_value: + rate_.liquid_inner = value; + break; + default: + throw bs_exception ("well_controller::set_rate", "invalid control value type"); + } + } + } + + template + void + well_controller::save_control () + { + BS_ASSERT (current_control_); + saved_control_ = current_control_; + } + template + bool + well_controller::restore_control () + { + BS_ASSERT (current_control_); + bool flag = current_control_ != saved_control_; + current_control_ = saved_control_; + + return flag; + } + template + void + well_controller::save_niter_control () + { + BS_ASSERT (current_control_); + saved_niter_control_ = current_control_; + } + template + bool + well_controller::restore_niter_control () + { + BS_ASSERT (current_control_); + bool flag = current_control_ != saved_niter_control_; + current_control_ = saved_niter_control_; + + return flag; + } + + /////////////////////////////////////////////////////////////////////////// + template + bool + well_controller::check (sp_well_t &well) + { + BS_ASSERT (current_control_); + BS_ASSERT (rate_control_); + BS_ASSERT (bhp_control_); + + //BOSOUT (section::wells, level::low) << "[" << well->name () << "] " << "limit_bhp: " << bhp_ << "\twell_bhp: " << well->bhp () << bs_end; + //BOSOUT (section::wells, level::low) << "[" << well->name () << "] " << "limit_liquid: " << rate_.liquid << "\twell_liquid: " << -well->liquid_rate () << bs_end; + //BOSOUT (section::wells, level::low) << "[" << well->name () << "] " << "limit_oil: " << rate_.oil << "\twell_oil: " << -well->oil_rate () << bs_end; + //BOSOUT (section::wells, level::low) << "[" << well->name () << "] " << "limit_water: " << rate_.water << "\twell_water: " << -well->water_rate () << bs_end; + //BOSOUT (section::wells, level::low) << "[" << well->name () << "] " << "limit_gas: " << rate_.gas << "\twell_gas: " << -well->gas_rate () << bs_end; + + if (current_control_ == rate_control_) + { + bool do_switch = false; + if (is_production ()) + { + do_switch = bhp_ > well->bhp (); + } + else + { + do_switch = bhp_ < well->bhp (); + } + + if (do_switch) + { + BOSOUT (section::wells, level::medium) << "[" << well->name () << "] switch from rate to bhp (is_prod: " << is_production() << ") " << bs_end; + + current_control_ = bhp_control_; + well->set_bhp (bhp_); + return true; + } + } + else if (current_control_ == bhp_control_) + { + rate_control_type control_type = rate_control_->get_control_type (); + bool do_switch = false; + + if (is_production ()) + { + switch (control_type) + { + case liquid_rate_control: + do_switch = rate_.prod.liquid < -well->rate ().prod.liquid; + break; + case oil_rate_control: + do_switch = rate_.prod.oil < -well->rate ().prod.oil; + break; + case water_rate_control: + do_switch = rate_.prod.water < -well->rate ().prod.water; + break; + case gas_rate_control: + do_switch = rate_.prod.gas < -well->rate ().prod.gas; + break; + default: + bs_throw_exception (boost::format ("control_type is unknown: %d") % control_type); + } + } + else + { + switch (injection_type_) + { + case injection_oil: + do_switch = rate_.inj.oil < well->rate ().inj.oil; + break; + case injection_water: + do_switch = rate_.inj.water < well->rate ().inj.water; + break; + case injection_gas: + do_switch = rate_.inj.gas < well->rate ().inj.gas; + break; + default: + throw bs_exception ("well_controller::check", "injection_type is unknown"); + } + } + + if (do_switch) + { + BOSOUT (section::wells, level::medium) << "[" << well->name () << "] switch from bhp to rate (is_prod: " << is_production() << ") " << bs_end; + + current_control_ = rate_control_; + //if (is_production ()) + // { + // well->bhp_ = bhp_ + 1; + // } + //else + // { + // well->bhp_ = bhp_ - 1; + // } + return true; + } + else + { + //return false; // in this case well should shutdown himself + } + } + + return false; + } + + ////////////////////////////////////////////////////////////////////////// + template + bool + well_controller::is_bhp () const + { + BS_ASSERT (current_control_); + return current_control_->is_bhp (); + } + template + bool + well_controller::is_rate () const + { + BS_ASSERT (current_control_); + return current_control_->is_rate (); + } + template + bool + well_controller::is_production () const + { + BS_ASSERT (current_control_); + return current_control_->is_production (); + } + + template + bool + well_controller ::is_valid_connection_bhp (item_t pressure, item_t bhp) const + { + item_t diff = pressure - bhp; + if (is_production ()) + return diff > 0; + else + return diff < 0; + } + + + template + void + well_controller::switch_to_bhp (sp_well_t &well) + { + BS_ASSERT (current_control_); + BS_ASSERT (bhp_control_); + + BOSOUT (section::wells, level::medium) << "[" << well->name () << "] switch to bhp" << bs_end; + BOSOUT (section::wells, level::low) << "\tlimit_bhp: " << bhp_ << "\twell_bhp: " << well->bhp () << bs_end; + + well->set_bhp (bhp_); + current_control_ = bhp_control_; + } + + template + const injection_type & + well_controller::injection () const + { + return injection_type_; + } + template + void + well_controller::set_injection_type (injection_type type) + { + injection_type_ = type; + } + + template + void + well_controller ::calc_rate (const sp_calc_model_t &calc_model, sp_well_t &well, sp_jmatrix_t &jmatrix) const + { + BS_ASSERT (current_control_); + const smart_ptr sp_this (this); + current_control_->compute_rate (calc_model, jmatrix, well, sp_this); + } + template + void + well_controller ::calc_derivs (const sp_calc_model_t &calc_model, sp_well_t &well, sp_jmatrix_t &jmatrix) const + { + BS_ASSERT (current_control_); + const smart_ptr sp_this (this); + current_control_->compute_derivs (calc_model, jmatrix, well, sp_this); + } + + template + rate_control_type + well_controller ::get_control_type () const + { + BS_ASSERT (current_control_); + return current_control_->get_control_type (); + } + + ////////////////////////////////////////////////////////////////////////// + + template + well_controller_factory::well_controller_factory (bs_type_ctor_param param /* = NULL */) + : well_rate_control_factory_ (BS_KERNEL.create_object (default_well_rate_control_factory ::bs_type ())) + { + + } + template + well_controller_factory::well_controller_factory (const well_controller_factory &f) + : bs_refcounter (f), objbase (f) + { + *this = f; + } + + template + typename well_controller_factory::sp_well_controller_t + well_controller_factory::create_controller () const + { + return BS_KERNEL.create_object (well_controller_t::bs_type (), true); + } + + template + typename well_controller_factory::sp_rate_control_t + well_controller_factory::create_control (rate_control_type control_type, bool is_prod, const sp_calc_model_t &calc_model) const + { + sp_rate_control_t control = BS_KERNEL.create_object (well_rate_control_t::bs_type (), true); + if (!control) + { + bs_throw_exception ("Can't create well_rate_control"); + } + + control->set_is_bhp (is_bhp_control (control_type)); + control->set_is_prod (is_prod); + control->set_control_type (control_type); + control->set_impl (well_rate_control_factory_->create_control (control_type, is_bhp_control (control_type), is_prod, calc_model)); + + return control; + } + + template + void + well_controller_factory ::set_rate_control_factory (const sp_well_rate_control_factory_t &f) + { + well_rate_control_factory_ = f; + } + + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF (well_controller, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (well_controller, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_controller), 1, (objbase), "well_controller_seq_fi", "Base class for well controllers", "Base class for well controllers", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_controller), 1, (objbase), "well_controller_seq_di", "Base class for well controllers", "Base class for well controllers", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_controller), 1, (objbase), "well_controller_seq_mixi", "Base class for well controllers", "Base class for well controllers", false); + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (well_controller_factory, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (well_controller_factory, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_controller_factory), 1, (objbase), "well_controller_factory_seq_fi", "Base class for factory of well controllers", "Base class for factory of well controllers", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_controller_factory), 1, (objbase), "well_controller_factory_seq_di", "Base class for factory of well controllers", "Base class for factory of well controllers", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_controller_factory), 1, (objbase), "well_controller_factory_seq_mixi", "Base class for factory of well controllers", "Base class for factory of well controllers", false); + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + bool + well_controller_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, well_controller::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well_controller::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well_controller::bs_type ()); + BS_ASSERT (res); + + return res; + } + bool + well_controller_factory_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, well_controller_factory::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well_controller_factory::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well_controller_factory::bs_type ()); + BS_ASSERT (res); + + return res; + } + ////////////////////////////////////////////////////////////////////////// + + } // namespace wells +} // namespace blue_sky + diff --git a/bs_bos_core/src/well_event_apply_methods.cpp b/bs_bos_core/src/well_event_apply_methods.cpp new file mode 100644 index 0000000..509fdd3 --- /dev/null +++ b/bs_bos_core/src/well_event_apply_methods.cpp @@ -0,0 +1,597 @@ +/** + * \file well_event_apply_methods.cpp + * \brief impl of ::apply methods + * \author Sergey Miryanov + * \date 11.07.2008 + * */ +#include "stdafx.h" + +#include "reservoir.h" +#include "reservoir_simulator.h" +#include "well_events.h" +#include "calc_well.h" +#include "well_controller.h" +#include "well_limit_operation.h" +#include "well_connection.h" +#include "facility_manager.h" +#include "well_rate_control.h" + +#include "calc_model.h" + +namespace blue_sky + { + + +#define DECL_GET_WELL_EVENT_NAMES(event_name) \ + template \ + BS_API_PLUGIN std::string \ + event_name ::get_well_name () const \ + { \ + return main_params_->get_WELL_NAME ("WELL_NAME NOT SET"); \ + } \ + template \ + BS_API_PLUGIN std::string \ + event_name ::get_event_name () const \ + { \ + return BOOST_PP_STRINGIZE (event_name); \ + } + +#define DECL_GET_WELL_EVENT_NAME(event_name) \ + template \ + BS_API_PLUGIN std::string \ + event_name ::get_event_name () const \ + { \ + return BOOST_PP_STRINGIZE (event_name); \ + } + ////////////////////////////////////////////////////////////////////////// + template + void + WELSPECS_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &/*calc_model*/) const + { + const sp_top &locked (top); + // TODO: FIELD + std::string group_name = main_params_->get_WELL_GROUP_NAME (""); + std::string name = main_params_->get_WELL_NAME (""); + + BS_ASSERT (name.size ()); + + sp_well_t well = locked->get_well (group_name, name); + if (!well) + { + well = locked->create_well (group_name, name); + BS_ERROR (well, "apply_internal");// (group_name) (name); + } + + const sp_well_t &locked_well (well); + + BS_ASSERT (main_params_->get_I (0) && main_params_->get_J (0)) (main_params_->get_I (0)) (main_params_->get_J (0)); + + locked_well->set_coord (main_params_->get_I (), main_params_->get_J ()); + locked_well->set_bhp_depth (main_params_->get_BHP_DEPTH ()); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WELLCON_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &/*calc_model*/) const + { + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_GROUP_NAME (""), main_params_->get_WELL_NAME ("")); + if (!well) + { + well = locked->create_well (main_params_->get_WELL_GROUP_NAME (""), main_params_->get_WELL_NAME ("")); + if (!well) + { + bs_throw_exception (boost::format ("Can't create well (name: %s, group: %s)") % main_params_->get_WELL_NAME ("") % main_params_->get_WELL_GROUP_NAME ("")); + } + } + + bs_throw_exception ("NOT IMPL YET"); + + //const sp_well_t &locked_well (well); + //locked_well->set_coord (main_params_->get_I (0), main_params_->get_J (0)); + //locked_well->set_state (get_int_d (WELL_STATE)); + //locked_well->set_layer_interval (get_int_d (FIRST_LAYER), get_int_d (LAST_LAYER)); + //locked_well->set_diameter (get_float_d (WELL_DIAMETER)); + //locked_well->set_skin (main_params_->get_SKIN (0)); + //locked_well->set_Kh (get_float_d (KH)); + //locked_well->set_direction (get_int_d (DIRECTION)); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + COMPDAT_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const + { + const sp_top &locked (top); + const sp_smesh_iface_t struct_msh (msh, bs_dynamic_cast()); + BS_ASSERT (struct_msh); + + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + index_t i_coord = main_params_->get_I (0); + index_t j_coord = main_params_->get_J (0); + index_t first_layer = main_params_->get_FIRST_LAYER (0); + index_t last_layer = main_params_->get_LAST_LAYER (0); + BS_ASSERT (last_layer - first_layer >= 0) (last_layer) (first_layer); + + const sp_well_t &locked_well (well); + + using namespace wells; + connection_status_type perf_status = wells::connection_status_cast (main_params_->get_PERFORATION_STATUS ("")); + item_t perf_factor = main_params_->get_PERFORATION_FACTOR (0); + item_t well_diameter = main_params_->get_WELL_DIAMETER (0); + item_t kh = main_params_->get_KH (0); + item_t skin = main_params_->get_SKIN (0); + connection_direction_type dir = wells::connection_direction_cast (main_params_->get_DIRECTION ("")); + index_t seg_number = main_params_->get_SEG_NUMBER (0) - 1; + for (index_t k_coord = first_layer; k_coord != last_layer + 1; ++k_coord) + { + BS_ASSERT (i_coord > 0) (i_coord); + BS_ASSERT (j_coord > 0) (j_coord); + BS_ASSERT (k_coord > 0) (k_coord); + + index_t n_block = struct_msh->get_element_ijk_to_int (i_coord - 1, j_coord - 1, k_coord - 1); + BS_ASSERT (n_block >= 0) (i_coord) (j_coord) (k_coord); + + if (n_block < 0) + { + BOSOUT (section::schedule, level::warning) << boost::format ("COMPDAT: Connection for well %s in inactive cell [%d, %d, %d]") % well->name () % i_coord % j_coord % k_coord << bs_end; + continue; + } + else + { + BOSOUT (section::schedule, level::debug) << boost::format ("COMPDAT: Connection for well %s in cell [%d, %d, %d, %d]") % well->name () % i_coord % j_coord % k_coord % n_block << bs_end; + } + + sp_connection_t con = well->get_connection_map (n_block); + if (!con) + { + con = well->add_connection (i_coord - 1, j_coord - 1, k_coord - 1, n_block); + } + else + { + BOSOUT (section::schedule, level::debug) << boost::format ("COMPDAT: Connection for well %s in cell [%d, %d, %d, %d] will be set to [%d, %d, %d, %d]") + % well->name () % (con->i_coord () + 1) % (con->j_coord () + 1) % (con->k_coord () + 1) % con->n_block () + % i_coord % j_coord % k_coord % n_block + << bs_end; + } + + const sp_connection_t &locked_connection (con); + + locked_connection->set_status (perf_status); + locked_connection->set_factor (perf_factor); + locked_connection->set_diameter (well_diameter); + locked_connection->set_Kh (kh); + locked_connection->set_skin (skin); + locked_connection->set_direction (dir); + locked_connection->set_connection_depth (msh); + locked_connection->set_mult (1.0); + locked_connection->set_seg_number (seg_number); + } + + locked_well->check_shut (calc_model); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WCONPROD_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &calc_model) const + { + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + const sp_well_t &locked_well (well); + locked_well->set_state (well_state_cast (main_params_->get_WELL_STATE ("")), calc_model); + + sp_well_controller_t controller = well->get_controller (); + if (!controller) + controller = locked->create_well_controller (well); + + const sp_well_controller_t &locked_controller (controller); + BS_ASSERT (locked_controller); + + using namespace wells; + + locked_controller->set_bhp (main_params_->get_BHP (calc_model->internal_constants.default_production_bhp_limit)); + + // TODO: BUG: + locked_well->set_bhp (locked_controller->bhp ()); + + wells::rate_control_type control_type = wells::rate_control_cast (main_params_->get_WELL_CONTROL_MODE ("")); + locked_controller->add_bhp_control (locked->create_bhp_control (true, calc_model)); + locked_controller->add_rate_control (locked->create_rate_control (true, control_type, calc_model)); + locked_controller->set_main_control (well, control_type); + + // TODO: bad design, but i don't know better way + locked_controller->clear_rate (); + locked_controller->set_rate (oil_rate_value, main_params_->get_OIL_RATE (0)); + locked_controller->set_rate (water_rate_value, main_params_->get_WATER_RATE (0)); + locked_controller->set_rate (gas_rate_value, main_params_->get_GAS_RATE (0)); + locked_controller->set_rate (liquid_rate_value, main_params_->get_OUTER_RATE (calc_model->internal_constants.default_liquid_rate_limit)); + locked_controller->set_rate (liquid_inner_rate_value, main_params_->get_INNER_RATE (0)); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WCONHIST_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &calc_model) const + { + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + const sp_well_t &locked_well (well); + locked_well->set_state (well_state_cast (main_params_->get_WELL_STATE ("")), calc_model); + + sp_well_controller_t controller = well->get_controller (); + if (!controller) + controller = locked->create_well_controller (well); + + const sp_well_controller_t &locked_controller (controller); + BS_ASSERT (locked_controller); + + using namespace wells; + locked_controller->set_bhp (calc_model->internal_constants.default_production_bhp_limit); + locked_controller->set_bhp_history (main_params_->get_BHP (calc_model->internal_constants.default_production_bhp_limit)); + + //BOSOUT (section::schedule, level::debug) << "default_production_bhp_limit: " << calc_model->internal_constants.default_production_bhp_limit << bs_end; + + // TODO: BUG: + locked_well->set_bhp (locked_controller->bhp ()); + + wells::rate_control_type control_type = wells::rate_control_cast (main_params_->get_WELL_CONTROL_MODE ("")); + locked_controller->add_bhp_control (locked->create_bhp_control (true, calc_model)); + locked_controller->add_rate_control (locked->create_rate_control (true, control_type, calc_model)); + locked_controller->set_main_control (well, control_type); + + // TODO: bad design, but i don't know better way + locked_controller->clear_rate (); + locked_controller->set_rate (liquid_rate_value, calc_model->internal_constants.default_liquid_rate_limit); + locked_controller->set_rate (oil_rate_value, main_params_->get_OIL_RATE (0)); + locked_controller->set_rate (water_rate_value, main_params_->get_WATER_RATE (0)); + locked_controller->set_rate (gas_rate_value, main_params_->get_GAS_RATE (0)); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WCONINJE_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &calc_model) const + { + using namespace wells; + + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + const sp_well_t &locked_well (well); + locked_well->set_state (well_state_cast (main_params_->get_WELL_STATE ("")), calc_model); + + sp_well_controller_t controller = well->get_controller (); + if (!controller) + controller = locked->create_well_controller (well); + + const sp_well_controller_t &locked_controller (controller); + BS_ASSERT (locked_controller); + + locked_controller->set_injection_type (wells::injection_type_cast (main_params_->get_INJECTOR_TYPE ("NONE"))); + locked_controller->set_bhp (main_params_->get_BHP (calc_model->internal_constants.default_injection_bhp_limit)); + + // TODO: BUG: + locked_well->set_bhp (locked_controller->bhp ()); + + wells::rate_control_type control_type = wells::rate_control_cast (main_params_->get_WELL_CONTROL_MODE ("")); + locked_controller->add_bhp_control (locked->create_bhp_control (false, calc_model)); + locked_controller->add_rate_control (locked->create_rate_control (false, control_type, calc_model)); + locked_controller->set_main_control (well, control_type); + + // TODO: bad design, but i don't know better way + locked_controller->clear_rate (); + locked_controller->set_rate (rate_value, main_params_->get_OUTER_RATE (calc_model->internal_constants.default_liquid_rate_limit)); + locked_controller->set_rate (liquid_inner_rate_value, main_params_->get_INNER_RATE (0)); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WECON_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &/*calc_model*/) const + { + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + wells::limit_operation_type type = wells::limit_operation_cast (main_params_->get_OPERATION ("")); + const sp_well_limit_operation_t &locked_limit (locked->create_well_limit_operation (well, type)); + BS_ASSERT (locked_limit) (main_params_->get_WELL_NAME ("")) (main_params_->get_OPERATION ("")); + + locked_limit->set_min_oil_rate (main_params_->get_MIN_OIL_RATE (0)); + locked_limit->set_max_water_cut (main_params_->get_WATER_CUT (0)); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WECONINJ_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &/*calc_model*/) const + { + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + if (!well->get_limit_operation ()) + locked->create_well_limit_operation (well, wells::operation_none); + + const sp_well_limit_operation_t &locked_limit (well->get_limit_operation ()); + locked_limit->set_min_water_cut (main_params_->get_MIN_RATE (0)); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WEFAC_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &/*calc_model*/) const + { + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + const sp_well_t &locked_well (well); + locked_well->set_exploitation_factor (main_params_->get_OPERATION_FACTOR (-1.0)); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WELTARG_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &calc_model) const + { + const sp_top &locked (top); + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + BS_ASSERT (well->get_controller ()); + const sp_well_controller_t &locked_controller (well->get_controller ()); + + using namespace wells; + rate_value_type type = wells::rate_value_cast (main_params_->get_WELL_CONTROL ("")); + if (type == bhp_value) + { + typename strategy_t::item_t bhp = locked_controller->is_production () + ? main_params_->get_VALUE (calc_model->internal_constants.default_production_bhp_limit) + : main_params_->get_VALUE (calc_model->internal_constants.default_injection_bhp_limit) + ; + + if (!well->is_rate ()) + well->set_bhp (bhp); + + locked_controller->set_bhp (bhp); + } + else + { + locked_controller->set_rate (type, main_params_->get_VALUE (0)); + } + } + + ////////////////////////////////////////////////////////////////////////// + template + void + WPIMULT_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &/*calc_model*/) const + { + const sp_top &locked (top); + const sp_smesh_iface_t struct_msh (msh, bs_dynamic_cast()); + + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + typedef typename strategy_t::index_t index_t; + + double perm_mult = main_params_->get_PERM_FACTOR (0); + index_t i_cell = main_params_->get_I (0); + index_t j_cell = main_params_->get_J (0); + index_t k_cell = main_params_->get_K (0); + index_t z1_cell = main_params_->get_Z1 (0); + index_t z2_cell = main_params_->get_Z2 (0); + + if (i_cell && j_cell && k_cell && z1_cell && z2_cell) + { + bs_throw_exception ("Should be specified only [i, j, k] or [z1, z2] values"); + } + if (z1_cell || z2_cell) + { + bs_throw_exception ("[z1, z2] values not supported now"); + } + + if (/*(!z1_cell && !z2_cell) || */!i_cell || !j_cell || !k_cell) + { + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + well->get_connection (i)->mul_perm_mult (perm_mult); + } + } + else if (i_cell && j_cell && k_cell) + { + index_t n_block = struct_msh->get_element_ijk_to_int (i_cell - 1, j_cell - 1, k_cell - 1); + const typename well_t::sp_connection_t &c = well->get_connection_map (n_block); + if (c) + { + c->mul_perm_mult (perm_mult); + } + } + //else + // { + // if (!z1_cell) + // { + // z1_cell = 1; + // } + + // if (!z2_cell) + // { + // z2_cell = struct_msh->get_dimens()[2]; + // } + + // index_t x = well->i_coord_; + // index_t y = well->j_coord_; + // for (index_t z = z1_cell; z < z2_cell; ++z) + // { + // index_t n_block = struct_msh->get_element_ijk_to_int (x, y, z - 1); + // const typename well_t::sp_connection_t &c = well->get_connection (n_block); + // if (c) + // { + // c->mul_perm_mult (perm_mult); + // } + // } + // } + } + + ////////////////////////////////////////////////////////////////////////// + template + void + COMPENSATION_event::apply_internal (const sp_top &/*top*/, const sp_mesh_iface_t &/*msh*/, const sp_calc_model_t &/*calc_model*/) const + { + bs_throw_exception ("NOT IMPL YET"); + } + + ////////////////////////////////////////////////////////////////////////// + template + void + FRACTURE_event::apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const + { + const sp_top &locked (top); + const sp_smesh_iface_t struct_msh (msh, bs_dynamic_cast()); + + sp_well_t well = locked->get_well (main_params_->get_WELL_NAME ("")); + BS_ASSERT (well) (main_params_->get_WELL_NAME ("")); + if (!well) + return ; + + typedef typename strategy_t::index_t index_t; + typedef typename strategy_t::item_t item_t; + + index_t i_cell = main_params_->get_I (0); + index_t j_cell = main_params_->get_J (0); + index_t kw1_cell = main_params_->get_KW1 (0); + index_t kw2_cell = main_params_->get_KW2 (0); + + if (!i_cell || !j_cell || !kw1_cell || !kw2_cell) + { + bs_throw_exception ("Default values not allowed"); + } + + item_t half_length = main_params_->get_HALF_LENGHT (0); + item_t theta = main_params_->get_TETTA (0); + item_t skin = main_params_->get_SKIN (0); + + for (index_t k = kw1_cell; k < kw2_cell; ++k) + { + index_t n_block = struct_msh->get_element_ijk_to_int (i_cell - 1, j_cell - 1, k - 1); + const typename well_t::sp_connection_t &c = well->get_connection_map (n_block); + if (c) + { + c->set_half_length (half_length); + c->set_theta (theta); + c->set_skin (skin); + } + + } + + well->set_state (well_state_cast (main_params_->get_WELL_STATE ("")), calc_model); + } + +#define SPEC_APPLY(name) \ + template void name::apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const;\ + template void name::apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const;\ + template void name::apply_internal (const sp_top &top, const sp_mesh_iface_t &msh, const sp_calc_model_t &calc_model) const; + + SPEC_APPLY (WELSPECS_event); + SPEC_APPLY (WELLCON_event); + SPEC_APPLY (COMPDAT_event); + SPEC_APPLY (WCONPROD_event); + SPEC_APPLY (WCONHIST_event); + SPEC_APPLY (WCONINJE_event); + SPEC_APPLY (WECON_event); + SPEC_APPLY (WECONINJ_event); + SPEC_APPLY (WEFAC_event); + SPEC_APPLY (WELTARG_event); + SPEC_APPLY (WPIMULT_event); + SPEC_APPLY (COMPENSATION_event); + SPEC_APPLY (FRACTURE_event); +//SPEC_APPLY (PERMFRAC_event); + + DECL_GET_WELL_EVENT_NAMES (WELSPECS_event); + DECL_GET_WELL_EVENT_NAMES (WELLCON_event); + DECL_GET_WELL_EVENT_NAMES (COMPDAT_event); + DECL_GET_WELL_EVENT_NAMES (WCONPROD_event); + DECL_GET_WELL_EVENT_NAMES (WCONHIST_event); + DECL_GET_WELL_EVENT_NAMES (WCONINJE_event); + DECL_GET_WELL_EVENT_NAMES (WECON_event); + DECL_GET_WELL_EVENT_NAMES (WECONINJ_event); + DECL_GET_WELL_EVENT_NAMES (WEFAC_event); + DECL_GET_WELL_EVENT_NAMES (WELTARG_event); + DECL_GET_WELL_EVENT_NAMES (WPIMULT_event); + DECL_GET_WELL_EVENT_NAMES (FRACTURE_event); + + DECL_GET_WELL_EVENT_NAME (COMPENSATION_event); + DECL_GET_WELL_EVENT_NAME (PERMFRAC_event); + + template class WELSPECS_event ; + template class WELSPECS_event ; + template class WELSPECS_event ; + template class WELLCON_event ; + template class WELLCON_event ; + template class WELLCON_event ; + template class COMPDAT_event ; + template class COMPDAT_event ; + template class COMPDAT_event ; + template class WCONPROD_event ; + template class WCONPROD_event ; + template class WCONPROD_event ; + template class WCONHIST_event ; + template class WCONHIST_event ; + template class WCONHIST_event ; + template class WCONINJE_event ; + template class WCONINJE_event ; + template class WCONINJE_event ; + template class WECON_event ; + template class WECON_event ; + template class WECON_event ; + template class WECONINJ_event ; + template class WECONINJ_event ; + template class WECONINJ_event ; + template class WEFAC_event ; + template class WEFAC_event ; + template class WEFAC_event ; + template class WELTARG_event ; + template class WELTARG_event ; + template class WELTARG_event ; + template class WPIMULT_event ; + template class WPIMULT_event ; + template class WPIMULT_event ; + template class COMPENSATION_event ; + template class COMPENSATION_event ; + template class COMPENSATION_event ; + template class FRACTURE_event ; + template class FRACTURE_event ; + template class FRACTURE_event ; + template class PERMFRAC_event ; + template class PERMFRAC_event ; + template class PERMFRAC_event ; + +} // namespace blue_sky + diff --git a/bs_bos_core/src/well_events.cpp b/bs_bos_core/src/well_events.cpp new file mode 100644 index 0000000..80eaa1d --- /dev/null +++ b/bs_bos_core/src/well_events.cpp @@ -0,0 +1,348 @@ +/** +* @file well_events.cpp +* @brief Constructors of well events. Each constructor contains the structure of event parameters defenition +* @author Morozov Andrey +* @date 2008-06-07 +*/ +#include "stdafx.h" + +#include "well_events.h" +#include "calc_model.h" +#include "event_filter.h" +#include "reservoir.h" +#include "facility_manager.h" +#include "well_connection.h" + +#define EREGF(class_name,name,descr,type) ereg(name, #name, descr, type) + +namespace blue_sky + { + + template + void + well_event ::apply (const sp_top &top, const sp_mesh_iface_t &mesh, const sp_calc_model_t &calc_model) const + { + if (top->get_event_filter ()->accept_well (get_well_name ())) + { + apply_internal (top, mesh, calc_model); + } + else + { + BOSOUT (section::schedule, level::low) << "[" << get_well_name () << "] reject well event " << get_event_name () << bs_end; + } + } + template + void + well_event ::apply_internal (const sp_top &top, const sp_mesh_iface_t &mesh, const sp_calc_model_t &calc_model) const + { + BS_ASSERT (false && "BASE METHOD CALL"); + } + + template + std::string + well_event ::get_well_name () const + { + BS_ASSERT (false && "BASE METHOD CALL"); + return "BASE METHOD CALL"; + } + template + std::string + well_event ::get_group_name () const + { + BS_ASSERT (false && "BASE METHOD CALL"); + return "BASE METHOD CALL"; + } + template + std::string + well_event ::get_event_name () const + { + BS_ASSERT (false && "BASE METHOD CALL"); + return "BASE METHOD CALL"; + } + + + //constructors + template + WELSPECS_event::WELSPECS_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WELSPECS_event::WELSPECS_event(const WELSPECS_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + WELLCON_event::WELLCON_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WELLCON_event::WELLCON_event(const WELLCON_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + COMPDAT_event::COMPDAT_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + COMPDAT_event::COMPDAT_event(const COMPDAT_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + WCONPROD_event::WCONPROD_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WCONPROD_event::WCONPROD_event(const WCONPROD_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + WCONHIST_event::WCONHIST_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WCONHIST_event::WCONHIST_event(const WCONHIST_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + WCONINJE_event::WCONINJE_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WCONINJE_event::WCONINJE_event(const WCONINJE_event& src) + : bs_refcounter (src) + { + *this = src; + } + + //======================================================================== + + template + WECON_event::WECON_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WECON_event::WECON_event(const WECON_event& src) + : bs_refcounter (src) + { + *this = src; + } + + //======================================================================== + + template + WECONINJ_event::WECONINJ_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WECONINJ_event::WECONINJ_event(const WECONINJ_event& src) + : bs_refcounter (src) + { + *this = src; + } + + //======================================================================== + + template + WEFAC_event::WEFAC_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WEFAC_event::WEFAC_event(const WEFAC_event& src) + : bs_refcounter (src) + { + *this = src; + } + + //======================================================================== + + template + WELTARG_event::WELTARG_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WELTARG_event::WELTARG_event(const WELTARG_event& src) + : bs_refcounter (src) + { + *this = src; + } + + +//======================================================================== + + template + WPIMULT_event::WPIMULT_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + WPIMULT_event::WPIMULT_event(const WPIMULT_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + COMPENSATION_event::COMPENSATION_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + COMPENSATION_event::COMPENSATION_event(const COMPENSATION_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + FRACTURE_event::FRACTURE_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + FRACTURE_event::FRACTURE_event(const FRACTURE_event& src) + : bs_refcounter (src) + { + *this = src; + } + +//======================================================================== + + template + PERMFRAC_event::PERMFRAC_event(bs_type_ctor_param param) + : main_params_ (BS_KERNEL.create_object (main_params_class::bs_type ())) + { + } + template + PERMFRAC_event::PERMFRAC_event(const PERMFRAC_event& src) + : bs_refcounter (src) + { + *this = src; + } + + + + //bs stuff + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WELSPECS_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WELSPECS_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELSPECS_event ), 1, (well_event ), "WELSPECS_seq_fi", "WELSPECS", "BOS_Core WELSPECS_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELSPECS_event ), 1, (well_event ), "WELSPECS_seq_di", "WELSPECS", "BOS_Core WELSPECS_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELSPECS_event ), 1, (well_event ), "WELSPECS_seq_mixi", "WELSPECS", "BOS_Core WELSPECS_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WELLCON_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WELLCON_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELLCON_event ), 1, (well_event ), "WELLCON_seq_fi", "WELLCON", "BOS_Core WELLCON_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELLCON_event ), 1, (well_event ), "WELLCON_seq_di", "WELLCON", "BOS_Core WELLCON_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELLCON_event ), 1, (well_event ), "WELLCON_seq_mixi", "WELLCON", "BOS_Core WELLCON_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (COMPDAT_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (COMPDAT_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (COMPDAT_event ), 1, (well_event ), "COMPDAT_seq_fi", "COMPDAT", "BOS_Core COMPDAT_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (COMPDAT_event ), 1, (well_event ), "COMPDAT_seq_di", "COMPDAT", "BOS_Core COMPDAT_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (COMPDAT_event ), 1, (well_event ), "COMPDAT_seq_mixi", "COMPDAT", "BOS_Core COMPDAT_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WCONPROD_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WCONPROD_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONPROD_event ), 1, (well_event ), "WCONPROD_seq_fi", "WCONPROD", "BOS_Core WCONPROD_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONPROD_event ), 1, (well_event ), "WCONPROD_seq_di", "WCONPROD", "BOS_Core WCONPROD_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONPROD_event ), 1, (well_event ), "WCONPROD_seq_mixi", "WCONPROD", "BOS_Core WCONPROD_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WCONHIST_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WCONHIST_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONHIST_event ), 1, (well_event ), "WCONHIST_seq_fi", "WCONHIST", "BOS_Core WCONHIST_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONHIST_event ), 1, (well_event ), "WCONHIST_seq_di", "WCONHIST", "BOS_Core WCONHIST_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONHIST_event ), 1, (well_event ), "WCONHIST_seq_mixi", "WCONHIST", "BOS_Core WCONHIST_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WCONINJE_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WCONINJE_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONINJE_event ), 1, (well_event ), "WCONINJE_seq_fi", "WCONINJE", "BOS_Core WCONINJE_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONINJE_event ), 1, (well_event ), "WCONINJE_seq_di", "WCONINJE", "BOS_Core WCONINJE_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WCONINJE_event ), 1, (well_event ), "WCONINJE_seq_mixi", "WCONINJE", "BOS_Core WCONINJE_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WECON_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WECON_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WECON_event ), 1, (well_event ), "WECON_seq_fi", "WECON", "BOS_Core WECON_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WECON_event ), 1, (well_event ), "WECON_seq_di", "WECON", "BOS_Core WECON_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WECON_event ), 1, (well_event ), "WECON_seq_mixi", "WECON", "BOS_Core WECON_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WECONINJ_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WECONINJ_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WECONINJ_event ), 1, (well_event ), "WECONINJ_seq_fi", "WECONINJ", "BOS_Core WECONINJ_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WECONINJ_event ), 1, (well_event ), "WECONINJ_seq_di", "WECONINJ", "BOS_Core WECONINJ_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WECONINJ_event ), 1, (well_event ), "WECONINJ_seq_mixi", "WECONINJ", "BOS_Core WECONINJ_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WEFAC_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WEFAC_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WEFAC_event ), 1, (well_event ), "WEFAC_seq_fi", "WEFAC", "BOS_Core WEFAC_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WEFAC_event ), 1, (well_event ), "WEFAC_seq_di", "WEFAC", "BOS_Core WEFAC_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WEFAC_event ), 1, (well_event ), "WEFAC_seq_mixi", "WEFAC", "BOS_Core WEFAC_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WELTARG_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WELTARG_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELTARG_event ), 1, (well_event ), "WELTARG_seq_fi", "WELTARG", "BOS_Core WELTARG_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELTARG_event ), 1, (well_event ), "WELTARG_seq_di", "WELTARG", "BOS_Core WELTARG_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WELTARG_event ), 1, (well_event ), "WELTARG_seq_mixi", "WELTARG", "BOS_Core WELTARG_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (WPIMULT_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (WPIMULT_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WPIMULT_event ), 1, (well_event ), "WPIMULT_seq_fi", "WPIMULT", "BOS_Core WPIMULT_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WPIMULT_event ), 1, (well_event ), "WPIMULT_seq_di", "WPIMULT", "BOS_Core WPIMULT_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (WPIMULT_event ), 1, (well_event ), "WPIMULT_seq_mixi", "WPIMULT", "BOS_Core WPIMULT_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (COMPENSATION_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (COMPENSATION_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (COMPENSATION_event ), 1, (well_event ), "COMPENSATION_seq_fi", "COMPENSATION", "BOS_Core COMPENSATION_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (COMPENSATION_event ), 1, (well_event ), "COMPENSATION_seq_di", "COMPENSATION", "BOS_Core COMPENSATION_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (COMPENSATION_event ), 1, (well_event ), "COMPENSATION_seq_mixi", "COMPENSATION", "BOS_Core COMPENSATION_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (FRACTURE_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (FRACTURE_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (FRACTURE_event ), 1, (well_event ), "FRACTURE_seq_fi", "FRACTURE", "BOS_Core FRACTURE_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (FRACTURE_event ), 1, (well_event ), "FRACTURE_seq_di", "FRACTURE", "BOS_Core FRACTURE_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (FRACTURE_event ), 1, (well_event ), "FRACTURE_seq_mixi", "FRACTURE", "BOS_Core FRACTURE_event class", false) + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (PERMFRAC_event, (class)) + BLUE_SKY_TYPE_STD_COPY_T_DEF (PERMFRAC_event, (class)) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (PERMFRAC_event ), 1, (well_event ), "PERMFRAC_seq_fi", "PERMFRAC", "BOS_Core PERMFRAC_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (PERMFRAC_event ), 1, (well_event ), "PERMFRAC_seq_di", "PERMFRAC", "BOS_Core PERMFRAC_event class", false) + BLUE_SKY_TYPE_IMPL_T_EXT (1, (PERMFRAC_event ), 1, (well_event ), "PERMFRAC_seq_mixi", "PERMFRAC", "BOS_Core PERMFRAC_event class", false) + + +}//ns bs diff --git a/bs_bos_core/src/well_factory.cpp b/bs_bos_core/src/well_factory.cpp new file mode 100644 index 0000000..bb37089 --- /dev/null +++ b/bs_bos_core/src/well_factory.cpp @@ -0,0 +1,81 @@ +/** + * \file well_factory.cpp + * \brief impl of well and connection factories + * \author Sergey Miryanov + * \date 17.07.2008 + * */ +#include "stdafx.h" + +#include "calc_well.h" +#include "well_connection.h" +#include "reservoir.h" +#include "facility_manager.h" +#include "default_connection.h" +#include "default_well.h" + +namespace blue_sky + { + + template + well_factory::well_factory (bs_type_ctor_param param /* = NULL */) + { + + } + template + well_factory::well_factory (const well_factory &f) + : bs_refcounter (f), objbase (f) + { + + } + + template + typename well_factory::sp_well_t + well_factory::create_well (const std::string &group_name, const std::string &well_name) const + { + BS_ASSERT (well_name.size ()); + + sp_well_t w = BS_KERNEL.create_object (wells::default_well ::bs_type (), true); + BS_ASSERT (w) (well_name); + + w->set_name (well_name); + + //sp_well_t w = BS_KERNEL.create_object_v2 > (well_name, true); + //BS_ERROR (w, "well_factory::create_well: Can't create well"); + + return w; + } + + template + typename well_factory::sp_connection_t + well_factory::create_connection () const + { + sp_connection_t con = BS_KERNEL.create_object (wells::default_connection ::bs_type (), true); + BS_ASSERT (con); + + return con; + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF (well_factory, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (well_factory, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_factory ), 1, (objbase), "well_factory_seq_fi", "Base class for well factory", "Base class for well factory", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_factory ), 1, (objbase), "well_factory_seq_di", "Base class for well factory", "Base class for well factory", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_factory ), 1, (objbase), "well_factory_seq_mixi", "Base class for well factory", "Base class for well factory", false); + ////////////////////////////////////////////////////////////////////////// + + bool + well_factory_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, well_factory::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well_factory::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well_factory::bs_type ()); + BS_ASSERT (res); + + return res; + } + +} // namespace blue_sky diff --git a/bs_bos_core/src/well_iterator.cpp b/bs_bos_core/src/well_iterator.cpp new file mode 100644 index 0000000..5cfdd8c --- /dev/null +++ b/bs_bos_core/src/well_iterator.cpp @@ -0,0 +1,98 @@ +/** + * \file well_iterator.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 08.08.2008 + * */ +#include "stdafx.h" +// +//#include "well_iterator.h" +//#include "facility_manager.h" +//#include "calc_well.h" +//#include "well_connection.h" +//#include "reservoir.h" +//#include "facility_manager.h" +//namespace blue_sky +// { +// +// template +// well_iterator::well_iterator (const list_t &list_, const iterator_t &it_) +// : list_ (list_) +// , it_ (it_) +// { +// } +// +// template +// bool +// well_iterator::operator == (const this_t &rhs) const +// { +// return it_ == rhs.it_; +// } +// template +// bool +// well_iterator::operator != (const this_t &rhs) const +// { +// return it_ != rhs.it_; +// } +// +// template +// const typename well_iterator::this_t& +// well_iterator::operator = (const this_t &src) +// { +// list_->clear(); +// list_->insert (src.list_->begin(),src.list_->end()); +// it_ = src.it_; +// return *this; +// } +// +// template +// typename well_iterator::value_type +// well_iterator::operator * () const +// { +// typename value_type_t::base_t w (it_->second, bs_dynamic_cast ()); +// BS_ASSERT (w); +// if (!w) +// throw bs_exception ("well_iterator::operator *()", "Oh, iterator value is not a well"); +// +// return w; +// } +// +// template +// typename well_iterator::this_t & +// well_iterator::operator ++ () +// { +// iterator_t end = list_->end (); +// +// ++it_; +// while (it_ != end) +// { +// typename value_type_t::base_t w (it_->second, bs_dynamic_cast ()); +// +// if (w) +// break; +// else +// ++it_; +// } +// +// return *this; +// } +// +// template +// typename well_iterator::this_t +// well_iterator::operator ++ (int) +// { +// this_t it = *this; +// +// ++it; +// return it; +// } +// +// ////////////////////////////////////////////////////////////////////////// +// typedef facility_manager fm_fi; +// typedef facility_manager fm_di; +// +// template class well_iterator ; +// template class well_iterator ; +// +//} // namespace blue_sky +// diff --git a/bs_bos_core/src/well_limit_operation.cpp b/bs_bos_core/src/well_limit_operation.cpp new file mode 100644 index 0000000..fff51d1 --- /dev/null +++ b/bs_bos_core/src/well_limit_operation.cpp @@ -0,0 +1,176 @@ +/** + * \file well_limit_operation.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 16.07.2008 + * */ +#include "stdafx.h" + +#include "well_limit_operation.h" + +namespace blue_sky + { + namespace wells + { + + limit_operation_type + limit_operation_cast (const std::string &str) + { + if (str == "NONE") + return operation_none; + else if (str == "CON") + return operation_con; + else if (str == "WELL") + return operation_well; + else if (str == "") + { + BS_ASSERT (false && "limit_operation_type is empty. will be used operation_none"); + return operation_none; + } + else + { + BS_ASSERT (false && "Unsupported value of limit_operation type") (str); + throw bs_exception ("limit_operation_cast", "Unsupported value of limit_operation type"); + } + } + + well_limit_operation::well_limit_operation (bs_type_ctor_param param /* = NULL */) + : min_oil_rate_ (0) + , max_water_cut_ (0) + , min_water_cut_ (0) + { + + } + well_limit_operation::well_limit_operation (const well_limit_operation &op) + : bs_refcounter (op), objbase (op) + { + min_oil_rate_ = op.min_oil_rate_; + max_water_cut_ = op.max_water_cut_; + min_water_cut_ = op.min_water_cut_; + } + + void + well_limit_operation::set_min_oil_rate (item_t min_oil_rate) + { + min_oil_rate_ = min_oil_rate; + } + void + well_limit_operation::set_max_water_cut (item_t max_water_cut) + { + max_water_cut_ = max_water_cut; + } + void + well_limit_operation::set_min_water_cut (item_t min_water_cut) + { + min_water_cut_ = min_water_cut; + } + + void + well_limit_operation::set_value (int value_type, item_t value) + { + BS_ASSERT (false && "NOT IMPL YET"); + } + + bool + well_limit_operation::fi_check_limits () const + { + BS_ASSERT (false && "NOT IMPL YET"); + return false; + + //if (current_status < 0) + // { + // if (current_rate.oil > 0.1 || + // current_rate.water > 0.1 || + // current_rate.gas > 0.1) + // { + // rep->print (LOG_ITERS_SECTION, LOG_ERR, + // "***---------------------------------------------------------------------***\n"); + // rep->print (LOG_ITERS_SECTION, LOG_ERR, + // GET_TEXT ("Warning: production well %s could not operate under current conditions\n"), + // get_name ()); + // print_current_status (); + // fi_close_well (); + // rep->print (LOG_ITERS_SECTION, LOG_ERR, + // "***---------------------------------------------------------------------***\n"); + // return 1; + // } + // } + //// injection well + //else if (current_status > 0) + // { + // if (current_rate.oil_inj < -0.1 || + // current_rate.water_inj < -0.1 || + // current_rate.gas_inj < -0.1) + // { + // rep->print (LOG_ITERS_SECTION, LOG_ERR, + // "***---------------------------------------------------------------------***\n"); + // rep->print (LOG_ITERS_SECTION, LOG_ERR, + // GET_TEXT ("Warning: injection well %s could not operate under current conditions\n"), + // get_name ()); + // print_current_status (); + // fi_close_well (); + // rep->print (LOG_ITERS_SECTION, LOG_ERR, + // "***---------------------------------------------------------------------***\n"); + // return 1; + // } + // } + //return 0; + + } + + ////////////////////////////////////////////////////////////////////////// + + well_limit_operation_factory::well_limit_operation_factory (bs_type_ctor_param param /* = NULL */) + { + + } + well_limit_operation_factory::well_limit_operation_factory (const well_limit_operation_factory &f) + : bs_refcounter (f), objbase (f) + { + + } + + well_limit_operation_factory::sp_well_limit_operation_t + well_limit_operation_factory::create_limit (limit_operation_type type) const + { + BS_ASSERT (false && "BASE METHOD CALL"); + return BS_KERNEL.create_object (well_limit_operation::bs_type ()); + } + + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE (well_limit_operation); + BLUE_SKY_TYPE_STD_COPY (well_limit_operation); + BLUE_SKY_TYPE_IMPL (well_limit_operation, objbase, "well_limit_operation", "Base class for well limit operations", "Base class for well limit operation"); + + BLUE_SKY_TYPE_STD_CREATE (well_limit_operation_factory); + BLUE_SKY_TYPE_STD_COPY (well_limit_operation_factory); + BLUE_SKY_TYPE_IMPL (well_limit_operation_factory, objbase, "well_limit_operation_factory", "Base class for factory of well limit operations", "Base class for factory of well limit operations"); + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + bool + well_limit_operation_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, well_limit_operation::bs_type ()); + BS_ASSERT (res); + + return res; + } + bool + well_limit_operation_factory_register_type (const blue_sky::plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, well_limit_operation_factory::bs_type ()); + BS_ASSERT (res); + + return res; + } + ////////////////////////////////////////////////////////////////////////// + + } // namespace wells +} // namespace blue_sky diff --git a/bs_bos_core/src/well_rate_control.cpp b/bs_bos_core/src/well_rate_control.cpp new file mode 100644 index 0000000..7b19662 --- /dev/null +++ b/bs_bos_core/src/well_rate_control.cpp @@ -0,0 +1,34 @@ +/** + * \file well_rate_contorl.cpp + * \brief well_rate_control impl + * \author Sergey Miryanov + * \date 21.11.2008 + * */ +#include "stdafx.h" +#include "well_rate_control.h" + +namespace blue_sky { +namespace wells { + + template + well_rate_control ::well_rate_control (bs_type_ctor_param /*param = NULL */) + { + + } + template + well_rate_control ::well_rate_control (const well_rate_control &x) + : bs_refcounter (x), objbase (x) + { + + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (well_rate_control, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (well_rate_control, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_rate_control ), 1, (objbase), "well_rate_control_seq_fi", "Base class for well_rate_control", "Base class for well_rate_control", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_rate_control ), 1, (objbase), "well_rate_control_seq_di", "Base class for well_rate_control", "Base class for well_rate_control", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_rate_control ), 1, (objbase), "well_rate_control_seq_mixi", "Base class for well_rate_control", "Base class for well_rate_control", false); + + +} // namespace wells +} // namespace blue_sky + diff --git a/bs_bos_core/src/well_rate_control_impl.cpp b/bs_bos_core/src/well_rate_control_impl.cpp new file mode 100644 index 0000000..aa8253a --- /dev/null +++ b/bs_bos_core/src/well_rate_control_impl.cpp @@ -0,0 +1,73 @@ +/** + * \file + * \brief + * \author + * \date + * */ +#include "stdafx.h" + +#include "calc_well.h" +#include "well_connection.h" +#include "well_controller.h" +#include "well_rate_control.h" + +#include "calc_model_data_accessors.h" + +#include "rate_control_type.h" + +#include "well_rate_control_prod_mobility.h" +#include "well_rate_control_inj_mobility.h" + +#include "well_rate_control_bhp_deriv.h" +#include "well_rate_control_rate_deriv.h" +#include "well_rate_control_rate.h" + +#include "well_rate_control_impl.h" +#include "well_rate_control_impl_type.h" + +#include "reservoir.h" +#include "facility_manager.h" + +namespace blue_sky + { + + + template + well_rate_control_impl ::well_rate_control_impl (bs_type_ctor_param param /* = NULL */) + { + } + + template + well_rate_control_impl ::well_rate_control_impl (const well_rate_control_impl &i) + : bs_refcounter (i) + { + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (well_rate_control_impl, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (well_rate_control_impl, (class)); + +#define DEFINE_WELL_RATE_CONTROL_IMPL(TYPE) \ + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_rate_control_impl >), 1, (objbase), BOOST_PP_STRINGIZE(well_rate_control_impl >), BOOST_PP_STRINGIZE(well_rate_control_impl >), BOOST_PP_STRINGIZE(well_rate_control_impl >), false); \ + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_rate_control_impl >), 1, (objbase), BOOST_PP_STRINGIZE(well_rate_control_impl >), BOOST_PP_STRINGIZE(well_rate_control_impl >), BOOST_PP_STRINGIZE(well_rate_control_impl >), false);\ + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_rate_control_impl >), 1, (objbase), BOOST_PP_STRINGIZE(well_rate_control_impl >), BOOST_PP_STRINGIZE(well_rate_control_impl >), BOOST_PP_STRINGIZE(well_rate_control_impl >), false); + + using namespace wells; + DEFINE_WELL_RATE_CONTROL_IMPL (compute_bhp_3p_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_rate_3p_type); + + DEFINE_WELL_RATE_CONTROL_IMPL (compute_bhp_2p_ow_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_bhp_2p_og_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_rate_2p_ow_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_rate_2p_og_type); + + DEFINE_WELL_RATE_CONTROL_IMPL (compute_bhp_1p_o_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_bhp_1p_w_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_bhp_1p_g_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_rate_1p_o_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_rate_1p_w_type); + DEFINE_WELL_RATE_CONTROL_IMPL (compute_rate_1p_g_type); + + DEFINE_WELL_RATE_CONTROL_IMPL (compute_dummy_type); + +} // namespace blue_sky + diff --git a/bs_bos_core/src/well_reporter.cpp b/bs_bos_core/src/well_reporter.cpp new file mode 100644 index 0000000..70928ed --- /dev/null +++ b/bs_bos_core/src/well_reporter.cpp @@ -0,0 +1,1267 @@ +/** + * \file well_reporter.cpp + * \brief prints well data + * \date 29.09.2009 + * \author Sergey Miryanov + * */ +#include "stdafx.h" +#include "well_reporter.h" +#include "calc_well.h" +#include "facility_manager.h" +#include "well_connection.h" + +#include + +#include +#include +#include +#include +#include + +#define LIQUID_RATE_MULT data->output_units_converter.liquid_rate_mult () +#define GAS_RATE_MULT data->output_units_converter.gas_rate_mult () +#define GAS_OIL_RATIO_MULT data->output_units_converter.gas_liquid_mult () +#define WATER_GAS_RATIO_MULT 1.0 / data->output_units_converter.gas_liquid_mult () +#define PRESSURE_MULT data->output_units_converter.pressure_mult () +#define GAS_LIQUID_RATE_MULT data->output_units_converter.gas_liquid_rate_mult () +#define GRAVITY data->input_units_converter.output_constants.gravity_constant + +#define RATE_LIQUID_SURFACE_NOTE convert_units::rate_liquid_surface_note (data->output_units_converter.get_output_units ()) +#define RATE_GAS_SURFACE_NOTE convert_units::rate_gas_surface_note (data->output_units_converter.get_output_units ()) +#define RATE_LIQUID_RESERVOIR_NOTE convert_units::rate_liquid_reservoir_note (data->output_units_converter.get_output_units ()) +#define GAS_LIQUID_NOTE convert_units::gas_liquid_note (data->output_units_converter.get_output_units ()) +#define LIQUID_GAS_NOTE convert_units::liquid_gas_note (data->output_units_converter.get_output_units ()) +#define PRESSURE_NOTE convert_units::pressure_note (data->output_units_converter.get_output_units ()) +#define VOL_LIQUID_SURFACE_NOTE convert_units::volume_liquid_surface_note (data->output_units_converter.get_output_units ()) +#define VOL_GAS_SURFACE_NOTE convert_units::volume_gas_surface_note (data->output_units_converter.get_output_units ()) +#define VOL_LIQUID_RES_NOTE convert_units::volume_liquid_reservoir_note (data->output_units_converter.get_output_units ()) + +#define DECL_COLUMN_HOLDER_I(r, _, i, elem) \ + column_t elem; + +#define DECL_COLUMN_HOLDER_PTR_I(r, _, i, elem) \ + columns_[i] = &elem; + +#define DATA_LEN_I(r, _, idx, elem) \ + + 1 + columns.BOOST_PP_TUPLE_ELEM (3, 0, elem).width + +#define DATA_I(r, func, i, elem) \ + sprintf (buffer + idx, \ + BOOST_PP_TUPLE_ELEM (3, 1, elem).format_string ( \ + columns.BOOST_PP_TUPLE_ELEM (3, 0, elem)), \ + BOOST_PP_TUPLE_ELEM (3, 1, elem).data ( \ + columns.BOOST_PP_TUPLE_ELEM (3, 0, elem), \ + ds, \ + columns.BOOST_PP_TUPLE_ELEM (3, 0, elem).mult, \ + BOOST_PP_TUPLE_ELEM (3, 2, elem))); \ + idx += 1 + columns.BOOST_PP_TUPLE_ELEM (3, 0, elem).width; + +#define DECL_COLUMN_HOLDER(holder_name, len, tuple) \ + struct holder_name \ + { \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_COLUMN_HOLDER_I, _, \ + BOOST_PP_TUPLE_TO_SEQ (len, tuple)) \ + \ + column_t *columns_[len]; \ + size_t columns_count_; \ + mutable char *line_buffer; \ + mutable char *unit_buffer; \ + mutable char *header_buffer[column_t::line_count]; \ + mutable size_t header_buffer_count; \ + holder_name () \ + : columns_count_ (len) \ + , line_buffer (0) \ + , unit_buffer (0) \ + , header_buffer_count (0) \ + { \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_COLUMN_HOLDER_PTR_I, _, \ + BOOST_PP_TUPLE_TO_SEQ (len, tuple)) \ + detail::init_header_buffer (header_buffer); \ + } \ + ~holder_name () \ + { \ + delete [] line_buffer; \ + delete [] unit_buffer; \ + detail::free_header_buffer (header_buffer); \ + } \ + }; + +#define DATA_LINE(columns_type, name, data_type, type, seq) \ + struct BOOST_PP_CAT (name, _class) \ + { \ + mutable char *buffer; \ + BOOST_PP_CAT (name, _class) () \ + : buffer (0) \ + { \ + } \ + ~BOOST_PP_CAT (name, _class) () \ + { \ + delete[] buffer; \ + } \ + void \ + print (const columns_type &columns, const data_type &data, const type &ds, \ + bool do_print_line = true) const \ + { \ + size_t len = 1 \ + BOOST_PP_SEQ_FOR_EACH_I (DATA_LEN_I, _, seq); \ + if (!buffer) \ + { \ + buffer = new char [len + 1]; \ + } \ + memset (buffer, 0, len + 1); \ + size_t idx = 0; \ + BOOST_PP_SEQ_FOR_EACH_I (DATA_I, _, seq) \ + buffer[idx] = '|'; \ + BOSOUT (section::print_reports, level::highest) << buffer << bs_end; \ + if (do_print_line) \ + print_line (columns); \ + } \ + }; \ + BOOST_PP_CAT (name, _class) name; + +namespace blue_sky { + + namespace detail { + template + void + init_header_buffer (char *(&header_buffer)[line_count]) + { + for (size_t i = 0; i < line_count; ++i) + { + header_buffer[i] = 0; + } + } + + template + void + free_header_buffer (char *(&header_buffer)[line_count]) + { + for (size_t i = 0; i < line_count; ++i) + { + delete[] header_buffer[i]; + } + } + } + + + struct column_info + { + size_t w, w2; + size_t header_len; + const char *header; + double mult; + + column_info (size_t w, size_t w2, size_t len, const char *header, double mult = 1.0) + : w (w), w2 (w2), header_len (len), header (header), mult (mult) + { + } + }; + + template + column_info + column (size_t width, size_t width2, const char (&header) [N]) + { + return column_info (width, width2, N, header); + } + + template + column_info + column (size_t w, size_t w2, const char (&header) [N], double mult) + { + return column_info (w, w2, N, header, mult); + } + + const char * + unit (const char *str) + { + return str; + } + + template + struct unit_t + { + const ds_t &ds; + const function_t &function; + const char *note; + + unit_t (const ds_t &ds, const function_t &function, const char *note) + : ds (ds) + , function (function) + , note (note) + { + } + }; + + template + unit_t + unit (const ds_t &ds, const function_t &function, const char *note) + { + return unit_t (ds, function, note); + } + + struct column_t + { + enum { + line_count = 4, + }; + + const char *line[line_count]; + size_t line_idx; + size_t width; + double mult; + + public: + char string_format[15 + 1]; + char float_format[15 + 1]; + char *unit_format; + + char *header; + char *unit; + + column_t () + { + line_idx = 0; + width = 0; + + memset (line, 0, sizeof (line)); + memset (string_format, 0, sizeof (string_format)); + memset (float_format, 0, sizeof (float_format)); + + unit_format = 0; + + header = 0; + unit = 0; + } + + ~column_t () + { + delete[] header; + delete[] unit; + } + + template + void + make_header (const column_info_t &c) + { + width = c.w; + header = new char [c.header_len + 1]; + memcpy (header, c.header, c.header_len); + make_header (header, 0, c.header_len, c.w - 1); + } + + void + make_header (char *str, size_t space_idx, size_t len, size_t width) + { + static const char *empty_str = ""; + size_t idx = 0; + + line[line_idx] = str + space_idx; + if (line_idx < line_count) + line[line_idx + 1] = empty_str; + + for (size_t i = space_idx; i < len; ++i) + { + char c = str[i]; + if (c == ' ') + { + space_idx = i; + } + + if (idx >= width) + { + str[space_idx] = 0; + ++line_idx; + make_header (str, space_idx + 1, len, width); + break; + } + + idx++; + } + } + + void + operator () (const column_info &c, const char *unit_str) + { + mult = c.mult; + sprintf (string_format, "| %%%ds ", (int)c.w - 2); + sprintf (float_format, "|%%%d.%df", (int)c.w, (int)c.w2); + make_header (c); + + unit_format = string_format; + unit = new char [strlen (unit_str) + 1]; + + memset (unit, 0, strlen (unit_str) + 1); + memcpy (unit, unit_str, strlen (unit_str) + 1); + } + + template + void + operator () (const column_info &c, const unit_t &u) + { + mult = c.mult; + sprintf (string_format, "| %%%ds ", (int)c.w - 2); + sprintf (float_format, "|%%%d.%df", (int)c.w, (int)c.w2); + make_header (c); + + unit_format = float_format; + double value = u.function.data (*this, u.ds, mult, 1.0); + + if (value > 1.e9) + { + mult *= 1.e-6; + unit = new char[strlen (u.note) + 1 + 1]; + unit[0] = 'M'; + memset (unit + 1, 0, strlen (u.note) + 1); + memcpy (unit + 1, u.note, strlen (u.note)); + } + else if (value > 1.e6) + { + mult *= 1.e-3; + unit = new char[strlen (u.note) + 1 + 1]; + unit[0] = 'K'; + memset (unit + 1, 0, strlen (u.note) + 1); + memcpy (unit + 1, u.note, strlen (u.note)); + } + else + { + unit = new char[strlen (u.note) + 1]; + memset (unit, 0, strlen (u.note) + 1); + memcpy (unit, u.note, strlen (u.note)); + } + } + }; + namespace detail { + struct rate_rc + { + template + static typename ds_t::rate_data_t + get (const ds_t &ds) + { + return ds.rate_rc_; + } + }; + struct rate_rc_wefac + { + template + static typename ds_t::rate_data_t + get (const ds_t &ds) + { + return ds.rate_rc_wefac_; + } + }; + struct rate_total + { + template + static typename ds_t::rate_data_t + get (const ds_t &ds) + { + return ds.rate_total_; + } + }; + struct rate + { + template + static typename ds_t::rate_data_t + get (const ds_t &ds) + { + return ds.rate_; + } + }; + struct rate_wefac + { + template + static typename ds_t::rate_data_t + get (const ds_t &ds) + { + return ds.rate_wefac_; + } + }; + + struct prod_rate_data + { + template + static typename data_t::rate_data_inner + get (const data_t &data) + { + return data.prod; + } + }; + + struct inj_rate_data + { + template + static typename data_t::rate_data_inner + get (const data_t &data) + { + return data.inj; + } + }; + } + + struct string_data + { + const char * + format_string (const column_t &c) const + { + return c.string_format; + } + }; + + struct float_data + { + const char * + format_string (const column_t &c) const + { + return c.float_format; + } + }; + + struct reservoir_name : string_data + { + template + const char * + data (const column_t &c, const data_source_t &ds, float, float) const + { + return "RESERVOIR"; + } + }; + + struct empty_cell : string_data + { + template + const char * + data (const column_t &c, const data_source_t &ds, float, float) const + { + return ""; + } + }; + + template + struct liquid_rate : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float a_mult) const + { + const typename data_source_t::rate_data_t::rate_data_inner &rate = get_inner_rate_data_t::get (get_rate_data_t::get (ds)); + return rate.liquid * mult * a_mult; + } + }; + template + struct oil_rate : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float a_mult) const + { + const typename data_source_t::rate_data_t::rate_data_inner &rate = get_inner_rate_data_t::get (get_rate_data_t::get (ds)); + return rate.oil * mult * a_mult; + } + }; + template + struct water_rate : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float a_mult) const + { + const typename data_source_t::rate_data_t::rate_data_inner &rate = get_inner_rate_data_t::get (get_rate_data_t::get (ds)); + return rate.water * mult * a_mult; + } + }; + template + struct gas_rate : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float a_mult) const + { + const typename data_source_t::rate_data_t::rate_data_inner &rate = get_inner_rate_data_t::get (get_rate_data_t::get (ds)); + return rate.gas * mult * a_mult; + } + }; + + template + struct prod_fluid_rate : float_data + { + float gas_liquid_rate_mult; + + prod_fluid_rate (float gas_liquid_rate_mult) + : gas_liquid_rate_mult (gas_liquid_rate_mult) + { + } + + template + float + data (const column_t &c, const data_source_t &ds, float mult, float a_mult) const + { + return (rate_t::get (ds).free_gas * gas_liquid_rate_mult + + rate_t::get (ds).prod.water + + rate_t::get (ds).prod.oil) * mult * a_mult; + } + }; + template + struct inj_fluid_rate : float_data + { + float gas_liquid_rate_mult; + + inj_fluid_rate (float gas_liquid_rate_mult) + : gas_liquid_rate_mult (gas_liquid_rate_mult) + { + } + + template + float + data (const column_t &c, const data_source_t &ds, float mult, float a_mult) const + { + return (rate_t::get (ds).inj.gas * gas_liquid_rate_mult + + rate_t::get (ds).inj.water + + rate_t::get (ds).inj.oil) * mult * a_mult; + } + }; + + template + struct water_cut : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float, float) const + { + const typename data_source_t::rate_data_t::rate_data_inner &rate = get_inner_rate_data_t::get (get_rate_data_t::get (ds)); + return (rate.water * rate.oil) != 0.0 ? (rate.water / (rate.water + rate.oil)) : 0; + } + }; + + template + struct gas_oil_ratio : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float) const + { + const typename data_source_t::rate_data_t::rate_data_inner &rate = get_inner_rate_data_t::get (get_rate_data_t::get (ds)); + return fabs (rate.oil) > 0 ? (rate.gas * mult / rate.oil) : 0; + } + }; + + template + struct water_gas_ratio : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float) const + { + const typename data_source_t::rate_data_t::rate_data_inner &rate = get_inner_rate_data_t::get (get_rate_data_t::get (ds)); + return fabs (rate.gas) > 0 ? (rate.water * mult / rate.gas) : 0; + } + }; + + struct wefac : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float, float) const + { + return ds.exploitation_factor_; + } + }; + + struct well_name : string_data + { + template + const char * + data (const column_t &c, const data_source_t &ds, float, float) const + { + return ds.name ().c_str (); + } + }; + + struct ctrl_mode : string_data + { + template + const char * + data (const column_t &c, const data_source_t &ds, float, float) const + { + if (ds.is_shut ()) + return "SHUT"; + + if (ds.is_bhp ()) + { + return "BHP"; + } + else + { + if (ds.get_well_controller ()->is_production ()) + { + using namespace wells; + rate_control_type type = ds.get_well_controller ()->get_control_type (); + switch (type) + { + case liquid_rate_control: + return "LRAT"; + case oil_rate_control: + return "ORAT"; + case water_rate_control: + return "WRAT"; + case gas_rate_control: + return "GRAT"; + default: + return "UNKNOWN"; + } + } + else + { + return "RATE"; + } + } + } + }; + struct total_ctrl_mode : string_data + { + template + const char * + data (const column_t &c, const data_source_t &ds, float, float) const + { + if (ds.is_shut ()) + return "SHUTED WELL"; + + if (ds.get_well_controller ()->is_production ()) + { + if (!ds.is_bhp ()) + { + using namespace wells; + rate_control_type type = ds.get_well_controller ()->get_control_type (); + switch (type) + { + case liquid_rate_control: + return "LIQUID PRODUCER"; + case oil_rate_control: + return "OIL PRODUCER"; + case water_rate_control: + return "WATER PRODUCER"; + case gas_rate_control: + return "GAS PRODUCER"; + default: + return "UNKNOWN PRODUCER"; + } + } + else + { + return "BHP PRODUCER"; + } + } + else + { + if (ds.is_bhp ()) + { + return "BHP INJECTOR"; + } + else + { + using namespace wells; + injection_type type = ds.get_well_controller ()->injection (); + switch (type) + { + case injection_oil: + return "OIL INJECTOR"; + case injection_water: + return "WATER INJECTOR"; + case injection_gas: + return "GAS INJECTOR"; + default: + return "UNKNOWN INJECTOR"; + } + } + } + } + }; + + struct well_gas_oil_ratio : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float a_mult) const + { + return fabs (ds.rate ().prod.oil) > 0 ? (ds.gor_ * mult) : 0; + } + }; + + struct first_con_bhp : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float) const + { + return ds.get_connections_count () ? (ds.get_connection (0)->get_cur_bhp () * mult) : 0; + } + }; + + struct first_con_bulkp : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float) const + { + return ds.get_connections_count () ? (ds.get_connection (0)->get_bulkp () * mult) : 0; + } + }; + + struct grid_block + { + mutable char buffer [128 * 3 + 1]; + mutable char format [128 * 3 + 1]; + + const char * + format_string (const column_t &c) + { + return "%s"; + } + + template + const char * + data (const column_t &c, const data_source_t &ds, float mult, float) const + { + memset (buffer, 0, sizeof (buffer)); + memset (format, 0, sizeof (format)); + int width = (int)c.width - 2; + int size = width / 3; + + sprintf (format, "|%%%dd,%%%dd,%%%dd", size, size, width - size - size); + sprintf (buffer, format, ds.i_coord () + 1, ds.j_coord () + 1, ds.k_coord () + 1); + + return buffer; + } + }; + + struct con_bhp : float_data + { + float gravity; + + con_bhp (float gravity) + : gravity (gravity) + { + } + + template + float + data (const column_t &c, const data_source_t &ds, float mult, float) const + { + return (ds.get_cur_bhp () + ds.get_density () * gravity * ds.get_connection_depth () * 0.5) * mult; + } + }; + + struct con_bulkp : float_data + { + template + float + data (const column_t &c, const data_source_t &ds, float mult, float) const + { + return ds.get_bulkp () * mult; + } + }; + + namespace detail { + template + size_t + buffer_len (const holder_t &holder) + { + size_t len = 1; + for (size_t i = 0; i < holder.columns_count_; ++i) + { + len += holder.columns_[i]->width + 1; + } + + return len; + } + + template + struct aptr + { + aptr (T *t = 0) : t (t) {} + ~aptr () {delete[] t;} + + T *get () { return t; } + T &operator[] (size_t i) { return t[i];} + + T *t; + }; + + } + + template + void + print_line (const holder_t &holder) + { + if (!holder.line_buffer) + { + size_t len = detail::buffer_len (holder); + holder.line_buffer = new char [len + 1]; + memset (holder.line_buffer, '-', len); + + size_t idx = 0; + for (size_t i = 0; i < holder.columns_count_; ++i) + { + holder.line_buffer[idx] = '|'; + idx += holder.columns_[i]->width + 1; + } + + holder.line_buffer[idx + 0] = '|'; + holder.line_buffer[idx + 1] = 0; + } + + BS_ASSERT (holder.line_buffer); + BOSOUT (section::print_reports, level::highest) << holder.line_buffer << bs_end; + } + + template + void + print_units (const holder_t &holder) + { + if (!holder.unit_buffer) + { + size_t len = detail::buffer_len (holder); + holder.unit_buffer = new char [len + 1]; + memset (holder.unit_buffer, 0, len + 1); + + size_t idx = 0; + for (size_t i = 0; i < holder.columns_count_; ++i) + { + sprintf (holder.unit_buffer + idx, holder.columns_[i]->string_format, holder.columns_[i]->unit); + idx += holder.columns_[i]->width + 1; + } + holder.unit_buffer[idx + 0] = '|'; + } + + BOSOUT (section::print_reports, level::highest) << holder.unit_buffer << bs_end; + } + + template + void + print_header (const holder_t &holder) + { + print_line (holder); + + if (!holder.header_buffer_count) + { + size_t line_idx = 0; + for (size_t i = 0; i < holder.columns_count_; ++i) + { + if (holder.columns_[i]->line_idx > line_idx) + line_idx = holder.columns_[i]->line_idx; + } + + holder.header_buffer_count = line_idx; + size_t len = detail::buffer_len (holder); + for (size_t j = 0; j <= line_idx; ++j) + { + holder.header_buffer[j] = new char[len + 1]; + memset (holder.header_buffer[j], 0, len + 1); + size_t idx = 0; + for (size_t i = 0; i < holder.columns_count_; ++i) + { + sprintf (holder.header_buffer[j] + idx, holder.columns_[i]->string_format, holder.columns_[i]->line[j]); + idx += holder.columns_[i]->width + 1; + } + holder.header_buffer[j][idx + 0] = '|'; + } + } + + for (size_t j = 0; j <= holder.header_buffer_count; ++j) + { + BOSOUT (section::print_reports, level::highest) << holder.header_buffer[j] << bs_end; + } + + print_units (holder); + print_line (holder); + } + + namespace detail { + struct is_prod + { + template + inline bool + filter (const T &well) const + { + return well->get_well_controller ()->is_production (); + } + }; + + struct is_inj + { + template + inline bool + filter (const T &well) const + { + return !well->get_well_controller ()->is_production (); + } + }; + + template + void + print_well_data (const printer_t &printer, const data_t &data, const rs_t &rs, const well_filter_t &well_filter) + { + typedef typename rs_t::well_t well_t; + typedef typename rs_t::connection_t connection_t; + typedef typename rs_t::facility_manager_t::well_const_iterator_t well_iterator_t; + + typedef data_t sp_data_t; + typedef typename rs_t::sp_well_t sp_well_t; + typedef typename rs_t::sp_connection_t sp_connection_t; + + print_header (printer.columns); + printer.reservoir_data.print (printer.columns, data, rs); + + well_iterator_t wb = rs.get_facility_list ()->wells_begin (); + well_iterator_t we = rs.get_facility_list ()->wells_end (); + + for (; wb != we; ++wb) + { + sp_well_t well (wb->second, bs_dynamic_cast ()); + + if (well_filter.filter (well)) + { + printer.well_data.print (printer.columns, data, *well); + + for (size_t j = 0, jcnt = well->get_connections_count (); j < jcnt; ++j) + { + printer.connection_data.print (printer.columns, data, *well->get_connection (j), false); + } + if (well->get_connections_count ()) + print_line (printer.columns); + } + } + } + } + + template + struct prod_printer + { + typedef reservoir reservoir_t; + typedef well well_t; + typedef wells::connection connection_t; + typedef smart_ptr sp_data_t; + + DECL_COLUMN_HOLDER (prod_columns_holder_t, 13, + (WELL_NAME, + GRID_BLOCK, + CTRL_MODE, + WEFAC, + OIL_RATE, + WATER_RATE, + GAS_RATE, + FLUID_RES_VOL, + WATER_CUT, + GAS_OIL_RATIO, + WATER_GAS_RATIO, + BHP, + BULK_PRESSURE)); + + prod_columns_holder_t columns; + + typedef liquid_rate liquid_rate_t; + typedef oil_rate oil_rate_t; + typedef water_rate water_rate_t; + typedef gas_rate gas_rate_t; + typedef water_cut water_cut_t; + typedef gas_oil_ratio gas_oil_ratio_t; + typedef water_gas_ratio water_gas_ratio_t; + + typedef oil_rate oil_rate_wefac_t; + typedef water_rate water_rate_wefac_t; + typedef gas_rate gas_rate_wefac_t; + typedef water_cut water_cut_wefac_t; + typedef gas_oil_ratio gas_oil_ratio_wefac_t; + typedef water_gas_ratio water_gas_ratio_wefac_t; + + typedef prod_fluid_rate fluid_rate_t; + typedef prod_fluid_rate fluid_rate_rc_wefac_t; + + prod_printer (const sp_data_t &data, const smart_ptr &rs) + { + columns.WELL_NAME (column (12, 0, "WELL NAME"), unit ("")); + columns.GRID_BLOCK (column (14, 0, "LOCATION (I,J,K)"), unit ("")); + columns.CTRL_MODE (column (12, 0, "CTRL MODE"), unit ("")); + columns.WEFAC (column (12, 5, "WEFAC"), unit ("")); + columns.OIL_RATE (column (13, 3, "OIL RATE", LIQUID_RATE_MULT), unit (*rs, oil_rate_wefac_t (), RATE_LIQUID_SURFACE_NOTE)); + columns.WATER_RATE (column (13, 3, "WATER RATE", LIQUID_RATE_MULT), unit (*rs, water_rate_wefac_t (), RATE_LIQUID_SURFACE_NOTE)); + columns.GAS_RATE (column (13, 3, "GAS RATE", GAS_RATE_MULT), unit (*rs, gas_rate_wefac_t (), RATE_GAS_SURFACE_NOTE)); + columns.FLUID_RES_VOL (column (16, 3, "FLUID RES.VOL.", LIQUID_RATE_MULT), unit (*rs, fluid_rate_rc_wefac_t (GAS_LIQUID_RATE_MULT), RATE_LIQUID_RESERVOIR_NOTE)); + columns.WATER_CUT (column (15, 3, "WATER CUT"), unit ("")); + columns.GAS_OIL_RATIO (column (15, 3, "GAS/OIL RATIO", GAS_OIL_RATIO_MULT), unit (*rs, gas_oil_ratio_wefac_t (), GAS_LIQUID_NOTE)); + columns.WATER_GAS_RATIO (column (15, 4, "WATER/GAS RATIO", WATER_GAS_RATIO_MULT), unit (*rs, water_gas_ratio_wefac_t (), LIQUID_GAS_NOTE)); + columns.BHP (column (15, 2, "BHP OR CON.PR.", PRESSURE_MULT), unit (PRESSURE_NOTE)); + columns.BULK_PRESSURE (column (12, 2, "Bulk Pressure", PRESSURE_MULT), unit (PRESSURE_NOTE)); + } + + DATA_LINE (prod_columns_holder_t, reservoir_data, sp_data_t, reservoir_t, + ((WELL_NAME, reservoir_name (), 1.0)) + ((GRID_BLOCK, empty_cell (), 1.0)) + ((CTRL_MODE, empty_cell (), 1.0)) + ((WEFAC, empty_cell (), 1.0)) + ((OIL_RATE, oil_rate_wefac_t (), -1.0)) + ((WATER_RATE, water_rate_wefac_t (), -1.0)) + ((GAS_RATE, gas_rate_wefac_t (), -1.0)) + ((FLUID_RES_VOL, fluid_rate_rc_wefac_t (GAS_LIQUID_RATE_MULT), -1.0)) + ((WATER_CUT, water_cut_wefac_t (), 1.0)) + ((GAS_OIL_RATIO, gas_oil_ratio_wefac_t (), 1.0)) + ((WATER_GAS_RATIO, water_gas_ratio_wefac_t (), 1.0)) + ((BHP, empty_cell (), 1.0)) + ((BULK_PRESSURE, empty_cell (), 1.0)) + ); + + DATA_LINE (prod_columns_holder_t, well_data, sp_data_t, well_t, + ((WELL_NAME, well_name (), 1.0)) + ((GRID_BLOCK, empty_cell (), 1.0)) + ((CTRL_MODE, ctrl_mode (), 1.0)) + ((WEFAC, wefac (), 1.0)) + ((OIL_RATE, oil_rate_t (), -1.0)) + ((WATER_RATE, water_rate_t (), -1.0)) + ((GAS_RATE, gas_rate_t (), -1.0)) + ((FLUID_RES_VOL, fluid_rate_t (GAS_LIQUID_RATE_MULT), -1.0)) + ((WATER_CUT, water_cut_t (), 1.0)) + ((GAS_OIL_RATIO, well_gas_oil_ratio (), 1.0)) + ((WATER_GAS_RATIO, water_gas_ratio_t (), 1.0)) + ((BHP, first_con_bhp (), 1.0)) + ((BULK_PRESSURE, first_con_bulkp (), 1.0)) + ); + + DATA_LINE (prod_columns_holder_t, connection_data, sp_data_t, connection_t, + ((WELL_NAME, empty_cell (), 1.0)) + ((GRID_BLOCK, grid_block (), 1.0)) + ((CTRL_MODE, empty_cell (), 1.0)) + ((WEFAC, empty_cell (), 1.0)) + ((OIL_RATE, oil_rate_t (), -1.0)) + ((WATER_RATE, water_rate_t (), -1.0)) + ((GAS_RATE, gas_rate_t (), -1.0)) + ((FLUID_RES_VOL, fluid_rate_t (GAS_LIQUID_RATE_MULT), -1.0)) + ((WATER_CUT, water_cut_t (), 1.0)) + ((GAS_OIL_RATIO, gas_oil_ratio_t (), 1.0)) + ((WATER_GAS_RATIO, water_gas_ratio_t (), 1.0)) + ((BHP, con_bhp (GRAVITY), 1.0)) + ((BULK_PRESSURE, con_bulkp (), 1.0)) + ); + }; + + template + struct inj_printer + { + typedef reservoir reservoir_t; + typedef well well_t; + typedef wells::connection connection_t; + typedef smart_ptr sp_data_t; + + DECL_COLUMN_HOLDER (inj_columns_holder_t, 10, + ( + WELL_NAME, + GRID_BLOCK, + CTRL_MODE, + WEFAC, + WATER_RATE, + OIL_RATE, + GAS_RATE, + FLUID_RES_VOL, + BHP, + BULK_PRESSURE + )); + + inj_columns_holder_t columns; + + typedef oil_rate oil_rate_t; + typedef water_rate water_rate_t; + typedef gas_rate gas_rate_t; + + typedef oil_rate oil_rate_wefac_t; + typedef oil_rate water_rate_wefac_t; + typedef oil_rate gas_rate_wefac_t; + + typedef inj_fluid_rate fluid_rate_t; + typedef inj_fluid_rate fluid_rate_rc_wefac_t; + + inj_printer (const sp_data_t &data, const smart_ptr &rs) + { + columns.WELL_NAME (column (12, 0, "WELL NAME"), unit ("")); + columns.GRID_BLOCK (column (15, 0, "LOCATION (I,J,K)"), unit ("")); + columns.CTRL_MODE (column (20, 0, "CTRL MODE"), unit ("")); + columns.WEFAC (column (13, 5, "WEFAC"), unit ("")); + columns.WATER_RATE (column (13, 3, "WATER RATE", LIQUID_RATE_MULT), unit (*rs, water_rate_wefac_t (), RATE_LIQUID_SURFACE_NOTE)); + columns.OIL_RATE (column (14, 3, "OIL RATE", LIQUID_RATE_MULT), unit (*rs, oil_rate_wefac_t (), RATE_LIQUID_SURFACE_NOTE)); + columns.GAS_RATE (column (14, 3, "GAS RATE", GAS_RATE_MULT), unit (*rs, gas_rate_wefac_t (), RATE_GAS_SURFACE_NOTE)); + columns.FLUID_RES_VOL (column (16, 3, "FLUID RES.VOL.", LIQUID_RATE_MULT), unit (*rs, fluid_rate_rc_wefac_t (GAS_LIQUID_RATE_MULT), RATE_LIQUID_RESERVOIR_NOTE)); + columns.BHP (column (15, 2, "BHP OR CON.PR.", PRESSURE_MULT), unit (PRESSURE_NOTE)); + columns.BULK_PRESSURE (column (13, 2, "Bulk Pressure", PRESSURE_MULT), unit (PRESSURE_NOTE)); + } + + DATA_LINE (inj_columns_holder_t, reservoir_data, sp_data_t, reservoir_t, + ((WELL_NAME, reservoir_name (), 1.0)) + ((GRID_BLOCK, empty_cell (), 1.0)) + ((CTRL_MODE, empty_cell (), 1.0)) + ((WEFAC, empty_cell (), 1.0)) + ((WATER_RATE, water_rate_wefac_t (), 1.0)) + ((OIL_RATE, oil_rate_wefac_t (), 1.0)) + ((GAS_RATE, gas_rate_wefac_t (), 1.0)) + ((FLUID_RES_VOL, fluid_rate_rc_wefac_t (GAS_LIQUID_RATE_MULT), 1.0)) + ((BHP, empty_cell (), 1.0)) + ((BULK_PRESSURE, empty_cell (), 1.0)) + ); + + DATA_LINE (inj_columns_holder_t, well_data, sp_data_t, well_t, + ((WELL_NAME, well_name (), 1.0)) + ((GRID_BLOCK, empty_cell (), 1.0)) + ((CTRL_MODE, ctrl_mode (), 1.0)) + ((WEFAC, wefac (), 1.0)) + ((WATER_RATE, water_rate_t (), 1.0)) + ((OIL_RATE, oil_rate_t (), 1.0)) + ((GAS_RATE, gas_rate_t (), 1.0)) + ((FLUID_RES_VOL, fluid_rate_t (GAS_LIQUID_RATE_MULT), 1.0)) + ((BHP, first_con_bhp (), 1.0)) + ((BULK_PRESSURE, first_con_bulkp (), 1.0)) + ); + + DATA_LINE (inj_columns_holder_t, connection_data, sp_data_t, connection_t, + ((WELL_NAME, empty_cell (), 1.0)) + ((GRID_BLOCK, grid_block (), 1.0)) + ((CTRL_MODE, empty_cell (), 1.0)) + ((WEFAC, empty_cell (), 1.0)) + ((WATER_RATE, water_rate_t (), 1.0)) + ((OIL_RATE, oil_rate_t (), 1.0)) + ((GAS_RATE, gas_rate_t (), 1.0)) + ((FLUID_RES_VOL, fluid_rate_t (GAS_LIQUID_RATE_MULT), 1.0)) + ((BHP, con_bhp (GRAVITY), 1.0)) + ((BULK_PRESSURE, con_bulkp (), 1.0)) + ); + }; + + template + struct prod_total_printer + { + typedef reservoir reservoir_t; + typedef well well_t; + typedef wells::connection connection_t; + typedef smart_ptr sp_data_t; + typedef smart_ptr sp_well_t; + + DECL_COLUMN_HOLDER (columns_holder, 9, + ( + WELL_NAME, + CTRL_MODE, + OIL_PROD, + WATER_PROD, + GAS_PROD, + LIQUID_PROD, + WATER_INJ, + OIL_INJ, + GAS_INJ + )); + + columns_holder columns; + + typedef oil_rate prod_oil_rate_t; + typedef water_rate prod_water_rate_t; + typedef gas_rate prod_gas_rate_t; + typedef liquid_rate prod_liquid_rate_t; + + typedef oil_rate inj_oil_rate_t; + typedef water_rate inj_water_rate_t; + typedef gas_rate inj_gas_rate_t; + + prod_total_printer (const sp_data_t &data, const smart_ptr &rs) + { + columns.WELL_NAME (column (12, 0, "WELL NAME"), unit ("")); + columns.CTRL_MODE (column (22, 0, "Current CTRL MODE and status:"), unit ("")); + columns.OIL_PROD (column (17, 0, "Total Oil production", LIQUID_RATE_MULT), unit (*rs, prod_oil_rate_t (), VOL_LIQUID_SURFACE_NOTE)); + columns.WATER_PROD (column (15, 0, "Total Water production", LIQUID_RATE_MULT), unit (*rs, prod_water_rate_t (), VOL_LIQUID_SURFACE_NOTE)); + columns.GAS_PROD (column (20, 0, "Total Gas production", GAS_RATE_MULT), unit (*rs, prod_gas_rate_t (), VOL_GAS_SURFACE_NOTE)); + columns.LIQUID_PROD (column (24, 0, "Total Reser Liq. production", LIQUID_RATE_MULT), unit (*rs, prod_liquid_rate_t (), VOL_LIQUID_RES_NOTE)); + columns.WATER_INJ (column (20, 0, "Total Water injection", LIQUID_RATE_MULT), unit (*rs, inj_water_rate_t (), VOL_LIQUID_SURFACE_NOTE)); + columns.OIL_INJ (column (20, 0, "Total Oil injection", LIQUID_RATE_MULT), unit (*rs, inj_oil_rate_t (), VOL_LIQUID_SURFACE_NOTE)); + columns.GAS_INJ (column (20, 0, "Total Gas injection", GAS_RATE_MULT), unit (*rs, inj_gas_rate_t (), VOL_GAS_SURFACE_NOTE)); + } + + DATA_LINE (columns_holder, reservoir_data, sp_data_t, reservoir_t, + ((WELL_NAME, reservoir_name (), 1.0)) + ((CTRL_MODE, empty_cell (), 1.0)) + ((OIL_PROD, prod_oil_rate_t (), -1.0)) + ((WATER_PROD, prod_water_rate_t (), -1.0)) + ((GAS_PROD, prod_gas_rate_t (), -1.0)) + ((LIQUID_PROD, prod_liquid_rate_t (), -1.0)) + ((WATER_INJ, inj_water_rate_t (), 1.0)) + ((OIL_INJ, inj_oil_rate_t (), 1.0)) + ((GAS_INJ, inj_gas_rate_t (), 1.0)) + ); + + DATA_LINE (columns_holder, well_data, sp_data_t, well_t, + ((WELL_NAME, well_name (), 1.0)) + ((CTRL_MODE, total_ctrl_mode (), 1.0)) + ((OIL_PROD, prod_oil_rate_t (), -1.0)) + ((WATER_PROD, prod_water_rate_t (), -1.0)) + ((GAS_PROD, prod_gas_rate_t (), -1.0)) + ((LIQUID_PROD, prod_liquid_rate_t (), -1.0)) + ((WATER_INJ, inj_water_rate_t (), 1.0)) + ((OIL_INJ, inj_oil_rate_t (), 1.0)) + ((GAS_INJ, inj_gas_rate_t (), 1.0)) + ); + + void + print (const sp_data_t &data, const reservoir_t &rs) + { + print_header (columns); + reservoir_data.print (columns, data, rs); + + typedef typename reservoir_t::facility_manager_t::well_const_iterator_t well_iterator_t; + + well_iterator_t wb = rs.get_facility_list ()->wells_begin (); + well_iterator_t we = rs.get_facility_list ()->wells_end (); + + for (; wb != we; ++wb) + { + sp_well_t well (wb->second, bs_dynamic_cast ()); + well_data.print (columns, data, *well); + } + } + }; + + template + void + well_data_printer ::print_prod (const smart_ptr &data, const smart_ptr , true> &rs) + { + static prod_printer prod_printer_ (data, rs); + + BOSOUT (section::print_reports, level::highest) << + " PRODUCTION REPORT\n" + " -----------------" + << bs_end; + detail::print_well_data (prod_printer_, data, *rs, detail::is_prod ()); + } + + template + void + well_data_printer ::print_inj (const smart_ptr &data, const smart_ptr , true> &rs) + { + static inj_printer inj_printer_ (data, rs); + + BOSOUT (section::print_reports, level::highest) << + " INJECTOR REPORT\n" + " ---------------" + << bs_end; + detail::print_well_data (inj_printer_, data, *rs, detail::is_inj ()); + } + + template + void + well_data_printer ::print_total_prod (const smart_ptr &data, const smart_ptr , true> &rs) + { + static prod_total_printer prod_total_printer_ (data, rs); + + BOSOUT (section::print_reports, level::highest) << + " CUMULATIVE INJECTION/PRODUCTION TOTAL\n" + " -------------------------------------" + << bs_end; + prod_total_printer_.print (data, *rs); + } + + template struct well_data_printer ; + template struct well_data_printer ; + template struct well_data_printer ; + +} // namespace blue_sky + diff --git a/bs_bos_core/src/well_results_storage.cpp b/bs_bos_core/src/well_results_storage.cpp new file mode 100644 index 0000000..ac8c4dd --- /dev/null +++ b/bs_bos_core/src/well_results_storage.cpp @@ -0,0 +1,96 @@ +/** + * @file well_results_storage.cpp + * @brief well results storage + * @author Sayfullin Ilshat + * @date 2009-01-28 + */ +#include "stdafx.h" +#include "well_results_storage.h" + +namespace blue_sky + { + + /** + * @brief constructor + */ + connection_results::connection_results () + { + d_params.resize (CONN_D_PARAM_COUNT); + i_params.resize (CONN_I_PARAM_COUNT); + } + + /** + * @brief destructor + */ + connection_results::~connection_results () + {} + + void + connection_results::clear () + { + for (size_t i = 0, cnt = d_params.size (); i < cnt; ++i) + { + d_params[i].clear (); + } + + for (size_t i = 0, cnt = i_params.size (); i < cnt; ++i) + { + i_params[i].clear (); + } + } + + /** + * @brief constructor + */ + well_results::well_results () + { + d_params.resize (WELL_D_PARAM_COUNT); + i_params.resize (WELL_I_PARAM_COUNT); + } + + /** + * @brief destructor + */ + well_results::~well_results () + {} + + void + well_results::clear () + { + dates.clear (); + + for (size_t i = 0, cnt = d_params.size (); i < cnt; ++i) + { + d_params[i].clear (); + } + + for (size_t i = 0, cnt = i_params.size (); i < cnt; ++i) + { + i_params[i].clear (); + } + } + + /** + * @brief constructor + */ + well_results_storage::well_results_storage (bs_type_ctor_param param /* = NULL */) + {} + well_results_storage::well_results_storage (const well_results_storage& src) + : bs_refcounter (src), objbase (src) + { + *this = src; + } + /** + * @brief destructor + */ + well_results_storage::~well_results_storage () + {} + + class well_results; + class connection_results; + + BLUE_SKY_TYPE_STD_CREATE(well_results_storage) + BLUE_SKY_TYPE_STD_COPY(well_results_storage) + BLUE_SKY_TYPE_IMPL_SHORT(well_results_storage, objbase, "well_results_storage") +} //blue_sky + diff --git a/bs_bos_core/src/well_serializer.cpp b/bs_bos_core/src/well_serializer.cpp new file mode 100644 index 0000000..06420db --- /dev/null +++ b/bs_bos_core/src/well_serializer.cpp @@ -0,0 +1,68 @@ +/** + * \file well_serializer.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 21.07.2008 + * */ +#include "stdafx.h" + +#include "calc_well.h" +#include "well_serializer.h" +#include "well_connection.h" +#include "reservoir.h" +#include "facility_manager.h" +namespace blue_sky + { + namespace wells + { + + template + well_serializer::well_serializer (bs_type_ctor_param param /* = NULL */) + { + handled_type_ = well_t::bs_type (); + } + template + well_serializer::well_serializer (const well_serializer& w) + : bs_refcounter (w), data_serializer (w) + { + handled_type_ = well_t::bs_type (); + } + + template + void + well_serializer::save (const sp_storage_t &storage, const sp_obj &obj) const + { + sp_well_t w (obj, bs_dynamic_cast ()); + + BS_ASSERT (w) (obj->bs_resolve_type ().stype_); + + const sp_storage_t &locked_storage (storage); + data_storage &st = *locked_storage; + + st.save ("i_coord", w->i_coord_) + .save ("j_coord", w->j_coord_) + .save ("name", w->name_) + ; + } + + ////////////////////////////////////////////////////////////////////////// + BLUE_SKY_TYPE_STD_CREATE_T_DEF (well_serializer, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (well_serializer, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_serializer ), 1, (data_serializer), "well_serializer_seq_fi", "well_serializer", "well_serializer", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (well_serializer ), 1, (data_serializer), "well_serializer_seq_di", "well_serializer", "well_serializer", false); + + ////////////////////////////////////////////////////////////////////////// + bool + well_serializer_register_type (const plugin_descriptor &pd) + { + bool res = true; + + res &= BS_KERNEL.register_type (pd, well_serializer::bs_type ()); + BS_ASSERT (res); + res &= BS_KERNEL.register_type (pd, well_serializer::bs_type ()); + BS_ASSERT (res); + + return res; + } + } // namespace wells +} // namespace blue_sky diff --git a/bs_bos_core/src/wellbore_density_calc.cpp b/bs_bos_core/src/wellbore_density_calc.cpp new file mode 100644 index 0000000..aa38938 --- /dev/null +++ b/bs_bos_core/src/wellbore_density_calc.cpp @@ -0,0 +1,359 @@ +/** + * \file wellbore_density_calc.h + * \brief impl of + * \author Sergey Miryanov + * \date 18.11.2008 + * */ +#include "stdafx.h" + +#include "wellbore_density_calc.h" + +#include "calc_model.h" +#include "calc_well.h" +#include "well_connection.h" + +#include "well_rate_control.h" + +#include "reservoir.h" +#include "facility_manager.h" +namespace blue_sky + { + + template + wellbore_density_calc::wellbore_density_calc (bs_type_ctor_param param /* = NULL */) + { + + } + template + wellbore_density_calc::wellbore_density_calc (const wellbore_density_calc &x) + : bs_refcounter (x) + { + + } + + template + void + wellbore_density_calc ::calculate (sp_well_t &well, const sp_calc_model_t &calc_model) const + { + BS_ASSERT (!well->is_shut ()) (well->name ()); + + typedef typename base_t::well_t well_t; + typedef typename base_t::calc_model_t calc_model_t; + typedef typename well_t::connection_t connection_t; + typedef typename well_t::sp_connection_t sp_connection_t; + typedef typename well_t::sp_connection_t sp_connection_t; + + item_t atm_pressure = calc_model->internal_constants.atmospheric_pressure; + + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &c (well->get_connection (i)); + + item_t pbhp = calc_model->pressure[c->n_block ()]; + if (c->cur_bhp >= atm_pressure) + { + pbhp = c->cur_bhp; + } + else if (well->bhp () >= atm_pressure) + { + pbhp = well->bhp (); + } + + if (density_calc (well, calc_model, pbhp)) + return ; + } + + // TODO: throw exception + return ; + } + + template + bool + wellbore_density_calc ::density_calc (sp_well_t &well, const sp_calc_model_t &calc_model, item_t p_bhp) const + { + BS_ASSERT (!well->is_shut ()) (well->name ()); + BS_ASSERT (well->get_connections_count ()) (well->name ()); + + typedef typename base_t::index_t index_t; + typedef typename base_t::well_t::sp_connection_t sp_connection_t; + typedef typename base_t::calc_model_t::sp_pvt_water sp_pvt_water_t; + typedef typename base_t::calc_model_t::sp_pvt_gas sp_pvt_gas_t; + typedef typename base_t::calc_model_t::sp_pvt_dead_oil sp_pvt_dead_oil_t; + typedef typename base_t::well_t::sp_connection_t sp_connection_t; + + item_t gravity_const = calc_model->internal_constants.gravity_constant; + index_t n_phases = calc_model->n_phases; + + index_t d_w = calc_model->phase_d[FI_PHASE_WATER]; + index_t d_g = calc_model->phase_d[FI_PHASE_GAS]; + index_t d_o = calc_model->phase_d[FI_PHASE_OIL]; + index_t d_s_w = calc_model->sat_d[FI_PHASE_WATER]; + index_t d_s_g = calc_model->sat_d[FI_PHASE_GAS]; + + bool is_w = calc_model->is_water (); + bool is_g = calc_model->is_gas (); + bool is_o = calc_model->is_oil (); + + boost::array local_invers_fvf; + local_invers_fvf.assign (0); + + BS_ERROR (well->get_connections_count (), "density_calc"); + + const sp_connection_t &first_con = well->get_connection (0); + BS_ASSERT (first_con); + + item_t ppo = 0; + if (!p_bhp) + { + // Average pressure is equal BHP at first connection ... + if (first_con->cur_bhp) + ppo = first_con->cur_bhp; + // or reservoir pressure at connection + else if (well->bhp ()) + ppo = well->bhp (); + else + ppo = calc_model->pressure[first_con->n_block ()]; + } + else + ppo = p_bhp; + + item_t ppo1 = ppo; + item_t p_water = 0; + item_t p_gas = 0; + item_t p_oil = 0; + item_t rrso = 0.0f; + + item_t sat_w = 0; + item_t sat_g = 0; + item_t sat_o = 0; + + typename base_t::well_t::sp_well_controller_t well_controller_ = well->get_well_controller (); + wells::injection_type injection = well_controller_->injection (); + + const rate_data &rate = well->rate (); + + sp_connection_t prev_con; + for (size_t i = 0, cnt = well->get_connections_count (); i < cnt; ++i) + { + const sp_connection_t &con (well->get_connection (i)); + + index_t n_block = con->n_block (); + index_t n_pvt_reg = calc_model->pvt_regions[n_block]; + index_t i_w = n_block * n_phases + d_w; + index_t i_g = n_block * n_phases + d_g; + index_t i_o = n_block * n_phases + d_o; + + item_t con_denom = 0; + item_t con_upnom = 0; + + if (prev_con && prev_con->cur_bhp) + ppo1 = prev_con->cur_bhp + 0.5 * (prev_con->density + con->density) * gravity_const * + (con->connection_depth - prev_con->connection_depth); + else + ppo1 = ppo; + + sp_pvt_water_t pvt_water; + sp_pvt_gas_t pvt_gas; + sp_pvt_dead_oil_t pvt_oil; + + if (is_w) + pvt_water = calc_model->pvt_water_array [n_pvt_reg]; + if (is_g) + pvt_gas = calc_model->pvt_gas_array [n_pvt_reg]; + if (is_o) + pvt_oil = calc_model->pvt_oil_array [n_pvt_reg]; + + if (ppo1) + p_oil = ppo1; + else + p_oil = ppo; + p_water = p_gas = p_oil; + + if (n_phases > 1) + { + // two or three phases + // water phase + if (is_w) + p_water += calc_model->data[n_block].cap_pressure[d_s_w]; + // gas phase + if (is_g) + p_gas += calc_model->data[n_block].cap_pressure[d_s_g]; + } + + // calculate 1 / (formation volume factor), 1 / (viscosity), 1 / (viscosity) / (fvf) + // and derivates + // water phase + // calculate pvt properties + if (is_w) + { + pvt_water->calc (p_water, &local_invers_fvf[d_w], 0, 0, 0, 0, 0); + } + if (is_g) + { + pvt_gas->calc (p_gas, &local_invers_fvf[d_g], 0, 0, 0, 0, 0); + } + if (is_o && is_g) + { + rrso = calc_model->gas_oil_ratio[n_block]; + if (!pvt_oil->calc (is_g, calc_model->main_variable[n_block], + p_oil, rrso, + &local_invers_fvf[d_o], 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0)) + { + BOSERR (section::wells, level::error) << "pvt_oil (o && g) can't calculate (" << p_oil << ", " << rrso << ")" << bs_end; + BOSERR (section::wells, level::error) << "p_bhp: " << p_bhp << bs_end; + if (first_con->cur_bhp) + BOSERR (section::wells, level::error) << "first_con: " << first_con->cur_bhp << bs_end; + else if (well->bhp ()) + BOSERR (section::wells, level::error) << "well: " << well->bhp () << bs_end; + else + BOSERR (section::wells, level::error) << "pressure: " << calc_model->pressure[first_con->n_block ()] << bs_end; + // TODO: BUG: + //throw bs_exception ("wellbore_density_calc", "pvt->oil (o && g) can't calc"); + return false; + } + } + else if (is_o) + { + if (!pvt_oil->calc (is_g, -1, p_oil, 0, + &local_invers_fvf[d_o], 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0)) + { + BOSERR (section::wells, level::error) << "pvt_oil (o) can't calculate (" << p_oil << ", " << rrso << ")" << bs_end; + BOSERR (section::wells, level::error) << "p_bhp: " << p_bhp << bs_end; + if (first_con->cur_bhp) + BOSERR (section::wells, level::error) << "first_con: " << first_con->cur_bhp << bs_end; + else if (well->bhp ()) + BOSERR (section::wells, level::error) << "well: " << well->bhp () << bs_end; + else + BOSERR (section::wells, level::error) << "pressure: " << calc_model->pressure[first_con->n_block ()] << bs_end; + // TODO: BUG: + //throw bs_exception ("wellbore_density_calc", "pvt->oil (o) can't calc"); + return false; + } + } + + // production well + if (well_controller_->is_production ()) + { + // water phase + if (is_w) + { + con_denom += rate.prod.water / local_invers_fvf[d_w]; + con_upnom += pvt_water->get_surface_density () * rate.prod.water / local_invers_fvf[d_w]; + } + + // gas phase + if (is_g) + { + con_denom += (rate.prod.gas - rrso * rate.prod.oil) / local_invers_fvf[d_g]; + con_upnom += pvt_gas->get_surface_density () * (rate.prod.gas - rrso * rate.prod.oil) / local_invers_fvf[d_g]; + } + + // oil phase + if (is_o) + { + con_denom += rate.prod.oil / local_invers_fvf[d_o]; + con_upnom += pvt_oil->get_surface_density () * rate.prod.oil / local_invers_fvf[d_o]; + } + + // calculate density for current connection + if (fabs (con_denom) > EPS_DIV) + { + con->density = con_upnom / con_denom; + } + else + { + con->density = 0.0; + sat_w = 0.0; + sat_g = 0.0; + sat_o = 0.0; + + if (n_phases > 1) + { + if (is_w) + { + sat_w = calc_model->saturation_3p[i_w]; + con->density += sat_w * pvt_water->get_surface_density () * local_invers_fvf[d_w]; + } + + if (is_g && is_o) + { + sat_g = calc_model->saturation_3p[i_g]; + sat_o = calc_model->saturation_3p[i_o]; + con->density += sat_g * pvt_gas->get_surface_density () * local_invers_fvf[d_g] + + sat_o * (pvt_oil->get_surface_density () + + calc_model->gas_oil_ratio[n_block] * pvt_gas->get_surface_density ()) * local_invers_fvf[d_o]; + } + else if (is_o) + { + sat_o = calc_model->saturation_3p[i_o]; + con->density += sat_o * pvt_oil->get_surface_density () * local_invers_fvf[d_o]; + } + else if (is_g) + { + sat_g = calc_model->saturation_3p[i_g]; + con->density += sat_g * pvt_gas->get_surface_density () * local_invers_fvf[d_g]; + } + } + else + { + // one phase only + if (is_w) + { + con->density = pvt_water->get_surface_density () * local_invers_fvf[d_w]; + } + if (is_g) + { + con->density = pvt_gas->get_surface_density () * local_invers_fvf[d_g]; + } + if (is_o) + { + con->density = pvt_oil->get_surface_density () * local_invers_fvf[d_o]; + } + } + } + } + // injection well + else //if (well->current_status > 0) + { + if (injection == wells::injection_water) + { + if (is_w) + con->density = pvt_water->get_surface_density () * local_invers_fvf[d_w]; + else + return false; + } + else if (injection == wells::injection_gas) + { + if (is_g) + con->density = pvt_gas->get_surface_density () * local_invers_fvf[d_g]; + else + return false; + } + else if (injection == wells::injection_oil) + { + if (is_o) + con->density = pvt_oil->get_surface_density () * local_invers_fvf[d_o]; + else + return false; + } + } + } + + return true; + } + + BLUE_SKY_TYPE_STD_CREATE_T_DEF (wellbore_density_calc, (class)); + BLUE_SKY_TYPE_STD_COPY_T_DEF (wellbore_density_calc, (class)); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (wellbore_density_calc ), 1, (objbase), "wellbore_density_calc_fi", "wellbore_density_calc_fi", "wellbore_density_calc_fi", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (wellbore_density_calc), 1, (objbase), "wellbore_density_calc_di", "wellbore_density_calc_di", "wellbore_density_calc_di", false); + BLUE_SKY_TYPE_IMPL_T_EXT (1, (wellbore_density_calc), 1, (objbase), "wellbore_density_calc_mixi", "wellbore_density_calc_mixi", "wellbore_density_calc_mixi", false); + + +} // namespace blue_sky + diff --git a/bs_bos_core/src/wells_compute_connection_factors.cpp b/bs_bos_core/src/wells_compute_connection_factors.cpp new file mode 100644 index 0000000..bd254c2 --- /dev/null +++ b/bs_bos_core/src/wells_compute_connection_factors.cpp @@ -0,0 +1,279 @@ +/** + * \file wells_compute_connection_factors.cpp + * \brief impl of + * \author Sergey Miryanov + * \date 08.07.2008 + * */ +#include "stdafx.h" + +#include "calc_well.h" +#include "wells_compute_connection_factors.h" +#include "wells_common_const.h" +#include "fi_params.h" +#include "well_connection.h" + +namespace blue_sky + { + namespace wells + { + namespace compute_factors + { + + /** + * \brief computes connection factor by peaceman model. + * d1 equals to msh->elements[k].d[dir_plane1] + * d2 equals to msh->elements[k].d[dir_plane2] + * d3 or d_ort equals to msh->elements[k].d[dir_orthogonal] + * */ + template + void + peaceman_model::compute (connection_t &con, + const physical_constants &internal_constants, + const sp_params_t ¶ms, + const sp_mesh_iface_t &mesh, + const item_array_t &perm, + const item_array_t &ntg, + bool ro_calc_flag) + { + BS_ASSERT (con.n_block_ >= 0) (con.n_block_); + + int dir_orth = con.dir_; + int dir_plane1 = (dir_orth + 1) % 3; + int dir_plane2 = (dir_orth + 2) % 3; + + item_t d1, d2, d_ort; + item_t d[] = {0, 0, 0}; + mesh->get_element_size (con.n_block (), d[0], d[1], d[2]); + d1 = d[dir_plane1]; + d2 = d[dir_plane2]; + d_ort = d[dir_orth]; + + item_t perm1 = (perm[3 * con.n_block () + dir_plane1]); + item_t perm2 = (perm[3 * con.n_block () + dir_plane2]); + item_t coef1 = fabs (perm1) < 1.0e-7 ? sqrt (perm2) : sqrt (perm2 / perm1); + item_t coef2 = fabs (perm2) < 1.0e-7 ? sqrt (perm1) : sqrt (perm1 / perm2); + + if (con.R0_ < MIN_ZERO_DIFF || ro_calc_flag) + { + item_t denomin = sqrt (coef1) + sqrt (coef2); + if (denomin > 1.0e-7) + con.R0_ = 0.28 * sqrt (coef1 * d1 * d1 + coef2 * d2 * d2) / denomin; + else + { + BS_ASSERT (denomin > 1.0e-7) (denomin) (coef1) (coef2); + throw bs_exception ("well::connection::compute_factors_by_peaceman_model", "Connection factor is equal to zero"); + } + } + + if (::log (2.0 * con.R0_ / con.diam_) + con.skin_ < MIN_ZERO_DIFF) + { + if (params->get_bool (fi_params::USE_LOW_SKIN_TRANS_MULT)) + { + item_t D = item_t (0.14036); + item_t alpha = d1 > d2 ? (d1 / d2) : (d2 / d1); + item_t dP = 1. / (2. * PI) * ::log (sqrt (1. / ((alpha * alpha + 1) * 4 * D * D) + + (alpha - 1) / (alpha + 1))+ 1. / (2 * D * sqrt (alpha * alpha + 1)));; + + if (con.skin_ < ::log (con.diam_ / (2 * con.R0_)) - 2 * PI * dP) + { + BS_ASSERT (con.skin_ >= ::log (con.diam_ / (2 * con.R0_)) - 2 * PI * dP) (::log (con.diam_ / (2 * con.R0_)) - 2 * PI * dP) (dP); + throw bs_exception ("well::connection::compute_factors_by_peaceman_model", "Wrong value of skin factor for connection"); + } + + con.skin_ += 2 * PI * dP; + } + else + { + BS_ASSERT (false && "FI_PARAMS_B_USE_LOW_SKIN_TRANS_MULT"); + throw bs_exception ("well::connection::compute_factors_by_peaceman_model", "Wrong value of skin factor for connection"); + } + } + + if (con.kh_ <= 0 || ro_calc_flag) + { + con.kh_ = sqrt (perm1 * perm2) * d_ort; + } + + item_t cdarcy = 2 * PI * internal_constants.darcy_constant; + con.fact_ = cdarcy * con.mult_ * con.kh_ / ((::log (2. * con.R0_ / con.diam_) + con.skin_)); + + if (dir_orth == direction_z) + { + con.fact_ *= ntg[con.n_block_]; + + if (con.connection_type_ != CONNECTION_USUAL) + { +#ifndef _USE_GRP_FRACTURE_CORRELATION_ + con.fact_ *= compute_grp_pi_mult (con); +#else + item_t fracture_mult_corr = fracture_mult_correlat (sqrt (d1 * d2), 2.0 * con.fracture_half_length_); + if (fracture_mult_corr < MIN_FRACTURE_MULT_CORR) + { + BOSWARN (section::wells, level::warning) << "Couldn't correlate multiplier for fracture in cell for well" << bs_end; + } + else + { + con.fact_ *= fracture_mult_corr; + } +#endif + } + } + + if (con.fact_ < -MIN_ZERO_DIFF) + { + bs_throw_exception (boost::format ("Negative value of connection factor %f for connection of well") % con.fact_); + } + } + + template + typename strategy_t::item_t + peaceman_model::compute_grp_pi_mult (connection_t &con) + { + return (::log (4.0 * con.fracture_half_length_ / con.diam_) /*+ con.skin_ */) / (::log (4.0) /*+ con.skin_ */); + } + + ////////////////////////////////////////////////////////////////////////// + ///** + // * \brief computes connection factor by baby and odeh model. + // * d1 equals to msh->elements[k].d[dir_plane] + // * d2 equals to msh->elements[k].d[dir_orth] + // * d3 equals to msh->elements[k].d[2] + // * */ + //void + //baby_odeh_model::compute (well::connection &con, + // physical_constants *internal_constants, + // item_t d1, item_t d2, item_t d3, + // item_t perm1, item_t perm2, item_t perm3, + // const well::item_array_t &ntg, + // bool ro_calc_flag) + //{ + // item_t kr_z = perm1; + // item_t k_orth = perm2; + // item_t kr_plane = perm3; + // item_t c = d1; + // item_t d = d2; + // item_t h = d3; + + // item_t center_coordinate_xy = c * 0.5; + // item_t center_coordinate_z = h * 0.5; + + // item_t coef1 = sqrt (kr_z / kr_plane); + // item_t coef2 = c / h; + // item_t coef3 = center_coordinate_xy / c; + + // // compute log (C_h) + // item_t log_Ch = 6.28 * coef2 * coef1 * (1. / 3. - coef3 + coef3 * coef3) + // - log (fabs (sin (PI * center_coordinate_z / h))) + // - 0.5 * log (coef2 * coef1) + // - 1.088; + + // item_t full_skin = 0.0; + // const item_t &L = con.d_length_; + // item_t y_mid = 0.0; + + // if (L < DIFF_EPSILON) + // { + // con.fact_ = 0.0; + // return ; + // } + + // // case 1: connection fully penetrates well grid block + // if (L >= d) + // { + // full_skin = con.skin_; + // } + // // case 2: + // else if (c / sqrt (kr_plane) >= 0.75 * d / sqrt (k_orth)) + // { + // y_mid = (con.con_end_distance_ + con.con_start_distance_) * 0.5; + // item_t p_xyz = (d / L - 1.0) * (log (h / con.diam_) + 0.25 * log (kr_plane / kr_z) + // - log (sin (PI * center_coordinate_z / h)) - 1.84); + // item_t p_xy = (2.0 * d * d / (L * h)) * sqrt (kr_z / k_orth) + // * (F_table (L, d, y_mid, 0) + 0.5 * (F_table (L, d, y_mid, 1) - F_table (L, d, y_mid, 2))); + // full_skin = con.skin_ + p_xyz + p_xy; + // } + // // case 3: + // else + // { + // y_mid = (con.con_end_distance_ + con.con_start_distance_) * 0.5; + // item_t p_xyz = (d / L - 1.0) * (log (h / con.diam_) + 0.25 * log (kr_plane / kr_z) + // - log (sin (PI * center_coordinate_z / h)) - 1.84); + // item_t p_y = (6.28 * d * d / (c * h)) * sqrt (kr_z * kr_plane) / k_orth + // * (1.0 / 3.0 - y_mid / d + y_mid * y_mid / (d * d) + L / (24.0 * d) * (L / d - 3.0)); + // item_t p_xy = (d / L - 1.0) * 6.28 * (c / h) * coef1 * (1.0 / 3.0 - coef3 + coef3 * coef3); + // full_skin = con.skin_ + p_xyz + p_y + p_xy; + // } + + // item_t cdarcy = 2 * PI * internal_constants->darcy_constant; + // con.fact_ = cdarcy * con.mult_ * sqrt (kr_z * kr_plane) * d + // / ((log (sqrt (c * h) / con.diam_) + log_Ch + full_skin - 0.75)); + //} + + ////! definition of constant #1 + //#define CONST_1 0.145 + ////! definition of constant #2 + //#define CONST_2 0.137 + ///*! + //\brief prototype of table function + //*/ + //inline item_t f_prototype (item_t x) + //{ + // return x * (CONST_1 + log (x) - CONST_2 * x * x); + //} + ///*! + //\brief Function for horizontal wells for Babu model + //\param L -- length of connection + //\param d -- block size + //\param y_mid -- middle point + //\param arg_type -- type of arguments of function F + //*/ + //item_t baby_odeh_model::F_table (item_t L, item_t d, item_t y_mid, int arg_type) + //{ + // item_t s; + // item_t s1; + // item_t s2; + // + // s = L / (2. * d); + // s1 = (4. * y_mid + L) / (2. * d); + // s2 = (4. * y_mid - L) / (2. * d); + // item_t result = 0.0; + // + // if (arg_type == 1) + // { + // if (s1 <= 1) + // { + // result = (-1.0) * f_prototype (s1); + // } + // else // s1 > 1 + // { + // item_t v = 2.0 - s1; + // result = f_prototype (v); + // } + // } + // else if (arg_type == 2) + // { + // if (s2 <= 1) + // { + // result = (-1.0) * f_prototype (s2); + // } + // else + // { + // item_t v = 2.0 - s2; + // result = f_prototype (v); + // } + // } + // else // arg)type == 0 + // { + // result = (-1.0) * f_prototype (s); + // } + // return result; + //} + + template struct peaceman_model ; + template struct peaceman_model ; + template struct peaceman_model ; + + } // namespace compute_factors + } // namespace wells +} // namespace blue_sky + diff --git a/bs_bos_core_base/SConscript.bs b/bs_bos_core_base/SConscript.bs new file mode 100644 index 0000000..b619153 --- /dev/null +++ b/bs_bos_core_base/SConscript.bs @@ -0,0 +1,26 @@ +import os +Import ("*") + +lib_name = "bs_bos_core_base" +tar_name = "bs_bos_core_base" + +env = custom_env.Clone () +env.Append (CPPPATH = ["include"] + includes["kernel"]) + +if (build_kind == "debug") : + env.AppendUnique (LIBS = ["blue_sky_d"]) + lib_name += "_d" +elif (build_kind == "release") : + env.AppendUnique (LIBS = ["blue_sky"]) + +bs_bos_core_base = env.SharedLibrary (target = os.path.join (tar_exe_plugin_dir, lib_name), source = files (["."], ["property_base_new.cpp", "stdafx.cpp"]).sources) + +env.Alias (tar_name, bs_bos_core_base) +Export ("bs_bos_core_base") + +if (env["install"] == 1) : + inst_tar = env.Install ("$plugins_prefix", bs_bos_core_base) + env.Alias (tar_name, inst_tar) + + + diff --git a/bs_bos_core_base/bs_bos_core_base.vcproj b/bs_bos_core_base/bs_bos_core_base.vcproj new file mode 100644 index 0000000..052bc8c --- /dev/null +++ b/bs_bos_core_base/bs_bos_core_base.vcproj @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bs_bos_core_base/include/auto_value.h b/bs_bos_core_base/include/auto_value.h new file mode 100644 index 0000000..741eda8 --- /dev/null +++ b/bs_bos_core_base/include/auto_value.h @@ -0,0 +1,253 @@ +/** + * \file auto_value.h + * \brief helper to init scalar variables with auto value + * \author Sergey Miryanov, idea Kodt@RSDN + * \date 10.09.2008 + */ +#ifndef BS_AUTO_VALUE_HELPER_H_ +#define BS_AUTO_VALUE_HELPER_H_ + +namespace blue_sky + { + + // TODO: type traits + template + class auto_value + { + public: + typedef T data_t; + typedef auto_value &self_t; + + inline auto_value() + : t_(T (value)) +#ifdef _DEBUG + , is_init_ (false) +#endif + { + } + + template< class V > + inline auto_value(V v) + : t_(v) +#ifdef _DEBUG + , is_init_ (true) +#endif + { + } + + inline const T& data() const + { + return t_; + } + inline T& data() + { + return t_; + } + + inline operator T () const + { + return t_; + } + inline operator T& () + { + return t_; + } + +#ifdef _DEBUG + template< class V > inline self_t operator = (V v) + { + t_ = v; + is_init_ = true; + return *this; + } +#else + template< class V > inline self_t operator = (V v) + { + t_ = v; + return *this; + } +#endif + template< class V > inline self_t operator += (V v) + { + t_ += v; + return *this; + } + template< class V > inline self_t operator -= (V v) + { + t_ -= v; + return *this; + } + template< class V > inline self_t operator *= (V v) + { + t_ *= v; + return *this; + } + template< class V > inline self_t operator /= (V v) + { + t_ /= v; + return *this; + } + template< class V > inline self_t operator %= (V v) + { + t_ %= v; + return *this; + } + template< class V > inline self_t operator &= (V v) + { + t_ &= v; + return *this; + } + template< class V > inline self_t operator |= (V v) + { + t_ |= v; + return *this; + } + template< class V > inline self_t operator ^= (V v) + { + t_ ^= v; + return *this; + } + template< class V > inline self_t operator <<= (V v) + { + t_ <<= v; + return *this; + } + template< class V > inline self_t operator >>= (V v) + { + t_ >>= v; + return *this; + } + + inline self_t operator ++ () + { + ++t_; + return *this; + } + inline data_t operator ++ (int) + { + return t_++; + } + inline self_t operator -- () + { + --t_; + return *this; + } + inline data_t operator -- (int) + { + return t_--; + } + +#ifdef _DEBUG + inline bool is_init () const + { + return is_init_; + } +#endif + + private: + T t_; +#ifdef _DEBUG + bool is_init_; +#endif + }; + + //template<> + //class auto_value + //{ + //public: + // typedef float T; + // typedef T data_t; + // typedef auto_value &self_t; + + // enum { value = 0 }; + + // inline auto_value() + // : t_(value) + // { + // } + + // template< class V > + // inline auto_value(V v) + // : t_(v) + // { + // } + + // inline const T& data() const { return t_; } + // inline T& data() { return t_; } + + // inline operator T () const { return t_; } + // inline operator T& () { return t_; } + + // template< class V > inline self_t operator = (V v) { t_ = v; return *this; } + // template< class V > inline self_t operator += (V v) { t_ += v; return *this; } + // template< class V > inline self_t operator -= (V v) { t_ -= v; return *this; } + // template< class V > inline self_t operator *= (V v) { t_ *= v; return *this; } + // template< class V > inline self_t operator /= (V v) { t_ /= v; return *this; } + // template< class V > inline self_t operator %= (V v) { t_ %= v; return *this; } + // template< class V > inline self_t operator &= (V v) { t_ &= v; return *this; } + // template< class V > inline self_t operator |= (V v) { t_ |= v; return *this; } + // template< class V > inline self_t operator ^= (V v) { t_ ^= v; return *this; } + // template< class V > inline self_t operator <<= (V v) { t_ <<= v; return *this; } + // template< class V > inline self_t operator >>= (V v) { t_ >>= v; return *this; } + + // inline self_t operator ++ () { ++t_; return *this; } + // inline data_t operator ++ (int) { return t_++; } + // inline self_t operator -- () { --t_; return *this; } + // inline data_t operator -- (int) { return t_--; } + + //private: + // T t_; + //}; + + //template<> + //class auto_value + //{ + //public: + // typedef float T; + // typedef T data_t; + // typedef auto_value &self_t; + + // enum { value = 0 }; + + // inline auto_value() + // : t_(value) + // { + // } + + // template< class V > + // inline auto_value(V v) + // : t_(v) + // { + // } + + // inline const T& data() const { return t_; } + // inline T& data() { return t_; } + + // inline operator T () const { return t_; } + // inline operator T& () { return t_; } + + // template< class V > inline self_t operator = (V v) { t_ = v; return *this; } + // template< class V > inline self_t operator += (V v) { t_ += v; return *this; } + // template< class V > inline self_t operator -= (V v) { t_ -= v; return *this; } + // template< class V > inline self_t operator *= (V v) { t_ *= v; return *this; } + // template< class V > inline self_t operator /= (V v) { t_ /= v; return *this; } + // template< class V > inline self_t operator %= (V v) { t_ %= v; return *this; } + // template< class V > inline self_t operator &= (V v) { t_ &= v; return *this; } + // template< class V > inline self_t operator |= (V v) { t_ |= v; return *this; } + // template< class V > inline self_t operator ^= (V v) { t_ ^= v; return *this; } + // template< class V > inline self_t operator <<= (V v) { t_ <<= v; return *this; } + // template< class V > inline self_t operator >>= (V v) { t_ >>= v; return *this; } + + // inline self_t operator ++ () { ++t_; return *this; } + // inline data_t operator ++ (int) { return t_++; } + // inline self_t operator -- () { --t_; return *this; } + // inline data_t operator -- (int) { return t_--; } + + //private: + // T t_; + //}; + +} // namespace blue_sky + + +#endif // #ifndef BS_AUTO_VALUE_HELPER_H_ diff --git a/bs_bos_core_base/include/bos_report.h b/bs_bos_core_base/include/bos_report.h new file mode 100644 index 0000000..cc36a7c --- /dev/null +++ b/bs_bos_core_base/include/bos_report.h @@ -0,0 +1,207 @@ +#ifndef BOS_REPORT_H +#define BOS_REPORT_H + +#include BS_FORCE_PLUGIN_IMPORT () +#include "bs_report.h" +#include BS_STOP_PLUGIN_IMPORT () + +#include +#include + +#define STLOG BS_KERNEL.get_log () +#define MTLOG BS_KERNEL.get_tlog () + +#define BOSOUT STLOG.get_locked ("bos_out", __FILE__, __LINE__) +#define BOSERR STLOG.get_locked ("bos_err", __FILE__, __LINE__) +#define BOSWARN STLOG.get_locked ("bos_warn", __FILE__, __LINE__) + +#define MBOSOUT MTLOG["bos_out"] +#define MBOSERR MTLOG["bos_err"] +#define MBOSWARN MTLOG["bos_warn"] + +#define MTLOG_INIT \ + MTLOG.add_log_channel(sp_channel(new bs_channel(*BOSOUT))); \ + MTLOG.add_log_channel(sp_channel(new bs_channel(*BOSERR))); \ + MTLOG.add_log_channel(sp_channel(new bs_channel(*BOSWARN))); \ + +#define MTLOG_FINI \ + MTLOG.rem_log_channel("bos_out"); \ + MTLOG.rem_log_channel("bos_err"); \ + MTLOG.rem_log_channel("bos_warn"); \ + +namespace blue_sky +{ + //namespace sn + // { + // typedef enum + // { + // sn_start, + // read, /*Messages about reading input data*/ + // write, /*Messages about writing input data*/ + // check, /*Messages about checking input data*/ + // init, /*Messages about initialization of simulation process*/ + // iters, /*Messages about iteration process*/ + // fip, /*Messages about fip*/ + // solve, /*Messages about solving*/ + // gui, /*Messages about user interface*/ + // jacobian, /*Messages about jacobian*/ + // rsv, /*Messages about reservoir*/ + // group, /*Messages about well groups*/ + // well, /*Messages about wells*/ + // conn, /*Messages about connections*/ + // print_logs, /*Messages about logs*/ + // sys_info, /*Messages about current system*/ + // thread_info, /*Messages about current thread*/ + // sn_end + // } section_names; + //} + +#define DECL_LOG_SECTIONS_ENUM_I(r, data, i, elem) \ + BOOST_PP_TUPLE_ELEM (3, 0, elem), + +#define DECL_LOG_LEVELS_ENUM_I(r, data, i, elem) \ + BOOST_PP_TUPLE_ELEM (3, 0, elem), + +#define DECL_LOG_SECTIONS_KEYWORD_HANDLER_I(r, data, i, elem) \ + if (BOOST_PP_TUPLE_ELEM (3, 1, elem) == name) \ + { \ + using namespace section; \ + BOSOUT.set_priority (BOOST_PP_TUPLE_ELEM (3, 0, elem), priority); \ + return true; \ + } \ + else + +#define DECL_LOG_SECTIONS_SET_PRIORITY_STREAM_I(r, data, i, elem) \ + if (BOOST_PP_TUPLE_ELEM (3, 1, elem) == name) \ + { \ + using namespace section; \ + stream->set_priority (priority (BOOST_PP_TUPLE_ELEM (3, 0, elem), level)); \ + return true; \ + } \ + else + +#define DECL_LOG_LEVELS_FUNCTION_I(r, data, i, elem) \ + if (BOOST_PP_TUPLE_ELEM (3, 1, elem) == name) \ + { \ + using namespace blue_sky::level; \ + return BOOST_PP_TUPLE_ELEM (3, 0, elem); \ + } \ + else + +#define DECL_LOG_SECTIONS_ADD_SECTION_I(r, data, i, elem) \ + .add_section (BOOST_PP_TUPLE_ELEM (3, 0, elem), \ + BOOST_PP_TUPLE_ELEM (3, 2, elem)) + +#define DECLARE_LOG_SECTIONS_ENUM(section_name, seq) \ + namespace section_name \ + { \ + enum \ + { \ + section_begin, \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_LOG_SECTIONS_ENUM_I, _, seq) \ + section_end, \ + }; \ + } + +#define DECLARE_LOG_SECTIONS_KEYWORD_HANDLER(function_name, seq) \ + namespace log { namespace detail { \ + inline bool \ + function_name (const std::string &name, int priority) \ + { \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_LOG_SECTIONS_KEYWORD_HANDLER_I, _, seq) \ + { \ + return false; \ + } \ + } \ + inline bool \ + function_name (const std::string &name, int level, const sp_stream &stream) \ + { \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_LOG_SECTIONS_SET_PRIORITY_STREAM_I, _, seq) \ + { \ + return false; \ + } \ + } \ + } } + +#define DECLARE_LOG_LEVELS_ENUM(name, seq) \ + namespace name \ + { \ + enum \ + { \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_LOG_LEVELS_ENUM_I, _, seq) \ + }; \ + } + +#define DECLARE_LOG_LEVELS_FUNCTION(function_name, seq) \ + namespace log { namespace detail { \ + inline int \ + function_name (const std::string &name) \ + { \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_LOG_LEVELS_FUNCTION_I, _, seq) \ + { \ + return -1; \ + } \ + } \ + } } + +#define DECLARE_LOG_SECTIONS_ADD_SECTION(seq) \ + namespace log { namespace detail { \ + inline void \ + add_section_to_channel (bs_channel &ch) \ + { \ + using namespace section; \ + ch \ + BOOST_PP_SEQ_FOR_EACH_I (DECL_LOG_SECTIONS_ADD_SECTION_I, _, seq) \ + ; \ + } \ + } } + +#define DECLARE_LOG_SECTIONS(section_name, function_name, sections_seq) \ + DECLARE_LOG_SECTIONS_ENUM (section_name, sections_seq) \ + DECLARE_LOG_SECTIONS_KEYWORD_HANDLER (function_name, sections_seq) \ + DECLARE_LOG_SECTIONS_ADD_SECTION (sections_seq) + +#define DECLARE_LOG_LEVELS(level_name, function_name, levels_seq) \ + DECLARE_LOG_LEVELS_ENUM (level_name, levels_seq) \ + DECLARE_LOG_LEVELS_FUNCTION (function_name, levels_seq) + + DECLARE_LOG_LEVELS (level, get_log_level_by_name, + ((critical, "CRITICAL", "")) /* Critical errors such as "Cannot allocate memory" */ + ((error, "ERROR", "")) /* Program errors occurs because of input data */ + ((warning, "WARNING", "")) /* Program warnings */ + ((highest, "HIGHEST", "")) /* Highest message priority level */ + ((high, "HIGH", "")) /* High message priority level */ + ((medium, "MEDIUM", "")) /* Medium message priority level */ + ((low, "LOW", "")) /* Low message priority level */ + ((debug, "DEBUG", "")) /* Developing messages not for end users */ + ); + + DECLARE_LOG_SECTIONS (section, set_section_level_by_name, + ((iters, "ITERS", level::low)) /* Messages about iteration process */ + ((wells, "WELLS", level::low)) /* Messages about wells */ + ((mesh, "MESH", level::low)) /* Messages about mesh */ + ((solvers, "SOLVERS", level::low)) /* Messages about linear solvers except AMG */ + ((amg, "AMG", level::low)) /* Messages about AMG solver */ + ((read_data, "READ_DATA", level::low)) /* Messages about reading input data */ + ((init_data, "INIT_DATA", level::low)) /* Messages about initialization data */ + ((check_data, "CHECK_DATA", level::low)) /* Messages about checking data */ + ((save_data, "SAVE_DATA", level::low)) /* Messages about save data */ + ((main_loop, "MAIN_LOOP", level::low)) /* Messages about main_loop */ + ((pvt, "PVT", level::low)) /* Messages about pvt */ + ((scal, "SCAL", level::low)) /* Messages about scal */ + ((schedule, "SCHEDULE", level::low)) /* Messages about schedule */ + ((keywords, "KEYWORDS", level::low)) /* Messages about keywords */ + ((fip, "FIP", level::low)) /* Messages about fip */ + ((arithmetic, "ARITHMETIC", level::low)) /* Messages about arithmetic */ + ((print_reports, "PRINT_REPORTS", level::low)) /* Report messages */ + ((app_info, "APP_INFO", level::debug)) /* Messages about internal application state (for debug only) */ + ((sys_info, "SYS_INFO", level::debug)) /* Messages about external system info */ + ); + + BS_API_PLUGIN + void init_bos_logs(); + +} // namespace blue_sky + +#endif // BOS_REPORT_H + diff --git a/bs_bos_core_base/include/bs_bos_core_base_stdafx.h b/bs_bos_core_base/include/bs_bos_core_base_stdafx.h new file mode 100644 index 0000000..247760a --- /dev/null +++ b/bs_bos_core_base/include/bs_bos_core_base_stdafx.h @@ -0,0 +1,74 @@ +/** + * \file stdafx.h + * \brief precompiled header + * \author Sergey Miryanov + * */ +#ifndef BS_BOS_CORE_BASE_PRECOMPILED_HEADERS_H_ +#define BS_BOS_CORE_BASE_PRECOMPILED_HEADERS_H_ + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#ifndef UNIX +#include +#else +#include +#endif + +#include + +#include + +#include "bs_common.h" +#include BS_FORCE_PLUGIN_IMPORT () +#include "smart_ptr.h" +#include "bs_kernel.h" +#include "bs_link.h" +#include "bs_object_base.h" +#include "bs_tree.h" +#include "bs_exception.h" +#include "bs_assert.h" +#include BS_STOP_PLUGIN_IMPORT () + +#ifdef BSPY_EXPORTING_PLUGIN +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include BS_FORCE_PLUGIN_IMPORT () +#include "bs_plugin_common.h" +#include "py_bs_object_base.h" +#include "py_bs_command.h" +#include "py_bs_tree.h" +#include BS_STOP_PLUGIN_IMPORT () +#endif + +#include "force_inline.h" +#include "bos_report.h" + +#include "aligned_allocator.h" + +#endif // #ifndef BS_BOS_CORE_BASE_PRECOMPILED_HEADERS_H_ diff --git a/bs_bos_core_base/include/constants.h b/bs_bos_core_base/include/constants.h new file mode 100644 index 0000000..c11e7e6 --- /dev/null +++ b/bs_bos_core_base/include/constants.h @@ -0,0 +1,228 @@ +/** + * \file constants.h + * \brief + * \author Miryanov Sergey + * \date 07.05.2008 + */ +#ifndef BS_SOLVER_CONSTANTS_H_ +#define BS_SOLVER_CONSTANTS_H_ + +namespace blue_sky + { + +#define EPS_DIFF 1.0e-7 +#define EPS_DIV 1e-15 + + + /*! + \brief variables in grid block for gas-phase model + */ + + enum well_model_type + { + BLACK_OIL = 0, + COMPOSIT + }; + + enum main_var_type + { + FI_NULL = -1, + FI_SG_VAR = 0, + FI_RO_VAR, + FI_MOMG_VAR, + }; + + //! well model type + enum well_model_var_type + { + WELL_MODEL_1VAR = 0, + WELL_MODEL_3VAR + }; + + enum RPO_MODEL_ENUM + { + RPO_DEFAULT_MODEL = 0, + STONE1_MODEL, + STONE2_MODEL + }; + + enum PHASE_ENUM + { + PHASE_NULL = 0, + PHASE_WATER = 1, + PHASE_GAS = 2, + PHASE_OIL = 4, + + PHASE_TOTAL, + }; + + enum FI_PHASE_ENUM + { + FI_PHASE_NULL = 0, + FI_PHASE_WATER = 0, + FI_PHASE_GAS, + FI_PHASE_OIL, + FI_PHASE_TOT, + }; + + //! types of gas phase rates + enum + { + GAS_RATE_FREE, + GAS_RATE_SOL, + GAS_RATE_TOTAL + }; + + enum + { + FI_WELL_FW_VAR = 0, + FI_WELL_FG_VAR, + FI_WELL_XREF_VAR + }; + + enum FI_LIN_SOLVER_ENUM + { + FI_LIN_SOLVER_BICGSTAB = 0, + FI_LIN_SOLVER_GMRES + }; + + enum FI_LIN_PREC_ENUM + { + FI_LIN_PREC_CPR = 0, + FI_LIN_PREC_ILU, + FI_LIN_PREC_CPR_SOR, + FI_LIN_PREC_AMG + }; + + // check if phase is present +#ifdef COMPOSITIONAL +#define FI_CHK_WATER(PH) ((PH) & (1 << COMP_PHASE_WATER)) +#define FI_CHK_GAS(PH) ((PH) & (1 << COMP_PHASE_GAS)) +#define FI_CHK_OIL(PH) ((PH) & (1 << COMP_PHASE_OIL)) +#else +#define FI_CHK_WATER(PH) ((PH) & (1 << FI_PHASE_WATER)) +#define FI_CHK_GAS(PH) ((PH) & (1 << FI_PHASE_GAS)) +#define FI_CHK_OIL(PH) ((PH) & (1 << FI_PHASE_OIL)) +#endif + + // get index I of phase with displacement D in array, N -- total number of phases +#define FI_PH_IND(I,D,N) ((I) * (N) + (D)) + + // check for oil - gas gas system is present +#define FI_CHK_OIL_GAS(PH) (FI_CHK_GAS((PH)) && FI_CHK_OIL((PH))) + // check for oil - water system is present +#define FI_CHK_OIL_WATER(PH) (FI_CHK_OIL((PH)) && FI_CHK_WATER((PH))) + // check for gas - water system is present +#define FI_CHK_GAS_WATER(PH) (FI_CHK_GAS((PH)) && FI_CHK_WATER((PH))) + + //--------------------- + // 3 phase (gas, oil, water) system + //--------------------- + //! displacements of d()/d(Sg) in Jacobian block row + const int p3_sg = 0; + //! displacements of d()/d(So) in Jacobian block row + const int p3_so = 1; + //! displacements of d()/d(Po) in Jacobian block row + const int p3_po = 2; + + //! displacements of d(Rg)/d() in Jacobian block column + const int p3_gas = 0; + //! displacements of d(Ro)/d() in Jacobian block column + const int p3_oil = 1; + //! displacements of d(Rw)/d() in Jacobian block column + const int p3_wat = 2; + + enum p3_deriv_index_type + { + p3_gas_sg = 0, + p3_gas_so, + p3_gas_po, + p3_oil_sg, + p3_oil_so, + p3_oil_po, + p3_wat_sg, + p3_wat_so, + p3_wat_po + }; + //============================== + + //--------------------- + // 2 phase (gas, oil) system + //--------------------- + //! displacements of d()/d(Sg) in Jacobian block row + const int p2og_sg = 0; + //! displacements of d()/d(Po) in Jacobian block row + const int p2og_po = 1; + + //! displacements of d(Rg)/d() in Jacobian block column + const int p2og_gas = 0; + //! displacements of d(Ro)/d() in Jacobian block column + const int p2og_oil = 1; + + enum + { + p2og_gas_sg = 0, + p2og_gas_po, + p2og_oil_sg, + p2og_oil_po + }; + //============================== + + //--------------------- + // 2 phase (oil, water) system + //--------------------- + //! displacements of d()/d(So) in Jacobian block row + const int p2ow_so = 0; + //! displacements of d()/d(Po) in Jacobian block row + const int p2ow_po = 1; + + //! displacements of d(Ro)/d() in Jacobian block column + const int p2ow_oil = 0; + //! displacements of d(Rw)/d() in Jacobian block column + const int p2ow_wat = 1; + + //! values returned by fi_operator method + enum fi_operator_return_type + { + FI_OPERATOR_RETURN_FAIL = 0, + FI_OPERATOR_RETURN_OK = 1, + FI_OPERATOR_RETURN_RESTART, + FI_OPERATOR_APPROX_DT + }; + + enum + { + p2ow_oil_so = 0, + p2ow_oil_po, + p2ow_wat_so, + p2ow_wat_po + }; + //============================== + + //! check for main variable (Sg or Ro) in grid block +#define FI_GET_VAR(VAR,I) ((VAR)[(I)]) +#define FI_CHK_SG(VAR,I) ((VAR)[(I)]) == FI_SG_VAR ? 1 : 0 +#define FI_CHK_RO(VAR,I) ((VAR)[(I)]) == FI_RO_VAR ? 1 : 0 +#define FI_CHK_MOMG(VAR,I) ((VAR)[(I)]) == FI_MOMG_VAR ? 1 : 0 + +//! EQUIL keyword enumerated params + enum + { + EQUIL_DAT_DEPTH = 0, + EQUIL_DAT_PRESS, + EQUIL_WOC_DEPTH, + EQUIL_WOC_PRESS, + EQUIL_GOC_DEPTH, + EQUIL_GOC_PRESS, + EQUIL_RS_TYPE, + EQUIL_RV_TYPE, + EQUIL_NUM_SEC, + EQUIL_COMP_TYPE, + EQUIL_COMP_ARG, + EQUIL_TOTAL + }; + +} // namespace blue_sky + + +#endif // #ifndef BS_SOLVER_CONSTANTS_H_ diff --git a/bs_bos_core_base/include/construct_python_object.h b/bs_bos_core_base/include/construct_python_object.h new file mode 100644 index 0000000..92193c9 --- /dev/null +++ b/bs_bos_core_base/include/construct_python_object.h @@ -0,0 +1,59 @@ +/** + * \file construct_python_object.h + * \brief function for create and initialize c++ objects from python + * \author Sergey Miryanov + * \date 08.05.2009 + * */ +#ifndef BS_CONSTRUCT_PYTHON_OBJECT_H_ +#define BS_CONSTRUCT_PYTHON_OBJECT_H_ + +#include "throw_exception.h" +#include "py_object_handler.h" + +namespace blue_sky { +namespace python { + + template + static boost::python::object + init_python_object (boost::python::object py_obj) + { + using namespace boost::python; + object return_value = call_method (py_obj.ptr (), "__cons__"); + + object_t *obj = extract (py_obj); + if (!obj) + { + bs_throw_exception ("Can't extract c++ object from python object"); + } + + obj->subscribe (objbase::on_delete, new blue_sky::tools::py_object_handler (py_obj.ptr ())); + return return_value; + } + + template + static smart_ptr + construct_python_object () + { + smart_ptr obj (BS_KERNEL.create_object (object_t::bs_type ()), bs_dynamic_cast ()); + if (!obj) + { + bs_throw_exception ("Can't create object: " + object_t::bs_type ().stype_); + } + + return obj; + } + + template + static void + destroy_python_object (const smart_ptr & /*obj*/) + { + + } + + +} // namespace python +} // namespace blue_sky + + + +#endif // #ifndef BS_CONSTRUCT_PYTHON_OBJECT_H_ diff --git a/bs_bos_core_base/include/debug_macroses.h b/bs_bos_core_base/include/debug_macroses.h new file mode 100644 index 0000000..26c92db --- /dev/null +++ b/bs_bos_core_base/include/debug_macroses.h @@ -0,0 +1,117 @@ +#ifndef __DEBUG_MACROSES_H_ +#define __DEBUG_MACROSES_H_ +/*! + * \file debug_macroses.h + * \brief usefull macroses for debug + * \author Borschuk Oleg + * \date 2006-06-19 + */ + +#include +#include +//#include "sysinfo.h" + +/////////////////////////////////////////////////////////////////////////////////// +//! author KarimovRF, +//! date 2005-10-06 +//! check array A access for index I conforming with array size SZ. +//! If the given index is illegal (is less than zero or greater than the array size) +//! then the error_messager (see sysinfo.h) function is called. +//! Otherwise macro returns I-th element of A array +#ifdef MEM_DEBUG +#define CHA(A,I,SZ) ((((I) < 0) || ((I) > (SZ - 1))) ? (A)[error_messager (__FILE__, __LINE__, " Array bounds overrun!" )] : (A)[I]) +#else +#define CHA(A,I,SZ) ((A)[I]) +#endif + +/////////////////////////////////////////////////////////////////////////////////// +//! author SharipovTR, +//! date 2006-01-06 +//! check array A access for index I conforming with array size SZ. +//! If the given index is illegal (is less than zero or greater than the array size) +//! then the error_messager (see sysinfo.h) function is called. +//! Otherwise macro returns I-th element of A array +#define ERROR_MSG() error_messager (__FILE__, __LINE__, " Array bounds overrun!" ) + +#define MEMORY_ERROR_REPORT_PRINT() \ + { \ + rep->print ( \ + LOG_READ_SECTION, LOG_CRIT, "%s: %s\n", \ + GET_TEXT ("Fatal error"), \ + GET_TEXT ("not enough memory!")); \ + } + +#ifdef MEM_DEBUG +#define ITEM(A,I,J,SZI,SZJ) ((((I) < 0) || ((I) > (SZI - 1)) || ((J) < 0) || ((J) > (SZJ - 1))) ? \ + (A)[ERROR_MSG()][ERROR_MSG()] : (A)[I][J]) +#else +#define ITEM(A,I,J,SZI,SZJ) ((A)[I][J]) +#endif + +//! author KarimovRF, +//! date 2005-10-06 +//! checking specified pointer for being initialized. If not, error message +//! is generated, and ERR value is returned +#ifdef MEM_DEBUG +#define CH_PTR(PT) \ + if (!(PT)) \ + { \ + error_messager (__FILE__, __LINE__, " null pointer!" ); \ + } +#else //MEM_DEBUG +#define CH_PTR(PT) ; +#endif //MEM_DEBUG + + +/*! + * \brief Base class for ASSERT macros implementation + */ +class asserter + { + public: + asserter(int holds, const char *msg) : holds_(holds), msg_(msg) {} + + virtual ~asserter() {} + + virtual int handle(const char * /*file*/, int /*line*/) const + { + if (holds_) + return true; + + enum {n = 2048}; + //static char buf[n]; + +//! sprintf(buf, "\n\tSource File: %s, Line: %d\n\tMessage: %s\n\n", + // file, line, msg_ ? msg_ : ""); + + //crit err + +//! //print log fatal error + //fatal_error_handler(buf); + + exit(-1); + } + + protected: + const int holds_; + const char *msg_; + + asserter &operator = (const asserter &rhs); + }; + +/** + * BUG: Expansion of __LINE__ Macro Is Incorrect When Using /ZI + * RESOLUTION: To work around this problem, use the Program Database option (/Zi) + * instead of Edit and Continue (/ZI). + * + * Using an trick for avoid duplicate identifiers error in case: + * ASSERT(exp1); ASSERT(exp2); + */ +#define BOS_ASSERT(x)\ + {\ + asserter info(x, "Assertion failed: "#x);\ + info.handle(__FILE__, __LINE__);\ + } + +#endif //__DEBUG_MACROSES_H_ + diff --git a/bs_bos_core_base/include/dummy_base.h b/bs_bos_core_base/include/dummy_base.h new file mode 100644 index 0000000..b96908a --- /dev/null +++ b/bs_bos_core_base/include/dummy_base.h @@ -0,0 +1,31 @@ +/** + * \file dummy_base.h + * \brief dummy class for any base python wrappers + * \author Miryanov Sergey + * \date 08.05.2008 + */ +#ifndef BS_DUMMY_BASE_H_ +#define BS_DUMMY_BASE_H_ + +#include BS_FORCE_PLUGIN_IMPORT () +#include "bs_object_base.h" +#include "bs_link.h" +#include BS_STOP_PLUGIN_IMPORT () + +namespace blue_sky + { + + /** + * \brief dummy linear_solver base + */ + class BS_API_PLUGIN dummy_base : public objbase + { + public: + + BLUE_SKY_TYPE_DECL (dummy_base); + }; + + +} // namespace blue_sky + +#endif // #ifndef BS_DUMMY_BASE_H_ diff --git a/bs_bos_core_base/include/export_python_wrapper.h b/bs_bos_core_base/include/export_python_wrapper.h new file mode 100644 index 0000000..8cee9b1 --- /dev/null +++ b/bs_bos_core_base/include/export_python_wrapper.h @@ -0,0 +1,222 @@ +/** + * \file export_python_wrapper.h + * \brief + * \author Sergey Miryanov + * \date 08.05.2009 + * */ +#ifndef BS_BOS_CORE_BASE_EXPORT_PYTHON_WRAPPER_H_ +#define BS_BOS_CORE_BASE_EXPORT_PYTHON_WRAPPER_H_ + +#include "construct_python_object.h" +#include "python_method_wrapper.h" +#include "python_class_wrapper.h" + +#define PY_EXPORTER(exporter_name_, base_exporter_) \ + template \ + struct exporter_name_ \ + { \ + template \ + static class_t & \ + export_class (class_t &class__) \ + { \ + using namespace boost::python; \ + \ + base_exporter_ ::export_class (class__) + +#define PY_EXPORTER_END \ + ; \ + return class__; \ + } \ + }; + +namespace blue_sky { +namespace python { + + template + struct default_exporter + { + template + static class_t & + export_class (class_t &class__) + { + using namespace boost::python; + class__ + .def ("__cons__", make_constructor (construct_python_object )) + .def ("__init__", make_function (init_python_object )) + ; + + return class__; + } + }; + + template + struct empty_exporter + { + template + static class_t & + export_class (class_t &class__) + { + return class__; + } + }; + + namespace class_type + { + template + struct abstract_class + { + typedef boost::python::class_ bp_class_t; + + static bp_class_t + export_class (const std::string &name) + { + using namespace boost::python; + return bp_class_t (name.c_str (), no_init); + } + template + static void + register_base_ptr () + { + } + template + static void + register_class_ptr () + { + } + }; + template + struct concrete_class + { + typedef boost::python::class_ bp_class_t; + + static bp_class_t + export_class (const std::string &name) + { + return bp_class_t (name.c_str ()); + } + template + static void + register_base_ptr () + { + } + template + static void + register_class_ptr () + { + } + }; + template + struct blue_sky_class + { + typedef boost::python::class_ bp_class_t; + + static bp_class_t + export_class (const std::string &name) + { + using namespace boost::python; + return bp_class_t (name.c_str (), no_init); + } + + template + static void + register_base_ptr () + { + using namespace boost::python; + register_ptr_to_python > (); + } + template + static void + register_class_ptr () + { + using namespace boost::python; + register_ptr_to_python > (); + implicitly_convertible , smart_ptr > (); + } + }; + } + + template class post_exporter = default_exporter, template class bp_class_type = class_type::blue_sky_class> + struct base_exporter + { + typedef bp_class_type > bp_class_type_t; + typedef typename bp_class_type_t::bp_class_t bp_class_t; + + static void + export_class (const std::string &name) + { + using namespace boost::python; + + bp_class_t class__ = bp_class_type_t::export_class (name.c_str ()) + ; + + post_exporter ::export_class (class__); + bp_class_type_t::template register_base_ptr (); + } + }; + template class post_exporter = default_exporter, template class bp_class_type = class_type::blue_sky_class> + struct class_exporter + { + typedef bp_class_type > bp_class_type_t; + typedef typename bp_class_type_t::bp_class_t bp_class_t; + + static void + export_class (const std::string &name) + { + using namespace boost::python; + + bp_class_t class__ = bp_class_type_t::export_class (name.c_str ()) + ; + + post_exporter ::export_class (class__); + bp_class_type_t::template register_class_ptr (); + } + }; + + struct strategy_exporter + { + template