diff --git a/3rd/Pebi/V3/AccelWT_CPU.dll b/3rd/Pebi/V3/AccelWT_CPU.dll new file mode 100644 index 0000000..ed7ba53 Binary files /dev/null and b/3rd/Pebi/V3/AccelWT_CPU.dll differ diff --git a/3rd/Pebi/V3/HX_NWTM.dll b/3rd/Pebi/V3/HX_NWTM.dll new file mode 100644 index 0000000..7da5d2d Binary files /dev/null and b/3rd/Pebi/V3/HX_NWTM.dll differ diff --git a/3rd/Pebi/V3/HX_NWTM.lib b/3rd/Pebi/V3/HX_NWTM.lib new file mode 100644 index 0000000..f5ba5d9 Binary files /dev/null and b/3rd/Pebi/V3/HX_NWTM.lib differ diff --git a/3rd/Pebi/V3/HX_license.dat b/3rd/Pebi/V3/HX_license.dat new file mode 100644 index 0000000..5e45563 --- /dev/null +++ b/3rd/Pebi/V3/HX_license.dat @@ -0,0 +1 @@ +7d534fb716ed6121f939 \ No newline at end of file diff --git a/3rd/Pebi/V3/Krow.csv b/3rd/Pebi/V3/Krow.csv new file mode 100644 index 0000000..ba4a5f3 --- /dev/null +++ b/3rd/Pebi/V3/Krow.csv @@ -0,0 +1,22 @@ +So,Krw,Kro +0,1,0 +0.05,1,0 +0.1,1,0 +0.15,0.864105595,0.020840082 +0.2,0.744179203,0.044454989 +0.25,0.638344534,0.071214184 +0.3,0.544945766,0.101536324 +0.35,0.462521643,0.135895811 +0.4,0.389782609,0.17483021 +0.45,0.325590638,0.218948664 +0.5,0.268941421,0.268941421 +0.55,0.218948664,0.325590638 +0.6,0.17483021,0.389782609 +0.65,0.135895811,0.462521643 +0.7,0.101536324,0.544945766 +0.75,0.071214184,0.638344534 +0.8,0.044454989,0.744179203 +0.85,0.020840082,0.864105595 +0.9,0,1 +0.95,0,1 +1,0,1 diff --git a/3rd/Pebi/V3/PVT_ow.csv b/3rd/Pebi/V3/PVT_ow.csv new file mode 100644 index 0000000..00f6ac3 --- /dev/null +++ b/3rd/Pebi/V3/PVT_ow.csv @@ -0,0 +1,202 @@ +p,Bw,miuw,,Bo,miuo +0.101325,1.04263,0.294823,0,1.17376,0.653595 +0.446063,1.04246,0.294823,0,1.13543,0.653595 +0.790801,1.04228,0.294823,0,1.12095,0.653595 +1.13554,1.04211,0.294823,0,1.1119,0.653595 +1.48028,1.04194,0.294823,0,1.10532,0.653595 +1.82501,1.04177,0.294823,0,1.10015,0.653595 +2.16975,1.0416,0.294823,0,1.09589,0.653595 +2.51449,1.04143,0.294823,0,1.09228,0.653595 +2.85923,1.04126,0.294823,0,1.08914,0.653595 +3.20397,1.04109,0.294823,0,1.08636,0.653595 +3.5487,1.04092,0.294823,0,1.08388,0.653595 +3.89344,1.04075,0.294823,0,1.08163,0.653595 +4.23818,1.04058,0.294823,0,1.07958,0.653595 +4.58292,1.04041,0.294823,0,1.07769,0.653595 +4.92765,1.04024,0.294823,0,1.07594,0.653595 +5.27239,1.04008,0.294823,0,1.07431,0.653595 +5.61713,1.03991,0.294823,0,1.07278,0.653595 +5.96187,1.03974,0.294823,0,1.07135,0.653595 +6.30661,1.03957,0.294823,0,1.07001,0.653595 +6.65134,1.0394,0.294823,0,1.06873,0.653595 +6.99608,1.03924,0.294823,0,1.06752,0.653595 +7.34082,1.03907,0.294823,0,1.06637,0.653595 +7.68556,1.0389,0.294823,0,1.06528,0.653595 +8.0303,1.03873,0.294823,0,1.06423,0.653595 +8.37503,1.03857,0.294823,0,1.06323,0.653595 +8.71977,1.0384,0.294823,0,1.06227,0.653595 +9.06451,1.03823,0.294823,0,1.06134,0.653595 +9.40925,1.03807,0.294823,0,1.06046,0.653595 +9.75398,1.0379,0.294823,0,1.0596,0.653595 +10.0987,1.03774,0.294823,0,1.05878,0.653595 +10.4435,1.03757,0.294823,0,1.05798,0.653595 +10.7882,1.0374,0.294823,0,1.05721,0.653595 +11.1329,1.03724,0.294823,0,1.05647,0.653595 +11.4777,1.03707,0.294823,0,1.05575,0.653595 +11.8224,1.03691,0.294823,0,1.05505,0.653595 +12.1671,1.03674,0.294823,0,1.05437,0.653595 +12.5119,1.03658,0.294823,0,1.05371,0.653595 +12.8566,1.03642,0.294823,0,1.05307,0.653595 +13.2014,1.03625,0.294823,0,1.05244,0.653595 +13.5461,1.03609,0.294823,0,1.05183,0.653595 +13.8908,1.03592,0.294823,0,1.05124,0.653595 +14.2356,1.03576,0.294823,0,1.05067,0.653595 +14.5803,1.0356,0.294823,0,1.0501,0.653595 +14.9251,1.03543,0.294823,0,1.04955,0.653595 +15.2698,1.03527,0.294823,0,1.04902,0.653595 +15.6145,1.03511,0.294823,0,1.04849,0.653595 +15.9593,1.03495,0.294823,0,1.04798,0.653595 +16.304,1.03478,0.294823,0,1.04748,0.653595 +16.6487,1.03462,0.294823,0,1.04699,0.653595 +16.9935,1.03446,0.294823,0,1.04651,0.653595 +17.3382,1.0343,0.294823,0,1.04603,0.653595 +17.683,1.03414,0.294823,0,1.04557,0.653595 +18.0277,1.03397,0.294823,0,1.04512,0.653595 +18.3724,1.03381,0.294823,0,1.04468,0.653595 +18.7172,1.03365,0.294823,0,1.04424,0.653595 +19.0619,1.03349,0.294823,0,1.04382,0.653595 +19.4066,1.03333,0.294823,0,1.0434,0.653595 +19.7514,1.03317,0.294823,0,1.04299,0.653595 +20.0961,1.03301,0.294823,0,1.04258,0.653595 +20.4409,1.03285,0.294823,0,1.04218,0.653595 +20.7856,1.03269,0.294823,0,1.04179,0.653595 +21.1303,1.03253,0.294823,0,1.04141,0.653595 +21.4751,1.03237,0.294823,0,1.04103,0.653595 +21.8198,1.03221,0.294823,0,1.04066,0.653595 +22.1645,1.03205,0.294823,0,1.0403,0.653595 +22.5093,1.03189,0.294823,0,1.03994,0.653595 +22.854,1.03173,0.294823,0,1.03958,0.653595 +23.1988,1.03158,0.294823,0,1.03923,0.653595 +23.5435,1.03142,0.294823,0,1.03889,0.653595 +23.8882,1.03126,0.294823,0,1.03855,0.653595 +24.233,1.0311,0.294823,0,1.03822,0.653595 +24.5777,1.03094,0.294823,0,1.03789,0.653595 +24.9225,1.03079,0.294823,0,1.03757,0.653595 +25.2672,1.03063,0.294823,0,1.03725,0.653595 +25.6119,1.03047,0.294823,0,1.03693,0.653595 +25.9567,1.03031,0.294823,0,1.03662,0.653595 +26.3014,1.03016,0.294823,0,1.03631,0.653595 +26.6461,1.03,0.294823,0,1.03601,0.653595 +26.9909,1.02984,0.294823,0,1.03571,0.653595 +27.3356,1.02969,0.294823,0,1.03542,0.653595 +27.6804,1.02953,0.294823,0,1.03513,0.653595 +28.0251,1.02937,0.294823,0,1.03484,0.653595 +28.3698,1.02922,0.294823,0,1.03456,0.653595 +28.7146,1.02906,0.294823,0,1.03428,0.653595 +29.0593,1.02891,0.294823,0,1.034,0.653595 +29.404,1.02875,0.294823,0,1.03373,0.653595 +29.7488,1.0286,0.294823,0,1.03346,0.653595 +30.0935,1.02844,0.294823,0,1.03319,0.653595 +30.4383,1.02829,0.294823,0,1.03293,0.653595 +30.783,1.02813,0.294823,0,1.03267,0.653595 +31.1277,1.02798,0.294823,0,1.03241,0.653595 +31.4725,1.02782,0.294823,0,1.03216,0.653595 +31.8172,1.02767,0.294823,0,1.0319,0.653595 +32.1619,1.02751,0.294823,0,1.03166,0.653595 +32.5067,1.02736,0.294823,0,1.03141,0.653595 +32.8514,1.02721,0.294823,0,1.03116,0.653595 +33.1962,1.02705,0.294823,0,1.03092,0.653595 +33.5409,1.0269,0.294823,0,1.03069,0.653595 +33.8856,1.02675,0.294823,0,1.03045,0.653595 +34.2304,1.02659,0.294823,0,1.03022,0.653595 +34.5751,1.02644,0.294823,0,1.02998,0.653595 +34.9198,1.02629,0.294823,0,1.02976,0.653595 +35.2646,1.02614,0.294823,0,1.02953,0.653595 +35.6093,1.02598,0.294823,0,1.0293,0.653595 +35.9541,1.02583,0.294823,0,1.02908,0.653595 +36.2988,1.02568,0.294823,0,1.02886,0.653595 +36.6435,1.02553,0.294823,0,1.02864,0.653595 +36.9883,1.02538,0.294823,0,1.02843,0.653595 +37.333,1.02522,0.294823,0,1.02821,0.653595 +37.6778,1.02507,0.294823,0,1.028,0.653595 +38.0225,1.02492,0.294823,0,1.02779,0.653595 +38.3672,1.02477,0.294823,0,1.02759,0.653595 +38.712,1.02462,0.294823,0,1.02738,0.653595 +39.0567,1.02447,0.294823,0,1.02718,0.653595 +39.4014,1.02432,0.294823,0,1.02697,0.653595 +39.7462,1.02417,0.294823,0,1.02677,0.653595 +40.0909,1.02402,0.294823,0,1.02657,0.653595 +40.4357,1.02387,0.294823,0,1.02638,0.653595 +40.7804,1.02372,0.294823,0,1.02618,0.653595 +41.1251,1.02357,0.294823,0,1.02599,0.653595 +41.4699,1.02342,0.294823,0,1.0258,0.653595 +41.8146,1.02327,0.294823,0,1.02561,0.653595 +42.1593,1.02312,0.294823,0,1.02542,0.653595 +42.5041,1.02297,0.294823,0,1.02523,0.653595 +42.8488,1.02282,0.294823,0,1.02505,0.653595 +43.1936,1.02267,0.294823,0,1.02486,0.653595 +43.5383,1.02253,0.294823,0,1.02468,0.653595 +43.883,1.02238,0.294823,0,1.0245,0.653595 +44.2278,1.02223,0.294823,0,1.02432,0.653595 +44.5725,1.02208,0.294823,0,1.02414,0.653595 +44.9172,1.02193,0.294823,0,1.02396,0.653595 +45.262,1.02179,0.294823,0,1.02379,0.653595 +45.6067,1.02164,0.294823,0,1.02361,0.653595 +45.9515,1.02149,0.294823,0,1.02344,0.653595 +46.2962,1.02134,0.294823,0,1.02327,0.653595 +46.6409,1.0212,0.294823,0,1.0231,0.653595 +46.9857,1.02105,0.294823,0,1.02293,0.653595 +47.3304,1.0209,0.294823,0,1.02276,0.653595 +47.6751,1.02076,0.294823,0,1.0226,0.653595 +48.0199,1.02061,0.294823,0,1.02243,0.653595 +48.3646,1.02046,0.294823,0,1.02227,0.653595 +48.7094,1.02032,0.294823,0,1.02211,0.653595 +49.0541,1.02017,0.294823,0,1.02194,0.653595 +49.3988,1.02003,0.294823,0,1.02178,0.653595 +49.7436,1.01988,0.294823,0,1.02162,0.653595 +50.0883,1.01974,0.294823,0,1.02147,0.653595 +50.4331,1.01959,0.294823,0,1.02131,0.653595 +50.7778,1.01944,0.294823,0,1.02115,0.653595 +51.1225,1.0193,0.294823,0,1.021,0.653595 +51.4673,1.01915,0.294823,0,1.02085,0.653595 +51.812,1.01901,0.294823,0,1.02069,0.653595 +52.1567,1.01887,0.294823,0,1.02054,0.653595 +52.5015,1.01872,0.294823,0,1.02039,0.653595 +52.8462,1.01858,0.294823,0,1.02024,0.653595 +53.191,1.01843,0.294823,0,1.02009,0.653595 +53.5357,1.01829,0.294823,0,1.01994,0.653595 +53.8804,1.01814,0.294823,0,1.0198,0.653595 +54.2252,1.018,0.294823,0,1.01965,0.653595 +54.5699,1.01786,0.294823,0,1.01951,0.653595 +54.9146,1.01771,0.294823,0,1.01936,0.653595 +55.2594,1.01757,0.294823,0,1.01922,0.653595 +55.6041,1.01743,0.294823,0,1.01908,0.653595 +55.9489,1.01729,0.294823,0,1.01894,0.653595 +56.2936,1.01714,0.294823,0,1.0188,0.653595 +56.6383,1.017,0.294823,0,1.01866,0.653595 +56.9831,1.01686,0.294823,0,1.01852,0.653595 +57.3278,1.01672,0.294823,0,1.01838,0.653595 +57.6725,1.01657,0.294823,0,1.01825,0.653595 +58.0173,1.01643,0.294823,0,1.01811,0.653595 +58.362,1.01629,0.294823,0,1.01797,0.653595 +58.7068,1.01615,0.294823,0,1.01784,0.653595 +59.0515,1.01601,0.294823,0,1.01771,0.653595 +59.3962,1.01586,0.294823,0,1.01757,0.653595 +59.741,1.01572,0.294823,0,1.01744,0.653595 +60.0857,1.01558,0.294823,0,1.01731,0.653595 +60.4304,1.01544,0.294823,0,1.01718,0.653595 +60.7752,1.0153,0.294823,0,1.01705,0.653595 +61.1199,1.01516,0.294823,0,1.01692,0.653595 +61.4647,1.01502,0.294823,0,1.01679,0.653595 +61.8094,1.01488,0.294823,0,1.01667,0.653595 +62.1541,1.01474,0.294823,0,1.01654,0.653595 +62.4989,1.0146,0.294823,0,1.01641,0.653595 +62.8436,1.01446,0.294823,0,1.01629,0.653595 +63.1884,1.01432,0.294823,0,1.01616,0.653595 +63.5331,1.01418,0.294823,0,1.01604,0.653595 +63.8778,1.01404,0.294823,0,1.01592,0.653595 +64.2226,1.0139,0.294823,0,1.01579,0.653595 +64.5673,1.01376,0.294823,0,1.01567,0.653595 +64.912,1.01362,0.294823,0,1.01555,0.653595 +65.2568,1.01348,0.294823,0,1.01543,0.653595 +65.6015,1.01334,0.294823,0,1.01531,0.653595 +65.9463,1.01321,0.294823,0,1.01519,0.653595 +66.291,1.01307,0.294823,0,1.01507,0.653595 +66.6357,1.01293,0.294823,0,1.01496,0.653595 +66.9805,1.01279,0.294823,0,1.01484,0.653595 +67.3252,1.01265,0.294823,0,1.01472,0.653595 +67.6699,1.01251,0.294823,0,1.01461,0.653595 +68.0147,1.01238,0.294823,0,1.01449,0.653595 +68.3594,1.01224,0.294823,0,1.01437,0.653595 +68.7042,1.0121,0.294823,0,1.01426,0.653595 +69.0489,1.01196,0.294823,0,1.01415,0.653595 diff --git a/3rd/Pebi/V3/accelwt_cpu.h b/3rd/Pebi/V3/accelwt_cpu.h new file mode 100644 index 0000000..42ca01c --- /dev/null +++ b/3rd/Pebi/V3/accelwt_cpu.h @@ -0,0 +1,223 @@ +#ifndef ACCELWT_CPU_H +#define ACCELWT_CPU_H + +#if defined(_WIN32) || defined(__CYGWIN__) +# if defined(ACCELWT_CPU_STATIC_DEFINE) +# define ACCELWT_CPU_API +# elif defined(ACCELWT_CPU_BUILDING_LIBRARY) +# define ACCELWT_CPU_API __declspec(dllexport) +# else +# define ACCELWT_CPU_API __declspec(dllimport) +# endif +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define ACCELWT_CPU_API __attribute__((visibility("default"))) +#else +# define ACCELWT_CPU_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACCELWT_CPU_VERSION_MAJOR 3 +#define ACCELWT_CPU_VERSION_MINOR 2 +#define ACCELWT_CPU_VERSION_PATCH 0 + +/* + * Persistent simulation session. Create one context for a fixed CSR sparsity + * pattern, reuse it across accepted physical time steps, and destroy it when + * the simulation ends. Keeping this object alive enables temporal history, + * workspace reuse and lagged preconditioner refreshes. + */ +typedef struct AccelWTCPUContext AccelWTCPUContext; +typedef AccelWTCPUContext AccelWTCPUSession; + +typedef enum AccelWTCPUStatus +{ + ACCELWT_CPU_SUCCESS = 0, + ACCELWT_CPU_INVALID_ARGUMENT = 1, + ACCELWT_CPU_INVALID_MATRIX = 2, + ACCELWT_CPU_ALLOCATION_FAILED = 3, + ACCELWT_CPU_SETUP_FAILED = 4, + ACCELWT_CPU_NOT_READY = 5, + ACCELWT_CPU_SOLVE_FAILED = 6, + ACCELWT_CPU_NOT_CONVERGED = 7 +} AccelWTCPUStatus; + +typedef struct AccelWTCPUOptions +{ + int max_iterations; + double relative_tolerance; + double absolute_tolerance; + int ilu_jacobi_iterations; + int omp_threads; + int use_initial_guess; + /* Default: 1. Set to 0 to opt into experimental LU-split Jacobi. */ + int use_exact_triangular_solve; + /* + * Experimental four-thread block triangular application. + * 0 keeps the mode selected above, 1 performs one block sweep and + * 2 performs one cross-subdomain correction sweep. Requires omp_threads=4. + */ + int block_triangular_sweeps; +} AccelWTCPUOptions; + +typedef struct AccelWTCPUInfo +{ + int iterations; + double final_rel_residual; + double final_abs_residual; + double setup_seconds; + double solve_seconds; + int status; +} AccelWTCPUInfo; + +typedef struct AccelWTCPUPhaseInfo +{ + double initialization_seconds; + double direction_update_seconds; + double preconditioner_seconds; + double spmv_reduction_seconds; + double solution_update_seconds; + double true_residual_seconds; +} AccelWTCPUPhaseInfo; + +typedef enum AccelWTCPUTemporalGuess +{ + ACCELWT_CPU_TEMPORAL_GUESS_NONE = 0, + ACCELWT_CPU_TEMPORAL_GUESS_PREVIOUS = 1, + ACCELWT_CPU_TEMPORAL_GUESS_MR2 = 2 +} AccelWTCPUTemporalGuess; + +typedef struct AccelWTCPUTemporalOptions +{ + int initial_guess_policy; + int enable_early_exit; + int ilu_refresh_interval; + int ilu_refresh_iteration_threshold; +} AccelWTCPUTemporalOptions; + +typedef struct AccelWTCPUStepInfo +{ + AccelWTCPUInfo solve; + int used_mr2; + int history_depth; + int early_exit; + int refreshed_preconditioner; + double predicted_relative_residual; + double prediction_seconds; + double update_seconds; + double solve_seconds; +} AccelWTCPUStepInfo; + +/* + * Simple session configuration for time-dependent applications. + * Zero values select library defaults. One ILU factor is used for + * ilu_reuse_steps consecutive time steps; 1 rebuilds it every step. + */ +typedef struct AccelWTCPUSessionOptions +{ + int omp_threads; + int ilu_reuse_steps; +} AccelWTCPUSessionOptions; + +#define ACCELWT_CPU_SESSION_OPTIONS_DEFAULT {0, 5} + +/* + * Simple three-function interface. Passing NULL options uses the defaults, + * including an ILU reuse window of five time steps. + */ +ACCELWT_CPU_API int accelwt_cpu_session_create( + int n, + int nnz, + const int *row_ptr, + const int *col_ind, + const AccelWTCPUSessionOptions *options, + AccelWTCPUSession **session); + +ACCELWT_CPU_API int accelwt_cpu_session_solve( + AccelWTCPUSession *session, + const double *values, + const double *rhs, + double *x, + AccelWTCPUStepInfo *info); + +/* Accepts NULL. */ +ACCELWT_CPU_API void accelwt_cpu_session_destroy(AccelWTCPUSession *session); + +/* Returns the default options without allocating a solver context. */ +ACCELWT_CPU_API void accelwt_cpu_default_options(AccelWTCPUOptions *options); +ACCELWT_CPU_API void accelwt_cpu_default_temporal_options( + AccelWTCPUTemporalOptions *options); + +ACCELWT_CPU_API const char *accelwt_cpu_backend_name(void); +ACCELWT_CPU_API const char *accelwt_cpu_status_string(int status); + +/* + * Creates a persistent solver for a zero-based, square CSR matrix pattern. + * The row and column arrays are copied and may be released after this call. + * Column indices must be strictly increasing within each row, and every row + * must contain its diagonal entry. + */ +ACCELWT_CPU_API int accelwt_cpu_create(int n, + int nnz, + const int *row_ptr, + const int *col_ind, + const AccelWTCPUOptions *options, + AccelWTCPUContext **context); + +/* + * Copies new CSR values into the context. A nonzero refresh_preconditioner + * rebuilds ILU0. The first update always builds ILU0, regardless of the flag. + */ +ACCELWT_CPU_API int accelwt_cpu_update_matrix(AccelWTCPUContext *context, + const double *values, + int refresh_preconditioner, + AccelWTCPUInfo *info); + +/* Solves A*x=rhs. The context is not safe for concurrent solve calls. */ +ACCELWT_CPU_API int accelwt_cpu_solve(AccelWTCPUContext *context, + const double *rhs, + double *x, + AccelWTCPUInfo *info); + +/* + * Returns phase timings from the latest solve. Values are zero unless the + * library was built with ACCELWT_CPU_PHASE_TIMING=ON. + */ +ACCELWT_CPU_API int accelwt_cpu_get_last_phase_info( + const AccelWTCPUContext *context, + AccelWTCPUPhaseInfo *info); + +/* + * Configures the library-owned temporal policy. The default is MR2 with + * verified early exit and a five-step lagged-ILU interval. + */ +ACCELWT_CPU_API int accelwt_cpu_set_temporal_options( + AccelWTCPUContext *context, + const AccelWTCPUTemporalOptions *options); + +/* + * Updates A and solves one accepted physical time step while managing MR2 + * history, verified early exit and lagged-ILU refreshes inside the session. + * This interface assumes one linear solve per accepted physical time step. + * Do not call it for intermediate or rejected nonlinear iterations because a + * successful call immediately commits x to the temporal history. + */ +ACCELWT_CPU_API int accelwt_cpu_solve_step(AccelWTCPUContext *context, + const double *values, + const double *rhs, + double *x, + AccelWTCPUStepInfo *info); + +ACCELWT_CPU_API int accelwt_cpu_reset_temporal_history( + AccelWTCPUContext *context); + +/* Accepts NULL. */ +ACCELWT_CPU_API void accelwt_cpu_destroy(AccelWTCPUContext *context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/3rd/Pebi/V3/libiomp5md.dll b/3rd/Pebi/V3/libiomp5md.dll new file mode 100644 index 0000000..1c4a9b3 Binary files /dev/null and b/3rd/Pebi/V3/libiomp5md.dll differ diff --git a/3rd/Pebi/V3/main.cpp b/3rd/Pebi/V3/main.cpp new file mode 100644 index 0000000..de701d6 --- /dev/null +++ b/3rd/Pebi/V3/main.cpp @@ -0,0 +1,652 @@ +#include"pch.h" +#include +#include + +#include +#include +#include + +static int g_orgStdout = -1; +static FILE* g_nulPipe = nullptr; +void EnterSilentDllMode() +{ + // 备份原始标准输出句柄 + g_orgStdout = _dup(_fileno(stdout)); + + // fopen_s 替代 fopen,打开空设备 NUL + errno_t err; + err = fopen_s(&g_nulPipe, "NUL", "w"); + if (err == 0 && g_nulPipe != nullptr) + { + _dup2(_fileno(g_nulPipe), _fileno(stdout)); + _dup2(_fileno(g_nulPipe), _fileno(stderr)); + } +} + +void LeaveSilentDllMode() +{ + // 恢复原始控制台输出 + if (g_orgStdout != -1) + { + _dup2(g_orgStdout, _fileno(stdout)); + _dup2(g_orgStdout, _fileno(stderr)); + _close(g_orgStdout); + g_orgStdout = -1; + } + + // 关闭空文件流 + if (g_nulPipe != nullptr) + { + fclose(g_nulPipe); + g_nulPipe = nullptr; + } +} + +void Write2DVectorToCSV(const std::vector>& data, const std::string& filename) { + std::ofstream file(filename.c_str()); // VS2010需使用.c_str() + if (file.is_open()) { + for (size_t row = 0; row < data.size(); ++row) { + for (size_t col = 0; col < data[row].size(); ++col) { + // 设置固定小数格式和精度 + file << std::fixed << std::setprecision(15) << data[row][col]; + // 非最后一列时添加逗号 + if (col != data[row].size() - 1) { + file << ","; + } + } + file << "\n"; // 换行符 + } + file.close(); + } +} +void Write1DVectorToCSV(const std::vector& data, const std::string& filename, int precision = 15) { + std::ofstream file(filename.c_str()); + if (file.is_open()) { + file << std::fixed << std::setprecision(precision); + for (size_t i = 0; i < data.size(); ++i) { + file << data[i] << "\n"; // 每个元素单独一行 + } + file.close(); + } +} +bool readCSVColumn(const std::string& filename, int columnIndex, std::vector& data) { + std::ifstream file(filename); + if (!file.is_open()) { + std::cerr << "无法打开文件: " << filename << std::endl; + return false; + } + + std::string line; + // 跳过标题行(如果有) + if (file.good()) { + std::getline(file, line); + } + data.resize(0); + // 逐行处理数据 + while (std::getline(file, line)) { + std::istringstream ss(line); + std::string cell; + int currentColumn = 0; + bool columnFound = false; + + // 处理当前行的每个单元格 + while (std::getline(ss, cell, ',')) { + if (currentColumn == columnIndex) { + try { + // 转换为double并添加到vector + data.push_back(std::stod(cell)); + } + catch (const std::invalid_argument& e) { + std::cerr << "转换错误: " << cell << " 不是有效的数字" << std::endl; + return false; + } + columnFound = true; + break; + } + currentColumn++; + } + + // 如果指定列不存在,给出警告 + if (!columnFound) { + std::cerr << "警告: 行 " << data.size() + 1 << " 不包含列 " << columnIndex << std::endl; + } + } + + file.close(); + return true; +} + +int main() +{ + + set_ilu_reuse_steps(5); + int solvetype[] = { 1,2 }; + std::string solvetypename[] = {"新库","原库"}; + int omp_threads[] = { 1, 2, 4, 8, 16 }; + //不同井型算例 + int welltype;//1为一口直井,2为一口压裂直井,3为一口多段压裂水平井,4为五口井(含直井,压裂直井,多段压裂水平井,断层),5为50口直井 + welltype = 1; + //模型算例 + int flowtype;//1为油单相常数pvt(一口井),2为油单相常数pvt(五口井),3为油单相常数pvt(五十口井),4为油单相变化pvt(一口井),5为水单相常数pvt(一口井),6为水单相变化pvt(一口井),7为气单相变化pvt(一口井),8为气单相拟压力(一口井),9为油水两相(一口井) + flowtype = 1; + + const int WT[] = { 1,1,2,2,3,3,4,5 }; + const int FT[] = { 1,9,1,9,1,9,2,3 }; + std::string name[] = + { + "1-1油单相常数pvt(1口直井)", + "1-9油水两相 (1口直井)", + "2-1油单相常数pvt(1口压裂直井)", + "2-9油水两相 (1口压裂直井)", + "3-1油单相常数pvt(1口多段压裂水平井)", + "3-9油水两相 (1口多段压裂水平井)", + "4-2油单相常数pvt(5口井)", + "5-3油单相常数pvt(50口直井)" + }; + for (int type = 0; type < 2; ++type){ + set_solvetype(solvetype[type]); + std::cout << solvetypename[type] << "\n"; + int threads ; + if (solvetype[type] == 1) { + threads = 5; + } + else if (solvetype[type] == 2) { + threads = 1; + } + for (int thr = 0; thr < threads; ++thr) + { + set_omp_threads(omp_threads[thr]); + std::cout << omp_threads[thr] << "线程测试\n"; + for (int iiii = 0; iiii < 8; ++iiii) + { + welltype = WT[iiii]; + flowtype = FT[iiii]; + + + //非均质性 + int feijunzhi = 0;//0为不考虑储层非均质,1为考虑储层非均质 + HX_NWTM_GRID_INPUT p0; + HX_NWTM_GRID_OUTPUT1 p1; + HX_NWTM_GRID_OUTPUT2 p2; + //不同井型设置 + dVec1 a(3), b(4), c(5), d(6); + if (welltype == 1) { + //一口直井 + p0.Boundary.resize(4); + b[0] = -1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = 1500.0; p0.Boundary[0] = b; + b[0] = -1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = 1500.0; p0.Boundary[1] = b; + b[0] = 1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = -1500.0; p0.Boundary[2] = b; + b[0] = 1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = -1500.0; p0.Boundary[3] = b; + p0.VerticalWell.resize(1); + a[0] = 0; a[1] = 0; a[2] = 0.1; p0.VerticalWell[0] = a; + p0.HorizontalWell.resize(0); + p0.FractureVerticalWell.resize(0); + p0.MultistageFracturedHorizontalWell.resize(0); + p0.InclinedWell.resize(0); + p0.Fault.resize(0); + } + else if (welltype == 2) { + //一口压裂直井 + p0.Boundary.resize(4); + b[0] = -1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = 1500.0; p0.Boundary[0] = b; + b[0] = -1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = 1500.0; p0.Boundary[1] = b; + b[0] = 1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = -1500.0; p0.Boundary[2] = b; + b[0] = 1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = -1500.0; p0.Boundary[3] = b; + p0.VerticalWell.resize(0); + p0.HorizontalWell.resize(0); + p0.FractureVerticalWell.resize(1); + d[0] = -200; d[1] = 0; d[2] = 200; d[3] = 0; d[4] = 0.05; d[5] = 100.0; p0.FractureVerticalWell[0] = d; + p0.MultistageFracturedHorizontalWell.resize(0); + p0.InclinedWell.resize(0); + p0.Fault.resize(0); + } + else if (welltype == 3) { + //一口多段压裂水平井 + p0.Boundary.resize(4); + b[0] = -1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = 1500.0; p0.Boundary[0] = b; + b[0] = -1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = 1500.0; p0.Boundary[1] = b; + b[0] = 1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = -1500.0; p0.Boundary[2] = b; + b[0] = 1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = -1500.0; p0.Boundary[3] = b; + p0.VerticalWell.resize(0); + p0.HorizontalWell.resize(0); + p0.FractureVerticalWell.resize(0); + p0.MultistageFracturedHorizontalWell.resize(1); + p0.MultistageFracturedHorizontalWell[0].resize(5, dVec1(6)); + d[0] = -400; d[1] = -200; d[2] = -400; d[3] = 200; d[4] = 0.05; d[5] = 100; p0.MultistageFracturedHorizontalWell[0][0] = d; + d[0] = -200; d[1] = -200; d[2] = -200; d[3] = 200; d[4] = 0.05; d[5] = 100; p0.MultistageFracturedHorizontalWell[0][1] = d; + d[0] = 0; d[1] = -200; d[2] = 0; d[3] = 200; d[4] = 0.05; d[5] = 100; p0.MultistageFracturedHorizontalWell[0][2] = d; + d[0] = 200; d[1] = -200; d[2] = 200; d[3] = 200; d[4] = 0.05; d[5] = 100; p0.MultistageFracturedHorizontalWell[0][3] = d; + d[0] = 400; d[1] = -200; d[2] = 400; d[3] = 200; d[4] = 0.05; d[5] = 100; p0.MultistageFracturedHorizontalWell[0][4] = d; + p0.InclinedWell.resize(0); + p0.Fault.resize(0); + } + else if (welltype == 4) { + //五口井(含直井,压裂直井,多段压裂水平井,断层) + p0.Boundary.resize(4); + b[0] = -1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = 1500.0; p0.Boundary[0] = b; + b[0] = -1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = 1500.0; p0.Boundary[1] = b; + b[0] = 1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = -1500.0; p0.Boundary[2] = b; + b[0] = 1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = -1500.0; p0.Boundary[3] = b; + p0.VerticalWell.resize(3); + a[0] = 0; a[1] = 0; a[2] = 0.1; p0.VerticalWell[0] = a; + a[0] = 1000; a[1] = 1000; a[2] = 0.1; p0.VerticalWell[1] = a; + a[0] = -1000; a[1] = -1000; a[2] = 0.1; p0.VerticalWell[2] = a; + p0.HorizontalWell.resize(0); + p0.FractureVerticalWell.resize(1); + d[0] = -200; d[1] = -200; d[2] = 200; d[3] = -200; d[4] = 0.05; d[5] = 0; p0.FractureVerticalWell[0] = d; + p0.MultistageFracturedHorizontalWell.resize(1); + p0.MultistageFracturedHorizontalWell[0].resize(3, dVec1(6)); + d[0] = -600; d[1] = 600; d[2] = -400; d[3] = 600; d[4] = 0.1; d[5] = 0; p0.MultistageFracturedHorizontalWell[0][0] = d; + d[0] = -600; d[1] = 400; d[2] = -400; d[3] = 400; d[4] = 0.1; d[5] = 0; p0.MultistageFracturedHorizontalWell[0][1] = d; + d[0] = -600; d[1] = 200; d[2] = -400; d[3] = 200; d[4] = 0.1; d[5] = 0; p0.MultistageFracturedHorizontalWell[0][2] = d; + p0.InclinedWell.resize(0); + p0.Fault.resize(1); + b[0] = -500; b[1] = 1000; b[2] = 500; b[3] = 500; p0.Fault[0] = b; + } + else if (welltype == 5) { + //50口直井 + p0.Boundary.resize(4); + b[0] = -1000.0; b[1] = -1000.0; b[2] = -1000.0; b[3] = 1000.0; p0.Boundary[0] = b; + b[0] = -1000.0; b[1] = 1000.0; b[2] = 1000.0; b[3] = 1000.0; p0.Boundary[1] = b; + b[0] = 1000.0; b[1] = 1000.0; b[2] = 1000.0; b[3] = -1000.0; p0.Boundary[2] = b; + b[0] = 1000.0; b[1] = -1000.0; b[2] = -1000.0; b[3] = -1000.0; p0.Boundary[3] = b; + p0.VerticalWell.resize(50); + a[0] = 766.32207856101854; a[1] = -408.4253100821785; a[2] = 0.108; p0.VerticalWell[0] = a; + a[0] = -359.11086885711029; a[1] = -242.17185988435722; a[2] = 0.108; p0.VerticalWell[1] = a; + a[0] = -396.28113134064483; a[1] = 618.18974488936828; a[2] = 0.108; p0.VerticalWell[2] = a; + a[0] = -844.38929572547772; a[1] = 859.25724767620932; a[2] = 0.108; p0.VerticalWell[3] = a; + a[0] = -631.69279373636357; a[1] = 620.26791301684102; a[2] = 0.108; p0.VerticalWell[4] = a; + a[0] = -858.84439780240791; a[1] = 333.48071142559911; a[2] = 0.108; p0.VerticalWell[5] = a; + a[0] = -844.38929572547772; a[1] = 609.87707237947734; a[2] = 0.108; p0.VerticalWell[6] = a; + a[0] = -639.95285206603785; a[1] = 867.56992018610026; a[2] = 0.108; p0.VerticalWell[7] = a; + a[0] = 764.25706397860017; a[1] = -190.2176566975379; a[2] = 0.108; p0.VerticalWell[8] = a; + a[0] = -410.73623341757479; a[1] = 867.56992018610026; a[2] = 0.108; p0.VerticalWell[9] = a; + a[0] = -121.63419187897284; a[1] = 98.647713021176514; a[2] = 0.108; p0.VerticalWell[10] = a; + a[0] = -152.6094106152517; a[1] = 364.65323333769061; a[2] = 0.108; p0.VerticalWell[11] = a; + a[0] = -152.6094106152517; a[1] = 620.26791301684102; a[2] = 0.108; p0.VerticalWell[12] = a; + a[0] = -361.17588343952877; a[1] = 102.80404927612199; a[2] = 0.108; p0.VerticalWell[13] = a; + a[0] = -844.38929572547772; a[1] = -231.78101924699342; a[2] = 0.108; p0.VerticalWell[14] = a; + a[0] = -156.73943978008879; a[1] = 875.88259269599121; a[2] = 0.108; p0.VerticalWell[15] = a; + a[0] = 138.55764550576896; a[1] = 890.42976958830059; a[2] = 0.108; p0.VerticalWell[16] = a; + a[0] = 446.24481828613784; a[1] = -439.59783199426988; a[2] = 0.108; p0.VerticalWell[17] = a; + a[0] = -846.45431030789632; a[1] = 61.240686726666581; a[2] = 0.108; p0.VerticalWell[18] = a; + a[0] = -142.28433770315883; a[1] = -223.46834673710214; a[2] = 0.108; p0.VerticalWell[19] = a; + a[0] = -375.63098551645885; a[1] = -472.84852203383423; a[2] = 0.108; p0.VerticalWell[20] = a; + a[0] = -602.78258958250342; a[1] = 354.2623927003267; a[2] = 0.108; p0.VerticalWell[21] = a; + a[0] = 431.78971620920788; a[1] = 624.42424927178672; a[2] = 0.108; p0.VerticalWell[22] = a; + a[0] = -834.06422281338484; a[1] = -474.92669016130685; a[2] = 0.108; p0.VerticalWell[23] = a; + a[0] = -836.12923739580344; a[1] = -747.16671486023938; a[2] = 0.108; p0.VerticalWell[24] = a; + a[0] = 813.81741395664631; a[1] = -693.13434354594744; a[2] = 0.108; p0.VerticalWell[25] = a; + a[0] = 458.63490578064966; a[1] = -718.07236107562062; a[2] = 0.108; p0.VerticalWell[26] = a; + a[0] = 409.07455580260353; a[1] = 873.80442456851847; a[2] = 0.108; p0.VerticalWell[27] = a; + a[0] = 124.10254342883854; a[1] = -454.14500888657915; a[2] = 0.108; p0.VerticalWell[28] = a; + a[0] = 138.55764550576896; a[1] = 96.569544893703778; a[2] = 0.108; p0.VerticalWell[29] = a; + a[0] = 101.38738302223419; a[1] = 611.95524050694985; a[2] = 0.108; p0.VerticalWell[30] = a; + a[0] = -373.56597093404037; a[1] = 360.49689708274514; a[2] = 0.108; p0.VerticalWell[31] = a; + a[0] = -604.8476041649219; a[1] = 79.944199873921661; a[2] = 0.108; p0.VerticalWell[32] = a; + a[0] = -611.0426479121777; a[1] = -219.31201048215667; a[2] = 0.108; p0.VerticalWell[33] = a; + a[0] = 448.30983286855667; a[1] = -202.68666546237455; a[2] = 0.108; p0.VerticalWell[34] = a; + a[0] = 735.34685982474002; a[1] = 880.03892895093713; a[2] = 0.108; p0.VerticalWell[35] = a; + a[0] = 107.58242676948976; a[1] = -724.30686545803894; a[2] = 0.108; p0.VerticalWell[36] = a; + a[0] = 150.94773300028032; a[1] = -196.45216107995623; a[2] = 0.108; p0.VerticalWell[37] = a; + a[0] = 762.19204939618135; a[1] = 113.19488991348589; a[2] = 0.108; p0.VerticalWell[38] = a; + a[0] = -125.76422104381015; a[1] = -470.77035390636138; a[2] = 0.108; p0.VerticalWell[39] = a; + a[0] = 452.43986203339387; a[1] = 366.73140146516357; a[2] = 0.108; p0.VerticalWell[40] = a; + a[0] = -350.85081052743578; a[1] = -751.32305111518485; a[2] = 0.108; p0.VerticalWell[41] = a; + a[0] = 122.03752884641995; a[1] = 354.2623927003267; a[2] = 0.108; p0.VerticalWell[42] = a; + a[0] = -608.9776333297591; a[1] = -447.91050450416094; a[2] = 0.108; p0.VerticalWell[43] = a; + a[0] = 407.0095412201847; a[1] = 113.19488991348589; a[2] = 0.108; p0.VerticalWell[44] = a; + a[0] = 731.21683065990283; a[1] = 636.89325803662314; a[2] = 0.108; p0.VerticalWell[45] = a; + a[0] = -121.63419187897284; a[1] = -724.30686545803894; a[2] = 0.108; p0.VerticalWell[46] = a; + a[0] = 289.3037100223255; a[1] = -925.88917382289742; a[2] = 0.108; p0.VerticalWell[47] = a; + a[0] = 737.41187440715862; a[1] = 366.73140146516357; a[2] = 0.108; p0.VerticalWell[48] = a; + a[0] = -611.0426479121777; a[1] = -730.54136984045726; a[2] = 0.108; p0.VerticalWell[49] = a; + p0.HorizontalWell.resize(0); + p0.FractureVerticalWell.resize(0); + p0.MultistageFracturedHorizontalWell.resize(0); + p0.InclinedWell.resize(0); + p0.Fault.resize(0); + } + p0.GridControl = 150.0; + p0.D = 2; + EnterSilentDllMode(); + //网格计算 + + HX_NWTM_GRID(p1, p2, p0, "HX_license.dat"); + HX_NWTM_MODEL_INPUT p3(p2); + HX_NWTM_MODEL_OUTPUT p4; + + //模型设置 + if (flowtype == 1) { + //油单相常数pvt(一口井) + p3.T = 1; + p3.Rate.t.resize(1); + p3.Rate.qo.resize(1); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + p3.Rate.qo[0].resize(2); p3.Rate.qo[0][0] = 20; p3.Rate.qo[0][1] = 0; + p3.CS.C.resize(1); + p3.CS.C[0] = 0; + p3.CS.S.resize(1); + p3.CS.S[0] = 0; + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bo = dVec1(200, 1.2);//所有数为一个值 + p3.PVT.miuo = dVec1(200, 0.5);//所有数为一个值 + p3.Base.Pi = 40.0; + p3.Base.Cti = 1e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 2) { + //油单相常数pvt(五口井) + p3.T = 1; + p3.Rate.t.resize(5); + p3.Rate.qo.resize(5); + p3.Rate.qw.resize(5); + p3.Rate.qg.resize(5); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + p3.Rate.qo[0].resize(2); p3.Rate.qo[0][0] = 10; p3.Rate.qo[0][1] = 0; + p3.Rate.t[1].resize(0); + p3.Rate.qo[1].resize(0); + p3.Rate.t[2].resize(3); p3.Rate.t[2][0] = 1000; p3.Rate.t[2][1] = 1000; p3.Rate.t[2][2] = 500; + p3.Rate.qo[2].resize(3); p3.Rate.qo[2][0] = 30; p3.Rate.qo[2][1] = 40; p3.Rate.qo[2][2] = 20; + p3.Rate.t[3].resize(2); p3.Rate.t[3][0] = 1500; p3.Rate.t[3][1] = 1000; + p3.Rate.qo[3].resize(2); p3.Rate.qo[3][0] = 30; p3.Rate.qo[3][1] = 20; + p3.Rate.t[4].resize(2); p3.Rate.t[4][0] = 1000; p3.Rate.t[4][1] = 1500; + p3.Rate.qo[4].resize(2); p3.Rate.qo[4][0] = -50; p3.Rate.qo[4][1] = -60; + p3.Pressure.t.resize(0); + p3.Pressure.p.resize(0); + p3.CS.C.resize(5); + p3.CS.C[0] = 0.1; p3.CS.C[1] = 0.1; p3.CS.C[2] = 0.1; p3.CS.C[3] = 0.1; p3.CS.C[4] = 0.1; + p3.CS.S.resize(5); + p3.CS.S[0] = 0.1; p3.CS.S[1] = 0.1; p3.CS.S[2] = 0.1; p3.CS.S[3] = 0.1; p3.CS.S[4] = 0.1; + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bo = dVec1(200, 1.2);//所有数为一个值 + p3.PVT.miuo = dVec1(200, 0.5);//所有数为一个值 + p3.Base.Pi = 40.0; + p3.Base.Cti = 1e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 3) { + //油单相常数pvt(五十口井) + p3.T = 1; + dVec1 t; + t.push_back(12); + t.push_back(12); + t.push_back(12); + t.push_back(48); + t.push_back(72); + p3.Rate.t.assign(50, t); + dVec1 q; + q.push_back(158.98699999999999); + q.push_back(190.785); + q.push_back(222.58199999999999); + q.push_back(238.48099999999999); + q.push_back(0.0); + p3.Rate.qo.assign(50, q); + p3.CS.C = dVec1(50, 0.01); + p3.CS.S = dVec1(50, 0); + + + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bo = dVec1(200, 1.07);//所有数为一个值 + p3.PVT.miuo = dVec1(200, 0.79);//所有数为一个值 + p3.Base.Pi = 40; + p3.Base.Cti = 0.43e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.025); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 4) { + //油单相变化pvt(一口井) + p3.T = 2; + p3.Rate.t.resize(1); + p3.Rate.qo.resize(1); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + p3.Rate.qo[0].resize(2); p3.Rate.qo[0][0] = 10; p3.Rate.qo[0][1] = 0; + p3.CS.C.resize(1); + p3.CS.C[0] = 0.1; + p3.CS.S.resize(1); + p3.CS.S[0] = 0.1; + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bo = dVec1(200, 1.2);//数值随压力变化 + p3.PVT.miuo = dVec1(200, 0.5);//数值随压力变化 + p3.PVT.Co = dVec1(200, 0.001);//数值随压力变化 + p3.Base.Pi = 40.0; + p3.Base.Cf = 1e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 5) { + //水单相常数pvt(一口井) + p3.T = 3; + p3.Rate.t.resize(1); + p3.Rate.qw.resize(1); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + p3.Rate.qw[0].resize(2); p3.Rate.qw[0][0] = -10; p3.Rate.qw[0][1] = 0; + p3.CS.C.resize(1); + p3.CS.C[0] = 0.1; + p3.CS.S.resize(1); + p3.CS.S[0] = 0.1; + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bw = dVec1(200, 1.05);//所有数为一个值 + p3.PVT.miuw = dVec1(200, 0.8);//所有数为一个值 + p3.Base.Pi = 40.0; + p3.Base.Cti = 1e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 6) { + //水单相变化pvt(一口井) + p3.T = 4; + p3.Rate.t.resize(1); + p3.Rate.qw.resize(1); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + p3.Rate.qw[0].resize(2); p3.Rate.qw[0][0] = -10; p3.Rate.qw[0][1] = 0; + p3.CS.C.resize(1); + p3.CS.C[0] = 0.1; + p3.CS.S.resize(1); + p3.CS.S[0] = 0.1; + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bw = dVec1(200, 1.05);//数值随压力变化 + p3.PVT.miuw = dVec1(200, 0.8);//数值随压力变化 + p3.PVT.Cw = dVec1(200, 0.0001);//数值随压力变化 + p3.Base.Pi = 40.0; + p3.Base.Cf = 1e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 7) { + //气单相变化pvt(一口井) + p3.T = 5; + p3.Rate.t.resize(1); + p3.Rate.qg.resize(1); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + p3.Rate.qg[0].resize(2); p3.Rate.qg[0][0] = 50000; p3.Rate.qg[0][1] = 0; + p3.CS.C.resize(1); + p3.CS.C[0] = 0.1; + p3.CS.S.resize(1); + p3.CS.S[0] = 0.1; + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bg = dVec1(200, 5e-3);//数值随压力变化 + p3.PVT.miug = dVec1(200, 2e-2);//数值随压力变化 + p3.PVT.Cg = dVec1(200, 2e-2);//数值随压力变化 + p3.Base.Pi = 40.0; + p3.Base.Cf = 1e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 8) { + //气单相拟压力(一口井) + p3.T = 6; + p3.Rate.t.resize(1); + p3.Rate.qg.resize(1); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + p3.Rate.qg[0].resize(2); p3.Rate.qg[0][0] = 50000; p3.Rate.qg[0][1] = 0; + p3.CS.C.resize(1); + p3.CS.C[0] = 0.1; + p3.CS.S.resize(1); + p3.CS.S[0] = 0.1; + p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + p3.PVT.Bg = dVec1(200, 5e-3);//数值随压力变化 + p3.PVT.miug = dVec1(200, 2e-2);//数值随压力变化 + p3.PVT.Cg = dVec1(200, 2e-2);//数值随压力变化 + p3.Base.Pi = 40.0; + p3.Base.Cf = 1e-3; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + else if (flowtype == 9) { + //油水两相(一口井) + p3.T = 8; + p3.Rate.t.resize(1); + p3.Rate.qg.resize(1); + p3.Rate.t[0].resize(2); p3.Rate.t[0][0] = 2000; p3.Rate.t[0][1] = 500; + //定产油量 + p3.Rate.qo[0].resize(2); p3.Rate.qo[0][0] = 20; p3.Rate.qo[0][1] = 0; + p3.Rate.qw[0].resize(2); p3.Rate.qw[0][0] = 0; p3.Rate.qw[0][1] = 0; + ////定产液量 + //p3.Rate.qo[0].resize(2); p3.Rate.qo[0][0] = 15; p3.Rate.qo[0][1] = 0; + //p3.Rate.qw[0].resize(2); p3.Rate.qw[0][0] = 5; p3.Rate.qw[0][1] = 0; + ////定注水量 + //p3.Rate.qo[0].resize(2); p3.Rate.qo[0][0] = 0; p3.Rate.qo[0][1] = 0; + //p3.Rate.qw[0].resize(2); p3.Rate.qw[0][0] = -20; p3.Rate.qw[0][1] = 0; + + p3.CS.C.resize(1); + p3.CS.C[0] = 0.1; + p3.CS.S.resize(1); + p3.CS.S[0] = 0.1; + //p3.PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { p3.PVT.p[i] = (i + 1.0); } + //p3.PVT.Bo = dVec1(200, 1.2);//数值随压力变化 + //p3.PVT.miuo = dVec1(200, 0.5);//数值随压力变化 + //p3.PVT.Bw = dVec1(200, 1.05);//数值随压力变化 + //p3.PVT.miuw = dVec1(200, 0.8);//数值随压力变化 + //p3.PVT.So = dVec1(81, 0); for (int i = 0; i < 81; ++i) { p3.PVT.So[i] = (0.1 + i * 0.01); } + //p3.PVT.Kro = dVec1(81, 0); for (int i = 0; i < 81; ++i) { p3.PVT.Kro[i] = (i*0.0125); } + //p3.PVT.Krw = dVec1(81, 0); for (int i = 0; i < 81; ++i) { p3.PVT.Krw[i] = (1 - i * 0.0125); } + + readCSVColumn("PVT_ow.csv", 5, p3.PVT.miuo); + readCSVColumn("PVT_ow.csv", 4, p3.PVT.Bo); + readCSVColumn("PVT_ow.csv", 2, p3.PVT.miuw); + readCSVColumn("PVT_ow.csv", 1, p3.PVT.Bw); + readCSVColumn("PVT_ow.csv", 0, p3.PVT.p); + readCSVColumn("Krow.csv", 0, p3.PVT.So); + readCSVColumn("Krow.csv", 2, p3.PVT.Kro); + readCSVColumn("Krow.csv", 1, p3.PVT.Krw); + + p3.Base.Pi = 40.0; + p3.Base.Cf = 1e-4; + p3.Base.Swi = 0.2; + p3.Base.k = dVec1(p2.Trinodexy.size(), 0.001); + p3.Base.phi = dVec1(p2.Trinodexy.size(), 0.1); + p3.Base.h = dVec1(p2.Trinodexy.size(), 10); + p3.Base.d = 1.05; + p3.Base.dt_Min = 0.0025; + p3.Base.dt_Max = 12.5; + } + + //非均质性设置 + if (feijunzhi == 1) { + dVec2 k; + a[0] = -1000; a[1] = -800; a[2] = 0.001; k.push_back(a); + a[0] = -800; a[1] = 1000; a[2] = 0.01; k.push_back(a); + a[0] = 0; a[1] = 100; a[2] = 0.005; k.push_back(a); + a[0] = 500; a[1] = -1000; a[2] = 0.008; k.push_back(a); + a[0] = 1000; a[1] = 800; a[2] = 0.02; k.push_back(a); + HX_KRING_INPUT k0(0.01, 100, 1000, 0, p2.Trinodexy, k); + HX_KRING_OUTPUT k1; + HX_NWTM_KRINGING(k1, k0, "HX_license.dat"); + p3.Base.k = k1.v; + + dVec2 phi; + a[0] = -600; a[1] = 0; a[2] = 0.1; phi.push_back(a); + a[0] = 0; a[1] = 100; a[2] = 0.2; phi.push_back(a); + a[0] = 1000; a[1] = -200; a[2] = 0.05; phi.push_back(a); + HX_KRING_INPUT phi0(0.01, 100, 1000, 0, p2.Trinodexy, phi); + HX_KRING_OUTPUT phi1; + HX_NWTM_KRINGING(phi1, phi0, "HX_license.dat"); + p3.Base.phi = phi1.v; + + dVec2 h; + a[0] = -1000; a[1] = 100; a[2] = 10; h.push_back(a); + a[0] = 0; a[1] = 0; a[2] = 5; h.push_back(a); + a[0] = 1000; a[1] = 300; a[2] = 12; h.push_back(a); + HX_KRING_INPUT h0(0.01, 100, 1000, 0, p2.Trinodexy, h); + HX_KRING_OUTPUT h1; + HX_NWTM_KRINGING(h1, h0, "HX_license.dat"); + p3.Base.h = h1.v; + + /* std::ofstream file("k_phi_h.csv"); + file << std::fixed << std::setprecision(15); + for (int i = 0; i < p2.Trinodexy.size(); ++i) + { + file << p2.Trinodexy[i][0] << "," << p2.Trinodexy[i][1] << "," << p3.Base.k[i] << "," << p3.Base.phi[i] << "," << p3.Base.h[i] <<"\n"; + } + + file.close();*/ + } + + //模型计算 + HX_NWTM_MODEL(p4, p3, "HX_license.dat"); + LeaveSilentDllMode(); + + std::cout << " " << name[iiii] << ":" << getPEBInum() << "," << getsolvetime() << "ms\n"; + + //数据导出 + /*dVec2 pwf; + for (int i = 0; i < p4.t.size(); ++i) { + dVec1 a; + a.resize(p4.pw.size() + 1); + a[0] = p4.t[i]; + for (int j = 1; j < a.size(); ++j) { + a[j] = p4.pw[j - 1][i]; + } + pwf.push_back(a); + } + std::string filename = solvetypename[type] + name[iiii] + "pwf.csv"; + Write2DVectorToCSV(pwf, filename);*/ + + /* Write1DVectorToCSV(p4.t, "t.csv"); + Write2DVectorToCSV(p4.pw, "pw.csv"); + Write2DVectorToCSV(p4.p, "C2.csv"); + if (p3.T == 8) { + Write2DVectorToCSV(p4.So, "So.csv"); + }*/ + } + + } + } + + return 0; +} \ No newline at end of file diff --git a/3rd/Pebi/V3/pch.h b/3rd/Pebi/V3/pch.h new file mode 100644 index 0000000..48ec5f1 --- /dev/null +++ b/3rd/Pebi/V3/pch.h @@ -0,0 +1,482 @@ +#pragma once +#ifndef PCH_H +#define PCH_H +#include "framework.h" +#endif //PCH_H + +#define HX_API extern "C" _declspec(dllexport) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "accelwt_solver_api.h" +#include "accelwt_cpu.h" +#include +const double M_PI = acos(-1.0); +typedef std::vector>>dVec3; //三维数组:double +typedef std::vector>dVec2; //二维数组:double +typedef std::vector>iVec2; //二维数组:int +typedef std::vectordVec1; //一维数组:double +typedef std::vectoriVec1; //一维数组:int + +template void HX_copy(std::vector>>& p1, const std::vector>>& p0) +{ + int m = p0.size(); p1.resize(m); + for (int i = 0; i < m; ++i) + { + int n = p0[i].size(); p1[i].resize(n); + for (int j = 0; j < n; ++j) + { + int l = p0[i][j].size(); p1[i][j].resize(l); + for (int k = 0; k < l; ++k) + { + p1[i][j][k] = p0[i][j][k]; + } + } + } +} +template void HX_copy(std::vector>& p1, const std::vector>& p0) +{ + int m = p0.size(); p1.resize(m); + for (int i = 0; i < m; ++i) + { + int n = p0[i].size(); p1[i].resize(n); + for (int j = 0; j < n; ++j) + { + p1[i][j] = p0[i][j]; + } + } +} +template void HX_copy(std::vector& p1, const std::vector& p0) +{ + int m = p0.size(); p1.resize(m); + for (int i = 0; i < m; ++i) + { + p1[i] = p0[i]; + } +} +template void HX_copy(std::vector>>& p1, T*** p0, int m, int* n, int l) +{ + p1.resize(m); + for (int i = 0; i < m; ++i) + { + p1[i].resize(n[i]); + for (int j = 0; j < n[i]; ++j) + { + p1[i][j].resize(l); + for (int k = 0; k < l; ++k) + { + p1[i][j][k] = p0[i][j][k]; + } + } + } +} +template void HX_copy(std::vector>& p1, T** p0, int m, int n) +{ + p1.resize(m); + for (int i = 0; i < m; ++i) + { + p1[i].resize(n); + for (int j = 0; j < n; ++j) + { + p1[i][j] = p0[i][j]; + } + } +} +template void HX_copy(std::vector& p1, T* p0, int m) +{ + p1.resize(m); + for (int i = 0; i < m; ++i) + { + p1[i] = p0[i]; + } +} + +//点结构体 +struct point +{ + //点结构体 + double x; double y; //点坐标 + point() { x = 0; y = 0; } + ~point() {} + void set(const double& x_ = 0, const double& y_ = 0) { x = x_; y = y_; } + void set(const point& p) { x = p.x; y = p.y; } +}; +struct point3 +{ + double x; + double y; + double z; + point3() { x = 0; y = 0; z = 0; } + ~point3() {} + point3(const dVec1&p) { x = p[0]; y = p[1]; z = p[2]; } + point3(const double& x_ = 0, const double& y_ = 0, const double&z_ = 0) { x = x_; y = y_; z = z_;} + void set(const double& x_ = 0, const double& y_ = 0, const double& z_ = 0) { x = x_; y = y_; z = z_; } + void set(const point3&p) { x = p.x; y = p.y; z = p.z; } +}; +//网格结构体 +struct cell +{ + //网格单元结构体 + std::vector p; + iVec2 pindex; + iVec1 isplot; + cell() {} + ~cell() {} +}; + + +//网格算法输入参数结构体 +struct HX_NWTM_GRID_INPUT +{ + // 网格划分算法输入参数结构体 + dVec2 Boundary; //3D:{x0, y0, z0, x1, y1, z1} //2D:{x0, y0, x1, y1} 边界数据 + dVec2 VerticalWell; //3D:{x0, y0, z0, x1, y1, z1, rw} //2D:{x0, y0, x1, y1, rw} 直井数据 + dVec2 HorizontalWell; //3D:{x0, y0, z0, x1, y1, z1, rw} 水平井数据 + dVec2 FractureVerticalWell; //3D:{x0, y0, z0, x1, y1, z1, wf} //2D:{x0, y0, x1, y1, wf, FC} 压裂直井数据(wf裂缝半宽,m,FC,裂缝导流能力,mD.m(FC为0时为无限导流,大于0时为有限导流)) + dVec3 MultistageFracturedHorizontalWell; //3D:{x0, y0, z0, x1, y1, z1, wf} //2D:{x0, y0, x1, y1, wf, FC} 多级压裂水平井数据(wf裂缝半宽,m,FC,裂缝导流能力,mD.m(FC为0时为无限导流,大于0时为有限导流)) + dVec2 InclinedWell; //3D:{x0, y0, z0, x1, y1, z1, rw} 斜井数据 + dVec2 Fault; //3D:{x0, y0, z0, x1, y1, z1} //2D:{x0, y0, x1, y1} 断层数据 + double GridControl; // 网格大小控制参数 + int D; // 维数 + + //默认初始化 + HX_NWTM_GRID_INPUT() + { + dVec1 a(3), b(4), c(5), d(6); + Boundary.resize(4); + b[0] = -1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = 1500.0; Boundary[0] = b; + b[0] = -1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = 1500.0; Boundary[1] = b; + b[0] = 1500.0; b[1] = 1500.0; b[2] = 1500.0; b[3] = -1500.0; Boundary[2] = b; + b[0] = 1500.0; b[1] = -1500.0; b[2] = -1500.0; b[3] = -1500.0; Boundary[3] = b; + + VerticalWell.resize(3); + a[0] = 0; a[1] = 0; a[2] = 0.1; VerticalWell[0] = a; + a[0] = 1000; a[1] = 1000; a[2] = 0.1; VerticalWell[1] = a; + a[0] = -1000; a[1] = -1000; a[2] = 0.1; VerticalWell[2] = a; + + HorizontalWell.resize(0); + + FractureVerticalWell.resize(1); + d[0] = -200; d[1] = -200; d[2] = 200; d[3] = -200; d[4] = 0.05; d[5] = 0; FractureVerticalWell[0] = d; + + MultistageFracturedHorizontalWell.resize(1); + MultistageFracturedHorizontalWell[0].resize(3, dVec1(5)); + d[0] = -600; d[1] = 600; d[2] = -400; d[3] = 600; d[4] = 0.1; d[5] = 0; MultistageFracturedHorizontalWell[0][0] = d; + d[0] = -600; d[1] = 400; d[2] = -400; d[3] = 400; d[4] = 0.1; d[5] = 0; MultistageFracturedHorizontalWell[0][1] = d; + d[0] = -600; d[1] = 200; d[2] = -400; d[3] = 200; d[4] = 0.1; d[5] = 0; MultistageFracturedHorizontalWell[0][2] = d; + + InclinedWell.resize(0); + + Fault.resize(1); + b[0] = -500; b[1] = 1000; b[2] = 500; b[3] = 500; Fault[0] = b; + + GridControl = 150.0; + + D = 2; + } + ~HX_NWTM_GRID_INPUT() {} +}; + +//网格算法输出参数结构体(绘图用) +struct HX_NWTM_GRID_OUTPUT1 +{ + cell TRI_cell; //三角形网格 + cell PEBI_cell; //PEBI网格 + + HX_NWTM_GRID_OUTPUT1() {} + ~HX_NWTM_GRID_OUTPUT1() {} +}; + +//网格算法输出参数结构体(模型用) +struct HX_NWTM_GRID_OUTPUT2 +{ + dVec2 Trinodexy; + dVec1 Area; + dVec2 D; + struct { + int n; + dVec2 XiLinw; + dVec2 lw; + dVec2 dw; + dVec1 rw; + iVec2 inwell; + dVec1 dwell; + } ZhiJingNeiBianJie; + struct { + int n; + dVec2 XiLinf; + dVec2 lf; + dVec2 df; + dVec1 xf; + iVec2 infra; + iVec1 nf; + iVec1 jjf; + iVec1 jjfl; + dVec1 lfcd; + iVec2 infra1; + dVec2 lf1; + dVec2 df1; + } LieFengJingNeiBianJie; + struct { + int n; + dVec2 XiLinh; + dVec2 lh; + dVec2 dh; + dVec2 dsxf; + iVec2 inhor; + iVec1 nhor; + dVec2 areah; + iVec2 inhor1; + iVec2 nh; + iVec2 jjh; + dVec2 hfcd; + iVec2 jjhl; + iVec2 jjh2; + iVec2 inhor2; + dVec2 lh1; + dVec2 dh1; + } DuoJiYaLieShuiPingJingNeiBianJie; + struct { + int n; + dVec2 WaiBianh; + dVec2 WaiBianl; + dVec2 WaiBiand; + } WaiBianJie; + struct { + int n; + dVec2 faultb1; + dVec2 faultb2; + dVec2 faultl1; + dVec2 faultd1; + } NeiBuDuanCeng; + struct { + iVec1 ia; + iVec1 ja; + iVec2 nzeros; + int numk; + } YuChuLiJuZhen; + HX_NWTM_GRID_OUTPUT2() {} + ~HX_NWTM_GRID_OUTPUT2() {} +}; + + +//KRINGING插值输入参数结构体 +struct HX_KRING_INPUT +{ + double nugget; //块金值:表示空间点在零距离处的变异程度,即测量误差和小于采样尺度的随机变异之和 + double sill; //基台值:表示变差函数随距离增加而趋于稳定的极限值,反映区域化变量的总变异程度 + double range; //变程:表示空间相关性的有效距离。当两点间距离超过 range 时,它们之间不再具有空间相关性 + double model; //变差函数模型:指定变差函数的数学形式,描述空间相关性随距离的变化规律{, , } + //高斯模型SPHERICAL(0):相关性随距离增加呈指数衰减,适用于连续性较强的变量 + //指数模型EXPONENTIAL(1):相关性快速衰减,适用于局部变异性较大的变量 + //球状模型GAUSSIAN(2):在变程内呈抛物线变化,超过变程后相关性为零 + dVec2 p; //插值点 + dVec2 v; // + ~HX_KRING_INPUT() {} + HX_KRING_INPUT(double nugget0, double sill0, double range0, double model0 , const dVec2& p0, const dVec2& v0) + { + nugget = nugget0; sill = sill0; range = range0; model = model0; + p = p0; + v = v0; + } +}; + +//KRINGING插值输出参数结构体 +struct HX_KRING_OUTPUT +{ + dVec1 v; + HX_KRING_OUTPUT() {} + ~HX_KRING_OUTPUT() {} +}; + +//数值试井模型求解器输入参数结构体 +struct HX_NWTM_MODEL_INPUT +{ + int T; //1:油单相常数pvt; 2:油单相变化pvt; 3:水单相常数pvt; 4:水单相变化pvt; 5:气单相变化pvt; 6:气单相拟压力; 7:油气两相; 8:油水两相; 9:气水两相; 10:油气水三相 + HX_NWTM_GRID_OUTPUT2 GRID; + struct Rate //流量数据 + { + dVec2 t; //时间, h [一口井一组数] + dVec2 qo; //油流量,m^3/d [一口井一组数] + dVec2 qg; //气流量,m^3/d [一口井一组数] + dVec2 qw; //水流量,m^3/d [一口井一组数] + }Rate; + struct Pressure //压力数据 + { + dVec2 t; //时间, h [一口井一组数] + dVec2 p; //压力, MPa [一口井一组数] + }Pressure; + struct CS //井储表皮数据 + { + dVec1 C; //井储, m^3/MPa [一口井一个数] + dVec1 S; //表皮, [一口井一个数] + }CS; + struct PVT //流体性质数据 + { + dVec1 p; //压力, MPa + double pb; //饱和压力, MPa + dVec1 Rso; //溶解气油比, m^3/m^3 + dVec1 Bo; //油体积系数, m^3/m^3 + dVec1 Co; //油压缩系数, 1/MPa + dVec1 miuo; //油粘度, mPa·s + dVec1 rouo; //油密度, kg/m^3 + dVec1 Rv; //凝析油气比, m^3/m^3 + dVec1 Bg; //气体积系数, m^3/m^3 + dVec1 Cg; //气压缩系数, 1/MPa + dVec1 miug; //气粘度, mPa·s + dVec1 roug; //气密度, kg/m^3 + dVec1 Z; //气偏差因子, 1 + dVec1 Rsw; //溶解气水比, m^3/m^3 + dVec1 Bw; //水体积系数, m^3/m^3 + dVec1 Cw; //水压缩系数, 1/MPa + dVec1 miuw; //水粘度, mPa·s + dVec1 rouw; //水密度, kg/m^3 + dVec1 V; //吸附气量, m^3/kg + dVec1 k_kinitial; //渗透率比, 1 + dVec1 Cf_Cfinitial; //岩石压缩系数比, 1 + dVec1 So; //油饱和度 + dVec1 Kro; //油相对渗透率 + dVec1 Sg; //气饱和度 + dVec1 Krg; //气相对渗透率 + dVec1 Sw; //水饱和度 + dVec1 Krw; //水相对渗透率 + }PVT; + struct Base //基础数据 + { + double Pi; //初始压力, MPa + double Cti; //综合压缩系数, 1/MPa + double Cf; //岩石压缩系数, 1/MPa + double Soi; //初始含油饱和度 + double Sgi; //初始含气饱和度 + double Swi; //初始含水饱和度 + dVec1 k; //渗透率, D [一个网格单元一个值] + dVec1 phi; //孔隙度, 1 [一个网格单元一个值] + dVec1 h; //储层厚度, m [一个网格单元一个值] + double d; //时间增长指数 + double dt_Min; //最小时间间隔, h + double dt_Max; //最大时间间隔, h + }Base; + + //初始化 + HX_NWTM_MODEL_INPUT() {} + ~HX_NWTM_MODEL_INPUT() {} + HX_NWTM_MODEL_INPUT(const HX_NWTM_GRID_OUTPUT2& p0) + { + T =1; + GRID = p0; + + Rate.t.resize(5); + Rate.qo.resize(5); + Rate.qw.resize(5); + Rate.qg.resize(5); + + Rate.t[0].resize(2); Rate.t[0][0] = 2000; Rate.t[0][1] = 500; + Rate.qo[0].resize(2); Rate.qo[0][0] = 10; Rate.qo[0][1] = 0; + Rate.qw[0].resize(2); Rate.qw[0][0] = 2; Rate.qw[0][1] = 0; + Rate.qg[0].resize(2); Rate.qg[0][0] = 20000; Rate.qg[0][1] = 0; + + Rate.t[1].resize(0); + Rate.qo[1].resize(0); + Rate.qw[1].resize(0); + Rate.qg[1].resize(0); + + Rate.t[2].resize(3); Rate.t[2][0] = 1000; Rate.t[2][1] = 1000; Rate.t[2][2] = 500; + Rate.qo[2].resize(3); Rate.qo[2][0] = 30; Rate.qo[2][1] = 40; Rate.qo[2][2] = 20; + Rate.qw[2].resize(3); Rate.qw[2][0] = 3; Rate.qw[2][1] = 4; Rate.qw[2][2] = 2; + Rate.qg[2].resize(3); Rate.qg[2][0] = 30000; Rate.qg[2][1] = 40000; Rate.qg[2][2] = 20000; + + Rate.t[3].resize(2); Rate.t[3][0] = 1500; Rate.t[3][1] = 1000; + Rate.qo[3].resize(2); Rate.qo[3][0] = 30; Rate.qo[3][1] = 20; + Rate.qw[3].resize(2); Rate.qw[3][0] = 5; Rate.qw[3][1] = 2; + Rate.qg[3].resize(2); Rate.qg[3][0] = 50000; Rate.qg[3][1] = 20000; + Rate.t[4].resize(2); Rate.t[4][0] = 1000; Rate.t[4][1] = 1500; + Rate.qo[4].resize(2); Rate.qo[4][0] = -50; Rate.qo[4][1] = -60; + Rate.qw[4].resize(2); Rate.qw[4][0] = -2; Rate.qw[4][1] = -5; + Rate.qg[4].resize(2); Rate.qg[4][0] = -20000; Rate.qg[4][1] = -50000; + + Pressure.t.resize(0); + Pressure.p.resize(0); + + CS.C.resize(5); + CS.C[0] = 0.1; CS.C[1] = 0.1; CS.C[2] = 0.1; CS.C[3] = 0.1; CS.C[4] = 0.1; + CS.S.resize(5); + CS.S[0] = 0.1; CS.S[1] = 0.1; CS.S[2] = 0.1; CS.S[3] = 0.1; CS.S[4] = 0.1; + + + PVT.p = dVec1(200, 0); for (int i = 0; i < 200; ++i) { PVT.p[i] = (i + 1.0); } + PVT.pb = 40.0; + PVT.Rso = dVec1(200, 0); + PVT.Bo = dVec1(200, 1.2); + PVT.Co = dVec1(200, 5e-4); + PVT.miuo = dVec1(200, 0.5); + PVT.rouo = dVec1(200, 800); + PVT.Rv = dVec1(200, 0); + PVT.Bg = dVec1(200, 5e-3); + PVT.Cg = dVec1(200, 2e-2); + PVT.miug = dVec1(200, 2e-2); + PVT.roug = dVec1(200, 200); + PVT.Z = dVec1(200, 1); + PVT.Rsw = dVec1(200, 0); + PVT.Bw = dVec1(200, 1.05); + PVT.Cw = dVec1(200, 1e-4); + PVT.miuw = dVec1(200, 0.8); + PVT.rouw = dVec1(200, 1000); + PVT.V = dVec1(200, 0); + + PVT.k_kinitial = dVec1(200, 1); + PVT.Cf_Cfinitial = dVec1(200, 1); + + PVT.So = dVec1(81, 0); for (int i = 0; i < 81; ++i) { PVT.So[i] = (0.1+i*0.01); } + PVT.Kro = dVec1(81, 0); for (int i = 0; i < 81; ++i) { PVT.Kro[i] = (i*0.0125); } + PVT.Krw = dVec1(81, 0); for (int i = 0; i < 81; ++i) { PVT.Krw[i] = (1 - i * 0.0125); } + PVT.Sg = dVec1(100, 0); + PVT.Krg = dVec1(100, 0); + PVT.Sw = dVec1(100, 0); + + + + Base.Pi = 40.0; + Base.Cti = 1e-3; + Base.Cf = 1e-4; + Base.Soi = 0.8; + Base.Sgi = 0.0; + Base.Swi = 0.2; + Base.k = dVec1(p0.Trinodexy.size(), 0.001); + Base.phi = dVec1(p0.Trinodexy.size(), 0.1); + Base.h = dVec1(p0.Trinodexy.size(), 10); + Base.d = 1.05; + Base.dt_Min = 0.0025; + Base.dt_Max = 12.5; + } +}; + +//数值试井模型求解器输出参数结构体 +struct HX_NWTM_MODEL_OUTPUT +{ + dVec1 t; //时间, h + dVec2 pw; //井底压力, MPa [一口井一组数] + dVec2 p; //压力分布, MPa [一个时间一组数] + dVec2 So; //油饱和度分布 [一个时间一组数] + dVec2 Sg; //气饱和度分布 [一个时间一组数] + dVec2 Sw; //水饱和度分布 [一个时间一组数] + dVec2 k; //渗透率分布,mD [一个时间一组数] + HX_NWTM_MODEL_OUTPUT() {} + ~HX_NWTM_MODEL_OUTPUT() {} +}; + +HX_API void HX_NWTM_GRID(HX_NWTM_GRID_OUTPUT1& p1, HX_NWTM_GRID_OUTPUT2& p2, const HX_NWTM_GRID_INPUT& p0, std::string LIC); //数值试井网格接口 +HX_API void HX_NWTM_KRINGING(HX_KRING_OUTPUT& p1, const HX_KRING_INPUT p0, std::string LIC); //数值试井非均质性计算接口 +HX_API void HX_NWTM_MODEL(HX_NWTM_MODEL_OUTPUT& p1, const HX_NWTM_MODEL_INPUT& p0, std::string LIC); //数值试井模型求解器接口 +HX_API void set_omp_threads(int n); +HX_API void set_ilu_reuse_steps(int n); +HX_API int getPEBInum(); +HX_API int getsolvetime(); +HX_API void set_solvetype(int n); + + diff --git a/3rd/Pebi/bin/AccelWT_CPU.dll b/3rd/Pebi/bin/AccelWT_CPU.dll new file mode 100644 index 0000000..ed7ba53 Binary files /dev/null and b/3rd/Pebi/bin/AccelWT_CPU.dll differ diff --git a/3rd/Pebi/bin/HX_NWTM.dll b/3rd/Pebi/bin/HX_NWTM.dll index fec1884..7da5d2d 100644 Binary files a/3rd/Pebi/bin/HX_NWTM.dll and b/3rd/Pebi/bin/HX_NWTM.dll differ diff --git a/3rd/Pebi/bin/libiomp5md.dll b/3rd/Pebi/bin/libiomp5md.dll new file mode 100644 index 0000000..1c4a9b3 Binary files /dev/null and b/3rd/Pebi/bin/libiomp5md.dll differ diff --git a/3rd/Pebi/include/accelwt_cpu.h b/3rd/Pebi/include/accelwt_cpu.h new file mode 100644 index 0000000..42ca01c --- /dev/null +++ b/3rd/Pebi/include/accelwt_cpu.h @@ -0,0 +1,223 @@ +#ifndef ACCELWT_CPU_H +#define ACCELWT_CPU_H + +#if defined(_WIN32) || defined(__CYGWIN__) +# if defined(ACCELWT_CPU_STATIC_DEFINE) +# define ACCELWT_CPU_API +# elif defined(ACCELWT_CPU_BUILDING_LIBRARY) +# define ACCELWT_CPU_API __declspec(dllexport) +# else +# define ACCELWT_CPU_API __declspec(dllimport) +# endif +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define ACCELWT_CPU_API __attribute__((visibility("default"))) +#else +# define ACCELWT_CPU_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACCELWT_CPU_VERSION_MAJOR 3 +#define ACCELWT_CPU_VERSION_MINOR 2 +#define ACCELWT_CPU_VERSION_PATCH 0 + +/* + * Persistent simulation session. Create one context for a fixed CSR sparsity + * pattern, reuse it across accepted physical time steps, and destroy it when + * the simulation ends. Keeping this object alive enables temporal history, + * workspace reuse and lagged preconditioner refreshes. + */ +typedef struct AccelWTCPUContext AccelWTCPUContext; +typedef AccelWTCPUContext AccelWTCPUSession; + +typedef enum AccelWTCPUStatus +{ + ACCELWT_CPU_SUCCESS = 0, + ACCELWT_CPU_INVALID_ARGUMENT = 1, + ACCELWT_CPU_INVALID_MATRIX = 2, + ACCELWT_CPU_ALLOCATION_FAILED = 3, + ACCELWT_CPU_SETUP_FAILED = 4, + ACCELWT_CPU_NOT_READY = 5, + ACCELWT_CPU_SOLVE_FAILED = 6, + ACCELWT_CPU_NOT_CONVERGED = 7 +} AccelWTCPUStatus; + +typedef struct AccelWTCPUOptions +{ + int max_iterations; + double relative_tolerance; + double absolute_tolerance; + int ilu_jacobi_iterations; + int omp_threads; + int use_initial_guess; + /* Default: 1. Set to 0 to opt into experimental LU-split Jacobi. */ + int use_exact_triangular_solve; + /* + * Experimental four-thread block triangular application. + * 0 keeps the mode selected above, 1 performs one block sweep and + * 2 performs one cross-subdomain correction sweep. Requires omp_threads=4. + */ + int block_triangular_sweeps; +} AccelWTCPUOptions; + +typedef struct AccelWTCPUInfo +{ + int iterations; + double final_rel_residual; + double final_abs_residual; + double setup_seconds; + double solve_seconds; + int status; +} AccelWTCPUInfo; + +typedef struct AccelWTCPUPhaseInfo +{ + double initialization_seconds; + double direction_update_seconds; + double preconditioner_seconds; + double spmv_reduction_seconds; + double solution_update_seconds; + double true_residual_seconds; +} AccelWTCPUPhaseInfo; + +typedef enum AccelWTCPUTemporalGuess +{ + ACCELWT_CPU_TEMPORAL_GUESS_NONE = 0, + ACCELWT_CPU_TEMPORAL_GUESS_PREVIOUS = 1, + ACCELWT_CPU_TEMPORAL_GUESS_MR2 = 2 +} AccelWTCPUTemporalGuess; + +typedef struct AccelWTCPUTemporalOptions +{ + int initial_guess_policy; + int enable_early_exit; + int ilu_refresh_interval; + int ilu_refresh_iteration_threshold; +} AccelWTCPUTemporalOptions; + +typedef struct AccelWTCPUStepInfo +{ + AccelWTCPUInfo solve; + int used_mr2; + int history_depth; + int early_exit; + int refreshed_preconditioner; + double predicted_relative_residual; + double prediction_seconds; + double update_seconds; + double solve_seconds; +} AccelWTCPUStepInfo; + +/* + * Simple session configuration for time-dependent applications. + * Zero values select library defaults. One ILU factor is used for + * ilu_reuse_steps consecutive time steps; 1 rebuilds it every step. + */ +typedef struct AccelWTCPUSessionOptions +{ + int omp_threads; + int ilu_reuse_steps; +} AccelWTCPUSessionOptions; + +#define ACCELWT_CPU_SESSION_OPTIONS_DEFAULT {0, 5} + +/* + * Simple three-function interface. Passing NULL options uses the defaults, + * including an ILU reuse window of five time steps. + */ +ACCELWT_CPU_API int accelwt_cpu_session_create( + int n, + int nnz, + const int *row_ptr, + const int *col_ind, + const AccelWTCPUSessionOptions *options, + AccelWTCPUSession **session); + +ACCELWT_CPU_API int accelwt_cpu_session_solve( + AccelWTCPUSession *session, + const double *values, + const double *rhs, + double *x, + AccelWTCPUStepInfo *info); + +/* Accepts NULL. */ +ACCELWT_CPU_API void accelwt_cpu_session_destroy(AccelWTCPUSession *session); + +/* Returns the default options without allocating a solver context. */ +ACCELWT_CPU_API void accelwt_cpu_default_options(AccelWTCPUOptions *options); +ACCELWT_CPU_API void accelwt_cpu_default_temporal_options( + AccelWTCPUTemporalOptions *options); + +ACCELWT_CPU_API const char *accelwt_cpu_backend_name(void); +ACCELWT_CPU_API const char *accelwt_cpu_status_string(int status); + +/* + * Creates a persistent solver for a zero-based, square CSR matrix pattern. + * The row and column arrays are copied and may be released after this call. + * Column indices must be strictly increasing within each row, and every row + * must contain its diagonal entry. + */ +ACCELWT_CPU_API int accelwt_cpu_create(int n, + int nnz, + const int *row_ptr, + const int *col_ind, + const AccelWTCPUOptions *options, + AccelWTCPUContext **context); + +/* + * Copies new CSR values into the context. A nonzero refresh_preconditioner + * rebuilds ILU0. The first update always builds ILU0, regardless of the flag. + */ +ACCELWT_CPU_API int accelwt_cpu_update_matrix(AccelWTCPUContext *context, + const double *values, + int refresh_preconditioner, + AccelWTCPUInfo *info); + +/* Solves A*x=rhs. The context is not safe for concurrent solve calls. */ +ACCELWT_CPU_API int accelwt_cpu_solve(AccelWTCPUContext *context, + const double *rhs, + double *x, + AccelWTCPUInfo *info); + +/* + * Returns phase timings from the latest solve. Values are zero unless the + * library was built with ACCELWT_CPU_PHASE_TIMING=ON. + */ +ACCELWT_CPU_API int accelwt_cpu_get_last_phase_info( + const AccelWTCPUContext *context, + AccelWTCPUPhaseInfo *info); + +/* + * Configures the library-owned temporal policy. The default is MR2 with + * verified early exit and a five-step lagged-ILU interval. + */ +ACCELWT_CPU_API int accelwt_cpu_set_temporal_options( + AccelWTCPUContext *context, + const AccelWTCPUTemporalOptions *options); + +/* + * Updates A and solves one accepted physical time step while managing MR2 + * history, verified early exit and lagged-ILU refreshes inside the session. + * This interface assumes one linear solve per accepted physical time step. + * Do not call it for intermediate or rejected nonlinear iterations because a + * successful call immediately commits x to the temporal history. + */ +ACCELWT_CPU_API int accelwt_cpu_solve_step(AccelWTCPUContext *context, + const double *values, + const double *rhs, + double *x, + AccelWTCPUStepInfo *info); + +ACCELWT_CPU_API int accelwt_cpu_reset_temporal_history( + AccelWTCPUContext *context); + +/* Accepts NULL. */ +ACCELWT_CPU_API void accelwt_cpu_destroy(AccelWTCPUContext *context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/3rd/Pebi/include/pch.h b/3rd/Pebi/include/pch.h index 455979c..dba643a 100644 --- a/3rd/Pebi/include/pch.h +++ b/3rd/Pebi/include/pch.h @@ -1,4 +1,4 @@ -锘#pragma once +#pragma once #ifndef PCH_H #define PCH_H #include "framework.h" @@ -14,15 +14,18 @@ #include #include #include +#include "accelwt_cpu.h" +#include #ifndef M_PI const double M_PI = acos(-1.0); #endif -typedef std::vector>>dVec3; //涓夌淮鏁扮粍:double -typedef std::vector>dVec2; //浜岀淮鏁扮粍:double -typedef std::vector>iVec2; //浜岀淮鏁扮粍:int -typedef std::vectordVec1; //涓缁存暟缁:double -typedef std::vectoriVec1; //涓缁存暟缁:int + +typedef std::vector>>dVec3; //三维数组:double +typedef std::vector>dVec2; //二维数组:double +typedef std::vector>iVec2; //二维数组:int +typedef std::vectordVec1; //一维数组:double +typedef std::vectoriVec1; //一维数组:int template void HX_copy(std::vector>>& p1, const std::vector>>& p0) { @@ -97,11 +100,11 @@ template void HX_copy(std::vector& p1, T* p0, int m) } } -//鐐圭粨鏋勪綋 +//点结构体 struct point { - //鐐圭粨鏋勪綋 - double x; double y; //鐐瑰潗鏍 + //点结构体 + double x; double y; //点坐标 point() { x = 0; y = 0; } ~point() {} void set(const double& x_ = 0, const double& y_ = 0) { x = x_; y = y_; } @@ -119,10 +122,10 @@ struct point3 void set(const double& x_ = 0, const double& y_ = 0, const double& z_ = 0) { x = x_; y = y_; z = z_; } void set(const point3&p) { x = p.x; y = p.y; z = p.z; } }; -//缃戞牸缁撴瀯浣 +//网格结构体 struct cell { - //缃戞牸鍗曞厓缁撴瀯浣 + //网格单元结构体 std::vector p; iVec2 pindex; iVec1 isplot; @@ -131,21 +134,21 @@ struct cell }; -//缃戞牸绠楁硶杈撳叆鍙傛暟缁撴瀯浣 +//网格算法输入参数结构体 struct HX_NWTM_GRID_INPUT { - // 缃戞牸鍒掑垎绠楁硶杈撳叆鍙傛暟缁撴瀯浣 - dVec2 Boundary; //3D:{x0, y0, z0, x1, y1, z1} //2D:{x0, y0, x1, y1} 杈圭晫鏁版嵁 - dVec2 VerticalWell; //3D:{x0, y0, z0, x1, y1, z1, rw} //2D:{x0, y0, x1, y1, rw} 鐩翠簳鏁版嵁 - dVec2 HorizontalWell; //3D:{x0, y0, z0, x1, y1, z1, rw} 姘村钩浜曟暟鎹 - dVec2 FractureVerticalWell; //3D:{x0, y0, z0, x1, y1, z1, wf} //2D:{x0, y0, x1, y1, wf, FC} 鍘嬭鐩翠簳鏁版嵁(wf瑁傜紳鍗婂,m,FC,瑁傜紳瀵兼祦鑳藉姏,mD.m(FC涓0鏃朵负鏃犻檺瀵兼祦锛屽ぇ浜0鏃朵负鏈夐檺瀵兼祦)) - dVec3 MultistageFracturedHorizontalWell; //3D:{x0, y0, z0, x1, y1, z1, wf} //2D:{x0, y0, x1, y1, wf, FC} 澶氱骇鍘嬭姘村钩浜曟暟鎹(wf瑁傜紳鍗婂,m,FC,瑁傜紳瀵兼祦鑳藉姏,mD.m(FC涓0鏃朵负鏃犻檺瀵兼祦锛屽ぇ浜0鏃朵负鏈夐檺瀵兼祦)) - dVec2 InclinedWell; //3D:{x0, y0, z0, x1, y1, z1, rw} 鏂滀簳鏁版嵁 - dVec2 Fault; //3D:{x0, y0, z0, x1, y1, z1} //2D:{x0, y0, x1, y1} 鏂眰鏁版嵁 - double GridControl; // 缃戞牸澶у皬鎺у埗鍙傛暟 - int D; // 缁存暟 - - //榛樿鍒濆鍖 + // 网格划分算法输入参数结构体 + dVec2 Boundary; //3D:{x0, y0, z0, x1, y1, z1} //2D:{x0, y0, x1, y1} 边界数据 + dVec2 VerticalWell; //3D:{x0, y0, z0, x1, y1, z1, rw} //2D:{x0, y0, x1, y1, rw} 直井数据 + dVec2 HorizontalWell; //3D:{x0, y0, z0, x1, y1, z1, rw} 水平井数据 + dVec2 FractureVerticalWell; //3D:{x0, y0, z0, x1, y1, z1, wf} //2D:{x0, y0, x1, y1, wf, FC} 压裂直井数据(wf裂缝半宽,m,FC,裂缝导流能力,mD.m(FC为0时为无限导流,大于0时为有限导流)) + dVec3 MultistageFracturedHorizontalWell; //3D:{x0, y0, z0, x1, y1, z1, wf} //2D:{x0, y0, x1, y1, wf, FC} 多级压裂水平井数据(wf裂缝半宽,m,FC,裂缝导流能力,mD.m(FC为0时为无限导流,大于0时为有限导流)) + dVec2 InclinedWell; //3D:{x0, y0, z0, x1, y1, z1, rw} 斜井数据 + dVec2 Fault; //3D:{x0, y0, z0, x1, y1, z1} //2D:{x0, y0, x1, y1} 断层数据 + double GridControl; // 网格大小控制参数 + int D; // 维数 + + //默认初始化 HX_NWTM_GRID_INPUT() { dVec1 a(3), b(4), c(5), d(6); @@ -183,17 +186,17 @@ struct HX_NWTM_GRID_INPUT ~HX_NWTM_GRID_INPUT() {} }; -//缃戞牸绠楁硶杈撳嚭鍙傛暟缁撴瀯浣(缁樺浘鐢) +//网格算法输出参数结构体(绘图用) struct HX_NWTM_GRID_OUTPUT1 { - cell TRI_cell; //涓夎褰㈢綉鏍 - cell PEBI_cell; //PEBI缃戞牸 + cell TRI_cell; //三角形网格 + cell PEBI_cell; //PEBI网格 HX_NWTM_GRID_OUTPUT1() {} ~HX_NWTM_GRID_OUTPUT1() {} }; -//缃戞牸绠楁硶杈撳嚭鍙傛暟缁撴瀯浣(妯″瀷鐢) +//网格算法输出参数结构体(模型用) struct HX_NWTM_GRID_OUTPUT2 { dVec2 Trinodexy; @@ -266,17 +269,17 @@ struct HX_NWTM_GRID_OUTPUT2 }; -//KRINGING鎻掑艰緭鍏ュ弬鏁扮粨鏋勪綋 +//KRINGING插值输入参数结构体 struct HX_KRING_INPUT { - double nugget; //鍧楅噾鍊:琛ㄧず绌洪棿鐐瑰湪闆惰窛绂诲鐨勫彉寮傜▼搴︼紝鍗虫祴閲忚宸拰灏忎簬閲囨牱灏哄害鐨勯殢鏈哄彉寮備箣鍜 - double sill; //鍩哄彴鍊:琛ㄧず鍙樺樊鍑芥暟闅忚窛绂诲鍔犺岃秼浜庣ǔ瀹氱殑鏋侀檺鍊硷紝鍙嶆槧鍖哄煙鍖栧彉閲忕殑鎬诲彉寮傜▼搴 - double range; //鍙樼▼:琛ㄧず绌洪棿鐩稿叧鎬х殑鏈夋晥璺濈銆傚綋涓ょ偣闂磋窛绂昏秴杩 range 鏃讹紝瀹冧滑涔嬮棿涓嶅啀鍏锋湁绌洪棿鐩稿叧鎬 - double model; //鍙樺樊鍑芥暟妯″瀷:鎸囧畾鍙樺樊鍑芥暟鐨勬暟瀛﹀舰寮忥紝鎻忚堪绌洪棿鐩稿叧鎬ч殢璺濈鐨勫彉鍖栬寰媨, , } - //楂樻柉妯″瀷SPHERICAL(0)锛氱浉鍏虫ч殢璺濈澧炲姞鍛堟寚鏁拌“鍑忥紝閫傜敤浜庤繛缁ц緝寮虹殑鍙橀噺 - //鎸囨暟妯″瀷EXPONENTIAL(1)锛氱浉鍏虫у揩閫熻“鍑忥紝閫傜敤浜庡眬閮ㄥ彉寮傛ц緝澶х殑鍙橀噺 - //鐞冪姸妯″瀷GAUSSIAN(2)锛氬湪鍙樼▼鍐呭憟鎶涚墿绾垮彉鍖栵紝瓒呰繃鍙樼▼鍚庣浉鍏虫т负闆 - dVec2 p; //鎻掑肩偣 + double nugget; //块金值:表示空间点在零距离处的变异程度,即测量误差和小于采样尺度的随机变异之和 + double sill; //基台值:表示变差函数随距离增加而趋于稳定的极限值,反映区域化变量的总变异程度 + double range; //变程:表示空间相关性的有效距离。当两点间距离超过 range 时,它们之间不再具有空间相关性 + double model; //变差函数模型:指定变差函数的数学形式,描述空间相关性随距离的变化规律{, , } + //高斯模型SPHERICAL(0):相关性随距离增加呈指数衰减,适用于连续性较强的变量 + //指数模型EXPONENTIAL(1):相关性快速衰减,适用于局部变异性较大的变量 + //球状模型GAUSSIAN(2):在变程内呈抛物线变化,超过变程后相关性为零 + dVec2 p; //插值点 dVec2 v; // ~HX_KRING_INPUT() {} HX_KRING_INPUT(double nugget0, double sill0, double range0, double model0 , const dVec2& p0, const dVec2& v0) @@ -287,7 +290,7 @@ struct HX_KRING_INPUT } }; -//KRINGING鎻掑艰緭鍑哄弬鏁扮粨鏋勪綋 +//KRINGING插值输出参数结构体 struct HX_KRING_OUTPUT { dVec1 v; @@ -295,75 +298,75 @@ struct HX_KRING_OUTPUT ~HX_KRING_OUTPUT() {} }; -//鏁板艰瘯浜曟ā鍨嬫眰瑙e櫒杈撳叆鍙傛暟缁撴瀯浣 +//数值试井模型求解器输入参数结构体 struct HX_NWTM_MODEL_INPUT { - int T; //1:娌瑰崟鐩稿父鏁皃vt; 2:娌瑰崟鐩稿彉鍖杙vt; 3:姘村崟鐩稿父鏁皃vt; 4:姘村崟鐩稿彉鍖杙vt; 5:姘斿崟鐩稿彉鍖杙vt; 6:姘斿崟鐩告嫙鍘嬪姏; 7:娌规皵涓ょ浉; 8:娌规按涓ょ浉; 9:姘旀按涓ょ浉; 10:娌规皵姘翠笁鐩 + int T; //1:油单相常数pvt; 2:油单相变化pvt; 3:水单相常数pvt; 4:水单相变化pvt; 5:气单相变化pvt; 6:气单相拟压力; 7:油气两相; 8:油水两相; 9:气水两相; 10:油气水三相 HX_NWTM_GRID_OUTPUT2 GRID; - struct Rate //娴侀噺鏁版嵁 + struct Rate //流量数据 { - dVec2 t; //鏃堕棿, h [涓鍙d簳涓缁勬暟] - dVec2 qo; //娌规祦閲,m^3/d [涓鍙d簳涓缁勬暟] - dVec2 qg; //姘旀祦閲,m^3/d [涓鍙d簳涓缁勬暟] - dVec2 qw; //姘存祦閲,m^3/d [涓鍙d簳涓缁勬暟] + dVec2 t; //时间, h [一口井一组数] + dVec2 qo; //油流量,m^3/d [一口井一组数] + dVec2 qg; //气流量,m^3/d [一口井一组数] + dVec2 qw; //水流量,m^3/d [一口井一组数] }Rate; - struct Pressure //鍘嬪姏鏁版嵁 + struct Pressure //压力数据 { - dVec2 t; //鏃堕棿, h [涓鍙d簳涓缁勬暟] - dVec2 p; //鍘嬪姏, MPa [涓鍙d簳涓缁勬暟] + dVec2 t; //时间, h [一口井一组数] + dVec2 p; //压力, MPa [一口井一组数] }Pressure; - struct CS //浜曞偍琛ㄧ毊鏁版嵁 + struct CS //井储表皮数据 { - dVec1 C; //浜曞偍, m^3/MPa [涓鍙d簳涓涓暟] - dVec1 S; //琛ㄧ毊, [涓鍙d簳涓涓暟] + dVec1 C; //井储, m^3/MPa [一口井一个数] + dVec1 S; //表皮, [一口井一个数] }CS; - struct PVT //娴佷綋鎬ц川鏁版嵁 + struct PVT //流体性质数据 { - dVec1 p; //鍘嬪姏, MPa - double pb; //楗卞拰鍘嬪姏, MPa - dVec1 Rso; //婧惰В姘旀补姣, m^3/m^3 - dVec1 Bo; //娌逛綋绉郴鏁, m^3/m^3 - dVec1 Co; //娌瑰帇缂╃郴鏁, 1/MPa - dVec1 miuo; //娌圭矘搴, mPa路s - dVec1 rouo; //娌瑰瘑搴, kg/m^3 - dVec1 Rv; //鍑濇瀽娌规皵姣, m^3/m^3 - dVec1 Bg; //姘斾綋绉郴鏁, m^3/m^3 - dVec1 Cg; //姘斿帇缂╃郴鏁, 1/MPa - dVec1 miug; //姘旂矘搴, mPa路s - dVec1 roug; //姘斿瘑搴, kg/m^3 - dVec1 Z; //姘斿亸宸洜瀛, 1 - dVec1 Rsw; //婧惰В姘旀按姣, m^3/m^3 - dVec1 Bw; //姘翠綋绉郴鏁, m^3/m^3 - dVec1 Cw; //姘村帇缂╃郴鏁, 1/MPa - dVec1 miuw; //姘寸矘搴, mPa路s - dVec1 rouw; //姘村瘑搴, kg/m^3 - dVec1 V; //鍚搁檮姘旈噺, m^3/kg - dVec1 k_kinitial; //娓楅忕巼姣, 1 - dVec1 Cf_Cfinitial; //宀╃煶鍘嬬缉绯绘暟姣, 1 - dVec1 So; //娌归ケ鍜屽害 - dVec1 Kro; //娌圭浉瀵规笚閫忕巼 - dVec1 Sg; //姘旈ケ鍜屽害 - dVec1 Krg; //姘旂浉瀵规笚閫忕巼 - dVec1 Sw; //姘撮ケ鍜屽害 - dVec1 Krw; //姘寸浉瀵规笚閫忕巼 + dVec1 p; //压力, MPa + double pb; //饱和压力, MPa + dVec1 Rso; //溶解气油比, m^3/m^3 + dVec1 Bo; //油体积系数, m^3/m^3 + dVec1 Co; //油压缩系数, 1/MPa + dVec1 miuo; //油粘度, mPa·s + dVec1 rouo; //油密度, kg/m^3 + dVec1 Rv; //凝析油气比, m^3/m^3 + dVec1 Bg; //气体积系数, m^3/m^3 + dVec1 Cg; //气压缩系数, 1/MPa + dVec1 miug; //气粘度, mPa·s + dVec1 roug; //气密度, kg/m^3 + dVec1 Z; //气偏差因子, 1 + dVec1 Rsw; //溶解气水比, m^3/m^3 + dVec1 Bw; //水体积系数, m^3/m^3 + dVec1 Cw; //水压缩系数, 1/MPa + dVec1 miuw; //水粘度, mPa·s + dVec1 rouw; //水密度, kg/m^3 + dVec1 V; //吸附气量, m^3/kg + dVec1 k_kinitial; //渗透率比, 1 + dVec1 Cf_Cfinitial; //岩石压缩系数比, 1 + dVec1 So; //油饱和度 + dVec1 Kro; //油相对渗透率 + dVec1 Sg; //气饱和度 + dVec1 Krg; //气相对渗透率 + dVec1 Sw; //水饱和度 + dVec1 Krw; //水相对渗透率 }PVT; - struct Base //鍩虹鏁版嵁 + struct Base //基础数据 { - double Pi; //鍒濆鍘嬪姏, MPa - double Cti; //缁煎悎鍘嬬缉绯绘暟, 1/MPa - double Cf; //宀╃煶鍘嬬缉绯绘暟, 1/MPa - double Soi; //鍒濆鍚补楗卞拰搴 - double Sgi; //鍒濆鍚皵楗卞拰搴 - double Swi; //鍒濆鍚按楗卞拰搴 - dVec1 k; //娓楅忕巼, D [涓涓綉鏍煎崟鍏冧竴涓糫 - dVec1 phi; //瀛旈殭搴, 1 [涓涓綉鏍煎崟鍏冧竴涓糫 - dVec1 h; //鍌ㄥ眰鍘氬害, m [涓涓綉鏍煎崟鍏冧竴涓糫 - double d; //鏃堕棿澧為暱鎸囨暟 - double dt_Min; //鏈灏忔椂闂撮棿闅, h - double dt_Max; //鏈澶ф椂闂撮棿闅, h + double Pi; //初始压力, MPa + double Cti; //综合压缩系数, 1/MPa + double Cf; //岩石压缩系数, 1/MPa + double Soi; //初始含油饱和度 + double Sgi; //初始含气饱和度 + double Swi; //初始含水饱和度 + dVec1 k; //渗透率, D [一个网格单元一个值] + dVec1 phi; //孔隙度, 1 [一个网格单元一个值] + dVec1 h; //储层厚度, m [一个网格单元一个值] + double d; //时间增长指数 + double dt_Min; //最小时间间隔, h + double dt_Max; //最大时间间隔, h }Base; - //鍒濆鍖 + //初始化 HX_NWTM_MODEL_INPUT() {} ~HX_NWTM_MODEL_INPUT() {} HX_NWTM_MODEL_INPUT(const HX_NWTM_GRID_OUTPUT2& p0) @@ -456,23 +459,27 @@ struct HX_NWTM_MODEL_INPUT } }; -//鏁板艰瘯浜曟ā鍨嬫眰瑙e櫒杈撳嚭鍙傛暟缁撴瀯浣 +//数值试井模型求解器输出参数结构体 struct HX_NWTM_MODEL_OUTPUT { - dVec1 t; //鏃堕棿, h - dVec2 pw; //浜曞簳鍘嬪姏, MPa [涓鍙d簳涓缁勬暟] - dVec2 p; //鍘嬪姏鍒嗗竷, MPa [涓涓椂闂翠竴缁勬暟] - dVec2 So; //娌归ケ鍜屽害鍒嗗竷 [涓涓椂闂翠竴缁勬暟] - dVec2 Sg; //姘旈ケ鍜屽害鍒嗗竷 [涓涓椂闂翠竴缁勬暟] - dVec2 Sw; //姘撮ケ鍜屽害鍒嗗竷 [涓涓椂闂翠竴缁勬暟] - dVec2 k; //娓楅忕巼鍒嗗竷,mD [涓涓椂闂翠竴缁勬暟] + dVec1 t; //时间, h + dVec2 pw; //井底压力, MPa [一口井一组数] + dVec2 p; //压力分布, MPa [一个时间一组数] + dVec2 So; //油饱和度分布 [一个时间一组数] + dVec2 Sg; //气饱和度分布 [一个时间一组数] + dVec2 Sw; //水饱和度分布 [一个时间一组数] + dVec2 k; //渗透率分布,mD [一个时间一组数] HX_NWTM_MODEL_OUTPUT() {} ~HX_NWTM_MODEL_OUTPUT() {} }; -HX_API void HX_NWTM_GRID(HX_NWTM_GRID_OUTPUT1& p1, HX_NWTM_GRID_OUTPUT2& p2, const HX_NWTM_GRID_INPUT& p0, std::string LIC); //鏁板艰瘯浜曠綉鏍兼帴鍙 -HX_API void HX_NWTM_KRINGING(HX_KRING_OUTPUT& p1, const HX_KRING_INPUT p0, std::string LIC); //鏁板艰瘯浜曢潪鍧囪川鎬ц绠楁帴鍙 -HX_API void HX_NWTM_MODEL(HX_NWTM_MODEL_OUTPUT& p1, const HX_NWTM_MODEL_INPUT& p0, std::string LIC); //鏁板艰瘯浜曟ā鍨嬫眰瑙e櫒鎺ュ彛 - +HX_API void HX_NWTM_GRID(HX_NWTM_GRID_OUTPUT1& p1, HX_NWTM_GRID_OUTPUT2& p2, const HX_NWTM_GRID_INPUT& p0, std::string LIC); //数值试井网格接口 +HX_API void HX_NWTM_KRINGING(HX_KRING_OUTPUT& p1, const HX_KRING_INPUT p0, std::string LIC); //数值试井非均质性计算接口 +HX_API void HX_NWTM_MODEL(HX_NWTM_MODEL_OUTPUT& p1, const HX_NWTM_MODEL_INPUT& p0, std::string LIC); //数值试井模型求解器接口 +HX_API void set_omp_threads(int n); +HX_API void set_ilu_reuse_steps(int n); +HX_API int getPEBInum(); +HX_API int getsolvetime(); +HX_API void set_solvetype(int n); diff --git a/3rd/Pebi/license/HX_license.dat b/3rd/Pebi/license/HX_license.dat index 98362c9..5e45563 100644 --- a/3rd/Pebi/license/HX_license.dat +++ b/3rd/Pebi/license/HX_license.dat @@ -1 +1 @@ -7d534fb716ec6521f938 \ No newline at end of file +7d534fb716ed6121f939 \ No newline at end of file diff --git a/3rd/Pebi/src/Krow.csv b/3rd/Pebi/src/Krow.csv new file mode 100644 index 0000000..ba4a5f3 --- /dev/null +++ b/3rd/Pebi/src/Krow.csv @@ -0,0 +1,22 @@ +So,Krw,Kro +0,1,0 +0.05,1,0 +0.1,1,0 +0.15,0.864105595,0.020840082 +0.2,0.744179203,0.044454989 +0.25,0.638344534,0.071214184 +0.3,0.544945766,0.101536324 +0.35,0.462521643,0.135895811 +0.4,0.389782609,0.17483021 +0.45,0.325590638,0.218948664 +0.5,0.268941421,0.268941421 +0.55,0.218948664,0.325590638 +0.6,0.17483021,0.389782609 +0.65,0.135895811,0.462521643 +0.7,0.101536324,0.544945766 +0.75,0.071214184,0.638344534 +0.8,0.044454989,0.744179203 +0.85,0.020840082,0.864105595 +0.9,0,1 +0.95,0,1 +1,0,1 diff --git a/3rd/Pebi/src/PVT_ow.csv b/3rd/Pebi/src/PVT_ow.csv new file mode 100644 index 0000000..00f6ac3 --- /dev/null +++ b/3rd/Pebi/src/PVT_ow.csv @@ -0,0 +1,202 @@ +p,Bw,miuw,,Bo,miuo +0.101325,1.04263,0.294823,0,1.17376,0.653595 +0.446063,1.04246,0.294823,0,1.13543,0.653595 +0.790801,1.04228,0.294823,0,1.12095,0.653595 +1.13554,1.04211,0.294823,0,1.1119,0.653595 +1.48028,1.04194,0.294823,0,1.10532,0.653595 +1.82501,1.04177,0.294823,0,1.10015,0.653595 +2.16975,1.0416,0.294823,0,1.09589,0.653595 +2.51449,1.04143,0.294823,0,1.09228,0.653595 +2.85923,1.04126,0.294823,0,1.08914,0.653595 +3.20397,1.04109,0.294823,0,1.08636,0.653595 +3.5487,1.04092,0.294823,0,1.08388,0.653595 +3.89344,1.04075,0.294823,0,1.08163,0.653595 +4.23818,1.04058,0.294823,0,1.07958,0.653595 +4.58292,1.04041,0.294823,0,1.07769,0.653595 +4.92765,1.04024,0.294823,0,1.07594,0.653595 +5.27239,1.04008,0.294823,0,1.07431,0.653595 +5.61713,1.03991,0.294823,0,1.07278,0.653595 +5.96187,1.03974,0.294823,0,1.07135,0.653595 +6.30661,1.03957,0.294823,0,1.07001,0.653595 +6.65134,1.0394,0.294823,0,1.06873,0.653595 +6.99608,1.03924,0.294823,0,1.06752,0.653595 +7.34082,1.03907,0.294823,0,1.06637,0.653595 +7.68556,1.0389,0.294823,0,1.06528,0.653595 +8.0303,1.03873,0.294823,0,1.06423,0.653595 +8.37503,1.03857,0.294823,0,1.06323,0.653595 +8.71977,1.0384,0.294823,0,1.06227,0.653595 +9.06451,1.03823,0.294823,0,1.06134,0.653595 +9.40925,1.03807,0.294823,0,1.06046,0.653595 +9.75398,1.0379,0.294823,0,1.0596,0.653595 +10.0987,1.03774,0.294823,0,1.05878,0.653595 +10.4435,1.03757,0.294823,0,1.05798,0.653595 +10.7882,1.0374,0.294823,0,1.05721,0.653595 +11.1329,1.03724,0.294823,0,1.05647,0.653595 +11.4777,1.03707,0.294823,0,1.05575,0.653595 +11.8224,1.03691,0.294823,0,1.05505,0.653595 +12.1671,1.03674,0.294823,0,1.05437,0.653595 +12.5119,1.03658,0.294823,0,1.05371,0.653595 +12.8566,1.03642,0.294823,0,1.05307,0.653595 +13.2014,1.03625,0.294823,0,1.05244,0.653595 +13.5461,1.03609,0.294823,0,1.05183,0.653595 +13.8908,1.03592,0.294823,0,1.05124,0.653595 +14.2356,1.03576,0.294823,0,1.05067,0.653595 +14.5803,1.0356,0.294823,0,1.0501,0.653595 +14.9251,1.03543,0.294823,0,1.04955,0.653595 +15.2698,1.03527,0.294823,0,1.04902,0.653595 +15.6145,1.03511,0.294823,0,1.04849,0.653595 +15.9593,1.03495,0.294823,0,1.04798,0.653595 +16.304,1.03478,0.294823,0,1.04748,0.653595 +16.6487,1.03462,0.294823,0,1.04699,0.653595 +16.9935,1.03446,0.294823,0,1.04651,0.653595 +17.3382,1.0343,0.294823,0,1.04603,0.653595 +17.683,1.03414,0.294823,0,1.04557,0.653595 +18.0277,1.03397,0.294823,0,1.04512,0.653595 +18.3724,1.03381,0.294823,0,1.04468,0.653595 +18.7172,1.03365,0.294823,0,1.04424,0.653595 +19.0619,1.03349,0.294823,0,1.04382,0.653595 +19.4066,1.03333,0.294823,0,1.0434,0.653595 +19.7514,1.03317,0.294823,0,1.04299,0.653595 +20.0961,1.03301,0.294823,0,1.04258,0.653595 +20.4409,1.03285,0.294823,0,1.04218,0.653595 +20.7856,1.03269,0.294823,0,1.04179,0.653595 +21.1303,1.03253,0.294823,0,1.04141,0.653595 +21.4751,1.03237,0.294823,0,1.04103,0.653595 +21.8198,1.03221,0.294823,0,1.04066,0.653595 +22.1645,1.03205,0.294823,0,1.0403,0.653595 +22.5093,1.03189,0.294823,0,1.03994,0.653595 +22.854,1.03173,0.294823,0,1.03958,0.653595 +23.1988,1.03158,0.294823,0,1.03923,0.653595 +23.5435,1.03142,0.294823,0,1.03889,0.653595 +23.8882,1.03126,0.294823,0,1.03855,0.653595 +24.233,1.0311,0.294823,0,1.03822,0.653595 +24.5777,1.03094,0.294823,0,1.03789,0.653595 +24.9225,1.03079,0.294823,0,1.03757,0.653595 +25.2672,1.03063,0.294823,0,1.03725,0.653595 +25.6119,1.03047,0.294823,0,1.03693,0.653595 +25.9567,1.03031,0.294823,0,1.03662,0.653595 +26.3014,1.03016,0.294823,0,1.03631,0.653595 +26.6461,1.03,0.294823,0,1.03601,0.653595 +26.9909,1.02984,0.294823,0,1.03571,0.653595 +27.3356,1.02969,0.294823,0,1.03542,0.653595 +27.6804,1.02953,0.294823,0,1.03513,0.653595 +28.0251,1.02937,0.294823,0,1.03484,0.653595 +28.3698,1.02922,0.294823,0,1.03456,0.653595 +28.7146,1.02906,0.294823,0,1.03428,0.653595 +29.0593,1.02891,0.294823,0,1.034,0.653595 +29.404,1.02875,0.294823,0,1.03373,0.653595 +29.7488,1.0286,0.294823,0,1.03346,0.653595 +30.0935,1.02844,0.294823,0,1.03319,0.653595 +30.4383,1.02829,0.294823,0,1.03293,0.653595 +30.783,1.02813,0.294823,0,1.03267,0.653595 +31.1277,1.02798,0.294823,0,1.03241,0.653595 +31.4725,1.02782,0.294823,0,1.03216,0.653595 +31.8172,1.02767,0.294823,0,1.0319,0.653595 +32.1619,1.02751,0.294823,0,1.03166,0.653595 +32.5067,1.02736,0.294823,0,1.03141,0.653595 +32.8514,1.02721,0.294823,0,1.03116,0.653595 +33.1962,1.02705,0.294823,0,1.03092,0.653595 +33.5409,1.0269,0.294823,0,1.03069,0.653595 +33.8856,1.02675,0.294823,0,1.03045,0.653595 +34.2304,1.02659,0.294823,0,1.03022,0.653595 +34.5751,1.02644,0.294823,0,1.02998,0.653595 +34.9198,1.02629,0.294823,0,1.02976,0.653595 +35.2646,1.02614,0.294823,0,1.02953,0.653595 +35.6093,1.02598,0.294823,0,1.0293,0.653595 +35.9541,1.02583,0.294823,0,1.02908,0.653595 +36.2988,1.02568,0.294823,0,1.02886,0.653595 +36.6435,1.02553,0.294823,0,1.02864,0.653595 +36.9883,1.02538,0.294823,0,1.02843,0.653595 +37.333,1.02522,0.294823,0,1.02821,0.653595 +37.6778,1.02507,0.294823,0,1.028,0.653595 +38.0225,1.02492,0.294823,0,1.02779,0.653595 +38.3672,1.02477,0.294823,0,1.02759,0.653595 +38.712,1.02462,0.294823,0,1.02738,0.653595 +39.0567,1.02447,0.294823,0,1.02718,0.653595 +39.4014,1.02432,0.294823,0,1.02697,0.653595 +39.7462,1.02417,0.294823,0,1.02677,0.653595 +40.0909,1.02402,0.294823,0,1.02657,0.653595 +40.4357,1.02387,0.294823,0,1.02638,0.653595 +40.7804,1.02372,0.294823,0,1.02618,0.653595 +41.1251,1.02357,0.294823,0,1.02599,0.653595 +41.4699,1.02342,0.294823,0,1.0258,0.653595 +41.8146,1.02327,0.294823,0,1.02561,0.653595 +42.1593,1.02312,0.294823,0,1.02542,0.653595 +42.5041,1.02297,0.294823,0,1.02523,0.653595 +42.8488,1.02282,0.294823,0,1.02505,0.653595 +43.1936,1.02267,0.294823,0,1.02486,0.653595 +43.5383,1.02253,0.294823,0,1.02468,0.653595 +43.883,1.02238,0.294823,0,1.0245,0.653595 +44.2278,1.02223,0.294823,0,1.02432,0.653595 +44.5725,1.02208,0.294823,0,1.02414,0.653595 +44.9172,1.02193,0.294823,0,1.02396,0.653595 +45.262,1.02179,0.294823,0,1.02379,0.653595 +45.6067,1.02164,0.294823,0,1.02361,0.653595 +45.9515,1.02149,0.294823,0,1.02344,0.653595 +46.2962,1.02134,0.294823,0,1.02327,0.653595 +46.6409,1.0212,0.294823,0,1.0231,0.653595 +46.9857,1.02105,0.294823,0,1.02293,0.653595 +47.3304,1.0209,0.294823,0,1.02276,0.653595 +47.6751,1.02076,0.294823,0,1.0226,0.653595 +48.0199,1.02061,0.294823,0,1.02243,0.653595 +48.3646,1.02046,0.294823,0,1.02227,0.653595 +48.7094,1.02032,0.294823,0,1.02211,0.653595 +49.0541,1.02017,0.294823,0,1.02194,0.653595 +49.3988,1.02003,0.294823,0,1.02178,0.653595 +49.7436,1.01988,0.294823,0,1.02162,0.653595 +50.0883,1.01974,0.294823,0,1.02147,0.653595 +50.4331,1.01959,0.294823,0,1.02131,0.653595 +50.7778,1.01944,0.294823,0,1.02115,0.653595 +51.1225,1.0193,0.294823,0,1.021,0.653595 +51.4673,1.01915,0.294823,0,1.02085,0.653595 +51.812,1.01901,0.294823,0,1.02069,0.653595 +52.1567,1.01887,0.294823,0,1.02054,0.653595 +52.5015,1.01872,0.294823,0,1.02039,0.653595 +52.8462,1.01858,0.294823,0,1.02024,0.653595 +53.191,1.01843,0.294823,0,1.02009,0.653595 +53.5357,1.01829,0.294823,0,1.01994,0.653595 +53.8804,1.01814,0.294823,0,1.0198,0.653595 +54.2252,1.018,0.294823,0,1.01965,0.653595 +54.5699,1.01786,0.294823,0,1.01951,0.653595 +54.9146,1.01771,0.294823,0,1.01936,0.653595 +55.2594,1.01757,0.294823,0,1.01922,0.653595 +55.6041,1.01743,0.294823,0,1.01908,0.653595 +55.9489,1.01729,0.294823,0,1.01894,0.653595 +56.2936,1.01714,0.294823,0,1.0188,0.653595 +56.6383,1.017,0.294823,0,1.01866,0.653595 +56.9831,1.01686,0.294823,0,1.01852,0.653595 +57.3278,1.01672,0.294823,0,1.01838,0.653595 +57.6725,1.01657,0.294823,0,1.01825,0.653595 +58.0173,1.01643,0.294823,0,1.01811,0.653595 +58.362,1.01629,0.294823,0,1.01797,0.653595 +58.7068,1.01615,0.294823,0,1.01784,0.653595 +59.0515,1.01601,0.294823,0,1.01771,0.653595 +59.3962,1.01586,0.294823,0,1.01757,0.653595 +59.741,1.01572,0.294823,0,1.01744,0.653595 +60.0857,1.01558,0.294823,0,1.01731,0.653595 +60.4304,1.01544,0.294823,0,1.01718,0.653595 +60.7752,1.0153,0.294823,0,1.01705,0.653595 +61.1199,1.01516,0.294823,0,1.01692,0.653595 +61.4647,1.01502,0.294823,0,1.01679,0.653595 +61.8094,1.01488,0.294823,0,1.01667,0.653595 +62.1541,1.01474,0.294823,0,1.01654,0.653595 +62.4989,1.0146,0.294823,0,1.01641,0.653595 +62.8436,1.01446,0.294823,0,1.01629,0.653595 +63.1884,1.01432,0.294823,0,1.01616,0.653595 +63.5331,1.01418,0.294823,0,1.01604,0.653595 +63.8778,1.01404,0.294823,0,1.01592,0.653595 +64.2226,1.0139,0.294823,0,1.01579,0.653595 +64.5673,1.01376,0.294823,0,1.01567,0.653595 +64.912,1.01362,0.294823,0,1.01555,0.653595 +65.2568,1.01348,0.294823,0,1.01543,0.653595 +65.6015,1.01334,0.294823,0,1.01531,0.653595 +65.9463,1.01321,0.294823,0,1.01519,0.653595 +66.291,1.01307,0.294823,0,1.01507,0.653595 +66.6357,1.01293,0.294823,0,1.01496,0.653595 +66.9805,1.01279,0.294823,0,1.01484,0.653595 +67.3252,1.01265,0.294823,0,1.01472,0.653595 +67.6699,1.01251,0.294823,0,1.01461,0.653595 +68.0147,1.01238,0.294823,0,1.01449,0.653595 +68.3594,1.01224,0.294823,0,1.01437,0.653595 +68.7042,1.0121,0.294823,0,1.01426,0.653595 +69.0489,1.01196,0.294823,0,1.01415,0.653595 diff --git a/3rd/Pebi/src/main.cpp b/3rd/Pebi/src/main.cpp index aa97cba..de701d6 100644 --- a/3rd/Pebi/src/main.cpp +++ b/3rd/Pebi/src/main.cpp @@ -1,19 +1,60 @@ #include"pch.h" #include #include + +#include +#include +#include + +static int g_orgStdout = -1; +static FILE* g_nulPipe = nullptr; +void EnterSilentDllMode() +{ + // 备份原始标准输出句柄 + g_orgStdout = _dup(_fileno(stdout)); + + // fopen_s 替代 fopen,打开空设备 NUL + errno_t err; + err = fopen_s(&g_nulPipe, "NUL", "w"); + if (err == 0 && g_nulPipe != nullptr) + { + _dup2(_fileno(g_nulPipe), _fileno(stdout)); + _dup2(_fileno(g_nulPipe), _fileno(stderr)); + } +} + +void LeaveSilentDllMode() +{ + // 恢复原始控制台输出 + if (g_orgStdout != -1) + { + _dup2(g_orgStdout, _fileno(stdout)); + _dup2(g_orgStdout, _fileno(stderr)); + _close(g_orgStdout); + g_orgStdout = -1; + } + + // 关闭空文件流 + if (g_nulPipe != nullptr) + { + fclose(g_nulPipe); + g_nulPipe = nullptr; + } +} + void Write2DVectorToCSV(const std::vector>& data, const std::string& filename) { - std::ofstream file(filename.c_str()); // VS2010闇浣跨敤.c_str() + std::ofstream file(filename.c_str()); // VS2010需使用.c_str() if (file.is_open()) { for (size_t row = 0; row < data.size(); ++row) { for (size_t col = 0; col < data[row].size(); ++col) { - // 璁剧疆鍥哄畾灏忔暟鏍煎紡鍜岀簿搴 + // 设置固定小数格式和精度 file << std::fixed << std::setprecision(15) << data[row][col]; - // 闈炴渶鍚庝竴鍒楁椂娣诲姞閫楀彿 + // 非最后一列时添加逗号 if (col != data[row].size() - 1) { file << ","; } } - file << "\n"; // 鎹㈣绗 + file << "\n"; // 换行符 } file.close(); } @@ -23,7 +64,7 @@ void Write1DVectorToCSV(const std::vector& data, const std::string& file if (file.is_open()) { file << std::fixed << std::setprecision(precision); for (size_t i = 0; i < data.size(); ++i) { - file << data[i] << "\n"; // 姣忎釜鍏冪礌鍗曠嫭涓琛 + file << data[i] << "\n"; // 每个元素单独一行 } file.close(); } @@ -31,32 +72,32 @@ void Write1DVectorToCSV(const std::vector& data, const std::string& file bool readCSVColumn(const std::string& filename, int columnIndex, std::vector& data) { std::ifstream file(filename); if (!file.is_open()) { - std::cerr << "鏃犳硶鎵撳紑鏂囦欢: " << filename << std::endl; + std::cerr << "无法打开文件: " << filename << std::endl; return false; } std::string line; - // 璺宠繃鏍囬琛岋紙濡傛灉鏈夛級 + // 跳过标题行(如果有) if (file.good()) { std::getline(file, line); } data.resize(0); - // 閫愯澶勭悊鏁版嵁 + // 逐行处理数据 while (std::getline(file, line)) { std::istringstream ss(line); std::string cell; int currentColumn = 0; bool columnFound = false; - // 澶勭悊褰撳墠琛岀殑姣忎釜鍗曞厓鏍 + // 处理当前行的每个单元格 while (std::getline(ss, cell, ',')) { if (currentColumn == columnIndex) { try { - // 杞崲涓篸ouble骞舵坊鍔犲埌vector + // 转换为double并添加到vector data.push_back(std::stod(cell)); } catch (const std::invalid_argument& e) { - std::cerr << "杞崲閿欒: " << cell << " 涓嶆槸鏈夋晥鐨勬暟瀛" << std::endl; + std::cerr << "转换错误: " << cell << " 不是有效的数字" << std::endl; return false; } columnFound = true; @@ -65,9 +106,9 @@ bool readCSVColumn(const std::string& filename, int columnIndex, std::vector Solver Progress 璁$畻杩涘害 + + Solver completed + 姹傝В瀹屾垚 + + + Solve time: %1 ms + 鏈姹傝В鑰楁椂锛%1 ms + nmSubWndPostprocessing @@ -4960,6 +4968,30 @@ Please check your input coordinates. Numerical settings 鏁板艰缃 + + Solver settings + 姹傝В鍣ㄨ缃 + + + Solver library: + 姹傝В鍣ㄥ簱锛 + + + CPU accelerated solver + CPU鍔犻熸眰瑙e櫒 + + + Original solver + 鍘熸眰瑙e櫒 + + + OpenMP threads: + OpenMP绾跨▼鏁帮細 + + + ILU reuse steps: + ILU澶嶇敤姝ユ暟锛 + Use automatic settings 浣跨敤鑷姩璁剧疆 diff --git a/Bin/Res/license/V1/HXNWTM_license.dat b/Bin/Res/license/V1/HXNWTM_license.dat deleted file mode 100644 index 98362c9..0000000 --- a/Bin/Res/license/V1/HXNWTM_license.dat +++ /dev/null @@ -1 +0,0 @@ -7d534fb716ec6521f938 \ No newline at end of file diff --git a/Include/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.h b/Include/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.h index 3efc33f..d52547e 100644 --- a/Include/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.h +++ b/Include/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.h @@ -23,6 +23,10 @@ class NMCALCULATION_EXPORT nmCalculationDllPebiSolverTask : public QThread { // PSO 绛夊緟绾跨▼缁撴潫鍚庨氳繃璇ユ帴鍙e垽鏂湰娆$粨鏋滄槸鍚﹀彲浠ョ户缁弬涓庤宸绠. // 杩斿洖 false 鏃惰皟鐢ㄦ柟浼氫涪寮冩湰娆$粨鏋, 闃叉澶嶇敤涓婁竴绮掑瓙鐣欎笅鐨勬棫鏇茬嚎. bool wasSuccessful() const; + /** @brief 鑾峰彇鏈DLL鍐呴儴姹傝В鑰楁椂锛屽崟浣嶄负姣銆 */ + int getSolveTimeMs() const; + /** @brief 鑾峰彇鏈姹傝В鐨凱EBI缃戞牸鏁伴噺銆 */ + int getPebiCount() const; // 鑷姩鎷熷悎绮掑瓙璇勪环鍙彁鍙栫洰鏍囦簳鏇茬嚎锛屼笉鍐欏洖鍏变韩鏁版嵁鍜岀綉鏍煎帇鍔涘満銆 // 浜曞悕涓虹┖鏃朵繚鎸佸師鏈夊畬鏁寸粨鏋滀繚瀛樻ā寮忋 @@ -46,6 +50,10 @@ class NMCALCULATION_EXPORT nmCalculationDllPebiSolverTask : public QThread { QString m_sPostprocessingDir; // run() 鍦ㄧ嚎绋嬪唴淇濆瓨 execute() 缁撴灉, 绛夊緟绾跨▼缁撴潫鐨勮皟鐢ㄦ柟鍙鍙栬鐘舵. bool m_lastRunSucceeded; + /** @brief 鏈DLL鍐呴儴姹傝В鑰楁椂锛屽崟浣嶄负姣銆 */ + int m_nSolveTimeMs; + /** @brief 鏈姹傝В鐨凱EBI缃戞牸鏁伴噺銆 */ + int m_nPebiCount; QString m_autoFitTargetWellName; QVector > m_autoFitResultPressure; QVector > m_autoFitResultLogLog; diff --git a/Include/nmNum/nmData/nmDataAnalyzeManager.h b/Include/nmNum/nmData/nmDataAnalyzeManager.h index a2a0f4e..a68c4c3 100644 --- a/Include/nmNum/nmData/nmDataAnalyzeManager.h +++ b/Include/nmNum/nmData/nmDataAnalyzeManager.h @@ -1,4 +1,4 @@ -#ifndef NMDATAANALYZEMANAGER_H +锘#ifndef NMDATAANALYZEMANAGER_H #define NMDATAANALYZEMANAGER_H #include @@ -145,7 +145,14 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin { ZX_DECLARE_DYNAMIC Q_OBJECT - public: +public: + /** @brief PEBI绾挎ф眰瑙e櫒绫诲瀷绋冲畾缂栫爜銆 */ + enum PebiSolverType + { + PebiSolverCpuAccelerated = 1, + PebiSolverOriginal = 2 + }; + nmDataAnalyzeManager(); // 閲婃斁褰撳墠娴佸姩娈靛垎鏋愮嫭鍗犵殑鏁版嵁瀵硅薄 ~nmDataAnalyzeManager(); @@ -361,6 +368,19 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin NM_SOLVER_MODEL_TYPE getSolverModelType() const; void setSolverModelType(NM_SOLVER_MODEL_TYPE newSolverModelType); + /** @brief 鑾峰彇PEBI姹傝В鍣ㄧ被鍨嬶紝1涓篊PU鍔犻熸眰瑙e櫒锛2涓哄師姹傝В鍣ㄣ */ + int getPebiSolverType() const; + /** @brief 璁剧疆PEBI姹傝В鍣ㄧ被鍨嬨 */ + void setPebiSolverType(int nSolverType); + /** @brief 鑾峰彇PEBI姹傝В鍣ㄧ殑OpenMP绾跨▼鏁般 */ + int getPebiOmpThreads() const; + /** @brief 璁剧疆PEBI姹傝В鍣ㄧ殑OpenMP绾跨▼鏁般 */ + void setPebiOmpThreads(int nOmpThreads); + /** @brief 鑾峰彇PEBI姹傝В鍣ㄧ殑ILU澶嶇敤姝ユ暟銆 */ + int getPebiIluReuseSteps() const; + /** @brief 璁剧疆PEBI姹傝В鍣ㄧ殑ILU澶嶇敤姝ユ暟銆 */ + void setPebiIluReuseSteps(int nIluReuseSteps); + // 鑾峰彇Pebi缃戞牸姹傝В鏁版嵁鎺ュ彛 // 鑾峰彇鍘嬪姏鍘嗗彶鏁版嵁 QVector> getPebiSolverHistoryDataByName(const QString& wellName); @@ -681,6 +701,13 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin // 姹傝В妯″瀷绫诲瀷 NM_SOLVER_MODEL_TYPE m_eSolverModelType; + /** @brief PEBI姹傝В鍣ㄧ被鍨嬶紝1涓篊PU鍔犻熸眰瑙e櫒锛2涓哄師姹傝В鍣ㄣ */ + int m_nPebiSolverType; + /** @brief PEBI姹傝В鍣ㄧ殑OpenMP绾跨▼鏁般 */ + int m_nPebiOmpThreads; + /** @brief PEBI姹傝В鍣ㄧ殑ILU澶嶇敤姝ユ暟銆 */ + int m_nPebiIluReuseSteps; + // Pvt鏁版嵁(Pebi) nmDataPvtParaForPebi* m_pebiPvtPara; diff --git a/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h b/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h index b63c9b7..15bedee 100644 --- a/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h +++ b/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h @@ -1,4 +1,4 @@ -#ifndef NMWXANALYTICALDESIGN_H +锘#ifndef NMWXANALYTICALDESIGN_H #define NMWXANALYTICALDESIGN_H #include "nmSubWxs_global.h" @@ -15,6 +15,7 @@ class QHBoxLayout; class QLabel; class QRadioButton; class QComboBox; +class QSpinBox; class QDateTimeEdit; class QStackedLayout; @@ -73,6 +74,10 @@ signals: void onResultWellChanged(int index); // 褰撳墠妯″瀷涓嬫媺妗嗗垏鎹㈡Ы void onCurrentModelChanged(int index); + /** @brief 姹傝В鍣ㄥ簱閫夋嫨鍙戠敓鍙樺寲銆 */ + void onPebiSolverTypeChanged(int index); + /** @brief 灏嗘眰瑙e櫒璁剧疆鍚屾鍒板綋鍓嶆暟鎹鐞嗗櫒銆 */ + void onPebiSolverSettingsChanged(); // 澶勭悊鏃堕棿鍙傝冪郴鍗曢夋寜閽垏鎹 //void onTimeReferenceSystemToggled(bool checked); @@ -97,6 +102,12 @@ private: void initAdvancedGroup(); // 鍒濆鍖栭珮绾х粍 (鏂) void initTimeSteppingGroup(); // 鍒濆鍖栨椂闂存杩涚粍 void initNumericalSettingsGroup(); // 鍒濆鍖栨暟鍊艰缃粍 (鏂) + /** @brief 鍒濆鍖朠EBI姹傝В鍣ㄨ缃粍銆 */ + void initPebiSolverSettingsGroup(); + /** @brief 鏍规嵁姹傝В鍣ㄥ簱鏇存柊鍔犻熷弬鏁版帶浠剁姸鎬併 */ + void updatePebiSolverSettingEnabled(); + /** @brief 灏哖EBI姹傝В鍣ㄨ缃繚瀛樺埌褰撳墠鏁版嵁绠$悊鍣ㄣ */ + void updatePebiSolverSettingsToData(); void setupConnections(); // 璁剧疆淇″彿妲借繛鎺 void initButton(); // 鍒濆鍖栨寜閽 @@ -177,6 +188,15 @@ private: QRadioButton* m_pUseCustomSettingsRadio; // "浣跨敤鑷畾涔夎缃"鍗曢夋寜閽 QPushButton* m_pCustomSettingsIconButton; // "鑷畾涔夎缃"鏃佽竟鐨勫浘鏍囨寜閽 + /** @brief PEBI姹傝В鍣ㄨ缃垎缁勬銆 */ + QGroupBox* m_pPebiSolverSettingsGroup; + /** @brief 姹傝В鍣ㄥ簱涓嬫媺妗嗐 */ + QComboBox* m_pPebiSolverTypeCombo; + /** @brief OpenMP绾跨▼鏁颁笅鎷夋銆 */ + QComboBox* m_pPebiOmpThreadsCombo; + /** @brief ILU澶嶇敤姝ユ暟杈撳叆妗嗐 */ + QSpinBox* m_pPebiIluReuseStepsSpin; + // 鎸夐挳 QPushButton* m_pGenerateButton; QPushButton* m_pAutomaticfittingBtn; diff --git a/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp b/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp index 021b101..255171d 100644 --- a/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp @@ -313,7 +313,9 @@ nmCalculationDllPebiSolverTask::nmCalculationDllPebiSolverTask( QObject *parent): QThread(parent), m_sPostprocessingDir(sPostprocessingDir), - m_lastRunSucceeded(false) + m_lastRunSucceeded(false), + m_nSolveTimeMs(-1), + m_nPebiCount(-1) { } @@ -327,6 +329,8 @@ nmCalculationDllPebiSolverTask::~nmCalculationDllPebiSolverTask() void nmCalculationDllPebiSolverTask::run() { + m_nSolveTimeMs = -1; + m_nPebiCount = -1; m_lastRunSucceeded = this->execute(); emit sig_calculateDone(m_lastRunSucceeded); } @@ -336,6 +340,16 @@ bool nmCalculationDllPebiSolverTask::wasSuccessful() const return m_lastRunSucceeded; } +int nmCalculationDllPebiSolverTask::getSolveTimeMs() const +{ + return m_nSolveTimeMs; +} + +int nmCalculationDllPebiSolverTask::getPebiCount() const +{ + return m_nPebiCount; +} + void nmCalculationDllPebiSolverTask::setAutoFitTargetWell(const QString& wellName) { m_autoFitTargetWellName = wellName; @@ -377,9 +391,26 @@ bool nmCalculationDllPebiSolverTask::execPebiMode() // 瀹氫箟鍑芥暟鎸囬拡绫诲瀷 typedef void (*HX_NWTM_GRID_Func)(HX_NWTM_GRID_OUTPUT1&, HX_NWTM_GRID_OUTPUT2&, const HX_NWTM_GRID_INPUT&, std::string); typedef void (*HX_NWTM_MODEL_Fun)(HX_NWTM_MODEL_OUTPUT&, const HX_NWTM_MODEL_INPUT&, std::string); + typedef void (*SetIntValueFunc)(int); + typedef int (*GetIntValueFunc)(); // 鑾峰彇鍑芥暟鍦板潃 HX_NWTM_MODEL_Fun HX_NWTM_MODEL = (HX_NWTM_MODEL_Fun)GetProcAddress(dll, "HX_NWTM_MODEL"); + SetIntValueFunc setSolverType = (SetIntValueFunc)GetProcAddress(dll, "set_solvetype"); + SetIntValueFunc setOmpThreads = (SetIntValueFunc)GetProcAddress(dll, "set_omp_threads"); + SetIntValueFunc setIluReuseSteps = (SetIntValueFunc)GetProcAddress(dll, "set_ilu_reuse_steps"); + GetIntValueFunc getPebiCount = (GetIntValueFunc)GetProcAddress(dll, "getPEBInum"); + GetIntValueFunc getSolveTime = (GetIntValueFunc)GetProcAddress(dll, "getsolvetime"); + + if(HX_NWTM_MODEL == nullptr || setSolverType == nullptr + || setOmpThreads == nullptr || setIluReuseSteps == nullptr + || getPebiCount == nullptr || getSolveTime == nullptr) { + QString sLogMessage = "Failed to resolve PEBI solver configuration interface."; + qWarning() << sLogMessage; + zxLogInstance::getInstance()->writeLogF(sLogMessage); + FreeLibrary(dll); + return false; + } if(HX_NWTM_MODEL) { if(pGridInstance->getGridOutput1().PEBI_cell.p.size() <= 0 @@ -645,8 +676,22 @@ bool nmCalculationDllPebiSolverTask::execPebiMode() nmDataAnalyzeManager* pDataManager = nmDataAnalyzeManager::getCurrentInstance(); QString licensePath = pDataManager->getLicensePath(); std::string licensePathStd = licensePath.toStdString(); + int nSolverType = pDataManager->getPebiSolverType(); + setSolverType(nSolverType); + if(nSolverType == nmDataAnalyzeManager::PebiSolverCpuAccelerated) { + setOmpThreads(pDataManager->getPebiOmpThreads()); + setIluReuseSteps(pDataManager->getPebiIluReuseSteps()); + } HX_NWTM_MODEL(p1, p0, licensePathStd); + m_nPebiCount = getPebiCount(); + m_nSolveTimeMs = getSolveTime(); + if(m_autoFitTargetWellName.isEmpty()) { + QString sSolveLog = QString("PEBI count: %1, solve time: %2 ms") + .arg(m_nPebiCount).arg(m_nSolveTimeMs); + qDebug() << sSolveLog; + zxLogInstance::getInstance()->writeLogF(sSolveLog); + } } catch(const std::exception& e) { // 鎹曡幏 C++ 鏍囧噯寮傚父 qDebug() << QString("C++ Exception during HX_NWTM_MODEL call: %1").arg(e.what()); diff --git a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp index d615efd..96af7af 100644 --- a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp +++ b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp @@ -1,4 +1,4 @@ -#include "nmDataAnalyzeManager.h" +锘#include "nmDataAnalyzeManager.h" #include "nmAttrRegistry.h" @@ -528,6 +528,9 @@ ZX_DEFINE_DYNAMIC(DataAnalyzeManager, nmDataAnalyzeManager) m_pLayerData = new nmDataLayer; m_eGridType = NM_Grid_Type::NM_Grid_PEBI; //榛樿缃戞牸绫诲瀷涓篜EBI m_eSolverModelType = NM_SOLVER_MODEL_TYPE::SMT_Oil_ConstPvt; + m_nPebiSolverType = PebiSolverCpuAccelerated; + m_nPebiOmpThreads = 4; + m_nPebiIluReuseSteps = 5; this->initDefaultDisplaySettings(); // 鍒濆鍖栦腑鑻辨枃缈昏瘧鏄犲皠 nmTranslationManager::initTranslations(); @@ -2732,6 +2735,43 @@ void nmDataAnalyzeManager::setSolverModelType(NM_SOLVER_MODEL_TYPE newSolverMode m_eSolverModelType = newSolverModelType; } +int nmDataAnalyzeManager::getPebiSolverType() const +{ + return m_nPebiSolverType; +} + +void nmDataAnalyzeManager::setPebiSolverType(int nSolverType) +{ + if(nSolverType == PebiSolverCpuAccelerated || nSolverType == PebiSolverOriginal) { + m_nPebiSolverType = nSolverType; + } +} + +int nmDataAnalyzeManager::getPebiOmpThreads() const +{ + return m_nPebiOmpThreads; +} + +void nmDataAnalyzeManager::setPebiOmpThreads(int nOmpThreads) +{ + if(nOmpThreads == 1 || nOmpThreads == 2 || nOmpThreads == 4 + || nOmpThreads == 8 || nOmpThreads == 16) { + m_nPebiOmpThreads = nOmpThreads; + } +} + +int nmDataAnalyzeManager::getPebiIluReuseSteps() const +{ + return m_nPebiIluReuseSteps; +} + +void nmDataAnalyzeManager::setPebiIluReuseSteps(int nIluReuseSteps) +{ + if(nIluReuseSteps >= 1 && nIluReuseSteps <= 100) { + m_nPebiIluReuseSteps = nIluReuseSteps; + } +} + // 鑾峰彇Pebi缃戞牸姹傝В鏁版嵁鎺ュ彛 // 鑾峰彇鍘嬪姏鍘嗗彶鏁版嵁 QVector> nmDataAnalyzeManager::getPebiSolverHistoryDataByName(const QString & wellName) @@ -3767,6 +3807,15 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath) if(doc.HasMember("SolverModelType") && doc["SolverModelType"].IsInt()) { m_eSolverModelType = static_cast(doc["SolverModelType"].GetInt()); } + if(doc.HasMember("PebiSolverType") && doc["PebiSolverType"].IsInt()) { + setPebiSolverType(doc["PebiSolverType"].GetInt()); + } + if(doc.HasMember("PebiOmpThreads") && doc["PebiOmpThreads"].IsInt()) { + setPebiOmpThreads(doc["PebiOmpThreads"].GetInt()); + } + if(doc.HasMember("PebiIluReuseSteps") && doc["PebiIluReuseSteps"].IsInt()) { + setPebiIluReuseSteps(doc["PebiIluReuseSteps"].GetInt()); + } return true; } @@ -3993,6 +4042,9 @@ bool nmDataAnalyzeManager::WriteProjectData(const QString & filePath) // 淇濆瓨褰撳墠姹傝В鍣ㄦā鍨嬬被鍨 doc.AddMember("SolverModelType", static_cast(m_eSolverModelType), allocator); + doc.AddMember("PebiSolverType", m_nPebiSolverType, allocator); + doc.AddMember("PebiOmpThreads", m_nPebiOmpThreads, allocator); + doc.AddMember("PebiIluReuseSteps", m_nPebiIluReuseSteps, allocator); // 灏嗘渶缁堟瀯寤哄ソ鐨 Document 鍐欏叆鏂囦欢 if(!nmDataJsonTools::WriteDomToFile(doc, filePath)) { diff --git a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp index ec424fd..46af449 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp @@ -2058,6 +2058,7 @@ void nmSubWndMain::on_solverTaskFinished(bool isSuccessed) { // 绾跨▼瀹屾垚鍚庢竻绌轰袱涓寔鏈夌偣锛氬綋鍓嶇獥鍙f寚閽堝拰鍏ㄥ眬杩愯涓寚閽堛 nmCalculationDllPebiSolverTask* pTask = qobject_cast(sender()); + int nSolveTimeMs = pTask != nullptr ? pTask->getSolveTimeMs() : -1; if(pTask == m_pSolverTask) { m_pSolverTask = nullptr; } @@ -2068,6 +2069,11 @@ void nmSubWndMain::on_solverTaskFinished(bool isSuccessed) // 淇濇寔鏃ф祦绋嬩笉鍙橈細bool缁撴灉杞崲涓鸿绠楃粨鏋滄灇涓撅紝鍐嶄氦缁欏師鏉ョ殑缁熶竴鍚庡鐞嗗嚱鏁般 NM_Calculation_Result result = isSuccessed ? NM_Calculation_Result_Success : NM_Calculation_Result_Fail; this->on_calculationFinished(result); + + if(isSuccessed && nSolveTimeMs >= 0) { + QMessageBox::information(this, tr("Solver completed"), + tr("Solve time: %1 ms").arg(nSolveTimeMs)); + } } void nmSubWndMain::deleteOneObj() diff --git a/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp b/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp index 008dfbb..eb17684 100644 --- a/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp +++ b/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp @@ -1,10 +1,11 @@ -#include "nmWxNumericalDesign.h" +锘#include "nmWxNumericalDesign.h" #include #include #include #include #include +#include #include #include #include @@ -99,6 +100,7 @@ nmWxNumericalDesign::nmWxNumericalDesign(QWidget *parent) initAdvancedGroup(); // 鍒濆鍖栭珮绾х粍 (鏂) initTimeSteppingGroup(); // 鍒濆鍖栨椂闂存杩涚粍 initNumericalSettingsGroup(); // 鍒濆鍖栨暟鍊艰缃粍 (鏂) + initPebiSolverSettingsGroup(); // 鍒濆鍖朠EBI姹傝В鍣ㄨ缃粍 initButton(); // 鍒濆鍖栫敓鎴愭寜閽 // 灏嗗悇涓粍娣诲姞鍒版粴鍔ㄥ尯鍩熺殑甯冨眬涓 @@ -109,6 +111,7 @@ nmWxNumericalDesign::nmWxNumericalDesign(QWidget *parent) pScrollLayout->addWidget(m_pAdvancedGroup); pScrollLayout->addWidget(m_pTimeSteppingGroup); pScrollLayout->addWidget(m_pNumericalSettingsGroup); // 鏂扮殑鏁板艰缃粍 + pScrollLayout->addWidget(m_pPebiSolverSettingsGroup); pScrollLayout->addStretch(); // 娣诲姞鎷変几鍣紝浣垮唴瀹归潬涓 pScrollWidget->setLayout(pScrollLayout); // 璁剧疆婊氬姩瀹瑰櫒鐨勫竷灞 @@ -688,6 +691,69 @@ void nmWxNumericalDesign::initNumericalSettingsGroup() m_pNumericalSettingsGroup->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); // 璁剧疆灏哄绛栫暐 } +void nmWxNumericalDesign::initPebiSolverSettingsGroup() +{ + m_pPebiSolverSettingsGroup = new QGroupBox(tr("Solver settings"), this); + QGridLayout* pGridLayout = new QGridLayout(m_pPebiSolverSettingsGroup); + + QLabel* pSolverTypeLabel = new QLabel(tr("Solver library:"), this); + QLabel* pOmpThreadsLabel = new QLabel(tr("OpenMP threads:"), this); + QLabel* pIluReuseStepsLabel = new QLabel(tr("ILU reuse steps:"), this); + pSolverTypeLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + pOmpThreadsLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + pIluReuseStepsLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + + m_pPebiSolverTypeCombo = new QComboBox(this); + m_pPebiSolverTypeCombo->addItem(tr("CPU accelerated solver"), + nmDataAnalyzeManager::PebiSolverCpuAccelerated); + m_pPebiSolverTypeCombo->addItem(tr("Original solver"), + nmDataAnalyzeManager::PebiSolverOriginal); + + m_pPebiOmpThreadsCombo = new QComboBox(this); + m_pPebiOmpThreadsCombo->addItem("1", 1); + m_pPebiOmpThreadsCombo->addItem("2", 2); + m_pPebiOmpThreadsCombo->addItem("4", 4); + m_pPebiOmpThreadsCombo->addItem("8", 8); + m_pPebiOmpThreadsCombo->addItem("16", 16); + + m_pPebiIluReuseStepsSpin = new QSpinBox(this); + m_pPebiIluReuseStepsSpin->setRange(1, 100); + + pGridLayout->addWidget(pSolverTypeLabel, 0, 0); + pGridLayout->addWidget(m_pPebiSolverTypeCombo, 0, 1); + pGridLayout->addWidget(pOmpThreadsLabel, 1, 0); + pGridLayout->addWidget(m_pPebiOmpThreadsCombo, 1, 1); + pGridLayout->addWidget(pIluReuseStepsLabel, 2, 0); + pGridLayout->addWidget(m_pPebiIluReuseStepsSpin, 2, 1); + pGridLayout->setColumnStretch(0, 0); + pGridLayout->setColumnStretch(1, 1); + + m_pPebiSolverSettingsGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); +} + +void nmWxNumericalDesign::updatePebiSolverSettingEnabled() +{ + bool bAccelerationEnabled = m_pPebiSolverTypeCombo->itemData( + m_pPebiSolverTypeCombo->currentIndex()).toInt() + == nmDataAnalyzeManager::PebiSolverCpuAccelerated; + m_pPebiOmpThreadsCombo->setEnabled(bAccelerationEnabled); + m_pPebiIluReuseStepsSpin->setEnabled(bAccelerationEnabled); +} + +void nmWxNumericalDesign::updatePebiSolverSettingsToData() +{ + nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance(); + if(pManager == nullptr) { + return; + } + + pManager->setPebiSolverType(m_pPebiSolverTypeCombo->itemData( + m_pPebiSolverTypeCombo->currentIndex()).toInt()); + pManager->setPebiOmpThreads(m_pPebiOmpThreadsCombo->itemData( + m_pPebiOmpThreadsCombo->currentIndex()).toInt()); + pManager->setPebiIluReuseSteps(m_pPebiIluReuseStepsSpin->value()); +} + void nmWxNumericalDesign::initButton() { @@ -789,6 +855,29 @@ void nmWxNumericalDesign::setupConnections() // "鑷畾涔夎缃"鍥炬爣鎸夐挳鐨勫惎鐢ㄧ姸鎬佸彇鍐充簬"浣跨敤鑷畾涔夎缃"鍗曢夋寜閽 connect(m_pUseCustomSettingsRadio, SIGNAL(toggled(bool)), m_pCustomSettingsIconButton, SLOT(setEnabled(bool))); connect(m_pCustomSettingsIconButton, SIGNAL(clicked()), this, SLOT(onCustomNumericalSettingsClicked())); // 鍥炬爣鎸夐挳鐐瑰嚮杩炴帴 + + // PEBI姹傝В鍣ㄨ缃粍杩炴帴 + connect(m_pPebiSolverTypeCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onPebiSolverTypeChanged(int))); + connect(m_pPebiOmpThreadsCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onPebiSolverSettingsChanged())); + connect(m_pPebiIluReuseStepsSpin, SIGNAL(valueChanged(int)), + this, SLOT(onPebiSolverSettingsChanged())); +} + +void nmWxNumericalDesign::onPebiSolverTypeChanged(int index) +{ + if(index < 0) { + return; + } + + updatePebiSolverSettingEnabled(); + updatePebiSolverSettingsToData(); +} + +void nmWxNumericalDesign::onPebiSolverSettingsChanged() +{ + updatePebiSolverSettingsToData(); } void nmWxNumericalDesign::onTimeDependentCheck(bool checked) @@ -1070,22 +1159,47 @@ void nmWxNumericalDesign::onOutputResultFieldsToggled(bool checked) void nmWxNumericalDesign::updateUiFromData() { - nmDataTimeStepSetting* pTimeStepSetting = nmDataAnalyzeManager::getCurrentInstance()->getTimeStep(); - if(!pTimeStepSetting) { + nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance(); + if(pManager == nullptr) { return; } + nmDataTimeStepSetting* pTimeStepSetting = pManager->getTimeStep(); + // 浣跨敤缁勪欢鐨勬洿鏂版柟娉 - if(m_pTimeGrowthExponentCom) { + if(pTimeStepSetting != nullptr && m_pTimeGrowthExponentCom) { m_pTimeGrowthExponentCom->updateValueFromOrigin(); } - if(m_pDtMinCom) { + if(pTimeStepSetting != nullptr && m_pDtMinCom) { m_pDtMinCom->updateValueFromOrigin(); } - if(m_pDtMaxCom) { + if(pTimeStepSetting != nullptr && m_pDtMaxCom) { m_pDtMaxCom->updateValueFromOrigin(); } + m_pPebiSolverTypeCombo->blockSignals(true); + m_pPebiOmpThreadsCombo->blockSignals(true); + m_pPebiIluReuseStepsSpin->blockSignals(true); + + int nSolverTypeIndex = m_pPebiSolverTypeCombo->findData(pManager->getPebiSolverType()); + if(nSolverTypeIndex < 0) { + nSolverTypeIndex = m_pPebiSolverTypeCombo->findData( + nmDataAnalyzeManager::PebiSolverCpuAccelerated); + } + m_pPebiSolverTypeCombo->setCurrentIndex(nSolverTypeIndex); + + int nOmpThreadsIndex = m_pPebiOmpThreadsCombo->findData(pManager->getPebiOmpThreads()); + if(nOmpThreadsIndex < 0) { + nOmpThreadsIndex = m_pPebiOmpThreadsCombo->findData(4); + } + m_pPebiOmpThreadsCombo->setCurrentIndex(nOmpThreadsIndex); + m_pPebiIluReuseStepsSpin->setValue(pManager->getPebiIluReuseSteps()); + + m_pPebiSolverTypeCombo->blockSignals(false); + m_pPebiOmpThreadsCombo->blockSignals(false); + m_pPebiIluReuseStepsSpin->blockSignals(false); + updatePebiSolverSettingEnabled(); + //// 闃诲淇″彿 //m_pTimeGrowthExponentLineEdit->blockSignals(true); //m_pDtMinLineEdit->blockSignals(true); @@ -1219,22 +1333,26 @@ void nmWxNumericalDesign::updateUiFromData() void nmWxNumericalDesign::updateDataFromUi() { - nmDataTimeStepSetting* pTimeStepSetting = nmDataAnalyzeManager::getCurrentInstance()->getTimeStep(); - if(!pTimeStepSetting) { + nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance(); + if(pManager == nullptr) { return; } + nmDataTimeStepSetting* pTimeStepSetting = pManager->getTimeStep(); + // 浣跨敤缁勪欢鐨勬洿鏂版柟娉 - if(m_pTimeGrowthExponentCom) { + if(pTimeStepSetting != nullptr && m_pTimeGrowthExponentCom) { m_pTimeGrowthExponentCom->updateValueToOrigin(); } - if(m_pDtMinCom) { + if(pTimeStepSetting != nullptr && m_pDtMinCom) { m_pDtMinCom->updateValueToOrigin(); } - if(m_pDtMaxCom) { + if(pTimeStepSetting != nullptr && m_pDtMaxCom) { m_pDtMaxCom->updateValueToOrigin(); } + updatePebiSolverSettingsToData(); + //// 鏇存柊鏁版嵁妯″瀷 //pTimeStepSetting->getTimeGrowthExponent().setValue(m_pTimeGrowthExponentLineEdit->text().toDouble()); //pTimeStepSetting->getMinDeltaTAttribute().setValue(m_pDtMinLineEdit->text().toDouble());